1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-06 07:29:07 +02:00

Free AudioIO from cycles, 24 files left in the big component

This commit is contained in:
Paul Licameli 2019-06-24 12:22:27 -04:00
commit b8838b38ed
10 changed files with 67 additions and 34 deletions

View File

@ -441,6 +441,7 @@ time warp info and AudioIOListener and whether the playback is looped.
#endif #endif
#include <wx/app.h> #include <wx/app.h>
#include <wx/frame.h>
#include <wx/wxcrtvararg.h> #include <wx/wxcrtvararg.h>
#include <wx/log.h> #include <wx/log.h>
#include <wx/textctrl.h> #include <wx/textctrl.h>
@ -455,14 +456,12 @@ time warp info and AudioIOListener and whether the playback is looped.
#include "prefs/GUISettings.h" #include "prefs/GUISettings.h"
#include "Prefs.h" #include "Prefs.h"
#include "Project.h" #include "Project.h"
#include "ProjectWindow.h"
#include "WaveTrack.h" #include "WaveTrack.h"
#include "AutoRecovery.h" #include "AutoRecovery.h"
#include "effects/RealtimeEffectManager.h" #include "effects/RealtimeEffectManager.h"
#include "prefs/QualityPrefs.h" #include "prefs/QualityPrefs.h"
#include "prefs/RecordingPrefs.h" #include "prefs/RecordingPrefs.h"
#include "toolbars/ControlToolBar.h"
#include "widgets/MeterPanelBase.h" #include "widgets/MeterPanelBase.h"
#include "widgets/AudacityMessageBox.h" #include "widgets/AudacityMessageBox.h"
#include "widgets/ErrorDialog.h" #include "widgets/ErrorDialog.h"
@ -519,8 +518,6 @@ constexpr size_t TimeQueueGrainSize = 2000;
#ifdef EXPERIMENTAL_SCRUBBING_SUPPORT #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
#include "tracks/ui/Scrubbing.h"
#ifdef __WXGTK__ #ifdef __WXGTK__
// Might #define this for a useful thing on Linux // Might #define this for a useful thing on Linux
#undef REALTIME_ALSA_THREAD #undef REALTIME_ALSA_THREAD
@ -1431,7 +1428,7 @@ void AudioIO::StartMonitoring( const AudioIOStartStreamOptions &options )
if (!success) { if (!success) {
wxString msg = wxString::Format(_("Error opening recording device.\nError code: %s"), Get()->LastPaErrorString()); 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")); _("Error"), msg, wxT("Error_opening_sound_device"));
return; return;
} }
@ -1705,17 +1702,11 @@ int AudioIO::StartStream(const TransportTracks &tracks,
mAudioThreadShouldCallFillBuffersOnce = true; mAudioThreadShouldCallFillBuffersOnce = true;
while( mAudioThreadShouldCallFillBuffersOnce ) { while( mAudioThreadShouldCallFillBuffersOnce ) {
#ifndef USE_SCRUB_THREAD auto interval = 50ull;
// Yuck, we either have to poll "by hand" when scrub polling doesn't if (options.playbackStreamPrimer) {
// work with a thread, or else yield to timer messages, but that would interval = options.playbackStreamPrimer();
// execute too much else
if (mScrubState) {
Scrubber::Get( *mOwningProject ).ContinueScrubbingPoll();
wxMilliSleep( Scrubber::ScrubPollInterval_ms * 0.9 );
} }
else wxMilliSleep( interval );
#endif
wxMilliSleep( 50 );
} }
if(mNumPlaybackChannels > 0 || mNumCaptureChannels > 0) { if(mNumPlaybackChannels > 0 || mNumCaptureChannels > 0) {
@ -2363,8 +2354,8 @@ void AudioIO::StopStream()
} }
} }
ControlToolBar &bar = ControlToolBar::Get( *mOwningProject ); if (mListener)
bar.CommitRecording(); mListener->OnCommitRecording();
} }
} }
@ -2545,7 +2536,7 @@ AudioThread::ExitCode AudioThread::Entry()
{ {
using Clock = std::chrono::steady_clock; using Clock = std::chrono::steady_clock;
auto loopPassStart = Clock::now(); auto loopPassStart = Clock::now();
const auto interval = Scrubber::ScrubPollInterval_ms; const auto interval = ScrubPollInterval_ms;
// Set LoopActive outside the tests to avoid race condition // Set LoopActive outside the tests to avoid race condition
gAudioIO->mAudioThreadFillBuffersLoopActive = true; gAudioIO->mAudioThreadFillBuffersLoopActive = true;
@ -3692,8 +3683,8 @@ void AudioIoCallback::CheckSoundActivatedRecordingLevel( const void *inputBuffer
bool bShouldBePaused = mInputMeter->GetMaxPeak() < mSilenceLevel; bool bShouldBePaused = mInputMeter->GetMaxPeak() < mSilenceLevel;
if( bShouldBePaused != IsPaused()) if( bShouldBePaused != IsPaused())
{ {
auto &bar = ControlToolBar::Get( *mOwningProject ); if ( mListener )
bar.CallAfter(&ControlToolBar::Pause); mListener->OnSoundActivationThreshold();
} }
} }

View File

@ -789,4 +789,6 @@ private:
void StartStreamCleanup(bool bOnlyBuffers = false); void StartStreamCleanup(bool bOnlyBuffers = false);
}; };
static constexpr unsigned ScrubPollInterval_ms = 50;
#endif #endif

