Audacity 3.2.0
Namespaces | Classes | Typedefs | Functions | Variables
Journal Namespace Reference

Facilities for recording and playback of sequences of user interaction. More...

Namespaces

namespace  anonymous_namespace{Journal.cpp}
 
namespace  anonymous_namespace{JournalOutput.cpp}
 
namespace  anonymous_namespace{JournalRegistry.cpp}
 
namespace  Events
 
namespace  WindowPaths
 

Classes

struct  RegisteredCommand
 
struct  RegisteredInitializer
 
class  SyncException
 

Typedefs

using InteractiveAction = std::function< int() >
 Function that returns a value which will be written to the journal. More...
 
using Dispatcher = std::function< bool(const wxArrayStringEx &fields) >
 
using Dictionary = std::unordered_map< wxString, Journal::Dispatcher >
 
using Initializer = std::function< bool() >
 
using Initializers = std::vector< Initializer >
 

Functions

bool RecordEnabled ()
 
bool SetRecordEnabled (bool value)
 
bool IsReplaying ()
 
void SetInputFileName (const wxString &path)
 
bool Begin (const FilePath &dataDir)
 
wxArrayStringEx GetTokens ()
 
bool Dispatch ()
 
void Sync (const wxString &string)
 
void Sync (const wxArrayString &strings)
 
void Sync (std::initializer_list< const wxString > strings)
 
int IfNotPlaying (const wxString &string, const InteractiveAction &action)
 Call action only if not replaying; synchronize on string and int values. More...
 
int GetExitCode ()
 
bool IsRecording ()
 
bool OpenOut (const wxString &fullPath)
 
void Output (const wxString &string)
 
void Output (const wxArrayString &strings)
 
void Output (std::initializer_list< const wxString > strings)
 
void Comment (const wxString &string)
 
bool GetError ()
 
void SetError ()
 
const DictionaryGetDictionary ()
 
static std::vector< Initializer > & sInitializers ()
 
const InitializersGetInitializers ()
 

Variables

constexpr auto SeparatorCharacter = ','
 
constexpr auto EscapeCharacter = '\\'
 
constexpr auto CommentCharacter = '#'
 

Detailed Description

Facilities for recording and playback of sequences of user interaction.

Typedef Documentation

◆ Dictionary

using Journal::Dictionary = typedef std::unordered_map< wxString, Journal::Dispatcher >

Definition at line 44 of file JournalRegistry.h.

◆ Dispatcher

using Journal::Dispatcher = typedef std::function< bool(const wxArrayStringEx &fields) >

Definition at line 33 of file JournalRegistry.h.

◆ Initializer

using Journal::Initializer = typedef std::function< bool() >

Definition at line 51 of file JournalRegistry.h.

◆ Initializers

using Journal::Initializers = typedef std::vector< Initializer >

Definition at line 59 of file JournalRegistry.h.

◆ InteractiveAction

using Journal::InteractiveAction = typedef std::function< int() >

Function that returns a value which will be written to the journal.

In future, might generalize to more return values and of other types

Definition at line 69 of file Journal.h.

Function Documentation

◆ Begin()

bool Journal::Begin ( const FilePath dataDir)

Definition at line 141 of file Journal.cpp.

142{
143 if ( !GetError() && !sFileNameIn.empty() ) {
144 wxFileName fName{ sFileNameIn };
145 fName.MakeAbsolute( dataDir );
146 const auto path = fName.GetFullPath();
147 sFileIn.Open( path );
148 if ( !sFileIn.IsOpened() )
149 SetError();
150 else {
151 sLine = sFileIn.GetFirstLine();
152 sLineNumber = 0;
153
154 auto tokens = PeekTokens();
155 NextIn();
156 if( !(
157 tokens.size() == 2 &&
158 tokens[0] == VersionToken &&
159 VersionCheck( tokens[1] )
160 ) )
161 SetError();
162 }
163 }
164
165 if ( !GetError() && RecordEnabled() ) {
166 wxFileName fName{ dataDir, "journal", "txt" };
167 const auto path = fName.GetFullPath();
168 if ( !OpenOut( path ) )
169 SetError();
170 else {
171 // Generate a header
172 Comment( wxString::Format(
173 wxT("Journal recorded by %s on %s")
174 , wxGetUserName()
175 , wxDateTime::Now().Format()
176 ) );
178 }
179 }
180
181 // Call other registered initialization steps
182 for (auto &initializer : GetInitializers()) {
183 if (initializer && !initializer()) {
184 SetError();
185 break;
186 }
187 }
188
189 return !GetError();
190}
Abstract base class used in importing a file.
bool VersionCheck(const wxString &value)
True if value is an acceptable journal version number to be rerun.
Definition: Journal.cpp:85
bool OpenOut(const wxString &fullPath)
bool RecordEnabled()
Definition: Journal.cpp:119
void Comment(const wxString &string)
bool GetError()
void Output(const wxString &string)
void SetError()
const Initializers & GetInitializers()

