From 2f0a76ed1037b4f49c469ef32335d4375102ef96 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Tue, 22 Jan 2019 14:59:25 -0500 Subject: [PATCH] static Scrubber::Get()... ... not member functions of AudacityProject --- src/AdornedRulerPanel.cpp | 22 +++++++++++----------- src/AudacityApp.cpp | 2 +- src/AudioIO.cpp | 2 +- src/Project.cpp | 4 ++-- src/Project.h | 5 ----- src/menus/TransportMenus.cpp | 6 +++--- src/toolbars/ControlToolBar.cpp | 19 ++++++++++++------- src/toolbars/ScrubbingToolBar.cpp | 6 +++--- src/toolbars/TranscriptionToolBar.cpp | 5 +++-- src/tracks/ui/CommonTrackPanelCell.cpp | 2 +- src/tracks/ui/PlayIndicatorOverlay.cpp | 2 +- src/tracks/ui/Scrubbing.cpp | 21 ++++++++++++++++++--- src/tracks/ui/Scrubbing.h | 8 +++++++- 13 files changed, 63 insertions(+), 41 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index 8f1200fd1..c8bda39ca 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -196,11 +196,12 @@ AdornedRulerPanel *AdornedRulerPanel::QuickPlayRulerOverlay::GetRuler() const void AdornedRulerPanel::QuickPlayRulerOverlay::Update() { const auto project = mPartner.mProject; + auto &scrubber = Scrubber::Get( *project ); auto ruler = GetRuler(); // Hide during transport, or if mouse is not in the ruler, unless scrubbing if ((!ruler->LastCell() || project->IsAudioActive()) - && (!project->GetScrubber().IsScrubbing() || project->GetScrubber().IsSpeedPlaying())) + && (!scrubber.IsScrubbing() || scrubber.IsSpeedPlaying())) mNewQPIndicatorPos = -1; else { const auto &selectedRegion = ViewInfo::Get( *project ).selectedRegion; @@ -215,7 +216,6 @@ void AdornedRulerPanel::QuickPlayRulerOverlay::Update() // These determine which shape is drawn on the ruler, and whether // in the scrub or the qp zone - const auto &scrubber = mPartner.mProject->GetScrubber(); mNewScrub = ruler->mMouseEventState == AdornedRulerPanel::mesNone && (ruler->LastCell() == ruler->mScrubbingCell || @@ -227,7 +227,7 @@ void AdornedRulerPanel::QuickPlayRulerOverlay::Update() // the track panel, green for scrub or yellow for snapped or white mNewPreviewingScrub = ruler->LastCell() == ruler->mScrubbingCell && - !project->GetScrubber().IsScrubbing(); + !scrubber.IsScrubbing(); mNewQPIndicatorSnapped = ruler->mIsSnapped; } } @@ -725,7 +725,7 @@ private: auto result = CommonRulerHandle::Click(event, pProject); if (!( result & RefreshCode::Cancelled )) { if (mClicked == Button::Left) { - auto &scrubber = pProject->GetScrubber(); + auto &scrubber = Scrubber::Get( *pProject ); // only if scrubbing is allowed now bool canScrub = scrubber.CanScrub() && @@ -776,7 +776,7 @@ private: auto result = CommonRulerHandle::Cancel(pProject); if (mClicked == Button::Left) { - auto &scrubber = pProject->GetScrubber(); + auto &scrubber = Scrubber::Get( *pProject ); scrubber.Cancel(); auto ctb = pProject->GetControlToolBar(); @@ -1233,7 +1233,7 @@ auto AdornedRulerPanel::QPHandle::Click if (!(mParent && mParent->mQuickPlayEnabled)) return RefreshCode::Cancelled; - auto &scrubber = pProject->GetScrubber(); + auto &scrubber = Scrubber::Get( *pProject ); if(scrubber.HasMark()) { // We can't stop scrubbing yet (see comments in Bug 1391), // but we can pause it. @@ -1394,7 +1394,7 @@ auto AdornedRulerPanel::ScrubbingHandle::Preview -> HitTestPreview { (void)state;// Compiler food - const auto &scrubber = pProject->GetScrubber(); + auto &scrubber = Scrubber::Get( *pProject ); auto message = ScrubbingMessage(scrubber, mClicked == Button::Left); return { @@ -1418,7 +1418,7 @@ auto AdornedRulerPanel::QPHandle::Preview } wxString message; - const auto &scrubber = pProject->GetScrubber(); + auto &scrubber = Scrubber::Get( *pProject ); const bool scrubbing = scrubber.HasMark(); if (scrubbing) // Don't distinguish zones @@ -1615,7 +1615,7 @@ void AdornedRulerPanel::StartQPPlay(bool looped, bool cutPreview) // For example buttons and menus must update. void AdornedRulerPanel::OnToggleScrubRulerFromMenu(wxCommandEvent&) { - auto &scrubber = mProject->GetScrubber(); + auto &scrubber = Scrubber::Get( *mProject ); scrubber.OnToggleScrubRuler(*mProject); } @@ -1745,12 +1745,12 @@ void AdornedRulerPanel::ShowMenu(const wxPoint & pos) void AdornedRulerPanel::ShowScrubMenu(const wxPoint & pos) { - auto &scrubber = mProject->GetScrubber(); + auto &scrubber = Scrubber::Get( *mProject ); PushEventHandler(&scrubber); auto cleanup = finally([this]{ PopEventHandler(); }); wxMenu rulerMenu; - mProject->GetScrubber().PopulatePopupMenu(rulerMenu); + scrubber.PopulatePopupMenu(rulerMenu); PopupMenu(&rulerMenu, pos); } diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index 166d3bdd5..29c98ae3d 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -1607,7 +1607,7 @@ void AudacityApp::OnKeyDown(wxKeyEvent &event) // Stop play, including scrub, but not record auto project = ::GetActiveProject(); auto token = project->GetAudioIOToken(); - auto &scrubber = project->GetScrubber(); + auto &scrubber = Scrubber::Get( *project ); auto scrubbing = scrubber.HasMark(); if (scrubbing) scrubber.Cancel(); diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 53de3a852..d8c7efabb 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -1980,7 +1980,7 @@ int AudioIO::StartStream(const TransportTracks &tracks, // work with a thread, or else yield to timer messages, but that would // execute too much else if (mScrubState) { - mOwningProject->GetScrubber().ContinueScrubbingPoll(); + Scrubber::Get( *mOwningProject ).ContinueScrubbingPoll(); wxMilliSleep( Scrubber::ScrubPollInterval_ms * 0.9 ); } else diff --git a/src/Project.cpp b/src/Project.cpp index f0b54e6ae..e1b0227ee 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -1238,7 +1238,6 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id, #ifdef EXPERIMENTAL_SCRUBBING_BASIC mScrubOverlay = std::make_shared(this); - mScrubber = std::make_unique(this); #endif mPlaybackScroller = std::make_unique(this); @@ -1854,11 +1853,12 @@ void AudacityProject::OnScrollRightButton(wxScrollEvent & /*event*/) bool AudacityProject::MayScrollBeyondZero() const { auto &project = *this; + auto &scrubber = Scrubber::Get( project ); auto &viewInfo = ViewInfo::Get( project ); if (viewInfo.bScrollBeyondZero) return true; - if (GetScrubber().HasMark() || + if (scrubber.HasMark() || IsAudioActive()) { if (mPlaybackScroller) { auto mode = mPlaybackScroller->GetMode(); diff --git a/src/Project.h b/src/Project.h index 72c5cf528..50925b6b4 100644 --- a/src/Project.h +++ b/src/Project.h @@ -69,7 +69,6 @@ class MeterPanel; class ControlToolBar; class DeviceToolBar; class MixerToolBar; -class Scrubber; class ScrubbingToolBar; class SelectionBar; class SpectralSelectionBar; @@ -659,10 +658,6 @@ private: #ifdef EXPERIMENTAL_SCRUBBING_BASIC std::shared_ptr mScrubOverlay; - std::unique_ptr mScrubber; -public: - Scrubber &GetScrubber() { return *mScrubber; } - const Scrubber &GetScrubber() const { return *mScrubber; } private: #endif diff --git a/src/menus/TransportMenus.cpp b/src/menus/TransportMenus.cpp index 06e271b04..fdd0261a0 100644 --- a/src/menus/TransportMenus.cpp +++ b/src/menus/TransportMenus.cpp @@ -206,7 +206,7 @@ bool DoPlayStopSelect (AudacityProject &project, bool click, bool shift) { auto toolbar = project.GetControlToolBar(); - auto &scrubber = project.GetScrubber(); + auto &scrubber = Scrubber::Get( project ); auto token = project.GetAudioIOToken(); auto &viewInfo = ViewInfo::Get( project ); auto &selection = viewInfo.selectedRegion; @@ -335,7 +335,7 @@ void DoTogglePinnedHead( AudacityProject &project ) // Update button image ruler->UpdateButtonStates(); - auto &scrubber = project.GetScrubber(); + auto &scrubber = Scrubber::Get( project ); if (scrubber.HasMark()) scrubber.SetScrollScrubbing(value); } @@ -1110,7 +1110,7 @@ MenuTable::BaseItemPtr TransportMenu( AudacityProject &project ) ), // Scrubbing sub-menu - project.GetScrubber().Menu(), + Scrubber::Get( project ).Menu(), CursorMenu, diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index 64309b376..08369bd24 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -836,7 +836,8 @@ void ControlToolBar::StopPlaying(bool stopStream /* = true*/) if(project) { // Let scrubbing code do some appearance change - project->GetScrubber().StopScrubbing(); + auto &scrubber = Scrubber::Get( *project ); + scrubber.StopScrubbing(); } if (!CanStopAudioStream()) @@ -1284,11 +1285,14 @@ void ControlToolBar::OnPause(wxCommandEvent & WXUNUSED(evt)) #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT + auto project = GetActiveProject(); + auto &scrubber = Scrubber::Get( *project ); + // Bug 1494 - Pausing a seek or scrub should just STOP as // it is confusing to be in a paused scrub state. bool bStopInstead = mPaused && gAudioIO->IsScrubbing() && - !GetActiveProject()->GetScrubber().IsSpeedPlaying(); + !scrubber.IsSpeedPlaying(); if (bStopInstead) { wxCommandEvent dummy; @@ -1297,7 +1301,7 @@ void ControlToolBar::OnPause(wxCommandEvent & WXUNUSED(evt)) } if (gAudioIO->IsScrubbing()) - GetActiveProject()->GetScrubber().Pause(mPaused); + scrubber.Pause(mPaused); else #endif { @@ -1395,8 +1399,9 @@ wxString ControlToolBar::StateForStatusBar() wxString state; auto pProject = GetActiveProject(); - auto scrubState = - pProject ? pProject->GetScrubber().GetUntranslatedStateString() : wxString(); + auto scrubState = pProject + ? Scrubber::Get( *pProject ).GetUntranslatedStateString() + : wxString(); if (!scrubState.empty()) state = wxGetTranslation(scrubState); else if (mPlay->IsDown()) @@ -1426,7 +1431,7 @@ bool ControlToolBar::IsTransportingPinned() { if (!TracksPrefs::GetPinnedHeadPreference()) return false; - const auto &scrubber = ::GetActiveProject()->GetScrubber(); + const auto &scrubber = Scrubber::Get( *::GetActiveProject() ); return !(scrubber.HasMark() && !scrubber.WasSpeedPlaying() && @@ -1438,7 +1443,7 @@ void ControlToolBar::StartScrollingIfPreferred() if (IsTransportingPinned()) StartScrolling(); #ifdef __WXMAC__ - else if (::GetActiveProject()->GetScrubber().HasMark()) { + else if (Scrubber::Get( *::GetActiveProject() ).HasMark()) { // PRL: cause many "unnecessary" refreshes. For reasons I don't understand, // doing this causes wheel rotation events (mapped from the double finger vertical // swipe) to be delivered more uniformly to the application, so that speed control diff --git a/src/toolbars/ScrubbingToolBar.cpp b/src/toolbars/ScrubbingToolBar.cpp index f0e36d88f..9ad76184e 100644 --- a/src/toolbars/ScrubbingToolBar.cpp +++ b/src/toolbars/ScrubbingToolBar.cpp @@ -142,7 +142,7 @@ void ScrubbingToolBar::RegenerateTooltips() auto project = GetActiveProject(); if (project) { - auto &scrubber = project->GetScrubber(); + auto &scrubber = Scrubber::Get( *project ); const auto scrubButton = mButtons[STBScrubID]; const auto seekButton = mButtons[STBSeekID]; @@ -184,7 +184,7 @@ void ScrubbingToolBar::OnButton(wxCommandEvent &event) { AudacityProject *p = GetActiveProject(); if (!p) return; - auto &scrubber = p->GetScrubber(); + auto &scrubber = Scrubber::Get( *p ); int id = event.GetId(); @@ -215,7 +215,7 @@ void ScrubbingToolBar::EnableDisableButtons() AudacityProject *p = GetActiveProject(); if (!p) return; - auto &scrubber = p->GetScrubber(); + auto &scrubber = Scrubber::Get( *p ); const auto canScrub = scrubber.CanScrub(); if (scrubber.Scrubs()) { diff --git a/src/toolbars/TranscriptionToolBar.cpp b/src/toolbars/TranscriptionToolBar.cpp index 4a3313c01..64257fe10 100644 --- a/src/toolbars/TranscriptionToolBar.cpp +++ b/src/toolbars/TranscriptionToolBar.cpp @@ -496,8 +496,9 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview) } else { - Scrubber &Scrubber = p->GetScrubber(); - Scrubber.StartSpeedPlay(GetPlaySpeed(), playRegionStart, playRegionEnd); + auto &scrubber = Scrubber::Get( *p ); + scrubber.StartSpeedPlay(GetPlaySpeed(), + playRegionStart, playRegionEnd); } } diff --git a/src/tracks/ui/CommonTrackPanelCell.cpp b/src/tracks/ui/CommonTrackPanelCell.cpp index 1408929ed..3e8fac25a 100644 --- a/src/tracks/ui/CommonTrackPanelCell.cpp +++ b/src/tracks/ui/CommonTrackPanelCell.cpp @@ -47,7 +47,7 @@ unsigned CommonTrackPanelCell::HandleWheelRotation unsigned result = RefreshAll; const wxMouseEvent &event = evt.event; auto &viewInfo = ViewInfo::Get( *pProject ); - Scrubber &scrubber = pProject->GetScrubber(); + Scrubber &scrubber = Scrubber::Get( *pProject ); const auto steps = evt.steps; if (event.ShiftDown() diff --git a/src/tracks/ui/PlayIndicatorOverlay.cpp b/src/tracks/ui/PlayIndicatorOverlay.cpp index 25073f295..b720f4bac 100644 --- a/src/tracks/ui/PlayIndicatorOverlay.cpp +++ b/src/tracks/ui/PlayIndicatorOverlay.cpp @@ -144,7 +144,7 @@ void PlayIndicatorOverlay::OnTimer(wxCommandEvent &event) if (!mProject->IsAudioActive()) { mNewIndicatorX = -1; mNewIsCapturing = false; - const auto &scrubber = mProject->GetScrubber(); + const auto &scrubber = Scrubber::Get( *mProject ); if (scrubber.HasMark()) { auto position = scrubber.GetScrubStartPosition(); const auto offset = trackPanel->GetLeftOffset(); diff --git a/src/tracks/ui/Scrubbing.cpp b/src/tracks/ui/Scrubbing.cpp index 7595ba70a..b104c112b 100644 --- a/src/tracks/ui/Scrubbing.cpp +++ b/src/tracks/ui/Scrubbing.cpp @@ -198,6 +198,21 @@ void Scrubber::ScrubPoller::Notify() mScrubber.ContinueScrubbingUI(); } +static const AudacityProject::AttachedObjects::RegisteredFactory key{ + []( AudacityProject &parent ){ + return std::make_shared< Scrubber >( &parent ); } +}; + +Scrubber &Scrubber::Get( AudacityProject &project ) +{ + return project.AttachedObjects::Get< Scrubber >( key ); +} + +const Scrubber &Scrubber::Get( const AudacityProject &project ) +{ + return Get( const_cast< AudacityProject & >( project ) ); +} + Scrubber::Scrubber(AudacityProject *project) : mScrubToken(-1) , mPaused(true) @@ -1009,12 +1024,12 @@ void ScrubbingOverlay::OnTimer(wxCommandEvent &event) const Scrubber &ScrubbingOverlay::GetScrubber() const { - return mProject->GetScrubber(); + return Scrubber::Get( *mProject ); } Scrubber &ScrubbingOverlay::GetScrubber() { - return mProject->GetScrubber(); + return Scrubber::Get( *mProject ); } void Scrubber::DoScrub(bool seek) @@ -1152,7 +1167,7 @@ bool Scrubber::CanScrub() const // To supply the "finder" argument static CommandHandlerObject &findme(AudacityProject &project) -{ return project.GetScrubber(); } +{ return Scrubber::Get( project ); } MenuTable::BaseItemPtr Scrubber::Menu() { diff --git a/src/tracks/ui/Scrubbing.h b/src/tracks/ui/Scrubbing.h index 4845c76f9..845fe7590 100644 --- a/src/tracks/ui/Scrubbing.h +++ b/src/tracks/ui/Scrubbing.h @@ -16,6 +16,7 @@ Paul Licameli split from TrackPanel.cpp #include #include +#include "../../ClientData.h" #include "../../widgets/Overlay.h" // to inherit #include "../../commands/CommandContext.h" #include "../../commands/CommandManager.h" // for MenuTable @@ -64,11 +65,16 @@ struct ScrubbingOptions { }; // Scrub state object -class Scrubber : public wxEvtHandler +class Scrubber final + : public wxEvtHandler + , public ClientData::Base { public: static constexpr unsigned ScrubPollInterval_ms = 50; + static Scrubber &Get( AudacityProject &project ); + static const Scrubber &Get( const AudacityProject &project ); + Scrubber(AudacityProject *project); ~Scrubber();