16#include <wx/statusbr.h>
53 return std::make_shared< ProjectAudioManager >(
project );
83 return XO(
"Actual Rate: %d").Format( rate );
96 int rate = audioManager.mDisplayedRate;
125 double trackTime,
size_t nSamples)
override;
127 bool RepositionPlayback(
129 size_t frames,
size_t available)
override;
133 {
return mReversed ? mGapLeft + mGapLength : mGapLeft; }
135 {
return mReversed ? mGapLeft : mGapLeft + mGapLength; }
137 {
return mReversed ? trackTime1 >= trackTime2 : trackTime1 <= trackTime2; }
143 double mStart = 0, mEnd = 0;
146 double mDuration1 = 0, mDuration2 = 0;
147 double mInitDuration1 = 0, mInitDuration2 = 0;
149 bool mDiscontinuity{
false };
150 bool mReversed{
false };
153CutPreviewPlaybackPolicy::CutPreviewPlaybackPolicy(
154 double gapLeft,
double gapLength)
155: mGapLeft{ gapLeft }, mGapLength{ gapLength }
157 wxASSERT(gapLength >= 0.0);
169 double right =
mEnd = schedule.
mT1;
202 auto space = std::clamp(
mGapLeft - time, 0.0, offset);
236 size_t frames = available;
237 size_t toProduce = frames;
239 if (samples1 > 0 && samples1 < frames)
241 toProduce = frames = samples1.
as_size_t();
242 else if (samples1 == 0) {
244 if (samples2 < frames) {
251 return { available, frames, toProduce };
257 auto realDuration = nSamples /
mRate;
273 return {
mEnd, std::numeric_limits<double>::infinity()};
279 const Mixers &playbackMixers,
size_t,
size_t )
284 for (
auto &pMixer : playbackMixers)
285 pMixer->Reposition(newTime,
true);
298 auto &projectAudioManager = *
this;
299 bool canStop = projectAudioManager.CanStopAudioStream();
311 double t0 = selectedRegion.
t0();
312 double t1 = selectedRegion.
t1();
323 bool success =
false;
326 if (gAudioIO->IsBusy())
330 if (cutpreview && t0==t1)
337 mLastPlayMode = mode;
345 double latestEnd =
tracks.GetEndTime();
350#if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR)
351 double initSeek = 0.0;
353 double loopOffset = 0.0;
362 if ((t0 > selectedRegion.
t0()) && (t0 < selectedRegion.
t1())) {
363 t0 = selectedRegion.
t0();
364 t1 = selectedRegion.
t1();
369 loopOffset = t0 -
tracks.GetStartTime();
373 pStartTime.emplace(loopOffset);
374 t0 =
tracks.GetStartTime();
380 t0 =
tracks.GetStartTime();
382 else if (t0 >
tracks.GetEndTime()) {
385#if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR)
389 pStartTime.emplace(initSeek);
390 t0 =
tracks.GetStartTime();
401 t0 = std::max(0.0,
std::min(t0, latestEnd));
402 t1 = std::max(0.0,
std::min(t1, latestEnd));
412 const double tless =
std::min(t0, t1);
413 const double tgreater = std::max(t0, t1);
414 double beforeLen, afterLen;
415 gPrefs->
Read(
wxT(
"/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0);
416 gPrefs->
Read(
wxT(
"/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0);
417 double tcp0 = tless-beforeLen;
418 const double diff = tgreater - tless;
419 double tcp1 = tgreater+afterLen;
424 [tless, diff](
auto&) -> std::unique_ptr<PlaybackPolicy> {
425 return std::make_unique<CutPreviewPlaybackPolicy>(tless, diff);
427 token = gAudioIO->StartStream(
429 tcp0, tcp1, tcp1, myOptions);
432 double mixerLimit = t1;
434 mixerLimit = latestEnd;
435 if (pStartTime && *pStartTime >= t1)
438 token = gAudioIO->StartStream(
440 t0, t1, mixerLimit, options);
453 window.CallAfter( [&]{
458 XO(
"Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."),
459 wxT(
"Error_opening_sound_device"),
474 auto &projectAudioManager = *
this;
475 bool canStop = projectAudioManager.CanStopAudioStream();
490 options.envelope =
nullptr;
495 PlayPlayRegion(
SelectedRegion(playRegion.GetStart(), playRegion.GetEnd()),
504 auto &projectAudioManager = *
this;
505 bool canStop = projectAudioManager.CanStopAudioStream();
513 scrubber.StopScrubbing();
518 auto cleanup =
finally( [&]{
519 projectAudioManager.SetStopping(
false );
522 if (stopStream && gAudioIO->IsBusy()) {
524 projectAudioManager.SetStopping(
true );
526 while( wxTheApp->ProcessIdle() )
531 gAudioIO->StopStream();
533 projectAudioManager.SetLooping(
false );
534 projectAudioManager.SetCutting(
false );
536 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
537 gAudioIO->AILADisable();
540 projectAudioManager.SetPausedOff();
542 gAudioIO->SetPaused(
false );
548 auto meter = projectAudioIO.GetPlaybackMeter();
553 meter = projectAudioIO.GetCaptureMeter();
566 bool strictRules = (recordingChannels <= 2);
585 if (!strictRules && !selectedOnly)
590 std::vector<unsigned> channelCounts;
591 size_t totalChannels = 0;
592 const auto range = trackList.Any<
WaveTrack>();
598 const auto nChannels = candidate->
NChannels();
599 if (strictRules && nChannels > recordingChannels) {
604 channelCounts.clear();
611 nChannels + totalChannels > recordingChannels) {
612 candidates.erase(candidates.begin());
613 auto nOldChannels = channelCounts[0];
614 assert(nOldChannels > 0);
615 channelCounts.erase(channelCounts.begin());
616 totalChannels -= nOldChannels;
618 candidates.push_back(candidate->SharedPointer<
WaveTrack>());
619 channelCounts.push_back(nChannels);
620 totalChannels += nChannels;
621 if (totalChannels >= recordingChannels)
627 if (!strictRules && !candidates.empty())
638 bool bPreferNewTrack;
639 gPrefs->
Read(
"/GUI/PreferNewTrackRecord", &bPreferNewTrack,
false);
640 const bool appendRecord = (altAppearance == bPreferNewTrack);
647 double t0 = selectedRegion.
t0();
648 double t1 = selectedRegion.t1();
660 const bool anySelected{ selectedTracks.anySelected };
661 const bool allSameRate{ selectedTracks.allSameRate };
665 "for recording must all have the same sampling rate"),
666 XO(
"Mismatched Sampling Rates"),
667 wxICON_ERROR | wxCENTRE);
675 existingTracks = ChooseExistingRecordingTracks(*p,
true, rateOfSelected);
676 if (!existingTracks.empty()) {
680 options.rate = rateOfSelected;
683 if (anySelected && rateOfSelected != options.rate) {
685 "Too few tracks are selected for recording at this sample rate.\n"
686 "(Audacity requires two channels at the same sample rate for\n"
687 "each stereo track)"),
688 XO(
"Too Few Compatible Tracks Selected"),
689 wxICON_ERROR | wxCENTRE);
694 existingTracks = ChooseExistingRecordingTracks(*p,
false, options.rate);
695 if (!existingTracks.empty())
697 const auto endTime = accumulate(
698 existingTracks.begin(), existingTracks.end(),
699 std::numeric_limits<double>::lowest(),
700 [](
double acc,
auto &pTrack) {
701 return std::max(acc, pTrack->GetEndTime());
707 t0 = std::max(t0, endTime);
714 if (t1 <= selectedRegion.t0() && selectedRegion.t1() > selectedRegion.t0()) {
715 t1 = selectedRegion.t1();
730 for (
const auto &wt : existingTracks) {
732 auto it = std::find_if(
734 [&wt](
const auto& playbackSequence) {
735 return playbackSequence->FindChannelGroup() ==
736 wt->FindChannelGroup();
743 std::copy(existingTracks.begin(), existingTracks.end(),
746 DoRecord(*p, transportTracks, t0, t1, altAppearance, options);
759 double t0,
double t1,
763 auto &projectAudioManager = *
this;
777 if (gAudioIO->IsBusy())
780 projectAudioManager.SetAppending(!altAppearance);
782 bool success =
false;
784 auto transportSequences = sequences;
794 auto insertEmptyInterval =
795 [&](
WaveTrack &track,
double t0,
bool placeholder) {
797 for (
auto i = 1; ; ++i) {
799 name =
XC(
"%s.%d",
"clip name template")
800 .Format(track.
GetName(), i).Translation();
807 clip->SetIsPlaceholder(
true);
810 clip->SetIsPlaceholder(
false);
822 if (!(wt =
dynamic_cast<WaveTrack *
>(sequence.get()))) {
826 auto endTime = wt->GetEndTime();
831 const auto shared = wt->SharedPointer<
WaveTrack>();
833 const auto &range = transportSequences.playbackSequences;
834 bool prerollTrack = any_of(range.begin(), range.end(),
835 [&](
const auto &pSequence){
836 return shared.get() == pSequence->FindChannelGroup(); });
838 transportSequences.prerollSequences.push_back(shared);
846 auto &src =
static_cast<const WaveTrack&
>(s);
854 const auto lastClip = wt->GetRightmostClip();
859 const auto recordingStart =
860 std::round(t0 * wt->GetRate()) / wt->GetRate();
861 const auto recordingStartsBeforeTrackEnd =
862 lastClip && recordingStart < lastClip->GetPlayEndTime();
867 !recordingStartsBeforeTrackEnd ||
868 lastClip->WithinPlayRegion(recordingStart));
870 if (!recordingStartsBeforeTrackEnd ||
871 lastClip->HasPitchOrSpeed())
872 newClip = insertEmptyInterval(*wt, t0,
true);
875 const auto pending =
static_cast<WaveTrack*
>(
876 pendingTracks.RegisterPendingChangedTrack(
updater, wt)
881 newClip->SetIsPlaceholder(
false);
882 if (
auto copiedClip = pending->NewestOrNewClip())
883 copiedClip->SetIsPlaceholder(
false);
884 transportSequences.captureSequences
885 .push_back(pending->SharedPointer<
WaveTrack>());
887 pendingTracks.UpdatePendingTracks();
890 if (transportSequences.captureSequences.empty()) {
892 bool recordingNameCustom, useTrackNumber, useDateStamp, useTimeStamp;
893 wxString defaultTrackName, defaultRecordingTrackName;
900 gPrefs->
Read(
wxT(
"/GUI/TrackNames/RecordingNameCustom"), &recordingNameCustom,
false);
901 gPrefs->
Read(
wxT(
"/GUI/TrackNames/TrackNumber"), &useTrackNumber,
false);
902 gPrefs->
Read(
wxT(
"/GUI/TrackNames/DateStamp"), &useDateStamp,
false);
903 gPrefs->
Read(
wxT(
"/GUI/TrackNames/TimeStamp"), &useTimeStamp,
false);
905 gPrefs->
Read(
wxT(
"/GUI/TrackNames/RecodingTrackName"), &defaultRecordingTrackName, defaultTrackName);
907 wxString baseTrackName = recordingNameCustom? defaultRecordingTrackName : defaultTrackName;
911 const auto first = *newTracks->begin();
912 int trackCounter = 0;
913 const auto minimizeChannelView = recordingChannels > 2
915 for (
auto newTrack : newTracks->Any<
WaveTrack>()) {
917 if (newTrack == first) {
919 t0 = newTrack->SnapToSample(t0);
921 t1 = newTrack->SnapToSample(t1);
924 newTrack->MoveTo(t0);
925 wxString nameSuffix = wxString(
wxT(
""));
927 if (useTrackNumber) {
928 nameSuffix += wxString::Format(
wxT(
"%d"), 1 + (
int) numTracks + trackCounter++);
932 if (!nameSuffix.empty()) {
933 nameSuffix +=
wxT(
"_");
935 nameSuffix += wxDateTime::Now().FormatISODate();
939 if (!nameSuffix.empty()) {
940 nameSuffix +=
wxT(
"_");
942 nameSuffix += wxDateTime::Now().FormatISOTime();
946 nameSuffix.Replace(
wxT(
":"),
wxT(
"-"));
948 if (baseTrackName.empty())
949 newTrack->SetName(nameSuffix);
950 else if (nameSuffix.empty())
951 newTrack->SetName(baseTrackName);
953 newTrack->SetName(baseTrackName +
wxT(
"_") + nameSuffix);
956 insertEmptyInterval(*newTrack, t0,
false);
958 transportSequences.captureSequences.push_back(
959 std::static_pointer_cast<WaveTrack>(newTrack->shared_from_this())
962 for(
auto channel : newTrack->Channels())
967 pendingTracks.RegisterPendingNewTracks(std::move(*newTracks));
970 if (!trackList.empty()) {
972 if (!pProject.expired()) {
973 auto &project = *pProject.lock();
974 auto &trackList = TrackList::Get(project);
975 Viewport::Get(project).ShowTrack(**trackList.rbegin());
982 #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
983 gAudioIO->AILAInitialize();
987 gAudioIO->StartStream(transportSequences, t0, t1, t1, options);
989 success = (token != 0);
998 auto msg =
XO(
"Error opening recording device.\nError code: %s")
999 .Format( gAudioIO->LastPaErrorString() );
1002 XO(
"Error"), msg,
wxT(
"Error_opening_sound_device"),
1012 auto &projectAudioManager = *
this;
1013 bool canStop = projectAudioManager.CanStopAudioStream();
1019 bool paused = !projectAudioManager.Paused();
1029 bool bStopInstead = paused &&
1031 !scrubber.IsSpeedPlaying() &&
1032 !scrubber.IsKeyboardScrubbing();
1040 scrubber.Pause(paused);
1043 constexpr auto publish =
true;
1044 gAudioIO->SetPaused(paused, publish);
1051 mPaused.fetch_xor(1, std::memory_order::memory_order_relaxed);
1056 mPaused.store(0, std::memory_order::memory_order_relaxed);
1061 return mPaused.load(std::memory_order_relaxed) == 1;
1067 const auto project = &mProject;
1075 mDisplayedRate = rate;
1096 if (projectAudioIO.GetAudioIOToken() > 0)
1100 if (IsTimerRecordCancelled()) {
1102 history.RollbackState();
1104 ResetTimerRecordCancelled();
1114 history.PushState(
XO(
"Recorded Audio"),
XO(
"Record"), flags);
1119 auto &intervals = gAudioIO->LostCaptureIntervals();
1120 if (intervals.size())
1131 wxTheApp->CallAfter( [&]{ projectFileIO.AutoSave(
true); });
1136 const auto project = &mProject;
1144 if (gAudioIO && &
project == gAudioIO->GetOwningProject().get())
1146 bool canStop = CanStopAudioStream();
1148 gAudioIO->SetPaused(!gAudioIO->IsPaused());
1169 gAudioIO->IsBusy() &&
1170 CanStopAudioStream() &&
1172 !gAudioIO->IsMonitoring() &&
1174 gAudioIO->GetNumCaptureChannels() == 0;
1181 gAudioIO->IsBusy() &&
1182 CanStopAudioStream() &&
1183 gAudioIO->GetNumCaptureChannels() > 0;
1189 return (!gAudioIO->IsStreamActive() ||
1190 gAudioIO->IsMonitoring() ||
1191 gAudioIO->GetOwningProject().get() == &mProject );
1198 bool canStop = projectAudioManager.CanStopAudioStream();
1213 options.loopEnabled = loopEnabled;
1218 options.policyFactory = [&
project, trackEndTime, loopEndTime](
1220 -> std::unique_ptr<PlaybackPolicy>
1222 return std::make_unique<DefaultPlaybackPolicy>(
project,
1223 trackEndTime, loopEndTime, options.pStartTime,
1224 options.loopEnabled, options.variableSpeed);
1239 auto PlayAtSpeedRate = gAudioIO->GetBestRate(
1244 result.rate = PlayAtSpeedRate;
1261 auto &selection = viewInfo.selectedRegion;
1265 if (scrubber.HasMark() ||
1266 gAudioIO->IsStreamActive(token)) {
1268 auto time = gAudioIO->GetStreamTime();
1271 if (click && (scrubber.WasSpeedPlaying() || scrubber.WasKeyboardScrubbing()))
1275 else if (shift && click) {
1277 auto t0 = selection.t0(), t1 = selection.t1();
1286 if (fabs(t0 - time) < fabs(t1 - time))
1291 selection.setTimes(t0, t1);
1295 time = wxMax( time, 0 );
1297 selection.setTimes(time, time);
1301 selection.setT0(time,
false);
1314 if (DoPlayStopSelect(
false,
false))
1316 else if (!gAudioIO->IsBusy()) {
1320 PlayCurrentRegion(
false);
1345 const auto selectedTracks{
1348 for (
const auto & track : selectedTracks) {
1350 track->GetRate() != rateOfSelection)
1353 rateOfSelection = track->GetRate();
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
IntSetting AudioIORecordChannels
Toolkit-neutral facade for basic user interface services.
constexpr CommandFlag AlwaysEnabledFlag
std::bitset< NCommandFlags > CommandFlag
const ReservedCommandFlag & AudioIONotBusyFlag()
const ReservedCommandFlag & PausedFlag()
constexpr size_t TimeQueueGrainSize
audacity::BasicSettings * gPrefs
std::unique_ptr< const BasicUI::WindowPlacement > ProjectFramePlacement(AudacityProject *project)
Make a WindowPlacement object suitable for project (which may be null)
static TranslatableString FormatRate(int rate)
static ProjectAudioIO::DefaultOptions::Scope sScope
Install an implementation in a library hook.
AudioIOStartStreamOptions DefaultSpeedPlayOptions(AudacityProject &project)
static RegisteredMenuItemEnabler stopIfPaused
static AudacityProject::AttachedObjects::RegisteredFactory sProjectAudioManagerKey
const ReservedCommandFlag & CanStopAudioStreamFlag()
PropertiesOfSelected GetPropertiesOfSelected(const AudacityProject &proj)
std::vector< std::shared_ptr< WritableSampleTrack > > WritableSampleTrackArray
constexpr int RATE_NOT_SELECTED
ProjectFileIOMessage
Subscribe to ProjectFileIO to receive messages; always in idle time.
@ CheckpointFailure
Failure happened in a worker thread.
an object holding per-project preferred sample rate
StatusBarField RateStatusBarField()
ID of the third field in the status bar. This field is used to display the current rate.
AUDACITY_DLL_API wxFrame & GetProjectFrame(AudacityProject &project)
Get the top-level window associated with the project (as a wxFrame only, when you do not need to use ...
accessors for certain important windows associated with each project
TransportSequences MakeTransportTracks(TrackList &trackList, bool selectedOnly, bool nonWaveToo)
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
static AudioIOBase * Get()
bool HasRecordingException() const
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
virtual size_t NChannels() const =0
Report the number of channels.
static ChannelView & Get(Channel &channel)
void SetMinimized(bool minimized)
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
bool TryToMakeActionAllowed(CommandFlag &flags, CommandFlag flagsRqd)
static CommandManager & Get(AudacityProject &project)
typename GlobalVariable< DefaultOptions, const std::function< std::remove_pointer_t< decltype(DefaultFunction)> >, Default, Options... >::Scope Scope
An explicitly nonlocalized string, not meant for the user to see.
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
static PendingTracks & Get(AudacityProject &project)
void ClearPendingTracks(std::vector< std::shared_ptr< Track > > *pAdded=nullptr)
Forget pending track additions and changes;.
bool ApplyPendingTracks()
Change the state of the project.
AudioTrack subclass that can also be audibly replayed by the program.
Directs which parts of tracks to fetch for playback.
std::vector< std::unique_ptr< Mixer > > Mixers
virtual void Initialize(PlaybackSchedule &schedule, double rate)
Called before starting an audio stream.
static AudioIOStartStreamOptions DefaultOptionsFactory(AudacityProject &project, bool newDefaults)
Default factory function ignores the second argument.
int GetAudioIOToken() const
void SetAudioIOToken(int token)
static AudioIOStartStreamOptions GetDefaultOptions(AudacityProject &project, bool newDefaults=false)
Invoke the global hook, supplying a default argument.
static ProjectAudioIO & Get(AudacityProject &project)
void Stop(bool stopStream=true)
static std::pair< TranslatableStrings, unsigned > StatusWidthFunction(const AudacityProject &project, StatusBarField field)
bool CanStopAudioStream() const
void OnAudioIONewBlocks() override
void OnAudioIOStartRecording() override
void OnCommitRecording() override
static WritableSampleTrackArray ChooseExistingRecordingTracks(AudacityProject &proj, bool selectedOnly, double targetRate=RATE_NOT_SELECTED)
Find suitable tracks to record into, or return an empty array.
void OnAudioIORate(int rate) override
static ProjectAudioManager & Get(AudacityProject &project)
void OnCheckpointFailure(ProjectFileIOMessage)
void OnAudioIOStopRecording() override
~ProjectAudioManager() override
ProjectAudioManager(AudacityProject &project)
int PlayPlayRegion(const SelectedRegion &selectedRegion, const AudioIOStartStreamOptions &options, PlayMode playMode, bool backwards=false)
bool DoRecord(AudacityProject &project, const TransportSequences &transportSequences, double t0, double t1, bool altAppearance, const AudioIOStartStreamOptions &options)
Observer::Subscription mCheckpointFailureSubscription
void PlayCurrentRegion(bool newDefault=false, bool cutpreview=false)
void OnRecord(bool altAppearance)
void OnSoundActivationThreshold() override
static ProjectFileIO & Get(AudacityProject &project)
void ModifyState(bool bWantsAutoSave)
static ProjectHistory & Get(AudacityProject &project)
static ProjectRate & Get(AudacityProject &project)
std::pair< std::vector< TranslatableString >, unsigned > StatusWidthResult
static ProjectStatus & Get(AudacityProject &project)
void Set(const TranslatableString &msg, StatusBarField field=MainStatusBarField())
static Scrubber & Get(AudacityProject &project)
Defines a selected portion of a project.
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined */
Abstract base class for an object holding data associated with points on a time axis.
const wxString & GetName() const
Name is always the same for all channels of a group.
double GetEndTime() const
Return the greatest end time of the tracks, or 0 when no tracks.
static TrackList & Get(AudacityProject &project)
auto Selected() -> TrackIterRange< TrackType >
static BoolSetting TracksFitVerticallyZoomed
Holds a msgid for the translation catalog; may also bind format arguments.
NotifyingSelectedRegion selectedRegion
static ViewInfo & Get(AudacityProject &project)
static WaveTrackFactory & Get(AudacityProject &project)
TrackListHolder CreateMany(size_t nChannels)
Creates tracks with project's default rate and format and the given number of channels.
A Track that contains audio waveform data.
bool HasClipNamed(const wxString &name) const
IntervalHolder CreateClip(double offset=.0, const wxString &name=wxEmptyString, const Interval *pToCopy=nullptr, bool copyCutlines=true)
void InsertInterval(const IntervalHolder &interval, bool newClip, bool allowEmpty=false)
static wxString GetDefaultAudioTrackNamePreference()
void Init(const WaveTrack &orig)
std::shared_ptr< Interval > IntervalHolder
size_t NChannels() const override
A constant property.
std::pair< double, double > AdvancedTrackTime(PlaybackSchedule &schedule, double trackTime, size_t nSamples) override
Compute a new point in a track's timeline from an old point and a real duration.
PlaybackSlice GetPlaybackSlice(PlaybackSchedule &schedule, size_t available) override
Choose length of one fetch of samples from tracks in a call to AudioIO::FillPlayBuffers.
double OffsetSequenceTime(PlaybackSchedule &schedule, double offset) override
Called when the play head needs to jump a certain distance.
void Initialize(PlaybackSchedule &schedule, double rate) override
Called before starting an audio stream.
double mStart
Starting and ending track times set in Initialize()
bool Done(PlaybackSchedule &schedule, unsigned long) override
Returns true if schedule.GetSequenceTime() has reached the end of playback.
~CutPreviewPlaybackPolicy() override
bool RepositionPlayback(PlaybackSchedule &schedule, const Mixers &playbackMixers, size_t frames, size_t available) override
AudioIO::FillPlayBuffers calls this to update its cursors into tracks for changes of position or spee...
const double mGapLeft
Fixed at construction time; these are a track time and duration.
bool AtOrBefore(double trackTime1, double trackTime2) const
virtual bool Read(const wxString &key, bool *value) const =0
Positions or offsets within audio files need a wide type.
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
double GetRate(const Track &track)
const char * end(const char *str) noexcept
fastfloat_really_inline void round(adjusted_mantissa &am, callback cb) noexcept
void copy(const T *src, T *dst, int32_t n)
struct holding stream options, including a pointer to the time warp info and AudioIOListener and whet...
PolicyFactory policyFactory
std::optional< double > pStartTime
Options for variations of error dialogs; the default is for modal dialogs.
double mT0
Playback starts at offset of mT0, which is measured in seconds.
double mT1
Playback ends at offset of mT1, which is measured in seconds. Note that mT1 may be less than mT0 duri...
double SolveWarpedLength(double t0, double length) const
Compute how much unwarped time must have elapsed if length seconds of warped time has elapsed,...
double GetSequenceTime() const
Get current track time value, unadjusted.
double ComputeWarpedLength(double t0, double t1) const
Compute signed duration (in seconds at playback) of the specified region of the track.
Describes an amount of contiguous (but maybe time-warped) data to be extracted from tracks to play.
Notification, after recording has stopped, when dropouts have been detected.
static bool IsScrubbing()
RecordableSequences captureSequences
ConstPlayableSequences playbackSequences