References Comment(), GetError(), GetInitializers(), Journal::Events::anonymous_namespace{JournalEvents.cpp}::initializer, Journal::anonymous_namespace{Journal.cpp}::NextIn(), OpenOut(), Output(), Journal::anonymous_namespace{Journal.cpp}::PeekTokens(), RecordEnabled(), SetError(), Journal::anonymous_namespace{Journal.cpp}::sFileIn, Journal::anonymous_namespace{Journal.cpp}::sFileNameIn, Journal::anonymous_namespace{Journal.cpp}::sLine, Journal::anonymous_namespace{Journal.cpp}::sLineNumber, Journal::anonymous_namespace{Journal.cpp}::VersionCheck(), Journal::anonymous_namespace{Journal.cpp}::VersionString(), and Journal::anonymous_namespace{Journal.cpp}::VersionToken.

Referenced by AudacityApp::InitPart2(), anonymous_namespace{Registry.cpp}::CollectedItems::InsertNewItemUsingHint(), and anonymous_namespace{Registry.cpp}::CollectedItems::MergeItems().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Comment()

void Journal::Comment ( const wxString &  string)

Definition at line 62 of file JournalOutput.cpp.

63{
64 if ( IsRecording() )
65 sFileOut.AddLine( CommentCharacter + string );
66}
Journal::anonymous_namespace{JournalOutput.cpp}::FlushingTextFile sFileOut
bool IsRecording()
constexpr auto CommentCharacter
Definition: JournalOutput.h:24

References CommentCharacter, IsRecording(), and Journal::anonymous_namespace{JournalOutput.cpp}::sFileOut.

Referenced by Begin().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Dispatch()

bool Journal::Dispatch ( )

Definition at line 202 of file Journal.cpp.

203{
204 if ( GetError() )
205 // Don't repeatedly indicate error
206 // Do nothing
207 return false;
208
209 if ( !IsReplaying() )
210 return false;
211
212 // This will throw if no lines remain. A proper journal should exit the
213 // program before that happens.
214 auto words = GetTokens();
215
216 // Lookup dispatch function by the first field of the line
217 auto &table = GetDictionary();
218 auto &name = words[0];
219 auto iter = table.find( name );
220 if ( iter == table.end() )
221 throw SyncException{};
222
223 // Pass all the fields including the command name to the function
224 if ( !iter->second( words ) )
225 throw SyncException{};
226
227 return true;
228}
const TranslatableString name
Definition: Distortion.cpp:82
const Dictionary & GetDictionary()
wxArrayStringEx GetTokens()
Definition: Journal.cpp:192
bool IsReplaying()
Definition: Journal.cpp:131

References GetDictionary(), GetError(), GetTokens(), IsReplaying(), and name.

Referenced by AudacityApp::OnExit(), and AudacityApp::OnIdle().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetDictionary()

const Dictionary & Journal::GetDictionary ( )

Definition at line 53 of file JournalRegistry.cpp.

54{
55 return sDictionary();
56}

References Journal::anonymous_namespace{JournalRegistry.cpp}::sDictionary().

Referenced by Dispatch().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetError()

bool Journal::GetError ( )

Definition at line 30 of file JournalRegistry.cpp.

References Journal::anonymous_namespace{JournalRegistry.cpp}::sError.

Referenced by Begin(), Dispatch(), and GetExitCode().

Here is the caller graph for this function:

◆ GetExitCode()

int Journal::GetExitCode ( )

Definition at line 288 of file Journal.cpp.

289{
290 // Unconsumed commands remaining in the input file is also an error condition.
291 if( !GetError() && !PeekTokens().empty() ) {
292 NextIn();
293 SetError();
294 }
295 if ( GetError() ) {
296 // Return nonzero
297 // Returning the (1-based) line number at which the script failed is a
298 // simple way to communicate that information to the test driver script.
299 return sLineNumber ? sLineNumber : -1;
300 }
301
302 // Return zero to mean all is well, the convention for command-line tools
303 return 0;
304}

References GetError(), Journal::anonymous_namespace{Journal.cpp}::NextIn(), Journal::anonymous_namespace{Journal.cpp}::PeekTokens(), SetError(), and Journal::anonymous_namespace{Journal.cpp}::sLineNumber.

