Audacity  2.3.1
Track.h
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Track.h
6 
7  Dominic Mazzoni
8 
9 **********************************************************************/
10 
11 #ifndef __AUDACITY_TRACK__
12 #define __AUDACITY_TRACK__
13 
14 #include "Audacity.h"
15 
16 #include "MemoryX.h"
17 #include <vector>
18 #include <list>
19 #include <functional>
20 #include <wx/event.h>
21 #include <wx/gdicmn.h>
22 #include <wx/longlong.h>
23 #include <wx/string.h>
24 
25 #include "Experimental.h"
26 #include "SampleFormat.h"
28 #include "xml/XMLTagHandler.h"
29 
30 #ifdef __WXMSW__
31 #pragma warning(disable:4284)
32 #endif
33 
34 class wxTextFile;
35 class DirManager;
36 class Track;
37 class AudioTrack;
38 class PlayableTrack;
39 class LabelTrack;
40 class TimeTrack;
41 class TrackControls;
44 class WaveTrack;
45 class NoteTrack;
46 class AudacityProject;
47 class ZoomInfo;
48 
49 class SelectHandle;
50 class TimeShiftHandle;
51 
52 using TrackArray = std::vector< Track* >;
53 using WaveTrackArray = std::vector < std::shared_ptr< WaveTrack > > ;
54 using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >;
55 
56 using NoteTrackConstArray = std::vector < std::shared_ptr< const NoteTrack > >;
57 
58 #if defined(USE_MIDI)
59 class NoteTrack;
60 #endif
61 
62 class TrackList;
63 
64 using ListOfTracks = std::list< std::shared_ptr< Track > >;
65 
66 using TrackNodePointer =
67 std::pair< ListOfTracks::iterator, ListOfTracks* >;
68 
69 inline bool operator == (const TrackNodePointer &a, const TrackNodePointer &b)
70 { return a.second == b.second && a.first == b.first; }
71 
72 inline bool operator != (const TrackNodePointer &a, const TrackNodePointer &b)
73 { return !(a == b); }
74 
75 enum class TrackKind
76 {
77  None,
78  Wave,
79 #if defined(USE_MIDI)
80  Note,
81 #endif
82  Label,
83  Time,
84  Audio,
85  Playable,
86  All
87 };
88 
92 constexpr bool CompatibleTrackKinds( TrackKind desired, TrackKind actual )
93 {
94  return
95  (desired == actual)
96  ||
97  (desired == TrackKind::All)
98  ||
99  (desired == TrackKind::Audio && actual == TrackKind::Wave)
100 #ifdef USE_MIDI
101  ||
102  (desired == TrackKind::Audio && actual == TrackKind::Note)
103 #endif
104  ||
105  (desired == TrackKind::Playable && actual == TrackKind::Wave)
106 #ifdef EXPERIMENTAL_MIDI_OUT
107  ||
108  (desired == TrackKind::Playable && actual == TrackKind::Note)
109 #endif
110  ;
111 }
112 
115 namespace TrackTyper {
116  template<typename, TrackKind> struct Pair;
117  using List = std::tuple<
125  // New classes can be added easily to this list
126  >;
127  template<typename...> struct Lookup;
128  template<typename TrackType, TrackKind Here, typename... Rest>
129  struct Lookup< TrackType, std::tuple< Pair<TrackType, Here>, Rest... > > {
130  static constexpr TrackKind value() {
131  return Here;
132  }
133  };
134  template<typename TrackType, typename NotHere, typename... Rest>
135  struct Lookup< TrackType, std::tuple< NotHere, Rest... > > {
136  static constexpr TrackKind value() {
137  return Lookup< TrackType, std::tuple< Rest... > >::value();
138  }
139  };
140 };
141 
142 template<typename TrackType> constexpr TrackKind track_kind ()
143 {
144  using namespace TrackTyper;
146 }
147 
148 // forward declarations, so we can make them friends
149 template<typename T>
150  typename std::enable_if< std::is_pointer<T>::value, T >::type
151  track_cast(Track *track);
152 
153 template<typename T>
154  typename std::enable_if<
155  std::is_pointer<T>::value &&
156  std::is_const< typename std::remove_pointer< T >::type >::value,
157  T
158  >::type
159  track_cast(const Track *track);
160 
161 class ViewInfo;
162 
170 class TrackId
171 {
172 public:
173  TrackId() : mValue(-1) {}
174  explicit TrackId (long value) : mValue(value) {}
175 
176  bool operator == (const TrackId &other) const
177  { return mValue == other.mValue; }
178 
179  bool operator != (const TrackId &other) const
180  { return mValue != other.mValue; }
181 
182  // Define this in case you want to key a std::map on TrackId
183  // The operator does not mean anything else
184  bool operator < (const TrackId &other) const
185  { return mValue < other.mValue; }
186 
187 private:
188  long mValue;
189 };
190 
191 class AUDACITY_DLL_API Track /* not final */
192  : public CommonTrackPanelCell, public XMLTagHandler
193 {
194  friend class TrackList;
195 
196  // To be TrackDisplay
197  private:
199 
200  protected:
201  std::weak_ptr<TrackList> mList;
203  int mIndex;
204  int mY;
205  int mHeight;
206  wxString mName;
207  wxString mDefaultName;
208 
209  private:
210  bool mSelected;
211 
212  protected:
213  bool mLinked;
215 
216  public:
217 
219  {
220  LeftChannel = 0,
221  RightChannel = 1,
222  MonoChannel = 2
223  };
224 
225  TrackId GetId() const { return mId; }
226  private:
227  void SetId( TrackId id ) { mId = id; }
228  public:
229 
230  // Given a bare pointer, find a shared_ptr. But this is not possible for
231  // a track not owned by any project, so the result can be null.
232  template<typename Subclass = Track>
233  inline static std::shared_ptr<Subclass> Pointer( Track *t )
234  {
235  if (t) {
236  auto pList = t->mList.lock();
237  if (pList)
238  return std::static_pointer_cast<Subclass>(*t->mNode.first);
239  }
240  return {};
241  }
242 
243  template<typename Subclass = const Track>
244  inline static std::shared_ptr<Subclass> Pointer( const Track *t )
245  {
246  if (t) {
247  auto pList = t->mList.lock();
248  if (pList) {
249  std::shared_ptr<const Track> p{ *t->mNode.first };
250  // Let you change the type, but not cast away the const
251  return std::static_pointer_cast<Subclass>(p);
252  }
253  }
254  return {};
255  }
256 
257  // Find anything registered with TrackList::RegisterPendingChangedTrack and
258  // not yet cleared or applied; if no such exists, return this track
259  std::shared_ptr<const Track> SubstitutePendingChangedTrack() const;
260 
261  // If this track is a pending changed track, return the corresponding
262  // original; else return this track
263  std::shared_ptr<const Track> SubstituteOriginalTrack() const;
264 
265  // Cause certain overriding tool modes (Zoom; future ones?) to behave
266  // uniformly in all tracks, disregarding track contents.
267  // Do not further override this...
268  std::vector<UIHandlePtr> HitTest
269  (const TrackPanelMouseState &, const AudacityProject *pProject)
270  final override;
271 
272  // Delegates the handling to the related TCP cell
273  std::shared_ptr<TrackPanelCell> ContextMenuDelegate() override
274  { return GetTrackControl(); }
275 
276  public:
277 
278  // Rather override this for subclasses:
279  virtual std::vector<UIHandlePtr> DetailedHitTest
280  (const TrackPanelMouseState &,
281  const AudacityProject *pProject, int currentTool, bool bMultiTool)
282  = 0;
283 
284  mutable wxSize vrulerSize;
285 
286  // Return another, associated TrackPanelCell object that implements the
287  // drop-down, close and minimize buttons, etc.
288  std::shared_ptr<TrackPanelCell> GetTrackControl();
289 
290  // Return another, associated TrackPanelCell object that implements the
291  // mouse actions for the vertical ruler
292  std::shared_ptr<TrackPanelCell> GetVRulerControl();
293 
294  // Return another, associated TrackPanelCell object that implements the
295  // click and drag to resize
296  std::shared_ptr<TrackPanelCell> GetResizer();
297 
298  // This just returns a constant and can be overriden by subclasses
299  // to specify a different height for the case that the track is minimized.
300  virtual int GetMinimizedHeight() const;
301  int GetActualHeight() const { return mHeight; }
302 
303  int GetIndex() const;
304  void SetIndex(int index);
305 
306  int GetY() const;
307 private:
308  // Always maintain a strictly contiguous layout of tracks.
309  // So client code is not permitted to modify this attribute directly.
310  void SetY(int y);
311  // No need yet to make this virtual
312  void DoSetY(int y);
313 public:
314 
315  int GetHeight() const;
316  void SetHeight(int h);
317 protected:
318  virtual void DoSetHeight(int h);
319 public:
320 
321  bool GetMinimized() const;
322  void SetMinimized(bool isMinimized);
323 protected:
324  virtual void DoSetMinimized(bool isMinimized);
325 
326 public:
327  static void FinishCopy (const Track *n, Track *dest);
328 
329  // For use when loading a file. Return true if ok, else make repair
330  bool LinkConsistencyCheck();
331 
332 private:
333  std::shared_ptr<TrackList> GetOwner() const { return mList.lock(); }
334 
335  Track *GetLink() const;
336  bool GetLinked () const { return mLinked; }
337 
338  friend WaveTrack; // WaveTrack needs to call SetLinked when reloading project
339  void SetLinked (bool l);
340 
341  void SetChannel(ChannelType c) { mChannel = c; }
342 private:
343  // No need yet to make this virtual
344  void DoSetLinked(bool l);
345 
346  TrackNodePointer GetNode() const;
347  void SetOwner
348  (const std::weak_ptr<TrackList> &list, TrackNodePointer node);
349 
350  // Keep in Track
351 
352  protected:
354  double mOffset;
355 
356  mutable std::shared_ptr<DirManager> mDirManager;
357 
358  public:
359 
360  enum : unsigned { DefaultHeight = 150 };
361 
362  Track(const std::shared_ptr<DirManager> &projDirManager);
363  Track(const Track &orig);
364 
365  virtual ~ Track();
366 
367  void Init(const Track &orig);
368 
369  using Holder = std::unique_ptr<Track>;
370  virtual Holder Duplicate() const = 0;
371 
372  // Called when this track is merged to stereo with another, and should
373  // take on some paramaters of its partner.
374  virtual void Merge(const Track &orig);
375 
376  wxString GetName() const { return mName; }
377  void SetName( const wxString &n );
378  wxString GetDefaultName() const { return mDefaultName; }
379  void SetDefaultName( const wxString &n ) { mDefaultName = n; }
380 
381  bool GetSelected() const { return mSelected; }
382 
383  virtual void SetSelected(bool s);
384 
385 public:
386 
387  virtual ChannelType GetChannel() const { return mChannel;}
388  virtual double GetOffset() const = 0;
389 
390  void Offset(double t) { SetOffset(GetOffset() + t); }
391  virtual void SetOffset (double o) { mOffset = o; }
392 
393  virtual void SetPan( float ){ ;}
394  virtual void SetPanFromChannelType(){ ;};
395 
396  // AS: Note that the dirManager is mutable. This is
397  // mostly to support "Duplicate" of const objects,
398  // but in general, mucking with the dir manager is
399  // separate from the Track.
400  const std::shared_ptr<DirManager> &GetDirManager() const { return mDirManager; }
401 
402  // Create a NEW track and modify this track
403  // Return non-NULL or else throw
404  // May assume precondition: t0 <= t1
405  virtual Holder Cut(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
406 
407  // Create a NEW track and don't modify this track
408  // Return non-NULL or else throw
409  // Note that subclasses may want to distinguish tracks stored in a clipboard
410  // from those stored in a project
411  // May assume precondition: t0 <= t1
412  virtual Holder Copy
413  (double WXUNUSED(t0), double WXUNUSED(t1), bool forClipboard = true) const = 0;
414 
415  // May assume precondition: t0 <= t1
416  virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
417 
418  virtual void Paste(double WXUNUSED(t), const Track * WXUNUSED(src)) = 0;
419 
420  // This can be used to adjust a sync-lock selected track when the selection
421  // is replaced by one of a different length.
422  virtual void SyncLockAdjust(double oldT1, double newT1);
423 
424  // May assume precondition: t0 <= t1
425  virtual void Silence(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
426 
427  // May assume precondition: t0 <= t1
428  virtual void InsertSilence(double WXUNUSED(t), double WXUNUSED(len)) = 0;
429 
430 private:
431  virtual TrackKind GetKind() const { return TrackKind::None; }
432 
433  template<typename T>
434  friend typename std::enable_if< std::is_pointer<T>::value, T >::type
435  track_cast(Track *track);
436  template<typename T>
437  friend typename std::enable_if<
438  std::is_pointer<T>::value &&
439  std::is_const< typename std::remove_pointer< T >::type >::value,
440  T
441  >::type
442  track_cast(const Track *track);
443 
444 public:
445  bool SameKindAs(const Track &track) const
446  { return GetKind() == track.GetKind(); }
447 
448  template < typename R = void >
449  using Continuation = std::function< R() >;
451 
452 private:
453 
454  // Variadic template specialized below
455  template< typename ...Params >
456  struct Executor;
457 
458  // This specialization grounds the recursion.
459  template< typename R, typename ConcreteType >
460  struct Executor< R, ConcreteType >
461  {
462  enum : unsigned { SetUsed = 0 };
463  // No functions matched, so do nothing.
464  R operator () (const void *) { return R{}; }
465  };
466 
467  // And another specialization is needed for void return.
468  template< typename ConcreteType >
469  struct Executor< void, ConcreteType >
470  {
471  enum : unsigned { SetUsed = 0 };
472  // No functions matched, so do nothing.
473  void operator () (const void *) { }
474  };
475 
476  // This struct groups some helpers needed to define the recursive cases of
477  // Executor.
478  struct Dispatcher {
479  // This implements the specialization of Executor
480  // for the first recursive case.
481  template< typename R, typename ConcreteType,
482  typename Function, typename ...Functions >
484  {
485  using Tail = Executor< R, ConcreteType, Functions... >;
486  enum : unsigned { SetUsed = Tail::SetUsed << 1 };
487 
488  // Ignore the first, inapplicable function and try others.
489  R operator ()
490  (const Track *pTrack,
491  const Function &, const Functions &...functions)
492  { return Tail{}( pTrack, functions... ); }
493  };
494 
495  // This implements the specialization of Executor
496  // for the second recursive case.
497  template< typename R, typename BaseClass, typename ConcreteType,
498  typename Function, typename ...Functions >
499  struct applicable1
500  {
501  enum : unsigned { SetUsed = 1u };
502 
503  // Ignore the remaining functions and call the first only.
504  R operator ()
505  (const Track *pTrack,
506  const Function &function, const Functions &...)
507  { return function( (BaseClass *)pTrack ); }
508  };
509 
510  // This implements the specialization of Executor
511  // for the third recursive case.
512  template< typename R, typename BaseClass, typename ConcreteType,
513  typename Function, typename ...Functions >
514  struct applicable2
515  {
516  using Tail = Executor< R, ConcreteType, Functions... >;
517  enum : unsigned { SetUsed = (Tail::SetUsed << 1) | 1u };
518 
519  // Call the first function, which may request dispatch to the further
520  // functions by invoking a continuation.
521  R operator ()
522  (const Track *pTrack, const Function &function,
523  const Functions &...functions)
524  {
525  auto continuation = Continuation<R>{ [&] {
526  return Tail{}( pTrack, functions... );
527  } };
528  return function( (BaseClass *)pTrack, continuation );
529  }
530  };
531 
532  // This variadic template chooses among the implementations above.
533  template< typename ... > struct Switch;
534 
535  // Ground the recursion.
536  template< typename R, typename ConcreteType >
537  struct Switch< R, ConcreteType >
538  {
539  // No BaseClass of ConcreteType is acceptable to Function.
540  template< typename Function, typename ...Functions >
541  static auto test()
542  -> inapplicable< R, ConcreteType, Function, Functions... >;
543  };
544 
545  // Recursive case.
546  template< typename R, typename ConcreteType,
547  typename BaseClass, typename ...BaseClasses >
548  struct Switch< R, ConcreteType, BaseClass, BaseClasses... >
549  {
550  using Retry = Switch< R, ConcreteType, BaseClasses... >;
551 
552  // If ConcreteType is not compatible with BaseClass, or if
553  // Function does not accept BaseClass, try other BaseClasses.
554  template< typename Function, typename ...Functions >
555  static auto test( const void * )
556  -> decltype( Retry::template test< Function, Functions... >() );
557 
558  // If BaseClass is a base of ConcreteType and Function can take it,
559  // then overload resolution chooses this.
560  // If not, then the sfinae rule makes this overload unavailable.
561  template< typename Function, typename ...Functions >
562  static auto test( std::true_type * )
563  -> decltype(
564  (void) std::declval<Function>()
565  ( (BaseClass*)nullptr ),
566  applicable1< R, BaseClass, ConcreteType,
567  Function, Functions... >{}
568  );
569 
570  // If BaseClass is a base of ConcreteType and Function can take it,
571  // with a second argument for a continuation,
572  // then overload resolution chooses this.
573  // If not, then the sfinae rule makes this overload unavailable.
574  template< typename Function, typename ...Functions >
575  static auto test( std::true_type * )
576  -> decltype(
577  (void) std::declval<Function>()
578  ( (BaseClass*)nullptr,
579  std::declval< Continuation<R> >() ),
580  applicable2< R, BaseClass, ConcreteType,
581  Function, Functions... >{}
582  );
583 
584  static constexpr bool Compatible = CompatibleTrackKinds(
585  track_kind<BaseClass>(), track_kind<ConcreteType>() );
586  template< typename Function, typename ...Functions >
587  static auto test()
588  -> decltype(
589  test< Function, Functions... >(
590  (std::integral_constant<bool, Compatible>*)nullptr) );
591  };
592  };
593 
594  // This specialization is the recursive case for non-const tracks.
595  template< typename R, typename ConcreteType,
596  typename Function, typename ...Functions >
597  struct Executor< R, ConcreteType, Function, Functions... >
598  : decltype(
599  Dispatcher::Switch< R, ConcreteType,
600  Track, AudioTrack, PlayableTrack,
601  WaveTrack, LabelTrack, TimeTrack,
602  NoteTrack >
603  ::template test<Function, Functions... >())
604  {};
605 
606  // This specialization is the recursive case for const tracks.
607  template< typename R, typename ConcreteType,
608  typename Function, typename ...Functions >
609  struct Executor< R, const ConcreteType, Function, Functions... >
610  : decltype(
611  Dispatcher::Switch< R, ConcreteType,
612  const Track, const AudioTrack, const PlayableTrack,
613  const WaveTrack, const LabelTrack, const TimeTrack,
614  const NoteTrack >
615  ::template test<Function, Functions... >())
616  {};
617 
618 public:
619 
620  // A variadic function taking any number of function objects, each taking
621  // a pointer to Track or a subclass, maybe const-qualified, and maybe a
622  // second argument which is a fall-through continuation.
623  // Each of the function objects (and supplied continuations) returns R.
624  // Call the first in the sequence that accepts the actual type of the track.
625  // If no function accepts the track, do nothing and return R{}
626  // if R is not void.
627  // If one of the functions invokes the call-through, then the next following
628  // applicable funtion is called.
629  template< typename R = void, typename ...Functions >
630  R TypeSwitch(const Functions &...functions)
631  {
632  using WaveExecutor =
633  Executor< R, WaveTrack, Functions... >;
634  using NoteExecutor =
635  Executor< R, NoteTrack, Functions... >;
636  using LabelExecutor =
637  Executor< R, LabelTrack, Functions... >;
638  using TimeExecutor =
639  Executor< R, TimeTrack, Functions... >;
640  using DefaultExecutor =
642  enum { All = sizeof...( functions ) };
643 
644  static_assert(
645  (1u << All) - 1u ==
646  (WaveExecutor::SetUsed |
647  NoteExecutor::SetUsed |
648  LabelExecutor::SetUsed |
649  TimeExecutor::SetUsed),
650  "Uncallable case in Track::TypeSwitch"
651  );
652 
653  switch (GetKind()) {
654  case TrackKind::Wave:
655  return WaveExecutor{} (this, functions...);
656 #if defined(USE_MIDI)
657  case TrackKind::Note:
658  return NoteExecutor{} (this, functions...);
659 #endif
660  case TrackKind::Label:
661  return LabelExecutor{}(this, functions...);
662  case TrackKind::Time:
663  return TimeExecutor{} (this, functions...);
664  default:
665  return DefaultExecutor{} (this);
666  }
667  }
668 
669  // This is the overload of TypeSwitch (see above) for const tracks, taking
670  // callable arguments that only accept arguments that are pointers to const
671  template< typename R = void, typename ...Functions >
672  R TypeSwitch(const Functions &...functions) const
673  {
674  using WaveExecutor =
675  Executor< R, const WaveTrack, Functions... >;
676  using NoteExecutor =
677  Executor< R, const NoteTrack, Functions... >;
678  using LabelExecutor =
679  Executor< R, const LabelTrack, Functions... >;
680  using TimeExecutor =
681  Executor< R, const TimeTrack, Functions... >;
682  using DefaultExecutor =
684  enum { All = sizeof...( functions ) };
685 
686  static_assert(
687  (1u << All) - 1u ==
688  (WaveExecutor::SetUsed |
689  NoteExecutor::SetUsed |
690  LabelExecutor::SetUsed |
691  TimeExecutor::SetUsed),
692  "Uncallable case in Track::TypeSwitch"
693  );
694 
695  switch (GetKind()) {
696  case TrackKind::Wave:
697  return WaveExecutor{} (this, functions...);
698 #if defined(USE_MIDI)
699  case TrackKind::Note:
700  return NoteExecutor{} (this, functions...);
701 #endif
702  case TrackKind::Label:
703  return LabelExecutor{}(this, functions...);
704  case TrackKind::Time:
705  return TimeExecutor{} (this, functions...);
706  default:
707  return DefaultExecutor{} (this);
708  }
709  }
710 
711  // XMLTagHandler callback methods -- NEW virtual for writing
712  virtual void WriteXML(XMLWriter &xmlFile) const = 0;
713 
714  // Returns true if an error was encountered while trying to
715  // open the track from XML
716  virtual bool GetErrorOpening() { return false; }
717 
718  virtual double GetStartTime() const = 0;
719  virtual double GetEndTime() const = 0;
720 
721  // Checks if sync-lock is on and any track in its sync-lock group is selected.
722  bool IsSyncLockSelected() const;
723 
724  // Send an event to listeners when state of the track changes
725  // To do: define values for the argument to distinguish different parts
726  // of the state, perhaps with wxNewId
727  void Notify( int code = -1 );
728 
729  // An always-true predicate useful for defining iterators
730  bool Any() const;
731 
732  // Frequently useful operands for + and -
733  bool IsSelected() const;
734  bool IsSelectedOrSyncLockSelected() const;
735  bool IsLeader() const;
736  bool IsSelectedLeader() const;
737 
738 protected:
739  std::shared_ptr<Track> FindTrack() override;
740 
741  // These are called to create controls on demand:
742  virtual std::shared_ptr<TrackControls> GetControls() = 0;
743  virtual std::shared_ptr<TrackVRulerControls> GetVRulerControls() = 0;
744 
745  // These hold the controls:
746  std::shared_ptr<TrackControls> mpControls;
747  std::shared_ptr<TrackVRulerControls> mpVRulerContols;
748  std::shared_ptr<TrackPanelResizerCell> mpResizer;
749 
750  std::weak_ptr<SelectHandle> mSelectHandle;
751  std::weak_ptr<TimeShiftHandle> mTimeShiftHandle;
752 };
753 
754 class AUDACITY_DLL_API AudioTrack /* not final */ : public Track
755 {
756 public:
757  AudioTrack(const std::shared_ptr<DirManager> &projDirManager)
758  : Track{ projDirManager } {}
759  AudioTrack(const Track &orig) : Track{ orig } {}
760 
761  // Serialize, not with tags of its own, but as attributes within a tag.
762  void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const {}
763 
764  // Return true iff the attribute is recognized.
765  bool HandleXMLAttribute(const wxChar * /*attr*/, const wxChar * /*value*/)
766  { return false; }
767 };
768 
769 class AUDACITY_DLL_API PlayableTrack /* not final */ : public AudioTrack
770 {
771 public:
772  PlayableTrack(const std::shared_ptr<DirManager> &projDirManager)
773  : AudioTrack{ projDirManager } {}
774  PlayableTrack(const Track &orig) : AudioTrack{ orig } {}
775 
776  bool GetMute () const { return mMute; }
777  bool GetSolo () const { return mSolo; }
778  void SetMute (bool m);
779  void SetSolo (bool s);
780 
781  void Init( const PlayableTrack &init );
782  void Merge( const Track &init ) override;
783 
784  // Serialize, not with tags of its own, but as attributes within a tag.
785  void WriteXMLAttributes(XMLWriter &xmlFile) const;
786 
787  // Return true iff the attribute is recognized.
788  bool HandleXMLAttribute(const wxChar *attr, const wxChar *value);
789 
790 protected:
791  bool mMute { false };
792  bool mSolo { false };
793 };
794 
795 // Functions to encapsulate the checked down-casting of track pointers,
796 // eliminating possibility of error -- and not quietly casting away const
797 // typical usage:
798 // if (auto wt = track_cast<WaveTrack*>(track)) { ... }
799 template<typename T>
800  inline typename std::enable_if< std::is_pointer<T>::value, T >::type
802 {
803  using BareType = typename std::remove_pointer< T >::type;
804  if (track &&
805  CompatibleTrackKinds( track_kind<BareType>(), track->GetKind() ))
806  return reinterpret_cast<T>(track);
807  else
808  return nullptr;
809 }
810 
811 // Overload for const pointers can cast only to other const pointer types
812 template<typename T>
813  inline typename std::enable_if<
814  std::is_pointer<T>::value &&
815  std::is_const< typename std::remove_pointer< T >::type >::value,
816  T
817  >::type
818  track_cast(const Track *track)
819 {
820  using BareType = typename std::remove_pointer< T >::type;
821  if (track &&
822  CompatibleTrackKinds( track_kind<BareType>(), track->GetKind() ))
823  return reinterpret_cast<T>(track);
824  else
825  return nullptr;
826 }
827 
828 template < typename TrackType > struct TrackIterRange;
829 
830 // new track iterators can eliminate the need to cast the result
831 template <
832  typename TrackType // Track or a subclass, maybe const-qualified
833 > class TrackIter
834  : public std::iterator<
835  std::bidirectional_iterator_tag,
836  TrackType *const,
837  ptrdiff_t,
838  // pointer is void to disable operator -> in the reverse_iterator...
839  void,
840  // ... because what operator * returns is really a value type,
841  // so you can't take its address
842  TrackType *const
843  >
844 {
845 public:
846  // Type of predicate taking pointer to const TrackType
847  // TODO C++14: simplify away ::type
848  using FunctionType = std::function< bool(
849  typename std::add_pointer<
850  typename std::add_const<
851  typename std::remove_pointer<
852  TrackType
853  >::type
854  >::type
855  >::type
856  ) >;
857 
858  template<typename Predicate = FunctionType>
860  TrackNodePointer end, const Predicate &pred = {} )
861  : mBegin( begin ), mIter( iter ), mEnd( end ), mPred( pred )
862  {
863  // Establish the class invariant
864  if (this->mIter != this->mEnd && !this->valid())
865  this->operator ++ ();
866  }
867 
868  // Return an iterator that replaces the predicate, advancing to the first
869  // position at or after the old position that satisfies the new predicate,
870  // or to the end.
871  template < typename Predicate2 >
872  TrackIter Filter( const Predicate2 &pred2 ) const
873  {
874  return { this->mBegin, this->mIter, this->mEnd, pred2 };
875  }
876 
877  // Return an iterator that refines the subclass (and not removing const),
878  // advancing to the first position at or after the old position that
879  // satisfies the type constraint, or to the end
880  template < typename TrackType2 >
881  auto Filter() const
882  -> typename std::enable_if<
883  std::is_base_of< TrackType, TrackType2 >::value &&
884  (!std::is_const<TrackType>::value ||
885  std::is_const<TrackType2>::value),
886  TrackIter< TrackType2 >
887  >::type
888  {
889  return { this->mBegin, this->mIter, this->mEnd, this->mPred };
890  }
891 
892  const FunctionType &GetPredicate() const
893  { return this->mPred; }
894 
895  // Unlike with STL iterators, this class gives well defined behavior when
896  // you increment an end iterator: you get the same.
898  {
899  // Maintain the class invariant
900  if (this->mIter != this->mEnd) do
901  ++this->mIter.first;
902  while (this->mIter != this->mEnd && !this->valid() );
903  return *this;
904  }
905 
907  {
908  TrackIter result { *this };
909  this-> operator ++ ();
910  return result;
911  }
912 
913  // Unlike with STL iterators, this class gives well defined behavior when
914  // you decrement past the beginning of a range: you wrap and get an end
915  // iterator.
917  {
918  // Maintain the class invariant
919  do {
920  if (this->mIter == this->mBegin)
921  // Go circularly
922  this->mIter = this->mEnd;
923  else
924  --this->mIter.first;
925  } while (this->mIter != this->mEnd && !this->valid() );
926  return *this;
927  }
928 
930  {
931  TrackIter result { *this };
932  this->operator -- ();
933  return result;
934  }
935 
936  // Unlike with STL iterators, this class gives well defined behavior when
937  // you dereference an end iterator: you get a null pointer.
938  TrackType *operator * () const
939  {
940  if (this->mIter == this->mEnd)
941  return nullptr;
942  else
943  // Other methods guarantee that the cast is correct
944  // (provided no operations on the TrackList invalidated
945  // underlying iterators or replaced the tracks there)
946  return static_cast< TrackType * >( &**this->mIter.first );
947  }
948 
949  // This might be called operator + ,
950  // but that might wrongly suggest constant time when the iterator is not
951  // random access.
952  TrackIter advance( long amount ) const
953  {
954  auto copy = *this;
955  std::advance( copy, amount );
956  return copy;
957  }
958 
959  friend inline bool operator == (TrackIter a, TrackIter b)
960  {
961  // Assume the predicate is not stateful. Just compare the iterators.
962  return
963  a.mIter == b.mIter
964  // Assume this too:
965  // && a.mBegin == b.mBegin && a.mEnd == b.mEnd
966  ;
967  }
968 
969  friend inline bool operator != (TrackIter a, TrackIter b)
970  {
971  return !(a == b);
972  }
973 
974 private:
975  bool valid() const
976  {
977  // assume mIter != mEnd
978  const auto pTrack = track_cast< TrackType * >( &**this->mIter.first );
979  if (!pTrack)
980  return false;
981  return !this->mPred || this->mPred( pTrack );
982  }
983 
984  // This friendship is needed in TrackIterRange::StartingWith and
985  // TrackIterRange::EndingAfter()
987 
988  // The class invariant is that mIter == mEnd, or else, mIter != mEnd and
989  // **mIter is of the appropriate subclass and mPred(&**mIter) is true.
992 };
993 
994 template <
995  typename TrackType // Track or a subclass, maybe const-qualified
996 > struct TrackIterRange
997  : public IteratorRange< TrackIter< TrackType > >
998 {
1000  ( const TrackIter< TrackType > &begin,
1001  const TrackIter< TrackType > &end )
1003  ( begin, end )
1004  {}
1005 
1006  // Conjoin the filter predicate with another predicate
1007  // Read + as "and"
1008  template< typename Predicate2 >
1009  TrackIterRange operator + ( const Predicate2 &pred2 ) const
1010  {
1011  const auto &pred1 = this->first.GetPredicate();
1012  using Function = typename TrackIter<TrackType>::FunctionType;
1013  const auto &newPred = pred1
1014  ? Function{ [=] (typename Function::argument_type track) {
1015  return pred1(track) && pred2(track);
1016  } }
1017  : Function{ pred2 };
1018  return {
1019  this->first.Filter( newPred ),
1020  this->second.Filter( newPred )
1021  };
1022  }
1023 
1024  // Specify the added conjunct as a pointer to member function
1025  // Read + as "and"
1026  template< typename R, typename C >
1027  TrackIterRange operator + ( R ( C ::* pmf ) () const ) const
1028  {
1029  return this->operator + ( std::mem_fn( pmf ) );
1030  }
1031 
1032  // Conjoin the filter predicate with the negation of another predicate
1033  // Read - as "and not"
1034  template< typename Predicate2 >
1035  TrackIterRange operator - ( const Predicate2 &pred2 ) const
1036  {
1037  using ArgumentType =
1038  typename TrackIterRange::iterator::FunctionType::argument_type;
1039  auto neg = [=] (ArgumentType track) { return !pred2( track ); };
1040  return this->operator + ( neg );
1041  }
1042 
1043  // Specify the negated conjunct as a pointer to member function
1044  // Read - as "and not"
1045  template< typename R, typename C >
1046  TrackIterRange operator - ( R ( C ::* pmf ) () const ) const
1047  {
1048  return this->operator + ( std::not1( std::mem_fn( pmf ) ) );
1049  }
1050 
1051  template< typename TrackType2 >
1053  {
1054  return {
1055  this-> first.template Filter< TrackType2 >(),
1056  this->second.template Filter< TrackType2 >()
1057  };
1058  }
1059 
1060  TrackIterRange StartingWith( const Track *pTrack ) const
1061  {
1062  auto newBegin = this->find( pTrack );
1063  // More careful construction is needed so that the independent
1064  // increment and decrement of each iterator in the NEW pair
1065  // has the expected behavior at boundaries of the range
1066  return {
1067  { newBegin.mIter, newBegin.mIter, this->second.mEnd,
1068  this->first.GetPredicate() },
1069  { newBegin.mIter, this->second.mEnd, this->second.mEnd,
1070  this->second.GetPredicate() }
1071  };
1072  }
1073 
1074  TrackIterRange EndingAfter( const Track *pTrack ) const
1075  {
1076  const auto newEnd = this->reversal().find( pTrack ).base();
1077  // More careful construction is needed so that the independent
1078  // increment and decrement of each iterator in the NEW pair
1079  // has the expected behavior at boundaries of the range
1080  return {
1081  { this->first.mBegin, this->first.mIter, newEnd.mIter,
1082  this->first.GetPredicate() },
1083  { this->first.mBegin, newEnd.mIter, newEnd.mIter,
1084  this->second.GetPredicate() }
1085  };
1086  }
1087 
1088  // Exclude one given track
1089  TrackIterRange Excluding ( const TrackType *pExcluded ) const
1090  {
1091  return this->operator - (
1092  [=](const Track *pTrack){ return pExcluded == pTrack; } );
1093  }
1094 
1095  // See Track::TypeSwitch
1096  template< typename ...Functions >
1097  void Visit(const Functions &...functions)
1098  {
1099  for (auto track : *this)
1100  track->TypeSwitch(functions...);
1101  }
1102 
1103  // See Track::TypeSwitch
1104  // Visit until flag is false, or no more tracks
1105  template< typename Flag, typename ...Functions >
1106  void VisitWhile(Flag &flag, const Functions &...functions)
1107  {
1108  if ( flag ) for (auto track : *this) {
1109  track->TypeSwitch(functions...);
1110  if (!flag)
1111  break;
1112  }
1113  }
1114 };
1115 
1116 
1121 struct TrackListEvent : public wxCommandEvent
1122 {
1123  explicit
1125  wxEventType commandType,
1126  const std::weak_ptr<Track> &pTrack = {}, int code = -1)
1127  : wxCommandEvent{ commandType }
1128  , mpTrack{ pTrack }
1129  , mCode{ code }
1130  {}
1131 
1132  TrackListEvent( const TrackListEvent& ) = default;
1133 
1134  wxEvent *Clone() const override { return new TrackListEvent(*this); }
1135 
1136  std::weak_ptr<Track> mpTrack;
1137  int mCode;
1138 };
1139 
1140 // Posted when the set of selected tracks changes.
1141 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
1142  EVT_TRACKLIST_SELECTION_CHANGE, TrackListEvent);
1143 
1144 // Posted when certain fields of a track change.
1145 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
1146  EVT_TRACKLIST_TRACK_DATA_CHANGE, TrackListEvent);
1147 
1148 // Posted when tracks are reordered but otherwise unchanged.
1149 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
1150  EVT_TRACKLIST_PERMUTED, TrackListEvent);
1151 
1152 // Posted when some track changed its height.
1153 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
1154  EVT_TRACKLIST_RESIZING, TrackListEvent);
1155 
1156 // Posted when a track has been added to a tracklist.
1157 // Also posted when one track replaces another
1158 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
1159  EVT_TRACKLIST_ADDITION, TrackListEvent);
1160 
1161 // Posted when a track has been deleted from a tracklist.
1162 // Also posted when one track replaces another
1163 wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API,
1164  EVT_TRACKLIST_DELETION, TrackListEvent);
1165 
1166 class TrackList final : public wxEvtHandler, public ListOfTracks
1167 {
1168  // privatize this, make you use Swap instead:
1169  using ListOfTracks::swap;
1170 
1171  // Create an empty TrackList
1172  TrackList();
1173 
1174  // Disallow copy
1175  TrackList(const TrackList &that) = delete;
1176  TrackList &operator= (const TrackList&) = delete;
1177 
1178  // Allow move
1179  TrackList(TrackList &&that) : TrackList() { Swap(that); }
1181 
1182  void clear() = delete;
1183 
1184  public:
1185  // Create an empty TrackList
1186  static std::shared_ptr<TrackList> Create();
1187 
1188  // Move is defined in terms of Swap
1189  void Swap(TrackList &that);
1190 
1191  // Destructor
1192  virtual ~TrackList();
1193 
1194  // Iteration
1195 
1196  // Hide the inherited begin() and end()
1199  using value_type = Track *;
1200  iterator begin() { return Any().begin(); }
1201  iterator end() { return Any().end(); }
1202  const_iterator begin() const { return Any().begin(); }
1203  const_iterator end() const { return Any().end(); }
1204  const_iterator cbegin() const { return begin(); }
1205  const_iterator cend() const { return end(); }
1206 
1207  // Turn a pointer into an iterator (constant time).
1208  template < typename TrackType = Track >
1209  auto Find(Track *pTrack)
1211  {
1212  if (!pTrack || pTrack->GetOwner().get() != this)
1213  return EndIterator<TrackType>();
1214  else
1215  return MakeTrackIterator<TrackType>( pTrack->GetNode() );
1216  }
1217 
1218  // Turn a pointer into an iterator (constant time).
1219  template < typename TrackType = const Track >
1220  auto Find(const Track *pTrack) const
1221  -> typename std::enable_if< std::is_const<TrackType>::value,
1223  >::type
1224  {
1225  if (!pTrack || pTrack->GetOwner().get() != this)
1226  return EndIterator<TrackType>();
1227  else
1228  return MakeTrackIterator<TrackType>( pTrack->GetNode() );
1229  }
1230 
1231  // If the track is not an audio track, or not one of a group of channels,
1232  // return the track itself; else return the first channel of its group --
1233  // in either case as an iterator that will only visit other leader tracks.
1234  // (Generalizing away from the assumption of at most stereo)
1235  TrackIter< Track > FindLeader( Track *pTrack );
1236 
1238  FindLeader( const Track *pTrack ) const
1239  {
1240  return const_cast<TrackList*>(this)->
1241  FindLeader( const_cast<Track*>(pTrack) ).Filter< const Track >();
1242  }
1243 
1244 
1245  template < typename TrackType = Track >
1246  auto Any()
1248  {
1249  return Tracks< TrackType >();
1250  }
1251 
1252  template < typename TrackType = const Track >
1253  auto Any() const
1254  -> typename std::enable_if< std::is_const<TrackType>::value,
1255  TrackIterRange< TrackType >
1256  >::type
1257  {
1258  return Tracks< TrackType >();
1259  }
1260 
1261  // Abbreviating some frequently used cases
1262  template < typename TrackType = Track >
1263  auto Selected()
1265  {
1266  return Tracks< TrackType >( &Track::IsSelected );
1267  }
1268 
1269  template < typename TrackType = const Track >
1270  auto Selected() const
1271  -> typename std::enable_if< std::is_const<TrackType>::value,
1272  TrackIterRange< TrackType >
1273  >::type
1274  {
1275  return Tracks< TrackType >( &Track::IsSelected );
1276  }
1277 
1278 
1279  template < typename TrackType = Track >
1280  auto Leaders()
1282  {
1283  return Tracks< TrackType >( &Track::IsLeader );
1284  }
1285 
1286  template < typename TrackType = const Track >
1287  auto Leaders() const
1288  -> typename std::enable_if< std::is_const<TrackType>::value,
1289  TrackIterRange< TrackType >
1290  >::type
1291  {
1292  return Tracks< TrackType >( &Track::IsLeader );
1293  }
1294 
1295 
1296  template < typename TrackType = Track >
1299  {
1300  return Tracks< TrackType >( &Track::IsSelectedLeader );
1301  }
1302 
1303  template < typename TrackType = const Track >
1304  auto SelectedLeaders() const
1305  -> typename std::enable_if< std::is_const<TrackType>::value,
1306  TrackIterRange< TrackType >
1307  >::type
1308  {
1309  return Tracks< TrackType >( &Track::IsSelectedLeader );
1310  }
1311 
1312 
1313  template<typename TrackType>
1314  static auto SingletonRange( TrackType *pTrack )
1316  {
1317  return pTrack->GetOwner()->template Any<TrackType>()
1318  .StartingWith( pTrack ).EndingAfter( pTrack );
1319  }
1320 
1321 
1323  SyncLockGroup( Track *pTrack );
1324 
1326  SyncLockGroup( const Track *pTrack )
1327  {
1328  return SyncLockGroup(const_cast<Track*>(pTrack)).Filter<const Track>();
1329  }
1330 
1331 private:
1332  template< typename TrackType, typename InTrackType >
1335  {
1336  // Assume iterator filters leader tracks
1337  if (*iter1) {
1338  return {
1339  iter1.Filter( &Track::Any )
1340  .template Filter<TrackType>(),
1341  (++iter1).Filter( &Track::Any )
1342  .template Filter<TrackType>()
1343  };
1344  }
1345  else
1346  // empty range
1347  return {
1348  iter1.template Filter<TrackType>(),
1349  iter1.template Filter<TrackType>()
1350  };
1351  }
1352 
1353 public:
1354  // Find an iterator range of channels including the given track.
1355  template< typename TrackType >
1356  static auto Channels( TrackType *pTrack )
1358  {
1359  return Channels_<TrackType>( pTrack->GetOwner()->FindLeader(pTrack) );
1360  }
1361 
1362  friend class Track;
1363 
1365  void Permute(const std::vector<TrackNodePointer> &permutation);
1366 
1367  Track *FindById( TrackId id );
1368 
1370  template<typename TrackKind>
1371  Track *Add(std::unique_ptr<TrackKind> &&t);
1372 
1374  template<typename TrackKind>
1375  Track *AddToHead(std::unique_ptr<TrackKind> &&t);
1376 
1378  template<typename TrackKind>
1379  Track *Add(std::shared_ptr<TrackKind> &&t);
1380 
1388  void GroupChannels(
1389  Track &track, size_t groupSize, bool resetChannels = true );
1390 
1393  ListOfTracks::value_type Replace(Track * t, ListOfTracks::value_type &&with);
1394 
1398 
1400  void Clear(bool sendEvent = true);
1401 
1402  int GetGroupHeight(const Track * t) const;
1403 
1404  bool CanMoveUp(Track * t) const;
1405  bool CanMoveDown(Track * t) const;
1406 
1407  bool MoveUp(Track * t);
1408  bool MoveDown(Track * t);
1409  bool Move(Track * t, bool up) { return up ? MoveUp(t) : MoveDown(t); }
1410 
1411  TimeTrack *GetTimeTrack();
1412  const TimeTrack *GetTimeTrack() const;
1413 
1420  unsigned GetNumExportChannels(bool selectionOnly) const;
1421 
1422  WaveTrackArray GetWaveTrackArray(bool selectionOnly, bool includeMuted = true);
1423  WaveTrackConstArray GetWaveTrackConstArray(bool selectionOnly, bool includeMuted = true) const;
1424 
1425 #if defined(USE_MIDI)
1426  NoteTrackConstArray GetNoteTrackConstArray(bool selectionOnly) const;
1427 #endif
1428 
1430  bool Contains(const Track * t) const;
1431 
1432  // Return non-null only if the weak pointer is not, and the track is
1433  // owned by this list; constant time.
1434  template <typename Subclass>
1435  std::shared_ptr<Subclass> Lock(const std::weak_ptr<Subclass> &wTrack)
1436  {
1437  auto pTrack = wTrack.lock();
1438  if (pTrack) {
1439  auto pList = pTrack->mList.lock();
1440  if (pTrack && this == pList.get())
1441  return pTrack;
1442  }
1443  return {};
1444  }
1445 
1446  bool empty() const;
1447  size_t size() const;
1448 
1449  double GetStartTime() const;
1450  double GetEndTime() const;
1451 
1452  double GetMinOffset() const;
1453  int GetHeight() const;
1454 
1455 #if LEGACY_PROJECT_FILE_SUPPORT
1456  // File I/O
1457  bool Load(wxTextFile * in, DirManager * dirManager) override;
1458  bool Save(wxTextFile * out, bool overwrite) override;
1459 #endif
1460 
1461 private:
1462 
1463  // Visit all tracks satisfying a predicate, mutative access
1464  template <
1465  typename TrackType = Track,
1466  typename Pred =
1468  >
1469  auto Tracks( const Pred &pred = {} )
1471  {
1472  auto b = getBegin(), e = getEnd();
1473  return { { b, b, e, pred }, { b, e, e, pred } };
1474  }
1475 
1476  // Visit all tracks satisfying a predicate, const access
1477  template <
1478  typename TrackType = const Track,
1479  typename Pred =
1481  >
1482  auto Tracks( const Pred &pred = {} ) const
1483  -> typename std::enable_if< std::is_const<TrackType>::value,
1485  >::type
1486  {
1487  auto b = const_cast<TrackList*>(this)->getBegin();
1488  auto e = const_cast<TrackList*>(this)->getEnd();
1489  return { { b, b, e, pred }, { b, e, e, pred } };
1490  }
1491 
1492  Track *GetPrev(Track * t, bool linked = false) const;
1493  Track *GetNext(Track * t, bool linked = false) const;
1494 
1495  std::pair<Track *, Track *> FindSyncLockGroup(Track *pMember) const;
1496 
1497  template < typename TrackType >
1500  {
1501  auto b = const_cast<TrackList*>(this)->getBegin();
1502  auto e = const_cast<TrackList*>(this)->getEnd();
1503  return { b, iter, e };
1504  }
1505 
1506  template < typename TrackType >
1508  EndIterator() const
1509  {
1510  auto e = const_cast<TrackList*>(this)->getEnd();
1511  return { e, e, e };
1512  }
1513 
1515 
1516  bool isNull(TrackNodePointer p) const
1517  { return (p.second == this && p.first == ListOfTracks::end())
1518  || (p.second == &mPendingUpdates && p.first == mPendingUpdates.end()); }
1520  { return { const_cast<TrackList*>(this)->ListOfTracks::end(),
1521  const_cast<TrackList*>(this)}; }
1523  { return { const_cast<TrackList*>(this)->ListOfTracks::begin(),
1524  const_cast<TrackList*>(this)}; }
1525 
1526  // Move an iterator to the next node, if any; else stay at end
1528  {
1529  if ( isNull(p) )
1530  return p;
1531  auto q = p;
1532  ++q.first;
1533  return q;
1534  }
1535 
1536  // Move an iterator to the previous node, if any; else wrap to end
1538  {
1539  if (p == getBegin())
1540  return getEnd();
1541  else {
1542  auto q = p;
1543  --q.first;
1544  return q;
1545  }
1546  }
1547 
1548  void RecalcPositions(TrackNodePointer node);
1549  void SelectionEvent( const std::shared_ptr<Track> &pTrack );
1550  void PermutationEvent();
1551  void DataEvent( const std::shared_ptr<Track> &pTrack, int code );
1552  void DeletionEvent();
1553  void AdditionEvent(TrackNodePointer node);
1554  void ResizingEvent(TrackNodePointer node);
1555 
1557 
1558  std::weak_ptr<TrackList> mSelf;
1559 
1560  // Nondecreasing during the session.
1561  // Nonpersistent.
1562  // Used to assign ids to added tracks.
1563  static long sCounter;
1564 
1565 public:
1566  using Updater = std::function< void(Track &dest, const Track &src) >;
1567  // Start a deferred update of the project.
1568  // The return value is a duplicate of the given track.
1569  // While ApplyPendingTracks or ClearPendingTracks is not yet called,
1570  // there may be other direct changes to the project that push undo history.
1571  // Meanwhile the returned object can accumulate other changes for a deferred
1572  // push, and temporarily shadow the actual project track for display purposes.
1573  // The Updater function, if not null, merges state (from the actual project
1574  // into the pending track) which is not meant to be overridden by the
1575  // accumulated pending changes.
1576  // To keep the display consistent, the Y and Height values, minimized state,
1577  // and Linked state must be copied, and this will be done even if the
1578  // Updater does not do it.
1579  // Pending track will have the same TrackId as the actual.
1580  // Pending changed tracks will not occur in iterations.
1581  std::shared_ptr<Track> RegisterPendingChangedTrack(
1582  Updater updater,
1583  Track *src
1584  );
1585 
1586  // Like the previous, but for a NEW track, not a replacement track. Caller
1587  // supplies the track, and there are no updates.
1588  // Pending track will have an unassigned TrackId.
1589  // Pending changed tracks WILL occur in iterations, always after actual
1590  // tracks, and in the sequence that they were added. They can be
1591  // distinguished from actual tracks by TrackId.
1592  void RegisterPendingNewTrack( const std::shared_ptr<Track> &pTrack );
1593 
1594  // Invoke the updaters of pending tracks. Pass any exceptions from the
1595  // updater functions.
1596  void UpdatePendingTracks();
1597 
1598  // Forget pending track additions and changes;
1599  // if requested, give back the pending added tracks.
1600  void ClearPendingTracks( ListOfTracks *pAdded = nullptr );
1601 
1602  // Change the state of the project.
1603  // Strong guarantee for project state in case of exceptions.
1604  // Will always clear the pending updates.
1605  // Return true if the state of the track list really did change.
1606  bool ApplyPendingTracks();
1607 
1608  bool HasPendingTracks() const;
1609 
1610 private:
1611  // Need to put pending tracks into a list so that GetLink() works
1613  // This is in correspondence with mPendingUpdates
1614  std::vector< Updater > mUpdaters;
1615 };
1616 
1617 class AUDACITY_DLL_API TrackFactory
1618 {
1619  private:
1620  TrackFactory(const std::shared_ptr<DirManager> &dirManager, const ZoomInfo *zoomInfo):
1621  mDirManager(dirManager)
1622  , mZoomInfo(zoomInfo)
1623  {
1624  }
1625 
1626  const std::shared_ptr<DirManager> mDirManager;
1627  const ZoomInfo *const mZoomInfo;
1628  friend class AudacityProject;
1629  friend class BenchmarkDialog;
1630 
1631  public:
1632  // These methods are defined in WaveTrack.cpp, NoteTrack.cpp,
1633  // LabelTrack.cpp, and TimeTrack.cpp respectively
1634  std::unique_ptr<WaveTrack> DuplicateWaveTrack(const WaveTrack &orig);
1635  std::unique_ptr<WaveTrack> NewWaveTrack(sampleFormat format = (sampleFormat)0,
1636  double rate = 0);
1637  std::unique_ptr<LabelTrack> NewLabelTrack();
1638  std::unique_ptr<TimeTrack> NewTimeTrack();
1639 #if defined(USE_MIDI)
1640  std::unique_ptr<NoteTrack> NewNoteTrack();
1641 #endif
1642 };
1643 
1644 // global functions
1645 struct TransportTracks;
1646 TransportTracks GetAllPlaybackTracks(TrackList &trackList, bool selectedOnly, bool useMidi = false);
1647 
1648 #endif
bool GetSolo() const
Definition: Track.h:777
void SetId(TrackId id)
Definition: Track.h:227
virtual void SetPan(float)
Definition: Track.h:393
constexpr bool CompatibleTrackKinds(TrackKind desired, TrackKind actual)
Definition: Track.h:92
iterator find(const T &t) const
Definition: MemoryX.h:460
Creates and manages BlockFile objects.
Definition: DirManager.h:52
TrackIterRange< TrackType2 > Filter() const
Definition: Track.h:1052
int GetActualHeight() const
Definition: Track.h:301
TransportTracks GetAllPlaybackTracks(TrackList &trackList, bool selectedOnly, bool useMidi=false)
Definition: Track.cpp:1418
ViewInfo is used mainly to hold the zooming, selection and scroll information. It also has some statu...
Definition: ViewInfo.h:143
TrackIter< TrackType > EndIterator() const
Definition: Track.h:1508
bool CanMoveDown(Track *t) const
Definition: Track.cpp:973
void DataEvent(const std::shared_ptr< Track > &pTrack, int code)
Definition: Track.cpp:647
auto Selected() const -> typename std::enable_if< std::is_const< TrackType >::value, TrackIterRange< TrackType > >::type
Definition: Track.h:1270
int GetHeight() const
Definition: Track.cpp:1191
PlayableTrack(const std::shared_ptr< DirManager > &projDirManager)
Definition: Track.h:772
bool isNull(TrackNodePointer p) const
Definition: Track.h:1516
auto Filter() const -> typename std::enable_if< std::is_base_of< TrackType, TrackType2 >::value &&(!std::is_const< TrackType >::value||std::is_const< TrackType2 >::value), TrackIter< TrackType2 > >::type
Definition: Track.h:881
R TypeSwitch(const Functions &...functions)
Definition: Track.h:630
double GetStartTime() const
Definition: Track.cpp:1226
TrackIter< const Track > FindLeader(const Track *pTrack) const
Definition: Track.h:1238
int mIndex
Definition: Track.h:203
std::vector< Track * > TrackArray
Definition: Snap.h:26
std::weak_ptr< Track > mpTrack
Definition: Track.h:1136
const_iterator cend() const
Definition: Track.h:1205
bool GetSelected() const
Definition: Track.h:381
TrackNodePointer mNode
Definition: Track.h:202
void GroupChannels(Track &track, size_t groupSize, bool resetChannels=true)
Define a group of channels starting at the given track.
Definition: Track.cpp:789
virtual void SetOffset(double o)
Definition: Track.h:391
auto SelectedLeaders() -> TrackIterRange< TrackType >
Definition: Track.h:1297
virtual TrackKind GetKind() const
Definition: Track.h:431
void Visit(const Functions &...functions)
Definition: Track.h:1097
auto Leaders() -> TrackIterRange< TrackType >
Definition: Track.h:1280
wxDECLARE_EXPORTED_EVENT(AUDACITY_DLL_API, EVT_TRACKLIST_SELECTION_CHANGE, TrackListEvent)
TrackId GetId() const
Definition: Track.h:225
Track * Add(std::unique_ptr< TrackKind > &&t)
Add a Track, giving it a fresh id.
Definition: Track.cpp:732
int mHeight
Definition: Track.h:205
ChannelType mChannel
Definition: Track.h:353
void DeletionEvent()
Definition: Track.cpp:660
double GetEndTime() const
Definition: Track.cpp:1231
R TypeSwitch(const Functions &...functions) const
Definition: Track.h:672
void Offset(double t)
Definition: Track.h:390
bool mSelected
Definition: Track.h:210
static auto SingletonRange(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1314
void RegisterPendingNewTrack(const std::shared_ptr< Track > &pTrack)
Definition: Track.cpp:1255
iterator begin()
Definition: Track.h:1200
void clear()=delete
void ClearPendingTracks(ListOfTracks *pAdded=nullptr)
Definition: Track.cpp:1282
TrackNodePointer mIter
Definition: Track.h:990
TrackKind
Definition: Track.h:75
std::pair< ListOfTracks::iterator, ListOfTracks * > TrackNodePointer
Definition: Track.h:67
auto Any() const -> typename std::enable_if< std::is_const< TrackType >::value, TrackIterRange< TrackType > >::type
Definition: Track.h:1253
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1246
void SwapNodes(TrackNodePointer s1, TrackNodePointer s2)
Definition: Track.cpp:982
bool GetLinked() const
Definition: Track.h:336
std::weak_ptr< SelectHandle > mSelectHandle
Definition: Track.h:750
const std::shared_ptr< DirManager > mDirManager
Definition: Track.h:1626
TrackIter< Track > FindLeader(Track *pTrack)
Definition: Track.cpp:697
auto Find(Track *pTrack) -> TrackIter< TrackType >
Definition: Track.h:1209
static long sCounter
Definition: Track.h:1563
A convenience for use with range-for.
Definition: MemoryX.h:437
bool MoveUp(Track *t)
Definition: Track.cpp:1041
virtual ChannelType GetChannel() const
Definition: Track.h:387
static TrackIterRange< const Track > SyncLockGroup(const Track *pTrack)
Definition: Track.h:1326
TrackList(TrackList &&that)
Definition: Track.h:1179
TrackId()
Definition: Track.h:173
TrackNodePointer mEnd
Definition: Track.h:990
static auto test(std::true_type *) -> decltype((void) std::declval< Function >()((BaseClass *) nullptr, std::declval< Continuation< R > >()), applicable2< R, BaseClass, ConcreteType, Function, Functions... >
Definition: Track.h:575
TrackNodePointer getPrev(TrackNodePointer p) const
Definition: Track.h:1537
bool ApplyPendingTracks()
Definition: Track.cpp:1309
TrackIter & operator--()
Definition: Track.h:916
TrackIterRange< Track > EmptyRange() const
Definition: Track.cpp:678
IteratorRange< reverse_iterator > reversal() const
Definition: MemoryX.h:447
constexpr TrackKind track_kind()
Definition: Track.h:142
const std::shared_ptr< DirManager > & GetDirManager() const
Definition: Track.h:400
wxString mDefaultName
Definition: Track.h:207
TrackId(long value)
Definition: Track.h:174
auto Leaders() const -> typename std::enable_if< std::is_const< TrackType >::value, TrackIterRange< TrackType > >::type
Definition: Track.h:1287
std::shared_ptr< TrackVRulerControls > mpVRulerContols
Definition: Track.h:747
TimeTrack * GetTimeTrack()
Definition: Track.cpp:1087
TrackList & operator=(const TrackList &)=delete
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1263
void ResizingEvent(TrackNodePointer node)
Definition: Track.cpp:672
static std::shared_ptr< TrackList > Create()
Definition: Track.cpp:574
Used to create a WaveTrack, or a LabelTrack.. Implementation of the functions of this class are dispe...
Definition: Track.h:1617
PlayableTrack(const Track &orig)
Definition: Track.h:774
virtual std::vector< UIHandlePtr > HitTest(const TrackPanelMouseState &state, const AudacityProject *pProject)=0
A LabelTrack is a Track that holds labels (LabelStruct).
Definition: LabelTrack.h:113
ChannelType
Definition: Track.h:218
std::shared_ptr< Track > RegisterPendingChangedTrack(Updater updater, Track *src)
Definition: Track.cpp:1237
FunctionType mPred
Definition: Track.h:991
wxString GetDefaultName() const
Definition: Track.h:378
TrackList()
Definition: Track.cpp:568
void Swap(TrackList &that)
Definition: Track.cpp:590
AudioTrack(const std::shared_ptr< DirManager > &projDirManager)
Definition: Track.h:757
TrackList is a flat linked list of tracks supporting Add, Remove, Clear, and Contains, plus serialization of the list of tracks.
Definition: Track.h:1121
TrackIter< TrackType > MakeTrackIterator(TrackNodePointer iter) const
Definition: Track.h:1499
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:174
A kind of Track used to 'warp time'.
Definition: TimeTrack.h:29
bool operator!=(const TrackId &other) const
Definition: Track.h:179
size_t size() const
Definition: Track.cpp:1077
TrackIter< TrackType > begin() const
Definition: MemoryX.h:450
std::function< void(Track &dest, const Track &src) > Updater
Definition: Track.h:1566
bool CanMoveUp(Track *t) const
Definition: Track.cpp:968
int format
Definition: ExportPCM.cpp:56
WaveTrackConstArray GetWaveTrackConstArray(bool selectionOnly, bool includeMuted=true) const
Definition: Track.cpp:1179
bool HandleXMLAttribute(const wxChar *, const wxChar *)
Definition: Track.h:765
AudioTrack(const Track &orig)
Definition: Track.h:759
friend bool operator!=(TrackIter a, TrackIter b)
Definition: Track.h:969
ListOfTracks mPendingUpdates
Definition: Track.h:1612
Track * GetNext(Track *t, bool linked=false) const
Return a track in the list that comes after Track t.
Definition: Track.cpp:906
long mValue
Definition: Track.h:188
void AdditionEvent(TrackNodePointer node)
Definition: Track.cpp:666
bool Any() const
Definition: Track.cpp:439
Track * AddToHead(std::unique_ptr< TrackKind > &&t)
Add a Track, giving it a fresh id.
Definition: Track.cpp:756
std::vector< std::shared_ptr< WaveTrack > > WaveTrackArray
Definition: AudioIO.h:67
bool operator<(const TrackId &other) const
Definition: Track.h:184
std::function< bool(typename std::add_pointer< typename std::add_const< typename std::remove_pointer< TrackType >::type >::type >::type) > FunctionType
Definition: Track.h:856
void RecalcPositions(TrackNodePointer node)
Definition: Track.cpp:613
std::shared_ptr< TrackPanelResizerCell > mpResizer
Definition: Track.h:748
std::vector< std::shared_ptr< const WaveTrack > > WaveTrackConstArray
Definition: AudioIO.h:68
TrackIter Filter(const Predicate2 &pred2) const
Definition: Track.h:872
bool mMinimized
Definition: Track.h:214
bool Contains(const Track *t) const
Mainly a test function. Uses a linear search, so could be slow.
Definition: Track.cpp:1067
TrackNodePointer mBegin
Definition: Track.h:990
virtual void SetPanFromChannelType()
Definition: Track.h:394
bool Move(Track *t, bool up)
Definition: Track.h:1409
std::shared_ptr< TrackPanelCell > ContextMenuDelegate() override
Definition: Track.h:273
TrackType * operator*() const
Definition: Track.h:938
A Track that can load/save audio data to/from XML.
Definition: Track.h:754
sampleFormat
Definition: Types.h:188
Track * FindById(TrackId id)
Definition: Track.cpp:720
TrackIter & operator++()
Definition: Track.h:897
virtual ~TrackList()
Definition: Track.cpp:608
std::weak_ptr< TimeShiftHandle > mTimeShiftHandle
Definition: Track.h:751
ListOfTracks::value_type Replace(Track *t, ListOfTracks::value_type &&with)
Definition: Track.cpp:841
std::weak_ptr< TrackList > mList
Definition: Track.h:201
A Track that contains audio waveform data.
Definition: WaveTrack.h:60
WaveTrackArray GetWaveTrackArray(bool selectionOnly, bool includeMuted=true)
Definition: Track.cpp:1174
TrackIter advance(long amount) const
Definition: Track.h:952
void VisitWhile(Flag &flag, const Functions &...functions)
Definition: Track.h:1106
bool HasPendingTracks() const
Definition: Track.cpp:1406
Fundamental data object of Audacity, placed in the TrackPanel. Classes derived form it include the Wa...
Definition: Track.h:191
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:333
const_iterator begin() const
Definition: Track.h:1202
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:72
unsigned GetNumExportChannels(bool selectionOnly) const
Find out how many channels this track list mixes to.
Definition: Track.cpp:1097
std::function< R() > Continuation
Definition: Track.h:449
auto SelectedLeaders() const -> typename std::enable_if< std::is_const< TrackType >::value, TrackIterRange< TrackType > >::type
Definition: Track.h:1304
auto Find(const Track *pTrack) const -> typename std::enable_if< std::is_const< TrackType >::value, TrackIter< TrackType > >::type
Definition: Track.h:1220
wxString GetName() const
Definition: Track.h:376
TrackIterRange(const TrackIter< TrackType > &begin, const TrackIter< TrackType > &end)
Definition: Track.h:1000
iterator end()
Definition: Track.h:1201
const_iterator cbegin() const
Definition: Track.h:1204
void SetChannel(ChannelType c)
Definition: Track.h:341
void Clear(bool sendEvent=true)
Make the list empty.
Definition: Track.cpp:884
TrackIterRange operator-(const Predicate2 &pred2) const
Definition: Track.h:1035
TrackNodePointer getEnd() const
Definition: Track.h:1519
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1435
TrackListEvent(wxEventType commandType, const std::weak_ptr< Track > &pTrack={}, int code=-1)
Definition: Track.h:1124
int GetGroupHeight(const Track *t) const
Definition: Track.cpp:963
TrackIterRange Excluding(const TrackType *pExcluded) const
Definition: Track.h:1089
An AudioTrack that can be played and stopped.
Definition: Track.h:769
static TrackIterRange< TrackType > Channels_(TrackIter< InTrackType > iter1)
Definition: Track.h:1334
bool MoveDown(Track *t)
Definition: Track.cpp:1054
double mOffset
Definition: Track.h:354
bool operator==(const TrackId &other) const
Definition: Track.h:176
void SetDefaultName(const wxString &n)
Definition: Track.h:379
bool operator==(const TrackNodePointer &a, const TrackNodePointer &b)
Definition: Track.h:69
friend class Track
Definition: Track.h:1362
bool mLinked
Definition: Track.h:213
bool IsLeader() const
Definition: Track.cpp:448
TrackNodePointer getBegin() const
Definition: Track.h:1522
double GetMinOffset() const
Definition: Track.cpp:1221
Continuation<> Fallthrough
Definition: Track.h:450
NoteTrackConstArray GetNoteTrackConstArray(bool selectionOnly) const
Definition: Track.cpp:1185
TrackNodePointer Remove(Track *t)
Definition: Track.cpp:863
void SelectionEvent(const std::shared_ptr< Track > &pTrack)
Definition: Track.cpp:640
friend bool operator==(TrackIter a, TrackIter b)
Definition: Track.h:959
Track * GetPrev(Track *t, bool linked=false) const
Definition: Track.cpp:925
void Permute(const std::vector< TrackNodePointer > &permutation)
For use in sorting: assume each iterator points into this list, no duplications.
Definition: Track.cpp:706
bool IsSelected() const
Definition: Track.cpp:442
auto Tracks(const Pred &pred={}) -> TrackIterRange< TrackType >
Definition: Track.h:1469
void Init(const Track &orig)
Definition: Track.cpp:78
std::tuple< Pair< Track, TrackKind::All >, Pair< AudioTrack, TrackKind::Audio >, Pair< PlayableTrack, TrackKind::Playable >, Pair< LabelTrack, TrackKind::Label >, Pair< NoteTrack, TrackKind::Note >, Pair< TimeTrack, TrackKind::Time >, Pair< WaveTrack, TrackKind::Wave > > List
Definition: Track.h:126
static auto test(std::true_type *) -> decltype((void) std::declval< Function >()((BaseClass *) nullptr), applicable1< R, BaseClass, ConcreteType, Function, Functions... >
Definition: Track.h:562
static TrackIterRange< Track > SyncLockGroup(Track *pTrack)
Definition: Track.cpp:688
bool IsSelectedLeader() const
Definition: Track.cpp:451
void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const
Definition: Track.h:762
TrackFactory(const std::shared_ptr< DirManager > &dirManager, const ZoomInfo *zoomInfo)
Definition: Track.h:1620
auto Tracks(const Pred &pred={}) const -> typename std::enable_if< std::is_const< TrackType >::value, TrackIterRange< TrackType > >::type
Definition: Track.h:1482
const ZoomInfo *const mZoomInfo
Definition: Track.h:1627
bool GetMute() const
Definition: Track.h:776
Definition: Track.h:170
std::vector< Updater > mUpdaters
Definition: Track.h:1614
bool SameKindAs(const Track &track) const
Definition: Track.h:445
TrackNodePointer getNext(TrackNodePointer p) const
Definition: Track.h:1527
TrackIterRange EndingAfter(const Track *pTrack) const
Definition: Track.h:1074
static std::shared_ptr< Subclass > Pointer(const Track *t)
Definition: Track.h:244
const_iterator end() const
Definition: Track.h:1203
std::unique_ptr< Track > Holder
Definition: Track.h:369
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:22
void PermutationEvent()
Definition: Track.cpp:654
static std::shared_ptr< Subclass > Pointer(Track *t)
Definition: Track.h:233
std::list< std::shared_ptr< Track > > ListOfTracks
Definition: Track.h:64
TrackIter(TrackNodePointer begin, TrackNodePointer iter, TrackNodePointer end, const Predicate &pred={})
Definition: Track.h:859
virtual void Merge(const Track &orig)
Definition: Track.cpp:112
std::enable_if< std::is_pointer< T >::value, T >::type track_cast(Track *track)
Definition: Track.h:801
bool valid() const
Definition: Track.h:975
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1356
TrackIterRange StartingWith(const Track *pTrack) const
Definition: Track.h:1060
virtual bool GetErrorOpening()
Definition: Track.h:716
wxSize vrulerSize
Definition: Track.h:284
bool operator!=(const TrackNodePointer &a, const TrackNodePointer &b)
Definition: Track.h:72
std::vector< std::shared_ptr< const NoteTrack > > NoteTrackConstArray
Definition: AudioIO.h:39
int mY
Definition: Track.h:204
std::pair< Track *, Track * > FindSyncLockGroup(Track *pMember) const
Definition: Track.cpp:511
std::shared_ptr< DirManager > mDirManager
Definition: Track.h:356
std::shared_ptr< TrackControls > mpControls
Definition: Track.h:746
std::weak_ptr< TrackList > mSelf
Definition: Track.h:1558
void UpdatePendingTracks()
Definition: Track.cpp:1262
wxEvent * Clone() const override
Definition: Track.h:1134
bool empty() const
Definition: Track.cpp:1072
TrackIterRange operator+(const Predicate2 &pred2) const
Definition: Track.h:1009
BenchmarkDialog is used for measuring performance and accuracy of the BlockFile system.
Definition: Benchmark.cpp:46
TrackIter< TrackType > end() const
Definition: MemoryX.h:451
A Track that is used for Midi notes. (Somewhat old code).
Definition: NoteTrack.h:66
TrackId mId
Definition: Track.h:198
friend WaveTrack
Definition: Track.h:338
const FunctionType & GetPredicate() const
Definition: Track.h:892
wxString mName
Definition: Track.h:206