Audacity  3.2.0
ProjectAudioManager.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 ProjectAudioManager.cpp
6 
7 Paul Licameli split from ProjectManager.cpp
8 
9 **********************************************************************/
10 
11 
12 #include "ProjectAudioManager.h"
13 
14 #include <wx/app.h>
15 #include <wx/frame.h>
16 #include <wx/statusbr.h>
17 #include <algorithm>
18 
19 #include "AudioIO.h"
20 #include "BasicUI.h"
21 #include "CommonCommandFlags.h"
22 #include "Menus.h"
23 #include "Meter.h"
24 #include "Mix.h"
25 #include "Project.h"
26 #include "ProjectAudioIO.h"
27 #include "ProjectFileIO.h"
28 #include "ProjectHistory.h"
29 #include "ProjectRate.h"
30 #include "ProjectSettings.h"
31 #include "ProjectStatus.h"
32 #include "ProjectWindows.h"
33 #include "ScrubState.h"
34 #include "TrackPanelAx.h"
35 #include "UndoManager.h"
36 #include "ViewInfo.h"
37 #include "WaveTrack.h"
38 #include "toolbars/ToolManager.h"
39 #include "prefs/TracksPrefs.h"
40 #include "tracks/ui/Scrubbing.h"
41 #include "tracks/ui/TrackView.h"
42 #include "widgets/MeterPanelBase.h"
44 
45 
46 wxDEFINE_EVENT(EVT_RECORDING_DROPOUT, RecordingDropoutEvent);
47 
50  []( AudacityProject &project ) {
51  return std::make_shared< ProjectAudioManager >( project );
52  }
53 };
54 
56 {
57  return project.AttachedObjects::Get< ProjectAudioManager >(
59 }
60 
62  const AudacityProject &project )
63 {
64  return Get( const_cast< AudacityProject & >( project ) );
65 }
66 
68  : mProject{ project }
69 {
71  registerStatusWidthFunction{ StatusWidthFunction };
72  project.Bind( EVT_CHECKPOINT_FAILURE,
74 }
75 
77 
78 static TranslatableString FormatRate( int rate )
79 {
80  if (rate > 0) {
81  return XO("Actual Rate: %d").Format( rate );
82  }
83  else
84  // clear the status field
85  return {};
86 }
87 
89  const AudacityProject &project, StatusBarField field )
91 {
92  if ( field == rateStatusBarField ) {
93  auto &audioManager = ProjectAudioManager::Get( project );
94  int rate = audioManager.mDisplayedRate;
95  return {
96  { { FormatRate( rate ) } },
97  50
98  };
99  }
100  return {};
101 }
102 
103 namespace {
104 // The implementation is general enough to allow backwards play too
106 public:
108  double gapLeft,
109  double gapLength
110  );
112 
113  void Initialize(PlaybackSchedule &schedule, double rate) override;
114 
115  bool Done(PlaybackSchedule &schedule, unsigned long) override;
116 
117  double OffsetTrackTime( PlaybackSchedule &schedule, double offset ) override;
118 
119  PlaybackSlice GetPlaybackSlice(
120  PlaybackSchedule &schedule, size_t available) override;
121 
122  std::pair<double, double> AdvancedTrackTime( PlaybackSchedule &schedule,
123  double trackTime, size_t nSamples) override;
124 
125  bool RepositionPlayback(
126  PlaybackSchedule &schedule, const Mixers &playbackMixers,
127  size_t frames, size_t available) override;
128 
129 private:
130  double GapStart() const
131  { return mReversed ? mGapLeft + mGapLength : mGapLeft; }
132  double GapEnd() const
133  { return mReversed ? mGapLeft : mGapLeft + mGapLength; }
134  bool AtOrBefore(double trackTime1, double trackTime2) const
135  { return mReversed ? trackTime1 >= trackTime2 : trackTime1 <= trackTime2; }
136 
138  const double mGapLeft, mGapLength;
139 
141  double mStart = 0, mEnd = 0;
142 
143  // Non-negative real time durations
144  double mDuration1 = 0, mDuration2 = 0;
145  double mInitDuration1 = 0, mInitDuration2 = 0;
146 
147  bool mDiscontinuity{ false };
148  bool mReversed{ false };
149 };
150 
151 CutPreviewPlaybackPolicy::CutPreviewPlaybackPolicy(
152  double gapLeft, double gapLength)
153 : mGapLeft{ gapLeft }, mGapLength{ gapLength }
154 {
155  wxASSERT(gapLength >= 0.0);
156 }
157 
159 
161  PlaybackSchedule &schedule, double rate)
162 {
163  PlaybackPolicy::Initialize(schedule, rate);
164 
165  // Examine mT0 and mT1 in the schedule only now; ignore changes during play
166  double left = mStart = schedule.mT0;
167  double right = mEnd = schedule.mT1;
168  mReversed = left > right;
169  if (mReversed)
170  std::swap(left, right);
171 
172  if (left < mGapLeft)
173  mDuration1 = schedule.ComputeWarpedLength(left, mGapLeft);
174  const auto gapEnd = mGapLeft + mGapLength;
175  if (gapEnd < right)
176  mDuration2 = schedule.ComputeWarpedLength(gapEnd, right);
177  if (mReversed)
179  if (sampleCount(mDuration2 * rate) == 0)
183 }
184 
185 bool CutPreviewPlaybackPolicy::Done(PlaybackSchedule &schedule, unsigned long)
186 {
188  auto diff = schedule.GetTrackTime() - mEnd;
189  if (mReversed)
190  diff *= -1;
191  return sampleCount(diff * mRate) >= 0;
192 }
193 
195  PlaybackSchedule &schedule, double offset )
196 {
197  // Compute new time by applying the offset, jumping over the gap
198  auto time = schedule.GetTrackTime();
199  if (offset >= 0) {
200  auto space = std::clamp(mGapLeft - time, 0.0, offset);
201  time += space;
202  offset -= space;
203  if (offset > 0)
204  time = std::max(time, mGapLeft + mGapLength) + offset;
205  }
206  else {
207  auto space = std::clamp(mGapLeft + mGapLength - time, offset, 0.0);
208  time += space;
209  offset -= space;
210  if (offset < 0)
211  time = std::min(time, mGapLeft) + offset;
212  }
213  time = std::clamp(time, std::min(mStart, mEnd), std::max(mStart, mEnd));
214 
215  // Reset the durations
216  mDiscontinuity = false;
219  if (AtOrBefore(time, GapStart()))
220  mDuration1 = std::max(0.0,
221  mDuration1 - fabs(schedule.ComputeWarpedLength(mStart, time)));
222  else {
223  mDuration1 = 0;
224  mDuration2 = std::max(0.0,
225  mDuration2 - fabs(schedule.ComputeWarpedLength(GapEnd(), time)));
226  }
227 
228  return time;
229 }
230 
232  PlaybackSchedule &, size_t available)
233 {
234  size_t frames = available;
235  size_t toProduce = frames;
236  sampleCount samples1(mDuration1 * mRate);
237  if (samples1 > 0 && samples1 < frames)
238  // Shorter slice than requested, up to the discontinuity
239  toProduce = frames = samples1.as_size_t();
240  else if (samples1 == 0) {
241  sampleCount samples2(mDuration2 * mRate);
242  if (samples2 < frames) {
243  toProduce = samples2.as_size_t();
244  // Produce some extra silence so that the time queue consumer can
245  // satisfy its end condition
246  frames = std::min(available, toProduce + TimeQueueGrainSize + 1);
247  }
248  }
249  return { available, frames, toProduce };
250 }
251 
253  PlaybackSchedule &schedule, double trackTime, size_t nSamples)
254 {
255  auto realDuration = nSamples / mRate;
256  if (mDuration1 > 0) {
257  mDuration1 = std::max(0.0, mDuration1 - realDuration);
258  if (sampleCount(mDuration1 * mRate) == 0) {
259  mDuration1 = 0;
260  mDiscontinuity = true;
261  return { GapStart(), GapEnd() };
262  }
263  }
264  else
265  mDuration2 = std::max(0.0, mDuration2 - realDuration);
266  if (mReversed)
267  realDuration *= -1;
268  const double time = schedule.SolveWarpedLength(trackTime, realDuration);
269 
270  if ( mReversed ? time <= mEnd : time >= mEnd )
271  return {mEnd, std::numeric_limits<double>::infinity()};
272  else
273  return {time, time};
274 }
275 
277  const Mixers &playbackMixers, size_t, size_t )
278 {
279  if (mDiscontinuity) {
280  mDiscontinuity = false;
281  auto newTime = GapEnd();
282  for (auto &pMixer : playbackMixers)
283  pMixer->Reposition(newTime, true);
284  // Tell TrackBufferExchange that we aren't done yet
285  return false;
286  }
287  return true;
288 }
289 }
290 
292  const AudioIOStartStreamOptions &options,
293  PlayMode mode,
294  bool backwards /* = false */)
295 {
296  auto &projectAudioManager = *this;
297  bool canStop = projectAudioManager.CanStopAudioStream();
298 
299  if ( !canStop )
300  return -1;
301 
302  auto &pStartTime = options.pStartTime;
303 
304  bool nonWaveToo = options.playNonWaveTracks;
305 
306  // Uncomment this for laughs!
307  // backwards = true;
308 
309  double t0 = selectedRegion.t0();
310  double t1 = selectedRegion.t1();
311  // SelectedRegion guarantees t0 <= t1, so we need another boolean argument
312  // to indicate backwards play.
313  const bool newDefault = (mode == PlayMode::loopedPlay);
314 
315  if (backwards)
316  std::swap(t0, t1);
317 
318  projectAudioManager.SetLooping( mode == PlayMode::loopedPlay );
319  projectAudioManager.SetCutting( mode == PlayMode::cutPreviewPlay );
320 
321  bool success = false;
322 
323  auto gAudioIO = AudioIO::Get();
324  if (gAudioIO->IsBusy())
325  return -1;
326 
327  const bool cutpreview = mode == PlayMode::cutPreviewPlay;
328  if (cutpreview && t0==t1)
329  return -1; /* msmeyer: makes no sense */
330 
331  AudacityProject *p = &mProject;
332 
333  auto &tracks = TrackList::Get( *p );
334 
335  mLastPlayMode = mode;
336 
337  bool hasaudio;
338  if (nonWaveToo)
339  hasaudio = ! tracks.Any<PlayableTrack>().empty();
340  else
341  hasaudio = ! tracks.Any<WaveTrack>().empty();
342 
343  double latestEnd = tracks.GetEndTime();
344 
345  if (!hasaudio)
346  return -1; // No need to continue without audio tracks
347 
348 #if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR)
349  double initSeek = 0.0;
350 #endif
351  double loopOffset = 0.0;
352 
353  if (t1 == t0) {
354  if (newDefault) {
355  const auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
356  // play selection if there is one, otherwise
357  // set start of play region to project start,
358  // and loop the project from current play position.
359 
360  if ((t0 > selectedRegion.t0()) && (t0 < selectedRegion.t1())) {
361  t0 = selectedRegion.t0();
362  t1 = selectedRegion.t1();
363  }
364  else {
365  // loop the entire project
366  // Bug2347, loop playback from cursor position instead of project start
367  loopOffset = t0 - tracks.GetStartTime();
368  if (!pStartTime)
369  // TODO move this reassignment elsewhere so we don't need an
370  // ugly mutable member
371  pStartTime.emplace(loopOffset);
372  t0 = tracks.GetStartTime();
373  t1 = tracks.GetEndTime();
374  }
375  } else {
376  // move t0 to valid range
377  if (t0 < 0) {
378  t0 = tracks.GetStartTime();
379  }
380  else if (t0 > tracks.GetEndTime()) {
381  t0 = tracks.GetEndTime();
382  }
383 #if defined(EXPERIMENTAL_SEEK_BEHIND_CURSOR)
384  else {
385  initSeek = t0; //AC: initSeek is where playback will 'start'
386  if (!pStartTime)
387  pStartTime.emplace(initSeek);
388  t0 = tracks.GetStartTime();
389  }
390 #endif
391  }
392  t1 = tracks.GetEndTime();
393  }
394  else {
395  // maybe t1 < t0, with backwards scrubbing for instance
396  if (backwards)
397  std::swap(t0, t1);
398 
399  t0 = std::max(0.0, std::min(t0, latestEnd));
400  t1 = std::max(0.0, std::min(t1, latestEnd));
401 
402  if (backwards)
403  std::swap(t0, t1);
404  }
405 
406  int token = -1;
407 
408  if (t1 != t0) {
409  if (cutpreview) {
410  const double tless = std::min(t0, t1);
411  const double tgreater = std::max(t0, t1);
412  double beforeLen, afterLen;
413  gPrefs->Read(wxT("/AudioIO/CutPreviewBeforeLen"), &beforeLen, 2.0);
414  gPrefs->Read(wxT("/AudioIO/CutPreviewAfterLen"), &afterLen, 1.0);
415  double tcp0 = tless-beforeLen;
416  const double diff = tgreater - tless;
417  double tcp1 = tgreater+afterLen;
418  if (backwards)
419  std::swap(tcp0, tcp1);
420  AudioIOStartStreamOptions myOptions = options;
421  myOptions.policyFactory =
422  [tless, diff](auto&) -> std::unique_ptr<PlaybackPolicy> {
423  return std::make_unique<CutPreviewPlaybackPolicy>(tless, diff);
424  };
425  token = gAudioIO->StartStream(
426  GetAllPlaybackTracks(TrackList::Get(*p), false, nonWaveToo),
427  tcp0, tcp1, tcp1, myOptions);
428  }
429  else {
430  double mixerLimit = t1;
431  if (newDefault) {
432  mixerLimit = latestEnd;
433  if (pStartTime && *pStartTime >= t1)
434  t1 = latestEnd;
435  }
436  token = gAudioIO->StartStream(
437  GetAllPlaybackTracks( tracks, false, nonWaveToo ),
438  t0, t1, mixerLimit, options);
439  }
440  if (token != 0) {
441  success = true;
443  }
444  else {
445  // Bug1627 (part of it):
446  // infinite error spew when trying to start scrub:
447  // Problem was that the error dialog yields to events,
448  // causing recursion to this function in the scrub timer
449  // handler! Easy fix, just delay the user alert instead.
450  auto &window = GetProjectFrame( mProject );
451  window.CallAfter( [&]{
452  using namespace BasicUI;
453  // Show error message if stream could not be opened
455  XO("Error"),
456  XO("Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."),
457  wxT("Error_opening_sound_device"),
458  ErrorDialogOptions{ ErrorDialogType::ModalErrorReport } );
459  });
460  }
461  }
462 
463  if (!success)
464  return -1;
465 
466  return token;
467 }
468 
469 void ProjectAudioManager::PlayCurrentRegion(bool newDefault /* = false */,
470  bool cutpreview /* = false */)
471 {
472  auto &projectAudioManager = *this;
473  bool canStop = projectAudioManager.CanStopAudioStream();
474 
475  if ( !canStop )
476  return;
477 
478  AudacityProject *p = &mProject;
479 
480  {
481 
482  const auto &playRegion = ViewInfo::Get( *p ).playRegion;
483 
484  if (newDefault)
485  cutpreview = false;
486  auto options = DefaultPlayOptions( *p, newDefault );
487  if (cutpreview)
488  options.envelope = nullptr;
489  auto mode =
490  cutpreview ? PlayMode::cutPreviewPlay
491  : newDefault ? PlayMode::loopedPlay
493  PlayPlayRegion(SelectedRegion(playRegion.GetStart(), playRegion.GetEnd()),
494  options,
495  mode);
496  }
497 }
498 
499 void ProjectAudioManager::Stop(bool stopStream /* = true*/)
500 {
501  AudacityProject *project = &mProject;
502  auto &projectAudioManager = *this;
503  bool canStop = projectAudioManager.CanStopAudioStream();
504 
505  if ( !canStop )
506  return;
507 
508  if(project) {
509  // Let scrubbing code do some appearance change
510  auto &scrubber = Scrubber::Get( *project );
511  scrubber.StopScrubbing();
512  }
513 
514  auto gAudioIO = AudioIO::Get();
515 
516  auto cleanup = finally( [&]{
517  projectAudioManager.SetStopping( false );
518  } );
519 
520  if (stopStream && gAudioIO->IsBusy()) {
521  // flag that we are stopping
522  projectAudioManager.SetStopping( true );
523  // Allow UI to update for that
524  while( wxTheApp->ProcessIdle() )
525  ;
526  }
527 
528  if(stopStream)
529  gAudioIO->StopStream();
530 
531  projectAudioManager.SetLooping( false );
532  projectAudioManager.SetCutting( false );
533 
534  #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
535  gAudioIO->AILADisable();
536  #endif
537 
538  projectAudioManager.SetPaused( false );
539  //Make sure you tell gAudioIO to unpause
540  gAudioIO->SetPaused( false );
541 
542  // So that we continue monitoring after playing or recording.
543  // also clean the MeterQueues
544  if( project ) {
545  auto &projectAudioIO = ProjectAudioIO::Get( *project );
546  auto meter = projectAudioIO.GetPlaybackMeter();
547  if( meter ) {
548  meter->Clear();
549  }
550 
551  meter = projectAudioIO.GetCaptureMeter();
552  if( meter ) {
553  meter->Clear();
554  }
555  }
556 
557  const auto toolbar = ToolManager::Get( *project ).GetToolBar(ScrubbingBarID);
558  if (toolbar)
559  toolbar->EnableDisableButtons();
560 }
561 
563 {
564  auto &projectAudioManager = *this;
565  bool canStop = projectAudioManager.CanStopAudioStream();
566 
567  if ( !canStop ) {
568  auto gAudioIO = AudioIO::Get();
569  gAudioIO->SetPaused(!gAudioIO->IsPaused());
570  }
571  else {
572  OnPause();
573  }
574 }
575 
577  AudacityProject &proj, bool selectedOnly, double targetRate)
578 {
579  auto p = &proj;
580  size_t recordingChannels = std::max(0, AudioIORecordChannels.Read());
581  bool strictRules = (recordingChannels <= 2);
582 
583  // Iterate over all wave tracks, or over selected wave tracks only.
584  // If target rate was specified, ignore all tracks with other rates.
585  //
586  // In the usual cases of one or two recording channels, seek a first-fit
587  // unbroken sub-sequence for which the total number of channels matches the
588  // required number exactly. Never drop inputs or fill only some channels
589  // of a track.
590  //
591  // In case of more than two recording channels, choose tracks only among the
592  // selected. Simply take the earliest wave tracks, until the number of
593  // channels is enough. If there are fewer channels than inputs, but at least
594  // one channel, then some of the input channels will be dropped.
595  //
596  // Resulting tracks may be non-consecutive within the list of all tracks
597  // (there may be non-wave tracks between, or non-selected tracks when
598  // considering selected tracks only.)
599 
600  if (!strictRules && !selectedOnly)
601  return {};
602 
603  auto &trackList = TrackList::Get( *p );
604  std::vector<unsigned> channelCounts;
605  WaveTrackArray candidates;
606  const auto range = trackList.Leaders<WaveTrack>();
607  for ( auto candidate : selectedOnly ? range + &Track::IsSelected : range ) {
608  if (targetRate != RATE_NOT_SELECTED && candidate->GetRate() != targetRate)
609  continue;
610 
611  // count channels in this track
612  const auto channels = TrackList::Channels( candidate );
613  unsigned nChannels = channels.size();
614 
615  if (strictRules && nChannels > recordingChannels) {
616  // The recording would under-fill this track's channels
617  // Can't use any partial accumulated results
618  // either. Keep looking.
619  candidates.clear();
620  channelCounts.clear();
621  continue;
622  }
623  else {
624  // Might use this but may have to discard some of the accumulated
625  while(strictRules &&
626  nChannels + candidates.size() > recordingChannels) {
627  auto nOldChannels = channelCounts[0];
628  wxASSERT(nOldChannels > 0);
629  channelCounts.erase(channelCounts.begin());
630  candidates.erase(candidates.begin(),
631  candidates.begin() + nOldChannels);
632  }
633  channelCounts.push_back(nChannels);
634  for ( auto channel : channels ) {
635  candidates.push_back(channel->SharedPointer<WaveTrack>());
636  if(candidates.size() == recordingChannels)
637  // Done!
638  return candidates;
639  }
640  }
641  }
642 
643  if (!strictRules && !candidates.empty())
644  // good enough
645  return candidates;
646 
647  // If the loop didn't exit early, we could not find enough channels
648  return {};
649 }
650 
652 void ProjectAudioManager::OnRecord(bool altAppearance)
653 {
654  bool bPreferNewTrack;
655  gPrefs->Read("/GUI/PreferNewTrackRecord", &bPreferNewTrack, false);
656  const bool appendRecord = (altAppearance == bPreferNewTrack);
657 
658  // Code from CommandHandler start...
659  AudacityProject *p = &mProject;
660 
661  if (p) {
662  const auto &selectedRegion = ViewInfo::Get( *p ).selectedRegion;
663  double t0 = selectedRegion.t0();
664  double t1 = selectedRegion.t1();
665  // When no time selection, recording duration is 'unlimited'.
666  if (t1 == t0)
667  t1 = DBL_MAX;
668 
669  auto options = DefaultPlayOptions(*p);
670  WaveTrackArray existingTracks;
671 
672  // Checking the selected tracks: counting them and
673  // making sure they all have the same rate
674  const auto selectedTracks{ GetPropertiesOfSelected(*p) };
675  const int rateOfSelected{ selectedTracks.rateOfSelected };
676  const int numberOfSelected{ selectedTracks.numberOfSelected };
677  const bool allSameRate{ selectedTracks.allSameRate };
678 
679  if (!allSameRate) {
680  AudacityMessageBox(XO("The tracks selected "
681  "for recording must all have the same sampling rate"),
682  XO("Mismatched Sampling Rates"),
683  wxICON_ERROR | wxCENTRE);
684 
685  return;
686  }
687 
688  if (appendRecord) {
689  const auto trackRange = TrackList::Get( *p ).Any< const WaveTrack >();
690 
691  // Try to find wave tracks to record into. (If any are selected,
692  // try to choose only from them; else if wave tracks exist, may record into any.)
693  existingTracks = ChooseExistingRecordingTracks(*p, true, rateOfSelected);
694  if (!existingTracks.empty()) {
695  t0 = std::max(t0,
696  (trackRange + &Track::IsSelected).max(&Track::GetEndTime));
697  }
698  else {
699  if (numberOfSelected > 0 && rateOfSelected != options.rate) {
701  "Too few tracks are selected for recording at this sample rate.\n"
702  "(Audacity requires two channels at the same sample rate for\n"
703  "each stereo track)"),
704  XO("Too Few Compatible Tracks Selected"),
705  wxICON_ERROR | wxCENTRE);
706 
707  return;
708  }
709 
710  existingTracks = ChooseExistingRecordingTracks(*p, false, options.rate);
711  if (!existingTracks.empty())
712  {
713  auto endTime = std::max_element(
714  existingTracks.begin(),
715  existingTracks.end(),
716  [](const auto& a, const auto& b) {
717  return a->GetEndTime() < b->GetEndTime();
718  }
719  )->get()->GetEndTime();
720 
721  //If there is a suitable track, then adjust t0 so
722  //that recording not starts before the end of that track
723  t0 = std::max(t0, endTime);
724  }
725  // If suitable tracks still not found, will record into NEW ones,
726  // starting with t0
727  }
728 
729  // Whether we decided on NEW tracks or not:
730  if (t1 <= selectedRegion.t0() && selectedRegion.t1() > selectedRegion.t0()) {
731  t1 = selectedRegion.t1(); // record within the selection
732  }
733  else {
734  t1 = DBL_MAX; // record for a long, long time
735  }
736  }
737 
738  TransportTracks transportTracks;
739  if (UseDuplex()) {
740  // Remove recording tracks from the list of tracks for duplex ("overdub")
741  // playback.
742  /* TODO: set up stereo tracks if that is how the user has set up
743  * their preferences, and choose sample format based on prefs */
744  transportTracks = GetAllPlaybackTracks(TrackList::Get( *p ), false, true);
745  for (const auto &wt : existingTracks) {
746  auto end = transportTracks.playbackTracks.end();
747  auto it = std::find(transportTracks.playbackTracks.begin(), end, wt);
748  if (it != end)
749  transportTracks.playbackTracks.erase(it);
750  }
751  }
752 
753  transportTracks.captureTracks = existingTracks;
754 
755  if (rateOfSelected != RATE_NOT_SELECTED)
756  options.rate = rateOfSelected;
757 
758  DoRecord(*p, transportTracks, t0, t1, altAppearance, options);
759  }
760 }
761 
763 {
764  bool duplex;
765  gPrefs->Read(wxT("/AudioIO/Duplex"), &duplex,
766 #ifdef EXPERIMENTAL_DA
767  false
768 #else
769  true
770 #endif
771  );
772  return duplex;
773 }
774 
776  const TransportTracks &tracks,
777  double t0, double t1,
778  bool altAppearance,
779  const AudioIOStartStreamOptions &options)
780 {
781  auto &projectAudioManager = *this;
782 
783  CommandFlag flags = AlwaysEnabledFlag; // 0 means recalc flags.
784 
785  // NB: The call may have the side effect of changing flags.
786  bool allowed = MenuManager::Get(project).TryToMakeActionAllowed(
787  flags,
789 
790  if (!allowed)
791  return false;
792  // ...end of code from CommandHandler.
793 
794  auto gAudioIO = AudioIO::Get();
795  if (gAudioIO->IsBusy())
796  return false;
797 
798  projectAudioManager.SetAppending( !altAppearance );
799 
800  bool success = false;
801 
802  auto transportTracks = tracks;
803 
804  // Will replace any given capture tracks with temporaries
805  transportTracks.captureTracks.clear();
806 
807  const auto p = &project;
808 
809  bool appendRecord = !tracks.captureTracks.empty();
810 
811  auto makeNewClipName = [&](WaveTrack* track) {
812  for (auto i = 1;; ++i)
813  {
814  //i18n-hint a numerical suffix added to distinguish otherwise like-named clips when new record started
815  auto name = XC("%s #%d", "clip name template").Format(track->GetName(), i).Translation();
816  if (track->FindClipByName(name) == nullptr)
817  return name;
818  }
819  };
820 
821  {
822  if (appendRecord) {
823  // Append recording:
824  // Pad selected/all wave tracks to make them all the same length
825  for (const auto &wt : tracks.captureTracks)
826  {
827  auto endTime = wt->GetEndTime();
828 
829  // If the track was chosen for recording and playback both,
830  // remember the original in preroll tracks, before making the
831  // pending replacement.
832  bool prerollTrack = make_iterator_range(transportTracks.playbackTracks).contains(wt);
833  if (prerollTrack)
834  transportTracks.prerollTracks.push_back(wt);
835 
836  // A function that copies all the non-sample data between
837  // wave tracks; in case the track recorded to changes scale
838  // type (for instance), during the recording.
839  auto updater = [](Track &d, const Track &s){
840  auto &dst = static_cast<WaveTrack&>(d);
841  auto &src = static_cast<const WaveTrack&>(s);
842  dst.Reinit(src);
843  };
844 
845  // Get a copy of the track to be appended, to be pushed into
846  // undo history only later.
847  auto pending = std::static_pointer_cast<WaveTrack>(
849  updater, wt.get() ) );
850 
851  // End of current track is before or at recording start time.
852  // Less than or equal, not just less than, to ensure a clip boundary.
853  // when append recording.
854  if (endTime <= t0) {
855  pending->CreateClip(t0, makeNewClipName(pending.get()));
856  }
857  transportTracks.captureTracks.push_back(pending);
858  }
860  }
861 
862  if( transportTracks.captureTracks.empty() )
863  { // recording to NEW track(s).
864  bool recordingNameCustom, useTrackNumber, useDateStamp, useTimeStamp;
865  wxString defaultTrackName, defaultRecordingTrackName;
866 
867  // Count the tracks.
868  auto &trackList = TrackList::Get( *p );
869  auto numTracks = trackList.Leaders< const WaveTrack >().size();
870 
871  auto recordingChannels = std::max(1, AudioIORecordChannels.Read());
872 
873  gPrefs->Read(wxT("/GUI/TrackNames/RecordingNameCustom"), &recordingNameCustom, false);
874  gPrefs->Read(wxT("/GUI/TrackNames/TrackNumber"), &useTrackNumber, false);
875  gPrefs->Read(wxT("/GUI/TrackNames/DateStamp"), &useDateStamp, false);
876  gPrefs->Read(wxT("/GUI/TrackNames/TimeStamp"), &useTimeStamp, false);
878  gPrefs->Read(wxT("/GUI/TrackNames/RecodingTrackName"), &defaultRecordingTrackName, defaultTrackName);
879 
880  wxString baseTrackName = recordingNameCustom? defaultRecordingTrackName : defaultTrackName;
881 
882  Track *first {};
883  for (int c = 0; c < recordingChannels; c++) {
884  auto newTrack = WaveTrackFactory::Get( *p ).NewWaveTrack();
885  if (!first)
886  first = newTrack.get();
887 
888  // Quantize bounds to the rate of the new track.
889  if (c == 0) {
890  if (t0 < DBL_MAX)
891  t0 = newTrack->LongSamplesToTime(newTrack->TimeToLongSamples(t0));
892  if (t1 < DBL_MAX)
893  t1 = newTrack->LongSamplesToTime(newTrack->TimeToLongSamples(t1));
894  }
895 
896  newTrack->SetOffset(t0);
897  wxString nameSuffix = wxString(wxT(""));
898 
899  if (useTrackNumber) {
900  nameSuffix += wxString::Format(wxT("%d"), 1 + (int) numTracks + c);
901  }
902 
903  if (useDateStamp) {
904  if (!nameSuffix.empty()) {
905  nameSuffix += wxT("_");
906  }
907  nameSuffix += wxDateTime::Now().FormatISODate();
908  }
909 
910  if (useTimeStamp) {
911  if (!nameSuffix.empty()) {
912  nameSuffix += wxT("_");
913  }
914  nameSuffix += wxDateTime::Now().FormatISOTime();
915  }
916 
917  // ISO standard would be nice, but ":" is unsafe for file name.
918  nameSuffix.Replace(wxT(":"), wxT("-"));
919 
920  if (baseTrackName.empty()) {
921  newTrack->SetName(nameSuffix);
922  }
923  else if (nameSuffix.empty()) {
924  newTrack->SetName(baseTrackName);
925  }
926  else {
927  newTrack->SetName(baseTrackName + wxT("_") + nameSuffix);
928  }
929  //create a new clip with a proper name before recording is started
930  newTrack->CreateClip(t0, makeNewClipName(newTrack.get()));
931 
932  TrackList::Get( *p ).RegisterPendingNewTrack( newTrack );
933 
934  if ((recordingChannels > 2) &&
936  TrackView::Get( *newTrack ).SetMinimized(true);
937  }
938 
939  transportTracks.captureTracks.push_back(newTrack);
940  }
941  TrackList::Get( *p ).MakeMultiChannelTrack(*first, recordingChannels, true);
942  // Bug 1548. First of new tracks needs the focus.
943  TrackFocus::Get(*p).Set(first);
944  if (TrackList::Get(*p).back())
945  TrackList::Get(*p).back()->EnsureVisible();
946  }
947 
948  //Automated Input Level Adjustment Initialization
949  #ifdef EXPERIMENTAL_AUTOMATED_INPUT_LEVEL_ADJUSTMENT
950  gAudioIO->AILAInitialize();
951  #endif
952 
953  int token = gAudioIO->StartStream(transportTracks, t0, t1, t1, options);
954 
955  success = (token != 0);
956 
957  if (success) {
959  }
960  else {
961  CancelRecording();
962 
963  // Show error message if stream could not be opened
964  auto msg = XO("Error opening recording device.\nError code: %s")
965  .Format( gAudioIO->LastPaErrorString() );
966  using namespace BasicUI;
968  XO("Error"), msg, wxT("Error_opening_sound_device"),
969  ErrorDialogOptions{ ErrorDialogType::ModalErrorReport } );
970  }
971  }
972 
973  return success;
974 }
975 
977 {
978  auto &projectAudioManager = *this;
979  bool canStop = projectAudioManager.CanStopAudioStream();
980 
981  if ( !canStop ) {
982  return;
983  }
984 
985  bool paused = !projectAudioManager.Paused();
986  projectAudioManager.SetPaused( paused );
987 
988  auto gAudioIO = AudioIO::Get();
989 
990 #ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
991 
992  auto project = &mProject;
993  auto &scrubber = Scrubber::Get( *project );
994 
995  // Bug 1494 - Pausing a seek or scrub should just STOP as
996  // it is confusing to be in a paused scrub state.
997  bool bStopInstead = paused &&
999  !scrubber.IsSpeedPlaying() &&
1000  !scrubber.IsKeyboardScrubbing();
1001 
1002  if (bStopInstead) {
1003  Stop();
1004  return;
1005  }
1006 
1008  scrubber.Pause(paused);
1009  else
1010 #endif
1011  {
1012  gAudioIO->SetPaused(paused);
1013  }
1014 }
1015 
1017 {
1018  const auto project = &mProject;
1019  TrackList::Get( *project ).ClearPendingTracks();
1020 }
1021 
1023 {
1024  auto &project = mProject;
1025 
1026  mDisplayedRate = rate;
1027 
1028  auto display = FormatRate( rate );
1029 
1030  ProjectStatus::Get( project ).Set( display, rateStatusBarField );
1031 }
1032 
1034 {
1035  // Auto-save was done here before, but it is unnecessary, provided there
1036  // are sufficient autosaves when pushing or modifying undo states.
1037 }
1038 
1039 // This is called after recording has stopped and all tracks have flushed.
1041 {
1042  auto &project = mProject;
1043  auto &projectAudioIO = ProjectAudioIO::Get( project );
1044  auto &projectFileIO = ProjectFileIO::Get( project );
1045 
1046  // Only push state if we were capturing and not monitoring
1047  if (projectAudioIO.GetAudioIOToken() > 0)
1048  {
1049  auto &history = ProjectHistory::Get( project );
1050 
1051  if (IsTimerRecordCancelled()) {
1052  // discard recording
1053  history.RollbackState();
1054  // Reset timer record
1055  ResetTimerRecordCancelled();
1056  }
1057  else {
1058  // Add to history
1059  // We want this to have No-fail-guarantee if we get here from exception
1060  // handling of recording, and that means we rely on the last autosave
1061  // successfully committed to the database, not risking a failure
1062  history.PushState(XO("Recorded Audio"), XO("Record"),
1064 
1065  // Now, we may add a label track to give information about
1066  // dropouts. We allow failure of this.
1067  auto gAudioIO = AudioIO::Get();
1068  auto &intervals = gAudioIO->LostCaptureIntervals();
1069  if (intervals.size()) {
1070  RecordingDropoutEvent evt{ intervals };
1071  mProject.ProcessEvent(evt);
1072  }
1073  }
1074  }
1075 }
1076 
1078 {
1079  auto &project = mProject;
1080  auto &projectFileIO = ProjectFileIO::Get( project );
1081  projectFileIO.AutoSave(true);
1082 }
1083 
1085 {
1086  const auto project = &mProject;
1087  TrackList::Get( *project ).ApplyPendingTracks();
1088 }
1089 
1091 {
1092  auto &project = mProject;
1093  auto gAudioIO = AudioIO::Get();
1094  if ( gAudioIO && &project == gAudioIO->GetOwningProject().get() ) {
1095  wxTheApp->CallAfter( [this]{ Pause(); } );
1096  }
1097 }
1098 
1100 {
1101  evt.Skip();
1102  Stop();
1103 }
1104 
1106 {
1107  auto gAudioIO = AudioIO::Get();
1108  return
1109  gAudioIO->IsBusy() &&
1110  CanStopAudioStream() &&
1111  // ... and not merely monitoring
1112  !gAudioIO->IsMonitoring() &&
1113  // ... and not punch-and-roll recording
1114  gAudioIO->GetNumCaptureChannels() == 0;
1115 }
1116 
1118 {
1119  auto gAudioIO = AudioIO::Get();
1120  return
1121  gAudioIO->IsBusy() &&
1122  CanStopAudioStream() &&
1123  gAudioIO->GetNumCaptureChannels() > 0;
1124 }
1125 
1127 {
1128  auto gAudioIO = AudioIO::Get();
1129  return (!gAudioIO->IsStreamActive() ||
1130  gAudioIO->IsMonitoring() ||
1131  gAudioIO->GetOwningProject().get() == &mProject );
1132 }
1133 
1134 const ReservedCommandFlag&
1136  [](const AudacityProject &project){
1137  auto &projectAudioManager = ProjectAudioManager::Get( project );
1138  bool canStop = projectAudioManager.CanStopAudioStream();
1139  return canStop;
1140  }
1141  }; return flag; }
1142 
1144 DefaultPlayOptions( AudacityProject &project, bool newDefault )
1145 {
1146  auto &projectAudioIO = ProjectAudioIO::Get( project );
1147  AudioIOStartStreamOptions options { project.shared_from_this(),
1148  ProjectRate::Get( project ).GetRate() };
1149  options.captureMeter = projectAudioIO.GetCaptureMeter();
1150  options.playbackMeter = projectAudioIO.GetPlaybackMeter();
1151  options.envelope = Mixer::WarpOptions::DefaultWarp::Call(TrackList::Get(project));
1152  options.listener = ProjectAudioManager::Get( project ).shared_from_this();
1153 
1154  bool loopEnabled = ViewInfo::Get(project).playRegion.Active();
1155  options.loopEnabled = loopEnabled;
1156 
1157  if (newDefault) {
1158  const double trackEndTime = TrackList::Get(project).GetEndTime();
1159  const double loopEndTime = ViewInfo::Get(project).playRegion.GetEnd();
1160  options.policyFactory = [&project, trackEndTime, loopEndTime](
1161  const AudioIOStartStreamOptions &options)
1162  -> std::unique_ptr<PlaybackPolicy>
1163  {
1164  return std::make_unique<NewDefaultPlaybackPolicy>( project,
1165  trackEndTime, loopEndTime,
1166  options.loopEnabled, options.variableSpeed);
1167  };
1168 
1169  // Start play from left edge of selection
1170  options.pStartTime.emplace(ViewInfo::Get(project).selectedRegion.t0());
1171  }
1172 
1173  return options;
1174 }
1175 
1178 {
1179  auto result = DefaultPlayOptions( project );
1180  auto gAudioIO = AudioIO::Get();
1181  auto PlayAtSpeedRate = gAudioIO->GetBestRate(
1182  false, //not capturing
1183  true, //is playing
1184  ProjectRate::Get( project ).GetRate() //suggested rate
1185  );
1186  result.rate = PlayAtSpeedRate;
1187  return result;
1188 }
1189 
1191  TrackList &trackList, bool selectedOnly, bool nonWaveToo)
1192 {
1193  TransportTracks result;
1194  {
1195  auto range = trackList.Any< WaveTrack >()
1196  + (selectedOnly ? &Track::IsSelected : &Track::Any );
1197  for (auto pTrack: range)
1198  result.playbackTracks.push_back(
1199  pTrack->SharedPointer< WaveTrack >() );
1200  }
1201 #ifdef EXPERIMENTAL_MIDI_OUT
1202  if (nonWaveToo) {
1203  auto range = trackList.Any< const PlayableTrack >() +
1204  (selectedOnly ? &Track::IsSelected : &Track::Any );
1205  for (auto pTrack: range)
1206  if (!track_cast<const WaveTrack *>(pTrack))
1207  result.otherPlayableTracks.push_back(
1208  pTrack->SharedPointer< const PlayableTrack >() );
1209  }
1210 #else
1211  WXUNUSED(useMidi);
1212 #endif
1213  return result;
1214 }
1215 
1216 // Stop playing or recording, if paused.
1218 {
1219  if( AudioIOBase::Get()->IsPaused() )
1220  Stop();
1221 }
1222 
1223 bool ProjectAudioManager::DoPlayStopSelect( bool click, bool shift )
1224 {
1225  auto &project = mProject;
1226  auto &scrubber = Scrubber::Get( project );
1227  auto token = ProjectAudioIO::Get( project ).GetAudioIOToken();
1228  auto &viewInfo = ViewInfo::Get( project );
1229  auto &selection = viewInfo.selectedRegion;
1230  auto gAudioIO = AudioIO::Get();
1231 
1232  //If busy, stop playing, make sure everything is unpaused.
1233  if (scrubber.HasMark() ||
1234  gAudioIO->IsStreamActive(token)) {
1235  // change the selection
1236  auto time = gAudioIO->GetStreamTime();
1237  // Test WasSpeedPlaying(), not IsSpeedPlaying()
1238  // as we could be stopped now. Similarly WasKeyboardScrubbing().
1239  if (click && (scrubber.WasSpeedPlaying() || scrubber.WasKeyboardScrubbing()))
1240  {
1241  ;// don't change the selection.
1242  }
1243  else if (shift && click) {
1244  // Change the region selection, as if by shift-click at the play head
1245  auto t0 = selection.t0(), t1 = selection.t1();
1246  if (time < t0)
1247  // Grow selection
1248  t0 = time;
1249  else if (time > t1)
1250  // Grow selection
1251  t1 = time;
1252  else {
1253  // Shrink selection, changing the nearer boundary
1254  if (fabs(t0 - time) < fabs(t1 - time))
1255  t0 = time;
1256  else
1257  t1 = time;
1258  }
1259  selection.setTimes(t0, t1);
1260  }
1261  else if (click){
1262  // avoid a point at negative time.
1263  time = wxMax( time, 0 );
1264  // Set a point selection, as if by a click at the play head
1265  selection.setTimes(time, time);
1266  } else
1267  // How stop and set cursor always worked
1268  // -- change t0, collapsing to point only if t1 was greater
1269  selection.setT0(time, false);
1270 
1271  ProjectHistory::Get( project ).ModifyState(false); // without bWantsAutoSave
1272  return true;
1273  }
1274  return false;
1275 }
1276 
1277 // The code for "OnPlayStopSelect" is simply the code of "OnPlayStop" and
1278 // "OnStopSelect" merged.
1280 {
1281  auto gAudioIO = AudioIO::Get();
1282  if (DoPlayStopSelect(false, false))
1283  Stop();
1284  else if (!gAudioIO->IsBusy()) {
1285  //Otherwise, start playing (assuming audio I/O isn't busy)
1286 
1287  // Will automatically set mLastPlayMode
1288  PlayCurrentRegion(false);
1289  }
1290 }
1291 
1292 #include "CommonCommandFlags.h"
1293 
1295  []{ return PausedFlag(); },
1296  []{ return AudioIONotBusyFlag(); },
1297  []( const AudacityProject &project ){
1298  return MenuManager::Get( project ).mStopIfWasPaused; },
1299  []( AudacityProject &project, CommandFlag ){
1300  if ( MenuManager::Get( project ).mStopIfWasPaused )
1302  }
1303 }};
1304 
1305 // GetSelectedProperties collects information about
1306 // currently selected audio tracks
1309 {
1310  double rateOfSelection{ RATE_NOT_SELECTED };
1311 
1312  PropertiesOfSelected result;
1313  result.allSameRate = true;
1314 
1315  const auto selectedTracks{
1316  TrackList::Get(proj).Selected< const WaveTrack >() };
1317 
1318  for (const auto & track : selectedTracks)
1319  {
1320  if (rateOfSelection != RATE_NOT_SELECTED &&
1321  track->GetRate() != rateOfSelection)
1322  result.allSameRate = false;
1323  else if (rateOfSelection == RATE_NOT_SELECTED)
1324  rateOfSelection = track->GetRate();
1325  }
1326 
1327  result.numberOfSelected = selectedTracks.size();
1328  result.rateOfSelected = rateOfSelection;
1329 
1330  return result;
1331 }
size
size_t size
Definition: ffmpeg-2.3.6-single-header.h:412
PropertiesOfSelected::allSameRate
bool allSameRate
Definition: ProjectAudioManager.h:200
WaveTrack.h
WaveTrackArray
std::vector< std::shared_ptr< WaveTrack > > WaveTrackArray
Definition: AudioIO.h:46
PlayMode::cutPreviewPlay
@ cutPreviewPlay
ProjectHistory::ModifyState
void ModifyState(bool bWantsAutoSave)
Definition: ProjectHistory.cpp:124
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
ViewInfo::Get
static ViewInfo & Get(AudacityProject &project)
Definition: ViewInfo.cpp:235
field
#define field(n, t)
Definition: ImportAUP.cpp:167
TransportTracks::playbackTracks
WaveTrackArray playbackTracks
Definition: AudioIO.h:70
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::RepositionPlayback
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...
Definition: ProjectAudioManager.cpp:276
ProjectAudioIO::GetAudioIOToken
int GetAudioIOToken() const
Definition: ProjectAudioIO.cpp:43
CanStopAudioStreamFlag
const ReservedCommandFlag & CanStopAudioStreamFlag()
Definition: ProjectAudioManager.cpp:1135
ProjectFramePlacement
std::unique_ptr< const BasicUI::WindowPlacement > ProjectFramePlacement(AudacityProject *project)
Make a WindowPlacement object suitable for project (which may be null)
Definition: ProjectWindows.cpp:101
WaveTrackFactory::Get
static WaveTrackFactory & Get(AudacityProject &project)
Definition: WaveTrack.cpp:2799
ProjectStatus.h
ToolManager.h
Scrubber::Get
static Scrubber & Get(AudacityProject &project)
Definition: Scrubbing.cpp:202
PropertiesOfSelected::numberOfSelected
int numberOfSelected
Definition: ProjectAudioManager.h:202
PlayRegion::GetEnd
double GetEnd() const
Definition: ViewInfo.h:133
WaveTrack
A Track that contains audio waveform data.
Definition: WaveTrack.h:75
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mInitDuration2
double mInitDuration2
Definition: ProjectAudioManager.cpp:145
make_iterator_range
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:423
ProjectFileIO.h
ProjectAudioManager::Get
static ProjectAudioManager & Get(AudacityProject &project)
Definition: ProjectAudioManager.cpp:55
ProjectAudioManager::OnRecord
void OnRecord(bool altAppearance)
Definition: ProjectAudioManager.cpp:652
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Definition: AudacityMessageBox.cpp:17
PlayMode
PlayMode
Definition: ProjectAudioManager.h:31
TrackView::Get
static TrackView & Get(Track &)
Definition: TrackView.cpp:69
TrackView::SetMinimized
void SetMinimized(bool minimized)
Definition: TrackView.cpp:93
flag
static std::once_flag flag
Definition: WaveformView.cpp:1133
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:71
PlaybackSchedule::mT1
double mT1
Playback ends at offset of mT1, which is measured in seconds. Note that mT1 may be less than mT0 duri...
Definition: PlaybackSchedule.h:270
TrackView.h
Track::GetEndTime
virtual double GetEndTime() const =0
SelectedRegion::t1
double t1() const
Definition: SelectedRegion.h:95
ProjectAudioManager::GetAllPlaybackTracks
static TransportTracks GetAllPlaybackTracks(TrackList &trackList, bool selectedOnly, bool nonWaveToo=false)
Definition: ProjectAudioManager.cpp:1190
BasicUI::ShowErrorDialog
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.
Definition: BasicUI.h:241
TransportTracks::captureTracks
WaveTrackArray captureTracks
Definition: AudioIO.h:71
ProjectAudioManager::DoPlayStopSelect
void DoPlayStopSelect()
Definition: ProjectAudioManager.cpp:1279
ProjectAudioManager::Pause
void Pause()
Definition: ProjectAudioManager.cpp:562
Project.h
ViewInfo::playRegion
PlayRegion playRegion
Definition: ViewInfo.h:216
ProjectRate::Get
static ProjectRate & Get(AudacityProject &project)
Definition: ProjectRate.cpp:28
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mStart
double mStart
Starting and ending track times set in Initialize()
Definition: ProjectAudioManager.cpp:141
PlaybackSchedule::mT0
double mT0
Playback starts at offset of mT0, which is measured in seconds.
Definition: PlaybackSchedule.h:268
AudioIONotBusyFlag
const ReservedCommandFlag & AudioIONotBusyFlag()
Definition: CommonCommandFlags.cpp:128
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::GapEnd
double GapEnd() const
Definition: ProjectAudioManager.cpp:132
sProjectAudioManagerKey
static AudacityProject::AttachedObjects::RegisteredFactory sProjectAudioManagerKey
Definition: ProjectAudioManager.cpp:49
ProjectAudioManager::OnAudioIOStopRecording
void OnAudioIOStopRecording() override
Definition: ProjectAudioManager.cpp:1040
TrackList::Channels
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1483
ProjectAudioManager::ChooseExistingRecordingTracks
static WaveTrackArray ChooseExistingRecordingTracks(AudacityProject &proj, bool selectedOnly, double targetRate=RATE_NOT_SELECTED)
Definition: ProjectAudioManager.cpp:576
Mix.h
TrackList
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1288
StatusBarField
StatusBarField
Definition: ProjectStatus.h:24
TracksPrefs.h
ToolManager::Get
static ToolManager & Get(AudacityProject &project)
Definition: ToolManager.cpp:341
ProjectAudioManager::OnCheckpointFailure
void OnCheckpointFailure(wxCommandEvent &evt)
Definition: ProjectAudioManager.cpp:1099
ReservedCommandFlag
Definition: CommandFlag.h:89
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::GapStart
double GapStart() const
Definition: ProjectAudioManager.cpp:130
TrackPanelAx.h
ProjectAudioManager::~ProjectAudioManager
~ProjectAudioManager() override
ToolBar::EnableDisableButtons
virtual void EnableDisableButtons()=0
DefaultPlayOptions
AudioIOStartStreamOptions DefaultPlayOptions(AudacityProject &project, bool newDefault)
Definition: ProjectAudioManager.cpp:1144
XO
#define XO(s)
Definition: Internat.h:31
XC
#define XC(s, c)
Definition: Internat.h:37
ProjectFileIO::Get
static ProjectFileIO & Get(AudacityProject &project)
Definition: ProjectFileIO.cpp:480
ProjectSettings::Get
static ProjectSettings & Get(AudacityProject &project)
Definition: ProjectSettings.cpp:45
AudioIOStartStreamOptions::policyFactory
PolicyFactory policyFactory
Definition: AudioIOBase.h:73
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mDiscontinuity
bool mDiscontinuity
Definition: ProjectAudioManager.cpp:147
ProjectAudioManager::CancelRecording
void CancelRecording()
Definition: ProjectAudioManager.cpp:1016
Track::Any
bool Any() const
Definition: Track.cpp:292
DefaultSpeedPlayOptions
AudioIOStartStreamOptions DefaultSpeedPlayOptions(AudacityProject &project)
Definition: ProjectAudioManager.cpp:1177
ProjectSettings.h
AlwaysEnabledFlag
constexpr CommandFlag AlwaysEnabledFlag
Definition: CommandFlag.h:35
CommandFlag
std::bitset< NCommandFlags > CommandFlag
Definition: CommandFlag.h:31
ProjectAudioManager.h
ProjectAudioIO::Get
static ProjectAudioIO & Get(AudacityProject &project)
Definition: ProjectAudioIO.cpp:24
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::Done
bool Done(PlaybackSchedule &schedule, unsigned long) override
Returns true if schedule.GetTrackTime() has reached the end of playback.
Definition: ProjectAudioManager.cpp:185
Meter.h
ProjectAudioManager::PlayCurrentRegion
void PlayCurrentRegion(bool newDefault=false, bool cutpreview=false)
Definition: ProjectAudioManager.cpp:469
ClientData::Site::RegisteredFactory
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:266
TransportTracks::otherPlayableTracks
PlayableTrackConstArray otherPlayableTracks
Definition: AudioIO.h:72
WaveTrack::Reinit
void Reinit(const WaveTrack &orig)
Definition: WaveTrack.cpp:216
PlaybackPolicy::Mixers
std::vector< std::unique_ptr< Mixer > > Mixers
Definition: PlaybackSchedule.h:245
Setting::Read
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:127
PlayMode::normalPlay
@ normalPlay
TrackList::RegisterPendingChangedTrack
std::shared_ptr< Track > RegisterPendingChangedTrack(Updater updater, Track *src)
Definition: Track.cpp:903
ProjectAudioManager::CanStopAudioStream
bool CanStopAudioStream() const
Definition: ProjectAudioManager.cpp:1126
TrackList::GetEndTime
double GetEndTime() const
Definition: Track.cpp:897
UndoPush::NOAUTOSAVE
@ NOAUTOSAVE
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mGapLeft
const double mGapLeft
Fixed at construction time; these are a track time and duration.
Definition: ProjectAudioManager.cpp:138
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mEnd
double mEnd
Definition: ProjectAudioManager.cpp:141
ProjectStatus::Set
void Set(const TranslatableString &msg, StatusBarField field=mainStatusBarField)
Definition: ProjectStatus.cpp:63
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mGapLength
const double mGapLength
Definition: ProjectAudioManager.cpp:138
ViewInfo::selectedRegion
NotifyingSelectedRegion selectedRegion
Definition: ViewInfo.h:215
ToolManager::GetToolBar
ToolBar * GetToolBar(int type) const
Definition: ToolManager.cpp:1015
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::AtOrBefore
bool AtOrBefore(double trackTime1, double trackTime2) const
Definition: ProjectAudioManager.cpp:134
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::GetPlaybackSlice
PlaybackSlice GetPlaybackSlice(PlaybackSchedule &schedule, size_t available) override
Choose length of one fetch of samples from tracks in a call to AudioIO::FillPlayBuffers.
Definition: ProjectAudioManager.cpp:231
TrackList::ClearPendingTracks
void ClearPendingTracks(ListOfTracks *pAdded=nullptr)
Definition: Track.cpp:948
ScrubbingBarID
@ ScrubbingBarID
Definition: ToolBar.h:80
PropertiesOfSelected
Definition: ProjectAudioManager.h:199
TrackList::MakeMultiChannelTrack
bool MakeMultiChannelTrack(Track &first, int nChannels, bool aligned)
Converts channels to a multichannel track.
Definition: Track.cpp:615
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mReversed
bool mReversed
Definition: ProjectAudioManager.cpp:148
wxDEFINE_EVENT
wxDEFINE_EVENT(EVT_RECORDING_DROPOUT, RecordingDropoutEvent)
anonymous_namespace{TimeTrack.cpp}::GetRate
double GetRate()
Definition: TimeTrack.cpp:192
PlaybackSchedule
Definition: PlaybackSchedule.h:265
ProjectAudioManager::Recording
bool Recording() const
Definition: ProjectAudioManager.cpp:1117
name
const TranslatableString name
Definition: Distortion.cpp:98
PlaybackSchedule::ComputeWarpedLength
double ComputeWarpedLength(double t0, double t1) const
Compute signed duration (in seconds at playback) of the specified region of the track.
Definition: PlaybackSchedule.cpp:455
WaveTrack::GetDefaultAudioTrackNamePreference
static wxString GetDefaultAudioTrackNamePreference()
Definition: WaveTrack.cpp:100
rateStatusBarField
@ rateStatusBarField
Definition: ProjectStatus.h:27
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy
Definition: ProjectAudioManager.cpp:105
ProjectAudioManager::UseDuplex
static bool UseDuplex()
Definition: ProjectAudioManager.cpp:762
Track::IsSelected
bool IsSelected() const
Definition: Track.cpp:295
PlaybackPolicy::Initialize
virtual void Initialize(PlaybackSchedule &schedule, double rate)
Called before starting an audio stream.
Definition: PlaybackSchedule.cpp:25
Scrubbing.h
AudioIOBase::Get
static AudioIOBase * Get()
Definition: AudioIOBase.cpp:89
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mInitDuration1
double mInitDuration1
Definition: ProjectAudioManager.cpp:145
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::OffsetTrackTime
double OffsetTrackTime(PlaybackSchedule &schedule, double offset) override
Called when the play head needs to jump a certain distance.
UndoManager.h
TrackFocus::Get
Track * Get()
Definition: TrackPanelAx.cpp:760
ProjectAudioManager::OnCommitRecording
void OnCommitRecording() override
Definition: ProjectAudioManager.cpp:1084
Journal::Events::anonymous_namespace{JournalEvents.cpp}::Initialize
void Initialize()
Definition: JournalEvents.cpp:438
AudioIOStartStreamOptions
struct holding stream options, including a pointer to the time warp info and AudioIOListener and whet...
Definition: AudioIOBase.h:43
PausedFlag
const ReservedCommandFlag & PausedFlag()
Definition: CommonCommandFlags.cpp:306
anonymous_namespace{NoteTrack.cpp}::swap
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:753
ProjectRate::GetRate
double GetRate() const
Definition: ProjectRate.cpp:53
TrackList::RegisterPendingNewTrack
void RegisterPendingNewTrack(const std::shared_ptr< Track > &pTrack)
Definition: Track.cpp:924
ProjectAudioManager::Stop
void Stop(bool stopStream=true)
Definition: ProjectAudioManager.cpp:499
PlayableTrack
AudioTrack subclass that can also be audibly replayed by the program.
Definition: Track.h:875
ViewInfo.h
sampleCount::as_size_t
size_t as_size_t() const
Definition: SampleCount.cpp:17
AudioIOStartStreamOptions::playNonWaveTracks
bool playNonWaveTracks
Definition: AudioIOBase.h:61
MenuManager::TryToMakeActionAllowed
bool TryToMakeActionAllowed(CommandFlag &flags, CommandFlag flagsRqd)
Definition: Menus.cpp:714
ScrubState::IsScrubbing
static bool IsScrubbing()
Definition: ScrubState.cpp:482
BasicUI::ErrorDialogOptions
Options for variations of error dialogs; the default is for modal dialogs.
Definition: BasicUI.h:49
Menus.h
TransportTracks
Definition: AudioIO.h:69
AudioIOStartStreamOptions::pStartTime
std::optional< double > pStartTime
Definition: AudioIOBase.h:58
ProjectAudioManager::OnAudioIONewBlocks
void OnAudioIONewBlocks(const WaveTrackArray *tracks) override
Definition: ProjectAudioManager.cpp:1077
ProjectWindows.h
accessors for certain important windows associated with each project
ProjectStatus::StatusWidthResult
std::pair< std::vector< TranslatableString >, unsigned > StatusWidthResult
Definition: ProjectStatus.h:49
TrackList::UpdatePendingTracks
void UpdatePendingTracks()
Definition: Track.cpp:930
BasicUI.h
Toolkit-neutral facade for basic user interface services.
ProjectAudioIO::SetAudioIOToken
void SetAudioIOToken(int token)
Definition: ProjectAudioIO.cpp:48
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
RATE_NOT_SELECTED
constexpr int RATE_NOT_SELECTED
Definition: ProjectAudioManager.h:21
SelectedRegion::t0
double t0() const
Definition: SelectedRegion.h:94
ProjectAudioManager::OnAudioIORate
void OnAudioIORate(int rate) override
Definition: ProjectAudioManager.cpp:1022
BasicUI
Definition: Effect.h:47
RegisteredMenuItemEnabler
Definition: CommandFlag.h:119
TrackList::Get
static TrackList & Get(AudacityProject &project)
Definition: Track.cpp:377
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::Initialize
void Initialize(PlaybackSchedule &schedule, double rate) override
Called before starting an audio stream.
Definition: ProjectAudioManager.cpp:160
TrackList::ApplyPendingTracks
bool ApplyPendingTracks()
Definition: Track.cpp:989
ProjectAudioManager::OnAudioIOStartRecording
void OnAudioIOStartRecording() override
Definition: ProjectAudioManager.cpp:1033
TimeQueueGrainSize
constexpr size_t TimeQueueGrainSize
Definition: PlaybackSchedule.h:29
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:224
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mDuration2
double mDuration2
Definition: ProjectAudioManager.cpp:144
ProjectSettings::GetTracksFitVerticallyZoomed
bool GetTracksFitVerticallyZoomed() const
Definition: ProjectSettings.h:76
AudioIO.h
sampleCount
Positions or offsets within audio files need a wide type.
Definition: SampleCount.h:18
RecordingDropoutEvent
Notification, posted on the project, after recording has stopped, when dropouts have been detected.
Definition: ProjectAudioManager.h:48
ProjectStatus::Get
static ProjectStatus & Get(AudacityProject &project)
Definition: ProjectStatus.cpp:21
ProjectStatus::RegisteredStatusWidthFunction
Definition: ProjectStatus.h:57
AudacityProject
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
MeterPanelBase.h
ProjectAudioManager
Definition: ProjectAudioManager.h:72
ScrubState.h
AudacityMessageBox.h
PlaybackSlice
Describes an amount of contiguous (but maybe time-warped) data to be extracted from tracks to play.
Definition: PlaybackSchedule.h:156
GetProjectFrame
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 ...
Definition: ProjectWindows.cpp:72
ProjectAudioManager::ProjectAudioManager
ProjectAudioManager(AudacityProject &project)
Definition: ProjectAudioManager.cpp:67
MenuManager::Get
static MenuManager & Get(AudacityProject &project)
Definition: Menus.cpp:70
PlaybackSchedule::GetTrackTime
double GetTrackTime() const
Get current track time value, unadjusted.
Definition: PlaybackSchedule.h:398
ProjectHistory.h
ProjectAudioManager::PlayPlayRegion
int PlayPlayRegion(const SelectedRegion &selectedRegion, const AudioIOStartStreamOptions &options, PlayMode playMode, bool backwards=false)
Definition: ProjectAudioManager.cpp:291
ProjectRate.h
an object holding per-project preferred sample rate
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::AdvancedTrackTime
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.
Definition: ProjectAudioManager.cpp:252
GlobalHook< DefaultWarp, const BoundedEnvelope *(const TrackList &) >::Call
static result_type Call(Arguments &&...arguments)
Null check of the installed function is done for you.
Definition: GlobalVariable.h:158
ProjectAudioManager::StopIfPaused
void StopIfPaused()
Definition: ProjectAudioManager.cpp:1217
NotifyingSelectedRegion::t0
double t0() const
Definition: ViewInfo.h:34
ProjectAudioManager::OnSoundActivationThreshold
void OnSoundActivationThreshold() override
Definition: ProjectAudioManager.cpp:1090
ProjectAudioManager::DoRecord
bool DoRecord(AudacityProject &project, const TransportTracks &transportTracks, double t0, double t1, bool altAppearance, const AudioIOStartStreamOptions &options)
Definition: ProjectAudioManager.cpp:775
PlayRegion::Active
bool Active() const
Definition: ViewInfo.h:122
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::mDuration1
double mDuration1
Definition: ProjectAudioManager.cpp:144
GetPropertiesOfSelected
PropertiesOfSelected GetPropertiesOfSelected(const AudacityProject &proj)
Definition: ProjectAudioManager.cpp:1308
TrackList::Any
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1379
PlaybackPolicy::mRate
double mRate
Definition: PlaybackSchedule.h:262
PlaybackSchedule::SolveWarpedLength
double SolveWarpedLength(double t0, double length) const
Compute how much unwarped time must have elapsed if length seconds of warped time has elapsed,...
Definition: PlaybackSchedule.cpp:463
AudioIO::Get
static AudioIO * Get()
Definition: AudioIO.cpp:140
PlayMode::loopedPlay
@ loopedPlay
CommonCommandFlags.h
TrackList::Selected
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1396
MenuManager::mStopIfWasPaused
bool mStopIfWasPaused
Definition: Menus.h:123
WaveTrackFactory::NewWaveTrack
std::shared_ptr< WaveTrack > NewWaveTrack(sampleFormat format=(sampleFormat) 0, double rate=0)
Definition: WaveTrack.cpp:126
PropertiesOfSelected::rateOfSelected
int rateOfSelected
Definition: ProjectAudioManager.h:201
ProjectAudioIO.h
PlaybackPolicy
Directs which parts of tracks to fetch for playback.
Definition: PlaybackSchedule.h:177
ProjectHistory::Get
static ProjectHistory & Get(AudacityProject &project)
Definition: ProjectHistory.cpp:26
AudioIORecordChannels
IntSetting AudioIORecordChannels
Definition: AudioIOBase.cpp:943
ProjectAudioManager::Playing
bool Playing() const
Definition: ProjectAudioManager.cpp:1105
ProjectAudioManager::StatusWidthFunction
static std::pair< TranslatableStrings, unsigned > StatusWidthFunction(const AudacityProject &project, StatusBarField field)
Definition: ProjectAudioManager.cpp:88
stopIfPaused
static RegisteredMenuItemEnabler stopIfPaused
Definition: ProjectAudioManager.cpp:1294
FormatRate
static TranslatableString FormatRate(int rate)
Definition: ProjectAudioManager.cpp:78
SelectedRegion
Defines a selected portion of a project.
Definition: SelectedRegion.h:38
ProjectAudioManager::OnPause
void OnPause()
Definition: ProjectAudioManager.cpp:976
anonymous_namespace{ProjectAudioManager.cpp}::CutPreviewPlaybackPolicy::~CutPreviewPlaybackPolicy
~CutPreviewPlaybackPolicy() override