Referenced by AudacityApp::OnRun().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetInitializers()

const Initializers & Journal::GetInitializers ( )

Definition at line 69 of file JournalRegistry.cpp.

70{
71 return sInitializers();
72}
static std::vector< Initializer > & sInitializers()

References sInitializers().

Referenced by Begin().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetTokens()

wxArrayStringEx Journal::GetTokens ( )

Definition at line 192 of file Journal.cpp.

193{
194 auto result = PeekTokens();
195 if ( !result.empty() ) {
196 NextIn();
197 return result;
198 }
199 throw SyncException{};
200}

References Journal::anonymous_namespace{Journal.cpp}::NextIn(), and Journal::anonymous_namespace{Journal.cpp}::PeekTokens().

Referenced by Dispatch(), IfNotPlaying(), and BasicMenu::anonymous_namespace{BasicMenu.cpp}::ReplayPopup().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IfNotPlaying()

int Journal::IfNotPlaying ( const wxString &  string,
const InteractiveAction action 
)

Call action only if not replaying; synchronize on string and int values.

If not replaying, call the function, and if recording, output the string and the return value.

If replaying, skip the action; Sync on the string; parse a value from the journal; throw SyncException if the value is ill-formed; otherwise output the value (if also recording), and return it

Definition at line 256 of file Journal.cpp.

258{
259 // Special journal word
260 Sync(string);
261
262 // Then read or write the return value on another journal line
263 if ( IsReplaying() ) {
264 auto tokens = GetTokens();
265 if ( tokens.size() == 1 ) {
266 try {
267 std::wstring str{ tokens[0].wc_str() };
268 size_t length = 0;
269 auto result = std::stoi(str, &length);
270 if (length == str.length()) {
271 if (IsRecording())
272 Journal::Output( std::to_wstring(result) );
273 return result;
274 }
275 }
276 catch ( const std::exception& ) {}
277 }
278 throw SyncException{};
279 }
280 else {
281 auto result = action ? action() : 0;
282 if ( IsRecording() )
283 Output( std::to_wstring( result ) );
284 return result;
285 }
286}
#define str(a)
void Sync(std::initializer_list< const wxString > strings)
Definition: Journal.cpp:251

References GetTokens(), IsRecording(), IsReplaying(), Output(), str, and Sync().

Referenced by AudacityMessageBox().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsRecording()

bool Journal::IsRecording ( )

Definition at line 28 of file JournalOutput.cpp.

29{
30 return sFileOut.IsOpened();
31}

References Journal::anonymous_namespace{JournalOutput.cpp}::sFileOut.

Referenced by Comment(), IfNotPlaying(), Output(), and Sync().

Here is the caller graph for this function:

◆ IsReplaying()

bool Journal::IsReplaying ( )

Definition at line 131 of file Journal.cpp.

132{
133 return sFileIn.IsOpened();
134}

References Journal::anonymous_namespace{Journal.cpp}::sFileIn.

Referenced by Dispatch(), IfNotPlaying(), Journal::anonymous_namespace{Journal.cpp}::PeekTokens(), BasicMenu::Handle::Popup(), and Sync().

Here is the caller graph for this function:

◆ OpenOut()

bool Journal::OpenOut ( const wxString &  fullPath)

Definition at line 33 of file JournalOutput.cpp.

34{
35 sFileOut.Open( fullPath );
36 if ( sFileOut.IsOpened() )
37 sFileOut.Clear();
38 else {
39 sFileOut.Create();
40 sFileOut.Open( fullPath );
41 }
42 return sFileOut.IsOpened();
43}

References Journal::anonymous_namespace{JournalOutput.cpp}::sFileOut.

Referenced by Begin().

Here is the caller graph for this function:

◆ Output() [1/3]

void Journal::Output ( const wxArrayString &  strings)

Definition at line 51 of file JournalOutput.cpp.

52{
53 if ( IsRecording() )
54 Output( ::wxJoin( strings, SeparatorCharacter, EscapeCharacter ) );
55}
constexpr auto EscapeCharacter
Definition: JournalOutput.h:23
constexpr auto SeparatorCharacter
Definition: JournalOutput.h:22
void Output(std::initializer_list< const wxString > strings)

References EscapeCharacter, IsRecording(), Output(), and SeparatorCharacter.

Here is the call graph for this function:

◆ Output() [2/3]

void Journal::Output ( const wxString &  string)

Definition at line 45 of file JournalOutput.cpp.

46{
47 if ( IsRecording() )
48 sFileOut.AddLine( string );
49}

References IsRecording(), and Journal::anonymous_namespace{JournalOutput.cpp}::sFileOut.

