diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index c22835090..3c6272465 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -810,9 +810,8 @@ void AudacityApp::MacNewFile() // This method should only be used on the Mac platform // when no project windows are open. - if (AllProjects{}.empty()) { - CreateNewAudacityProject(); - } + if (AllProjects{}.empty()) + (void) ProjectManager::New(); } #endif //__WXMAC__ @@ -880,7 +879,7 @@ bool AudacityApp::MRUOpen(const FilePath &fullPathStr) { // Test here even though AudacityProject::OpenFile() also now checks, because // that method does not return the bad result. // That itself may be a FIXME. - if (AudacityProject::IsAlreadyOpen(fullPathStr)) + if (ProjectManager::IsAlreadyOpen(fullPathStr)) return false; // DMM: If the project is dirty, that means it's been touched at @@ -893,12 +892,15 @@ bool AudacityApp::MRUOpen(const FilePath &fullPathStr) { // there are no tracks, but there's an Undo history, etc, then // bad things can happen, including data files moving to the NEW // project directory, etc. - if (proj && (proj->GetDirty() || !TrackList::Get( *proj ).empty())) + if (proj && ( + ProjectManager::Get( *proj ).GetDirty() || + !TrackList::Get( *proj ).empty() + ) ) proj = nullptr; // This project is clean; it's never been touched. Therefore // all relevant member variables are in their initial state, // and it's okay to open a NEW project inside this window. - AudacityProject::OpenProject( proj, fullPathStr ); + ( void ) ProjectManager::OpenProject( proj, fullPathStr ); } else { // File doesn't exist - remove file from history @@ -936,7 +938,7 @@ void AudacityApp::OnMRUFile(wxCommandEvent& event) { // PRL: Don't call SafeMRUOpen // -- if open fails for some exceptional reason of resource exhaustion that // the user can correct, leave the file in history. - if (!AudacityProject::IsAlreadyOpen(fullPathStr) && !MRUOpen(fullPathStr)) + if (!ProjectManager::IsAlreadyOpen(fullPathStr) && !MRUOpen(fullPathStr)) history.RemoveFileFromHistory(n); } @@ -1073,7 +1075,7 @@ bool AudacityApp::OnExceptionInMainLoop() // Restore the state of the project to what it was before the // failed operation if (pProject) { - pProject->RollbackState(); + ProjectManager::Get( *pProject ).RollbackState(); // Forget pending changes in the TrackList TrackList::Get( *pProject ).ClearPendingTracks(); @@ -1511,7 +1513,7 @@ bool AudacityApp::OnInit() // Root cause is problem with wxSplashScreen and other dialogs co-existing, that // seemed to arrive with wx3. { - project = CreateNewAudacityProject(); + project = ProjectManager::New(); mCmdHandler->SetProject(project); wxWindow * pWnd = MakeHijackPanel(); if (pWnd) @@ -2081,7 +2083,7 @@ void AudacityApp::OnMenuNew(wxCommandEvent & event) // all platforms. if(AllProjects{}.empty()) - CreateNewAudacityProject(); + (void) ProjectManager::New(); else event.Skip(); } @@ -2097,7 +2099,7 @@ void AudacityApp::OnMenuOpen(wxCommandEvent & event) if(AllProjects{}.empty()) - AudacityProject::OpenFiles(NULL); + ProjectManager::OpenFiles(NULL); else event.Skip(); diff --git a/src/AutoRecovery.cpp b/src/AutoRecovery.cpp index 6fd32beee..129c69cb0 100644 --- a/src/AutoRecovery.cpp +++ b/src/AutoRecovery.cpp @@ -227,7 +227,7 @@ static bool RecoverAllProjects(AudacityProject** pproj) // Open project. When an auto-save file has been opened successfully, // the opened auto-save file is automatically deleted and a NEW one // is created. - AudacityProject::OpenProject( proj, files[i], false ); + (void) ProjectManager::OpenProject( proj, files[i], false ); } return true; diff --git a/src/BatchCommands.cpp b/src/BatchCommands.cpp index f6b7d342e..44549ffda 100644 --- a/src/BatchCommands.cpp +++ b/src/BatchCommands.cpp @@ -842,7 +842,7 @@ bool MacroCommands::ApplyMacro( if (!res) { if(proj) { // Macro failed or was cancelled; revert to the previous state - proj->RollbackState(); + ProjectManager::Get( *proj ).RollbackState(); } } } ); @@ -888,7 +888,7 @@ bool MacroCommands::ApplyMacro( if (!proj) return false; if( MacroReentryCount <= 1 ) - proj->PushState(longDesc, shortDesc); + ProjectManager::Get( *proj ).PushState(longDesc, shortDesc); return true; } diff --git a/src/BatchProcessDialog.cpp b/src/BatchProcessDialog.cpp index a56b5712d..8fc7266a5 100644 --- a/src/BatchProcessDialog.cpp +++ b/src/BatchProcessDialog.cpp @@ -461,7 +461,7 @@ void ApplyMacroDialog::OnApplyToFiles(wxCommandEvent & WXUNUSED(event)) fileList->EnsureVisible(i); auto success = GuardedCall< bool >( [&] { - project->Import(files[i]); + ProjectManager::Get( *project ).Import(files[i]); ProjectWindow::Get( *project ).ZoomAfterImport(nullptr); SelectActions::DoSelectAll(*project); if (!mMacroCommands.ApplyMacro(mCatalog)) @@ -476,7 +476,7 @@ void ApplyMacroDialog::OnApplyToFiles(wxCommandEvent & WXUNUSED(event)) if (!success) break; - project->ResetProjectToEmpty(); + ProjectManager::Get( *project ).ResetProjectToEmpty(); } Show(); diff --git a/src/HistoryWindow.cpp b/src/HistoryWindow.cpp index 1ba5eb27c..10557adc5 100644 --- a/src/HistoryWindow.cpp +++ b/src/HistoryWindow.cpp @@ -254,7 +254,7 @@ void HistoryWindow::OnDiscard(wxCommandEvent & WXUNUSED(event)) mSelected -= i; mManager->RemoveStates(i); - mProject->SetStateTo(mSelected + 1); + ProjectManager::Get( *mProject ).SetStateTo(mSelected + 1); while(--i >= 0) mList->DeleteItem(i); @@ -292,7 +292,7 @@ void HistoryWindow::OnItemSelected(wxListEvent &event) // entry. Doing so can cause unnecessary delays upon initial load or while // clicking the same entry over and over. if (selected != mSelected) { - mProject->SetStateTo(selected + 1); + ProjectManager::Get( *mProject ).SetStateTo(selected + 1); } mSelected = selected; diff --git a/src/LabelTrack.cpp b/src/LabelTrack.cpp index 709afc905..6ce4344e6 100644 --- a/src/LabelTrack.cpp +++ b/src/LabelTrack.cpp @@ -1813,7 +1813,7 @@ unsigned LabelTrack::KeyDown(wxKeyEvent & event, ViewInfo &viewInfo, wxWindow *W // Pass keystroke to labeltrack's handler and add to history if any // updates were done if (OnKeyDown(viewInfo.selectedRegion, event)) { - pProj->PushState(_("Modified Label"), + ProjectManager::Get( *pProj ).PushState(_("Modified Label"), _("Label Edit"), UndoPush::CONSOLIDATE); } @@ -1845,7 +1845,7 @@ unsigned LabelTrack::Char(wxKeyEvent & event, ViewInfo &viewInfo, wxWindow *) AudacityProject *const pProj = GetActiveProject(); if (OnChar(viewInfo.selectedRegion, event)) - pProj->PushState(_("Modified Label"), + ProjectManager::Get( *pProj ).PushState(_("Modified Label"), _("Label Edit"), UndoPush::CONSOLIDATE); @@ -2130,13 +2130,13 @@ bool LabelTrack::OnChar(SelectedRegion &WXUNUSED(newSel), wxKeyEvent & event) } SetSelected(true); AddLabel(selectedRegion, title, -2); - p->PushState(_("Added label"), _("Label")); + ProjectManager::Get( *p ).PushState(_("Added label"), _("Label")); return false; } else { SetSelected(true); AddLabel(selectedRegion); - p->PushState(_("Added label"), _("Label")); + ProjectManager::Get( *p ).PushState(_("Added label"), _("Label")); } } @@ -2230,7 +2230,7 @@ void LabelTrack::OnContextMenu(wxCommandEvent & evt) case OnCutSelectedTextID: if (CutSelectedText()) { - p->PushState(_("Modified Label"), + ProjectManager::Get( *p ).PushState(_("Modified Label"), _("Label Edit"), UndoPush::CONSOLIDATE); } @@ -2245,7 +2245,7 @@ void LabelTrack::OnContextMenu(wxCommandEvent & evt) case OnPasteSelectedTextID: if (PasteSelectedText(selectedRegion.t0(), selectedRegion.t1())) { - p->PushState(_("Modified Label"), + ProjectManager::Get( *p ).PushState(_("Modified Label"), _("Label Edit"), UndoPush::CONSOLIDATE); } @@ -2257,7 +2257,7 @@ void LabelTrack::OnContextMenu(wxCommandEvent & evt) if (ndx != -1) { DeleteLabel(ndx); - p->PushState(_("Deleted Label"), + ProjectManager::Get( *p ).PushState(_("Deleted Label"), _("Label Edit"), UndoPush::CONSOLIDATE); } @@ -3104,7 +3104,8 @@ void LabelTrack::DoEditLabels #endif if (dlg.ShowModal() == wxID_OK) { - project.PushState(_("Edited labels"), _("Label")); + ProjectManager::Get( project ) + .PushState(_("Edited labels"), _("Label")); window.RedrawProject(); } } diff --git a/src/Menus.cpp b/src/Menus.cpp index 36488d641..f38ff99eb 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -327,7 +327,8 @@ void MenuManager::ModifyUndoMenuItems(AudacityProject &project) commandManager.Modify(wxT("Undo"), wxString::Format(_("&Undo %s"), desc)); - commandManager.Enable(wxT("Undo"), project.UndoAvailable()); + commandManager.Enable(wxT("Undo"), + ProjectManager::Get( project ).UndoAvailable()); } else { commandManager.Modify(wxT("Undo"), @@ -339,7 +340,8 @@ void MenuManager::ModifyUndoMenuItems(AudacityProject &project) commandManager.Modify(wxT("Redo"), wxString::Format(_("&Redo %s"), desc)); - commandManager.Enable(wxT("Redo"), project.RedoAvailable()); + commandManager.Enable(wxT("Redo"), + ProjectManager::Get( project ).RedoAvailable()); } else { commandManager.Modify(wxT("Redo"), @@ -519,10 +521,11 @@ CommandFlag MenuManager::GetUpdateFlags if (!mLastEffect.empty()) flags |= HasLastEffectFlag; - if (project.UndoAvailable()) + auto &projectManager = ProjectManager::Get( project ); + if (projectManager.UndoAvailable()) flags |= UndoAvailableFlag; - if (project.RedoAvailable()) + if (projectManager.RedoAvailable()) flags |= RedoAvailableFlag; if (ViewInfo::Get( project ).ZoomInAvailable() && (flags & TracksExistFlag)) diff --git a/src/MixerBoard.cpp b/src/MixerBoard.cpp index 2ebee5d23..95446943c 100644 --- a/src/MixerBoard.cpp +++ b/src/MixerBoard.cpp @@ -412,7 +412,8 @@ void MixerTrackCluster::HandleSliderGain(const bool bWantPushState /*= false*/) // Update the TrackPanel correspondingly. TrackPanel::Get( *mProject ).RefreshTrack(mTrack.get()); if (bWantPushState) - mProject->PushState(_("Moved gain slider"), _("Gain"), UndoPush::CONSOLIDATE ); + ProjectManager::Get( *mProject ) + .PushState(_("Moved gain slider"), _("Gain"), UndoPush::CONSOLIDATE ); } #ifdef EXPERIMENTAL_MIDI_OUT @@ -425,7 +426,9 @@ void MixerTrackCluster::HandleSliderVelocity(const bool bWantPushState /*= false // Update the TrackPanel correspondingly. TrackPanel::Get( *mProject ).RefreshTrack(mTrack.get()); if (bWantPushState) - mProject->PushState(_("Moved velocity slider"), _("Velocity"), UndoPush::CONSOLIDATE); + ProjectManager::Get( *mProject ) + .PushState(_("Moved velocity slider"), _("Velocity"), + UndoPush::CONSOLIDATE); } #endif @@ -441,7 +444,9 @@ void MixerTrackCluster::HandleSliderPan(const bool bWantPushState /*= false*/) TrackPanel::Get( *mProject ).RefreshTrack(mTrack.get()); if (bWantPushState) - mProject->PushState(_("Moved pan slider"), _("Pan"), UndoPush::CONSOLIDATE ); + ProjectManager::Get( *mProject ) + .PushState(_("Moved pan slider"), _("Pan"), + UndoPush::CONSOLIDATE ); } void MixerTrackCluster::ResetMeter(const bool bResetClipping) diff --git a/src/Project.cpp b/src/Project.cpp index 7d352c170..837e0cd26 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -105,7 +105,6 @@ scroll information. It also has some status flags. #include "AudioIO.h" #include "Dependencies.h" #include "Diags.h" -#include "export/Export.h" #include "InconsistencyException.h" #include "import/Import.h" #include "KeyboardCapture.h" @@ -161,6 +160,8 @@ scroll information. It also has some status flags. #include "commands/CommandType.h" #include "prefs/ThemePrefs.h" +#include "export/Export.h" + #include "prefs/QualityPrefs.h" #include "prefs/TracksPrefs.h" @@ -604,7 +605,7 @@ public: FileActions::DoImportMIDI(mProject, name); else #endif - mProject->Import(name); + ProjectManager::Get( *mProject ).Import(name); } auto &window = ProjectWindow::Get( *mProject ); @@ -622,8 +623,9 @@ private: XMLTagHandler * -AudacityProject::ImportHandlerFactory( AudacityProject &project ) { - auto &ptr = project.mImportXMLTagHandler; +ProjectManager::ImportHandlerFactory( AudacityProject &project ) { + auto &projectManager = Get( project ); + auto &ptr = projectManager.mImportXMLTagHandler; if (!ptr) ptr = std::make_unique( &project ); @@ -631,7 +633,7 @@ AudacityProject::ImportHandlerFactory( AudacityProject &project ) { } ProjectFileIORegistry::Entry -AudacityProject::sImportHandlerFactory{ +ProjectManager::sImportHandlerFactory{ wxT("import"), ImportHandlerFactory }; @@ -659,7 +661,8 @@ bool ImportXMLTagHandler::HandleXMLTag(const wxChar *tag, const wxChar **attrs) // Guard this call so that C++ exceptions don't propagate through // the expat library GuardedCall( - [&] { mProject->Import(strAttr, &trackArray); }, + [&] { + ProjectManager::Get( *mProject ).Import(strAttr, &trackArray); }, [&] (AudacityException*) { trackArray.clear(); } ); @@ -695,7 +698,7 @@ bool ImportXMLTagHandler::HandleXMLTag(const wxChar *tag, const wxChar **attrs) return bSuccess; }; -AudacityProject *CreateNewAudacityProject() +AudacityProject *ProjectManager::New() { wxRect wndRect; bool bMaximized = false; @@ -715,8 +718,15 @@ AudacityProject *CreateNewAudacityProject() AllProjects{}.Add( sp ); auto p = sp.get(); auto &project = *p; + auto &projectManager = Get( project ); auto &window = GetProjectFrame( *p ); + MissingAliasFilesDialog::SetShouldShow(true); + MenuManager::Get( project ).CreateMenusAndCommands( project ); + + projectManager.InitialState(); + projectManager.RestartTimer(); + // wxGTK3 seems to need to require creating the window using default position // and then manually positioning it. window.SetPosition(wndRect.GetPosition()); @@ -729,8 +739,23 @@ AudacityProject *CreateNewAudacityProject() // window.Iconize(TRUE); } - //Initialise the Listener - gAudioIO->SetListener(p); + //Initialise the Listeners + gAudioIO->SetListener( &projectManager ); + SelectionBar::Get( project ).SetListener( &projectManager ); +#ifdef EXPERIMENTAL_SPECTRAL_EDITING + SpectralSelectionBar::Get( project ).SetListener( &projectManager ); +#endif + + project.UpdatePrefs(); + +#if wxUSE_DRAG_AND_DROP + // We can import now, so become a drag target +// SetDropTarget(safenew AudacityDropTarget(this)); +// mTrackPanel->SetDropTarget(safenew AudacityDropTarget(this)); + + // SetDropTarget takes ownership + TrackPanel::Get( project ).SetDropTarget( safenew DropTarget( &project ) ); +#endif //Set the NEW project as active: SetActiveProject(p); @@ -1034,8 +1059,9 @@ int AudacityProject::NextWindowID() // a bad compilation dependency. The event was never emitted anywhere. I // preserve it and its handler here but I move it to remove the dependency. // Asynchronous open -DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_OPEN_AUDIO_FILE, -1); -DEFINE_EVENT_TYPE(EVT_OPEN_AUDIO_FILE); +wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, + EVT_OPEN_AUDIO_FILE, wxCommandEvent); +wxDEFINE_EVENT(EVT_OPEN_AUDIO_FILE, wxCommandEvent); BEGIN_EVENT_TABLE(AudacityProject, wxFrame) EVT_MENU(wxID_ANY, AudacityProject::OnMenu) @@ -1050,11 +1076,9 @@ BEGIN_EVENT_TABLE(AudacityProject, wxFrame) EVT_COMMAND_SCROLL_LINEDOWN(HSBarID, AudacityProject::OnScrollRightButton) EVT_COMMAND_SCROLL(HSBarID, AudacityProject::OnScroll) EVT_COMMAND_SCROLL(VSBarID, AudacityProject::OnScroll) - EVT_TIMER(AudacityProjectTimerID, AudacityProject::OnTimer) // Fires for menu with ID #1...first menu defined EVT_UPDATE_UI(1, AudacityProject::OnUpdateUI) EVT_ICONIZE(AudacityProject::OnIconize) - EVT_COMMAND(wxID_ANY, EVT_OPEN_AUDIO_FILE, AudacityProject::OnOpenAudioFile) EVT_COMMAND(wxID_ANY, EVT_TOOLBAR_UPDATED, AudacityProject::OnToolBarUpdate) //mchinen:multithreaded calls - may not be threadsafe with CommandEvent: may have to change. END_EVENT_TABLE() @@ -1088,8 +1112,6 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id, statusBar->SetName(wxT("status_line")); // not localized mProjectNo = mProjectCounter++; // Bug 322 - MissingAliasFilesDialog::SetShouldShow(true); - mLastSavedTracks.reset(); auto &viewInfo = ViewInfo::Get( *this ); @@ -1126,10 +1148,6 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id, // // Create the ToolDock // - SelectionBar::Get( project ).SetListener( &project ); -#ifdef EXPERIMENTAL_SPECTRAL_EDITING - SpectralSelectionBar::Get( project ).SetListener( &project ); -#endif ToolManager::Get( project ).LayoutToolBars(); // @@ -1202,8 +1220,6 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id, mPlaybackScroller = std::make_unique(this); - MenuManager::Get( project ).CreateMenusAndCommands( project ); - // LLL: When Audacity starts or becomes active after returning from // another application, the first window that can accept focus // will be given the focus even if we try to SetFocus(). By @@ -1273,7 +1289,6 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id, // MM: Give track panel the focus to ensure keyboard commands work trackPanel.SetFocus(); - InitialState(); FixScrollbars(); ruler.SetLeftOffset(trackPanel.GetLeftOffset()); // bevel on AdornedRuler @@ -1309,25 +1324,8 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id, statusBar->SetStatusText(msg, mainStatusBarField); ControlToolBar::Get( project ).UpdateStatusBar(this); - mTimer = std::make_unique(this, AudacityProjectTimerID); - RestartTimer(); - - UpdatePrefs(); - -#if wxUSE_DRAG_AND_DROP - // We can import now, so become a drag target -// SetDropTarget(safenew AudacityDropTarget(this)); -// mTrackPanel->SetDropTarget(safenew AudacityDropTarget(this)); - - // SetDropTarget takes ownership - trackPanel.SetDropTarget(safenew DropTarget(this)); -#endif - wxTheApp->Bind(EVT_THEME_CHANGE, &AudacityProject::OnThemeChange, this); - project.Bind(EVT_PROJECT_STATUS_UPDATE, - &AudacityProject::OnStatusChange, this); - #ifdef EXPERIMENTAL_DA2 ClearBackground();// For wxGTK. #endif @@ -1362,7 +1360,7 @@ DefaultPlayOptions( AudacityProject &project ) options.captureMeter = projectAudioIO.GetCaptureMeter(); options.playbackMeter = projectAudioIO.GetPlaybackMeter(); options.timeTrack = TrackList::Get( project ).GetTimeTrack(); - options.listener = &project; + options.listener = &ProjectManager::Get( project ); return options; } @@ -1379,7 +1377,7 @@ DefaultSpeedPlayOptions( AudacityProject &project ) options.captureMeter = projectAudioIO.GetCaptureMeter(); options.playbackMeter = projectAudioIO.GetPlaybackMeter(); options.timeTrack = TrackList::Get( project ).GetTimeTrack(); - options.listener = &project; + options.listener = &ProjectManager::Get( project ); return options; } @@ -1467,10 +1465,11 @@ void AudacityProject::SetProjectTitle( int number) SetName(name); // to make the nvda screen reader read the correct title } -bool AudacityProject::SnapSelection() +bool ProjectManager::SnapSelection() { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); + auto &window = project; auto snapTo = settings.GetSnapTo(); if (snapTo != SNAP_OFF) { auto &viewInfo = ViewInfo::Get( project ); @@ -1492,7 +1491,7 @@ bool AudacityProject::SnapSelection() if (t0 != oldt0 || t1 != oldt1) { selectedRegion.setTimes(t0, t1); - TP_DisplaySelection(); + window.TP_DisplaySelection(); return true; } } @@ -1500,33 +1499,34 @@ bool AudacityProject::SnapSelection() return false; } -double AudacityProject::AS_GetRate() +double ProjectManager::AS_GetRate() { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); return settings.GetRate(); } // Typically this came from the SelectionToolbar and does not need to // be communicated back to it. -void AudacityProject::AS_SetRate(double rate) +void ProjectManager::AS_SetRate(double rate) { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); settings.SetRate( rate ); } -int AudacityProject::AS_GetSnapTo() +int ProjectManager::AS_GetSnapTo() { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); return settings.GetSnapTo(); } -void AudacityProject::AS_SetSnapTo(int snap) +void ProjectManager::AS_SetSnapTo(int snap) { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); + auto &window = project; settings.SetSnapTo( snap ); @@ -1537,21 +1537,21 @@ void AudacityProject::AS_SetSnapTo(int snap) SnapSelection(); - RedrawProject(); + window.RedrawProject(); SelectionBar::Get( project ).SetSnapTo(snap); } -const NumericFormatSymbol & AudacityProject::AS_GetSelectionFormat() +const NumericFormatSymbol & ProjectManager::AS_GetSelectionFormat() { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); return settings.GetSelectionFormat(); } -void AudacityProject::AS_SetSelectionFormat(const NumericFormatSymbol & format) +void ProjectManager::AS_SetSelectionFormat(const NumericFormatSymbol & format) { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); settings.SetSelectionFormat( format ); @@ -1564,9 +1564,9 @@ void AudacityProject::AS_SetSelectionFormat(const NumericFormatSymbol & format) SelectionBar::Get( project ).SetSelectionFormat(format); } -double AudacityProject::SSBL_GetRate() const +double ProjectManager::SSBL_GetRate() const { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); auto &tracks = TrackList::Get( project ); // Return maximum of project rate and all track rates. @@ -1574,16 +1574,17 @@ double AudacityProject::SSBL_GetRate() const tracks.Any().max( &WaveTrack::GetRate ) ); } -const NumericFormatSymbol & AudacityProject::SSBL_GetFrequencySelectionFormatName() +const NumericFormatSymbol & ProjectManager::SSBL_GetFrequencySelectionFormatName() { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); return settings.GetFrequencySelectionFormatName(); } -void AudacityProject::SSBL_SetFrequencySelectionFormatName(const NumericFormatSymbol & formatName) +void ProjectManager::SSBL_SetFrequencySelectionFormatName( + const NumericFormatSymbol & formatName) { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); settings.SetFrequencySelectionFormatName( formatName ); @@ -1597,16 +1598,18 @@ void AudacityProject::SSBL_SetFrequencySelectionFormatName(const NumericFormatSy #endif } -const NumericFormatSymbol & AudacityProject::SSBL_GetBandwidthSelectionFormatName() +const NumericFormatSymbol & +ProjectManager::SSBL_GetBandwidthSelectionFormatName() { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); return settings.GetBandwidthSelectionFormatName(); } -void AudacityProject::SSBL_SetBandwidthSelectionFormatName(const NumericFormatSymbol & formatName) +void ProjectManager::SSBL_SetBandwidthSelectionFormatName( + const NumericFormatSymbol & formatName) { - auto &project = *this; + auto &project = mProject; auto &settings = ProjectSettings::Get( project ); settings.SetBandwidthSelectionFormatName( formatName ); @@ -1620,10 +1623,11 @@ void AudacityProject::SSBL_SetBandwidthSelectionFormatName(const NumericFormatSy #endif } -void AudacityProject::SSBL_ModifySpectralSelection(double &bottom, double &top, bool done) +void ProjectManager::SSBL_ModifySpectralSelection( + double &bottom, double &top, bool done) { #ifdef EXPERIMENTAL_SPECTRAL_EDITING - auto &project = *this; + auto &project = mProject; auto &trackPanel = TrackPanel::Get( project ); auto &viewInfo = ViewInfo::Get( project ); @@ -1643,9 +1647,9 @@ void AudacityProject::SSBL_ModifySpectralSelection(double &bottom, double &top, } -void AudacityProject::AS_ModifySelection(double &start, double &end, bool done) +void ProjectManager::AS_ModifySelection(double &start, double &end, bool done) { - auto &project = *this; + auto &project = mProject; auto &trackPanel = TrackPanel::Get( project ); auto &viewInfo = ViewInfo::Get( project ); viewInfo.selectedRegion.setTimes(start, end); @@ -2386,9 +2390,9 @@ public: // be deleted before the final mDirManager->Deref() in this // routine. Failing to do so can cause unwanted recursion // and/or attempts to DELETE objects twice. -void AudacityProject::OnCloseWindow(wxCloseEvent & event) +void ProjectManager::OnCloseWindow(wxCloseEvent & event) { - auto &project = *this; + auto &project = mProject; auto &projectFileIO = project; const auto &settings = ProjectSettings::Get( project ); auto &projectAudioIO = ProjectAudioIO::Get( project ); @@ -2406,7 +2410,7 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) return; } - if (event.CanVeto() && (::wxIsBusy() || mbBusyImporting)) + if (event.CanVeto() && (::wxIsBusy() || project.mbBusyImporting)) { event.Veto(); return; @@ -2426,9 +2430,9 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) wxCommandEvent dummyEvent; ControlToolBar::Get( project ).OnStop(dummyEvent); - FixScrollbars(); + window.FixScrollbars(); projectAudioIO.SetAudioIOToken(0); - RedrawProject(); + window.RedrawProject(); } else if (gAudioIO->IsMonitoring()) { gAudioIO->StopStream(); @@ -2441,7 +2445,7 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) // project is now empty. if (event.CanVeto() && (settings.EmptyCanBeDirty() || bHasTracks)) { if ( UndoManager::Get( project ).UnsavedChanges() ) { - TitleRestorer Restorer( this );// RAII + TitleRestorer Restorer( &window );// RAII /* i18n-hint: The first %s numbers the project, the second %s is the project name.*/ wxString Title = wxString::Format(_("%sSave changes to %s?"), Restorer.sProjNumber, Restorer.sProjName); wxString Message = _("Save project before closing?"); @@ -2452,10 +2456,10 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) int result = AudacityMessageBox( Message, Title, wxYES_NO | wxCANCEL | wxICON_QUESTION, - this); + &window); if (result == wxCANCEL || (result == wxYES && - !GuardedCall( [&]{ return Save(); } ) + !GuardedCall( [&]{ return projectFileIO.Save(); } ) )) { event.Veto(); return; @@ -2472,7 +2476,7 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) // (But is there a different way to do this? What do other applications do? // I don't see full screen windows of Safari shrinking, but I do see // momentary blackness.) - ShowFullScreen(false); + window.ShowFullScreen(false); #endif ModuleManager::Get().Dispatch(ProjectClosing); @@ -2482,7 +2486,7 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) // The project is now either saved or the user doesn't want to save it, // so there's no need to keep auto save info around anymore - DeleteCurrentAutoSaveFile(); + projectFileIO.DeleteCurrentAutoSaveFile(); // DMM: Save the size of the last window the user closes // @@ -2530,7 +2534,7 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) // to save the state of the toolbars. ToolManager::Get( project ).Destroy(); - DestroyChildren(); + window.DestroyChildren(); TrackFactory::Destroy( project ); @@ -2551,10 +2555,10 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) DirManager::Destroy( project ); // Remove self from the global array, but defer destruction of self - auto pSelf = AllProjects{}.Remove( *this ); + auto pSelf = AllProjects{}.Remove( project ); wxASSERT( pSelf ); - if (gActiveProject == this) { + if (gActiveProject == &project) { // Find a NEW active project if ( !AllProjects{}.empty() ) { SetActiveProject(AllProjects{}.begin()->get()); @@ -2567,7 +2571,10 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) // Since we're going to be destroyed, make sure we're not to // receive audio notifications anymore. if (gAudioIO->GetListener() == this) { - gAudioIO->SetListener(gActiveProject); + gAudioIO->SetListener( gActiveProject + ? &ProjectManager::Get( *gActiveProject ) + : nullptr + ); } if (AllProjects{}.empty() && !AllProjects::Closing()) { @@ -2581,28 +2588,34 @@ void AudacityProject::OnCloseWindow(wxCloseEvent & event) else { AllProjects::Reset(); // For non-Mac, always keep at least one project window open - CreateNewAudacityProject(); + (void) New(); } #endif } + window.Destroy(); + // Destroys this pSelf.reset(); } -void AudacityProject::OnOpenAudioFile(wxCommandEvent & event) +// PRL: I preserve this handler function for an event that was never sent, but +// I don't know the intention. + +void ProjectManager::OnOpenAudioFile(wxCommandEvent & event) { + auto &project = mProject; + auto &window = GetProjectFrame( project ); const wxString &cmd = event.GetString(); - if (!cmd.empty()) { + if (!cmd.empty()) OpenFile(cmd); - } - RequestUserAttention(); + window.RequestUserAttention(); } // static method, can be called outside of a project -wxArrayString AudacityProject::ShowOpenDialog(const wxString &extraformat, const wxString &extrafilter) +wxArrayString ProjectManager::ShowOpenDialog(const wxString &extraformat, const wxString &extrafilter) { FormatList l; wxString filter; ///< List of file format names and extensions, separated @@ -2707,13 +2720,13 @@ wxArrayString AudacityProject::ShowOpenDialog(const wxString &extraformat, const } // static method, can be called outside of a project -bool AudacityProject::IsAlreadyOpen(const FilePath &projPathName) +bool ProjectManager::IsAlreadyOpen(const FilePath &projPathName) { const wxFileName newProjPathName(projPathName); auto start = AllProjects{}.begin(), finish = AllProjects{}.end(), iter = std::find_if( start, finish, [&]( const AllProjects::value_type &ptr ){ - return (newProjPathName.SameAs(wxFileNameWrapper{ ptr->mFileName })); + return newProjPathName.SameAs(wxFileNameWrapper{ ptr->GetFileName() }); } ); if (iter != finish) { wxString errMsg = @@ -2726,14 +2739,22 @@ bool AudacityProject::IsAlreadyOpen(const FilePath &projPathName) return false; } +const int AudacityProjectTimerID = 5200; + +BEGIN_EVENT_TABLE( ProjectManager, wxEvtHandler ) + EVT_COMMAND(wxID_ANY, EVT_OPEN_AUDIO_FILE, ProjectManager::OnOpenAudioFile) + EVT_TIMER(AudacityProjectTimerID, ProjectManager::OnTimer) +END_EVENT_TABLE() + // static method, can be called outside of a project -void AudacityProject::OpenFiles(AudacityProject *proj) +void ProjectManager::OpenFiles(AudacityProject *proj) { /* i18n-hint: This string is a label in the file type filter in the open * and save dialogues, for the option that only shows project files created * with Audacity. Do not include pipe symbols or .aup (this extension will * now be added automatically for the Save Projects dialogues).*/ - auto selectedFiles = ShowOpenDialog(_("Audacity projects"), wxT("*.aup")); + auto selectedFiles = + ProjectManager::ShowOpenDialog(_("Audacity projects"), wxT("*.aup")); if (selectedFiles.size() == 0) { gPrefs->Write(wxT("/LastOpenType"),wxT("")); gPrefs->Flush(); @@ -2755,7 +2776,7 @@ void AudacityProject::OpenFiles(AudacityProject *proj) const wxString &fileName = selectedFiles[ff]; // Make sure it isn't already open. - if (AudacityProject::IsAlreadyOpen(fileName)) + if (IsAlreadyOpen(fileName)) continue; // Skip ones that are already open. FileNames::UpdateDefaultPath(FileNames::Operation::Open, fileName); @@ -2770,13 +2791,16 @@ void AudacityProject::OpenFiles(AudacityProject *proj) // there are no tracks, but there's an Undo history, etc, then // bad things can happen, including data files moving to the NEW // project directory, etc. - if ( proj && ( proj->mDirty || !TrackList::Get( *proj ).empty() ) ) + if ( proj && ( + Get( *proj ).mDirty || + !TrackList::Get( *proj ).empty() + ) ) proj = nullptr; // This project is clean; it's never been touched. Therefore // all relevant member variables are in their initial state, // and it's okay to open a NEW project inside this window. - proj = AudacityProject::OpenProject( proj, fileName ); + proj = OpenProject( proj, fileName ); } } @@ -2807,19 +2831,19 @@ bool AudacityProject::WarnOfLegacyFile( ) } -AudacityProject *AudacityProject::OpenProject( +AudacityProject *ProjectManager::OpenProject( AudacityProject *pProject, const FilePath &fileNameArg, bool addtohistory) { AudacityProject *pNewProject = nullptr; if ( ! pProject ) - pProject = pNewProject = CreateNewAudacityProject(); + pProject = pNewProject = New(); auto cleanup = finally( [&] { if( pNewProject ) GetProjectFrame( *pNewProject ).Close(true); } ); - pProject->OpenFile( fileNameArg, addtohistory ); + Get( *pProject ).OpenFile( fileNameArg, addtohistory ); pNewProject = nullptr; - if( pProject && pProject->mIsRecovered ) + if( pProject && pProject->IsRecovered() ) ProjectWindow::Get( *pProject ).Zoom( ViewActions::GetZoomOfToFit( *pProject ) ); @@ -2916,8 +2940,9 @@ auto AudacityProject::ReadProjectFile( const FilePath &fileName ) } XMLTagHandler * -AudacityProject::RecordingRecoveryFactory( AudacityProject &project ) { - auto &ptr = project.mRecordingRecoveryHandler; +ProjectManager::RecordingRecoveryFactory( AudacityProject &project ) { + auto &projectManager = Get( project ); + auto &ptr = projectManager.mRecordingRecoveryHandler; if (!ptr) ptr = std::make_unique( &project ); @@ -2925,18 +2950,20 @@ AudacityProject::RecordingRecoveryFactory( AudacityProject &project ) { } ProjectFileIORegistry::Entry -AudacityProject::sRecoveryFactory{ +ProjectManager::sRecoveryFactory{ wxT("recordingrecovery"), RecordingRecoveryFactory }; // FIXME:? TRAP_ERR This should return a result that is checked. // See comment in AudacityApp::MRUOpen(). -void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) +void ProjectManager::OpenFile(const FilePath &fileNameArg, bool addtohistory) { - auto &project = *this; + auto &project = mProject; + auto &projectFileIO = project; auto &tracks = TrackList::Get( project ); auto &trackPanel = TrackPanel::Get( project ); auto &dirManager = DirManager::Get( project ); + auto &window = ProjectWindow::Get( project ); // On Win32, we may be given a short (DOS-compatible) file name on rare // occassions (e.g. stuff like "C:\PROGRA~1\AUDACI~1\PROJEC~1.AUP"). We @@ -2951,7 +2978,7 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) // then open a NEW project from the same data with no warning. // This was reported in http://bugzilla.audacityteam.org/show_bug.cgi?id=137#c17, // but is not really part of that bug. Anyway, prevent it! - if (AudacityProject::IsAlreadyOpen(fileName)) + if (IsAlreadyOpen(fileName)) return; @@ -2963,7 +2990,7 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) AudacityMessageBox( _("You are trying to open an automatically created backup file.\nDoing this may result in severe data loss.\n\nPlease open the actual Audacity project file instead."), _("Warning - Backup File Detected"), - wxOK | wxCENTRE, this); + wxOK | wxCENTRE, &window); return; } @@ -2971,7 +2998,7 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) AudacityMessageBox( wxString::Format( _("Could not open file: %s"), fileName ), ("Error Opening File"), - wxOK | wxCENTRE, this); + wxOK | wxCENTRE, &window); return; } @@ -2987,14 +3014,14 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) AudacityMessageBox( wxString::Format( _("Could not open file: %s"), fileName ), _("Error opening file"), - wxOK | wxCENTRE, this); + wxOK | wxCENTRE, &window); return; } int numRead = ff.Read(buf, 15); if (numRead != 15) { AudacityMessageBox(wxString::Format(_("File may be invalid or corrupted: \n%s"), fileName), _("Error Opening File or Project"), - wxOK | wxCENTRE, this); + wxOK | wxCENTRE, &window); ff.Close(); return; } @@ -3006,14 +3033,14 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) if (temp == wxT("AudacityProject")) { // It's an Audacity 1.0 (or earlier) project file. // If they bail out, return and do no more. - if( !WarnOfLegacyFile() ) + if( !projectFileIO.WarnOfLegacyFile() ) return; // Convert to the NEW format. bool success = ConvertLegacyProjectFile(wxFileName{ fileName }); if (!success) { AudacityMessageBox(_("Audacity was unable to convert an Audacity 1.0 project to the new project format."), _("Error Opening Project"), - wxOK | wxCENTRE, this); + wxOK | wxCENTRE, &window); return; } else { @@ -3037,12 +3064,12 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) { #ifdef USE_MIDI if (Importer::IsMidi(fileName)) - FileActions::DoImportMIDI(this, fileName); + FileActions::DoImportMIDI( &project, fileName ); else #endif - Import(fileName); + Import( fileName ); - ZoomAfterImport(nullptr); + window.ZoomAfterImport(nullptr); } return; @@ -3055,7 +3082,7 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) mRecordingRecoveryHandler.reset(); } ); - auto results = ReadProjectFile( fileName ); + auto results = projectFileIO.ReadProjectFile( fileName ); if ( results.decodeError ) return; @@ -3075,7 +3102,7 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) InitialState(); trackPanel.SetFocusedTrack( *tracks.Any().begin() ); - HandleResize(); + window.HandleResize(); trackPanel.Refresh(false); trackPanel.Update(); // force any repaint to happen now, // else any asynch calls into the blockfile code will not have @@ -3096,19 +3123,19 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) if ( bParseSuccess ) { // This is a no-fail: dirManager.FillBlockfilesCache(); - EnqueueODTasks(); + projectFileIO.EnqueueODTasks(); } // For an unknown reason, OSX requires that the project window be // raised if a recovery took place. - CallAfter( [this] { Raise(); } ); + window.CallAfter( [&] { window.Raise(); } ); } } ); if (bParseSuccess) { bool saved = false; - if (mIsRecovered) + if (projectFileIO.IsRecovered()) { // This project has been recovered, so write a NEW auto-save file // now and then DELETE the old one in the auto-save folder. Note that @@ -3118,11 +3145,11 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) ::ProjectFSCK(dirManager, err, true); // Correct problems in auto-recover mode. // PushState calls AutoSave(), so no longer need to do so here. - this->PushState(_("Project was recovered"), _("Recover")); + PushState(_("Project was recovered"), _("Recover")); if (!wxRemoveFile(fileName)) AudacityMessageBox(_("Could not remove old auto save file"), - _("Error"), wxICON_STOP, this); + _("Error"), wxICON_STOP, &window); } else { @@ -3146,7 +3173,7 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) */ closed = true; SetMenuClose(true); - Close(); + window.Close(); return; } else if (status & FSCKstatus_CHANGED) @@ -3164,7 +3191,7 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) // this->PushState(_("Project checker repaired file"), _("Project Repair")); if (status & FSCKstatus_SAVE_AUP) - this->Save(), saved = true; + projectFileIO.Save(), saved = true; } } @@ -3172,7 +3199,7 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) if (!saved) // We processed an tag, so save it as a normal project, // with no tags. - this->Save(); + projectFileIO.Save(); } } else { @@ -3191,8 +3218,8 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) tracks.Clear(); //tracks.Clear(true); - mFileName = wxT(""); - SetProjectTitle(); + project.SetFileName( wxT("") ); + projectFileIO.SetProjectTitle(); wxLogError(wxT("Could not parse file \"%s\". \nError: %s"), fileName, errorStr); @@ -3257,7 +3284,7 @@ void AudacityProject::OpenFile(const FilePath &fileNameArg, bool addtohistory) */ ShowErrorDialog( - this, + &window, _("Error Opening Project"), errorStr, url); @@ -4095,10 +4122,11 @@ bool AudacityProject::SaveCopyWaveTracks(const FilePath & strProjectPathName, std::vector< std::shared_ptr< Track > > -AudacityProject::AddImportedTracks(const FilePath &fileName, +ProjectManager::AddImportedTracks(const FilePath &fileName, TrackHolders &&newTracks) { - auto &project = *this; + auto &project = mProject; + auto &projectFileIO = project; auto &tracks = TrackList::Get( project ); std::vector< std::shared_ptr< Track > > results; @@ -4160,7 +4188,7 @@ AudacityProject::AddImportedTracks(const FilePath &fileName, SeqBlock& block = blocks[0]; if (block.f->IsAlias()) { - mImportedDependencies = true; + projectFileIO.SetImportedDependencies( true ); } } } @@ -4176,7 +4204,7 @@ AudacityProject::AddImportedTracks(const FilePath &fileName, } PushState(wxString::Format(_("Imported '%s'"), fileName), - _("Import")); + _("Import")); #if defined(__WXGTK__) // See bug #1224 @@ -4187,11 +4215,12 @@ AudacityProject::AddImportedTracks(const FilePath &fileName, wxEventLoopBase::GetActive()->YieldFor(wxEVT_CATEGORY_UI | wxEVT_CATEGORY_USER_INPUT); #endif - if (initiallyEmpty && !IsProjectSaved() ) { + if (initiallyEmpty && !projectFileIO.IsProjectSaved() ) { wxString name = fileName.AfterLast(wxFILE_SEP_PATH).BeforeLast(wxT('.')); - mFileName =::wxPathOnly(fileName) + wxFILE_SEP_PATH + name + wxT(".aup"); - mbLoadedFromAup = false; - SetProjectTitle(); + project.SetFileName( + ::wxPathOnly(fileName) + wxFILE_SEP_PATH + name + wxT(".aup") ); + projectFileIO.SetLoadedFromAup( false ); + projectFileIO.SetProjectTitle(); } // Moved this call to higher levels to prevent flicker redrawing everything on each file. @@ -4215,9 +4244,10 @@ void AudacityProject::ZoomAfterImport(Track *pTrack) } // If pNewTrackList is passed in non-NULL, it gets filled with the pointers to NEW tracks. -bool AudacityProject::Import(const FilePath &fileName, WaveTrackArray* pTrackArray /*= NULL*/) +bool ProjectManager::Import( + const FilePath &fileName, WaveTrackArray* pTrackArray /*= NULL*/) { - auto &project = *this; + auto &project = mProject; auto &dirManager = DirManager::Get( project ); auto oldTags = Tags::Get( project ).shared_from_this(); TrackHolders newTracks; @@ -4242,7 +4272,7 @@ bool AudacityProject::Import(const FilePath &fileName, WaveTrackArray* pTrackArr if (!errorMessage.empty()) { // Error message derived from Importer::Import // Additional help via a Help button links to the manual. - ShowErrorDialog(this, _("Error Importing"), + ShowErrorDialog(&GetProjectFrame( project ), _("Error Importing"), errorMessage, wxT("Importing_Audio")); } if (!success) @@ -4520,9 +4550,9 @@ will be irreversibly overwritten."), fName, fName); // Undo/History methods // -void AudacityProject::InitialState() +void ProjectManager::InitialState() { - auto &project = *this; + auto &project = mProject; auto &tracks = TrackList::Get( project ); auto &viewInfo = ViewInfo::Get( project ); auto &undoManager = UndoManager::Get( project ); @@ -4541,34 +4571,35 @@ void AudacityProject::InitialState() menuManager.UpdateMenus( project ); } -bool AudacityProject::UndoAvailable() +bool ProjectManager::UndoAvailable() { - auto &project = *this; + auto &project = mProject; auto &tracks = TrackList::Get( project ); auto &undoManager = UndoManager::Get( project ); return undoManager.UndoAvailable() && !tracks.HasPendingTracks(); } -bool AudacityProject::RedoAvailable() +bool ProjectManager::RedoAvailable() { - auto &project = *this; + auto &project = mProject; auto &tracks = TrackList::Get( project ); auto &undoManager = UndoManager::Get( project ); return undoManager.RedoAvailable() && !tracks.HasPendingTracks(); } -void AudacityProject::PushState(const wxString &desc, const wxString &shortDesc) +void ProjectManager::PushState(const wxString &desc, const wxString &shortDesc) { PushState(desc, shortDesc, UndoPush::AUTOSAVE); } -void AudacityProject::PushState(const wxString &desc, +void ProjectManager::PushState(const wxString &desc, const wxString &shortDesc, UndoPush flags ) { - auto &project = *this; + auto &project = mProject; + auto &projectFileIO = project; const auto &settings = ProjectSettings::Get( project ); auto &tracks = TrackList::Get( project ); auto &viewInfo = ViewInfo::Get( project ); @@ -4587,21 +4618,22 @@ void AudacityProject::PushState(const wxString &desc, if (settings.GetTracksFitVerticallyZoomed()) ViewActions::DoZoomFitV( project ); if((flags & UndoPush::AUTOSAVE) != UndoPush::MINIMAL) - AutoSave(); + projectFileIO.AutoSave(); TrackPanel::Get( project ).HandleCursorForPresentMouseState(); } -void AudacityProject::RollbackState() +void ProjectManager::RollbackState() { - auto &project = *this; + auto &project = mProject; auto &undoManager = UndoManager::Get( project ); SetStateTo( undoManager.GetCurrentState() ); } -void AudacityProject::ModifyState(bool bWantsAutoSave) +void ProjectManager::ModifyState(bool bWantsAutoSave) { - auto &project = *this; + auto &project = mProject; + auto &projectFileIO = project; auto &tracks = TrackList::Get( project ); auto &viewInfo = ViewInfo::Get( project ); auto &undoManager = UndoManager::Get( project ); @@ -4609,18 +4641,20 @@ void AudacityProject::ModifyState(bool bWantsAutoSave) undoManager.ModifyState( &tracks, viewInfo.selectedRegion, tags.shared_from_this()); if (bWantsAutoSave) - AutoSave(); + projectFileIO.AutoSave(); TrackPanel::Get( project ).HandleCursorForPresentMouseState(); } // LL: Is there a memory leak here as "l" and "t" are not deleted??? // Vaughan, 2010-08-29: No, as "l" is a TrackList* of an Undo stack state. // Need to keep it and its tracks "t" available for Undo/Redo/SetStateTo. -void AudacityProject::PopState(const UndoState &state) +void ProjectManager::PopState(const UndoState &state) { - auto &project = *this; + auto &project = mProject; + auto &projectFileIO = project; auto &dstTracks = TrackList::Get( project ); auto &viewInfo = ViewInfo::Get( project ); + auto &window = ProjectWindow::Get( project ); viewInfo.selectedRegion = state.selectedRegion; @@ -4665,22 +4699,24 @@ void AudacityProject::PopState(const UndoState &state) if(odUsed) ODManager::Instance()->AddNewTask(std::move(computeTask)); - HandleResize(); + window.HandleResize(); MenuManager::Get( project ).UpdateMenus( project ); - AutoSave(); + projectFileIO.AutoSave(); } -void AudacityProject::SetStateTo(unsigned int n) +void ProjectManager::SetStateTo(unsigned int n) { - auto &project = *this; + auto &project = mProject; auto &trackPanel = TrackPanel::Get( project ); auto &undoManager = UndoManager::Get( project ); + auto &window = ProjectWindow::Get( project ); + undoManager.SetStateTo(n, [this]( const UndoState &state ){ PopState(state); } ); - HandleResize(); + window.HandleResize(); trackPanel.SetFocusedTrack(NULL); trackPanel.Refresh(false); MenuManager::Get( project ).ModifyUndoMenuItems( project ); @@ -4760,7 +4796,7 @@ void AudacityProject::SkipEnd(bool shift) } -void AudacityProject::RestartTimer() +void ProjectManager::RestartTimer() { if (mTimer) { // mTimer->Stop(); // not really needed @@ -4768,14 +4804,16 @@ void AudacityProject::RestartTimer() } } -void AudacityProject::OnTimer(wxTimerEvent& WXUNUSED(event)) +void ProjectManager::OnTimer(wxTimerEvent& WXUNUSED(event)) { - auto &project = *this; + auto &project = mProject; auto &projectAudioIO = ProjectAudioIO::Get( project ); - auto &window = project; + auto &window = GetProjectFrame( project ); auto &dirManager = DirManager::Get( project ); auto mixerToolBar = &MixerToolBar::Get( project ); mixerToolBar->UpdateControls(); + + auto &statusBar = *window.GetStatusBar(); // gAudioIO->GetNumCaptureChannels() should only be positive // when we are recording. @@ -4788,7 +4826,7 @@ void AudacityProject::OnTimer(wxTimerEvent& WXUNUSED(event)) sMessage.Printf(_("Disk space remaining for recording: %s"), GetHoursMinsString(iRecordingMins)); // Do not change mLastMainStatusMessage - window.GetStatusBar()->SetStatusText(sMessage, mainStatusBarField); + statusBar.SetStatusText(sMessage, mainStatusBarField); } } else if(ODManager::IsInstanceCreated()) @@ -4809,7 +4847,7 @@ void AudacityProject::OnTimer(wxTimerEvent& WXUNUSED(event)) msg = _("On-demand import and waveform calculation complete."); - window.GetStatusBar()->SetStatusText(msg, mainStatusBarField); + statusBar.SetStatusText(msg, mainStatusBarField); } else if(numTasks>1) @@ -4820,7 +4858,7 @@ void AudacityProject::OnTimer(wxTimerEvent& WXUNUSED(event)) ratioComplete*100.0); - window.GetStatusBar()->SetStatusText(msg, mainStatusBarField); + statusBar.SetStatusText(msg, mainStatusBarField); } } @@ -4840,9 +4878,9 @@ void AudacityProject::SetStatus(const wxString &msg) } } -void AudacityProject::OnStatusChange( wxCommandEvent & ) +void ProjectManager::OnStatusChange( wxCommandEvent & ) { - auto &project = *this; + auto &project = mProject; auto &window = project; const auto &msg = project.GetStatus(); window.GetStatusBar()->SetStatusText(msg, mainStatusBarField); @@ -4991,9 +5029,9 @@ void AudacityProject::DeleteCurrentAutoSaveFile() } -void AudacityProject::OnAudioIORate(int rate) +void ProjectManager::OnAudioIORate(int rate) { - auto &project = *this; + auto &project = mProject; auto &window = GetProjectFrame( project ); wxString display; if (rate > 0) { @@ -5016,19 +5054,21 @@ void AudacityProject::OnAudioIORate(int rate) statusBar->SetStatusText(display, rateStatusBarField); } -void AudacityProject::OnAudioIOStartRecording() +void ProjectManager::OnAudioIOStartRecording() { + auto &projectFileIO = mProject; // Before recording is started, auto-save the file. The file will have // empty tracks at the bottom where the recording will be put into - AutoSave(); + projectFileIO.AutoSave(); } // This is called after recording has stopped and all tracks have flushed. -void AudacityProject::OnAudioIOStopRecording() +void ProjectManager::OnAudioIOStopRecording() { - auto &project = *this; - auto &projectAudioIO = ProjectAudioIO::Get( project ); + auto &project = mProject; auto &dirManager = DirManager::Get( project ); + auto &projectAudioIO = ProjectAudioIO::Get( project ); + auto &projectFileIO = project; auto &window = ProjectWindow::Get( project ); // Only push state if we were capturing and not monitoring @@ -5072,7 +5112,7 @@ You are saving directly to a slow external storage device\n\ // Reset timer record if (IsTimerRecordCancelled()) { - EditActions::DoUndo( *this ); + EditActions::DoUndo( project ); ResetTimerRecordCancelled(); } @@ -5085,15 +5125,19 @@ You are saving directly to a slow external storage device\n\ dirManager.WriteCacheToDisk(); // Now we auto-save again to get the project to a "normal" state again. - AutoSave(); + projectFileIO.AutoSave(); } -void AudacityProject::OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) +void ProjectManager::OnAudioIONewBlockFiles( + const AutoSaveFile & blockFileLog) { + auto &project = mProject; + auto &projectFileIO = project; // New blockfiles have been created, so add them to the auto-save file - if (!mAutoSaveFileName.empty()) + const auto &autoSaveFileName = projectFileIO.GetAutoSaveFileName(); + if ( !autoSaveFileName.empty() ) { - wxFFile f(mAutoSaveFileName, wxT("ab")); + wxFFile f{ autoSaveFileName, wxT("ab") }; if (!f.IsOpened()) return; // Keep recording going, there's not much we can do here blockFileLog.Append(f); @@ -5111,8 +5155,8 @@ bool AudacityProject::IsProjectSaved() { } // This is done to empty out the tracks, but without creating a new project. -void AudacityProject::ResetProjectToEmpty() { - auto &project = *this; +void ProjectManager::ResetProjectToEmpty() { + auto &project = mProject; auto &projectFileIO = project; auto &viewInfo = ViewInfo::Get( project ); @@ -5185,7 +5229,7 @@ bool AudacityProject::SaveFromTimerRecording(wxFileName fnFile) { return bSuccess; } -wxString AudacityProject::GetHoursMinsString(int iMinutes) +wxString ProjectManager::GetHoursMinsString(int iMinutes) { wxString sFormatted; @@ -5214,8 +5258,8 @@ wxString AudacityProject::GetHoursMinsString(int iMinutes) // minutes of recording time we have available. // The calculations made are based on the user's current // preferences. -int AudacityProject::GetEstimatedRecordingMinsLeftOnDisk(long lCaptureChannels) { - auto &project = *this; +int ProjectManager::GetEstimatedRecordingMinsLeftOnDisk(long lCaptureChannels) { + auto &project = mProject; // Obtain the current settings auto oCaptureFormat = QualityPrefs::SampleFormatChoice(); @@ -5416,3 +5460,31 @@ void AudacityProject::CloseLock() mLastSavedTracks.reset(); } } + +static AudacityProject::AttachedObjects::RegisteredFactory sProjectManagerKey { + []( AudacityProject &project ) { + return std::make_shared< ProjectManager >( project ); + } +}; + +ProjectManager &ProjectManager::Get( AudacityProject &project ) +{ + return project.AttachedObjects::Get< ProjectManager >( sProjectManagerKey ); +} + +const ProjectManager &ProjectManager::Get( const AudacityProject &project ) +{ + return Get( const_cast< AudacityProject & >( project ) ); +} + +ProjectManager::ProjectManager( AudacityProject &project ) + : mProject{ project } + , mTimer{ std::make_unique(this, AudacityProjectTimerID) } +{ + auto &window = ProjectWindow::Get( mProject ); + window.Bind( wxEVT_CLOSE_WINDOW, &ProjectManager::OnCloseWindow, this ); + mProject.Bind(EVT_PROJECT_STATUS_UPDATE, + &ProjectManager::OnStatusChange, this); +} + +ProjectManager::~ProjectManager() = default; diff --git a/src/Project.h b/src/Project.h index 68f640400..d350a9bfb 100644 --- a/src/Project.h +++ b/src/Project.h @@ -35,8 +35,6 @@ #include "xml/XMLTagHandler.h" // to inherit -const int AudacityProjectTimerID = 5200; - wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_PROJECT_STATUS_UPDATE, wxCommandEvent); @@ -61,7 +59,6 @@ struct UndoState; enum class UndoPush : unsigned char; -AudacityProject *CreateNewAudacityProject(); AUDACITY_DLL_API AudacityProject *GetActiveProject(); void GetDefaultWindowRect(wxRect *defRect); @@ -165,10 +162,7 @@ using AttachedWindows = ClientData::Site< using ProjectWindow = AudacityProject; class AUDACITY_DLL_API AudacityProject final : public wxFrame, public TrackPanelListener, - public SelectionBarListener, - public SpectralSelectionBarListener, public XMLTagHandler, - public AudioIOListener, private PrefsListener , public AttachedObjects , public AttachedWindows @@ -200,47 +194,6 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame, bool IsActive() override; - // File I/O - - /** @brief Show an open dialogue for opening audio files, and possibly other - * sorts of files. - * - * The file type filter will automatically contain: - * - "All files" with any extension or none, - * - "All supported files" based on the file formats supported in this - * build of Audacity, - * - All of the individual formats specified by the importer plug-ins which - * are built into this build of Audacity, each with the relevant file - * extensions for that format. - * The dialogue will start in the DefaultOpenPath directory read from the - * preferences, failing that the working directory. The file format filter - * will be set to the DefaultOpenType from the preferences, failing that - * the first format specified in the dialogue. These two parameters will - * be saved to the preferences once the user has chosen a file to open. - * @param extraformat Specify the name of an additional format to allow - * opening in this dialogue. This string is free-form, but should be short - * enough to fit in the file dialogue filter drop-down. It should be - * translated. - * @param extrafilter Specify the file extension(s) for the additional format - * specified by extraformat. The patterns must include the wildcard (e.g. - * "*.aup" not "aup" or ".aup"), separate multiple patters with a semicolon, - * e.g. "*.aup;*.AUP" because patterns are case-sensitive. Do not add a - * trailing semicolon to the string. This string should not be translated - * @return Array of file paths which the user selected to open (multiple - * selections allowed). - */ - static wxArrayString ShowOpenDialog(const wxString &extraformat = {}, - const wxString &extrafilter = {}); - static bool IsAlreadyOpen(const FilePath &projPathName); - static void OpenFiles(AudacityProject *proj); - - // Return the given project if that is not NULL, else create a project. - // Then open the given project path. - // But if an exception escapes this function, create no NEW project. - static AudacityProject *OpenProject( - AudacityProject *pProject, - const FilePath &fileNameArg, bool addtohistory = true); - struct ReadProjectResults { bool decodeError; @@ -250,26 +203,14 @@ class AUDACITY_DLL_API AudacityProject final : public wxFrame, }; ReadProjectResults ReadProjectFile( const FilePath &fileName ); - void OpenFile(const FilePath &fileName, bool addtohistory = true); - -private: void EnqueueODTasks(); -public: using wxFrame::DetachMenuBar; bool WarnOfLegacyFile( ); - // If pNewTrackList is passed in non-NULL, it gets filled with the pointers to NEW tracks. - bool Import(const FilePath &fileName, WaveTrackArray *pTrackArray = NULL); - void ZoomAfterImport(Track *pTrack); - // Takes array of unique pointers; returns array of shared - std::vector< std::shared_ptr > - AddImportedTracks(const FilePath &fileName, - TrackHolders &&newTracks); - void CloseLock(); bool Save(); @@ -283,7 +224,9 @@ private: public: const FilePath &GetFileName() { return mFileName; } - bool GetDirty() { return mDirty; } + void SetFileName( const FilePath &value ) { mFileName = value; } + + const FilePath &GetAutoSaveFileName() { return mAutoSaveFileName; } void SetProjectTitle( int number =-1); wxWindow *GetMainPage() { return mMainPage; } @@ -292,13 +235,8 @@ public: // Timer Record Auto Save/Export Routines bool SaveFromTimerRecording(wxFileName fnFile); bool IsProjectSaved(); - void ResetProjectToEmpty(); - void ResetProjectFileIO(); - // Routine to estimate how many minutes of recording time are left on disk - int GetEstimatedRecordingMinsLeftOnDisk(long lCaptureChannels = 0); - // Converts number of minutes to human readable format - wxString GetHoursMinsString(int iMinutes); + void ResetProjectFileIO(); // Message Handlers @@ -316,10 +254,7 @@ public: void OnMove(wxMoveEvent & event); void DoScroll(); void OnScroll(wxScrollEvent & event); - void OnCloseWindow(wxCloseEvent & event); - void OnTimer(wxTimerEvent & event); void OnToolBarUpdate(wxCommandEvent & event); - void OnOpenAudioFile(wxCommandEvent & event); void HandleResize(); void UpdateLayout(); @@ -369,35 +304,7 @@ public: const wxString &GetStatus() const { return mLastMainStatusMessage; } void SetStatus(const wxString &msg); - void OnStatusChange( wxCommandEvent& ); - -private: - bool SnapSelection(); - public: - // SelectionBarListener callback methods - - double AS_GetRate() override; - void AS_SetRate(double rate) override; - int AS_GetSnapTo() override; - void AS_SetSnapTo(int snap) override; - const NumericFormatSymbol & AS_GetSelectionFormat() override; - void AS_SetSelectionFormat(const NumericFormatSymbol & format) override; - void AS_ModifySelection(double &start, double &end, bool done) override; - - // SpectralSelectionBarListener callback methods - - double SSBL_GetRate() const override; - - const NumericFormatSymbol & SSBL_GetFrequencySelectionFormatName() override; - void SSBL_SetFrequencySelectionFormatName(const NumericFormatSymbol & formatName) override; - - const NumericFormatSymbol & SSBL_GetBandwidthSelectionFormatName() override; - void SSBL_SetBandwidthSelectionFormatName(const NumericFormatSymbol & formatName) override; - - void SSBL_ModifySpectralSelection(double &bottom, double &top, bool done) override; - - void SetStateTo(unsigned int n); // XMLTagHandler callback methods @@ -408,32 +315,13 @@ public: void WriteXMLHeader(XMLWriter &xmlFile) const; - // Audio IO callback methods - void OnAudioIORate(int rate) override; - void OnAudioIOStartRecording() override; - void OnAudioIOStopRecording() override; - void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override; - - bool UndoAvailable(); - bool RedoAvailable(); - - void PushState(const wxString &desc, const wxString &shortDesc); // use UndoPush::AUTOSAVE - void PushState(const wxString &desc, const wxString &shortDesc, UndoPush flags); - void RollbackState(); - - private: void OnThemeChange(wxCommandEvent & evt); - void InitialState(); public: - void ModifyState(bool bWantsAutoSave); // if true, writes auto-save file. Should set only if you really want the state change restored after - // a crash, as it can take many seconds for large (eg. 10 track-hours) projects - - void PopState(const UndoState &state); - void AutoSave(); + void DeleteCurrentAutoSaveFile(); private: @@ -448,13 +336,10 @@ public: std::shared_ptr mLastSavedTracks; private: - bool mDirty{ false }; // Window elements wxString mLastMainStatusMessage; - std::unique_ptr mTimer; - void RestartTimer(); wxPanel *mTopPanel{}; wxWindow * mMainPage; @@ -481,24 +366,21 @@ private: void SetNormalizedWindowState(wxRect pSizeAndLocation) { mNormalizedWindowState = pSizeAndLocation; } wxRect GetNormalizedWindowState() const { return mNormalizedWindowState; } - bool IsTimerRecordCancelled(){return mTimerRecordCanceled;} - void SetTimerRecordCancelled(){mTimerRecordCanceled=true;} - void ResetTimerRecordCancelled(){mTimerRecordCanceled=false;} - private: bool mIsDeleting{ false }; public: bool IsBeingDeleted() const { return mIsDeleting; } void SetIsBeingDeleted() { mIsDeleting = true; } + bool IsRecovered() const { return mIsRecovered; } + void SetImportedDependencies( bool value ) { mImportedDependencies = value; } + void SetLoadedFromAup( bool value ) { mbLoadedFromAup = value; } private: bool mLockPlayRegion; - std::unique_ptr mImportXMLTagHandler; - // Last auto-save file name and path (empty if none) - wxString mAutoSaveFileName; + FilePath mAutoSaveFileName; // Are we currently auto-saving or not? bool mAutoSaving{ false }; @@ -509,9 +391,6 @@ private: // The auto-save data dir the project has been recovered from wxString mRecoveryAutoSaveDataDir; - // The handler that handles recovery of tags - std::unique_ptr mRecordingRecoveryHandler; - // Dependencies have been imported and a warning should be shown on save bool mImportedDependencies{ false }; @@ -519,16 +398,6 @@ private: wxRect mNormalizedWindowState; - //flag for cancellation of timer record. - bool mTimerRecordCanceled{ false }; - - // Are we currently closing as the result of a menu command? - bool mMenuClose{ false }; - -public: - void SetMenuClose(bool value) { mMenuClose = value; } - -private: bool mbInitializingScrollbar{ false }; public: @@ -560,14 +429,175 @@ public: private: std::unique_ptr mPlaybackScroller; +public: + PlaybackScroller &GetPlaybackScroller() { return *mPlaybackScroller; } + + DECLARE_EVENT_TABLE() +}; + +class ProjectManager final + : public wxEvtHandler + , public ClientData::Base + , public AudioIOListener + , private SelectionBarListener + , private SpectralSelectionBarListener +{ +public: + static ProjectManager &Get( AudacityProject &project ); + static const ProjectManager &Get( const AudacityProject &project ); + + explicit ProjectManager( AudacityProject &project ); + ~ProjectManager() override; + + // This is the factory for projects: + static AudacityProject *New(); + + // File I/O + + /** @brief Show an open dialogue for opening audio files, and possibly other + * sorts of files. + * + * The file type filter will automatically contain: + * - "All files" with any extension or none, + * - "All supported files" based on the file formats supported in this + * build of Audacity, + * - All of the individual formats specified by the importer plug-ins which + * are built into this build of Audacity, each with the relevant file + * extensions for that format. + * The dialogue will start in the DefaultOpenPath directory read from the + * preferences, failing that the working directory. The file format filter + * will be set to the DefaultOpenType from the preferences, failing that + * the first format specified in the dialogue. These two parameters will + * be saved to the preferences once the user has chosen a file to open. + * @param extraformat Specify the name of an additional format to allow + * opening in this dialogue. This string is free-form, but should be short + * enough to fit in the file dialogue filter drop-down. It should be + * translated. + * @param extrafilter Specify the file extension(s) for the additional format + * specified by extraformat. The patterns must include the wildcard (e.g. + * "*.aup" not "aup" or ".aup"), separate multiple patters with a semicolon, + * e.g. "*.aup;*.AUP" because patterns are case-sensitive. Do not add a + * trailing semicolon to the string. This string should not be translated + * @return Array of file paths which the user selected to open (multiple + * selections allowed). + */ + static wxArrayString ShowOpenDialog(const wxString &extraformat = {}, + const wxString &extrafilter = {}); + + static bool IsAlreadyOpen(const FilePath &projPathName); + + // The functions that open and import files can act as factories too, and + // they set projects to initial state. + static void OpenFiles(AudacityProject *proj); + + void OpenFile(const FilePath &fileName, bool addtohistory = true); + + // Return the given project if that is not NULL, else create a project. + // Then open the given project path. + // But if an exception escapes this function, create no NEW project. + static AudacityProject *OpenProject( + AudacityProject *pProject, + const FilePath &fileNameArg, bool addtohistory = true); + + // If pNewTrackList is passed in non-NULL, it gets filled with the pointers to NEW tracks. + bool Import(const FilePath &fileName, WaveTrackArray *pTrackArray = NULL); + + // Takes array of unique pointers; returns array of shared + std::vector< std::shared_ptr > + AddImportedTracks(const FilePath &fileName, + TrackHolders &&newTracks); + + bool GetDirty() { return mDirty; } + + void ResetProjectToEmpty(); + + // Routine to estimate how many minutes of recording time are left on disk + int GetEstimatedRecordingMinsLeftOnDisk(long lCaptureChannels = 0); + // Converts number of minutes to human readable format + wxString GetHoursMinsString(int iMinutes); + + void SetStateTo(unsigned int n); + bool UndoAvailable(); + bool RedoAvailable(); + void PushState(const wxString &desc, const wxString &shortDesc); // use UndoPush::AUTOSAVE + void PushState(const wxString &desc, const wxString &shortDesc, UndoPush flags); + void RollbackState(); + void ModifyState(bool bWantsAutoSave); // if true, writes auto-save file. + // Should set only if you really want the state change restored after + // a crash, as it can take many seconds for large (eg. 10 track-hours) + // projects + void PopState(const UndoState &state); + + bool IsTimerRecordCancelled() { return mTimerRecordCanceled; } + void SetTimerRecordCancelled() { mTimerRecordCanceled = true; } + void ResetTimerRecordCancelled() { mTimerRecordCanceled = false; } + + void SetMenuClose(bool value) { mMenuClose = value; } + + // SelectionBarListener callback methods + double AS_GetRate() override; + void AS_SetRate(double rate) override; + int AS_GetSnapTo() override; + void AS_SetSnapTo(int snap) override; + const NumericFormatSymbol & AS_GetSelectionFormat() override; + void AS_SetSelectionFormat(const NumericFormatSymbol & format) override; + void AS_ModifySelection(double &start, double &end, bool done) override; + + // SpectralSelectionBarListener callback methods + double SSBL_GetRate() const override; + const NumericFormatSymbol & SSBL_GetFrequencySelectionFormatName() override; + void SSBL_SetFrequencySelectionFormatName( + const NumericFormatSymbol & formatName) override; + const NumericFormatSymbol & SSBL_GetBandwidthSelectionFormatName() override; + void SSBL_SetBandwidthSelectionFormatName( + const NumericFormatSymbol & formatName) override; + void SSBL_ModifySpectralSelection( + double &bottom, double &top, bool done) override; + +private: + void OnCloseWindow(wxCloseEvent & event); + void OnTimer(wxTimerEvent & event); + void OnOpenAudioFile(wxCommandEvent & event); + void OnStatusChange( wxCommandEvent& ); + + bool SnapSelection(); + + // Audio IO callback methods + void OnAudioIORate(int rate) override; + void OnAudioIOStartRecording() override; + void OnAudioIOStopRecording() override; + void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override; + + void InitialState(); + + void RestartTimer(); + // Declared in this class so that they can have access to private members static XMLTagHandler *RecordingRecoveryFactory( AudacityProject &project ); static ProjectFileIORegistry::Entry sRecoveryFactory; static XMLTagHandler *ImportHandlerFactory( AudacityProject &project ); static ProjectFileIORegistry::Entry sImportHandlerFactory; -public: - PlaybackScroller &GetPlaybackScroller() { return *mPlaybackScroller; } + // non-static data members + AudacityProject &mProject; + + // The handler that handles recovery of tags + std::unique_ptr mRecordingRecoveryHandler; + + std::unique_ptr mImportXMLTagHandler; + + std::unique_ptr mTimer; + + bool mDirty{ false }; + + // See explanation in OnCloseWindow + bool mIsBeingDeleted{ false }; + + // Are we currently closing as the result of a menu command? + bool mMenuClose{ false }; + + //flag for cancellation of timer record. + bool mTimerRecordCanceled{ false }; DECLARE_EVENT_TABLE() }; diff --git a/src/TimerRecordDialog.cpp b/src/TimerRecordDialog.cpp index 9adeed5a3..ec4ef1f88 100644 --- a/src/TimerRecordDialog.cpp +++ b/src/TimerRecordDialog.cpp @@ -417,9 +417,10 @@ void TimerRecordDialog::OnOK(wxCommandEvent& WXUNUSED(event)) // as its possible that they plan to free up some // space before the recording begins AudacityProject* pProject = GetActiveProject(); + auto &projectManager = ProjectManager::Get( *pProject ); // How many minutes do we have left on the disc? - int iMinsLeft = pProject->GetEstimatedRecordingMinsLeftOnDisk(); + int iMinsLeft = projectManager.GetEstimatedRecordingMinsLeftOnDisk(); // How many minutes will this recording require? int iMinsRecording = m_TimeSpan_Duration.GetMinutes(); @@ -429,9 +430,9 @@ void TimerRecordDialog::OnOK(wxCommandEvent& WXUNUSED(event)) // Format the strings wxString sRemainingTime; - sRemainingTime = pProject->GetHoursMinsString(iMinsLeft); + sRemainingTime = projectManager.GetHoursMinsString(iMinsLeft); wxString sPlannedTime; - sPlannedTime = pProject->GetHoursMinsString(iMinsRecording); + sPlannedTime = projectManager.GetHoursMinsString(iMinsRecording); // Create the message string wxString sMessage; diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index f250c0f7c..8798a2db0 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -610,7 +610,7 @@ void TrackPanel::OnPaint(wxPaintEvent & /* event */) void TrackPanel::MakeParentModifyState(bool bWantsAutoSave) { - GetProject()->ModifyState(bWantsAutoSave); + ProjectManager::Get( *GetProject() ).ModifyState(bWantsAutoSave); } void TrackPanel::MakeParentRedrawScrollbars() diff --git a/src/TrackPanelResizeHandle.cpp b/src/TrackPanelResizeHandle.cpp index 9485bb650..68d98cbd2 100644 --- a/src/TrackPanelResizeHandle.cpp +++ b/src/TrackPanelResizeHandle.cpp @@ -219,7 +219,7 @@ UIHandle::Result TrackPanelResizeHandle::Release /// We also modify the undo state (the action doesn't become /// undo-able, but it gets merged with the previous undo-able /// event). - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); return RefreshCode::FixScrollbars; } diff --git a/src/commands/ImportExportCommands.cpp b/src/commands/ImportExportCommands.cpp index 736e9de9f..0dcf4585d 100644 --- a/src/commands/ImportExportCommands.cpp +++ b/src/commands/ImportExportCommands.cpp @@ -41,7 +41,7 @@ void ImportCommand::PopulateOrExchange(ShuttleGui & S) } bool ImportCommand::Apply(const CommandContext & context){ - return context.project.Import(mFileName); + return ProjectManager::Get( context.project ).Import(mFileName); } diff --git a/src/commands/OpenSaveCommands.cpp b/src/commands/OpenSaveCommands.cpp index beebd54e1..e033f52e8 100644 --- a/src/commands/OpenSaveCommands.cpp +++ b/src/commands/OpenSaveCommands.cpp @@ -48,11 +48,12 @@ bool OpenProjectCommand::Apply(const CommandContext & context){ if(mFileName.empty()) { auto project = &context.project; - AudacityProject::OpenFiles(project); + ProjectManager::OpenFiles(project); } else { - context.project.OpenFile(mFileName, mbAddToHistory); + ProjectManager::Get( context.project ) + .OpenFile(mFileName, mbAddToHistory); } const auto &newFileName = context.project.GetFileName(); diff --git a/src/commands/SelectCommand.cpp b/src/commands/SelectCommand.cpp index b5860adfc..2d82a4dc8 100644 --- a/src/commands/SelectCommand.cpp +++ b/src/commands/SelectCommand.cpp @@ -165,7 +165,7 @@ bool SelectFrequenciesCommand::Apply(const CommandContext & context){ if( !bHasBottom ) mBottom = 0.0; - context.project.SSBL_ModifySpectralSelection( + ProjectManager::Get( context.project ).SSBL_ModifySpectralSelection( mBottom, mTop, false);// false for not done. return true; } diff --git a/src/effects/EffectRack.cpp b/src/effects/EffectRack.cpp index 7031fadec..92cf6a24b 100644 --- a/src/effects/EffectRack.cpp +++ b/src/effects/EffectRack.cpp @@ -297,7 +297,7 @@ void EffectRack::OnApply(wxCommandEvent & WXUNUSED(evt)) auto state = UndoManager::Get( *project ).GetCurrentState(); auto cleanup = finally( [&] { if(!success) - project->SetStateTo(state); + ProjectManager::Get( *project ).SetStateTo( state ); } ); for (size_t i = 0, cnt = mEffects.size(); i < cnt; i++) diff --git a/src/import/ImportLOF.cpp b/src/import/ImportLOF.cpp index ba6f41990..3895bb87d 100644 --- a/src/import/ImportLOF.cpp +++ b/src/import/ImportLOF.cpp @@ -385,7 +385,7 @@ void LOFImportFileHandle::lofOpenFiles(wxString* ln) * audio file. TODO: Some sort of message here? */ #endif // USE_MIDI - mProject = AudacityProject::OpenProject( mProject, targetfile ); + mProject = ProjectManager::OpenProject( mProject, targetfile ); // Set tok to right after filename temptok2.SetString(targettoken); @@ -440,7 +440,7 @@ void LOFImportFileHandle::lofOpenFiles(wxString* ln) } // Amend the undo transaction made by import - mProject->ModifyState(false); + ProjectManager::Get( *mProject ).ModifyState(false); } // end of converting "offset" argument else { @@ -484,7 +484,7 @@ void LOFImportFileHandle::doDurationAndScrollOffset() if (doSomething) // Amend last undo state - mProject->ModifyState(false); + ProjectManager::Get( *mProject ).ModifyState(false); } LOFImportFileHandle::~LOFImportFileHandle() diff --git a/src/menus/ClipMenus.cpp b/src/menus/ClipMenus.cpp index 46e85fcd4..ccb244b73 100644 --- a/src/menus/ClipMenus.cpp +++ b/src/menus/ClipMenus.cpp @@ -389,7 +389,7 @@ void DoSelectClipBoundary(AudacityProject &project, bool next) else selectedRegion.setT0(results[0].time); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); wxString message = ClipBoundaryMessage(results); @@ -572,7 +572,7 @@ void DoSelectClip(AudacityProject &project, bool next) double t0 = results[0].startTime; double t1 = results[0].endTime; selectedRegion.setTimes(t0, t1); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.ScrollIntoView(selectedRegion.t0()); trackPanel.Refresh(false); @@ -618,7 +618,7 @@ void DoCursorClipBoundary // value. double time = results[0].time; selectedRegion.setTimes(time, time); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.ScrollIntoView(selectedRegion.t0()); trackPanel.Refresh(false); @@ -720,7 +720,8 @@ void DoClipLeftOrRight // keypress (keydown, then keyup), and holding down a key // (multiple keydowns followed by a keyup) result in a single // entry in Audacity's history dialog. - project.PushState(message, _("Time-Shift"), UndoPush::CONSOLIDATE); + ProjectManager::Get( project ) + .PushState(message, _("Time-Shift"), UndoPush::CONSOLIDATE); } if ( amount == 0.0 ) diff --git a/src/menus/EditMenus.cpp b/src/menus/EditMenus.cpp index 043b5620b..90bf5827a 100644 --- a/src/menus/EditMenus.cpp +++ b/src/menus/EditMenus.cpp @@ -49,7 +49,8 @@ bool DoPasteText(AudacityProject &project) if (pLabelTrack->PasteSelectedText(selectedRegion.t0(), selectedRegion.t1())) { - project.PushState(_("Pasted text from the clipboard"), _("Paste")); + ProjectManager::Get( project ) + .PushState(_("Pasted text from the clipboard"), _("Paste")); // Make sure caret is in view int x; @@ -148,7 +149,8 @@ bool DoPasteNothingSelected(AudacityProject &project) // half a sample earlier quantT1 - quantT0); - project.PushState(_("Pasted from the clipboard"), _("Paste")); + ProjectManager::Get( project ) + .PushState(_("Pasted from the clipboard"), _("Paste")); window.RedrawProject(); @@ -216,7 +218,7 @@ bool DoEditMetadata if (tags != *newTags) { // Commit the change to project state only now. Tags::Set( project, newTags ); - project.PushState(title, shortUndoDescription); + ProjectManager::Get( project ).PushState(title, shortUndoDescription); } bool bShowInFuture; gPrefs->Read(wxT("/AudioFiles/ShowId3Dialog"), &bShowInFuture, true); @@ -233,7 +235,7 @@ void DoUndo(AudacityProject &project) auto &undoManager = UndoManager::Get( project ); auto &window = ProjectWindow::Get( project ); - if (!project.UndoAvailable()) { + if (!ProjectManager::Get( project ).UndoAvailable()) { AudacityMessageBox(_("Nothing to undo")); return; } @@ -244,7 +246,8 @@ void DoUndo(AudacityProject &project) } undoManager.Undo( - [&]( const UndoState &state ){ project.PopState( state ); } ); + [&]( const UndoState &state ){ + ProjectManager::Get( project ).PopState( state ); } ); trackPanel.EnsureVisible(trackPanel.GetFirstSelectedTrack()); @@ -269,7 +272,7 @@ void OnRedo(const CommandContext &context) auto &undoManager = UndoManager::Get( project ); auto &window = ProjectWindow::Get( project ); - if (!project.RedoAvailable()) { + if (!ProjectManager::Get( project ).RedoAvailable()) { AudacityMessageBox(_("Nothing to redo")); return; } @@ -279,7 +282,8 @@ void OnRedo(const CommandContext &context) } undoManager.Redo( - [&]( const UndoState &state ){ project.PopState( state ); } ); + [&]( const UndoState &state ){ + ProjectManager::Get( project ).PopState( state ); } ); trackPanel.EnsureVisible(trackPanel.GetFirstSelectedTrack()); @@ -366,7 +370,7 @@ void OnCut(const CommandContext &context) selectedRegion.collapseToT0(); - project.PushState(_("Cut to the clipboard"), _("Cut")); + ProjectManager::Get( project ).PushState(_("Cut to the clipboard"), _("Cut")); // Bug 1663 //mRuler->ClearPlayRegion(); @@ -392,7 +396,7 @@ void OnDelete(const CommandContext &context) selectedRegion.collapseToT0(); - project.PushState(wxString::Format(_("Deleted %.2f seconds at t=%.2f"), + ProjectManager::Get( project ).PushState(wxString::Format(_("Deleted %.2f seconds at t=%.2f"), seconds, selectedRegion.t0()), _("Delete")); @@ -692,7 +696,8 @@ void OnPaste(const CommandContext &context) { selectedRegion.setT1( t0 + clipboard.Duration() ); - project.PushState(_("Pasted from the clipboard"), _("Paste")); + ProjectManager::Get( project ) + .PushState(_("Pasted from the clipboard"), _("Paste")); window.RedrawProject(); @@ -724,7 +729,7 @@ void OnDuplicate(const CommandContext &context) break; } - project.PushState(_("Duplicated"), _("Duplicate")); + ProjectManager::Get( project ).PushState(_("Duplicated"), _("Duplicate")); window.RedrawProject(); } @@ -766,7 +771,7 @@ void OnSplitCut(const CommandContext &context) clipboard.Assign( std::move( newClipboard ), selectedRegion.t0(), selectedRegion.t1(), &project ); - project.PushState(_("Split-cut to the clipboard"), _("Split Cut")); + ProjectManager::Get( project ).PushState(_("Split-cut to the clipboard"), _("Split Cut")); window.RedrawProject(); } @@ -789,7 +794,7 @@ void OnSplitDelete(const CommandContext &context) } ); - project.PushState( + ProjectManager::Get( project ).PushState( wxString::Format(_("Split-deleted %.2f seconds at t=%.2f"), selectedRegion.duration(), selectedRegion.t0()), @@ -808,7 +813,7 @@ void OnSilence(const CommandContext &context) for ( auto n : tracks.Selected< AudioTrack >() ) n->Silence(selectedRegion.t0(), selectedRegion.t1()); - project.PushState( + ProjectManager::Get( project ).PushState( wxString::Format(_("Silenced selected tracks for %.2f seconds at %.2f"), selectedRegion.duration(), selectedRegion.t0()), @@ -841,7 +846,7 @@ void OnTrim(const CommandContext &context) } ); - project.PushState( + ProjectManager::Get( project ).PushState( wxString::Format( _("Trim selected audio tracks from %.2f seconds to %.2f seconds"), selectedRegion.t0(), selectedRegion.t1()), @@ -863,7 +868,7 @@ void OnSplit(const CommandContext &context) for (auto wt : tracks.Selected< WaveTrack >()) wt->Split( sel0, sel1 ); - project.PushState(_("Split"), _("Split")); + ProjectManager::Get( project ).PushState(_("Split"), _("Split")); trackPanel.Refresh(false); #if 0 //ANSWER-ME: Do we need to keep this commented out OnSplit() code? @@ -963,7 +968,8 @@ void OnSplitNew(const CommandContext &context) break; } - project.PushState(_("Split to new track"), _("Split New")); + ProjectManager::Get( project ) + .PushState(_("Split to new track"), _("Split New")); window.RedrawProject(); } @@ -979,7 +985,7 @@ void OnJoin(const CommandContext &context) wt->Join(selectedRegion.t0(), selectedRegion.t1()); - project.PushState( + ProjectManager::Get( project ).PushState( wxString::Format(_("Joined %.2f seconds at t=%.2f"), selectedRegion.duration(), selectedRegion.t0()), @@ -999,7 +1005,7 @@ void OnDisjoin(const CommandContext &context) wt->Disjoin(selectedRegion.t0(), selectedRegion.t1()); - project.PushState( + ProjectManager::Get( project ).PushState( wxString::Format(_("Detached %.2f seconds at t=%.2f"), selectedRegion.duration(), selectedRegion.t0()), diff --git a/src/menus/FileMenus.cpp b/src/menus/FileMenus.cpp index 7cba59f65..3940b4169 100644 --- a/src/menus/FileMenus.cpp +++ b/src/menus/FileMenus.cpp @@ -116,7 +116,7 @@ AudacityProject *DoImportMIDI( AudacityProject *pNewProject {}; if ( !pProject ) - pProject = pNewProject = CreateNewAudacityProject(); + pProject = pNewProject = ProjectManager::New(); auto cleanup = finally( [&] { if ( pNewProject ) GetProjectFrame( *pNewProject ).Close(true); } ); @@ -128,7 +128,8 @@ AudacityProject *DoImportMIDI( auto pTrack = tracks.Add( newTrack ); pTrack->SetSelected(true); - pProject->PushState(wxString::Format(_("Imported MIDI from '%s'"), + ProjectManager::Get( *pProject ) + .PushState(wxString::Format(_("Imported MIDI from '%s'"), fileName), _("Import MIDI")); ProjectWindow::Get( *pProject ).ZoomAfterImport(pTrack); @@ -151,13 +152,13 @@ struct Handler : CommandHandlerObject { void OnNew(const CommandContext & ) { - CreateNewAudacityProject(); + ( void ) ProjectManager::New(); } void OnOpen(const CommandContext &context ) { auto &project = context.project; - AudacityProject::OpenFiles(&project); + ProjectManager::OpenFiles(&project); } // JKC: This is like OnClose, except it emptys the project in place, @@ -168,14 +169,14 @@ void OnOpen(const CommandContext &context ) void OnProjectReset(const CommandContext &context) { auto &project = context.project; - project.ResetProjectToEmpty(); + ProjectManager::Get( project ).ResetProjectToEmpty(); } void OnClose(const CommandContext &context ) { auto &project = context.project; - auto &window = GetProjectFrame( project ); - project.SetMenuClose(true); + auto &window = ProjectWindow::Get( project ); + ProjectManager::Get( project ).SetMenuClose(true); window.Close(); } @@ -405,7 +406,7 @@ void OnImport(const CommandContext &context) // this serves to track the file if the users zooms in and such. MissingAliasFilesDialog::SetShouldShow(true); - wxArrayString selectedFiles = project.ShowOpenDialog(wxT("")); + wxArrayString selectedFiles = ProjectManager::ShowOpenDialog(wxT("")); if (selectedFiles.size() == 0) { gPrefs->Write(wxT("/LastOpenType"),wxT("")); gPrefs->Flush(); @@ -435,7 +436,7 @@ void OnImport(const CommandContext &context) FileNames::UpdateDefaultPath(FileNames::Operation::Open, fileName); - project.Import(fileName); + ProjectManager::Get( project ).Import(fileName); } window.ZoomAfterImport(nullptr); @@ -479,9 +480,9 @@ void OnImportLabels(const CommandContext &context) newTrack->SetSelected(true); tracks.Add( newTrack ); - project.PushState(wxString:: - Format(_("Imported labels from '%s'"), fileName), - _("Import Labels")); + ProjectManager::Get( project ).PushState( + wxString::Format(_("Imported labels from '%s'"), fileName), + _("Import Labels")); window.ZoomAfterImport(nullptr); } @@ -532,7 +533,7 @@ void OnImportRaw(const CommandContext &context) if (newTracks.size() <= 0) return; - project.AddImportedTracks(fileName, std::move(newTracks)); + ProjectManager::Get( project ).AddImportedTracks(fileName, std::move(newTracks)); window.HandleResize(); // Adjust scrollers for NEW track sizes. } diff --git a/src/menus/HelpMenus.cpp b/src/menus/HelpMenus.cpp index b25698f9e..4ad83ab39 100644 --- a/src/menus/HelpMenus.cpp +++ b/src/menus/HelpMenus.cpp @@ -251,7 +251,7 @@ void QuickFixDialog::OnFix(wxCommandEvent &event) // preference dialogs. if( Str == "/SnapTo" ) { - pProject->AS_SetSnapTo( 0 ); + ProjectManager::Get( *pProject ).AS_SetSnapTo( 0 ); } else { diff --git a/src/menus/LabelMenus.cpp b/src/menus/LabelMenus.cpp index 0dd22865d..aed8c9b47 100644 --- a/src/menus/LabelMenus.cpp +++ b/src/menus/LabelMenus.cpp @@ -71,7 +71,7 @@ int DoAddLabel( int index = lt->AddLabel(region, title, focusTrackNumber); - project.PushState(_("Added label"), _("Label")); + ProjectManager::Get( project ).PushState(_("Added label"), _("Label")); window.RedrawProject(); if (!useDialog) { @@ -336,7 +336,7 @@ void OnPasteNewLabel(const CommandContext &context) } if (bPastedSomething) { - project.PushState( + ProjectManager::Get( project ).PushState( _("Pasted from the clipboard"), _("Paste Text to New Label")); // Is this necessary? (carried over from former logic in OnPaste()) @@ -376,7 +376,7 @@ void OnCutLabels(const CommandContext &context) selectedRegion.collapseToT0(); - project.PushState( + ProjectManager::Get( project ).PushState( /* i18n-hint: (verb) past tense. Audacity has just cut the labeled audio regions.*/ _( "Cut labeled audio regions to clipboard" ), @@ -400,7 +400,7 @@ void OnDeleteLabels(const CommandContext &context) selectedRegion.collapseToT0(); - project.PushState( + ProjectManager::Get( project ).PushState( /* i18n-hint: (verb) Audacity has just deleted the labeled audio regions*/ _( "Deleted labeled audio regions" ), /* i18n-hint: (verb)*/ @@ -422,7 +422,7 @@ void OnSplitCutLabels(const CommandContext &context) EditClipboardByLabel( project, tracks, selectedRegion, &WaveTrack::SplitCut ); - project.PushState( + ProjectManager::Get( project ).PushState( /* i18n-hint: (verb) Audacity has just split cut the labeled audio regions*/ _( "Split Cut labeled audio regions to clipboard" ), @@ -444,7 +444,7 @@ void OnSplitDeleteLabels(const CommandContext &context) EditByLabel( tracks, selectedRegion, &WaveTrack::SplitDelete, false ); - project.PushState( + ProjectManager::Get( project ).PushState( /* i18n-hint: (verb) Audacity has just done a special kind of DELETE on the labeled audio regions */ _( "Split Deleted labeled audio regions" ), @@ -467,7 +467,7 @@ void OnSilenceLabels(const CommandContext &context) EditByLabel( tracks, selectedRegion, &WaveTrack::Silence, false ); - project.PushState( + ProjectManager::Get( project ).PushState( /* i18n-hint: (verb)*/ _( "Silenced labeled audio regions" ), /* i18n-hint: (verb)*/ @@ -489,7 +489,7 @@ void OnCopyLabels(const CommandContext &context) EditClipboardByLabel( project, tracks, selectedRegion, &WaveTrack::CopyNonconst ); - project.PushState( _( "Copied labeled audio regions to clipboard" ), + ProjectManager::Get( project ).PushState( _( "Copied labeled audio regions to clipboard" ), /* i18n-hint: (verb)*/ _( "Copy Labeled Audio" ) ); @@ -505,7 +505,7 @@ void OnSplitLabels(const CommandContext &context) EditByLabel( tracks, selectedRegion, &WaveTrack::Split, false ); - project.PushState( + ProjectManager::Get( project ).PushState( /* i18n-hint: (verb) past tense. Audacity has just split the labeled audio (a point or a region)*/ _( "Split labeled audio (points or regions)" ), @@ -527,7 +527,7 @@ void OnJoinLabels(const CommandContext &context) EditByLabel( tracks, selectedRegion, &WaveTrack::Join, false ); - project.PushState( + ProjectManager::Get( project ).PushState( /* i18n-hint: (verb) Audacity has just joined the labeled audio (points or regions) */ _( "Joined labeled audio (points or regions)" ), @@ -549,7 +549,7 @@ void OnDisjoinLabels(const CommandContext &context) EditByLabel( tracks, selectedRegion, &WaveTrack::Disjoin, false ); - project.PushState( + ProjectManager::Get( project ).PushState( /* i18n-hint: (verb) Audacity has just detached the labeled audio regions. This message appears in history and tells you about something Audacity has done.*/ diff --git a/src/menus/NavigationMenus.cpp b/src/menus/NavigationMenus.cpp index c1eaa41f9..ce6db3776 100644 --- a/src/menus/NavigationMenus.cpp +++ b/src/menus/NavigationMenus.cpp @@ -84,6 +84,7 @@ void NextOrPrevFrame(AudacityProject &project, bool forward) void DoPrevTrack( AudacityProject &project, bool shift, bool circularTrackNavigation ) { + auto &projectManager = ProjectManager::Get( project ); auto &trackPanel = TrackPanel::Get( project ); auto &tracks = TrackList::Get( project ); auto &selectionState = SelectionState::Get( project ); @@ -94,7 +95,7 @@ void DoPrevTrack( t = *tracks.Any().rbegin(); trackPanel.SetFocusedTrack( t ); trackPanel.EnsureVisible( t ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } @@ -126,7 +127,7 @@ void DoPrevTrack( ( *t, false, false ); trackPanel.SetFocusedTrack( p ); // move focus to next track up trackPanel.EnsureVisible( p ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } if( tSelected && !pSelected ) @@ -135,7 +136,7 @@ void DoPrevTrack( ( *p, true, false ); trackPanel.SetFocusedTrack( p ); // move focus to next track up trackPanel.EnsureVisible( p ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } if( !tSelected && pSelected ) @@ -144,7 +145,7 @@ void DoPrevTrack( ( *p, false, false ); trackPanel.SetFocusedTrack( p ); // move focus to next track up trackPanel.EnsureVisible( p ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } if( !tSelected && !pSelected ) @@ -153,7 +154,7 @@ void DoPrevTrack( ( *t, true, false ); trackPanel.SetFocusedTrack( p ); // move focus to next track up trackPanel.EnsureVisible( p ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } } @@ -169,7 +170,7 @@ void DoPrevTrack( p = * range.rbegin(); // null if range is empty trackPanel.SetFocusedTrack( p ); // Wrap to the last track trackPanel.EnsureVisible( p ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } else @@ -182,7 +183,7 @@ void DoPrevTrack( { trackPanel.SetFocusedTrack( p ); // move focus to next track up trackPanel.EnsureVisible( p ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } } @@ -194,6 +195,7 @@ void DoPrevTrack( void DoNextTrack( AudacityProject &project, bool shift, bool circularTrackNavigation ) { + auto &projectManager = ProjectManager::Get( project ); auto &trackPanel = TrackPanel::Get( project ); auto &tracks = TrackList::Get( project ); auto &selectionState = SelectionState::Get( project ); @@ -204,7 +206,7 @@ void DoNextTrack( t = *tracks.Any().begin(); trackPanel.SetFocusedTrack( t ); trackPanel.EnsureVisible( t ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } @@ -230,7 +232,7 @@ void DoNextTrack( ( *t, false, false ); trackPanel.SetFocusedTrack( n ); // move focus to next track down trackPanel.EnsureVisible( n ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } if( tSelected && !nSelected ) @@ -239,7 +241,7 @@ void DoNextTrack( ( *n, true, false ); trackPanel.SetFocusedTrack( n ); // move focus to next track down trackPanel.EnsureVisible( n ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } if( !tSelected && nSelected ) @@ -248,7 +250,7 @@ void DoNextTrack( ( *n, false, false ); trackPanel.SetFocusedTrack( n ); // move focus to next track down trackPanel.EnsureVisible( n ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } if( !tSelected && !nSelected ) @@ -257,7 +259,7 @@ void DoNextTrack( ( *t, true, false ); trackPanel.SetFocusedTrack( n ); // move focus to next track down trackPanel.EnsureVisible( n ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } } @@ -272,7 +274,7 @@ void DoNextTrack( n = *tracks.Any().begin(); trackPanel.SetFocusedTrack( n ); // Wrap to the first track trackPanel.EnsureVisible( n ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } else @@ -285,7 +287,7 @@ void DoNextTrack( { trackPanel.SetFocusedTrack( n ); // move focus to next track down trackPanel.EnsureVisible( n ); - project.ModifyState(false); + projectManager.ModifyState(false); return; } } @@ -470,7 +472,7 @@ void OnFirstTrack(const CommandContext &context) if (t != f) { trackPanel.SetFocusedTrack(f); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } trackPanel.EnsureVisible(f); } @@ -489,7 +491,7 @@ void OnLastTrack(const CommandContext &context) if (t != l) { trackPanel.SetFocusedTrack(l); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } trackPanel.EnsureVisible(l); } @@ -521,7 +523,7 @@ void OnToggle(const CommandContext &context) selectionState.SelectTrack ( *t, !t->GetSelected(), true ); trackPanel.EnsureVisible( t ); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.GetAx().Updated(); diff --git a/src/menus/PluginMenus.cpp b/src/menus/PluginMenus.cpp index b04f1116f..f056d6678 100644 --- a/src/menus/PluginMenus.cpp +++ b/src/menus/PluginMenus.cpp @@ -493,7 +493,7 @@ bool DoEffect( { wxString shortDesc = em.GetCommandName(ID); wxString longDesc = em.GetCommandDescription(ID); - project.PushState(longDesc, shortDesc); + ProjectManager::Get( project ).PushState(longDesc, shortDesc); } if (!(flags & kDontRepeatLast)) diff --git a/src/menus/SelectMenus.cpp b/src/menus/SelectMenus.cpp index d2c978253..3022ed2dc 100644 --- a/src/menus/SelectMenus.cpp +++ b/src/menus/SelectMenus.cpp @@ -38,7 +38,7 @@ void DoSelectTimeAndTracks for (auto t : tracks.Any()) t->SetSelected(true); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } } @@ -63,7 +63,7 @@ void DoSelectTimeAndAudioTracks for (auto t : tracks.Any()) t->SetSelected(true); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } } @@ -88,7 +88,7 @@ void DoNextPeakFrequency(AudacityProject &project, bool up) SpectrumAnalyst analyst; SelectHandle::SnapCenterOnce(analyst, viewInfo, pTrack, up); trackPanel.Refresh(false); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } } @@ -179,7 +179,7 @@ bool OnlyHandleKeyUp( const CommandContext &context ) if( !bKeyUp ) return false; - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); return true; } @@ -420,7 +420,7 @@ void DoCursorMove( MoveWhenAudioInactive(project, seekStep, TIME_UNIT_SECONDS); } - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } void DoBoundaryMove(AudacityProject &project, int step, SeekInfo &info) @@ -454,7 +454,7 @@ void DoBoundaryMove(AudacityProject &project, int step, SeekInfo &info) else viewInfo.selectedRegion.setT1(indicator); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); return; } @@ -483,7 +483,7 @@ void DoBoundaryMove(AudacityProject &project, int step, SeekInfo &info) trackPanel.ScrollIntoView(newT); trackPanel.Refresh(false); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } } @@ -533,7 +533,7 @@ void DoListSelection trackPanel.SetFocusedTrack(t); window.Refresh(false); if (modifyState) - project.ModifyState(true); + ProjectManager::Get( project ).ModifyState(true); } void DoSelectAll(AudacityProject &project) @@ -583,7 +583,7 @@ void OnSelectNone(const CommandContext &context) selectedRegion.collapseToT0(); SelectNone( project ); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } void OnSelectAllTracks(const CommandContext &context) @@ -606,7 +606,7 @@ void OnSelectSyncLockSel(const CommandContext &context) } if (selected) - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } @@ -649,7 +649,7 @@ void OnSetLeftSelection(const CommandContext &context) if (bSelChanged) { - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } } @@ -689,7 +689,7 @@ void OnSetRightSelection(const CommandContext &context) if (bSelChanged) { - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } } @@ -715,7 +715,7 @@ void OnSelectStartCursor(const CommandContext &context) selectedRegion.setT0(minOffset); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } @@ -741,7 +741,7 @@ void OnSelectCursorEnd(const CommandContext &context) selectedRegion.setT1(maxEndOffset); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } @@ -761,7 +761,7 @@ void OnSelectTrackStartToEnd(const CommandContext &context) return; viewInfo.selectedRegion.setTimes( minOffset, maxEndOffset ); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } @@ -789,7 +789,7 @@ void OnSelectionRestore(const CommandContext &context) selectedRegion = mRegionSave; - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } @@ -822,7 +822,7 @@ void OnToggleSpectralSelection(const CommandContext &context) selectedRegion.setFrequencies(mLastF0, mLastF1); trackPanel.Refresh(false); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } void OnNextHigherPeakFrequency(const CommandContext &context) @@ -857,7 +857,7 @@ void OnSelectCursorStoredCursor(const CommandContext &context) std::min(cursorPositionCurrent, mCursorPositionStored), std::max(cursorPositionCurrent, mCursorPositionStored)); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } } @@ -890,7 +890,7 @@ void OnZeroCrossing(const CommandContext &context) selectedRegion.setTimes(t0, t1); } - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.Refresh(false); } @@ -898,19 +898,19 @@ void OnZeroCrossing(const CommandContext &context) void OnSnapToOff(const CommandContext &context) { auto &project = context.project; - project.AS_SetSnapTo(SNAP_OFF); + ProjectManager::Get( project ).AS_SetSnapTo(SNAP_OFF); } void OnSnapToNearest(const CommandContext &context) { auto &project = context.project; - project.AS_SetSnapTo(SNAP_NEAREST); + ProjectManager::Get( project ).AS_SetSnapTo(SNAP_NEAREST); } void OnSnapToPrior(const CommandContext &context) { auto &project = context.project; - project.AS_SetSnapTo(SNAP_PRIOR); + ProjectManager::Get( project ).AS_SetSnapTo(SNAP_PRIOR); } void OnSelToStart(const CommandContext &context) @@ -918,7 +918,7 @@ void OnSelToStart(const CommandContext &context) auto &project = context.project; auto &window = ProjectWindow::Get( project ); window.Rewind(true); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } void OnSelToEnd(const CommandContext &context) @@ -926,7 +926,7 @@ void OnSelToEnd(const CommandContext &context) auto &project = context.project; auto &window = ProjectWindow::Get( project ); window.SkipEnd(true); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } // Handler state: @@ -977,7 +977,7 @@ void OnCursorSelStart(const CommandContext &context) auto &selectedRegion = ViewInfo::Get( project ).selectedRegion; selectedRegion.collapseToT0(); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.ScrollIntoView(selectedRegion.t0()); trackPanel.Refresh(false); } @@ -989,7 +989,7 @@ void OnCursorSelEnd(const CommandContext &context) auto &selectedRegion = ViewInfo::Get( project ).selectedRegion; selectedRegion.collapseToT1(); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.ScrollIntoView(selectedRegion.t1()); trackPanel.Refresh(false); } @@ -1016,7 +1016,7 @@ void OnCursorTrackStart(const CommandContext &context) return; selectedRegion.setTimes(minOffset, minOffset); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.ScrollIntoView(selectedRegion.t0()); trackPanel.Refresh(false); } @@ -1043,7 +1043,7 @@ void OnCursorTrackEnd(const CommandContext &context) return; selectedRegion.setTimes(maxEndOffset, maxEndOffset); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); trackPanel.ScrollIntoView(selectedRegion.t1()); trackPanel.Refresh(false); } @@ -1055,7 +1055,7 @@ void OnSkipStart(const CommandContext &context) auto &controlToolBar = ControlToolBar::Get( project ); controlToolBar.OnRewind(evt); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } void OnSkipEnd(const CommandContext &context) @@ -1065,7 +1065,7 @@ void OnSkipEnd(const CommandContext &context) auto &controlToolBar = ControlToolBar::Get( project ); controlToolBar.OnFF(evt); - project.ModifyState(false); + ProjectManager::Get( project ).ModifyState(false); } void OnCursorLeft(const CommandContext &context) diff --git a/src/menus/TrackMenus.cpp b/src/menus/TrackMenus.cpp index e2c782725..5e0f3257b 100644 --- a/src/menus/TrackMenus.cpp +++ b/src/menus/TrackMenus.cpp @@ -91,7 +91,7 @@ void DoMixAndRender msg.Printf(_("Rendered all audio in track '%s'"), firstName); /* i18n-hint: Convert the audio into a more usable form, so apply * panning and amplification and write to some external file.*/ - project.PushState(msg, _("Render")); + ProjectManager::Get( project ).PushState(msg, _("Render")); } else { wxString msg; @@ -103,7 +103,7 @@ void DoMixAndRender msg.Printf( _("Mixed and rendered %d tracks into one new mono track"), (int)selectedCount); - project.PushState(msg, _("Mix and Render")); + ProjectManager::Get( project ).PushState(msg, _("Mix and Render")); } trackPanel.SetFocus(); @@ -131,7 +131,8 @@ void DoPanTracks(AudacityProject &project, float PanValue) auto flags = UndoPush::AUTOSAVE; /*i18n-hint: One or more audio tracks have been panned*/ - project.PushState(_("Panned audio track(s)"), _("Pan Track"), flags); + ProjectManager::Get( project ) + .PushState(_("Panned audio track(s)"), _("Pan Track"), flags); flags = flags | UndoPush::CONSOLIDATE; } @@ -292,7 +293,7 @@ void DoAlign if (moveSel) selectedRegion.move(delta); - project.PushState(action, shortAction); + ProjectManager::Get( project ).PushState(action, shortAction); window.RedrawProject(); } @@ -537,7 +538,8 @@ void SetTrackGain(AudacityProject &project, WaveTrack * wt, LWSlider * slider) for (auto channel : TrackList::Channels(wt)) channel->SetGain(newValue); - project.PushState(_("Adjusted gain"), _("Gain"), UndoPush::CONSOLIDATE); + ProjectManager::Get( project ) + .PushState(_("Adjusted gain"), _("Gain"), UndoPush::CONSOLIDATE); TrackPanel::Get( project ).RefreshTrack(wt); } @@ -550,7 +552,8 @@ void SetTrackPan(AudacityProject &project, WaveTrack * wt, LWSlider * slider) for (auto channel : TrackList::Channels(wt)) channel->SetPan(newValue); - project.PushState(_("Adjusted Pan"), _("Pan"), UndoPush::CONSOLIDATE); + ProjectManager::Get( project ) + .PushState(_("Adjusted Pan"), _("Pan"), UndoPush::CONSOLIDATE); TrackPanel::Get( project ).RefreshTrack(wt); } @@ -595,7 +598,8 @@ void DoRemoveTracks( AudacityProject &project ) if (f) trackPanel.EnsureVisible(f); - project.PushState(_("Removed audio track(s)"), _("Remove Track")); + ProjectManager::Get( project ) + .PushState(_("Removed audio track(s)"), _("Remove Track")); trackPanel.UpdateViewIfNoTracks(); trackPanel.Refresh(false); @@ -645,7 +649,7 @@ void DoTrackMute(AudacityProject &project, Track *t, bool exclusive) track->SetSolo( (nPlaying==1) && (nPlayableTracks > 1 ) && !track->GetMute() ); } } - project.ModifyState(true); + ProjectManager::Get( project ).ModifyState(true); trackPanel.UpdateAccessibility(); trackPanel.Refresh(false); @@ -698,7 +702,7 @@ void DoTrackSolo(AudacityProject &project, Track *t, bool exclusive) } } } - project.ModifyState(true); + ProjectManager::Get( project ).ModifyState(true); trackPanel.UpdateAccessibility(); trackPanel.Refresh(false); @@ -734,7 +738,7 @@ void DoRemoveTrack(AudacityProject &project, Track * toRemove) if (toRemoveWasFocused) trackPanel.SetFocusedTrack(newFocus); - project.PushState( + ProjectManager::Get( project ).PushState( wxString::Format(_("Removed track '%s.'"), name), _("Track Remove")); @@ -793,7 +797,7 @@ void DoMoveTrack longDesc = longDesc.Format(target->GetName()); - project.PushState(longDesc, shortDesc); + ProjectManager::Get( project ).PushState(longDesc, shortDesc); trackPanel.Refresh(false); } @@ -818,7 +822,8 @@ void OnNewWaveTrack(const CommandContext &context) t->SetSelected(true); - project.PushState(_("Created new audio track"), _("New Track")); + ProjectManager::Get( project ) + .PushState(_("Created new audio track"), _("New Track")); window.RedrawProject(); trackPanel.EnsureVisible(t); @@ -846,7 +851,8 @@ void OnNewStereoTrack(const CommandContext &context) tracks.GroupChannels(*left, 2); - project.PushState(_("Created new stereo audio track"), _("New Track")); + ProjectManager::Get( project ) + .PushState(_("Created new stereo audio track"), _("New Track")); window.RedrawProject(); trackPanel.EnsureVisible(left); @@ -866,7 +872,8 @@ void OnNewLabelTrack(const CommandContext &context) t->SetSelected(true); - project.PushState(_("Created new label track"), _("New Track")); + ProjectManager::Get( project ) + .PushState(_("Created new label track"), _("New Track")); window.RedrawProject(); trackPanel.EnsureVisible(t); @@ -891,7 +898,8 @@ void OnNewTimeTrack(const CommandContext &context) t->SetSelected(true); - project.PushState(_("Created new time track"), _("New Track")); + ProjectManager::Get( project ) + .PushState(_("Created new time track"), _("New Track")); window.RedrawProject(); trackPanel.EnsureVisible(t); @@ -1013,7 +1021,7 @@ void OnResample(const CommandContext &context) // commit that to the undo stack. The second and later times, // consolidate. - project.PushState( + ProjectManager::Get( project ).PushState( _("Resampled audio track(s)"), _("Resample Track"), flags); flags = flags | UndoPush::CONSOLIDATE; } @@ -1047,7 +1055,7 @@ void OnMuteAllTracks(const CommandContext &context) pt->SetSolo(false); } - project.ModifyState(true); + ProjectManager::Get( project ).ModifyState(true); window.RedrawProject(); } @@ -1068,7 +1076,7 @@ void OnUnmuteAllTracks(const CommandContext &context) pt->SetSolo(false); } - project.ModifyState(true); + ProjectManager::Get( project ).ModifyState(true); window.RedrawProject(); } @@ -1252,7 +1260,8 @@ void OnSortTime(const CommandContext &context) auto &project = context.project; DoSortTracks(project, kAudacitySortByTime); - project.PushState(_("Tracks sorted by time"), _("Sort by Time")); + ProjectManager::Get( project ) + .PushState(_("Tracks sorted by time"), _("Sort by Time")); auto &trackPanel = TrackPanel::Get( project ); trackPanel.Refresh(false); @@ -1263,7 +1272,8 @@ void OnSortName(const CommandContext &context) auto &project = context.project; DoSortTracks(project, kAudacitySortByName); - project.PushState(_("Tracks sorted by name"), _("Sort by Name")); + ProjectManager::Get( project ) + .PushState(_("Tracks sorted by name"), _("Sort by Name")); auto &trackPanel = TrackPanel::Get( project ); trackPanel.Refresh(false); diff --git a/src/menus/TransportMenus.cpp b/src/menus/TransportMenus.cpp index aadbec15b..c599c0b5f 100644 --- a/src/menus/TransportMenus.cpp +++ b/src/menus/TransportMenus.cpp @@ -258,7 +258,7 @@ bool DoPlayStopSelect // -- change t0, collapsing to point only if t1 was greater selection.setT0(time, false); - project.ModifyState(false); // without bWantsAutoSave + ProjectManager::Get( project ).ModifyState(false); // without bWantsAutoSave return true; } return false; @@ -459,7 +459,7 @@ void OnTimerRecord(const CommandContext &context) switch (iTimerRecordingOutcome) { case POST_TIMER_RECORD_CANCEL_WAIT: // Canceled on the wait dialog - project.RollbackState(); + ProjectManager::Get( project ).RollbackState(); break; case POST_TIMER_RECORD_CANCEL: // RunWaitDialog() shows the "wait for start" as well as "recording" @@ -468,7 +468,7 @@ void OnTimerRecord(const CommandContext &context) // However, we can't undo it here because the PushState() is called in TrackPanel::OnTimer(), // which is blocked by this function. // so instead we mark a flag to undo it there. - project.SetTimerRecordCancelled(); + ProjectManager::Get( project ).SetTimerRecordCancelled(); break; case POST_TIMER_RECORD_NOTHING: // No action required @@ -624,7 +624,7 @@ void OnPunchAndRoll(const CommandContext &context) ; else // Roll back the deletions - project.RollbackState(); + ProjectManager::Get( project ).RollbackState(); } #endif diff --git a/src/menus/ViewMenus.cpp b/src/menus/ViewMenus.cpp index 7740bfa61..5de1147ab 100644 --- a/src/menus/ViewMenus.cpp +++ b/src/menus/ViewMenus.cpp @@ -280,7 +280,7 @@ void OnZoomFitV(const CommandContext &context) window.GetVerticalScrollBar().SetThumbPosition(0); window.RedrawProject(); - project.ModifyState(true); + ProjectManager::Get( project ).ModifyState(true); } void OnAdvancedVZoom(const CommandContext &context) @@ -304,7 +304,7 @@ void OnCollapseAllTracks(const CommandContext &context) for (auto t : tracks.Any()) t->SetMinimized(true); - project.ModifyState(true); + ProjectManager::Get( project ).ModifyState(true); window.RedrawProject(); } @@ -317,7 +317,7 @@ void OnExpandAllTracks(const CommandContext &context) for (auto t : tracks.Any()) t->SetMinimized(false); - project.ModifyState(true); + ProjectManager::Get( project ).ModifyState(true); window.RedrawProject(); } diff --git a/src/tracks/labeltrack/ui/LabelGlyphHandle.cpp b/src/tracks/labeltrack/ui/LabelGlyphHandle.cpp index a9e9cdbb1..2c6cf09f0 100644 --- a/src/tracks/labeltrack/ui/LabelGlyphHandle.cpp +++ b/src/tracks/labeltrack/ui/LabelGlyphHandle.cpp @@ -141,7 +141,7 @@ UIHandle::Result LabelGlyphHandle::Release auto &viewInfo = ViewInfo::Get( *pProject ); if (mpLT->HandleGlyphDragRelease (mHit, event, mRect, viewInfo, &viewInfo.selectedRegion)) { - pProject->PushState(_("Modified Label"), + ProjectManager::Get( *pProject ).PushState(_("Modified Label"), _("Label Edit"), UndoPush::CONSOLIDATE); } @@ -152,7 +152,7 @@ UIHandle::Result LabelGlyphHandle::Release UIHandle::Result LabelGlyphHandle::Cancel(AudacityProject *pProject) { - pProject->RollbackState(); + ProjectManager::Get( *pProject ).RollbackState(); auto result = LabelDefaultClickHandle::Cancel( pProject ); return result | RefreshCode::RefreshAll; } diff --git a/src/tracks/labeltrack/ui/LabelTextHandle.cpp b/src/tracks/labeltrack/ui/LabelTextHandle.cpp index 6f2a32bfc..5c913e13d 100644 --- a/src/tracks/labeltrack/ui/LabelTextHandle.cpp +++ b/src/tracks/labeltrack/ui/LabelTextHandle.cpp @@ -110,7 +110,7 @@ UIHandle::Result LabelTextHandle::Click // PRL: bug1659 -- make selection change undo correctly const bool unsafe = ProjectAudioIO::Get( *pProject ).IsAudioActive(); if (!unsafe) - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); return result | RefreshCode::RefreshCell | RefreshCode::UpdateSelection; } diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp index 7ff878576..94940c92a 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp @@ -102,7 +102,7 @@ UIHandle::Result NoteTrackButtonHandle::Release if (pTrack->LabelClick(mRect, event.m_x, event.m_y, event.Button(wxMOUSE_BTN_RIGHT))) { // No undo items needed?? - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); return RefreshAll; } return RefreshNone; diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp index 03576ac6d..0c4534309 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackControls.cpp @@ -116,7 +116,8 @@ void NoteTrackMenuTable::OnChangeOctave(wxCommandEvent &event) pTrack->ShiftNoteRange((bDown) ? -12 : 12); AudacityProject *const project = ::GetActiveProject(); - project->ModifyState(false); + ProjectManager::Get( *project ) + .ModifyState(false); mpData->result = RefreshCode::RefreshAll; } diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp index 3bfcb7777..af51686fa 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp @@ -60,7 +60,9 @@ UIHandle::Result VelocitySliderHandle::SetValue UIHandle::Result VelocitySliderHandle::CommitChanges (const wxMouseEvent &, AudacityProject *pProject) { - pProject->PushState(_("Moved velocity slider"), _("Velocity"), UndoPush::CONSOLIDATE); + ProjectManager::Get( *pProject ) + .PushState(_("Moved velocity slider"), _("Velocity"), + UndoPush::CONSOLIDATE); return RefreshCode::RefreshCell; } diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackVRulerControls.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackVRulerControls.cpp index 09f4556c5..d3dd7187a 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackVRulerControls.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackVRulerControls.cpp @@ -81,7 +81,7 @@ unsigned NoteTrackVRulerControls::HandleWheelRotation return RefreshNone; } - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); return RefreshCell | UpdateVRuler; } diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp index 0f0ed8c91..a89ad6b82 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackVZoomHandle.cpp @@ -240,7 +240,7 @@ void NoteTrackVRulerMenuTable::OnZoom( int iZoomCode ){ mpData->pTrack->ShiftNoteRange(-12); break; } - GetActiveProject()->ModifyState(false); + ProjectManager::Get( *GetActiveProject() ).ModifyState(false); using namespace RefreshCode; mpData->result = UpdateVRuler | RefreshAll; } @@ -341,7 +341,7 @@ UIHandle::Result NoteTrackVZoomHandle::Release } mZoomEnd = mZoomStart = 0; - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); return RefreshAll; } diff --git a/src/tracks/playabletrack/notetrack/ui/StretchHandle.cpp b/src/tracks/playabletrack/notetrack/ui/StretchHandle.cpp index f229b1be9..12b3946f9 100644 --- a/src/tracks/playabletrack/notetrack/ui/StretchHandle.cpp +++ b/src/tracks/playabletrack/notetrack/ui/StretchHandle.cpp @@ -252,7 +252,7 @@ UIHandle::Result StretchHandle::Release /* i18n-hint: (noun) The track that is used for MIDI notes which can be dragged to change their duration.*/ - pProject->PushState(_("Stretch Note Track"), + ProjectManager::Get( *pProject ).PushState(_("Stretch Note Track"), /* i18n-hint: In the history list, indicates a MIDI note has been dragged to change its duration (stretch it). Using either past or present tense is fine here. If unsure, go for whichever is @@ -264,7 +264,7 @@ UIHandle::Result StretchHandle::Release UIHandle::Result StretchHandle::Cancel(AudacityProject *pProject) { - pProject->RollbackState(); + ProjectManager::Get( *pProject ).RollbackState(); return RefreshCode::RefreshNone; } diff --git a/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.cpp b/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.cpp index dac9213a8..8c2a9ab42 100644 --- a/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/CutlineHandle.cpp @@ -220,19 +220,21 @@ UIHandle::Result CutlineHandle::Release UIHandle::Result result = RefreshCode::RefreshNone; // Only now commit the result to the undo stack - AudacityProject *const project = pProject; switch (mOperation) { default: wxASSERT(false); case Merge: - project->PushState(_("Merged Clips"), _("Merge"), UndoPush::CONSOLIDATE); + ProjectManager::Get( *pProject ) + .PushState(_("Merged Clips"), _("Merge"), UndoPush::CONSOLIDATE); break; case Expand: - project->PushState(_("Expanded Cut Line"), _("Expand")); + ProjectManager::Get( *pProject ) + .PushState(_("Expanded Cut Line"), _("Expand")); result |= RefreshCode::UpdateSelection; break; case Remove: - project->PushState(_("Removed Cut Line"), _("Remove")); + ProjectManager::Get( *pProject ) + .PushState(_("Removed Cut Line"), _("Remove")); break; } @@ -244,7 +246,7 @@ UIHandle::Result CutlineHandle::Cancel(AudacityProject *pProject) { using namespace RefreshCode; UIHandle::Result result = RefreshCell; - pProject->RollbackState(); + ProjectManager::Get( *pProject ).RollbackState(); if (mOperation == Expand) { AudacityProject &project = *pProject; auto &selectedRegion = ViewInfo::Get( project ).selectedRegion; diff --git a/src/tracks/playabletrack/wavetrack/ui/SampleHandle.cpp b/src/tracks/playabletrack/wavetrack/ui/SampleHandle.cpp index 0fae1505f..00a8dd0ab 100644 --- a/src/tracks/playabletrack/wavetrack/ui/SampleHandle.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/SampleHandle.cpp @@ -434,7 +434,7 @@ UIHandle::Result SampleHandle::Release //************************************************* //On up-click, send the state to the undo stack mClickedTrack.reset(); //Set this to NULL so it will catch improper drag events. - pProject->PushState(_("Moved Samples"), + ProjectManager::Get( *pProject ).PushState(_("Moved Samples"), _("Sample Edit"), UndoPush::CONSOLIDATE | UndoPush::AUTOSAVE); @@ -444,7 +444,7 @@ UIHandle::Result SampleHandle::Release UIHandle::Result SampleHandle::Cancel(AudacityProject *pProject) { - pProject->RollbackState(); + ProjectManager::Get( *pProject ).RollbackState(); mClickedTrack.reset(); return RefreshCode::RefreshCell; } diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp index db6126d5a..7242dafca 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp @@ -219,7 +219,8 @@ void WaveColorMenuTable::OnWaveColorChange(wxCommandEvent & event) for (auto channel : TrackList::Channels(pTrack)) channel->SetWaveColorIndex(newWaveColor); - project->PushState(wxString::Format(_("Changed '%s' to %s"), + ProjectManager::Get( *project ) + .PushState(wxString::Format(_("Changed '%s' to %s"), pTrack->GetName(), GetWaveColorStr(newWaveColor)), _("WaveColor Change")); @@ -337,7 +338,8 @@ void FormatMenuTable::OnFormatChange(wxCommandEvent & event) channel->ConvertToSampleFormat(newFormat); /* i18n-hint: The strings name a track and a format */ - project->PushState(wxString::Format(_("Changed '%s' to %s"), + ProjectManager::Get( *project ) + .PushState(wxString::Format(_("Changed '%s' to %s"), pTrack->GetName(), GetSampleFormatStr(newFormat)), _("Format Change")); @@ -438,7 +440,8 @@ void RateMenuTable::SetRate(WaveTrack * pTrack, double rate) // Separate conversion of "rate" enables changing the decimals without affecting i18n wxString rateString = wxString::Format(wxT("%.3f"), rate); /* i18n-hint: The string names a track */ - project->PushState(wxString::Format(_("Changed '%s' to %s Hz"), + ProjectManager::Get( *project ) + .PushState(wxString::Format(_("Changed '%s' to %s Hz"), pTrack->GetName(), rateString), _("Rate Change")); } @@ -739,7 +742,7 @@ void WaveTrackMenuTable::OnSetDisplay(wxCommandEvent & event) } AudacityProject *const project = ::GetActiveProject(); - project->ModifyState(true); + ProjectManager::Get( *project ).ModifyState(true); using namespace RefreshCode; mpData->result = RefreshAll | UpdateVRuler; @@ -794,7 +797,7 @@ void WaveTrackMenuTable::OnSpectrogramSettings(wxCommandEvent &) if (0 != dialog.ShowModal()) { // Redraw AudacityProject *const project = ::GetActiveProject(); - project->ModifyState(true); + ProjectManager::Get( *project ).ModifyState(true); //Bug 1725 Toolbar was left greyed out. //This solution is overkill, but does fix the problem and is what the //prefs dialog normally does. @@ -880,7 +883,8 @@ void WaveTrackMenuTable::OnMergeStereo(wxCommandEvent &) } /* i18n-hint: The string names a track */ - project->PushState(wxString::Format(_("Made '%s' a stereo track"), + ProjectManager::Get( *project ) + .PushState(wxString::Format(_("Made '%s' a stereo track"), pTrack->GetName()), _("Make Stereo")); @@ -948,7 +952,8 @@ void WaveTrackMenuTable::OnSwapChannels(wxCommandEvent &) trackPanel.SetFocusedTrack(partner); /* i18n-hint: The string names a track */ - project->PushState(wxString::Format(_("Swapped Channels in '%s'"), + ProjectManager::Get( *project ) + .PushState(wxString::Format(_("Swapped Channels in '%s'"), pTrack->GetName()), _("Swap Channels")); @@ -962,7 +967,8 @@ void WaveTrackMenuTable::OnSplitStereo(wxCommandEvent &) WaveTrack *const pTrack = static_cast(mpData->pTrack); AudacityProject *const project = ::GetActiveProject(); /* i18n-hint: The string names a track */ - project->PushState(wxString::Format(_("Split stereo track '%s'"), + ProjectManager::Get( *project ) + .PushState(wxString::Format(_("Split stereo track '%s'"), pTrack->GetName()), _("Split")); @@ -977,7 +983,8 @@ void WaveTrackMenuTable::OnSplitStereoMono(wxCommandEvent &) WaveTrack *const pTrack = static_cast(mpData->pTrack); AudacityProject *const project = ::GetActiveProject(); /* i18n-hint: The string names a track */ - project->PushState(wxString::Format(_("Split Stereo to Mono '%s'"), + ProjectManager::Get( *project ). + PushState(wxString::Format(_("Split Stereo to Mono '%s'"), pTrack->GetName()), _("Split to Mono")); diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp index 7cd0279fe..557d9acf6 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp @@ -57,7 +57,8 @@ UIHandle::Result GainSliderHandle::SetValue UIHandle::Result GainSliderHandle::CommitChanges (const wxMouseEvent &, AudacityProject *pProject) { - pProject->PushState(_("Moved gain slider"), _("Gain"), UndoPush::CONSOLIDATE); + ProjectManager::Get( *pProject ) + .PushState(_("Moved gain slider"), _("Gain"), UndoPush::CONSOLIDATE); return RefreshCode::RefreshCell; } @@ -135,7 +136,8 @@ UIHandle::Result PanSliderHandle::SetValue(AudacityProject *pProject, float newV UIHandle::Result PanSliderHandle::CommitChanges (const wxMouseEvent &, AudacityProject *pProject) { - pProject->PushState(_("Moved pan slider"), _("Pan"), UndoPush::CONSOLIDATE); + ProjectManager::Get( *pProject ) + .PushState(_("Moved pan slider"), _("Pan"), UndoPush::CONSOLIDATE); return RefreshCode::RefreshCell; } diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackVRulerControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackVRulerControls.cpp index 1708c65ef..755df43c3 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackVRulerControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackVRulerControls.cpp @@ -186,7 +186,7 @@ unsigned WaveTrackVRulerControls::HandleWheelRotation else return RefreshNone; - pProject->ModifyState(true); + ProjectManager::Get( *pProject ).ModifyState(true); return RefreshCell | UpdateVRuler; } diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackVZoomHandle.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackVZoomHandle.cpp index dda3f1338..0ee52e4cf 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackVZoomHandle.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackVZoomHandle.cpp @@ -332,7 +332,7 @@ void WaveTrackVZoomHandle::DoZoom zoomEnd = zoomStart = 0; if( pProject ) - pProject->ModifyState(true); + ProjectManager::Get( *pProject ).ModifyState(true); } enum { @@ -478,7 +478,7 @@ void WaveformVRulerMenuTable::OnWaveformScaleType(wxCommandEvent &evt) channel->GetIndependentWaveformSettings().scaleType = newScaleType; } - ::GetActiveProject()->ModifyState(true); + ProjectManager::Get( *::GetActiveProject() ).ModifyState(true); using namespace RefreshCode; mpData->result = UpdateVRuler | RefreshAll; @@ -550,7 +550,7 @@ void SpectrumVRulerMenuTable::OnSpectrumScaleType(wxCommandEvent &evt) for (auto channel : TrackList::Channels(wt)) channel->GetIndependentSpectrogramSettings().scaleType = newScaleType; - ::GetActiveProject()->ModifyState(true); + ProjectManager::Get( *::GetActiveProject() ).ModifyState(true); using namespace RefreshCode; mpData->result = UpdateVRuler | RefreshAll; diff --git a/src/tracks/timetrack/ui/TimeTrackControls.cpp b/src/tracks/timetrack/ui/TimeTrackControls.cpp index 4bb5ddced..e07529413 100644 --- a/src/tracks/timetrack/ui/TimeTrackControls.cpp +++ b/src/tracks/timetrack/ui/TimeTrackControls.cpp @@ -104,7 +104,8 @@ void TimeTrackMenuTable::OnSetTimeTrackRange(wxCommandEvent & /*event*/) AudacityProject *const project = ::GetActiveProject(); pTrack->SetRangeLower((double)lower / 100.0); pTrack->SetRangeUpper((double)upper / 100.0); - project->PushState(wxString::Format(_("Set range to '%ld' - '%ld'"), + ProjectManager::Get( *project ) + .PushState(wxString::Format(_("Set range to '%ld' - '%ld'"), lower, upper), /* i18n-hint: (verb)*/ @@ -119,7 +120,8 @@ void TimeTrackMenuTable::OnTimeTrackLin(wxCommandEvent & /*event*/) TimeTrack *const pTrack = static_cast(mpData->pTrack); pTrack->SetDisplayLog(false); AudacityProject *const project = ::GetActiveProject(); - project->PushState(_("Set time track display to linear"), _("Set Display")); + ProjectManager::Get( *project ) + .PushState(_("Set time track display to linear"), _("Set Display")); using namespace RefreshCode; mpData->result = RefreshAll | UpdateVRuler; @@ -130,7 +132,8 @@ void TimeTrackMenuTable::OnTimeTrackLog(wxCommandEvent & /*event*/) TimeTrack *const pTrack = static_cast(mpData->pTrack); pTrack->SetDisplayLog(true); AudacityProject *const project = ::GetActiveProject(); - project->PushState(_("Set time track display to logarithmic"), _("Set Display")); + ProjectManager::Get( *project ) + .PushState(_("Set time track display to logarithmic"), _("Set Display")); using namespace RefreshCode; mpData->result = RefreshAll | UpdateVRuler; @@ -142,11 +145,13 @@ void TimeTrackMenuTable::OnTimeTrackLogInt(wxCommandEvent & /*event*/) AudacityProject *const project = ::GetActiveProject(); if (pTrack->GetInterpolateLog()) { pTrack->SetInterpolateLog(false); - project->PushState(_("Set time track interpolation to linear"), _("Set Interpolation")); + ProjectManager::Get( *project ) + .PushState(_("Set time track interpolation to linear"), _("Set Interpolation")); } else { pTrack->SetInterpolateLog(true); - project->PushState(_("Set time track interpolation to logarithmic"), _("Set Interpolation")); + ProjectManager::Get( *project ). + PushState(_("Set time track interpolation to logarithmic"), _("Set Interpolation")); } mpData->result = RefreshCode::RefreshAll; } diff --git a/src/tracks/ui/EnvelopeHandle.cpp b/src/tracks/ui/EnvelopeHandle.cpp index 8b19d3827..c9060c6d9 100644 --- a/src/tracks/ui/EnvelopeHandle.cpp +++ b/src/tracks/ui/EnvelopeHandle.cpp @@ -287,7 +287,7 @@ UIHandle::Result EnvelopeHandle::Release const bool needUpdate = ForwardEventToEnvelopes(event, viewInfo); - pProject->PushState( + ProjectManager::Get( *pProject ).PushState( /* i18n-hint: (verb) Audacity has just adjusted the envelope .*/ _("Adjusted envelope."), /* i18n-hint: The envelope is a curve that controls the audio loudness.*/ @@ -302,7 +302,7 @@ UIHandle::Result EnvelopeHandle::Release UIHandle::Result EnvelopeHandle::Cancel(AudacityProject *pProject) { - pProject->RollbackState(); + ProjectManager::Get( *pProject ).RollbackState(); mEnvelopeEditors.clear(); return RefreshCode::RefreshCell; } diff --git a/src/tracks/ui/SelectHandle.cpp b/src/tracks/ui/SelectHandle.cpp index 0f4066481..619505ce2 100644 --- a/src/tracks/ui/SelectHandle.cpp +++ b/src/tracks/ui/SelectHandle.cpp @@ -579,7 +579,7 @@ UIHandle::Result SelectHandle::Click } } ); - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); // Do not start a drag return RefreshAll | UpdateSelection | Cancelled; @@ -664,7 +664,7 @@ UIHandle::Result SelectHandle::Click }; // For persistence of the selection change: - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); // Get timer events so we can auto-scroll Connect(pProject); @@ -702,7 +702,7 @@ UIHandle::Result SelectHandle::Click static_cast(pTrack), viewInfo, event.m_y, mRect.y, mRect.height); // For persistence of the selection change: - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); mSelectionBoundary = SBWidth; return UpdateSelection; } @@ -986,7 +986,7 @@ UIHandle::Result SelectHandle::Release wxWindow *) { using namespace RefreshCode; - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); mFrequencySnapper.reset(); mSnapManager.reset(); if (mSelectionStateChanger) { @@ -1126,7 +1126,7 @@ void SelectHandle::StartSelection( AudacityProject *pProject ) // PRL: commented out the Sonify stuff with the TrackPanel refactor. // It was no-op anyway. //SonifyBeginModifyState(); - pProject->ModifyState(false); + ProjectManager::Get( *pProject ).ModifyState(false); //SonifyEndModifyState(); } diff --git a/src/tracks/ui/TimeShiftHandle.cpp b/src/tracks/ui/TimeShiftHandle.cpp index 6fc43ba00..d5eee9489 100644 --- a/src/tracks/ui/TimeShiftHandle.cpp +++ b/src/tracks/ui/TimeShiftHandle.cpp @@ -835,7 +835,7 @@ UIHandle::Result TimeShiftHandle::Release fabs( mClipMoveState.hSlideAmount ) ); consolidate = true; } - pProject->PushState(msg, _("Time-Shift"), + ProjectManager::Get( *pProject ).PushState(msg, _("Time-Shift"), consolidate ? (UndoPush::CONSOLIDATE) : (UndoPush::AUTOSAVE)); return result | FixScrollbars; @@ -843,7 +843,7 @@ UIHandle::Result TimeShiftHandle::Release UIHandle::Result TimeShiftHandle::Cancel(AudacityProject *pProject) { - pProject->RollbackState(); + ProjectManager::Get( *pProject ).RollbackState(); return RefreshCode::RefreshAll; } diff --git a/src/tracks/ui/TrackButtonHandles.cpp b/src/tracks/ui/TrackButtonHandles.cpp index 985d0d21b..b9b65e481 100644 --- a/src/tracks/ui/TrackButtonHandles.cpp +++ b/src/tracks/ui/TrackButtonHandles.cpp @@ -39,7 +39,7 @@ UIHandle::Result MinimizeButtonHandle::CommitChanges bool wasMinimized = pTrack->GetMinimized(); for (auto channel : TrackList::Channels(pTrack.get())) channel->SetMinimized(!wasMinimized); - pProject->ModifyState(true); + ProjectManager::Get( *pProject ).ModifyState(true); // Redraw all tracks when any one of them expands or contracts // (Could we invent a return code that draws only those at or below diff --git a/src/tracks/ui/TrackControls.cpp b/src/tracks/ui/TrackControls.cpp index d4d907160..045fec503 100644 --- a/src/tracks/ui/TrackControls.cpp +++ b/src/tracks/ui/TrackControls.cpp @@ -221,7 +221,8 @@ void TrackMenuTable::OnSetName(wxCommandEvent &) for (auto channel : TrackList::Channels(pTrack)) channel->SetName(newName); - proj->PushState(wxString::Format(_("Renamed '%s' to '%s'"), + ProjectManager::Get( *proj ) + .PushState(wxString::Format(_("Renamed '%s' to '%s'"), oldName, newName), _("Name Change")); diff --git a/src/tracks/ui/TrackSelectHandle.cpp b/src/tracks/ui/TrackSelectHandle.cpp index 927c4e045..661b10288 100644 --- a/src/tracks/ui/TrackSelectHandle.cpp +++ b/src/tracks/ui/TrackSelectHandle.cpp @@ -180,7 +180,7 @@ UIHandle::Result TrackSelectHandle::Release wxASSERT( mpTrack ); if (mRearrangeCount != 0) { AudacityProject *const project = ::GetActiveProject(); - project->PushState( + ProjectManager::Get( *project ).PushState( wxString::Format( /* i18n-hint: will substitute name of track for %s */ ( mRearrangeCount < 0 ? _("Moved '%s' up") : _("Moved '%s' down") ), @@ -199,7 +199,7 @@ UIHandle::Result TrackSelectHandle::Release UIHandle::Result TrackSelectHandle::Cancel(AudacityProject *pProject) { - pProject->RollbackState(); + ProjectManager::Get( *pProject ).RollbackState(); // Bug 1677 mpTrack.reset(); return RefreshCode::RefreshAll;