diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index ff7a0a16a..4c247aad4 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -1529,10 +1529,14 @@ void AudacityApp::OnKeyDown(wxKeyEvent &event) // Stop play, including scrub, but not record auto project = ::GetActiveProject(); auto token = project->GetAudioIOToken(); + auto &scrubber = project->GetScrubber(); + auto scrubbing = scrubber.HasStartedScrubbing(); + if (scrubbing) + scrubber.Cancel(); if((token > 0 && gAudioIO->IsAudioTokenActive(token) && gAudioIO->GetNumCaptureChannels() == 0) || - project->GetScrubber().HasStartedScrubbing()) + scrubbing) // ESC out of other play (but not record) project->OnStop(); else diff --git a/src/Menus.cpp b/src/Menus.cpp index bd9a21549..610d9f1ec 100644 --- a/src/Menus.cpp +++ b/src/Menus.cpp @@ -2295,19 +2295,30 @@ void AudacityProject::OnRecordAppend() GetControlToolBar()->OnRecord(evt); } +// The code for "OnPlayStopSelect" is simply the code of "OnPlayStop" and "OnStopSelect" merged. void AudacityProject::OnPlayStopSelect() { - DoPlayStopSelect(false, false); + ControlToolBar *toolbar = GetControlToolBar(); + wxCommandEvent evt; + if (DoPlayStopSelect(false, false)) + toolbar->OnStop(evt); + else if (!gAudioIO->IsBusy()) { + //Otherwise, start playing (assuming audio I/O isn't busy) + //toolbar->SetPlay(true); // Not needed as set in PlayPlayRegion() + toolbar->SetStop(false); + + // Will automatically set mLastPlayMode + toolbar->PlayCurrentRegion(false); + } } -// The code for "OnPlayStopSelect" is simply the code of "OnPlayStop" and "OnStopSelect" merged. -void AudacityProject::DoPlayStopSelect(bool click, bool shift) +bool AudacityProject::DoPlayStopSelect(bool click, bool shift) { - wxCommandEvent evt; ControlToolBar *toolbar = GetControlToolBar(); //If busy, stop playing, make sure everything is unpaused. - if (gAudioIO->IsStreamActive(GetAudioIOToken())) { + if (GetScrubber().HasStartedScrubbing() || + gAudioIO->IsStreamActive(GetAudioIOToken())) { toolbar->SetPlay(false); //Pops toolbar->SetStop(true); //Pushes stop down @@ -2341,16 +2352,9 @@ void AudacityProject::DoPlayStopSelect(bool click, bool shift) selection.setT0(time, false); ModifyState(false); // without bWantsAutoSave - toolbar->OnStop(evt); - } - else if (!gAudioIO->IsBusy()) { - //Otherwise, start playing (assuming audio I/O isn't busy) - //toolbar->SetPlay(true); // Not needed as set in PlayPlayRegion() - toolbar->SetStop(false); - - // Will automatically set mLastPlayMode - toolbar->PlayCurrentRegion(false); + return true; } + return false; } void AudacityProject::OnStopSelect() diff --git a/src/Menus.h b/src/Menus.h index cfb115c0f..0b7e6a43f 100644 --- a/src/Menus.h +++ b/src/Menus.h @@ -80,7 +80,7 @@ void OnSeekRightLong(); bool MakeReadyToPlay(bool loop = false, bool cutpreview = false); // Helper function that sets button states etc. void OnPlayStop(); -void DoPlayStopSelect(bool click, bool shift); +bool DoPlayStopSelect(bool click, bool shift); void OnPlayStopSelect(); void OnPlayOneSecond(); void OnPlayToSelection(); diff --git a/src/tracks/ui/Scrubbing.cpp b/src/tracks/ui/Scrubbing.cpp index 0bc64307c..48f2dcbe5 100644 --- a/src/tracks/ui/Scrubbing.cpp +++ b/src/tracks/ui/Scrubbing.cpp @@ -163,7 +163,7 @@ private: void Scrubber::ScrubPoller::Notify() { - // Call ContinueScrubbing() here in a timer handler + // Call Continue functions here in a timer handler // rather than in SelectionHandleDrag() // so that even without drag events, we can instruct the play head to // keep approaching the mouse cursor, when its maximum speed is limited. @@ -276,6 +276,8 @@ void Scrubber::MarkScrubStart( mScrubStartPosition = xx; ctb->UpdateStatusBar(mProject); mOptions.startClockTimeMillis = ::wxGetLocalTimeMillis(); + + mCancelled = false; } #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT @@ -453,6 +455,8 @@ void Scrubber::ContinueScrubbingUI() if (mDragging && !state.LeftIsDown()) { // Stop and set cursor mProject->DoPlayStopSelect(true, state.ShiftDown()); + wxCommandEvent evt; + mProject->GetControlToolBar()->OnStop(evt); return; } @@ -490,6 +494,12 @@ void Scrubber::StopScrubbing() mPoller->Stop(); + if (!mCancelled) { + const wxMouseState state(::wxGetMouseState()); + // Stop and set cursor + mProject->DoPlayStopSelect(true, state.ShiftDown()); + } + mScrubStartPosition = -1; mDragging = false; diff --git a/src/tracks/ui/Scrubbing.h b/src/tracks/ui/Scrubbing.h index e57b2edf7..3ef72e1cd 100644 --- a/src/tracks/ui/Scrubbing.h +++ b/src/tracks/ui/Scrubbing.h @@ -103,6 +103,9 @@ public: bool Scrubs() const { return mScrubbing; } + void Cancel() + { mCancelled = true; } + bool ShouldDrawScrubSpeed(); double FindScrubSpeed(bool seeking, double time) const; double GetMaxScrubSpeed() const { return mOptions.maxSpeed; } @@ -164,6 +167,8 @@ private: bool mDragging {}; + bool mCancelled {}; + #ifdef EXPERIMENTAL_SCRUBBING_SCROLL_WHEEL int mLogMaxScrubSpeed; #endif