Referenced by Begin(), Journal::Events::anonymous_namespace{JournalEvents.cpp}::Watcher::FilterEvent(), BasicMenu::anonymous_namespace{BasicMenu.cpp}::Watcher::FilterEvent(), CommandManager::HandleCommandEntry(), IfNotPlaying(), Output(), BasicMenu::Handle::Popup(), and Sync().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Output() [3/3]

void Journal::Output ( std::initializer_list< const wxString >  strings)

Definition at line 57 of file JournalOutput.cpp.

58{
59 return Output( wxArrayStringEx( strings ) );
60}
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.

References Output().

Here is the call graph for this function:

◆ RecordEnabled()

bool Journal::RecordEnabled ( )

Definition at line 119 of file Journal.cpp.

120{
121 return JournalEnabled.Read();
122}
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:185

References Journal::anonymous_namespace{Journal.cpp}::JournalEnabled, and Setting< T >::Read().

Referenced by Begin(), PluginActions::Handler::OnWriteJournal(), and anonymous_namespace{PluginMenus.cpp}::ToolsMenu().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetError()

void Journal::SetError ( )

Definition at line 35 of file JournalRegistry.cpp.

36{
37 sError = true;
38}

References Journal::anonymous_namespace{JournalRegistry.cpp}::sError.

Referenced by Begin(), GetExitCode(), Journal::RegisteredCommand::RegisteredCommand(), and Journal::SyncException::SyncException().

Here is the caller graph for this function:

◆ SetInputFileName()

void Journal::SetInputFileName ( const wxString &  path)

Definition at line 136 of file Journal.cpp.

137{
138 sFileNameIn = path;
139}

References Journal::anonymous_namespace{Journal.cpp}::sFileNameIn.

Referenced by AudacityApp::InitPart2().

Here is the caller graph for this function:

◆ SetRecordEnabled()

bool Journal::SetRecordEnabled ( bool  value)

Definition at line 124 of file Journal.cpp.

125{
126 auto result = JournalEnabled.Write(value);
127 gPrefs->Flush();
128 return result;
129}
FileConfig * gPrefs
Definition: Prefs.cpp:71
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
bool Write(const T &value)
Write value to config and return true if successful.
Definition: Prefs.h:229

References FileConfig::Flush(), gPrefs, Journal::anonymous_namespace{Journal.cpp}::JournalEnabled, and Setting< T >::Write().

Referenced by PluginActions::Handler::OnWriteJournal().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sInitializers()

static std::vector< Initializer > & Journal::sInitializers ( )
static

Definition at line 58 of file JournalRegistry.cpp.

59{
60 static std::vector<Initializer> sTheFunctions;
61 return sTheFunctions;
62}

Referenced by GetInitializers(), and Journal::RegisteredInitializer::RegisteredInitializer().

Here is the caller graph for this function:

◆ Sync() [1/3]

void Journal::Sync ( const wxArrayString &  strings)

Definition at line 243 of file Journal.cpp.

244{
245 if ( IsRecording() || IsReplaying() ) {
246 auto string = ::wxJoin( strings, SeparatorCharacter, EscapeCharacter );
247 Sync( string );
248 }
249}

References EscapeCharacter, IsRecording(), IsReplaying(), SeparatorCharacter, and Sync().

Here is the call graph for this function:

◆ Sync() [2/3]

void Journal::Sync ( const wxString &  string)

Definition at line 230 of file Journal.cpp.

231{
232 if ( IsRecording() || IsReplaying() ) {
233 if ( IsRecording() )
234 Output( string );
235 if ( IsReplaying() ) {
236 if ( sFileIn.Eof() || sLine != string )
237 throw SyncException{};
238 NextIn();
239 }
240 }
241}

References IsRecording(), IsReplaying(), Journal::anonymous_namespace{Journal.cpp}::NextIn(), Output(), Journal::anonymous_namespace{Journal.cpp}::sFileIn, and Journal::anonymous_namespace{Journal.cpp}::sLine.

Referenced by IfNotPlaying(), and Sync().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Sync() [3/3]

void Journal::Sync ( std::initializer_list< const wxString >  strings)

Definition at line 251 of file Journal.cpp.

252{
253 return Sync( wxArrayStringEx( strings ) );
254}

References Sync().

Here is the call graph for this function:

Variable Documentation

◆ CommentCharacter

constexpr auto Journal::CommentCharacter = '#'
constexpr

◆ EscapeCharacter

constexpr auto Journal::EscapeCharacter = '\\'
constexpr

◆ SeparatorCharacter

constexpr auto Journal::SeparatorCharacter = ','
constexpr