From ed5c92450db230a156510a7cd3b8e858c03f2cdd Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Wed, 19 Jun 2019 21:11:40 -0400 Subject: [PATCH 1/4] CommitRecording out of ControlToolBar --- src/AudioIO.cpp | 4 ++-- src/AudioIOListener.h | 4 ++++ src/ProjectAudioManager.cpp | 6 ++++++ src/ProjectAudioManager.h | 1 + src/toolbars/ControlToolBar.cpp | 6 ------ src/toolbars/ControlToolBar.h | 3 --- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 4e61b5545..1fb073687 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -2363,8 +2363,8 @@ void AudioIO::StopStream() } } - ControlToolBar &bar = ControlToolBar::Get( *mOwningProject ); - bar.CommitRecording(); + if (mListener) + mListener->OnCommitRecording(); } } diff --git a/src/AudioIOListener.h b/src/AudioIOListener.h index e23e6b580..f9739e44d 100644 --- a/src/AudioIOListener.h +++ b/src/AudioIOListener.h @@ -28,6 +28,10 @@ public: virtual void OnAudioIOStartRecording() = 0; virtual void OnAudioIOStopRecording() = 0; virtual void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) = 0; + + // Commit the addition of temporary recording tracks into the project + virtual void OnCommitRecording() = 0; + }; #endif diff --git a/src/ProjectAudioManager.cpp b/src/ProjectAudioManager.cpp index e6337f3a6..4a346c5cc 100644 --- a/src/ProjectAudioManager.cpp +++ b/src/ProjectAudioManager.cpp @@ -175,6 +175,12 @@ void ProjectAudioManager::OnAudioIONewBlockFiles( } } +void ProjectAudioManager::OnCommitRecording() +{ + const auto project = &mProject; + TrackList::Get( *project ).ApplyPendingTracks(); +} + AudioIOStartStreamOptions DefaultPlayOptions( AudacityProject &project ) { diff --git a/src/ProjectAudioManager.h b/src/ProjectAudioManager.h index c56026b42..b5e25238b 100644 --- a/src/ProjectAudioManager.h +++ b/src/ProjectAudioManager.h @@ -40,6 +40,7 @@ private: void OnAudioIOStartRecording() override; void OnAudioIOStopRecording() override; void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override; + void OnCommitRecording() override; AudacityProject &mProject; diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index 2eca5c15b..a342db3ed 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -1521,12 +1521,6 @@ void ControlToolBar::StopScrolling() (ProjectWindow::PlaybackScroller::Mode::Off); } -void ControlToolBar::CommitRecording() -{ - const auto project = &mProject; - TrackList::Get( *project ).ApplyPendingTracks(); -} - void ControlToolBar::CancelRecording() { const auto project = &mProject; diff --git a/src/toolbars/ControlToolBar.h b/src/toolbars/ControlToolBar.h index 13ff7bd9b..710a1a4f6 100644 --- a/src/toolbars/ControlToolBar.h +++ b/src/toolbars/ControlToolBar.h @@ -135,9 +135,6 @@ class ControlToolBar final : public ToolBar { void StartScrolling(); void StopScrolling(); - // Commit the addition of temporary recording tracks into the project - void CommitRecording(); - // Cancel the addition of temporary recording tracks into the project void CancelRecording(); From bcc90ee91a15b784771f2748f9416b913453c4b5 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 24 Jun 2019 10:52:57 -0400 Subject: [PATCH 2/4] AudioIO does not need ProjectWindow --- src/AudioIO.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 1fb073687..6d3a5290d 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -441,6 +441,7 @@ time warp info and AudioIOListener and whether the playback is looped. #endif #include +#include #include #include #include @@ -455,7 +456,6 @@ time warp info and AudioIOListener and whether the playback is looped. #include "prefs/GUISettings.h" #include "Prefs.h" #include "Project.h" -#include "ProjectWindow.h" #include "WaveTrack.h" #include "AutoRecovery.h" @@ -1431,7 +1431,7 @@ void AudioIO::StartMonitoring( const AudioIOStartStreamOptions &options ) if (!success) { wxString msg = wxString::Format(_("Error opening recording device.\nError code: %s"), Get()->LastPaErrorString()); - ShowErrorDialog( ProjectWindow::Find( mOwningProject ), + ShowErrorDialog( FindProjectFrame( mOwningProject ), _("Error"), msg, wxT("Error_opening_sound_device")); return; } From d9b780b0673d0019d77527f33f05dd6b89eacc08 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 24 Jun 2019 11:11:45 -0400 Subject: [PATCH 3/4] AudioIO does not depend directly on ControlToolBar ... ... use one more callback in the listener to change the ControlToolBar pause state. --- src/AudioIO.cpp | 5 ++--- src/AudioIOListener.h | 4 ++++ src/ProjectAudioManager.cpp | 10 ++++++++++ src/ProjectAudioManager.h | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 6d3a5290d..859eb5e6e 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -462,7 +462,6 @@ time warp info and AudioIOListener and whether the playback is looped. #include "effects/RealtimeEffectManager.h" #include "prefs/QualityPrefs.h" #include "prefs/RecordingPrefs.h" -#include "toolbars/ControlToolBar.h" #include "widgets/MeterPanelBase.h" #include "widgets/AudacityMessageBox.h" #include "widgets/ErrorDialog.h" @@ -3692,8 +3691,8 @@ void AudioIoCallback::CheckSoundActivatedRecordingLevel( const void *inputBuffer bool bShouldBePaused = mInputMeter->GetMaxPeak() < mSilenceLevel; if( bShouldBePaused != IsPaused()) { - auto &bar = ControlToolBar::Get( *mOwningProject ); - bar.CallAfter(&ControlToolBar::Pause); + if ( mListener ) + mListener->OnSoundActivationThreshold(); } } diff --git a/src/AudioIOListener.h b/src/AudioIOListener.h index f9739e44d..bcf58f566 100644 --- a/src/AudioIOListener.h +++ b/src/AudioIOListener.h @@ -32,6 +32,10 @@ public: // Commit the addition of temporary recording tracks into the project virtual void OnCommitRecording() = 0; + // During recording, the threshold for sound activation has been crossed + // in either direction + virtual void OnSoundActivationThreshold() = 0; + }; #endif diff --git a/src/ProjectAudioManager.cpp b/src/ProjectAudioManager.cpp index 4a346c5cc..e7e7cec35 100644 --- a/src/ProjectAudioManager.cpp +++ b/src/ProjectAudioManager.cpp @@ -181,6 +181,16 @@ void ProjectAudioManager::OnCommitRecording() TrackList::Get( *project ).ApplyPendingTracks(); } +void ProjectAudioManager::OnSoundActivationThreshold() +{ + auto &project = mProject; + auto gAudioIO = AudioIO::Get(); + if ( gAudioIO && &project == gAudioIO->GetOwningProject() ) { + auto &bar = ControlToolBar::Get( project ); + bar.CallAfter(&ControlToolBar::Pause); + } +} + AudioIOStartStreamOptions DefaultPlayOptions( AudacityProject &project ) { diff --git a/src/ProjectAudioManager.h b/src/ProjectAudioManager.h index b5e25238b..622f598ce 100644 --- a/src/ProjectAudioManager.h +++ b/src/ProjectAudioManager.h @@ -41,6 +41,7 @@ private: void OnAudioIOStopRecording() override; void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override; void OnCommitRecording() override; + void OnSoundActivationThreshold() override; AudacityProject &mProject; From 5627620b7885808bc251853dc683d829359695e8 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 24 Jun 2019 12:18:50 -0400 Subject: [PATCH 4/4] Remove dependency of AudioIO on Scrubbing.cpp ... ... though the demotion of the constant into AudioIO.h isn't wholly satisfactory and there is still the scrubbing queue in AudioIO --- src/AudioIO.cpp | 18 +++++------------- src/AudioIO.h | 2 ++ src/AudioIOBase.h | 6 ++++++ src/tracks/ui/Scrubbing.cpp | 23 +++++++++++++++++++++-- src/tracks/ui/Scrubbing.h | 4 +--- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 859eb5e6e..de431c6d7 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -518,8 +518,6 @@ constexpr size_t TimeQueueGrainSize = 2000; #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT -#include "tracks/ui/Scrubbing.h" - #ifdef __WXGTK__ // Might #define this for a useful thing on Linux #undef REALTIME_ALSA_THREAD @@ -1704,17 +1702,11 @@ int AudioIO::StartStream(const TransportTracks &tracks, mAudioThreadShouldCallFillBuffersOnce = true; while( mAudioThreadShouldCallFillBuffersOnce ) { -#ifndef USE_SCRUB_THREAD - // Yuck, we either have to poll "by hand" when scrub polling doesn't - // work with a thread, or else yield to timer messages, but that would - // execute too much else - if (mScrubState) { - Scrubber::Get( *mOwningProject ).ContinueScrubbingPoll(); - wxMilliSleep( Scrubber::ScrubPollInterval_ms * 0.9 ); + auto interval = 50ull; + if (options.playbackStreamPrimer) { + interval = options.playbackStreamPrimer(); } - else -#endif - wxMilliSleep( 50 ); + wxMilliSleep( interval ); } if(mNumPlaybackChannels > 0 || mNumCaptureChannels > 0) { @@ -2544,7 +2536,7 @@ AudioThread::ExitCode AudioThread::Entry() { using Clock = std::chrono::steady_clock; auto loopPassStart = Clock::now(); - const auto interval = Scrubber::ScrubPollInterval_ms; + const auto interval = ScrubPollInterval_ms; // Set LoopActive outside the tests to avoid race condition gAudioIO->mAudioThreadFillBuffersLoopActive = true; diff --git a/src/AudioIO.h b/src/AudioIO.h index c5de9bd2b..215d76149 100644 --- a/src/AudioIO.h +++ b/src/AudioIO.h @@ -789,4 +789,6 @@ private: void StartStreamCleanup(bool bOnlyBuffers = false); }; +static constexpr unsigned ScrubPollInterval_ms = 50; + #endif diff --git a/src/AudioIOBase.h b/src/AudioIOBase.h index 96526696c..d72391546 100644 --- a/src/AudioIOBase.h +++ b/src/AudioIOBase.h @@ -16,6 +16,7 @@ Paul Licameli split from AudioIO.h #include #include +#include #include #include #include @@ -102,6 +103,11 @@ struct AudioIOStartStreamOptions // contents may get swapped with empty vector PRCrossfadeData *pCrossfadeData{}; + + // An unfortunate thing needed just to make scrubbing work on Linux when + // we can't use a separate polling thread. + // The return value is a number of milliseconds to sleep before calling again + std::function< unsigned long() > playbackStreamPrimer; }; ///\brief A singleton object supporting queries of the state of any active diff --git a/src/tracks/ui/Scrubbing.cpp b/src/tracks/ui/Scrubbing.cpp index e0ad1a4e6..1b28fd20f 100644 --- a/src/tracks/ui/Scrubbing.cpp +++ b/src/tracks/ui/Scrubbing.cpp @@ -56,8 +56,6 @@ enum { ScrubSpeedStepsPerOctave = 4, #endif - ScrubPollInterval_ms = 50, - kOneSecondCountdown = 1000 / ScrubPollInterval_ms, }; @@ -386,6 +384,16 @@ bool Scrubber::MaybeStartScrubbing(wxCoord xx) mSpeedPlaying = false; auto options = DefaultPlayOptions( *mProject ); + +#ifndef USE_SCRUB_THREAD + // Yuck, we either have to poll "by hand" when scrub polling doesn't + // work with a thread, or else yield to timer messages, but that would + // execute too much else + options.playbackStreamPrimer = [this](){ + ContinueScrubbingPoll(); + return ScrubPollInterval_ms; + }; +#endif options.pScrubbingOptions = &mOptions; options.envelope = nullptr; mOptions.delay = (ScrubPollInterval_ms / 1000.0); @@ -487,6 +495,17 @@ bool Scrubber::StartSpeedPlay(double speed, double time0, double time1) mDragging = false; auto options = DefaultSpeedPlayOptions( *mProject ); + +#ifndef USE_SCRUB_THREAD + // Yuck, we either have to poll "by hand" when scrub polling doesn't + // work with a thread, or else yield to timer messages, but that would + // execute too much else + options.playbackStreamPrimer = [this](){ + ContinueScrubbingPoll(); + return ScrubPollInterval_ms; + }; +#endif + options.pScrubbingOptions = &mOptions; options.envelope = nullptr; mOptions.delay = (ScrubPollInterval_ms / 1000.0); diff --git a/src/tracks/ui/Scrubbing.h b/src/tracks/ui/Scrubbing.h index f32de50e4..62e03883c 100644 --- a/src/tracks/ui/Scrubbing.h +++ b/src/tracks/ui/Scrubbing.h @@ -40,9 +40,7 @@ class Scrubber final : public wxEvtHandler , public ClientData::Base { -public: - static constexpr unsigned ScrubPollInterval_ms = 50; - +public: static Scrubber &Get( AudacityProject &project ); static const Scrubber &Get( const AudacityProject &project );