From 87a9f34c2253d6a3c204d519d761872289ac010f Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 11 May 2019 18:49:02 -0400 Subject: [PATCH 1/8] ScreenshotCommand uses hooks in AudacityCommand and Effect dialogs... ... so that they don't have a static linkage dependency on it, and that frees it from dependency cycles, to a high level --- src/commands/AudacityCommand.cpp | 24 +++++++++++++++++++++--- src/commands/AudacityCommand.h | 5 +++++ src/commands/ScreenshotCommand.cpp | 17 ++++++++++++++++- src/commands/ScreenshotCommand.h | 2 +- src/effects/Effect.cpp | 25 ++++++++++++++++++++++--- src/effects/Effect.h | 5 +++++ 6 files changed, 70 insertions(+), 8 deletions(-) diff --git a/src/commands/AudacityCommand.cpp b/src/commands/AudacityCommand.cpp index c3f3b2c03..7ed08d232 100644 --- a/src/commands/AudacityCommand.cpp +++ b/src/commands/AudacityCommand.cpp @@ -44,10 +44,27 @@ ShuttleGui. #include "../widgets/HelpSystem.h" #include "../widgets/ErrorDialog.h" -#include "../commands/ScreenshotCommand.h" - #include +namespace { + +AudacityCommand::VetoDialogHook &GetVetoDialogHook() +{ + static AudacityCommand::VetoDialogHook sHook = nullptr; + return sHook; +} + +} + +auto AudacityCommand::SetVetoDialogHook( VetoDialogHook hook ) + -> VetoDialogHook +{ + auto &theHook = GetVetoDialogHook(); + auto result = theHook; + theHook = hook; + return result; +} + AudacityCommand::AudacityCommand() { mProgress = NULL; @@ -105,7 +122,8 @@ bool AudacityCommand::ShowInterface(wxWindow *parent, bool WXUNUSED(forceModal)) mUIDialog->SetMinSize(mUIDialog->GetSize()); // The Screenshot command might be popping this dialog up, just to capture it. - if( ScreenshotCommand::MayCapture( mUIDialog ) ) + auto hook = GetVetoDialogHook(); + if( hook && hook( mUIDialog ) ) return false; bool res = mUIDialog->ShowModal() != 0; diff --git a/src/commands/AudacityCommand.h b/src/commands/AudacityCommand.h index c17d15dad..d454c337d 100644 --- a/src/commands/AudacityCommand.h +++ b/src/commands/AudacityCommand.h @@ -45,6 +45,11 @@ class AUDACITY_DLL_API AudacityCommand /* not final */ : public wxEvtHandler, public: AudacityCommand(); virtual ~AudacityCommand(); + + // Type of a registered function that, if it returns true, + // causes ShowInterface to return early without making any dialog + using VetoDialogHook = bool (*) ( wxDialog* ); + static VetoDialogHook SetVetoDialogHook( VetoDialogHook hook ); // ComponentInterface implementation diff --git a/src/commands/ScreenshotCommand.cpp b/src/commands/ScreenshotCommand.cpp index bb9872599..24be56367 100644 --- a/src/commands/ScreenshotCommand.cpp +++ b/src/commands/ScreenshotCommand.cpp @@ -20,6 +20,8 @@ small calculations of rectangles. #include "../Audacity.h" #include "ScreenshotCommand.h" +#include + #include "../Project.h" #include #include @@ -31,6 +33,7 @@ small calculations of rectangles. #include "../AdornedRulerPanel.h" #include "../TrackPanel.h" +#include "../effects/Effect.h" #include "../toolbars/ToolManager.h" #include "../Prefs.h" #include "../Shuttle.h" @@ -87,7 +90,19 @@ kBackgroundStrings[ ScreenshotCommand::nBackgrounds ] = }; -bool ScreenshotCommand::DefineParams( ShuttleParams & S ){ +ScreenshotCommand::ScreenshotCommand() +{ + mbBringToTop=true; + mIgnore=NULL; + + static std::once_flag flag; + std::call_once( flag, []{ + AudacityCommand::SetVetoDialogHook( MayCapture ); + Effect::SetVetoDialogHook( MayCapture ); + }); +} + +bool ScreenshotCommand::DefineParams( ShuttleParams & S ){ S.Define( mPath, wxT("Path"), wxT("")); S.DefineEnum( mWhat, wxT("CaptureWhat"), kwindow,kCaptureWhatStrings, nCaptureWhats ); S.DefineEnum( mBack, wxT("Background"), kNone, kBackgroundStrings, nBackgrounds ); diff --git a/src/commands/ScreenshotCommand.h b/src/commands/ScreenshotCommand.h index f7e1a82ce..f2ff701d9 100644 --- a/src/commands/ScreenshotCommand.h +++ b/src/commands/ScreenshotCommand.h @@ -78,7 +78,7 @@ public: nCaptureWhats }; - ScreenshotCommand(){ mbBringToTop=true;mIgnore=NULL;}; + ScreenshotCommand(); // ComponentInterface overrides ComponentInterfaceSymbol GetSymbol() override {return SCREENSHOT_PLUGIN_SYMBOL;}; wxString GetDescription() override {return _("Takes screenshots.");}; diff --git a/src/effects/Effect.cpp b/src/effects/Effect.cpp index b20ad3ed9..7d70cf45b 100644 --- a/src/effects/Effect.cpp +++ b/src/effects/Effect.cpp @@ -59,6 +59,7 @@ greater use in future. #include "../ShuttleGui.h" #include "../Shuttle.h" #include "../WaveTrack.h" +#include "../commands/Command.h" #include "../toolbars/ControlToolBar.h" #include "../widgets/AButton.h" #include "../widgets/ProgressDialog.h" @@ -76,8 +77,6 @@ greater use in future. #include #endif -#include "../commands/ScreenshotCommand.h" - #include // Effect application counter @@ -109,6 +108,25 @@ const wxString Effect::kFactoryDefaultsIdent = wxT(""); using t2bHash = std::unordered_map< void*, bool >; +namespace { + +Effect::VetoDialogHook &GetVetoDialogHook() +{ + static Effect::VetoDialogHook sHook = nullptr; + return sHook; +} + +} + +auto Effect::SetVetoDialogHook( VetoDialogHook hook ) + -> VetoDialogHook +{ + auto &theHook = GetVetoDialogHook(); + auto result = theHook; + theHook = hook; + return result; +} + Effect::Effect() { mClient = NULL; @@ -556,7 +574,8 @@ bool Effect::ShowInterface(wxWindow *parent, bool forceModal) mUIDialog->Fit(); mUIDialog->SetMinSize(mUIDialog->GetSize()); - if( ScreenshotCommand::MayCapture( mUIDialog ) ) + auto hook = GetVetoDialogHook(); + if( hook && hook( mUIDialog ) ) return false; if( SupportsRealtime() && !forceModal ) diff --git a/src/effects/Effect.h b/src/effects/Effect.h index 2f41d3274..5bffba41c 100644 --- a/src/effects/Effect.h +++ b/src/effects/Effect.h @@ -72,6 +72,11 @@ class AUDACITY_DLL_API Effect /* not final */ : public wxEvtHandler, Effect(); virtual ~Effect(); + // Type of a registered function that, if it returns true, + // causes ShowInterface to return early without making any dialog + using VetoDialogHook = bool (*) ( wxDialog* ); + static VetoDialogHook SetVetoDialogHook( VetoDialogHook hook ); + // ComponentInterface implementation PluginPath GetPath() override; From 1c0453106dff1dec008e656829576bef1d5eef02 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 12 May 2019 06:45:39 -0400 Subject: [PATCH 2/8] CommandTargets.cpp has fewer dependencies... ... freeing two files from dependency cycles --- src/commands/CommandTargets.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/commands/CommandTargets.cpp b/src/commands/CommandTargets.cpp index d38158a9d..6668002a3 100644 --- a/src/commands/CommandTargets.cpp +++ b/src/commands/CommandTargets.cpp @@ -24,9 +24,10 @@ capture the more lengthy output from some commands. #include "../Audacity.h" #include "CommandTargets.h" +#include +#include #include #include "../ShuttleGui.h" -#include "../Project.h" #include "../widgets/ErrorDialog.h" void CommandMessageTarget::StartArray() @@ -375,7 +376,8 @@ void LongMessageDialog::OnCancel(wxCommandEvent & WXUNUSED(evt)){ void LongMessageDialog::AcceptText( const wxString & Text ) { if( pDlg == NULL ){ - pDlg = new LongMessageDialog( GetActiveProject(), _( "Long Message" ) ); + pDlg = new LongMessageDialog( + wxTheApp->GetTopWindow(), _( "Long Message" ) ); pDlg->Init(); pDlg->Show(); } From 9eb9104859837772fa249106e3cb68465511584c Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 11 May 2019 16:19:43 -0400 Subject: [PATCH 3/8] Remove CommandContext::GetProject() ... ... which called ::GetActiveProject(), but one purpose of the CommandContext class was to eliminate many uses of that global function, because a CommandContext must always be constructed from a reference to a project (which was always in fact the active one), then passed around to where it is needed! Also, just use the project member directly -- because CommandContext was intended as just a P.O.D (plain-old-data) structure. This also eliminates a dependency of CommandContext.cpp on Project.cpp. This is not enough by itself to break any dependency cycles. --- src/Screenshot.cpp | 22 ++++---- src/commands/Command.h | 2 +- src/commands/CommandContext.cpp | 7 +-- src/commands/CommandContext.h | 1 - src/commands/CommandHandler.cpp | 2 +- src/commands/CommandHandler.h | 2 +- src/commands/CompareAudioCommand.cpp | 2 +- src/commands/DragCommand.cpp | 2 +- src/commands/GetInfoCommand.cpp | 26 +++++----- src/commands/ImportExportCommands.cpp | 8 +-- src/commands/OpenSaveCommands.cpp | 12 ++--- src/commands/ScreenshotCommand.cpp | 72 +++++++++++++-------------- src/commands/SelectCommand.cpp | 8 +-- src/commands/SetLabelCommand.cpp | 4 +- src/commands/SetProjectCommand.cpp | 2 +- src/commands/SetTrackInfoCommand.cpp | 4 +- 16 files changed, 86 insertions(+), 90 deletions(-) diff --git a/src/Screenshot.cpp b/src/Screenshot.cpp index 3af7c82da..10bbead97 100644 --- a/src/Screenshot.cpp +++ b/src/Screenshot.cpp @@ -95,7 +95,7 @@ class ScreenFrame final : public wxFrame wxStatusBar *mStatus; std::unique_ptr mCommand; - CommandContext mContext; + const CommandContext mContext; DECLARE_EVENT_TABLE() }; @@ -469,7 +469,7 @@ void ScreenFrame::PopulateOrExchange(ShuttleGui & S) CentreOnParent(); } - SetIcon(mContext.GetProject()->GetIcon()); + SetIcon(mContext.project.GetIcon()); } bool ScreenFrame::ProcessEvent(wxEvent & e) @@ -564,8 +564,8 @@ void ScreenFrame::SizeMainWindow(int w, int h) { int top = 20; - mContext.GetProject()->Maximize(false); - mContext.GetProject()->SetSize(16, 16 + top, w, h); + mContext.project.Maximize(false); + mContext.project.SetSize(16, 16 + top, w, h); //Bug383 - Toolbar Resets not wanted. //mContext.GetProject()->GetToolManager()->Reset(); } @@ -669,9 +669,9 @@ void ScreenFrame::OnCaptureSomething(wxCommandEvent & event) void ScreenFrame::TimeZoom(double seconds) { int width, height; - mContext.GetProject()->GetClientSize(&width, &height); - mContext.GetProject()->mViewInfo.SetZoom((0.75 * width) / seconds); - mContext.GetProject()->RedrawProject(); + mContext.project.GetClientSize(&width, &height); + mContext.project.mViewInfo.SetZoom((0.75 * width) / seconds); + mContext.project.RedrawProject(); } void ScreenFrame::OnOneSec(wxCommandEvent & WXUNUSED(event)) @@ -708,7 +708,7 @@ void ScreenFrame::SizeTracks(int h) // If there should be more-than-stereo tracks, this makes // each channel as high as for a stereo channel - auto tracks = mContext.GetProject()->GetTracks(); + auto tracks = mContext.project.GetTracks(); for (auto t : tracks->Leaders()) { auto channels = TrackList::Channels(t); auto nChannels = channels.size(); @@ -716,15 +716,15 @@ void ScreenFrame::SizeTracks(int h) for (auto channel : channels) channel->SetHeight(height); } - mContext.GetProject()->RedrawProject(); + mContext.project.RedrawProject(); } void ScreenFrame::OnShortTracks(wxCommandEvent & WXUNUSED(event)) { - for (auto t : mContext.GetProject()->GetTracks()->Any()) + for (auto t : mContext.project.GetTracks()->Any()) t->SetHeight(t->GetMinimizedHeight()); - mContext.GetProject()->RedrawProject(); + mContext.project.RedrawProject(); } void ScreenFrame::OnMedTracks(wxCommandEvent & WXUNUSED(event)) diff --git a/src/commands/Command.h b/src/commands/Command.h index f2501e96a..a6f108193 100644 --- a/src/commands/Command.h +++ b/src/commands/Command.h @@ -65,7 +65,7 @@ public: ApplyAndSendResponse(const OldStyleCommandPointer &cmd, std::unique_ptr &target); bool Apply() override; bool Apply(const CommandContext &context) override;// Error to use this. - std::unique_ptr mCtx; + std::unique_ptr mCtx; }; diff --git a/src/commands/CommandContext.cpp b/src/commands/CommandContext.cpp index ad015b526..990e61ad1 100644 --- a/src/commands/CommandContext.cpp +++ b/src/commands/CommandContext.cpp @@ -24,6 +24,8 @@ messaging from a command back to its invoker. #include "CommandContext.h" #include +#include +#include #include #include #include @@ -32,8 +34,6 @@ messaging from a command back to its invoker. #include "CommandTargets.h" #include "CommandDirectory.h" -#include "../Project.h" - CommandContext::CommandContext( AudacityProject &p , const wxEvent *e @@ -92,9 +92,6 @@ void CommandContext::Progress( double d ) const AudacityApp * CommandContext::GetApp() const { return (AudacityApp *) wxTheApp;} -AudacityProject *CommandContext::GetProject() const -{ return GetActiveProject();} - void CommandContext::StartArray() const { if( pOutput ) diff --git a/src/commands/CommandContext.h b/src/commands/CommandContext.h index c80502411..dc53ddac1 100644 --- a/src/commands/CommandContext.h +++ b/src/commands/CommandContext.h @@ -56,6 +56,5 @@ public: int index; CommandParameter parameter; AudacityApp *GetApp() const; - AudacityProject *GetProject() const; }; #endif diff --git a/src/commands/CommandHandler.cpp b/src/commands/CommandHandler.cpp index 0954c4162..365f6bed5 100644 --- a/src/commands/CommandHandler.cpp +++ b/src/commands/CommandHandler.cpp @@ -59,5 +59,5 @@ void CommandHandler::OnReceiveCommand(AppCommandEvent &event) wxUnusedVar(result); // Redraw the project - mCurrentContext->GetProject()->RedrawProject(); + mCurrentContext->project.RedrawProject(); } diff --git a/src/commands/CommandHandler.h b/src/commands/CommandHandler.h index ce042978a..991a6df69 100644 --- a/src/commands/CommandHandler.h +++ b/src/commands/CommandHandler.h @@ -25,7 +25,7 @@ class CommandContext; class CommandHandler { private: - std::unique_ptr mCurrentContext; + std::unique_ptr mCurrentContext; public: CommandHandler(); diff --git a/src/commands/CompareAudioCommand.cpp b/src/commands/CompareAudioCommand.cpp index 7d52c1258..70aaca13c 100644 --- a/src/commands/CompareAudioCommand.cpp +++ b/src/commands/CompareAudioCommand.cpp @@ -107,7 +107,7 @@ inline int min(int a, int b) bool CompareAudioCommand::Apply(const CommandContext & context) { - if (!GetSelection(context, *context.GetProject())) + if (!GetSelection(context, context.project)) { return false; } diff --git a/src/commands/DragCommand.cpp b/src/commands/DragCommand.cpp index d8ecb4867..5d66614e8 100644 --- a/src/commands/DragCommand.cpp +++ b/src/commands/DragCommand.cpp @@ -90,7 +90,7 @@ bool DragCommand::Apply(const CommandContext & context) if( !bHasToY ) mToY = 10; - wxWindow * pWin = context.GetProject(); + wxWindow * pWin = &context.project; wxWindow * pWin1 = nullptr; wxMouseEvent Evt( wxEVT_MOTION ); Evt.m_x = mFromX; diff --git a/src/commands/GetInfoCommand.cpp b/src/commands/GetInfoCommand.cpp index b90b65582..a6609316f 100644 --- a/src/commands/GetInfoCommand.cpp +++ b/src/commands/GetInfoCommand.cpp @@ -121,7 +121,7 @@ bool GetInfoCommand::Apply(const CommandContext &context) if( mFormat == kLisp ) { CommandContext LispyContext( - *(context.GetProject()), + context.project, std::make_unique( *context.pOutput.get() ) ); return ApplyInner( LispyContext ); @@ -130,7 +130,7 @@ bool GetInfoCommand::Apply(const CommandContext &context) if( mFormat == kBrief ) { CommandContext BriefContext( - *(context.GetProject()), + context.project, std::make_unique( *context.pOutput.get() ) ); return ApplyInner( BriefContext ); @@ -159,7 +159,7 @@ bool GetInfoCommand::ApplyInner(const CommandContext &context) bool GetInfoCommand::SendMenus(const CommandContext &context) { - wxMenuBar * pBar = context.GetProject()->GetMenuBar(); + wxMenuBar * pBar = context.project.GetMenuBar(); if(!pBar ){ wxLogDebug("No menus"); return false; @@ -418,10 +418,10 @@ wxSpinCtrl * ShuttleGuiGetDefinition::TieSpinCtrl( bool GetInfoCommand::SendPreferences(const CommandContext &context) { context.StartArray(); - GlobalPrefsDialog dialog( context.GetProject() ); + GlobalPrefsDialog dialog( &context.project ); // wxCommandEvent Evt; //dialog.Show(); - wxWindow * pWin = context.GetProject(); + wxWindow * pWin = &context.project; ShuttleGuiGetDefinition S(pWin, *((context.pOutput)->mStatusTarget) ); dialog.ShuttleAll( S ); context.EndArray(); @@ -454,7 +454,7 @@ bool GetInfoCommand::SendCommands(const CommandContext &context, int flags ) bool GetInfoCommand::SendBoxes(const CommandContext &context) { //context.Status("Boxes"); - wxWindow * pWin = context.GetProject(); + wxWindow * pWin = &context.project; context.StartArray(); wxRect R = pWin->GetScreenRect(); @@ -483,11 +483,11 @@ bool GetInfoCommand::SendBoxes(const CommandContext &context) bool GetInfoCommand::SendTracks(const CommandContext & context) { - TrackList *projTracks = context.GetProject()->GetTracks(); + TrackList *projTracks = context.project.GetTracks(); context.StartArray(); for (auto trk : projTracks->Leaders()) { - TrackPanel *panel = context.GetProject()->GetTrackPanel(); + TrackPanel *panel = context.project.GetTrackPanel(); Track * fTrack = panel->GetFocusedTrack(); context.StartStruct(); @@ -530,7 +530,7 @@ bool GetInfoCommand::SendTracks(const CommandContext & context) bool GetInfoCommand::SendClips(const CommandContext &context) { - TrackList *tracks = context.GetProject()->GetTracks(); + TrackList *tracks = context.project.GetTracks(); int i=0; context.StartArray(); for (auto waveTrack : tracks->Leaders()) { @@ -552,7 +552,7 @@ bool GetInfoCommand::SendClips(const CommandContext &context) bool GetInfoCommand::SendEnvelopes(const CommandContext &context) { - TrackList *tracks = context.GetProject()->GetTracks(); + TrackList *tracks = context.project.GetTracks(); int i=0; int j=0; context.StartArray(); @@ -589,7 +589,7 @@ bool GetInfoCommand::SendEnvelopes(const CommandContext &context) bool GetInfoCommand::SendLabels(const CommandContext &context) { - TrackList *tracks = context.GetProject()->GetTracks(); + TrackList *tracks = context.project.GetTracks(); int i=0; context.StartArray(); for (auto t : tracks->Leaders()) { @@ -640,7 +640,7 @@ void GetInfoCommand::ExploreMenu( const CommandContext &context, wxMenu * pMenu, if( !pMenu ) return; - CommandManager * pMan = context.GetProject()->GetCommandManager(); + CommandManager * pMan = context.project.GetCommandManager(); wxMenuItemList list = pMenu->GetMenuItems(); size_t lcnt = list.size(); @@ -714,7 +714,7 @@ void GetInfoCommand::ExploreAdornments( const CommandContext &context, void GetInfoCommand::ExploreTrackPanel( const CommandContext &context, wxPoint P, wxWindow * pWin, int WXUNUSED(Id), int depth ) { - AudacityProject * pProj = context.GetProject(); + AudacityProject * pProj = &context.project; TrackPanel * pTP = pProj->GetTrackPanel(); wxRect trackRect = pWin->GetRect(); diff --git a/src/commands/ImportExportCommands.cpp b/src/commands/ImportExportCommands.cpp index 809c63558..71c33d8f7 100644 --- a/src/commands/ImportExportCommands.cpp +++ b/src/commands/ImportExportCommands.cpp @@ -40,7 +40,7 @@ void ImportCommand::PopulateOrExchange(ShuttleGui & S) } bool ImportCommand::Apply(const CommandContext & context){ - return context.GetProject()->Import(mFileName); + return context.project.Import(mFileName); } @@ -66,8 +66,8 @@ void ExportCommand::PopulateOrExchange(ShuttleGui & S) bool ExportCommand::Apply(const CommandContext & context) { double t0, t1; - t0 = context.GetProject()->mViewInfo.selectedRegion.t0(); - t1 = context.GetProject()->mViewInfo.selectedRegion.t1(); + t0 = context.project.mViewInfo.selectedRegion.t0(); + t1 = context.project.mViewInfo.selectedRegion.t1(); // Find the extension and check it's valid int splitAt = mFileName.Find(wxUniChar('.'), true); @@ -80,7 +80,7 @@ bool ExportCommand::Apply(const CommandContext & context) Exporter exporter; - bool exportSuccess = exporter.Process(context.GetProject(), + bool exportSuccess = exporter.Process(&context.project, std::max(0, mnChannels), extension, mFileName, true, t0, t1); diff --git a/src/commands/OpenSaveCommands.cpp b/src/commands/OpenSaveCommands.cpp index 17c9206d0..beebd54e1 100644 --- a/src/commands/OpenSaveCommands.cpp +++ b/src/commands/OpenSaveCommands.cpp @@ -44,17 +44,17 @@ void OpenProjectCommand::PopulateOrExchange(ShuttleGui & S) bool OpenProjectCommand::Apply(const CommandContext & context){ - auto oldFileName = context.GetProject()->GetFileName(); + auto oldFileName = context.project.GetFileName(); if(mFileName.empty()) { - auto project = context.GetProject(); + auto project = &context.project; AudacityProject::OpenFiles(project); } else { - context.GetProject()->OpenFile(mFileName, mbAddToHistory); + context.project.OpenFile(mFileName, mbAddToHistory); } - const auto &newFileName = context.GetProject()->GetFileName(); + const auto &newFileName = context.project.GetFileName(); // Because Open does not return a success or failure, we have to guess // at this point, based on whether the project file name has @@ -85,7 +85,7 @@ void SaveProjectCommand::PopulateOrExchange(ShuttleGui & S) bool SaveProjectCommand::Apply(const CommandContext &context) { if(mFileName.empty()) - return context.GetProject()->SaveAs(mbCompress); + return context.project.SaveAs(mbCompress); else - return context.GetProject()->SaveAs(mFileName,mbCompress,mbAddToHistory); + return context.project.SaveAs(mFileName,mbCompress,mbAddToHistory); } diff --git a/src/commands/ScreenshotCommand.cpp b/src/commands/ScreenshotCommand.cpp index 24be56367..52187a9bc 100644 --- a/src/commands/ScreenshotCommand.cpp +++ b/src/commands/ScreenshotCommand.cpp @@ -594,7 +594,7 @@ void ScreenshotCommand::CaptureScriptables( void ScreenshotCommand::CaptureCommands( const CommandContext & context, const wxArrayStringEx & Commands ){ - AudacityProject * pProject = context.GetProject(); + AudacityProject * pProject = &context.project; CommandManager * pMan = pProject->GetCommandManager(); wxString Str; // Yucky static variables. Is there a better way? The problem is that we need the @@ -807,16 +807,16 @@ bool ScreenshotCommand::Apply(const CommandContext & context) GetDerivedParams(); //Don't reset the toolbars to a known state. //We will be capturing variations of them. - //context.GetProject()->GetToolManager()->Reset(); + //context.project.GetToolManager()->Reset(); - wxTopLevelWindow *w = GetFrontWindow(context.GetProject()); + wxTopLevelWindow *w = GetFrontWindow(&context.project); if (!w) return false; - TrackPanel *panel = context.GetProject()->GetTrackPanel(); + TrackPanel *panel = context.project.GetTrackPanel(); AdornedRulerPanel *ruler = panel->mRuler; - int nTracks = context.GetProject()->GetTracks()->size(); + int nTracks = context.project.GetTracks()->size(); int x1,y1,x2,y2; w->ClientToScreen(&x1, &y1); @@ -826,47 +826,47 @@ bool ScreenshotCommand::Apply(const CommandContext & context) switch (mCaptureMode) { case kwindow: - return Capture(context, WindowFileName( context.GetProject(), w ) , w, GetWindowRect(w)); + return Capture(context, WindowFileName( &context.project, w ) , w, GetWindowRect(w)); case kfullwindow: case kwindowplus: - return Capture(context, WindowFileName( context.GetProject(), w ) , w, GetFullWindowRect(w)); + return Capture(context, WindowFileName( &context.project, w ) , w, GetFullWindowRect(w)); case kfullscreen: return Capture(context, mFileName, w,GetScreenRect()); case ktoolbars: - return CaptureDock(context, context.GetProject()->GetToolManager()->GetTopDock(), mFileName); + return CaptureDock(context, context.project.GetToolManager()->GetTopDock(), mFileName); case kscriptables: - CaptureScriptables(context, context.GetProject(), mFileName); + CaptureScriptables(context, &context.project, mFileName); break; case keffects: - CaptureEffects(context, context.GetProject(), mFileName); + CaptureEffects(context, &context.project, mFileName); break; case kpreferences: - CapturePreferences(context, context.GetProject(), mFileName); + CapturePreferences(context, &context.project, mFileName); break; case kselectionbar: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), SelectionBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), SelectionBarID, mFileName); case kspectralselection: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), SpectralSelectionBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), SpectralSelectionBarID, mFileName); case ktools: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), ToolsBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), ToolsBarID, mFileName); case ktransport: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), TransportBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), TransportBarID, mFileName); case kmixer: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), MixerBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), MixerBarID, mFileName); case kmeter: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), MeterBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), MeterBarID, mFileName); case krecordmeter: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), RecordMeterBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), RecordMeterBarID, mFileName); case kplaymeter: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), PlayMeterBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), PlayMeterBarID, mFileName); case kedit: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), EditBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), EditBarID, mFileName); case kdevice: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), DeviceBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), DeviceBarID, mFileName); case ktranscription: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), TranscriptionBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), TranscriptionBarID, mFileName); case kscrub: - return CaptureToolbar(context, context.GetProject()->GetToolManager(), ScrubbingBarID, mFileName); + return CaptureToolbar(context, context.project.GetToolManager(), ScrubbingBarID, mFileName); case ktrackpanel: return Capture(context, mFileName, panel, GetPanelRect(panel)); case kruler: @@ -874,9 +874,9 @@ bool ScreenshotCommand::Apply(const CommandContext & context) case ktracks: return Capture(context, mFileName, panel, GetTracksRect(panel)); case kfirsttrack: - return Capture(context, mFileName, panel, GetTrackRect( context.GetProject(), panel, 0 ) ); + return Capture(context, mFileName, panel, GetTrackRect( &context.project, panel, 0 ) ); case ksecondtrack: - return Capture(context, mFileName, panel, GetTrackRect( context.GetProject(), panel, 1 ) ); + return Capture(context, mFileName, panel, GetTrackRect( &context.project, panel, 1 ) ); case ktracksplus: { wxRect r = GetTracksRect(panel); r.SetTop( r.GetTop() - ruler->GetRulerHeight() ); @@ -884,36 +884,36 @@ bool ScreenshotCommand::Apply(const CommandContext & context) return Capture(context, mFileName, panel, r); } case kfirsttrackplus: - { wxRect r = GetTrackRect(context.GetProject(), panel, 0 ); + { wxRect r = GetTrackRect(&context.project, panel, 0 ); r.SetTop( r.GetTop() - ruler->GetRulerHeight() ); r.SetHeight( r.GetHeight() + ruler->GetRulerHeight() ); return Capture(context, mFileName, panel, r ); } case kfirsttwotracks: - { wxRect r = GetTrackRect( context.GetProject(), panel, 0 ); - r = r.Union( GetTrackRect( context.GetProject(), panel, 1 )); + { wxRect r = GetTrackRect( &context.project, panel, 0 ); + r = r.Union( GetTrackRect( &context.project, panel, 1 )); return Capture(context, mFileName, panel, r ); } case kfirstthreetracks: - { wxRect r = GetTrackRect( context.GetProject(), panel, 0 ); - r = r.Union( GetTrackRect( context.GetProject(), panel, 2 )); + { wxRect r = GetTrackRect( &context.project, panel, 0 ); + r = r.Union( GetTrackRect( &context.project, panel, 2 )); return Capture(context, mFileName, panel, r ); } case kfirstfourtracks: - { wxRect r = GetTrackRect( context.GetProject(), panel, 0 ); - r = r.Union( GetTrackRect( context.GetProject(), panel, 3 )); + { wxRect r = GetTrackRect( &context.project, panel, 0 ); + r = r.Union( GetTrackRect( &context.project, panel, 3 )); return Capture(context, mFileName, panel, r ); } case kalltracks: - { wxRect r = GetTrackRect( context.GetProject(), panel, 0 ); - r = r.Union( GetTrackRect( context.GetProject(), panel, nTracks-1 )); + { wxRect r = GetTrackRect( &context.project, panel, 0 ); + r = r.Union( GetTrackRect( &context.project, panel, nTracks-1 )); return Capture(context, mFileName, panel, r ); } case kalltracksplus: - { wxRect r = GetTrackRect( context.GetProject(), panel, 0 ); + { wxRect r = GetTrackRect( &context.project, panel, 0 ); r.SetTop( r.GetTop() - ruler->GetRulerHeight() ); r.SetHeight( r.GetHeight() + ruler->GetRulerHeight() ); - r = r.Union( GetTrackRect( context.GetProject(), panel, nTracks-1 )); + r = r.Union( GetTrackRect( &context.project, panel, nTracks-1 )); return Capture(context, mFileName, panel, r ); } default: diff --git a/src/commands/SelectCommand.cpp b/src/commands/SelectCommand.cpp index 0277300a2..ba46dae96 100644 --- a/src/commands/SelectCommand.cpp +++ b/src/commands/SelectCommand.cpp @@ -85,7 +85,7 @@ void SelectTimeCommand::PopulateOrExchange(ShuttleGui & S) bool SelectTimeCommand::Apply(const CommandContext & context){ // Many commands need focus on track panel. // No harm in setting it with a scripted select. - context.GetProject()->GetTrackPanel()->SetFocus(); + context.project.GetTrackPanel()->SetFocus(); if( !bHasT0 && !bHasT1 ) return true; @@ -97,7 +97,7 @@ bool SelectTimeCommand::Apply(const CommandContext & context){ if( !bHasRelativeSpec ) mRelativeTo = 0; - AudacityProject * p = context.GetProject(); + AudacityProject * p = &context.project; double end = p->GetTracks()->GetEndTime(); double t0; double t1; @@ -164,7 +164,7 @@ bool SelectFrequenciesCommand::Apply(const CommandContext & context){ if( !bHasBottom ) mBottom = 0.0; - context.GetProject()->SSBL_ModifySpectralSelection( + context.project.SSBL_ModifySpectralSelection( mBottom, mTop, false);// false for not done. return true; } @@ -214,7 +214,7 @@ bool SelectTracksCommand::Apply(const CommandContext &context) // Used to invalidate cached selection and tracks. Effect::IncEffectCounter(); int index = 0; - TrackList *tracks = context.GetProject()->GetTracks(); + TrackList *tracks = context.project.GetTracks(); // Defaults if no value... if( !bHasNumTracks ) diff --git a/src/commands/SetLabelCommand.cpp b/src/commands/SetLabelCommand.cpp index ab948101f..b9601c8d4 100644 --- a/src/commands/SetLabelCommand.cpp +++ b/src/commands/SetLabelCommand.cpp @@ -66,8 +66,8 @@ bool SetLabelCommand::Apply(const CommandContext & context) // this code could be put in subroutines/reduced. //wxString mode = GetString(wxT("Type")); - AudacityProject * p = context.GetProject(); - TrackList *tracks = context.GetProject()->GetTracks(); + AudacityProject * p = &context.project; + TrackList *tracks = context.project.GetTracks(); LabelStruct * pLabel = NULL; int i=0; int nn=0; diff --git a/src/commands/SetProjectCommand.cpp b/src/commands/SetProjectCommand.cpp index 8c6266fb9..1d9c62dd9 100644 --- a/src/commands/SetProjectCommand.cpp +++ b/src/commands/SetProjectCommand.cpp @@ -66,7 +66,7 @@ void SetProjectCommand::PopulateOrExchange(ShuttleGui & S) bool SetProjectCommand::Apply(const CommandContext & context) { - AudacityProject * pProj = context.GetProject(); + AudacityProject * pProj = &context.project; if( bHasName ) pProj->SetLabel(mName); diff --git a/src/commands/SetTrackInfoCommand.cpp b/src/commands/SetTrackInfoCommand.cpp index e7c690754..4b23c1b9c 100644 --- a/src/commands/SetTrackInfoCommand.cpp +++ b/src/commands/SetTrackInfoCommand.cpp @@ -94,7 +94,7 @@ bool SetTrackBase::Apply(const CommandContext & context ) { long i = 0;// track counter long j = 0;// channel counter - auto tracks = context.GetProject()->GetTracks(); + auto tracks = context.project.GetTracks(); for ( auto t : tracks->Leaders() ) { auto channels = TrackList::Channels(t); @@ -163,7 +163,7 @@ bool SetTrackStatusCommand::ApplyInner(const CommandContext & context, Track * t if( !bIsSecondChannel ){ if( bHasFocused ) { - TrackPanel *panel = context.GetProject()->GetTrackPanel(); + TrackPanel *panel = context.project.GetTrackPanel(); if( bFocused) panel->SetFocusedTrack( t ); else if( t== panel->GetFocusedTrack() ) From d81ca9964344c9f42d57c3ed60386f5a58880224 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 11 May 2019 15:48:39 -0400 Subject: [PATCH 4/8] CommandContext.cpp has fewer dependencies... ... freeing it (alone) from dependency cycles --- src/commands/CommandContext.cpp | 2 -- src/commands/CommandContext.h | 2 +- src/commands/CommandHandler.cpp | 1 + src/effects/EffectManager.cpp | 1 + 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/CommandContext.cpp b/src/commands/CommandContext.cpp index 990e61ad1..d979e911a 100644 --- a/src/commands/CommandContext.cpp +++ b/src/commands/CommandContext.cpp @@ -30,9 +30,7 @@ messaging from a command back to its invoker. #include #include -#include "CommandBuilder.h" #include "CommandTargets.h" -#include "CommandDirectory.h" CommandContext::CommandContext( AudacityProject &p diff --git a/src/commands/CommandContext.h b/src/commands/CommandContext.h index dc53ddac1..38f511347 100644 --- a/src/commands/CommandContext.h +++ b/src/commands/CommandContext.h @@ -11,8 +11,8 @@ #ifndef __AUDACITY_COMMAND_CONTEXT__ #define __AUDACITY_COMMAND_CONTEXT__ +#include #include "audacity/Types.h" -#include "Command.h" class AudacityProject; class AudacityApp; diff --git a/src/commands/CommandHandler.cpp b/src/commands/CommandHandler.cpp index 365f6bed5..70cff9317 100644 --- a/src/commands/CommandHandler.cpp +++ b/src/commands/CommandHandler.cpp @@ -24,6 +24,7 @@ #include "AppCommandEvent.h" #include "ScriptCommandRelay.h" #include "../commands/CommandContext.h" +#include "../commands/Command.h" CommandHandler::CommandHandler() : mCurrentContext(std::make_unique diff --git a/src/effects/EffectManager.cpp b/src/effects/EffectManager.cpp index dd9220767..a0dc02879 100644 --- a/src/effects/EffectManager.cpp +++ b/src/effects/EffectManager.cpp @@ -35,6 +35,7 @@ effects. #include "../ShuttleGetDefinition.h" #include "../commands/CommandContext.h" +#include "../commands/Command.h" #include "../PluginManager.h" From 13713aab67b13061d14cf4ee4b96348c0974a6c6 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 11 May 2019 18:10:21 -0400 Subject: [PATCH 5/8] Remove nullary overload of AudacityCommand::Apply... ... which by default used GetActiveProject(); do that call instead at a higher level; so that AudacityCommand.cpp does not depend on Project.cpp. We lose the override of that for CompareAudioCommand which just did nothing. But in fact this overload of the base class method could only be used by EffectUIHost constructed from a command, which never happened: it was only ever constructed from effects. This frees two files from dependency cycles --- src/commands/AudacityCommand.cpp | 7 ------- src/commands/AudacityCommand.h | 3 +-- src/commands/CompareAudioCommand.cpp | 4 ---- src/commands/CompareAudioCommand.h | 1 - src/effects/Effect.cpp | 4 +++- 5 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/commands/AudacityCommand.cpp b/src/commands/AudacityCommand.cpp index 7ed08d232..89e6dbfcf 100644 --- a/src/commands/AudacityCommand.cpp +++ b/src/commands/AudacityCommand.cpp @@ -37,7 +37,6 @@ ShuttleGui. #include "audacity/ConfigInterface.h" -#include "../Project.h" #include "../Shuttle.h" #include "../ShuttleGui.h" #include "../widgets/ProgressDialog.h" @@ -87,12 +86,6 @@ VendorSymbol AudacityCommand::GetVendor(){ return XO("Audacity");} wxString AudacityCommand::GetVersion(){ return AUDACITY_VERSION_STRING;} -bool AudacityCommand::Apply() { - AudacityProject * pProj = GetActiveProject(); - const CommandContext context( *pProj ); - return Apply( context ); -}; - bool AudacityCommand::Init(){ if( !mNeedsInit ) return true; diff --git a/src/commands/AudacityCommand.h b/src/commands/AudacityCommand.h index d454c337d..e26c0fb06 100644 --- a/src/commands/AudacityCommand.h +++ b/src/commands/AudacityCommand.h @@ -69,8 +69,7 @@ class AUDACITY_DLL_API AudacityCommand /* not final */ : public wxEvtHandler, virtual bool IsBatchProcessing(){ return mIsBatch;} virtual void SetBatchProcessing(bool start){ mIsBatch = start;}; - virtual bool Apply(const CommandContext & WXUNUSED(context) ) {return false;}; - virtual bool Apply(); // redirects to the command context version. + virtual bool Apply(const CommandContext & WXUNUSED(context) ) {return false;}; bool ShowInterface(wxWindow *parent, bool forceModal = false); virtual void SetHostUI(EffectUIHostInterface * WXUNUSED(host)){;}; diff --git a/src/commands/CompareAudioCommand.cpp b/src/commands/CompareAudioCommand.cpp index 70aaca13c..c3502b85b 100644 --- a/src/commands/CompareAudioCommand.cpp +++ b/src/commands/CompareAudioCommand.cpp @@ -46,10 +46,6 @@ bool CompareAudioCommand::DefineParams( ShuttleParams & S ){ return true; } -bool CompareAudioCommand::Apply(){ - return true; -} - void CompareAudioCommand::PopulateOrExchange(ShuttleGui & S) { S.AddSpace(0, 5); diff --git a/src/commands/CompareAudioCommand.h b/src/commands/CompareAudioCommand.h index 01a350181..de51d88fd 100644 --- a/src/commands/CompareAudioCommand.h +++ b/src/commands/CompareAudioCommand.h @@ -33,7 +33,6 @@ public: wxString GetDescription() override {return _("Compares a range on two tracks.");}; bool DefineParams( ShuttleParams & S ) override; void PopulateOrExchange(ShuttleGui & S) override; - bool Apply() override; // AudacityCommand overrides wxString ManualPage() override {return wxT("Extra_Menu:_Scriptables_II#compare_Audio");}; diff --git a/src/effects/Effect.cpp b/src/effects/Effect.cpp index 7d70cf45b..bd322748f 100644 --- a/src/effects/Effect.cpp +++ b/src/effects/Effect.cpp @@ -3322,7 +3322,9 @@ void EffectUIHost::OnApply(wxCommandEvent & evt) if( mEffect ) mEffect->Apply(); if( mCommand ) - mCommand->Apply(); + // PRL: I don't like the global and would rather pass *mProject! + // But I am preserving old behavior + mCommand->Apply( CommandContext{ *GetActiveProject() } ); } void EffectUIHost::DoCancel() From 016e1949ae0f89ee87c4c1ae7d4f6c25d5e36649 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 18 May 2019 13:20:19 -0400 Subject: [PATCH 6/8] CommandDirectory.cpp has fewer dependencies... ... This involved populating it with a new registration system. BatchEvalCommand, HelpCommand, MessageCommand escape from cycles and move higher in the dependency graph, and CommandDirectory moves lower. --- src/commands/BatchEvalCommand.cpp | 5 +++++ src/commands/CommandBuilder.cpp | 2 +- src/commands/CommandDirectory.cpp | 25 ++++++++++++++----------- src/commands/CommandDirectory.h | 14 ++++++++++---- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/commands/BatchEvalCommand.cpp b/src/commands/BatchEvalCommand.cpp index 8b9b86a8f..c486a07cf 100644 --- a/src/commands/BatchEvalCommand.cpp +++ b/src/commands/BatchEvalCommand.cpp @@ -17,6 +17,11 @@ #include "BatchEvalCommand.h" #include "CommandContext.h" +#include "CommandDirectory.h" + +static CommandDirectory::RegisterType sRegisterType{ + std::make_unique() +}; ComponentInterfaceSymbol BatchEvalCommandType::BuildName() { diff --git a/src/commands/CommandBuilder.cpp b/src/commands/CommandBuilder.cpp index 5b2da4cb1..44f9d9d2a 100644 --- a/src/commands/CommandBuilder.cpp +++ b/src/commands/CommandBuilder.cpp @@ -25,7 +25,7 @@ system by constructing BatchCommandEval objects. #include "CommandBuilder.h" #include "CommandDirectory.h" -#include "BatchEvalCommand.h" +#include "Command.h" #include "ScriptCommandRelay.h" #include "CommandContext.h" #include "CommandTargets.h" diff --git a/src/commands/CommandDirectory.cpp b/src/commands/CommandDirectory.cpp index 1fb58f6de..ba75042a4 100644 --- a/src/commands/CommandDirectory.cpp +++ b/src/commands/CommandDirectory.cpp @@ -17,10 +17,6 @@ functions to look up a command by name. #include "../Audacity.h" #include "CommandDirectory.h" -#include "HelpCommand.h" -#include "MessageCommand.h" -#include "BatchEvalCommand.h" - std::unique_ptr CommandDirectory::mInstance; CommandDirectory::CommandDirectory() @@ -28,7 +24,8 @@ CommandDirectory::CommandDirectory() // Create the command map. // First we have commands which return information //AddCommand(std::make_unique()); - AddCommand(std::make_unique()); + +// AddCommand(std::make_unique()); // Legacy adapter commands that previously was needed to @@ -68,24 +65,30 @@ CommandDirectory::~CommandDirectory() OldStyleCommandType *CommandDirectory::LookUp(const wxString &cmdName) const { - CommandMap::const_iterator iter = mCmdMap.find(cmdName); - if (iter == mCmdMap.end()) + auto iter = sCmdMap().find(cmdName); + if (iter == sCmdMap().end()) { - return NULL; + return nullptr; } return iter->second.get(); } -void CommandDirectory::AddCommand(std::unique_ptr &&type) +CommandMap &CommandDirectory::sCmdMap() +{ + static CommandMap theMap; + return theMap; +} + +void CommandDirectory::AddCommand(std::unique_ptr type) { wxASSERT(type != NULL); // Internal string is shown but only in assertion message auto cmdName = type->GetSymbol().Internal(); - wxASSERT_MSG(mCmdMap.find(cmdName) == mCmdMap.end() + wxASSERT_MSG(sCmdMap().find(cmdName) == sCmdMap().end() , wxT("A command named ") + cmdName + wxT(" already exists.")); - mCmdMap[cmdName] = std::move(type); + sCmdMap()[cmdName] = std::move(type); } CommandDirectory *CommandDirectory::Get() diff --git a/src/commands/CommandDirectory.h b/src/commands/CommandDirectory.h index 2122f4bed..3635871ee 100644 --- a/src/commands/CommandDirectory.h +++ b/src/commands/CommandDirectory.h @@ -31,8 +31,17 @@ class CommandDirectory { private: static std::unique_ptr mInstance; - CommandMap mCmdMap; + static CommandMap &sCmdMap(); + + static void AddCommand(std::unique_ptr type); public: + /// Register a type of command with the directory with a statically + /// constructed instance of this class. + struct RegisterType{ + RegisterType( std::unique_ptr type ) + { AddCommand( std::move( type ) ); } + }; + ~CommandDirectory(); /// If a command with the given name has been registered in the directory, @@ -40,9 +49,6 @@ public: /// Otherwise return NULL. OldStyleCommandType *LookUp(const wxString &cmdName) const; - /// Register a type of command with the directory. - void AddCommand(std::unique_ptr &&type); - /// Get a pointer to the singleton instance static CommandDirectory *Get(); From ae0cd061c6472ba755d43f9d58deb73b224b32ad Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sun, 12 May 2019 08:54:03 -0400 Subject: [PATCH 7/8] ScriptCommandRelay.cpp doesn't depend on AudacityProject.cpp ... ... This doesn't break any dependency cycles yet. --- src/commands/ScriptCommandRelay.cpp | 18 ++++++++++-------- src/commands/ScriptCommandRelay.h | 5 +++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/commands/ScriptCommandRelay.cpp b/src/commands/ScriptCommandRelay.cpp index 384fee65a..a0d57426b 100644 --- a/src/commands/ScriptCommandRelay.cpp +++ b/src/commands/ScriptCommandRelay.cpp @@ -24,8 +24,8 @@ code out of ModuleManager. #include "CommandTargets.h" #include "CommandBuilder.h" #include "AppCommandEvent.h" -#include "../Project.h" #include +#include #include // Declare static class members @@ -52,13 +52,16 @@ void ScriptCommandRelay::Run() } /// Send a command to a project, to be applied in that context. -void ScriptCommandRelay::PostCommand(AudacityProject *project, const OldStyleCommandPointer &cmd) +void ScriptCommandRelay::PostCommand( + wxWindow *pWindow, const OldStyleCommandPointer &cmd) { - wxASSERT(project != NULL); + wxASSERT( pWindow ); wxASSERT(cmd != NULL); - AppCommandEvent ev; - ev.SetCommand(cmd); - project->GetEventHandler()->AddPendingEvent(ev); + if ( pWindow ) { + AppCommandEvent ev; + ev.SetCommand(cmd); + pWindow->GetEventHandler()->AddPendingEvent(ev); + } } /// This is the function which actually obeys one command. Rather than applying @@ -71,9 +74,8 @@ int ExecCommand(wxString *pIn, wxString *pOut) CommandBuilder builder(*pIn); if (builder.WasValid()) { - AudacityProject *project = GetActiveProject(); OldStyleCommandPointer cmd = builder.GetCommand(); - ScriptCommandRelay::PostCommand(project, cmd); + ScriptCommandRelay::PostCommand(wxTheApp->GetTopWindow(), cmd); *pOut = wxEmptyString; } diff --git a/src/commands/ScriptCommandRelay.h b/src/commands/ScriptCommandRelay.h index e83377629..999b0fdac 100644 --- a/src/commands/ScriptCommandRelay.h +++ b/src/commands/ScriptCommandRelay.h @@ -20,11 +20,11 @@ #include "../MemoryX.h" +class wxWindow; class CommandHandler; class ResponseQueue; class Response; class ResponseQueueTarget; -class AudacityProject; class OldStyleCommand; using OldStyleCommandPointer = std::shared_ptr; class wxString; @@ -50,7 +50,8 @@ class ScriptCommandRelay static void SetCommandHandler(CommandHandler &ch); static void Run(); - static void PostCommand(AudacityProject *project, const OldStyleCommandPointer &cmd); + static void PostCommand( + wxWindow *pWindow, const OldStyleCommandPointer &cmd); static void SendResponse(const wxString &response); static Response ReceiveResponse(); static std::shared_ptr GetResponseTarget(); From 74c53efadc16348e5359bea672e87e2eb933d534 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Sat, 18 May 2019 13:29:54 -0400 Subject: [PATCH 8/8] Command.cpp does not depend on Project.cpp... ... To do that, hoist the call to GetActiveProject() into the factory that makes BatchEvalCommand Also remove unnecessary inclusion of CommandBuilder.h. This frees Command.cpp from dependency cycles; CommandBuilder and ScriptCommandRelay are now in a small cycle of only two. --- src/commands/BatchEvalCommand.cpp | 3 ++- src/commands/BatchEvalCommand.h | 6 ++++-- src/commands/Command.cpp | 18 +++++++++++------- src/commands/Command.h | 11 +++++++---- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/commands/BatchEvalCommand.cpp b/src/commands/BatchEvalCommand.cpp index c486a07cf..2718078a9 100644 --- a/src/commands/BatchEvalCommand.cpp +++ b/src/commands/BatchEvalCommand.cpp @@ -18,6 +18,7 @@ #include "CommandContext.h" #include "CommandDirectory.h" +#include "../Project.h" static CommandDirectory::RegisterType sRegisterType{ std::make_unique() @@ -40,7 +41,7 @@ void BatchEvalCommandType::BuildSignature(CommandSignature &signature) OldStyleCommandPointer BatchEvalCommandType::Create(std::unique_ptr && WXUNUSED(target)) { - return std::make_shared(*this); + return std::make_shared(*GetActiveProject(), *this); } bool BatchEvalCommand::Apply(const CommandContext & context) diff --git a/src/commands/BatchEvalCommand.h b/src/commands/BatchEvalCommand.h index 7292948a2..762a1fabc 100644 --- a/src/commands/BatchEvalCommand.h +++ b/src/commands/BatchEvalCommand.h @@ -26,6 +26,8 @@ to that system. #include "CommandType.h" #include "../BatchCommands.h" +class AudacityProject; + class BatchEvalCommandType final : public OldStyleCommandType { public: @@ -37,8 +39,8 @@ public: class BatchEvalCommand final : public CommandImplementation { public: - BatchEvalCommand(OldStyleCommandType &type) - : CommandImplementation(type) + BatchEvalCommand(AudacityProject &project, OldStyleCommandType &type) + : CommandImplementation(project, type) { } virtual ~BatchEvalCommand(); diff --git a/src/commands/Command.cpp b/src/commands/Command.cpp index 99724b3cd..0df8cfa24 100644 --- a/src/commands/Command.cpp +++ b/src/commands/Command.cpp @@ -79,16 +79,17 @@ classes derived from it. #include "Command.h" #include +#include #include #include #include -#include "CommandBuilder.h" #include "CommandTargets.h" #include "CommandDirectory.h" #include "CommandContext.h" -#include "../Project.h" + +#include "../AudacityException.h" @@ -119,9 +120,10 @@ bool DecoratedCommand::SetParameter(const wxString ¶mName, return mCommand->SetParameter(paramName, paramValue); } -ApplyAndSendResponse::ApplyAndSendResponse(const OldStyleCommandPointer &cmd, std::unique_ptr &target) +ApplyAndSendResponse::ApplyAndSendResponse( + const OldStyleCommandPointer &cmd, std::unique_ptr &target) : DecoratedCommand(cmd), - mCtx( std::make_unique( *GetActiveProject(), std::move(target) ) ) + mCtx( std::make_unique( cmd->mProject, std::move(target) ) ) { } @@ -167,8 +169,10 @@ bool ApplyAndSendResponse::Apply() return result; } -CommandImplementation::CommandImplementation(OldStyleCommandType &type) -: mType(type), +CommandImplementation::CommandImplementation( + AudacityProject &project, OldStyleCommandType &type) +: OldStyleCommand{ project }, + mType(type), mParams(type.GetSignature().GetDefaults()), mSetParams() { @@ -257,7 +261,7 @@ CommandSignature &CommandImplementation::GetSignature() bool CommandImplementation::SetParameter(const wxString ¶mName, const wxVariant ¶mValue) { wxASSERT(!paramValue.IsType(wxT("null"))); - CommandContext context( * GetActiveProject()); + CommandContext context( mProject ); ParamValueMap::iterator iter = mParams.find(paramName); if (iter == mParams.end()) { diff --git a/src/commands/Command.h b/src/commands/Command.h index a6f108193..9bd64660c 100644 --- a/src/commands/Command.h +++ b/src/commands/Command.h @@ -28,7 +28,9 @@ class CommandOutputTargets; class OldStyleCommand /* not final */ { public: - OldStyleCommand() {}; + AudacityProject &mProject; + + OldStyleCommand(AudacityProject &project) : mProject{ project } {}; virtual ~OldStyleCommand() { } virtual ComponentInterfaceSymbol GetSymbol() = 0; virtual CommandSignature &GetSignature() = 0; @@ -47,7 +49,7 @@ protected: OldStyleCommandPointer mCommand; public: DecoratedCommand(const OldStyleCommandPointer &cmd) - : mCommand(cmd) + : OldStyleCommand{ cmd->mProject }, mCommand(cmd) { wxASSERT(cmd != NULL); } @@ -62,7 +64,8 @@ public: class ApplyAndSendResponse : public DecoratedCommand { public: - ApplyAndSendResponse(const OldStyleCommandPointer &cmd, std::unique_ptr &target); + ApplyAndSendResponse( + const OldStyleCommandPointer &cmd, std::unique_ptr &target); bool Apply() override; bool Apply(const CommandContext &context) override;// Error to use this. std::unique_ptr mCtx; @@ -95,7 +98,7 @@ protected: public: /// Constructor should not be called directly; only by a factory which /// ensures name and params are set appropriately for the command. - CommandImplementation(OldStyleCommandType &type); + CommandImplementation(AudacityProject &project, OldStyleCommandType &type); virtual ~CommandImplementation();