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 226 of file Journal.cpp.

227{
228 if ( !GetError() && !sFileNameIn.empty() ) {
229 wxFileName fName{ sFileNameIn };
230 fName.MakeAbsolute( dataDir );
231 const auto path = fName.GetFullPath();
232 sFileIn.Open( path );
233 if (!sFileIn.IsOpened())
234 {
235 Log("Journal: failed to open journal file \"{}\"", path);
236 SetError();
237 }
238 else {
239 sLine = sFileIn.GetFirstLine();
240 sLineNumber = 0;
241
242 auto tokens = PeekTokens();
243 NextIn();
244
245 if (!(tokens.size() == 2 && tokens[0] == VersionToken &&
246 VersionCheck(tokens[1])))
247 {
248 Log("Journal: invalid journal version: \"{}\"", tokens[1]);
249 SetError();
250 }
251 }
252 }
253
254 if ( !GetError() && RecordEnabled() ) {
255 wxFileName fName{ dataDir, "journal", "txt" };
256 const auto path = fName.GetFullPath();
257 if ( !OpenOut( path ) )
258 SetError();
259 else {
260 // Generate a header
261 Comment( wxString::Format(
262 wxT("Journal recorded by %s on %s")
263 , wxGetUserName()
264 , wxDateTime::Now().Format()
265 ) );
267 }
268 }
269
270 // Call other registered initialization steps
271 for (auto &initializer : GetInitializers()) {
272 if (initializer && !initializer()) {
273 SetError();
274 break;
275 }
276 }
277
278 return !GetError();
279}
wxT("CloseDown"))
Abstract base class used in importing a file.
void Log(std::string_view message, const Args &... args)
Definition: Journal.cpp:87
bool VersionCheck(const wxString &value)
True if value is an acceptable journal version number to be rerun.
Definition: Journal.cpp:168
bool OpenOut(const wxString &fullPath)
bool RecordEnabled()
Definition: Journal.cpp:204
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}::Log(), 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(), Journal::anonymous_namespace{Journal.cpp}::VersionToken, and wxT().

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 291 of file Journal.cpp.

292{
293 if ( GetError() )
294 // Don't repeatedly indicate error
295 // Do nothing
296 return false;
297
298 if ( !IsReplaying() )
299 return false;
300
301 // This will throw if no lines remain. A proper journal should exit the
302 // program before that happens.
303 auto words = GetTokens();
304
305 // Lookup dispatch function by the first field of the line
306 auto &table = GetDictionary();
307 auto &name = words[0];
308 auto iter = table.find( name );
309 if (iter == table.end())
310 throw SyncException(
311 wxString::Format("unknown command: %s", name.ToStdString().c_str()));
312
313 // Pass all the fields including the command name to the function
314 if (!iter->second(words))
315 throw SyncException(wxString::Format(
316 "command '%s' has failed", wxJoin(words, ',').ToStdString().c_str()));
317
318 return true;
319}
const TranslatableString name
Definition: Distortion.cpp:82
const Dictionary & GetDictionary()
wxArrayStringEx GetTokens()
Definition: Journal.cpp:281
bool IsReplaying()
Definition: Journal.cpp:216

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 386 of file Journal.cpp.

387{
388 // Unconsumed commands remaining in the input file is also an error condition.
389 if( !GetError() && !PeekTokens().empty() ) {
390 NextIn();
391 SetError();
392 }
393 if ( GetError() ) {
394 // Return nonzero
395 // Returning the (1-based) line number at which the script failed is a
396 // simple way to communicate that information to the test driver script.
397 return sLineNumber ? sLineNumber : -1;
398 }
399
400 // Return zero to mean all is well, the convention for command-line tools
401 return 0;
402}

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 281 of file Journal.cpp.

282{
283 auto result = PeekTokens();
284 if ( !result.empty() ) {
285 NextIn();
286 return result;
287 }
288 throw SyncException("unexpected end of stream");
289}

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 352 of file Journal.cpp.

354{
355 // Special journal word
356 Sync(string);
357
358 // Then read or write the return value on another journal line
359 if ( IsReplaying() ) {
360 auto tokens = GetTokens();
361 if ( tokens.size() == 1 ) {
362 try {
363 std::wstring str{ tokens[0].wc_str() };
364 size_t length = 0;
365 auto result = std::stoi(str, &length);
366 if (length == str.length()) {
367 if (IsRecording())
368 Journal::Output( std::to_wstring(result) );
369 return result;
370 }
371 }
372 catch ( const std::exception& ) {}
373 }
374
375 throw SyncException(wxString::Format(
376 "unexpected tokens: %s", wxJoin(tokens, ',').ToStdString().c_str()));
377 }
378 else {
379 auto result = action ? action() : 0;
380 if ( IsRecording() )
381 Output( std::to_wstring( result ) );
382 return result;
383 }
384}
#define str(a)
void Sync(std::initializer_list< const wxString > strings)
Definition: Journal.cpp:347

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 216 of file Journal.cpp.

217{
218 return sFileIn.IsOpened();
219}

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 204 of file Journal.cpp.

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

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 221 of file Journal.cpp.

222{
223 sFileNameIn = path;
224}

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 209 of file Journal.cpp.

210{
211 auto result = JournalEnabled.Write(value);
212 gPrefs->Flush();
213 return result;
214}
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:252

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 339 of file Journal.cpp.

340{
341 if ( IsRecording() || IsReplaying() ) {
342 auto string = ::wxJoin( strings, SeparatorCharacter, EscapeCharacter );
343 Sync( string );
344 }
345}

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 321 of file Journal.cpp.

322{
323 if ( IsRecording() || IsReplaying() ) {
324 if ( IsRecording() )
325 Output( string );
326 if ( IsReplaying() ) {
327 if (sFileIn.Eof() || sLine != string)
328 {
329 throw SyncException(wxString::Format(
330 "sync failed. Expected '%s', got '%s'",
331 string.ToStdString().c_str(), sLine.ToStdString().c_str()));
332 }
333
334 NextIn();
335 }
336 }
337}

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 347 of file Journal.cpp.

348{
349 return Sync( wxArrayStringEx( strings ) );
350}

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