From 63b93fd2d148818991724466fb16b58e6d992a52 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Fri, 25 Jan 2019 23:39:29 -0500 Subject: [PATCH] Play region and its lock are stored together in ViewInfo --- src/AdornedRulerPanel.cpp | 180 ++++++++++++-------------- src/AdornedRulerPanel.h | 9 +- src/Menus.cpp | 7 +- src/Project.cpp | 9 -- src/Project.h | 6 - src/ProjectWindow.cpp | 9 +- src/ViewInfo.h | 54 ++++++++ src/effects/Effect.cpp | 7 +- src/menus/TransportMenus.cpp | 13 +- src/toolbars/ControlToolBar.cpp | 5 +- src/toolbars/TranscriptionToolBar.cpp | 12 +- 11 files changed, 165 insertions(+), 146 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index 408ac8aef..4d6c8caff 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -901,11 +901,6 @@ AdornedRulerPanel::AdornedRulerPanel(AudacityProject* project, mLeftOffset = 0; mIndTime = -1; - mPlayRegionStart = -1; - mPlayRegionLock = false; - mPlayRegionEnd = -1; - mOldPlayRegionStart = -1; - mOldPlayRegionEnd = -1; mLeftDownClick = -1; mMouseEventState = mesNone; mIsDragging = false; @@ -1280,9 +1275,9 @@ auto AdornedRulerPanel::QPHandle::Click } // Store the initial play region state - mParent->mOldPlayRegionStart = mParent->mPlayRegionStart; - mParent->mOldPlayRegionEnd = mParent->mPlayRegionEnd; - mParent->mPlayRegionLock = mParent->mProject->IsPlayRegionLocked(); + const auto &viewInfo = ViewInfo::Get( *pProject ); + const auto &playRegion = viewInfo.playRegion; + mParent->mOldPlayRegion = playRegion; // Save old selection, in case drag of selection is cancelled mOldSelection = ViewInfo::Get( *pProject ).selectedRegion; @@ -1298,27 +1293,29 @@ auto AdornedRulerPanel::QPHandle::Click void AdornedRulerPanel::HandleQPClick(wxMouseEvent &evt, wxCoord mousePosX) { // Temporarily unlock locked play region - if (mPlayRegionLock && evt.LeftDown()) { + if (mOldPlayRegion.Locked() && evt.LeftDown()) { //mPlayRegionLock = true; TransportActions::DoUnlockPlayRegion(*mProject); } mLeftDownClickUnsnapped = mQuickPlayPosUnsnapped; mLeftDownClick = mQuickPlayPos; - bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegionStart); - bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegionEnd); + bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegion.GetStart()); + bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegion.GetEnd()); if (isWithinStart || isWithinEnd) { // If Quick-Play is playing from a point, we need to treat it as a click // not as dragging. - if (mOldPlayRegionStart == mOldPlayRegionEnd) + if (mOldPlayRegion.Empty()) mMouseEventState = mesSelectingPlayRegionClick; // otherwise check which marker is nearer else { // Don't compare times, compare positions. //if (fabs(mQuickPlayPos - mPlayRegionStart) < fabs(mQuickPlayPos - mPlayRegionEnd)) - if (abs(Time2Pos(mQuickPlayPos) - Time2Pos(mPlayRegionStart)) < - abs(Time2Pos(mQuickPlayPos) - Time2Pos(mPlayRegionEnd))) + auto start = mOldPlayRegion.GetStart(); + auto end = mOldPlayRegion.GetEnd(); + if (abs(Time2Pos(mQuickPlayPos) - Time2Pos(start)) < + abs(Time2Pos(mQuickPlayPos) - Time2Pos(end))) mMouseEventState = mesDraggingPlayRegionStart; else mMouseEventState = mesDraggingPlayRegionEnd; @@ -1351,45 +1348,47 @@ void AdornedRulerPanel::HandleQPDrag(wxMouseEvent &/*event*/, wxCoord mousePosX) bool isWithinClick = (mLeftDownClickUnsnapped >= 0) && IsWithinMarker(mousePosX, mLeftDownClickUnsnapped); - bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegionStart); - bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegionEnd); - bool canDragSel = !mPlayRegionLock && mPlayRegionDragsSelection; + bool isWithinStart = IsWithinMarker(mousePosX, mOldPlayRegion.GetStart()); + bool isWithinEnd = IsWithinMarker(mousePosX, mOldPlayRegion.GetEnd()); + bool canDragSel = !mOldPlayRegion.Locked() && mPlayRegionDragsSelection; + auto &viewInfo = ViewInfo::Get( *GetProject() ); + auto &playRegion = viewInfo.playRegion; switch (mMouseEventState) { case mesNone: // If close to either end of play region, snap to closest if (isWithinStart || isWithinEnd) { - if (fabs(mQuickPlayPos - mOldPlayRegionStart) < fabs(mQuickPlayPos - mOldPlayRegionEnd)) - mQuickPlayPos = mOldPlayRegionStart; + if (fabs(mQuickPlayPos - mOldPlayRegion.GetStart()) < fabs(mQuickPlayPos - mOldPlayRegion.GetEnd())) + mQuickPlayPos = mOldPlayRegion.GetStart(); else - mQuickPlayPos = mOldPlayRegionEnd; + mQuickPlayPos = mOldPlayRegion.GetEnd(); } break; case mesDraggingPlayRegionStart: // Don't start dragging until beyond tolerance initial playback start if (!mIsDragging && isWithinStart) - mQuickPlayPos = mOldPlayRegionStart; + mQuickPlayPos = mOldPlayRegion.GetStart(); else mIsDragging = true; // avoid accidental tiny selection if (isWithinEnd) - mQuickPlayPos = mOldPlayRegionEnd; - mPlayRegionStart = mQuickPlayPos; + mQuickPlayPos = mOldPlayRegion.GetEnd(); + playRegion.SetStart( mQuickPlayPos ); if (canDragSel) { DragSelection(); } break; case mesDraggingPlayRegionEnd: if (!mIsDragging && isWithinEnd) { - mQuickPlayPos = mOldPlayRegionEnd; + mQuickPlayPos = mOldPlayRegion.GetEnd(); } else mIsDragging = true; if (isWithinStart) { - mQuickPlayPos = mOldPlayRegionStart; + mQuickPlayPos = mOldPlayRegion.GetStart(); } - mPlayRegionEnd = mQuickPlayPos; + playRegion.SetEnd( mQuickPlayPos ); if (canDragSel) { DragSelection(); } @@ -1399,8 +1398,7 @@ void AdornedRulerPanel::HandleQPDrag(wxMouseEvent &/*event*/, wxCoord mousePosX) // Don't start dragging until mouse is beyond tolerance of initial click. if (isWithinClick || mLeftDownClick == -1) { mQuickPlayPos = mLeftDownClick; - mPlayRegionStart = mLeftDownClick; - mPlayRegionEnd = mLeftDownClick; + playRegion.SetTimes(mLeftDownClick, mLeftDownClick); } else { mMouseEventState = mesSelectingPlayRegionRange; @@ -1411,14 +1409,10 @@ void AdornedRulerPanel::HandleQPDrag(wxMouseEvent &/*event*/, wxCoord mousePosX) mQuickPlayPos = mLeftDownClick; } - if (mQuickPlayPos < mLeftDownClick) { - mPlayRegionStart = mQuickPlayPos; - mPlayRegionEnd = mLeftDownClick; - } - else { - mPlayRegionEnd = mQuickPlayPos; - mPlayRegionStart = mLeftDownClick; - } + if (mQuickPlayPos < mLeftDownClick) + playRegion.SetTimes( mQuickPlayPos, mLeftDownClick ); + else + playRegion.SetTimes( mLeftDownClick, mQuickPlayPos ); if (canDragSel) { DragSelection(); } @@ -1474,9 +1468,9 @@ auto AdornedRulerPanel::QPHandle::Preview showArrows = (mClicked == Button::Left) || mParent->IsWithinMarker( - state.state.m_x, mParent->mOldPlayRegionStart) + state.state.m_x, mParent->mOldPlayRegion.GetStart()) || mParent->IsWithinMarker( - state.state.m_x, mParent->mOldPlayRegionEnd); + state.state.m_x, mParent->mOldPlayRegion.GetEnd()); return { message, @@ -1498,11 +1492,13 @@ auto AdornedRulerPanel::QPHandle::Release auto result = CommonRulerHandle::Release(event, pProject, pParent); if (!( result & RefreshCode::Cancelled )) { if (mClicked == Button::Left) { - if ( mParent ) + if ( mParent ) { mParent->HandleQPRelease( event.event ); // Update the hot zones for cursor changes - mParent->mOldPlayRegionStart = mParent->mPlayRegionStart; - mParent->mOldPlayRegionEnd = mParent->mPlayRegionEnd; + const auto &viewInfo = ViewInfo::Get( *pProject ); + const auto &playRegion = viewInfo.playRegion; + mParent->mOldPlayRegion = playRegion; + } } } return result; @@ -1510,38 +1506,37 @@ auto AdornedRulerPanel::QPHandle::Release void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt) { - if (mPlayRegionEnd < mPlayRegionStart) { - // Swap values to ensure mPlayRegionStart < mPlayRegionEnd - double tmp = mPlayRegionStart; - mPlayRegionStart = mPlayRegionEnd; - mPlayRegionEnd = tmp; - } + auto &viewInfo = ViewInfo::Get( *GetProject() ); + auto &playRegion = viewInfo.playRegion; + playRegion.Order(); const double t0 = mTracks->GetStartTime(); const double t1 = mTracks->GetEndTime(); - auto &viewInfo = ViewInfo::Get( *GetProject() ); const auto &selectedRegion = viewInfo.selectedRegion; const double sel0 = selectedRegion.t0(); const double sel1 = selectedRegion.t1(); // We want some audio in the selection, but we allow a dragged // region to include selected white-space and space before audio start. - if (evt.ShiftDown() && (mPlayRegionStart == mPlayRegionEnd)) { + if (evt.ShiftDown() && playRegion.Empty()) { // Looping the selection or project. // Disable if track selection is in white-space beyond end of tracks and // play position is outside of track contents. if (((sel1 < t0) || (sel0 > t1)) && - ((mPlayRegionStart < t0) || (mPlayRegionStart > t1))) { + ((playRegion.GetStart() < t0) || (playRegion.GetStart() > t1))) { ClearPlayRegion(); } } // Disable if beyond end. - else if (mPlayRegionStart >= t1) { + else if (playRegion.GetStart() >= t1) { ClearPlayRegion(); } // Disable if empty selection before start. // (allow Quick-Play region to include 'pre-roll' white space) - else if (((mPlayRegionEnd - mPlayRegionStart) > 0.0) && (mPlayRegionEnd < t0)) { + else if ( + playRegion.GetEnd() - playRegion.GetStart() > 0.0 && + playRegion.GetEnd() < t0 + ) { ClearPlayRegion(); } @@ -1550,12 +1545,12 @@ void AdornedRulerPanel::HandleQPRelease(wxMouseEvent &evt) mLeftDownClick = -1; auto cleanup = finally( [&] { - if (mPlayRegionLock) { + if (mOldPlayRegion.Locked()) { // Restore Locked Play region - SetPlayRegion(mOldPlayRegionStart, mOldPlayRegionEnd); + SetPlayRegion(mOldPlayRegion.GetStart(), mOldPlayRegion.GetEnd()); TransportActions::DoLockPlayRegion(*mProject); // and release local lock - mPlayRegionLock = false; + mOldPlayRegion.SetLocked( false ); } } ); @@ -1572,12 +1567,12 @@ auto AdornedRulerPanel::QPHandle::Cancel ViewInfo::Get( *pProject ).selectedRegion = mOldSelection; mParent->mMouseEventState = mesNone; mParent->SetPlayRegion( - mParent->mOldPlayRegionStart, mParent->mOldPlayRegionEnd); - if (mParent->mPlayRegionLock) { + mParent->mOldPlayRegion.GetStart(), mParent->mOldPlayRegion.GetEnd()); + if (mParent->mOldPlayRegion.Locked()) { // Restore Locked Play region TransportActions::DoLockPlayRegion(*pProject); // and release local lock - mParent->mPlayRegionLock = false; + mParent->mOldPlayRegion.SetLocked( false ); } } } @@ -1590,12 +1585,13 @@ void AdornedRulerPanel::StartQPPlay(bool looped, bool cutPreview) const double t0 = mTracks->GetStartTime(); const double t1 = mTracks->GetEndTime(); auto &viewInfo = ViewInfo::Get( *mProject ); + auto &playRegion = viewInfo.playRegion; const auto &selectedRegion = viewInfo.selectedRegion; const double sel0 = selectedRegion.t0(); const double sel1 = selectedRegion.t1(); // Start / Restart playback on left click. - bool startPlaying = (mPlayRegionStart >= 0); + bool startPlaying = (playRegion.GetStart() >= 0); if (startPlaying) { auto &ctb = ControlToolBar::Get( *mProject ); @@ -1604,9 +1600,9 @@ void AdornedRulerPanel::StartQPPlay(bool looped, bool cutPreview) bool loopEnabled = true; double start, end; - if ((mPlayRegionEnd - mPlayRegionStart == 0.0) && looped) { + if (playRegion.Empty() && looped) { // Loop play a point will loop either a selection or the project. - if ((mPlayRegionStart > sel0) && (mPlayRegionStart < sel1)) { + if ((playRegion.GetStart() > sel0) && (playRegion.GetStart() < sel1)) { // we are in a selection, so use the selection start = sel0; end = sel1; @@ -1617,8 +1613,8 @@ void AdornedRulerPanel::StartQPPlay(bool looped, bool cutPreview) } } else { - start = mPlayRegionStart; - end = mPlayRegionEnd; + start = playRegion.GetStart(); + end = playRegion.GetEnd(); } // Looping a tiny selection may freeze, so just play it once. loopEnabled = ((end - start) > 0.001)? true : false; @@ -1626,7 +1622,7 @@ void AdornedRulerPanel::StartQPPlay(bool looped, bool cutPreview) auto options = DefaultPlayOptions( *mProject ); options.playLooped = (loopEnabled && looped); - auto oldStart = mPlayRegionStart; + auto oldStart = playRegion.GetStart(); if (!cutPreview) options.pStartTime = &oldStart; else @@ -1637,8 +1633,7 @@ void AdornedRulerPanel::StartQPPlay(bool looped, bool cutPreview) : options.playLooped ? PlayMode::loopedPlay : PlayMode::normalPlay; - mPlayRegionStart = start; - mPlayRegionEnd = end; + playRegion.SetTimes( start, end ); Refresh(); ctb.PlayPlayRegion((SelectedRegion(start, end)), @@ -1740,6 +1735,8 @@ void AdornedRulerPanel::UpdateQuickPlayPos(wxCoord &mousePosX, bool shiftDown) void AdornedRulerPanel::ShowMenu(const wxPoint & pos) { + const auto &viewInfo = ViewInfo::Get( *GetProject() ); + const auto &playRegion = viewInfo.playRegion; wxMenu rulerMenu; if (mQuickPlayEnabled) @@ -1748,11 +1745,11 @@ void AdornedRulerPanel::ShowMenu(const wxPoint & pos) rulerMenu.Append(OnToggleQuickPlayID, _("Enable Quick-Play")); wxMenuItem *dragitem; - if (mPlayRegionDragsSelection && !mProject->IsPlayRegionLocked()) + if (mPlayRegionDragsSelection && !playRegion.Locked()) dragitem = rulerMenu.Append(OnSyncQuickPlaySelID, _("Disable dragging selection")); else dragitem = rulerMenu.Append(OnSyncQuickPlaySelID, _("Enable dragging selection")); - dragitem->Enable(mQuickPlayEnabled && !mProject->IsPlayRegionLocked()); + dragitem->Enable(mQuickPlayEnabled && !playRegion.Locked()); #if wxUSE_TOOLTIPS if (mTimelineToolTip) @@ -1767,11 +1764,11 @@ void AdornedRulerPanel::ShowMenu(const wxPoint & pos) rulerMenu.Append(OnAutoScrollID, _("Update display while playing")); wxMenuItem *prlitem; - if (!mProject->IsPlayRegionLocked()) + if (!playRegion.Locked()) prlitem = rulerMenu.Append(OnLockPlayRegionID, _("Lock Play Region")); else prlitem = rulerMenu.Append(OnLockPlayRegionID, _("Unlock Play Region")); - prlitem->Enable(mProject->IsPlayRegionLocked() || (mPlayRegionStart != mPlayRegionEnd)); + prlitem->Enable( playRegion.Locked() || !playRegion.Empty() ); wxMenuItem *ruleritem; if (mShowScrubbing) @@ -1811,9 +1808,10 @@ void AdornedRulerPanel::OnSyncSelToQuickPlay(wxCommandEvent&) void AdornedRulerPanel::DragSelection() { auto &viewInfo = ViewInfo::Get( *GetProject() ); + const auto &playRegion = viewInfo.playRegion; auto &selectedRegion = viewInfo.selectedRegion; - selectedRegion.setT0(mPlayRegionStart, false); - selectedRegion.setT1(mPlayRegionEnd, true); + selectedRegion.setT0(playRegion.GetStart(), false); + selectedRegion.setT1(playRegion.GetEnd(), true); } void AdornedRulerPanel::HandleSnapping() @@ -1854,7 +1852,9 @@ void AdornedRulerPanel::OnAutoScroll(wxCommandEvent&) void AdornedRulerPanel::OnLockPlayRegion(wxCommandEvent&) { - if (mProject->IsPlayRegionLocked()) + const auto &viewInfo = ViewInfo::Get( *GetProject() ); + const auto &playRegion = viewInfo.playRegion; + if (playRegion.Locked()) TransportActions::DoUnlockPlayRegion(*mProject); else TransportActions::DoLockPlayRegion(*mProject); @@ -1864,8 +1864,10 @@ void AdornedRulerPanel::OnLockPlayRegion(wxCommandEvent&) // Draws the horizontal <===> void AdornedRulerPanel::DoDrawPlayRegion(wxDC * dc) { - double start, end; - GetPlayRegion(&start, &end); + const auto &viewInfo = ViewInfo::Get( *GetProject() ); + const auto &playRegion = viewInfo.playRegion; + auto start = playRegion.GetStart(); + auto end = playRegion.GetEnd(); if (start >= 0) { @@ -1873,7 +1875,7 @@ void AdornedRulerPanel::DoDrawPlayRegion(wxDC * dc) const int x2 = Time2Pos(end)-2; int y = mInner.y - TopMargin + mInner.height/2; - bool isLocked = mProject->IsPlayRegionLocked(); + bool isLocked = playRegion.Locked(); AColor::PlayRegionColor(dc, isLocked); wxPoint tri[3]; @@ -2108,8 +2110,9 @@ void AdornedRulerPanel::SetPlayRegion(double playRegionStart, if (mMouseEventState != mesNone) return; - mPlayRegionStart = playRegionStart; - mPlayRegionEnd = playRegionEnd; + auto &viewInfo = ViewInfo::Get( *GetProject() ); + auto &playRegion = viewInfo.playRegion; + playRegion.SetTimes( playRegionStart, playRegionEnd ); Refresh(); } @@ -2119,28 +2122,13 @@ void AdornedRulerPanel::ClearPlayRegion() auto &ctb = ControlToolBar::Get( *mProject ); ctb.StopPlaying(); - mPlayRegionStart = -1; - mPlayRegionEnd = -1; + auto &viewInfo = ViewInfo::Get( *GetProject() ); + auto &playRegion = viewInfo.playRegion; + playRegion.SetTimes( -1, -1 ); Refresh(); } -void AdornedRulerPanel::GetPlayRegion(double* playRegionStart, - double* playRegionEnd) -{ - if (mPlayRegionStart >= 0 && mPlayRegionEnd >= 0 && - mPlayRegionEnd < mPlayRegionStart) - { - // swap values to make sure end > start - *playRegionStart = mPlayRegionEnd; - *playRegionEnd = mPlayRegionStart; - } else - { - *playRegionStart = mPlayRegionStart; - *playRegionEnd = mPlayRegionEnd; - } -} - void AdornedRulerPanel::GetMaxSize(wxCoord *width, wxCoord *height) { mRuler.GetMaxSize(width, height); diff --git a/src/AdornedRulerPanel.h b/src/AdornedRulerPanel.h index b13e2f149..09a267456 100644 --- a/src/AdornedRulerPanel.h +++ b/src/AdornedRulerPanel.h @@ -14,8 +14,8 @@ #include "CellularPanel.h" #include "widgets/Ruler.h" // member variable #include "Prefs.h" +#include "ViewInfo.h" // for PlayRegion -class ViewInfo; class AudacityProject; class SnapManager; class TrackList; @@ -54,7 +54,6 @@ public: void SetPlayRegion(double playRegionStart, double playRegionEnd); void ClearPlayRegion(); - void GetPlayRegion(double* playRegionStart, double* playRegionEnd); void GetMaxSize(wxCoord *width, wxCoord *height); @@ -132,11 +131,7 @@ private: bool mIsSnapped; - bool mPlayRegionLock; - double mPlayRegionStart; - double mPlayRegionEnd; - double mOldPlayRegionStart; - double mOldPlayRegionEnd; + PlayRegion mOldPlayRegion; bool mIsRecording; diff --git a/src/Menus.cpp b/src/Menus.cpp index 2e35062d4..97d6e140b 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -546,11 +546,10 @@ CommandFlag MenuManager::GetUpdateFlags flags |= GetFocusedFrame(project); - double start, end; - project.GetPlayRegion(&start, &end); - if (project.IsPlayRegionLocked()) + const auto &playRegion = viewInfo.playRegion; + if (playRegion.Locked()) flags |= PlayRegionLockedFlag; - else if (start != end) + else if (!playRegion.Empty()) flags |= PlayRegionNotLockedFlag; if (flags & AudioIONotBusyFlag) { diff --git a/src/Project.cpp b/src/Project.cpp index 2def8372d..88e4a1ac5 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -12,7 +12,6 @@ #include "Audacity.h" // for USE_* macros #include "Project.h" -#include "AdornedRulerPanel.h" #include "KeyboardCapture.h" #include "ondemand/ODTaskThread.h" @@ -156,14 +155,6 @@ void AudacityProject::SetStatus(const wxString &msg) } } -void AudacityProject::GetPlayRegion(double* playRegionStart, - double *playRegionEnd) -{ - auto &project = *this; - AdornedRulerPanel::Get( project ).GetPlayRegion( - playRegionStart, playRegionEnd); -} - wxFrame &GetProjectFrame( AudacityProject &project ) { auto ptr = project.GetFrame(); diff --git a/src/Project.h b/src/Project.h index 1caaf8664..b1d4512ad 100644 --- a/src/Project.h +++ b/src/Project.h @@ -122,10 +122,6 @@ class AUDACITY_DLL_API AudacityProject final const wxFrame *GetFrame() const { return mFrame; } void SetFrame( wxFrame *pFrame ); - void GetPlayRegion(double* playRegionStart, double *playRegionEnd); - bool IsPlayRegionLocked() { return mLockPlayRegion; } - void SetPlayRegionLocked(bool value) { mLockPlayRegion = value; } - wxString GetProjectName() const; const FilePath &GetFileName() { return mFileName; } @@ -149,8 +145,6 @@ class AUDACITY_DLL_API AudacityProject final int mBatchMode{ 0 };// 0 means not, >0 means in batch mode. private: - bool mLockPlayRegion{ false }; - wxString mLastMainStatusMessage; wxWeakRef< wxFrame > mFrame{}; diff --git a/src/ProjectWindow.cpp b/src/ProjectWindow.cpp index 8d256c5cf..2a08d67ff 100644 --- a/src/ProjectWindow.cpp +++ b/src/ProjectWindow.cpp @@ -1590,8 +1590,9 @@ void ProjectWindow::TP_DisplaySelection() auto &viewInfo = ViewInfo::Get( project ); const auto &selectedRegion = viewInfo.selectedRegion; double audioTime; + auto &playRegion = ViewInfo::Get( project ).playRegion; - if (!gAudioIO->IsBusy() && project.IsPlayRegionLocked()) + if (!gAudioIO->IsBusy() && playRegion.Locked()) ruler.SetPlayRegion( selectedRegion.t0(), selectedRegion.t1() ); else // Cause ruler redraw anyway, because we may be zooming or scrolling @@ -1599,10 +1600,8 @@ void ProjectWindow::TP_DisplaySelection() if (gAudioIO->IsBusy()) audioTime = gAudioIO->GetStreamTime(); - else { - double playEnd; - project.GetPlayRegion(&audioTime, &playEnd); - } + else + audioTime = playRegion.GetStart(); SelectionBar::Get( project ).SetTimes(selectedRegion.t0(), selectedRegion.t1(), audioTime); diff --git a/src/ViewInfo.h b/src/ViewInfo.h index 760f4e9c2..5cea3d7d9 100644 --- a/src/ViewInfo.h +++ b/src/ViewInfo.h @@ -11,6 +11,7 @@ #ifndef __AUDACITY_VIEWINFO__ #define __AUDACITY_VIEWINFO__ +#include #include #include // inherit wxEvtHandler #include "ClientData.h" @@ -147,6 +148,58 @@ public: {return 0;} // stub }; +class PlayRegion +{ +public: + PlayRegion() = default; + + PlayRegion( const PlayRegion& ) = delete; + PlayRegion &operator= ( const PlayRegion &that ) + { + mLocked = that.mLocked; + // Guarantee the equivalent un-swapped order of endpoints + mStart = that.GetStart(); + mEnd = that.GetEnd(); + return *this; + } + + bool Locked() const { return mLocked; } + void SetLocked( bool locked ) { mLocked = locked; } + + bool Empty() const { return GetStart() == GetEnd(); } + double GetStart() const + { + if ( mEnd < 0 ) + return mStart; + else + return std::min( mStart, mEnd ); + } + double GetEnd() const + { + if ( mStart < 0 ) + return mEnd; + else + return std::max( mStart, mEnd ); + } + + void SetStart( double start ) { mStart = start; } + void SetEnd( double end ) { mEnd = end; } + void SetTimes( double start, double end ) { mStart = start, mEnd = end; } + + void Order() + { + if ( mStart >= 0 && mEnd >= 0 && mStart > mEnd) + std::swap( mStart, mEnd ); + } + +private: + // Times: + double mStart{ -1.0 }; + double mEnd{ -1.0 }; + + bool mLocked{ false }; +}; + class AUDACITY_DLL_API ViewInfo final : public wxEvtHandler, public ZoomInfo { @@ -172,6 +225,7 @@ public: // Current selection SelectedRegion selectedRegion; + PlayRegion playRegion; // Scroll info diff --git a/src/effects/Effect.cpp b/src/effects/Effect.cpp index fd944baea..12d99c124 100644 --- a/src/effects/Effect.cpp +++ b/src/effects/Effect.cpp @@ -3512,11 +3512,10 @@ void EffectUIHost::OnPlay(wxCommandEvent & WXUNUSED(evt)) { auto &viewInfo = ViewInfo::Get( *mProject ); const auto &selectedRegion = viewInfo.selectedRegion; - if (mProject->IsPlayRegionLocked()) + const auto &playRegion = viewInfo.playRegion; + if ( playRegion.Locked() ) { - double t0, t1; - mProject->GetPlayRegion(&t0, &t1); - mRegion.setTimes(t0, t1); + mRegion.setTimes(playRegion.GetStart(), playRegion.GetEnd()); mPlayPos = mRegion.t0(); } else if (selectedRegion.t0() != mRegion.t0() || diff --git a/src/menus/TransportMenus.cpp b/src/menus/TransportMenus.cpp index 2c6824d12..4d86fe896 100644 --- a/src/menus/TransportMenus.cpp +++ b/src/menus/TransportMenus.cpp @@ -307,14 +307,14 @@ void DoLockPlayRegion( AudacityProject &project ) auto &tracks = TrackList::Get( project ); auto &ruler = AdornedRulerPanel::Get( project ); - double start, end; - project.GetPlayRegion(&start, &end); - if (start >= tracks.GetEndTime()) { + auto &viewInfo = ViewInfo::Get( project ); + auto &playRegion = viewInfo.playRegion; + if (playRegion.GetStart() >= tracks.GetEndTime()) { AudacityMessageBox(_("Cannot lock region beyond\nend of project."), _("Error")); } else { - project.SetPlayRegionLocked( true ); + playRegion.SetLocked( true ); ruler.Refresh(false); } } @@ -322,8 +322,9 @@ void DoLockPlayRegion( AudacityProject &project ) void DoUnlockPlayRegion( AudacityProject &project ) { auto &ruler = AdornedRulerPanel::Get( project ); - - project.SetPlayRegionLocked( false ); + auto &viewInfo = ViewInfo::Get( project ); + auto &playRegion = viewInfo.playRegion; + playRegion.SetLocked( false ); ruler.Refresh(false); } diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index 1ebbba6e1..3114f78c7 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -770,8 +770,7 @@ void ControlToolBar::PlayCurrentRegion(bool looped /* = false */, if (p) { - double playRegionStart, playRegionEnd; - p->GetPlayRegion(&playRegionStart, &playRegionEnd); + const auto &playRegion = ViewInfo::Get( *p ).playRegion; auto options = DefaultPlayOptions( *p ); options.playLooped = looped; @@ -781,7 +780,7 @@ void ControlToolBar::PlayCurrentRegion(bool looped /* = false */, cutpreview ? PlayMode::cutPreviewPlay : options.playLooped ? PlayMode::loopedPlay : PlayMode::normalPlay; - PlayPlayRegion(SelectedRegion(playRegionStart, playRegionEnd), + PlayPlayRegion(SelectedRegion(playRegion.GetStart(), playRegion.GetEnd()), options, mode); } diff --git a/src/toolbars/TranscriptionToolBar.cpp b/src/toolbars/TranscriptionToolBar.cpp index 14e577b69..245f3558d 100644 --- a/src/toolbars/TranscriptionToolBar.cpp +++ b/src/toolbars/TranscriptionToolBar.cpp @@ -487,11 +487,11 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview) } // Get the current play region - double playRegionStart, playRegionEnd; - p->GetPlayRegion(&playRegionStart, &playRegionEnd); + const auto &viewInfo = ViewInfo::Get( *p ); + const auto &playRegion = viewInfo.playRegion; // Start playing - if (playRegionStart < 0) + if (playRegion.GetStart() < 0) return; if (bFixedSpeedPlay) { @@ -504,8 +504,8 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview) : options.playLooped ? PlayMode::loopedPlay : PlayMode::normalPlay; auto &bar = ControlToolBar::Get( *p ); - bar.PlayPlayRegion - (SelectedRegion(playRegionStart, playRegionEnd), + bar.PlayPlayRegion( + SelectedRegion(playRegion.GetStart(), playRegion.GetEnd()), options, mode); } @@ -513,7 +513,7 @@ void TranscriptionToolBar::PlayAtSpeed(bool looped, bool cutPreview) { auto &scrubber = Scrubber::Get( *p ); scrubber.StartSpeedPlay(GetPlaySpeed(), - playRegionStart, playRegionEnd); + playRegion.GetStart(), playRegion.GetEnd()); } }