diff --git a/src/ProjectAudioManager.cpp b/src/ProjectAudioManager.cpp index a4a006326..c80c3f661 100644 --- a/src/ProjectAudioManager.cpp +++ b/src/ProjectAudioManager.cpp @@ -192,6 +192,18 @@ void ProjectAudioManager::OnSoundActivationThreshold() } } +bool ProjectAudioManager::Playing() const +{ + auto gAudioIO = AudioIO::Get(); + return + gAudioIO->IsBusy() && + ControlToolBar::Get( mProject ).CanStopAudioStream() && + // ... and not merely monitoring + !gAudioIO->IsMonitoring() && + // ... and not punch-and-roll recording + gAudioIO->GetNumCaptureChannels() == 0; +} + bool ProjectAudioManager::Recording() const { auto gAudioIO = AudioIO::Get(); @@ -265,7 +277,6 @@ bool DoPlayStopSelect //If busy, stop playing, make sure everything is unpaused. if (scrubber.HasMark() || gAudioIO->IsStreamActive(token)) { - toolbar.SetPlay(false); //Pops toolbar.SetStop(true); //Pushes stop down // change the selection @@ -321,7 +332,6 @@ void DoPlayStopSelect(AudacityProject &project) 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 diff --git a/src/ProjectAudioManager.h b/src/ProjectAudioManager.h index d3a6cad4f..67bba4da7 100644 --- a/src/ProjectAudioManager.h +++ b/src/ProjectAudioManager.h @@ -36,16 +36,22 @@ public: void ResetTimerRecordCancelled() { mTimerRecordCanceled = false; } bool Paused() const { return mPaused; } - + + bool Playing() const; + // Whether recording into this project (not just into some project) is // active bool Recording() const; // Whether the last attempt to start recording requested appending to tracks bool Appending() const { return mAppending; } + bool Looping() const { return mLooping; } + bool Cutting() const { return mCutting; } void SetPaused( bool value ) { mPaused = value; } void SetAppending( bool value ) { mAppending = value; } + void SetLooping( bool value ) { mLooping = value; } + void SetCutting( bool value ) { mCutting = value; } private: // Audio IO callback methods @@ -63,6 +69,8 @@ private: bool mPaused{ false }; bool mAppending{ false }; + bool mLooping{ false }; + bool mCutting{ false }; }; AudioIOStartStreamOptions DefaultPlayOptions( AudacityProject &project ); diff --git a/src/menus/TransportMenus.cpp b/src/menus/TransportMenus.cpp index adaff0849..5cb99df4f 100644 --- a/src/menus/TransportMenus.cpp +++ b/src/menus/TransportMenus.cpp @@ -42,8 +42,7 @@ namespace { /// and pops the play button up. Then, if nothing is now /// playing, it pushes the play button down and enables /// the stop button. -bool MakeReadyToPlay(AudacityProject &project, - bool loop = false, bool cutpreview = false) +bool MakeReadyToPlay(AudacityProject &project) { auto &toolbar = ControlToolBar::Get( project ); wxCommandEvent evt; @@ -53,6 +52,7 @@ bool MakeReadyToPlay(AudacityProject &project, if (gAudioIO->IsStreamActive( ProjectAudioIO::Get( project ).GetAudioIOToken() )) { + // Make momentary changes of button appearances toolbar.SetPlay(false); //Pops toolbar.SetStop(true); //Pushes stop down toolbar.OnStop(evt); @@ -65,11 +65,6 @@ bool MakeReadyToPlay(AudacityProject &project, if (gAudioIO->IsBusy()) return false; - ControlToolBar::PlayAppearance appearance = - cutpreview ? ControlToolBar::PlayAppearance::CutPreview - : loop ? ControlToolBar::PlayAppearance::Looped - : ControlToolBar::PlayAppearance::Straight; - toolbar.SetPlay(true, appearance); toolbar.SetStop(false); return true; @@ -97,7 +92,6 @@ void DoPlayStop(const CommandContext &context) //If this project is playing, stop playing, make sure everything is unpaused. auto gAudioIO = AudioIOBase::Get(); if (gAudioIO->IsStreamActive(token)) { - toolbar.SetPlay(false); //Pops toolbar.SetStop(true); //Pushes stop down toolbar.StopPlaying(); } @@ -116,7 +110,6 @@ void DoPlayStop(const CommandContext &context) if(iter != finish) { auto otherProject = *iter; auto &otherToolbar = ControlToolBar::Get( *otherProject ); - otherToolbar.SetPlay(false); //Pops otherToolbar.SetStop(true); //Pushes stop down otherToolbar.StopPlaying(); } @@ -126,7 +119,6 @@ void DoPlayStop(const CommandContext &context) //update the playing area window.TP_DisplaySelection(); //Otherwise, start playing (assuming audio I/O isn't busy) - //toolbar->SetPlay(true); // Not needed as done in PlayPlayRegion. toolbar.SetStop(false); // Will automatically set mLastPlayMode @@ -135,7 +127,6 @@ void DoPlayStop(const CommandContext &context) } else if (!gAudioIO->IsBusy()) { //Otherwise, start playing (assuming audio I/O isn't busy) - //toolbar->SetPlay(true); // Not needed as done in PlayPlayRegion. toolbar.SetStop(false); // Will automatically set mLastPlayMode @@ -223,7 +214,7 @@ void OnPlayLooped(const CommandContext &context) { auto &project = context.project; - if( !MakeReadyToPlay(project, true) ) + if( !MakeReadyToPlay(project) ) return; // Now play in a loop @@ -790,7 +781,7 @@ void OnPlayCutPreview(const CommandContext &context) { auto &project = context.project; - if ( !MakeReadyToPlay(project, false, true) ) + if ( !MakeReadyToPlay(project) ) return; // Play with cut preview diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index 42a3209d9..a2eedb66f 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -535,6 +535,8 @@ int ControlToolBar::PlayPlayRegion(const SelectedRegion &selectedRegion, bool playWhiteSpace /* = false */) // STRONG-GUARANTEE (for state of mCutPreviewTracks) { + auto &projectAudioManager = ProjectAudioManager::Get( mProject ); + if (!CanStopAudioStream()) return -1; @@ -556,23 +558,12 @@ int ControlToolBar::PlayPlayRegion(const SelectedRegion &selectedRegion, if (backwards) std::swap(t0, t1); - { - PlayAppearance appearance; - switch( mode ) { - case PlayMode::cutPreviewPlay: - appearance = PlayAppearance::CutPreview; break; - case PlayMode::loopedPlay: - appearance = PlayAppearance::Looped; break; - default: - appearance = PlayAppearance::Straight; break; - } - SetPlay(true, appearance); - } + projectAudioManager.SetLooping( mode == PlayMode::loopedPlay ); + projectAudioManager.SetCutting( mode == PlayMode::cutPreviewPlay ); bool success = false; auto cleanup = finally( [&] { if (!success) { - SetPlay(false); SetStop(false); } } ); @@ -744,25 +735,28 @@ void ControlToolBar::PlayCurrentRegion(bool looped /* = false */, void ControlToolBar::OnKeyEvent(wxKeyEvent & event) { + // PRL: is this handler really ever reached? Is the ControlToolBar ever + // focused? Isn't there a global event filter that interprets the spacebar + // key (or other key chosen in preferences) and dispatches to DoPlayStop, + // according to CommandManager's table, before we come to this redundant + // function? + if (event.ControlDown() || event.AltDown()) { event.Skip(); return; } auto gAudioIO = AudioIOBase::Get(); + auto &projectAudioManager = ProjectAudioManager::Get( mProject ); // Does not appear to be needed on Linux. Perhaps on some other platform? // If so, "!CanStopAudioStream()" should probably apply. if (event.GetKeyCode() == WXK_SPACE) { - if (gAudioIO->IsStreamActive( - ProjectAudioIO::Get( mProject ).GetAudioIOToken() - )) { - SetPlay(false); + if ( projectAudioManager.Playing() || projectAudioManager.Recording() ) { SetStop(true); StopPlaying(); } else if (!gAudioIO->IsBusy()) { - //SetPlay(true);// Not needed as done in PlayPlayRegion SetStop(false); PlayCurrentRegion(); } @@ -833,7 +827,9 @@ void ControlToolBar::StopPlaying(bool stopStream /* = true*/) SetStop(false); if(stopStream) gAudioIO->StopStream(); - SetPlay(false); + + projectAudioManager.SetLooping( false ); + projectAudioManager.SetCutting( false ); #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT gAudioIO->AILADisable(); @@ -1068,7 +1064,6 @@ bool ControlToolBar::DoRecord(AudacityProject &project, bool success = false; auto cleanup = finally([&] { if (!success) { - SetPlay(false); SetStop(false); } }); @@ -1296,6 +1291,28 @@ void ControlToolBar::OnIdle(wxIdleEvent & event) mRecord->PushDown(); mRecord->SetAlternateIdx( projectAudioManager.Appending() ? 0 : 1 ); } + + if ( !(projectAudioManager.Playing() || Scrubber::Get(mProject).HasMark()) + ) { + mPlay->PopUp(); + mPlay->SetAlternateIdx( + wxGetKeyState(WXK_CONTROL) + ? 2 + : wxGetKeyState(WXK_SHIFT) + ? 1 + : 0 + ); + } + else { + mPlay->PushDown(); + mPlay->SetAlternateIdx( + projectAudioManager.Cutting() + ? 2 + : projectAudioManager.Looping() + ? 1 + : 0 + ); + } UpdateStatusBar(); EnableDisableButtons(); diff --git a/src/tracks/ui/Scrubbing.cpp b/src/tracks/ui/Scrubbing.cpp index c018944c2..630671a30 100644 --- a/src/tracks/ui/Scrubbing.cpp +++ b/src/tracks/ui/Scrubbing.cpp @@ -330,7 +330,6 @@ void Scrubber::MarkScrubStart( mSeeking = seek; CheckMenuItems(); - ctb.SetPlay(true, ControlToolBar::PlayAppearance::Straight ); // Commented out for Bug 1421 // mSeeking // ? ControlToolBar::PlayAppearance::Seek @@ -732,14 +731,6 @@ void Scrubber::StopScrubbing() mDragging = false; mSeeking = false; - if (!IsScrubbing()) - { - // Marked scrub start, but - // didn't really play, but did change button apperance - auto &ctb = ControlToolBar::Get( *mProject ); - ctb.SetPlay(false, ControlToolBar::PlayAppearance::Straight); - } - AdornedRulerPanel::Get( *mProject ).DrawBothOverlays(); CheckMenuItems(); }