diff --git a/src/AudioIO.cpp b/src/AudioIO.cpp index 01e40f157..6a65f76c8 100644 --- a/src/AudioIO.cpp +++ b/src/AudioIO.cpp @@ -1823,6 +1823,16 @@ int AudioIO::StartStream(const TransportTracks &tracks, return mStreamToken; } +void AudioIO::DelayActions(bool recording) +{ + mDelayingActions = recording; +} + +bool AudioIO::DelayingActions() const +{ + return mDelayingActions || (mPortStreamV19 && mNumCaptureChannels > 0); +} + void AudioIO::CallAfterRecording(PostRecordingAction action) { if (!action) @@ -1839,7 +1849,7 @@ void AudioIO::CallAfterRecording(PostRecordingAction action) ]{ prevAction(); nextAction(); }; return; } - else if (mPortStreamV19 && mNumCaptureChannels > 0) { + else if (DelayingActions()) { mPostRecordingAction = std::move(action); return; } @@ -2456,6 +2466,7 @@ void AudioIO::StopStream() mPostRecordingAction(); mPostRecordingAction = {}; } + DelayActions(false); }); // diff --git a/src/AudioIO.h b/src/AudioIO.h index 031aea6c0..e8a22c692 100644 --- a/src/AudioIO.h +++ b/src/AudioIO.h @@ -739,15 +739,18 @@ public: static void Init(); static void Deinit(); - + /*! For purposes of CallAfterRecording, treat time from now as if + recording (when argument is true) or not necessarily so (false) */ + void DelayActions(bool recording); private: + bool DelayingActions() const; + /** \brief Set the current VU meters - this should be done once after * each call to StartStream currently */ void SetMeters(); - /** \brief Opens the portaudio stream(s) used to do playback or recording * (or both) through. * @@ -796,6 +799,7 @@ private: std::mutex mPostRecordingActionMutex; PostRecordingAction mPostRecordingAction; + bool mDelayingActions{ false }; }; static constexpr unsigned ScrubPollInterval_ms = 50; diff --git a/src/TimerRecordDialog.cpp b/src/TimerRecordDialog.cpp index 5da326810..80c60eed0 100644 --- a/src/TimerRecordDialog.cpp +++ b/src/TimerRecordDialog.cpp @@ -40,6 +40,7 @@ #include #include // wxDateTime::UNow()) - updateResult = this->WaitForStart(); + const auto gAudioIO = AudioIO::Get(); + gAudioIO->DelayActions(true); + { + auto cleanup = finally([gAudioIO]{ gAudioIO->DelayActions(false); }); - if (updateResult != ProgressResult::Success) { - // Don't proceed, but don't treat it as canceled recording. User just canceled waiting. - return POST_TIMER_RECORD_CANCEL_WAIT; - } else { - // Record for specified time. - ProjectAudioManager::Get( mProject ).OnRecord(false); - bool bIsRecording = true; + if (m_DateTime_Start > wxDateTime::UNow()) + updateResult = this->WaitForStart(); - auto sPostAction = Verbatim( - m_pTimerAfterCompleteChoiceCtrl->GetStringSelection() ); + if (updateResult != ProgressResult::Success) { + // Don't proceed, but don't treat it as canceled recording. User just canceled waiting. + return POST_TIMER_RECORD_CANCEL_WAIT; + } else { + // Record for specified time. + ProjectAudioManager::Get( mProject ).OnRecord(false); + bool bIsRecording = true; - // Two column layout. - TimerProgressDialog::MessageTable columns{ - { - XO("Recording start:") , - XO("Duration:") , - XO("Recording end:") , - {} , - XO("Automatic Save enabled:") , - XO("Automatic Export enabled:") , - XO("Action after Timer Recording:") , - }, - { - GetDisplayDate(m_DateTime_Start) , - Verbatim( m_TimeSpan_Duration.Format() ), - GetDisplayDate(m_DateTime_End) , - {} , - (m_bAutoSaveEnabled ? XO("Yes") : XO("No")) , - (m_bAutoExportEnabled ? XO("Yes") : XO("No")) , - sPostAction , + auto sPostAction = Verbatim( + m_pTimerAfterCompleteChoiceCtrl->GetStringSelection() ); + + // Two column layout. + TimerProgressDialog::MessageTable columns{ + { + XO("Recording start:") , + XO("Duration:") , + XO("Recording end:") , + {} , + XO("Automatic Save enabled:") , + XO("Automatic Export enabled:") , + XO("Action after Timer Recording:") , + }, + { + GetDisplayDate(m_DateTime_Start) , + Verbatim( m_TimeSpan_Duration.Format() ), + GetDisplayDate(m_DateTime_End) , + {} , + (m_bAutoSaveEnabled ? XO("Yes") : XO("No")) , + (m_bAutoExportEnabled ? XO("Yes") : XO("No")) , + sPostAction , + } + }; + + TimerProgressDialog + progress(m_TimeSpan_Duration.GetMilliseconds().GetValue(), + XO("Audacity Timer Record Progress"), + columns, + pdlgHideCancelButton | pdlgConfirmStopCancel); + + // Make sure that start and end time are updated, so we always get the full + // duration, even if there's some delay getting here. + wxTimerEvent dummyTimerEvent; + this->OnTimer(dummyTimerEvent); + + // Loop for progress display during recording. + while (bIsRecording && (updateResult == ProgressResult::Success)) { + updateResult = progress.UpdateProgress(); + wxMilliSleep(kTimerInterval); + bIsRecording = (wxDateTime::UNow() <= m_DateTime_End); // Call UNow() again for extra accuracy... } - }; - - TimerProgressDialog - progress(m_TimeSpan_Duration.GetMilliseconds().GetValue(), - XO("Audacity Timer Record Progress"), - columns, - pdlgHideCancelButton | pdlgConfirmStopCancel); - - // Make sure that start and end time are updated, so we always get the full - // duration, even if there's some delay getting here. - wxTimerEvent dummyTimerEvent; - this->OnTimer(dummyTimerEvent); - - // Loop for progress display during recording. - while (bIsRecording && (updateResult == ProgressResult::Success)) { - updateResult = progress.UpdateProgress(); - wxMilliSleep(kTimerInterval); - bIsRecording = (wxDateTime::UNow() <= m_DateTime_End); // Call UNow() again for extra accuracy... } }