1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-03 14:13:11 +02:00

Support: JSON, Lispy or Other formats

This commit is contained in:
James Crook 2018-02-08 16:22:01 +00:00 committed by Paul Licameli
parent c0c5cc6337
commit ca5dac59ff
12 changed files with 573 additions and 246 deletions

View File

@ -1614,8 +1614,8 @@ void AudacityProject::CreateMenusAndCommands()
AudioIONotBusyFlag, AudioIONotBusyFlag); AudioIONotBusyFlag, AudioIONotBusyFlag);
c->AddItem(wxT("GetInfo"), _("Get Info..."), FN(OnAudacityCommand), c->AddItem(wxT("GetInfo"), _("Get Info..."), FN(OnAudacityCommand),
AudioIONotBusyFlag, AudioIONotBusyFlag); AudioIONotBusyFlag, AudioIONotBusyFlag);
c->AddItem(wxT("GetTrackInfo"), _("Get Track Info..."), FN(OnAudacityCommand), // c->AddItem(wxT("GetTrackInfo"), _("Get Track Info..."), FN(OnAudacityCommand),
AudioIONotBusyFlag, AudioIONotBusyFlag); // AudioIONotBusyFlag, AudioIONotBusyFlag);
c->EndSubMenu(); c->EndSubMenu();

View File

@ -332,8 +332,23 @@ bool ShuttleParams::ExchangeWithMaster(const wxString & WXUNUSED(Name))
return true; return true;
} }
#pragma warning( push ) #pragma warning( push )
#pragma warning( disable: 4100 ) // unused parameters. #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 ) 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; var = temp;
} }
ShuttleGetDefinition::ShuttleGetDefinition( CommandMessageTarget & target ) : CommandMessageTargetDecorator( target )
{
}
// JSON definitions. // 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 ) 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", StartStruct();
key , vdefault ? "True" : "False" ); 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 ) 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", StartStruct();
key , vdefault ); 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 ) 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", StartStruct();
key , vdefault ); 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 ) 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", StartStruct();
key , vdefault ); 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 ) 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", StartStruct();
key , vdefault ); 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 ) 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", StartStruct();
key , vdefault ); 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 ) 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", StartStruct();
key , vdefault ); AddItem( wxString(key), "key" );
AddItem( "string", "type" );
AddItem( vdefault, "default" );
EndStruct();
} }
void ShuttleGetDefinition::DefineEnum( wxString &var, const wxChar * key, const wxString vdefault, wxArrayString strings ) 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 : [", StartStruct();
key , vdefault ); AddItem( wxString(key), "key" );
AddItem( "enum", "type" );
AddItem( vdefault, "default" );
AddField( "enum" );
StartArray();
for( size_t i=0;i<strings.Count(); i++ ) for( size_t i=0;i<strings.Count(); i++ )
Result += wxString::Format("%s\"%s\"", (i>0) ? ", ":"", strings[i] ); AddItem( strings[i] );
Result += "]\r\n },\r\n"; EndArray();
EndStruct();
} }
void ShuttleGetDefinition::DefineEnum( int&var, const wxChar * key, const int vdefault, wxArrayString strings ) 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 : [", StartStruct();
key , vdefault ); AddItem( wxString(key), "key" );
AddItem( "enum", "type" );
AddItem( (double)vdefault, "default" );
AddField( "enum" );
StartArray();
for( size_t i=0;i<strings.Count(); i++ ) for( size_t i=0;i<strings.Count(); i++ )
Result += wxString::Format("%s\"%s\"", (i>0) ? ", ":"",strings[i] ); AddItem( strings[i] );
Result += "]\r\n },\r\n"; EndArray();
EndStruct();
} }
#pragma warning( pop ) #pragma warning( pop )

View File