View File

@ -16,6 +16,7 @@ Paul Licameli split from AudioIO.h
#include <atomic> #include <atomic>
#include <cfloat> #include <cfloat>
#include <functional>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <wx/string.h> #include <wx/string.h>
@ -102,6 +103,11 @@ struct AudioIOStartStreamOptions
// contents may get swapped with empty vector // contents may get swapped with empty vector
PRCrossfadeData *pCrossfadeData{}; 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 ///\brief A singleton object supporting queries of the state of any active

View File

@ -28,6 +28,14 @@ public:
virtual void OnAudioIOStartRecording() = 0; virtual void OnAudioIOStartRecording() = 0;
virtual void OnAudioIOStopRecording() = 0; virtual void OnAudioIOStopRecording() = 0;
virtual void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) = 0; virtual void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) = 0;
// 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 #endif

View File

@ -175,6 +175,22 @@ void ProjectAudioManager::OnAudioIONewBlockFiles(
} }
} }
void ProjectAudioManager::OnCommitRecording()
{
const auto project = &mProject;
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 AudioIOStartStreamOptions
DefaultPlayOptions( AudacityProject &project ) DefaultPlayOptions( AudacityProject &project )
{ {

View File

@ -40,6 +40,8 @@ private:
void OnAudioIOStartRecording() override; void OnAudioIOStartRecording() override;
void OnAudioIOStopRecording() override; void OnAudioIOStopRecording() override;
void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override; void OnAudioIONewBlockFiles(const AutoSaveFile & blockFileLog) override;
void OnCommitRecording() override;
void OnSoundActivationThreshold() override;
AudacityProject &mProject; AudacityProject &mProject;

View File

@ -1521,12 +1521,6 @@ void ControlToolBar::StopScrolling()
(ProjectWindow::PlaybackScroller::Mode::Off); (ProjectWindow::PlaybackScroller::Mode::Off);
} }
void ControlToolBar::CommitRecording()
{
const auto project = &mProject;
TrackList::Get( *project ).ApplyPendingTracks();
}
void ControlToolBar::CancelRecording() void ControlToolBar::CancelRecording()
{ {
const auto project = &mProject; const auto project = &mProject;

View File

@ -135,9 +135,6 @@ class ControlToolBar final : public ToolBar {
void StartScrolling(); void StartScrolling();
void StopScrolling(); void StopScrolling();
// Commit the addition of temporary recording tracks into the project
void CommitRecording();
// Cancel the addition of temporary recording tracks into the project // Cancel the addition of temporary recording tracks into the project
void CancelRecording(); void CancelRecording();

View File

@ -56,8 +56,6 @@ enum {
ScrubSpeedStepsPerOctave = 4, ScrubSpeedStepsPerOctave = 4,
#endif #endif
ScrubPollInterval_ms = 50,
kOneSecondCountdown = 1000 / ScrubPollInterval_ms, kOneSecondCountdown = 1000 / ScrubPollInterval_ms,
}; };
@ -386,6 +384,16 @@ bool Scrubber::MaybeStartScrubbing(wxCoord xx)
mSpeedPlaying = false; mSpeedPlaying = false;
auto options = auto options =
DefaultPlayOptions( *mProject ); 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.pScrubbingOptions = &mOptions;
options.envelope = nullptr; options.envelope = nullptr;
mOptions.delay = (ScrubPollInterval_ms / 1000.0); mOptions.delay = (ScrubPollInterval_ms / 1000.0);
@ -487,6 +495,17 @@ bool Scrubber::StartSpeedPlay(double speed, double time0, double time1)
mDragging = false; mDragging = false;
auto options = DefaultSpeedPlayOptions( *mProject ); 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.pScrubbingOptions = &mOptions;
options.envelope = nullptr; options.envelope = nullptr;
mOptions.delay = (ScrubPollInterval_ms / 1000.0); mOptions.delay = (ScrubPollInterval_ms / 1000.0);

View File

@ -41,8 +41,6 @@ class Scrubber final
, public ClientData::Base , public ClientData::Base
{ {
public: public:
static constexpr unsigned ScrubPollInterval_ms = 50;
static Scrubber &Get( AudacityProject &project ); static Scrubber &Get( AudacityProject &project );
static const Scrubber &Get( const AudacityProject &project ); static const Scrubber &Get( const AudacityProject &project );