From ca5dac59ffdc4d179496ae8c0b5977ddc64a7a02 Mon Sep 17 00:00:00 2001 From: James Crook Date: Thu, 8 Feb 2018 16:22:01 +0000 Subject: [PATCH] Support: JSON, Lispy or Other formats --- src/Menus.cpp | 4 +- src/Shuttle.cpp | 96 ++++++-- src/Shuttle.h | 25 +- src/commands/CommandTargets.cpp | 187 +++++++++++++- src/commands/CommandTargets.h | 67 ++++- src/commands/GetInfoCommand.cpp | 352 ++++++++++++++++----------- src/commands/GetInfoCommand.h | 10 +- src/commands/GetTrackInfoCommand.cpp | 39 +-- src/commands/HelpCommand.cpp | 2 +- src/commands/LoadCommands.cpp | 5 +- src/effects/EffectManager.cpp | 29 ++- src/effects/EffectManager.h | 3 +- 12 files changed, 573 insertions(+), 246 deletions(-) diff --git a/src/Menus.cpp b/src/Menus.cpp index 6bbb21d32..2993bbc81 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -1614,8 +1614,8 @@ void AudacityProject::CreateMenusAndCommands() AudioIONotBusyFlag, AudioIONotBusyFlag); c->AddItem(wxT("GetInfo"), _("Get Info..."), FN(OnAudacityCommand), AudioIONotBusyFlag, AudioIONotBusyFlag); - c->AddItem(wxT("GetTrackInfo"), _("Get Track Info..."), FN(OnAudacityCommand), - AudioIONotBusyFlag, AudioIONotBusyFlag); +// c->AddItem(wxT("GetTrackInfo"), _("Get Track Info..."), FN(OnAudacityCommand), +// AudioIONotBusyFlag, AudioIONotBusyFlag); c->EndSubMenu(); diff --git a/src/Shuttle.cpp b/src/Shuttle.cpp index 6a207af84..7a025e2c7 100644 --- a/src/Shuttle.cpp +++ b/src/Shuttle.cpp @@ -332,8 +332,23 @@ bool ShuttleParams::ExchangeWithMaster(const wxString & WXUNUSED(Name)) return true; } + #pragma warning( push ) #pragma warning( disable: 4100 ) // unused parameters. + +// These are functions to override. They do nothing. +void ShuttleParams::Define( bool & var, const wxChar * key, const bool vdefault, const bool vmin, const bool vmax, const bool vscl){;}; +void ShuttleParams::Define( size_t & var, const wxChar * key, const int vdefault, const int vmin, const int vmax, const int vscl ){;}; +void ShuttleParams::Define( int & var, const wxChar * key, const int vdefault, const int vmin, const int vmax, const int vscl ){;}; +void ShuttleParams::Define( float & var, const wxChar * key, const float vdefault, const float vmin, const float vmax, const float vscl ){;}; +void ShuttleParams::Define( double & var, const wxChar * key, const float vdefault, const float vmin, const float vmax, const float vscl ){;}; +void ShuttleParams::Define( double & var, const wxChar * key, const double vdefault, const double vmin, const double vmax, const double vscl ){;}; +void ShuttleParams::Define( wxString &var, const wxChar * key, const wxString vdefault, const wxString vmin, const wxString vmax, const wxString vscl ){;}; +void ShuttleParams::DefineEnum( wxString &var, const wxChar * key, const wxString vdefault, wxArrayString strings ){;}; +void ShuttleParams::DefineEnum( int &var, const wxChar * key, const int vdefault, wxArrayString strings ){;}; + + + /* void ShuttleParams::DefineEnum( int &var, const wxChar * key, const int vdefault, wxArrayString strings ) { @@ -483,68 +498,103 @@ void ShuttleSetAutomation::DefineEnum( int &var, const wxChar * key, const int v var = temp; } +ShuttleGetDefinition::ShuttleGetDefinition( CommandMessageTarget & target ) : CommandMessageTargetDecorator( target ) +{ +} + // JSON definitions. -// All these MUST end with ",\r\n", so that we can put them in an array (and so we can remove the last "," easily for JSON). void ShuttleGetDefinition::Define( bool & var, const wxChar * key, const bool vdefault, const bool vmin, const bool vmax, const bool vscl ) { - Result += wxString::Format( " { key: \"%s\", type: \"bool\", default: \"%s\"},\r\n", - key , vdefault ? "True" : "False" ); + StartStruct(); + AddItem( wxString(key), "key" ); + AddItem( "bool", "type" ); + AddItem( vdefault ? "True" : "False", "default" ); + EndStruct(); } void ShuttleGetDefinition::Define( int & var, const wxChar * key, const int vdefault, const int vmin, const int vmax, const int vscl ) { - Result += wxString::Format( " { key: \"%s\", type: \"int\", default: \"%i\"},\r\n", - key , vdefault ); + StartStruct(); + AddItem( wxString(key), "key" ); + AddItem( "int", "type" ); + AddItem( (double)vdefault, "default" ); + EndStruct(); } void ShuttleGetDefinition::Define( size_t & var, const wxChar * key, const int vdefault, const int vmin, const int vmax, const int vscl ) { - Result += wxString::Format( " { key: \"%s\", type: \"size_t\", default: \"%li\"},\r\n", - key , vdefault ); + StartStruct(); + AddItem( wxString(key), "key" ); + AddItem( "size_t", "type" ); + AddItem( (double)vdefault, "default" ); + EndStruct(); + } void ShuttleGetDefinition::Define( float & var, const wxChar * key, const float vdefault, const float vmin, const float vmax, const float vscl ) { - Result += wxString::Format( " { key: \"%s\", type: \"float\", default: \"%f\"},\r\n", - key , vdefault ); + StartStruct(); + AddItem( wxString(key), "key" ); + AddItem( "float", "type" ); + AddItem( (double)vdefault, "default" ); + EndStruct(); } void ShuttleGetDefinition::Define( double & var, const wxChar * key, const float vdefault, const float vmin, const float vmax, const float vscl ) { - Result += wxString::Format( " { key: \"%s\", type: \"float\", default: \"%f\"},\r\n", - key , vdefault ); + StartStruct(); + AddItem( wxString(key), "key" ); + AddItem( "float", "type" ); + AddItem( (double)vdefault, "default" ); + EndStruct(); } void ShuttleGetDefinition::Define( double & var, const wxChar * key, const double vdefault, const double vmin, const double vmax, const double vscl ) { - Result += wxString::Format( " { key: \"%s\", type: \"double\", default: \"%f\"},\r\n", - key , vdefault ); + StartStruct(); + AddItem( wxString(key), "key" ); + AddItem( "double", "type" ); + AddItem( (double)vdefault, "default" ); + EndStruct(); } void ShuttleGetDefinition::Define( wxString &var, const wxChar * key, const wxString vdefault, const wxString vmin, const wxString vmax, const wxString vscl ) { - Result += wxString::Format( " { key: \"%s\", type: \"string\", default: \"%s\"},\r\n", - key , vdefault ); + StartStruct(); + AddItem( wxString(key), "key" ); + AddItem( "string", "type" ); + AddItem( vdefault, "default" ); + EndStruct(); } void ShuttleGetDefinition::DefineEnum( wxString &var, const wxChar * key, const wxString vdefault, wxArrayString strings ) { - Result += wxString::Format( " { key: \"%s\", type: \"enum\", default: \"%s\",\r\n enum : [", - key , vdefault ); + StartStruct(); + AddItem( wxString(key), "key" ); + AddItem( "enum", "type" ); + AddItem( vdefault, "default" ); + AddField( "enum" ); + StartArray(); for( size_t i=0;i0) ? ", ":"", strings[i] ); - Result += "]\r\n },\r\n"; + AddItem( strings[i] ); + EndArray(); + EndStruct(); } void ShuttleGetDefinition::DefineEnum( int&var, const wxChar * key, const int vdefault, wxArrayString strings ) { - Result += wxString::Format( " { key: \"%s\", type: \"enum\", default: \"%i\",\r\n enum : [", - key , vdefault ); + StartStruct(); + AddItem( wxString(key), "key" ); + AddItem( "enum", "type" ); + AddItem( (double)vdefault, "default" ); + AddField( "enum" ); + StartArray(); for( size_t i=0;i0) ? ", ":"",strings[i] ); - Result += "]\r\n },\r\n"; + AddItem( strings[i] ); + EndArray(); + EndStruct(); } #pragma warning( pop ) diff --git a/src/Shuttle.h b/src/Shuttle.h index e5593ce95..3a9deb402 100644 --- a/src/Shuttle.h +++ b/src/Shuttle.h @@ -11,7 +11,7 @@ #ifndef __AUDACITY_SHUTTLE__ #define __AUDACITY_SHUTTLE__ - +#include "commands/CommandTargets.h" class Enums { public: @@ -61,7 +61,7 @@ public: class CommandAutomationParameters; /**************************************************************************//** \brief Shuttle that deals with parameters. This is a base class with lots of -pure virtual functions. +virtual functions that do nothing by default. ********************************************************************************/ class ShuttleParams : public Shuttle { @@ -72,15 +72,15 @@ public: virtual ~ShuttleParams() {} bool ExchangeWithMaster(const wxString & Name) override; ShuttleParams & Optional( bool & var ){ var = true;return *this;}; - virtual void Define( bool & var, const wxChar * key, const bool vdefault, const bool vmin=false, const bool vmax=false, const bool vscl=false )=0; - virtual void Define( size_t & var, const wxChar * key, const int vdefault, const int vmin=0, const int vmax=100000, const int vscl=1 )=0; - virtual void Define( int & var, const wxChar * key, const int vdefault, const int vmin=0, const int vmax=100000, const int vscl=1 )=0; - virtual void Define( float & var, const wxChar * key, const float vdefault, const float vmin, const float vmax, const float vscl=1.0f )=0; - virtual void Define( double & var, const wxChar * key, const float vdefault, const float vmin, const float vmax, const float vscl=1.0f )=0; - virtual void Define( double & var, const wxChar * key, const double vdefault, const double vmin, const double vmax, const double vscl=1.0f )=0; - virtual void Define( wxString &var, const wxChar * key, const wxString vdefault, const wxString vmin="", const wxString vmax="", const wxString vscl="" )=0; - virtual void DefineEnum( wxString &var, const wxChar * key, const wxString vdefault, wxArrayString strings )=0; - virtual void DefineEnum( int &var, const wxChar * key, const int vdefault, wxArrayString strings )=0; + virtual void Define( bool & var, const wxChar * key, const bool vdefault, const bool vmin=false, const bool vmax=false, const bool vscl=false ); + virtual void Define( size_t & var, const wxChar * key, const int vdefault, const int vmin=0, const int vmax=100000, const int vscl=1 ); + virtual void Define( int & var, const wxChar * key, const int vdefault, const int vmin=0, const int vmax=100000, const int vscl=1 ); + virtual void Define( float & var, const wxChar * key, const float vdefault, const float vmin, const float vmax, const float vscl=1.0f ); + virtual void Define( double & var, const wxChar * key, const float vdefault, const float vmin, const float vmax, const float vscl=1.0f ); + virtual void Define( double & var, const wxChar * key, const double vdefault, const double vmin, const double vmax, const double vscl=1.0f ); + virtual void Define( wxString &var, const wxChar * key, const wxString vdefault, const wxString vmin="", const wxString vmax="", const wxString vscl="" ); + virtual void DefineEnum( wxString &var, const wxChar * key, const wxString vdefault, wxArrayString strings ); + virtual void DefineEnum( int &var, const wxChar * key, const int vdefault, wxArrayString strings ); }; /**************************************************************************//** @@ -125,9 +125,10 @@ public: /**************************************************************************//** \brief Shuttle that retrieves a JSON format definition of a command's parameters. ********************************************************************************/ -class ShuttleGetDefinition : public ShuttleParams +class ShuttleGetDefinition : public ShuttleParams, public CommandMessageTargetDecorator { public: + ShuttleGetDefinition( CommandMessageTarget & target ); wxString Result; void Define( bool & var, const wxChar * key, const bool vdefault, const bool vmin, const bool vmax, const bool vscl ) override; void Define( int & var, const wxChar * key, const int vdefault, const int vmin, const int vmax, const int vscl ) override; diff --git a/src/commands/CommandTargets.cpp b/src/commands/CommandTargets.cpp index d3dad0814..ff760b3f2 100644 --- a/src/commands/CommandTargets.cpp +++ b/src/commands/CommandTargets.cpp @@ -64,6 +64,169 @@ void CommandMessageTarget::AddItem(const double value, const wxString &name){ mCounts.Last() += 1; } +void CommandMessageTarget::AddField(const wxString &name){ + Update( wxString::Format( "%s%s%s", (mCounts.Last()>0)?", ":"", name, !name.IsEmpty()?":":"")); + mCounts.Last() = 0; // Lie so that we don't get a comma. +} + +void CommandMessageTarget::Flush(){ +} + + + +void LispyCommandMessageTarget::StartArray() +{ + wxString Padding; + Padding.Pad( mCounts.GetCount() *2 -2); + Update( wxString::Format( "%s%s( ", ( mCounts.Last() > 0 ) ? ",\n" : "\n", Padding )); + mCounts.Last() += 1; + mCounts.push_back( 0 ); +} + +void LispyCommandMessageTarget::EndArray(){ + if( mCounts.GetCount() > 1 ){ + mCounts.pop_back(); + } + Update( " )" ); +} +void LispyCommandMessageTarget::StartStruct(){ + wxString Padding; + Padding.Pad( mCounts.GetCount() *2 -2); + Update( wxString::Format( "%s%s( ", ( mCounts.Last() > 0 ) ? ",\n" : "\n", Padding )); + mCounts.Last() += 1; + mCounts.push_back( 0 ); +} +void LispyCommandMessageTarget::EndStruct(){ + if( mCounts.GetCount() > 1 ){ + mCounts.pop_back(); + } + Update( " )" ); +} +void LispyCommandMessageTarget::AddItem(const wxString &value, const wxString &name){ + Update( wxString::Format( "%s%s%s\"%s\"", (mCounts.Last()>0)?", ":"", name, !name.IsEmpty()?",":"",value)); + mCounts.Last() += 1; +} +void LispyCommandMessageTarget::AddItem(const bool value, const wxString &name){ + Update( wxString::Format( "%s%s%s%s", (mCounts.Last()>0)?", ":"", name, !name.IsEmpty()?",":"",value?"True":"False")); + mCounts.Last() += 1; +} +void LispyCommandMessageTarget::AddItem(const double value, const wxString &name){ + Update( wxString::Format( "%s%s%s%g", (mCounts.Last()>0)?", ":"", name, !name.IsEmpty()?",":"",value)); + mCounts.Last() += 1; +} + +void LispyCommandMessageTarget::AddField(const wxString &name){ + Update( wxString::Format( "%s%s%s", (mCounts.Last()>0)?", ":"", name, !name.IsEmpty()?",":"")); + mCounts.Last() = 0; // Lie so that we don't get a comma. +} + + + + + + + +void DeformattedCommandMessageTarget::StartArray() +{ + wxString Padding; + Padding.Pad( mCounts.GetCount() *2 -2); + if( mCounts.GetCount() <= 3 ) + Update( wxString::Format( "%s%s ", ( mCounts.Last() > 0 ) ? " \n" : "", Padding )); + mCounts.Last() += 1; + mCounts.push_back( 0 ); +} + +void DeformattedCommandMessageTarget::EndArray(){ + if( mCounts.GetCount() > 1 ){ + mCounts.pop_back(); + } + if( mCounts.GetCount() <= 3 ) + Update( " " ); +} +void DeformattedCommandMessageTarget::StartStruct(){ + wxString Padding; + Padding.Pad( mCounts.GetCount() *2 -2); + if( mCounts.GetCount() <= 3 ) + Update( wxString::Format( "%s%s ", ( mCounts.Last() > 0 ) ? " \n" : "", Padding )); + mCounts.Last() += 1; + mCounts.push_back( 0 ); +} +void DeformattedCommandMessageTarget::EndStruct(){ + if( mCounts.GetCount() > 1 ){ + mCounts.pop_back(); + } + if( mCounts.GetCount() <= 3 ) + Update( " " ); +} +void DeformattedCommandMessageTarget::AddItem(const wxString &value, const wxString &name){ + if( mCounts.GetCount() <= 3 ) + Update( wxString::Format( "%s\"%s\"", (mCounts.Last()>0)?" ":"",value)); + mCounts.Last() += 1; +} +void DeformattedCommandMessageTarget::AddItem(const bool value, const wxString &name){ + if( mCounts.GetCount() <= 3 ) + Update( wxString::Format( "%s%s", (mCounts.Last()>0)?" ":"",value?"True":"False")); + mCounts.Last() += 1; +} +void DeformattedCommandMessageTarget::AddItem(const double value, const wxString &name){ + if( mCounts.GetCount() <= 3 ) + Update( wxString::Format( "%s%g", (mCounts.Last()>0)?" ":"", value)); + mCounts.Last() += 1; +} + +void DeformattedCommandMessageTarget::AddField(const wxString &name){ + mCounts.Last() = 0; // Lie so that we don't get a comma. +} + + + + + +LispifiedCommandOutputTarget::LispifiedCommandOutputTarget( CommandOutputTarget & target ) + : CommandOutputTarget() , + pToRestore( &target ) +{ + mProgressTarget = std::move(target.mProgressTarget), + mStatusTarget = std::make_shared( *target.mStatusTarget.get() ), + mErrorTarget = std::move( target.mErrorTarget ); +} + +LispifiedCommandOutputTarget::~LispifiedCommandOutputTarget() +{ + pToRestore->mProgressTarget = std::move( mProgressTarget ); + //The status was never captured so does not need restoring. + //pToRestore->mStatusTarget = std::move( mStatusTarget ); + pToRestore->mErrorTarget = std::move( mErrorTarget ); +} + +DeformattedCommandOutputTarget::DeformattedCommandOutputTarget( CommandOutputTarget & target ) + : CommandOutputTarget() , + pToRestore( &target ) +{ + mProgressTarget = std::move(target.mProgressTarget), + mStatusTarget = std::make_shared( *target.mStatusTarget.get() ), + mErrorTarget = std::move( target.mErrorTarget ); +} + +DeformattedCommandOutputTarget::~DeformattedCommandOutputTarget() +{ + pToRestore->mProgressTarget = std::move( mProgressTarget ); + //The status was never captured so does not need restoring. + //pToRestore->mStatusTarget = std::move( mStatusTarget ); + pToRestore->mErrorTarget = std::move( mErrorTarget ); +} + + + + + + + + + + + + /// Dialog for long messages. class AUDACITY_DLL_API LongMessageDialog /* not final */ : public wxDialogWrapper @@ -82,8 +245,10 @@ public: virtual void OnCancel(wxCommandEvent & evt); static void AcceptText( const wxString & Text ); + static void Flush(); - wxTextCtrl * mText; + wxTextCtrl * mTextCtrl; + wxString mText; static LongMessageDialog * pDlg; private: int mType; @@ -124,7 +289,7 @@ bool LongMessageDialog::Init() S.SetBorder(5); S.StartVerticalLay(true); { - mText = S.AddTextWindow( "" ); + mTextCtrl = S.AddTextWindow( "" ); long buttons = eOkButton; S.AddStandardButtons(buttons|mAdditionalButtons); } @@ -154,7 +319,16 @@ void LongMessageDialog::AcceptText( const wxString & Text ) pDlg->Init(); pDlg->Show(); } - pDlg->mText->SetValue( pDlg->mText->GetValue( ) + Text ); + pDlg->mText = pDlg->mText + Text; +} + +void LongMessageDialog::Flush() +{ + if( pDlg ){ + pDlg->mText += "\n\n"; + pDlg->mTextCtrl->SetValue( pDlg->mText ); + pDlg->mTextCtrl->ShowPosition( pDlg->mTextCtrl->GetLastPosition() ); + } } @@ -166,11 +340,15 @@ void LongMessageDialog::AcceptText( const wxString & Text ) class MessageDialogTarget final : public CommandMessageTarget { public: - virtual ~MessageDialogTarget() {} + virtual ~MessageDialogTarget() {Flush();} void Update(const wxString &message) override { LongMessageDialog::AcceptText(message); } + void Flush() override + { + LongMessageDialog::Flush(); + } }; @@ -183,7 +361,6 @@ public: { return std::make_shared(); } - }; diff --git a/src/commands/CommandTargets.h b/src/commands/CommandTargets.h index c7e93d127..27bacd1c7 100644 --- a/src/commands/CommandTargets.h +++ b/src/commands/CommandTargets.h @@ -43,7 +43,7 @@ class CommandMessageTarget /* not final */ { public: CommandMessageTarget() {mCounts.push_back(0);} - virtual ~CommandMessageTarget() {} + virtual ~CommandMessageTarget() { Flush();} virtual void Update(const wxString &message) = 0; virtual void StartArray(); virtual void EndArray(); @@ -52,10 +52,56 @@ public: virtual void AddItem(const wxString &value , const wxString &name="" ); virtual void AddItem(const bool value , const wxString &name="" ); virtual void AddItem(const double value , const wxString &name="" ); + virtual void AddField( const wxString &name="" ); + virtual void Flush(); wxArrayInt mCounts; }; +class CommandMessageTargetDecorator : public CommandMessageTarget +{ +public: + CommandMessageTargetDecorator( CommandMessageTarget & target): mTarget(target) {}; + virtual ~CommandMessageTargetDecorator() { }; + virtual void Update(const wxString &message) { mTarget.Update( message );}; + virtual void StartArray() { mTarget.StartArray();}; + virtual void EndArray(){ mTarget.EndArray();}; + virtual void StartStruct(){ mTarget.StartStruct();}; + virtual void EndStruct(){ mTarget.EndStruct();}; + virtual void AddItem(const wxString &value , const wxString &name="" ){ mTarget.AddItem(value,name);}; + virtual void AddItem(const bool value , const wxString &name="" ){ mTarget.AddItem(value,name);}; + virtual void AddItem(const double value , const wxString &name="" ){ mTarget.AddItem(value,name);}; + virtual void AddField( const wxString &name="" ){ mTarget.AddField(name);}; + virtual void Flush(){ mTarget.Flush();}; + CommandMessageTarget & mTarget; +}; +class LispyCommandMessageTarget : public CommandMessageTargetDecorator /* not final */ +{ +public: + LispyCommandMessageTarget( CommandMessageTarget & target): CommandMessageTargetDecorator(target) {}; + virtual void StartArray() override; + virtual void EndArray() override; + virtual void StartStruct() override; + virtual void EndStruct() override; + virtual void AddItem(const wxString &value , const wxString &name="" )override; + virtual void AddItem(const bool value , const wxString &name="" )override; + virtual void AddItem(const double value , const wxString &name="" )override; + virtual void AddField( const wxString &name="" )override; +}; + +class DeformattedCommandMessageTarget : public CommandMessageTargetDecorator /* not final */ +{ +public: + DeformattedCommandMessageTarget( CommandMessageTarget & target): CommandMessageTargetDecorator(target) {}; + virtual void StartArray() override; + virtual void EndArray() override; + virtual void StartStruct() override; + virtual void EndStruct() override; + virtual void AddItem(const wxString &value , const wxString &name="" )override; + virtual void AddItem(const bool value , const wxString &name="" )override; + virtual void AddItem(const double value , const wxString &name="" )override; + virtual void AddField( const wxString &name="" )override; +}; /// Used to ignore a command's progress updates class NullProgressTarget final : public CommandProgressTarget @@ -197,7 +243,7 @@ public: /// Assumes responsibility for pointers passed into it. class CommandOutputTarget { -protected: +public: std::unique_ptr mProgressTarget; std::shared_ptr mStatusTarget; std::shared_ptr mErrorTarget; @@ -261,9 +307,24 @@ public: if (mStatusTarget) mStatusTarget->AddItem( value, name ); } +}; +class LispifiedCommandOutputTarget : public CommandOutputTarget +{ +public : + LispifiedCommandOutputTarget( CommandOutputTarget & target ); + ~LispifiedCommandOutputTarget(); +private: + CommandOutputTarget * pToRestore; +}; - +class DeformattedCommandOutputTarget : public CommandOutputTarget +{ +public : + DeformattedCommandOutputTarget( CommandOutputTarget & target ); + ~DeformattedCommandOutputTarget(); +private: + CommandOutputTarget * pToRestore; }; class InteractiveOutputTarget : public CommandOutputTarget diff --git a/src/commands/GetInfoCommand.cpp b/src/commands/GetInfoCommand.cpp index 735b43b4e..e79482678 100644 --- a/src/commands/GetInfoCommand.cpp +++ b/src/commands/GetInfoCommand.cpp @@ -24,7 +24,9 @@ This class now handles the GetAll script command, which can #include "../effects/EffectManager.h" #include "../widgets/Overlay.h" #include "../widgets/OverlayPanel.h" +#include "../Track.h" #include "../TrackPanel.h" +#include "../WaveTrack.h" #include "CommandContext.h" #include "SelectCommand.h" @@ -33,12 +35,14 @@ This class now handles the GetAll script command, which can #include "../ShuttleGui.h" #include "CommandContext.h" -const int nTypes =5; +const int nTypes =7; static const wxString kTypes[nTypes] = { XO("Commands"), XO("Menus"), + XO("Tracks"), XO("Clips"), + XO("Labels"), XO("Keycodes"), XO("Boxes") }; @@ -46,7 +50,9 @@ static const wxString kTypes[nTypes] = enum { kCommands, kMenus, + kTracks, kClips, + kLabels, kKeycodes, kBoxes }; @@ -61,8 +67,9 @@ static const wxString kFormats[nFormats] = }; enum { - kJson =0*nTypes, - kOther =1*nTypes + kJson , + kLisp, + kOther }; @@ -90,23 +97,201 @@ void GetInfoCommand::PopulateOrExchange(ShuttleGui & S) bool GetInfoCommand::Apply(const CommandContext &context) { - switch( mInfoType + nTypes * mFormat ){ - case kCommands + kJson : return SendCommandsAsJson( context); - case kCommands + kOther : return SendCommandsAsJson( context); - case kMenus + kJson : return SendMenusAsJson( context); - case kMenus + kOther : return SendMenus( context ); - case kClips + kJson : return SendClips( context); - case kClips + kOther : return SendClips( context ); - case kKeycodes + kJson : return SendKeycodes( context); - case kKeycodes + kOther : return SendKeycodes( context ); - case kBoxes + kJson : return SendBoxesAsJson( context); - case kBoxes + kOther : return SendBoxesAsJson( context ); + if( mFormat == kJson ) + return ApplyInner( context ); + + if( mFormat == kLisp ) + { + CommandContext LispyContext( + *(context.GetProject()), + std::make_unique( *context.pOutput.get() ) + ); + return ApplyInner( LispyContext ); + } + + if( mFormat == kOther ) + { + CommandContext DeformattedContext( + *(context.GetProject()), + std::make_unique( *context.pOutput.get() ) + ); + return ApplyInner( DeformattedContext ); + } + + return false; +} + +bool GetInfoCommand::ApplyInner(const CommandContext &context) +{ + switch( mInfoType ){ + case kCommands : return SendCommands( context ); + case kMenus : return SendMenus( context ); + case kTracks : return SendTracks( context ); + case kClips : return SendClips( context ); + case kLabels : return SendLabels( context ); + case kKeycodes : return SendKeycodes( context ); + case kBoxes : return SendBoxes( context ); default: context.Status( "Command options not recognised" ); } return false; } +bool GetInfoCommand::SendMenus(const CommandContext &context) +{ + wxMenuBar * pBar = context.GetProject()->GetMenuBar(); + if(!pBar ){ + wxLogDebug("No menus"); + return false; + } + + size_t cnt = pBar->GetMenuCount(); + size_t i; + wxString Label; + context.StartArray(); + for(i=0;iGetMenuLabelText( i ); + context.StartArray(); + context.AddItem( 0 ); + context.AddItem( 0 ); + context.AddItem( Label ); + context.AddItem( "" ); + context.EndArray(); + ExploreMenu( context, pBar->GetMenu( i ), pBar->GetId(), 1 ); + } + context.EndArray(); + return true; +} + +/** + Send the list of commands. + */ +bool GetInfoCommand::SendCommands(const CommandContext &context ) +{ + context.StartArray(); + PluginManager & pm = PluginManager::Get(); + EffectManager & em = EffectManager::Get(); + { + const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeEffect | PluginTypeGeneric); + while (plug) + { + auto command = em.GetCommandIdentifier(plug->GetID()); + if (!command.IsEmpty()){ + em.GetCommandDefinition( plug->GetID(), context ); + } + plug = pm.GetNextPlugin(PluginTypeEffect | PluginTypeGeneric ); + } + } + context.EndArray(); + return true; +} + +#if 0 +// Old version which gives enabled/disabled status too. +bool GetInfoCommand::SendMenus(const CommandContext &context) +{ + bool bShowStatus = true; + wxArrayString names; + CommandManager *cmdManager = context.GetProject()->GetCommandManager(); + cmdManager->GetAllCommandNames(names, false); + wxArrayString::iterator iter; + for (iter = names.begin(); iter != names.end(); ++iter) + { + wxString name = *iter; + wxString out = name; + if (bShowStatus) + { + out += wxT("\t"); + out += cmdManager->GetEnabled(name) ? wxT("Enabled") : wxT("Disabled"); + } + context.Status(out); + } + return true; +} +#endif + +bool GetInfoCommand::SendBoxes(const CommandContext &context) +{ + //context.Status("Boxes"); + wxWindow * pWin = context.GetProject(); + + context.StartArray(); + wxRect R = pWin->GetScreenRect(); + + //R.SetPosition( wxPoint(0,0) ); + + //wxString Name = pWin->GetName(); + context.StartArray(); + context.AddItem( 0 ); + context.AddItem( R.GetLeft() ); + context.AddItem( R.GetTop() ); + context.AddItem( R.GetRight() ); + context.AddItem( R.GetBottom() ); + context.AddItem( "Audacity Window" ); + context.EndArray( ); + + ExploreAdornments( context, pWin->GetPosition()+wxSize( 6,-1), pWin, pWin->GetId(), 1 ); + ExploreWindows( context, pWin->GetPosition()+wxSize( 6,-1), pWin, pWin->GetId(), 1 ); + context.EndArray( ); + return true; +} + +bool GetInfoCommand::SendTracks(const CommandContext & context) +{ + TrackList *projTracks = context.GetProject()->GetTracks(); + TrackListIterator iter(projTracks); + Track *trk = iter.First(); + context.StartArray(); + while (trk) + { + context.StartStruct(); + context.AddItem( trk->GetName(), "name" ); + auto t = dynamic_cast( trk ); + if( t ) + { + context.AddItem( t->GetStartTime(), "start" ); + context.AddItem( t->GetEndTime(), "end" ); + context.AddItem( t->GetPan() , "pan"); + context.AddItem( t->GetGain() , "gain"); + context.AddBool( t->GetSelected(), "selected" ); + context.AddBool( t->GetLinked(), "linked"); + context.AddBool( t->GetSolo(), "solo" ); + context.AddBool( t->GetMute(), "mute"); + } + TrackPanel *panel = context.GetProject()->GetTrackPanel(); + Track * fTrack = panel->GetFocusedTrack(); + context.AddBool( (trk == fTrack), "focused"); + context.EndStruct(); + trk=iter.Next(); + } + context.EndArray(); + return true; +} + +bool GetInfoCommand::SendClips(const CommandContext &context) +{ + context.Status("Clips - Not yet"); + return true; +} + +bool GetInfoCommand::SendLabels(const CommandContext &context) +{ + context.Status("Labels - Not yet"); + return true; +} + +bool GetInfoCommand::SendKeycodes(const CommandContext &context) +{ + context.Status("Keycodes - Not yet"); + return true; +} + +/******************************************************************* +The various Explore functions are called from the Send functions, +and may be recursive. 'Send' is the top level. +*******************************************************************/ + void GetInfoCommand::ExploreMenu( const CommandContext &context, wxMenu * pMenu, int Id, int depth ){ Id;//compiler food. if( !pMenu ) @@ -134,7 +319,13 @@ void GetInfoCommand::ExploreMenu( const CommandContext &context, wxMenu * pMenu, if (item->IsCheck() && item->IsChecked()) flags +=2; - context.Status( wxString::Format(" [ %2i, %2i, \"%s\", \"%s\" ],", depth, flags, Label,Accel )); + context.StartArray(); + context.AddItem( depth ); + context.AddItem( flags ); + context.AddItem( Label ); + context.AddItem( Accel ); + context.EndArray(); + if (item->IsSubMenu()) { pMenu = item->GetSubMenu(); ExploreMenu( context, pMenu, item->GetId(), depth+1 ); @@ -142,107 +333,6 @@ void GetInfoCommand::ExploreMenu( const CommandContext &context, wxMenu * pMenu, } } -bool GetInfoCommand::SendMenusAsJson(const CommandContext &context) -{ - wxMenuBar * pBar = context.GetProject()->GetMenuBar(); - if(!pBar ){ - wxLogDebug("No menus"); - return false; - } - - size_t cnt = pBar->GetMenuCount(); - size_t i; - wxString Label; - context.Status( "[" ); - for(i=0;iGetMenuLabelText( i ); - context.Status( wxString::Format(" [ %2i, %2i, \"%s\", \"%s\" ],", 0, 0, Label, "" )); - ExploreMenu( context, pBar->GetMenu( i ), pBar->GetId(), 1 ); - } - context.Status( "]" ); - return true; -} - -/** - Send the list of commands. - */ -bool GetInfoCommand::SendCommandsAsJson(const CommandContext &context ) -{ - PluginManager & pm = PluginManager::Get(); - EffectManager & em = EffectManager::Get(); - { - wxString out=""; - wxString maybeComma=""; - const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeEffect | PluginTypeGeneric); - while (plug) - { - auto command = em.GetCommandIdentifier(plug->GetID()); - if (!command.IsEmpty()){ - // delayed sending of previous string, so we can maybe add a comma. - if( !out.IsEmpty() ) - { - context.Status(out+maybeComma); - maybeComma = ","; - } - out = em.GetCommandDefinition( plug->GetID() ); - } - plug = pm.GetNextPlugin(PluginTypeEffect | PluginTypeGeneric ); - } - if( !out.IsEmpty() ) - context.Status(out); // Last one does not have a comma. - } - return true; -} - -bool GetInfoCommand::SendMenus(const CommandContext &context) -{ - bool bShowStatus = true; - wxArrayString names; - CommandManager *cmdManager = context.GetProject()->GetCommandManager(); - cmdManager->GetAllCommandNames(names, false); - wxArrayString::iterator iter; - for (iter = names.begin(); iter != names.end(); ++iter) - { - wxString name = *iter; - wxString out = name; - if (bShowStatus) - { - out += wxT("\t"); - out += cmdManager->GetEnabled(name) ? wxT("Enabled") : wxT("Disabled"); - } - context.Status(out); - } - return true; -} - -bool GetInfoCommand::SendClips(const CommandContext &context) -{ - bool bShowStatus = true; - wxArrayString names; - CommandManager *cmdManager = context.GetProject()->GetCommandManager(); - cmdManager->GetAllCommandNames(names, false); - wxArrayString::iterator iter; - for (iter = names.begin(); iter != names.end(); ++iter) - { - wxString name = *iter; - wxString out = name; - if (bShowStatus) - { - out += wxT("\t"); - out += cmdManager->GetEnabled(name) ? wxT("Enabled") : wxT("Disabled"); - } - context.Status(out); - } - return true; -} - -bool GetInfoCommand::SendKeycodes(const CommandContext &context) -{ - context.Status("Keycodes"); - return true; -} - void GetInfoCommand::ExploreAdornments( const CommandContext &context, wxPoint WXUNUSED(P), wxWindow * pWin, int WXUNUSED(Id), int depth ) { @@ -393,33 +483,3 @@ void GetInfoCommand::ExploreWindows( const CommandContext &context, } } - -bool GetInfoCommand::SendBoxesAsJson(const CommandContext &context) -{ - //context.Status("Boxes"); - wxWindow * pWin = context.GetProject(); - - context.StartArray(); - wxRect R = pWin->GetScreenRect(); - - //R.SetPosition( wxPoint(0,0) ); - - //wxString Name = pWin->GetName(); - context.StartArray(); - context.AddItem( 0 ); - context.AddItem( R.GetLeft() ); - context.AddItem( R.GetTop() ); - context.AddItem( R.GetRight() ); - context.AddItem( R.GetBottom() ); - context.AddItem( "Audacity Window" ); - context.EndArray( ); - - ExploreAdornments( context, pWin->GetPosition()+wxSize( 6,-1), pWin, pWin->GetId(), 1 ); - ExploreWindows( context, pWin->GetPosition()+wxSize( 6,-1), pWin, pWin->GetId(), 1 ); - context.EndArray( ); - return true; -} - - - - diff --git a/src/commands/GetInfoCommand.h b/src/commands/GetInfoCommand.h index f6aca78d5..17c02d667 100644 --- a/src/commands/GetInfoCommand.h +++ b/src/commands/GetInfoCommand.h @@ -40,19 +40,21 @@ public: // AudacityCommand overrides wxString ManualPage() override {return wxT("Automation");}; bool Apply(const CommandContext &context) override; + bool ApplyInner(const CommandContext &context); public: int mInfoType; int mFormat; private: - bool SendCommandsAsJson(const CommandContext & context); + bool SendCommands(const CommandContext & context); bool SendMenus(const CommandContext & context); - bool SendMenusAsJson(const CommandContext & context); - + bool SendTracks(const CommandContext & context); + bool SendLabels(const CommandContext & context); bool SendClips(const CommandContext & context); bool SendKeycodes(const CommandContext & context); - bool SendBoxesAsJson(const CommandContext & context); + bool SendBoxes(const CommandContext & context); + void ExploreMenu( const CommandContext &context, wxMenu * pMenu, int Id, int depth ); void ExploreTrackPanel( const CommandContext & context, wxPoint P, wxWindow * pWin, int Id, int depth ); diff --git a/src/commands/GetTrackInfoCommand.cpp b/src/commands/GetTrackInfoCommand.cpp index 4539921e3..b8eb5e9a6 100644 --- a/src/commands/GetTrackInfoCommand.cpp +++ b/src/commands/GetTrackInfoCommand.cpp @@ -12,7 +12,7 @@ \brief Definitions for GetTrackInfoCommand and GetTrackInfoCommandType classes \class GetTrackInfoCommand -\brief Command that returns requested track information +\brief Obsolete. GetInfo now does it. *//*******************************************************************/ @@ -58,38 +58,9 @@ void GetTrackInfoCommand::PopulateOrExchange(ShuttleGui & S) S.EndMultiColumn(); } -bool GetTrackInfoCommand::Apply(const CommandContext & context) + + +bool GetTrackInfoCommand::Apply(const CommandContext &context) { - TrackList *projTracks = context.GetProject()->GetTracks(); - TrackListIterator iter(projTracks); - Track *trk = iter.First(); - wxString str = "[\n"; - while (trk) - { - str += "{\n"; - str += wxString::Format(" name:\"%s\",\n", trk->GetName() ); - auto t = dynamic_cast( trk ); - if( t ) - { - str += wxString::Format(" start:%g,\n", t->GetStartTime() ); - str += wxString::Format(" end:%g,\n", t->GetEndTime() ); - str += wxString::Format(" pan:%g,\n", t->GetPan() ); - str += wxString::Format(" gain:%g,\n", t->GetGain() ); - str += wxString::Format(" selected:%s,\n", t->GetSelected()?"True":"False" ); - str += wxString::Format(" linked:%s,\n", t->GetLinked()?"True":"False" ); - str += wxString::Format(" solo:%s,\n", t->GetSolo()?"True":"False" ); - str += wxString::Format(" mute:%s,\n", t->GetMute()?"True":"False" ); - } - TrackPanel *panel = context.GetProject()->GetTrackPanel(); - Track * fTrack = panel->GetFocusedTrack(); - str += wxString::Format(" focused:%s,\n", (trk == fTrack)?"True":"False" ); - str += "},\n"; - trk=iter.Next(); - } - str += "]"; - // Make it true JSON by removing excess commas. - str.Replace(",\n}","\n}"); - str.Replace(",\n]","\n]"); - context.Status( str ); - return true; + return false; } diff --git a/src/commands/HelpCommand.cpp b/src/commands/HelpCommand.cpp index 669de29f8..ac18fabf9 100644 --- a/src/commands/HelpCommand.cpp +++ b/src/commands/HelpCommand.cpp @@ -43,7 +43,7 @@ bool HelpCommand::Apply(const CommandContext & context){ if( ID.IsEmpty() ) context.Status( "Command not found" ); else - context.Status( em.GetCommandDefinition( ID )); + em.GetCommandDefinition( ID, context); return true; } diff --git a/src/commands/LoadCommands.cpp b/src/commands/LoadCommands.cpp index 8d1e70289..c8509d67e 100644 --- a/src/commands/LoadCommands.cpp +++ b/src/commands/LoadCommands.cpp @@ -38,9 +38,8 @@ modelled on BuiltinEffectsModule // #define COMMAND_LIST \ COMMAND( DEMO, DemoCommand, () ) \ - COMMAND( SCREENSHOT, ScreenshotCommand, () ) \ + COMMAND( SCREENSHOT, ScreenshotCommand, () ) \ COMMAND( COMPARE_AUDIO, CompareAudioCommand, () ) \ - COMMAND( GET_TRACK_INFO, GetTrackInfoCommand, () ) \ COMMAND( SET_TRACK_INFO, SetTrackInfoCommand, () ) \ COMMAND( SELECT, SelectCommand, () ) \ COMMAND( SELECT_TIME, SelectTimeCommand, () ) \ @@ -54,6 +53,8 @@ modelled on BuiltinEffectsModule COMMAND( OPEN_PROJECT, OpenProjectCommand, () ) \ COMMAND( SAVE_PROJECT, SaveProjectCommand, () ) \ + // GET_TRACK_INFO subsumed by GET_INFO + //COMMAND( GET_TRACK_INFO, GetTrackInfoCommand, () ) // diff --git a/src/effects/EffectManager.cpp b/src/effects/EffectManager.cpp index 74accfc1b..25ad77f57 100644 --- a/src/effects/EffectManager.cpp +++ b/src/effects/EffectManager.cpp @@ -198,27 +198,30 @@ wxString EffectManager::GetCommandDescription(const PluginID & ID) return wxEmptyString; } -wxString EffectManager::GetCommandDefinition(const PluginID & ID) +void EffectManager::GetCommandDefinition(const PluginID & ID, const CommandContext & context) { CommandDefinitionInterface *command; command = GetEffect(ID); if( !command ) command = GetAudacityCommand( ID ); if( !command ) - return wxEmptyString; + return; - ShuttleGetDefinition S; - if( command->DefineParams( S ) ) - { - wxString Temp; - Temp += "{ id: \"" + GetCommandIdentifier( ID ) + "\", name: \"" + GetCommandName( ID ) + "\", params: [\r\n"; - Temp += S.Result; - Temp += "]}"; - Temp.Replace( ",\r\n]","\r\n]"); // fix up for trailing comma. Relies on \r\n endings from ShuttleGetDefinition - return Temp; - } + ShuttleParams NullShuttle; + // Test if it defines any parameters at all. + if( !command->DefineParams( NullShuttle ) ) + return; - return wxEmptyString; + // This is capturing the output context into the shuttle. + ShuttleGetDefinition S( *context.pOutput.get()->mStatusTarget.get() ); + S.StartStruct(); + S.AddItem( GetCommandIdentifier( ID ), "id" ); + S.AddItem( GetCommandName( ID ), "name" ); + S.AddField( "params" ); + S.StartArray(); + command->DefineParams( S ); + S.EndArray(); + S.EndStruct(); } diff --git a/src/effects/EffectManager.h b/src/effects/EffectManager.h index 4873511b8..84a89abff 100644 --- a/src/effects/EffectManager.h +++ b/src/effects/EffectManager.h @@ -31,6 +31,7 @@ class AudacityCommand; class CommandContext; +class CommandMessageTarget; using EffectArray = std::vector ; using EffectMap = std::unordered_map; @@ -92,7 +93,7 @@ public: wxString GetCommandName(const PluginID & ID); wxString GetCommandIdentifier(const PluginID & ID); wxString GetCommandDescription(const PluginID & ID); - wxString GetCommandDefinition(const PluginID & ID); + void GetCommandDefinition(const PluginID & ID, const CommandContext & context); bool IsHidden(const PluginID & ID); /** Support for batch commands */