@ -11,7 +11,7 @@
#ifndef __AUDACITY_SHUTTLE__ #ifndef __AUDACITY_SHUTTLE__
#define __AUDACITY_SHUTTLE__ #define __AUDACITY_SHUTTLE__
#include "commands/CommandTargets.h"
class Enums { class Enums {
public: public:
@ -61,7 +61,7 @@ public:
class CommandAutomationParameters; class CommandAutomationParameters;
/**************************************************************************//** /**************************************************************************//**
\brief Shuttle that deals with parameters. This is a base class with lots of \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 class ShuttleParams : public Shuttle
{ {
@ -72,15 +72,15 @@ public:
virtual ~ShuttleParams() {} virtual ~ShuttleParams() {}
bool ExchangeWithMaster(const wxString & Name) override; bool ExchangeWithMaster(const wxString & Name) override;
ShuttleParams & Optional( bool & var ){ var = true;return *this;}; 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( 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 )=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 );
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( 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 )=0; 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 )=0; 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 )=0; 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="" )=0; 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 )=0; 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 )=0; 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. \brief Shuttle that retrieves a JSON format definition of a command's parameters.
********************************************************************************/ ********************************************************************************/
class ShuttleGetDefinition : public ShuttleParams class ShuttleGetDefinition : public ShuttleParams, public CommandMessageTargetDecorator
{ {
public: public:
ShuttleGetDefinition( CommandMessageTarget & target );
wxString Result; wxString Result;
void Define( bool & var, const wxChar * key, const bool vdefault, const bool vmin, const bool vmax, const bool vscl ) override; 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; void Define( int & var, const wxChar * key, const int vdefault, const int vmin, const int vmax, const int vscl ) override;

View File

@ -64,6 +64,169 @@ void CommandMessageTarget::AddItem(const double value, const wxString &name){
mCounts.Last() += 1; 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<LispyCommandMessageTarget>( *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<DeformattedCommandMessageTarget>( *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. /// Dialog for long messages.
class AUDACITY_DLL_API LongMessageDialog /* not final */ : public wxDialogWrapper class AUDACITY_DLL_API LongMessageDialog /* not final */ : public wxDialogWrapper
@ -82,8 +245,10 @@ public:
virtual void OnCancel(wxCommandEvent & evt); virtual void OnCancel(wxCommandEvent & evt);
static void AcceptText( const wxString & Text ); static void AcceptText( const wxString & Text );
static void Flush();
wxTextCtrl * mText; wxTextCtrl * mTextCtrl;
wxString mText;
static LongMessageDialog * pDlg; static LongMessageDialog * pDlg;
private: private:
int mType; int mType;
@ -124,7 +289,7 @@ bool LongMessageDialog::Init()
S.SetBorder(5); S.SetBorder(5);
S.StartVerticalLay(true); S.StartVerticalLay(true);
{ {
mText = S.AddTextWindow( "" ); mTextCtrl = S.AddTextWindow( "" );
long buttons = eOkButton; long buttons = eOkButton;
S.AddStandardButtons(buttons|mAdditionalButtons); S.AddStandardButtons(buttons|mAdditionalButtons);
} }
@ -154,7 +319,16 @@ void LongMessageDialog::AcceptText( const wxString & Text )
pDlg->Init(); pDlg->Init();
pDlg->Show(); 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 class MessageDialogTarget final : public CommandMessageTarget
{ {
public: public:
virtual ~MessageDialogTarget() {} virtual ~MessageDialogTarget() {Flush();}
void Update(const wxString &message) override void Update(const wxString &message) override
{ {
LongMessageDialog::AcceptText(message); LongMessageDialog::AcceptText(message);
} }
void Flush() override
{
LongMessageDialog::Flush();
}
}; };
@ -183,7 +361,6 @@ public:
{ {
return std::make_shared<MessageDialogTarget>(); return std::make_shared<MessageDialogTarget>();
} }
}; };

View File

@ -43,7 +43,7 @@ class CommandMessageTarget /* not final */
{ {
public: public:
CommandMessageTarget() {mCounts.push_back(0);} CommandMessageTarget() {mCounts.push_back(0);}
virtual ~CommandMessageTarget() {} virtual ~CommandMessageTarget() { Flush();}
virtual void Update(const wxString &message) = 0; virtual void Update(const wxString &message) = 0;
virtual void StartArray(); virtual void StartArray();
virtual void EndArray(); virtual void EndArray();
@ -52,10 +52,56 @@ public:
virtual void AddItem(const wxString &value , const wxString &name="" ); virtual void AddItem(const wxString &value , const wxString &name="" );
virtual void AddItem(const bool value , const wxString &name="" ); virtual void AddItem(const bool value , const wxString &name="" );
virtual void AddItem(const double value , const wxString &name="" ); virtual void AddItem(const double value , const wxString &name="" );
virtual void AddField( const wxString &name="" );
virtual void Flush();
wxArrayInt mCounts; 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 /// Used to ignore a command's progress updates
class NullProgressTarget final : public CommandProgressTarget class NullProgressTarget final : public CommandProgressTarget
@ -197,7 +243,7 @@ public:
/// Assumes responsibility for pointers passed into it. /// Assumes responsibility for pointers passed into it.
class CommandOutputTarget class CommandOutputTarget
{ {
protected: public:
std::unique_ptr<CommandProgressTarget> mProgressTarget; std::unique_ptr<CommandProgressTarget> mProgressTarget;
std::shared_ptr<CommandMessageTarget> mStatusTarget; std::shared_ptr<CommandMessageTarget> mStatusTarget;
std::shared_ptr<CommandMessageTarget> mErrorTarget; std::shared_ptr<CommandMessageTarget> mErrorTarget;
@ -261,9 +307,24 @@ public:
if (mStatusTarget) if (mStatusTarget)
mStatusTarget->AddItem( value, name ); 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 class InteractiveOutputTarget : public CommandOutputTarget

View File

@ -24,7 +24,9 @@ This class now handles the GetAll script command, which can
#include "../effects/EffectManager.h" #include "../effects/EffectManager.h"
#include "../widgets/Overlay.h" #include "../widgets/Overlay.h"
#include "../widgets/OverlayPanel.h" #include "../widgets/OverlayPanel.h"
#include "../Track.h"
#include "../TrackPanel.h" #include "../TrackPanel.h"
#include "../WaveTrack.h"
#include "CommandContext.h" #include "CommandContext.h"
#include "SelectCommand.h" #include "SelectCommand.h"
@ -33,12 +35,14 @@ This class now handles the GetAll script command, which can
#include "../ShuttleGui.h" #include "../ShuttleGui.h"
#include "CommandContext.h" #include "CommandContext.h"
const int nTypes =5; const int nTypes =7;
static const wxString kTypes[nTypes] = static const wxString kTypes[nTypes] =
{ {
XO("Commands"), XO("Commands"),
XO("Menus"), XO("Menus"),
XO("Tracks"),
XO("Clips"), XO("Clips"),
XO("Labels"),
XO("Keycodes"), XO("Keycodes"),
XO("Boxes") XO("Boxes")
}; };
@ -46,7 +50,9 @@ static const wxString kTypes[nTypes] =
enum { enum {
kCommands, kCommands,
kMenus, kMenus,
kTracks,
kClips, kClips,
kLabels,
kKeycodes, kKeycodes,
kBoxes kBoxes
}; };
@ -61,8 +67,9 @@ static const wxString kFormats[nFormats] =
}; };
enum { enum {
kJson =0*nTypes, kJson ,
kOther =1*nTypes kLisp,
kOther
}; };
@ -90,23 +97,201 @@ void GetInfoCommand::PopulateOrExchange(ShuttleGui & S)
bool GetInfoCommand::Apply(const CommandContext &context) bool GetInfoCommand::Apply(const CommandContext &context)
{ {
switch( mInfoType + nTypes * mFormat ){ if( mFormat == kJson )
case kCommands + kJson : return SendCommandsAsJson( context); return ApplyInner( context );
case kCommands + kOther : return SendCommandsAsJson( context);
case kMenus + kJson : return SendMenusAsJson( context); if( mFormat == kLisp )
case kMenus + kOther : return SendMenus( context ); {
case kClips + kJson : return SendClips( context); CommandContext LispyContext(
case kClips + kOther : return SendClips( context ); *(context.GetProject()),
case kKeycodes + kJson : return SendKeycodes( context); std::make_unique<LispifiedCommandOutputTarget>( *context.pOutput.get() )
case kKeycodes + kOther : return SendKeycodes( context ); );
case kBoxes + kJson : return SendBoxesAsJson( context); return ApplyInner( LispyContext );
case kBoxes + kOther : return SendBoxesAsJson( context ); }
if( mFormat == kOther )
{
CommandContext DeformattedContext(
*(context.GetProject()),
std::make_unique<DeformattedCommandOutputTarget>( *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: default:
context.Status( "Command options not recognised" ); context.Status( "Command options not recognised" );
} }
return false; 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;i<cnt;i++)
{
Label = pBar->GetMenuLabelText( 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<WaveTrack*>( 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 ){ void GetInfoCommand::ExploreMenu( const CommandContext &context, wxMenu * pMenu, int Id, int depth ){
Id;//compiler food. Id;//compiler food.
if( !pMenu ) if( !pMenu )
@ -134,7 +319,13 @@ void GetInfoCommand::ExploreMenu( const CommandContext &context, wxMenu * pMenu,
if (item->IsCheck() && item->IsChecked()) if (item->IsCheck() && item->IsChecked())
flags +=2; 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()) { if (item->IsSubMenu()) {
pMenu = item->GetSubMenu(); pMenu = item->GetSubMenu();
ExploreMenu( context, pMenu, item->GetId(), depth+1 ); 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;i<cnt;i++)
{
Label = pBar->GetMenuLabelText( 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, void GetInfoCommand::ExploreAdornments( const CommandContext &context,
wxPoint WXUNUSED(P), wxWindow * pWin, int WXUNUSED(Id), int depth ) 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;
}

View File

@ -40,19 +40,21 @@ public:
// AudacityCommand overrides // AudacityCommand overrides
wxString ManualPage() override {return wxT("Automation");}; wxString ManualPage() override {return wxT("Automation");};
bool Apply(const CommandContext &context) override; bool Apply(const CommandContext &context) override;
bool ApplyInner(const CommandContext &context);
public: public:
int mInfoType; int mInfoType;
int mFormat; int mFormat;
private: private:
bool SendCommandsAsJson(const CommandContext & context); bool SendCommands(const CommandContext & context);
bool SendMenus(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 SendClips(const CommandContext & context);
bool SendKeycodes(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 ExploreMenu( const CommandContext &context, wxMenu * pMenu, int Id, int depth );
void ExploreTrackPanel( const CommandContext & context, void ExploreTrackPanel( const CommandContext & context,
wxPoint P, wxWindow * pWin, int Id, int depth ); wxPoint P, wxWindow * pWin, int Id, int depth );

View File

@ -12,7 +12,7 @@
\brief Definitions for GetTrackInfoCommand and GetTrackInfoCommandType classes \brief Definitions for GetTrackInfoCommand and GetTrackInfoCommandType classes
\class GetTrackInfoCommand \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(); S.EndMultiColumn();
} }
bool GetTrackInfoCommand::Apply(const CommandContext &context) bool GetTrackInfoCommand::Apply(const CommandContext &context)
{ {
TrackList *projTracks = context.GetProject()->GetTracks(); return false;
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<WaveTrack*>( 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;
} }

View File

@ -43,7 +43,7 @@ bool HelpCommand::Apply(const CommandContext & context){
if( ID.IsEmpty() ) if( ID.IsEmpty() )
context.Status( "Command not found" ); context.Status( "Command not found" );
else else
context.Status( em.GetCommandDefinition( ID )); em.GetCommandDefinition( ID, context);
return true; return true;
} }

View File

@ -40,7 +40,6 @@ modelled on BuiltinEffectsModule
COMMAND( DEMO, DemoCommand, () ) \ COMMAND( DEMO, DemoCommand, () ) \
COMMAND( SCREENSHOT, ScreenshotCommand, () ) \ COMMAND( SCREENSHOT, ScreenshotCommand, () ) \
COMMAND( COMPARE_AUDIO, CompareAudioCommand, () ) \ COMMAND( COMPARE_AUDIO, CompareAudioCommand, () ) \
COMMAND( GET_TRACK_INFO, GetTrackInfoCommand, () ) \
COMMAND( SET_TRACK_INFO, SetTrackInfoCommand, () ) \ COMMAND( SET_TRACK_INFO, SetTrackInfoCommand, () ) \
COMMAND( SELECT, SelectCommand, () ) \ COMMAND( SELECT, SelectCommand, () ) \
COMMAND( SELECT_TIME, SelectTimeCommand, () ) \ COMMAND( SELECT_TIME, SelectTimeCommand, () ) \
@ -54,6 +53,8 @@ modelled on BuiltinEffectsModule
COMMAND( OPEN_PROJECT, OpenProjectCommand, () ) \ COMMAND( OPEN_PROJECT, OpenProjectCommand, () ) \
COMMAND( SAVE_PROJECT, SaveProjectCommand, () ) \ COMMAND( SAVE_PROJECT, SaveProjectCommand, () ) \
// GET_TRACK_INFO subsumed by GET_INFO
//COMMAND( GET_TRACK_INFO, GetTrackInfoCommand, () )
// //

View File

@ -198,27 +198,30 @@ wxString EffectManager::GetCommandDescription(const PluginID & ID)
return wxEmptyString; return wxEmptyString;
} }
wxString EffectManager::GetCommandDefinition(const PluginID & ID) void EffectManager::GetCommandDefinition(const PluginID & ID, const CommandContext & context)
{ {
CommandDefinitionInterface *command; CommandDefinitionInterface *command;
command = GetEffect(ID); command = GetEffect(ID);
if( !command ) if( !command )
command = GetAudacityCommand( ID ); command = GetAudacityCommand( ID );
if( !command ) if( !command )
return wxEmptyString; return;
ShuttleGetDefinition S; ShuttleParams NullShuttle;
if( command->DefineParams( S ) ) // Test if it defines any parameters at all.
{ if( !command->DefineParams( NullShuttle ) )
wxString Temp; return;
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;
}
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();
} }

View File

@ -31,6 +31,7 @@
class AudacityCommand; class AudacityCommand;
class CommandContext; class CommandContext;
class CommandMessageTarget;
using EffectArray = std::vector <Effect*> ; using EffectArray = std::vector <Effect*> ;
using EffectMap = std::unordered_map<wxString, Effect *>; using EffectMap = std::unordered_map<wxString, Effect *>;
@ -92,7 +93,7 @@ public:
wxString GetCommandName(const PluginID & ID); wxString GetCommandName(const PluginID & ID);
wxString GetCommandIdentifier(const PluginID & ID); wxString GetCommandIdentifier(const PluginID & ID);
wxString GetCommandDescription(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); bool IsHidden(const PluginID & ID);
/** Support for batch commands */ /** Support for batch commands */