Audacity 3.2.0
Track.h
Go to the documentation of this file.
1/*!********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file Track.h
6 @brief declares abstract base class Track, TrackList, and iterators over TrackList
7
8 Dominic Mazzoni
9
10**********************************************************************/
11
12#ifndef __AUDACITY_TRACK__
13#define __AUDACITY_TRACK__
14
15#include <atomic>
16#include <utility>
17#include <vector>
18#include <list>
19#include <functional>
20#include <wx/longlong.h>
21
22#include "ClientData.h"
23#include "Observer.h"
24// TrackAttachment needs to be a complete type for the Windows build, though
25// not the others, so there is a nested include here:
26#include "TrackAttachment.h"
27#include "XMLTagHandler.h"
28
29#ifdef __WXMSW__
30#pragma warning(disable:4284)
31#endif
32
33class wxTextFile;
34class Track;
35class ProjectSettings;
36class AudacityProject;
37
38using TrackArray = std::vector< Track* >;
39
40class TrackList;
41
42using ListOfTracks = std::list< std::shared_ptr< Track > >;
43
45
48std::pair< ListOfTracks::iterator, ListOfTracks* >;
49
50inline bool operator == (const TrackNodePointer &a, const TrackNodePointer &b)
51{ return a.second == b.second && a.first == b.first; }
52
53inline bool operator != (const TrackNodePointer &a, const TrackNodePointer &b)
54{ return !(a == b); }
55
56namespace {
57
60
65
67template<unsigned U, typename Tag> using EnumeratedTrackType =
68 std::remove_reference_t< decltype( enumerateTrackTypes( Tag{},
69 std::integral_constant<unsigned, U>{} ) ) >;
70
72
75template<typename Tag>
77 template<unsigned U> struct Stop{
78 static constexpr unsigned value = U; };
79 template<unsigned U> struct Count
80 : std::conditional_t<
81 std::is_void_v<EnumeratedTrackType<U, Tag>>,
82 Stop<U>,
83 Count<U + 1>
84 >
85 {};
86public:
87 static constexpr unsigned value = Count<0>::value;
88};
89
91
96template<typename Tag>
98 template<typename... Types> struct Stop{
99 using type = std::tuple<Types...>; };
100 template<unsigned U, typename... Types> struct Accumulate;
101 template<unsigned U, typename Type, typename... Types> struct AccumulateType
102 : std::conditional_t< std::is_void_v<Type>,
103 Stop<Types...>,
104 Accumulate<U + 1, Type, Types...>
105 >
106 {};
107 template<unsigned U, typename... Types> struct Accumulate
108 : AccumulateType<U, EnumeratedTrackType<U, Tag>, Types...>
109 {};
110public:
111 using type = typename Accumulate<0>::type;
112};
113
115template<typename T>
118 static constexpr unsigned value = CountTrackTypes<Tag>::value;
119};
120
121}
122
124
125#define ENUMERATE_TRACK_TYPE(T) namespace { auto enumerateTrackTypes(\
126 TrackTypeCountTag, \
127 std::integral_constant<unsigned, TrackTypeCounter<T>::value>) -> T&; }
128
129// forward declarations, so we can make them friends
130template<typename T>
131 std::enable_if_t< std::is_pointer_v<T>, T >
132 track_cast(Track *track);
133
134template<typename T>
135 std::enable_if_t<
136 std::is_pointer_v<T> &&
137 std::is_const_v< std::remove_pointer_t< T > >,
138 T
139 >
140 track_cast(const Track *track);
141
143
151{
152public:
153 TrackId() : mValue(-1) {}
154 explicit TrackId (long value) : mValue(value) {}
155
156 bool operator == (const TrackId &other) const
157 { return mValue == other.mValue; }
158
159 bool operator != (const TrackId &other) const
160 { return mValue != other.mValue; }
161
162 // Define this in case you want to key a std::map on TrackId
163 // The operator does not mean anything else
164 bool operator < (const TrackId &other) const
165 { return mValue < other.mValue; }
166
167private:
168 long mValue;
169};
170
172struct TRACK_API TrackIntervalData {
174};
175
177
179public:
180
182 ConstTrackInterval( double start, double end,
183 std::unique_ptr<TrackIntervalData> pExtra = {} )
184 : start{ start }, end{ end }, pExtra{ std::move( pExtra ) }
185 {
186 wxASSERT( start <= end );
187 }
188
191
192 double Start() const { return start; }
193 double End() const { return end; }
194 const TrackIntervalData *Extra() const { return pExtra.get(); }
195
196private:
197 double start, end;
198protected:
199 // TODO C++17: use std::any instead
200 std::unique_ptr< TrackIntervalData > pExtra;
201};
202
204
206public:
208
211
212 TrackIntervalData *Extra() const { return pExtra.get(); }
213};
214
218>;
219
221class TRACK_API Track /* not final */
222 : public XMLTagHandler
223 , public AttachedTrackObjects
224 , public std::enable_shared_from_this<Track> // see SharedPointer()
225{
226protected:
228
233public:
234
236 enum class LinkType : int {
237 None = 0, //< No linkage
238 Group = 2, //< Tracks are grouped together
239 Aligned, //< Tracks are grouped and changes should be synchronized
240 };
241
242 struct ChannelGroupData;
243
247 >;
248
249 // Structure describing data common to channels of a group of tracks
250 // Should be deep-copyable (think twice before adding shared pointers!)
252 LinkType mLinkType{ LinkType::None };
253 };
254
255private:
256
257 friend class TrackList;
258
259 private:
261
262 std::unique_ptr<ChannelGroupData> mpGroupData;
263
264 protected:
265 std::weak_ptr<TrackList> mList;
267
269 int mIndex;
270 wxString mName;
271
272 private:
274
275 public:
276
279
281 {
282 LeftChannel = 0,
283 RightChannel = 1,
284 MonoChannel = 2
285 };
286
287 TrackId GetId() const { return mId; }
288 private:
289 void SetId( TrackId id ) { mId = id; }
290 public:
291
292 // Given a bare pointer, find a shared_ptr. Undefined results if the track
293 // is not yet managed by a shared_ptr. Undefined results if the track is
294 // not really of the subclass. (That is, trusts the caller and uses static
295 // not dynamic casting.)
296 template<typename Subclass = Track>
297 inline std::shared_ptr<Subclass> SharedPointer()
298 {
299 // shared_from_this is injected into class scope by base class
300 // std::enable_shared_from_this<Track>
301 return std::static_pointer_cast<Subclass>( shared_from_this() );
302 }
303
304 template<typename Subclass = const Track>
305 inline auto SharedPointer() const ->
306 std::enable_if_t<
307 std::is_const_v<Subclass>, std::shared_ptr<Subclass>
308 >
309 {
310 // shared_from_this is injected into class scope by base class
311 // std::enable_shared_from_this<Track>
312 return std::static_pointer_cast<Subclass>( shared_from_this() );
313 }
314
315 // Static overloads of SharedPointer for when the pointer may be null
316 template<typename Subclass = Track>
317 static inline std::shared_ptr<Subclass> SharedPointer( Track *pTrack )
318 { return pTrack ? pTrack->SharedPointer<Subclass>() : nullptr; }
319
320 template<typename Subclass = const Track>
321 static inline std::shared_ptr<Subclass> SharedPointer( const Track *pTrack )
322 { return pTrack ? pTrack->SharedPointer<Subclass>() : nullptr; }
323
324 // Find anything registered with TrackList::RegisterPendingChangedTrack and
325 // not yet cleared or applied; if no such exists, return this track
326 std::shared_ptr<Track> SubstitutePendingChangedTrack();
327 std::shared_ptr<const Track> SubstitutePendingChangedTrack() const;
328
329 // If this track is a pending changed track, return the corresponding
330 // original; else return this track
331 std::shared_ptr<const Track> SubstituteOriginalTrack() const;
332
335 using Intervals = std::vector< Interval >;
337 using ConstIntervals = std::vector< ConstInterval >;
338
340
341 struct TypeNames {
342 wxString info;
343 wxString property;
345 };
346 struct TypeInfo {
348 bool concrete = false;
349 const TypeInfo *pBaseInfo = nullptr;
350
351 bool IsBaseOf(const TypeInfo &other) const
352 {
353 for (auto pInfo = &other;
354 pInfo; pInfo = pInfo->pBaseInfo)
355 if (this == pInfo)
356 return true;
357 return false;
358 }
359 };
360 virtual const TypeInfo &GetTypeInfo() const = 0;
361 static const TypeInfo &ClassTypeInfo();
362 virtual const TypeNames &GetTypeNames() const
363 { return GetTypeInfo().names; }
364
366 virtual bool SupportsBasicEditing() const;
367
368 using Holder = std::shared_ptr<Track>;
369
371
372 virtual Holder PasteInto( AudacityProject & ) const = 0;
373
375
378 virtual ConstIntervals GetIntervals() const;
379
383 virtual Intervals GetIntervals();
384
385 public:
386 mutable std::pair<int, int> vrulerSize;
387
388 int GetIndex() const;
389 void SetIndex(int index);
390
391public:
392 static void FinishCopy (const Track *n, Track *dest);
393
395
401 virtual bool LinkConsistencyFix(bool doFix = true, bool completeList = true);
402
404 bool LinkConsistencyCheck(bool completeList)
405 { return const_cast<Track*>(this)->LinkConsistencyFix(false, completeList); }
406
407 bool HasOwner() const { return static_cast<bool>(GetOwner());}
408
409 std::shared_ptr<TrackList> GetOwner() const { return mList.lock(); }
410
411 LinkType GetLinkType() const noexcept;
413 bool IsAlignedWithLeader() const;
414
415 ChannelGroupData &GetGroupData();
416 const ChannelGroupData &GetGroupData() const;
417
418protected:
419
423 void SetLinkType(LinkType linkType, bool completeList = true);
424 void SetChannel(ChannelType c) noexcept;
425
426private:
427 ChannelGroupData &MakeGroupData();
431 void DoSetLinkType(LinkType linkType, bool completeList = true);
432
433 Track* GetLinkedTrack() const;
435 bool HasLinkedTrack() const noexcept;
436
438 TrackNodePointer GetNode() const;
440 void SetOwner
441 (const std::weak_ptr<TrackList> &list, TrackNodePointer node);
442
443 // Keep in Track
444
445 protected:
446 ChannelType mChannel;
447 double mOffset;
448
449 public:
450
451 Track();
452 Track(const Track &orig, ProtectedCreationArg&&);
453 Track& operator =(const Track &orig) = delete;
454
455 virtual ~ Track();
456
457 void Init(const Track &orig);
458
459 // public nonvirtual duplication function that invokes Clone():
460 virtual Holder Duplicate() const;
461
462 // Called when this track is merged to stereo with another, and should
463 // take on some parameters of its partner.
464 virtual void Merge(const Track &orig);
465
466 wxString GetName() const { return mName; }
467 void SetName( const wxString &n );
468
469 bool GetSelected() const { return mSelected; }
470
471 virtual void SetSelected(bool s);
472
473 // The argument tells whether the last undo history state should be
474 // updated for the appearance change
475 void EnsureVisible( bool modifyState = false );
476
477public:
478
479 virtual ChannelType GetChannel() const { return mChannel;}
480 virtual double GetOffset() const = 0;
481
482 void Offset(double t) { SetOffset(GetOffset() + t); }
483 virtual void SetOffset (double o) { mOffset = o; }
484
485 virtual void SetPan( float ){ ;}
486 virtual void SetPanFromChannelType(){ ;};
487
488 // Create a NEW track and modify this track
489 // Return non-NULL or else throw
490 // May assume precondition: t0 <= t1
491 virtual Holder Cut(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
492
493 // Create a NEW track and don't modify this track
494 // Return non-NULL or else throw
495 // Note that subclasses may want to distinguish tracks stored in a clipboard
496 // from those stored in a project
497 // May assume precondition: t0 <= t1
498 // Should invoke Track::Init
499 virtual Holder Copy
500 (double WXUNUSED(t0), double WXUNUSED(t1), bool forClipboard = true) const = 0;
501
502 // May assume precondition: t0 <= t1
503 virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
504
505 virtual void Paste(double WXUNUSED(t), const Track * WXUNUSED(src)) = 0;
506
507 // This can be used to adjust a sync-lock selected track when the selection
508 // is replaced by one of a different length.
509 virtual void SyncLockAdjust(double oldT1, double newT1);
510
511 // May assume precondition: t0 <= t1
512 virtual void Silence(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
513
514 // May assume precondition: t0 <= t1
515 virtual void InsertSilence(double WXUNUSED(t), double WXUNUSED(len)) = 0;
516
517private:
518 // Subclass responsibility implements only a part of Duplicate(), copying
519 // the track data proper (not associated data such as for groups and views):
520 virtual Holder Clone() const = 0;
521
522 template<typename T>
523 friend std::enable_if_t< std::is_pointer_v<T>, T >
524 track_cast(Track *track);
525 template<typename T>
526 friend std::enable_if_t<
527 std::is_pointer_v<T> &&
528 std::is_const_v< std::remove_pointer_t< T > >,
529 T
530 >
531 track_cast(const Track *track);
532
533public:
534 bool SameKindAs(const Track &track) const
535 { return &GetTypeInfo() == &track.GetTypeInfo(); }
536
538 template < typename R = void >
539 using Continuation = std::function< R() >;
542
543private:
545 template< typename ...Params >
546 struct Executor{};
547
549
550 struct Dispatcher {
552 template< typename Tag, typename R, typename ArgumentType,
553 typename Function, typename ...Functions >
555 {
557 std::conditional_t< std::is_const_v<ArgumentType>,
558 const Track, Track >;
559
561 using Tail = Executor< Tag, R, ArgumentType, Functions... >;
563 enum : unsigned { SetUsed = Tail::SetUsed << 1 };
564
566 R operator ()
567 (QualifiedTrackType *pTrack,
568 const Function &, const Functions &...functions) const
569 { return Tail{}( pTrack, functions... ); }
570 };
571
573 template< typename R, typename BaseClass, typename ArgumentType,
574 typename Function >
576 {
578 std::conditional_t< std::is_const_v<ArgumentType>,
579 const Track, Track >;
581 std::conditional_t< std::is_const_v<ArgumentType>,
582 const BaseClass, BaseClass >;
583
585 enum : unsigned { SetUsed = 1u };
586
588 R operator ()
589 (QualifiedTrackType *pTrack, const Function &function, ...) const
590 { return function( static_cast<QualifiedBaseClass *>(pTrack) ); }
591 };
592
594 template< typename Tag,
595 typename R, typename BaseClass, typename ArgumentType,
596 typename Function, typename ...Functions >
598 {
600 std::conditional_t< std::is_const_v<ArgumentType>,
601 const Track, Track >;
603 std::conditional_t< std::is_const_v<ArgumentType>,
604 const BaseClass, BaseClass >;
605
607 using Tail = Executor< Tag, R, ArgumentType, Functions... >;
609 enum : unsigned { SetUsed = (Tail::SetUsed << 1) | 1u };
610
612 R operator ()
613 (QualifiedTrackType *pTrack, const Function &function,
614 const Functions &...functions) const
615 {
616 auto continuation = Continuation<R>{ [&] {
617 return Tail{}( pTrack, functions... );
618 } };
619 return function( static_cast<QualifiedBaseClass *>(pTrack),
620 continuation );
621 }
622 };
623
625 template< typename ... > struct Switch {};
626
628
629 template< typename Tag, typename R, typename ArgumentType >
630 struct Switch< Tag, R, ArgumentType, std::tuple<> >
631 {
633 template< typename Function, typename ...Functions >
634 static auto test()
635 -> inapplicable< Tag, R, ArgumentType, Function, Functions... >;
636 };
637
639
640 template< typename Tag, typename R, typename ArgumentType,
641 typename BaseClass, typename ...BaseClasses >
642 struct Switch< Tag, R, ArgumentType, std::tuple<BaseClass, BaseClasses...> >
643 {
645 std::conditional_t< std::is_const_v<ArgumentType>,
646 const BaseClass, BaseClass >;
647
649 using Retry =
650 Switch< Tag, R, ArgumentType, std::tuple<BaseClasses...> >;
651
653
655 template< typename Function, typename ...Functions >
656 static auto test( const void * )
657 -> decltype( Retry::template test< Function, Functions... >() );
658
660
663 template< typename Function, typename ...Functions >
664 static auto test( std::true_type * )
665 -> decltype(
666 (void) std::declval<Function>()
667 ( (QualifiedBaseClass*)nullptr ),
669 );
670
672
676 template< typename Function, typename ...Functions >
677 static auto test( std::true_type * )
678 -> decltype(
679 (void) std::declval<Function>()
680 ( (QualifiedBaseClass*)nullptr,
681 std::declval< Continuation<R> >() ),
682 applicable2< Tag, R, BaseClass, ArgumentType,
683 Function, Functions... >{}
684 );
685
687 static constexpr bool Compatible =
688 std::is_base_of_v<BaseClass, ArgumentType>;
690 template< typename Function, typename ...Functions >
691 static auto test()
692 -> decltype(
693 test< Function, Functions... >(
694 (std::integral_constant<bool, Compatible>*)nullptr) );
695 };
696 };
697
699 template< typename Tag, typename R, typename ArgumentType >
700 struct Executor< Tag, R, ArgumentType >
701 {
702 using NominalType = ArgumentType;
704 enum : unsigned { SetUsed = 0 };
706 R operator () (const void *, ...)
707 {
708 if constexpr (std::is_void_v<R>)
709 return;
710 else
711 return R{};
712 }
713 };
714
716
717 template< typename Tag, typename R, typename ArgumentType,
718 typename Function, typename ...Functions >
719 struct Executor< Tag, R, ArgumentType, Function, Functions... >
720 : decltype(
721 Dispatcher::Switch< Tag, R, ArgumentType,
722 typename CollectTrackTypes<Tag>::type >
723 ::template test<Function, Functions... >())
724 {
725 using NominalType = ArgumentType;
726 };
727
728public:
729
730 template<typename TrackType>
731 static void checkTrackType()
732 {
733 static_assert(
734 std::is_same_v<Track, TrackType> ||
735 std::is_same_v<const Track, TrackType>, "Error" );
736 }
737 template<typename R, typename TrackType, typename... Functions>
738 static R CallExecutor(R*, std::tuple<>*, TrackType&, const Functions&...)
739 {
740 // This overload is needed so that the other overload of CallExecutor
741 // compiles, but it should never be reached at run-time, because an
742 // Executor generated for (const) Track should have been the catch-all.
743 wxASSERT(false);
744 checkTrackType<TrackType>();
745 if constexpr (std::is_void_v<R>)
746 return;
747 else
748 return R{};
749 }
750 template<
751 typename R, typename TrackType, typename... Functions,
752 typename Executor, typename... Executors>
753 static R CallExecutor(
754 R*, std::tuple<Executor, Executors...>*, TrackType &track,
755 const Functions &...functions)
756 {
757 checkTrackType<TrackType>();
758 const auto &info = Executor::NominalType::ClassTypeInfo();
759 // Dynamic type test of track
760 // Assumes Executor classes are sequenced with more specific accepted
761 // types earlier
762 if ( info.IsBaseOf(track.GetTypeInfo()) )
763 // Dispatch to an Executor that knows which of functions applies
764 return Executor{}(&track, functions...);
765 else
766 // Recur, with fewer candidate Executors and all of functions
767 return CallExecutor( (R*)nullptr,
768 (std::tuple<Executors...>*)nullptr, track, functions...);
769 }
770
771 template<typename ...Executors>
772 static constexpr unsigned UsedCases(std::tuple<Executors...>*)
773 {
774 return (Executors::SetUsed | ...); // My very first fold expression :-)
775 }
776
777 template<
778 typename Tag,
779 bool IsConst,
780 typename R,
781 typename ...TrackTypes,
782 typename ...Functions
783 >
784 static R DoTypeSwitch(
785 std::conditional_t<IsConst, const Track, Track> &track,
786 std::tuple<TrackTypes...>*,
787 const Functions &...functions )
788 {
789 // Generate Executor classes, for each of TrackTypes,
790 // each zero-sized and with an operator () that calls the correct
791 // one of functions, assuming the track is of the corresponding type
792 using Executors = std::tuple< Executor<
793 Tag, R,
794 std::conditional_t<IsConst, const TrackTypes, TrackTypes>,
795 Functions...
796 >... >;
797 // Don't even construct the tuple of zero-sized types, just point
798 constexpr Executors *executors = nullptr;
799
800 // Compile time reachability check of the given functions
801 enum { All = sizeof...( functions ) };
802 static_assert( (1u << All) - 1u == UsedCases(executors),
803 "Uncallable case in Track::TypeSwitch");
804
805 // Do dynamic dispatch to one of the Executors
806 return CallExecutor((R *)nullptr, executors, track, functions...);
807 }
808
810
828 template<
829 typename R = void,
830 typename ...Functions
831 >
832 R TypeSwitch(const Functions &...functions)
833 {
834 struct Tag : TrackTypeCountTag {};
835 // Collect all concrete and abstract track types known at compile time
836 using TrackTypes = typename CollectTrackTypes<Tag>::type;
837 TrackTypes *const trackTypes = nullptr;
838 // Generate a function that dispatches dynamically on track type
839 return DoTypeSwitch<Tag, false, R>(*this, trackTypes, functions...);
840 }
841
845 template<
846 typename R = void,
847 typename ...Functions
848 >
849 R TypeSwitch(const Functions &...functions) const
850 {
851 struct Tag : TrackTypeCountTag {};
852 // Collect all concrete and abstract track types known at compile time
853 using TrackTypes = typename CollectTrackTypes<Tag>::type;
854 TrackTypes *const trackTypes = nullptr;
855 // Generate a function that dispatches dynamically on track type
856 return DoTypeSwitch<Tag, true, R>(*this, trackTypes, functions...);
857 }
858
859 // XMLTagHandler callback methods -- NEW virtual for writing
860 virtual void WriteXML(XMLWriter &xmlFile) const = 0;
861
862 // Returns true if an error was encountered while trying to
863 // open the track from XML
864 virtual bool GetErrorOpening() { return false; }
865
866 virtual double GetStartTime() const = 0;
867 virtual double GetEndTime() const = 0;
868
869 // Send a notification to subscribers when state of the track changes
870 // To do: define values for the argument to distinguish different parts
871 // of the state
872 void Notify( int code = -1 );
873
874 // An always-true predicate useful for defining iterators
875 bool Any() const;
876
877 // Frequently useful operands for + and -
878 bool IsSelected() const;
879 bool IsLeader() const;
880 bool IsSelectedLeader() const;
881
882 // Cause this track and following ones in its TrackList to adjust
883 void AdjustPositions();
884
885 // Serialize, not with tags of its own, but as attributes within a tag.
886 void WriteCommonXMLAttributes(
887 XMLWriter &xmlFile, bool includeNameAndSelected = true) const;
888
889 // Return true iff the attribute is recognized.
890 bool HandleCommonXMLAttribute(const std::string_view& attr, const XMLAttributeValueView& valueView);
891};
892
894
896class TRACK_API AudioTrack /* not final */ : public Track
897{
898public:
899 AudioTrack();
900 AudioTrack(const Track &orig, ProtectedCreationArg &&a);
901
902 static const TypeInfo &ClassTypeInfo();
903
904 // Serialize, not with tags of its own, but as attributes within a tag.
905 void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const {}
906
907 // Return true iff the attribute is recognized.
908 bool HandleXMLAttribute(const std::string_view & /*attr*/, const XMLAttributeValueView &/*value*/)
909 { return false; }
910};
911
913
915class TRACK_API PlayableTrack /* not final */ : public AudioTrack
916{
917public:
920
921 static const TypeInfo &ClassTypeInfo();
922
923 bool GetMute () const { return DoGetMute(); }
924 bool GetSolo () const { return DoGetSolo(); }
925 bool GetNotMute () const { return !DoGetMute(); }
926 bool GetNotSolo () const { return !DoGetSolo(); }
927 void SetMute (bool m);
928 void SetSolo (bool s);
929
930 void Init( const PlayableTrack &init );
931 void Merge( const Track &init ) override;
932
933 // Serialize, not with tags of its own, but as attributes within a tag.
934 void WriteXMLAttributes(XMLWriter &xmlFile) const;
935
936 // Return true iff the attribute is recognized.
937 bool HandleXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &value);
938
939protected:
940 // These just abbreviate load and store with relaxed memory ordering
941 bool DoGetMute() const;
942 void DoSetMute(bool value);
943 bool DoGetSolo() const;
944 void DoSetSolo(bool value);
945
947 std::atomic<bool> mMute { false };
949 std::atomic<bool> mSolo { false };
950};
951
953
954
956
963template<typename T>
964 inline std::enable_if_t< std::is_pointer_v<T>, T >
966{
967 using BareType = std::remove_pointer_t< T >;
968 if (track &&
969 BareType::ClassTypeInfo().IsBaseOf(track->GetTypeInfo() ))
970 return reinterpret_cast<T>(track);
971 else
972 return nullptr;
973}
974
977template<typename T>
978 inline std::enable_if_t<
979 std::is_pointer_v<T> && std::is_const_v< std::remove_pointer_t< T > >,
980 T
981 >
982 track_cast(const Track *track)
983{
984 using BareType = std::remove_pointer_t< T >;
985 if (track &&
986 BareType::ClassTypeInfo().IsBaseOf(track->GetTypeInfo() ))
987 return reinterpret_cast<T>(track);
988 else
989 return nullptr;
990}
991
992template < typename TrackType > struct TrackIterRange;
993
995
1002template <
1003 typename TrackType
1005 : public ValueIterator< TrackType *, std::bidirectional_iterator_tag >
1006{
1007public:
1009 using FunctionType = std::function< bool(
1010 std::add_pointer_t< std::add_const_t< std::remove_pointer_t<TrackType> > >
1011 ) >;
1012
1016 TrackNodePointer iter,
1018 FunctionType pred = {}
1019 )
1020 : mBegin( begin ), mIter( iter ), mEnd( end )
1021 , mPred( std::move(pred) )
1022 {
1023 // Establish the class invariant
1024 if (this->mIter != this->mEnd && !this->valid())
1025 this->operator ++ ();
1026 }
1027
1029
1031 template < typename Predicate2 >
1032 TrackIter Filter( const Predicate2 &pred2 ) const
1033 {
1034 return { this->mBegin, this->mIter, this->mEnd, pred2 };
1035 }
1036
1038
1040 template < typename TrackType2 >
1041 auto Filter() const
1042 -> std::enable_if_t<
1043 std::is_base_of_v< TrackType, TrackType2 > &&
1044 (!std::is_const_v<TrackType> ||
1045 std::is_const_v<TrackType2>),
1046 TrackIter< TrackType2 >
1047 >
1048 {
1049 return { this->mBegin, this->mIter, this->mEnd, this->mPred };
1050 }
1051
1053 { return this->mPred; }
1054
1056
1058 {
1059 // Maintain the class invariant
1060 if (this->mIter != this->mEnd) do
1061 ++this->mIter.first;
1062 while (this->mIter != this->mEnd && !this->valid() );
1063 return *this;
1064 }
1065
1068 {
1069 TrackIter result { *this };
1070 this-> operator ++ ();
1071 return result;
1072 }
1073
1075
1077 {
1078 // Maintain the class invariant
1079 do {
1080 if (this->mIter == this->mBegin)
1081 // Go circularly
1082 this->mIter = this->mEnd;
1083 else
1084 --this->mIter.first;
1085 } while (this->mIter != this->mEnd && !this->valid() );
1086 return *this;
1087 }
1088
1091 {
1092 TrackIter result { *this };
1093 this->operator -- ();
1094 return result;
1095 }
1096
1098
1099 TrackType *operator * () const
1100 {
1101 if (this->mIter == this->mEnd)
1102 return nullptr;
1103 else
1104 // Other methods guarantee that the cast is correct
1105 // (provided no operations on the TrackList invalidated
1106 // underlying iterators or replaced the tracks there)
1107 return static_cast< TrackType * >( &**this->mIter.first );
1108 }
1109
1112 long amount
1113 ) const
1114 {
1115 auto copy = *this;
1116 std::advance( copy, amount );
1117 return copy;
1118 }
1119
1121 friend inline bool operator == (TrackIter a, TrackIter b)
1122 {
1123 // Assume the predicate is not stateful. Just compare the iterators.
1124 return
1125 a.mIter == b.mIter
1126 // Assume this too:
1127 // && a.mBegin == b.mBegin && a.mEnd == b.mEnd
1128 ;
1129 }
1130
1132 friend inline bool operator != (TrackIter a, TrackIter b)
1133 {
1134 return !(a == b);
1135 }
1136
1137private:
1143 bool valid() const
1144 {
1145 // assume mIter != mEnd
1146 const auto pTrack = track_cast< TrackType * >( &**this->mIter.first );
1147 if (!pTrack)
1148 return false;
1149 return !this->mPred || this->mPred( pTrack );
1150 }
1151
1154
1160};
1161
1163template <
1164 typename TrackType // Track or a subclass, maybe const-qualified
1166 : public IteratorRange< TrackIter< TrackType > >
1167{
1171 : IteratorRange< TrackIter< TrackType > >
1172 ( begin, end )
1173 {}
1174
1175 // Conjoin the filter predicate with another predicate
1176 // Read + as "and"
1177 template< typename Predicate2 >
1178 TrackIterRange operator + ( const Predicate2 &pred2 ) const
1179 {
1180 const auto &pred1 = this->first.GetPredicate();
1181 using Function = typename TrackIter<TrackType>::FunctionType;
1182 const auto &newPred = pred1
1183 ? Function{ [=] (typename Function::argument_type track) {
1184 return pred1(track) && pred2(track);
1185 } }
1186 : Function{ pred2 };
1187 return {
1188 this->first.Filter( newPred ),
1189 this->second.Filter( newPred )
1190 };
1191 }
1192
1193 // Specify the added conjunct as a pointer to member function
1194 // Read + as "and"
1195 template< typename R, typename C >
1196 TrackIterRange operator + ( R ( C ::* pmf ) () const ) const
1197 {
1198 return this->operator + ( std::mem_fn( pmf ) );
1199 }
1200
1201 // Conjoin the filter predicate with the negation of another predicate
1202 // Read - as "and not"
1203 template< typename Predicate2 >
1204 TrackIterRange operator - ( const Predicate2 &pred2 ) const
1205 {
1206 using ArgumentType =
1207 typename TrackIterRange::iterator::FunctionType::argument_type;
1208 auto neg = [=] (ArgumentType track) { return !pred2( track ); };
1209 return this->operator + ( neg );
1210 }
1211
1212 // Specify the negated conjunct as a pointer to member function
1213 // Read - as "and not"
1214 template< typename R, typename C >
1215 TrackIterRange operator - ( R ( C ::* pmf ) () const ) const
1216 {
1217 return this->operator + ( std::not1( std::mem_fn( pmf ) ) );
1218 }
1219
1220 template< typename TrackType2 >
1222 {
1223 return {
1224 this-> first.template Filter< TrackType2 >(),
1225 this->second.template Filter< TrackType2 >()
1226 };
1227 }
1228
1229 TrackIterRange StartingWith( const Track *pTrack ) const
1230 {
1231 auto newBegin = this->find( pTrack );
1232 // More careful construction is needed so that the independent
1233 // increment and decrement of each iterator in the NEW pair
1234 // has the expected behavior at boundaries of the range
1235 return {
1236 { newBegin.mIter, newBegin.mIter, this->second.mEnd,
1237 this->first.GetPredicate() },
1238 { newBegin.mIter, this->second.mIter, this->second.mEnd,
1239 this->second.GetPredicate() }
1240 };
1241 }
1242
1243 TrackIterRange EndingAfter( const Track *pTrack ) const
1244 {
1245 const auto newEnd = this->reversal().find( pTrack ).base();
1246 // More careful construction is needed so that the independent
1247 // increment and decrement of each iterator in the NEW pair
1248 // has the expected behavior at boundaries of the range
1249 return {
1250 { this->first.mBegin, this->first.mIter, newEnd.mIter,
1251 this->first.GetPredicate() },
1252 { this->first.mBegin, newEnd.mIter, newEnd.mIter,
1253 this->second.GetPredicate() }
1254 };
1255 }
1256
1257 // Exclude one given track
1258 TrackIterRange Excluding ( const TrackType *pExcluded ) const
1259 {
1260 return this->operator - (
1261 [=](const Track *pTrack){ return pExcluded == pTrack; } );
1262 }
1263
1265 template< typename ...Functions >
1266 void Visit(const Functions &...functions)
1267 {
1268 for (auto track : *this)
1269 track->TypeSwitch(functions...);
1270 }
1271
1273
1274 template< typename Flag, typename ...Functions >
1275 void VisitWhile(Flag &flag, const Functions &...functions)
1276 {
1277 if ( flag ) for (auto track : *this) {
1278 track->TypeSwitch(functions...);
1279 if (!flag)
1280 break;
1281 }
1282 }
1283};
1284
1285
1288{
1289 enum Type {
1292
1295
1298
1300
1302
1305
1308
1310
1314 };
1315
1317 const std::weak_ptr<Track> &pTrack = {}, int extra = -1)
1318 : mType{ type }
1319 , mpTrack{ pTrack }
1320 , mExtra{ extra }
1321 {}
1322
1323 TrackListEvent( const TrackListEvent& ) = default;
1324
1326 const std::weak_ptr<Track> mpTrack;
1327 const int mExtra;
1328};
1329
1333class TRACK_API TrackList final
1334 : public Observer::Publisher<TrackListEvent>
1335 , public ListOfTracks
1336 , public std::enable_shared_from_this<TrackList>
1337 , public ClientData::Base
1338{
1339 // privatize this, make you use Add instead:
1340 using ListOfTracks::push_back;
1341
1342 // privatize this, make you use Swap instead:
1343 using ListOfTracks::swap;
1344
1345 // Disallow copy
1346 TrackList(const TrackList &that) = delete;
1347 TrackList &operator= (const TrackList&) = delete;
1348
1349 // No need for move, disallow it
1350 TrackList(TrackList &&that) = delete;
1351 TrackList& operator= (TrackList&&) = delete;
1352
1353 void clear() = delete;
1354
1355 public:
1356 static TrackList &Get( AudacityProject &project );
1357 static const TrackList &Get( const AudacityProject &project );
1358
1359 // Create an empty TrackList
1360 // Don't call directly -- use Create() instead
1361 explicit TrackList( AudacityProject *pOwner );
1362
1363 // Create an empty TrackList
1364 static std::shared_ptr<TrackList> Create( AudacityProject *pOwner );
1365
1366 // Move is defined in terms of Swap
1367 void Swap(TrackList &that);
1368
1369 // Destructor
1370 virtual ~TrackList();
1371
1372 // Find the owning project, which may be null
1373 AudacityProject *GetOwner() { return mOwner; }
1374 const AudacityProject *GetOwner() const { return mOwner; }
1375
1382 wxString MakeUniqueTrackName(const wxString& baseTrackName) const;
1383
1384 // Iteration
1385
1386 // Hide the inherited begin() and end()
1390 iterator begin() { return Any().begin(); }
1391 iterator end() { return Any().end(); }
1392 const_iterator begin() const { return Any().begin(); }
1393 const_iterator end() const { return Any().end(); }
1394 const_iterator cbegin() const { return begin(); }
1395 const_iterator cend() const { return end(); }
1396
1398 template < typename TrackType = Track >
1399 auto Find(Track *pTrack)
1401 {
1402 if (!pTrack || pTrack->GetOwner().get() != this)
1403 return EndIterator<TrackType>();
1404 else
1405 return MakeTrackIterator<TrackType>( pTrack->GetNode() );
1406 }
1407
1409
1410 template < typename TrackType = const Track >
1411 auto Find(const Track *pTrack) const
1412 -> std::enable_if_t< std::is_const_v<TrackType>,
1414 >
1415 {
1416 if (!pTrack || pTrack->GetOwner().get() != this)
1417 return EndIterator<TrackType>();
1418 else
1419 return MakeTrackIterator<TrackType>( pTrack->GetNode() );
1420 }
1421
1422 // If the track is not an audio track, or not one of a group of channels,
1423 // return the track itself; else return the first channel of its group --
1424 // in either case as an iterator that will only visit other leader tracks.
1425 // (Generalizing away from the assumption of at most stereo)
1426 TrackIter< Track > FindLeader( Track *pTrack );
1427
1429 FindLeader( const Track *pTrack ) const
1430 {
1431 return const_cast<TrackList*>(this)->
1432 FindLeader( const_cast<Track*>(pTrack) ).Filter< const Track >();
1433 }
1434
1435
1436 template < typename TrackType = Track >
1437 auto Any()
1439 {
1440 return Tracks< TrackType >();
1441 }
1442
1443 template < typename TrackType = const Track >
1444 auto Any() const
1445 -> std::enable_if_t< std::is_const_v<TrackType>,
1446 TrackIterRange< TrackType >
1447 >
1448 {
1449 return Tracks< TrackType >();
1450 }
1451
1452 // Abbreviating some frequently used cases
1453 template < typename TrackType = Track >
1456 {
1457 return Tracks< TrackType >( &Track::IsSelected );
1458 }
1459
1460 template < typename TrackType = const Track >
1461 auto Selected() const
1462 -> std::enable_if_t< std::is_const_v<TrackType>,
1463 TrackIterRange< TrackType >
1464 >
1465 {
1466 return Tracks< TrackType >( &Track::IsSelected );
1467 }
1468
1469
1470 template < typename TrackType = Track >
1471 auto Leaders()
1473 {
1474 return Tracks< TrackType >( &Track::IsLeader );
1475 }
1476
1477 template < typename TrackType = const Track >
1478 auto Leaders() const
1479 -> std::enable_if_t< std::is_const_v<TrackType>,
1480 TrackIterRange< TrackType >
1481 >
1482 {
1483 return Tracks< TrackType >( &Track::IsLeader );
1484 }
1485
1486
1487 template < typename TrackType = Track >
1490 {
1491 return Tracks< TrackType >( &Track::IsSelectedLeader );
1492 }
1493
1494 template < typename TrackType = const Track >
1495 auto SelectedLeaders() const
1496 -> std::enable_if_t< std::is_const_v<TrackType>,
1497 TrackIterRange< TrackType >
1498 >
1499 {
1500 return Tracks< TrackType >( &Track::IsSelectedLeader );
1501 }
1502
1503
1504 template<typename TrackType>
1505 static auto SingletonRange( TrackType *pTrack )
1507 {
1508 return pTrack->GetOwner()->template Any<TrackType>()
1509 .StartingWith( pTrack ).EndingAfter( pTrack );
1510 }
1511
1512
1513private:
1514 Track *DoAddToHead(const std::shared_ptr<Track> &t);
1515 Track *DoAdd(const std::shared_ptr<Track> &t);
1516
1517 template< typename TrackType, typename InTrackType >
1520 {
1521 // Assume iterator filters leader tracks
1522 if (*iter1) {
1523 return {
1524 iter1.Filter( &Track::Any )
1525 .template Filter<TrackType>(),
1526 (++iter1).Filter( &Track::Any )
1527 .template Filter<TrackType>()
1528 };
1529 }
1530 else
1531 // empty range
1532 return {
1533 iter1.template Filter<TrackType>(),
1534 iter1.template Filter<TrackType>()
1535 };
1536 }
1537
1538public:
1539 // Find an iterator range of channels including the given track.
1540 template< typename TrackType >
1541 static auto Channels( TrackType *pTrack )
1543 {
1544 return Channels_<TrackType>( pTrack->GetOwner()->FindLeader(pTrack) );
1545 }
1546
1548
1549 static bool SwapChannels(Track &track);
1550
1551 friend class Track;
1552
1554 void Permute(const std::vector<TrackNodePointer> &permutation);
1555
1556 Track *FindById( TrackId id );
1557
1559 template<typename TrackKind>
1560 TrackKind *AddToHead( const std::shared_ptr< TrackKind > &t )
1561 { return static_cast< TrackKind* >( DoAddToHead( t ) ); }
1562
1563 template<typename TrackKind>
1564 TrackKind *Add( const std::shared_ptr< TrackKind > &t )
1565 { return static_cast< TrackKind* >( DoAdd( t ) ); }
1566
1568 void UnlinkChannels(Track& track);
1577 bool MakeMultiChannelTrack(Track& first, int nChannels, bool aligned);
1578
1581 ListOfTracks::value_type Replace(
1582 Track * t, const ListOfTracks::value_type &with);
1583
1586
1588 void Clear(bool sendEvent = true);
1589
1590 bool CanMoveUp(Track * t) const;
1591 bool CanMoveDown(Track * t) const;
1592
1593 bool MoveUp(Track * t);
1594 bool MoveDown(Track * t);
1595 bool Move(Track * t, bool up) { return up ? MoveUp(t) : MoveDown(t); }
1596
1598 bool Contains(const Track * t) const;
1599
1600 // Return non-null only if the weak pointer is not, and the track is
1601 // owned by this list; constant time.
1602 template <typename Subclass>
1603 std::shared_ptr<Subclass> Lock(const std::weak_ptr<Subclass> &wTrack)
1604 {
1605 auto pTrack = wTrack.lock();
1606 if (pTrack) {
1607 auto pList = pTrack->mList.lock();
1608 if (pTrack && this == pList.get())
1609 return pTrack;
1610 }
1611 return {};
1612 }
1613
1614 bool empty() const;
1615 size_t size() const;
1616
1617 double GetStartTime() const;
1618 double GetEndTime() const;
1619
1620 double GetMinOffset() const;
1621
1622private:
1623
1624 // Visit all tracks satisfying a predicate, mutative access
1625 template <
1626 typename TrackType = Track,
1627 typename Pred =
1629 >
1630 auto Tracks( const Pred &pred = {} )
1632 {
1633 auto b = getBegin(), e = getEnd();
1634 return { { b, b, e, pred }, { b, e, e, pred } };
1635 }
1636
1637 // Visit all tracks satisfying a predicate, const access
1638 template <
1639 typename TrackType = const Track,
1640 typename Pred =
1642 >
1643 auto Tracks( const Pred &pred = {} ) const
1644 -> std::enable_if_t< std::is_const_v<TrackType>,
1646 >
1647 {
1648 auto b = const_cast<TrackList*>(this)->getBegin();
1649 auto e = const_cast<TrackList*>(this)->getEnd();
1650 return { { b, b, e, pred }, { b, e, e, pred } };
1651 }
1652
1653 Track *GetPrev(Track * t, bool linked = false) const;
1654 Track *GetNext(Track * t, bool linked = false) const;
1655
1656 template < typename TrackType >
1659 {
1660 auto b = const_cast<TrackList*>(this)->getBegin();
1661 auto e = const_cast<TrackList*>(this)->getEnd();
1662 return { b, iter, e };
1663 }
1664
1665 template < typename TrackType >
1668 {
1669 auto e = const_cast<TrackList*>(this)->getEnd();
1670 return { e, e, e };
1671 }
1672
1673 TrackIterRange< Track > EmptyRange() const;
1674
1676 { return (p.second == this && p.first == ListOfTracks::end())
1677 || (p.second == &mPendingUpdates && p.first == mPendingUpdates.end()); }
1679 { return { const_cast<TrackList*>(this)->ListOfTracks::end(),
1680 const_cast<TrackList*>(this)}; }
1682 { return { const_cast<TrackList*>(this)->ListOfTracks::begin(),
1683 const_cast<TrackList*>(this)}; }
1684
1687 {
1688 if ( isNull(p) )
1689 return p;
1690 auto q = p;
1691 ++q.first;
1692 return q;
1693 }
1694
1697 {
1698 if (p == getBegin())
1699 return getEnd();
1700 else {
1701 auto q = p;
1702 --q.first;
1703 return q;
1704 }
1705 }
1706
1707 void RecalcPositions(TrackNodePointer node);
1708 void QueueEvent(TrackListEvent event);
1709 void SelectionEvent( const std::shared_ptr<Track> &pTrack );
1710 void PermutationEvent(TrackNodePointer node);
1711 void DataEvent( const std::shared_ptr<Track> &pTrack, int code );
1712 void EnsureVisibleEvent(
1713 const std::shared_ptr<Track> &pTrack, bool modifyState );
1714 void DeletionEvent(std::weak_ptr<Track> node, bool duringReplace);
1715 void AdditionEvent(TrackNodePointer node);
1716 void ResizingEvent(TrackNodePointer node);
1717
1718 void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);
1719
1720 // Nondecreasing during the session.
1721 // Nonpersistent.
1722 // Used to assign ids to added tracks.
1723 static long sCounter;
1724
1725public:
1726 using Updater = std::function< void(Track &dest, const Track &src) >;
1727 // Start a deferred update of the project.
1728 // The return value is a duplicate of the given track.
1729 // While ApplyPendingTracks or ClearPendingTracks is not yet called,
1730 // there may be other direct changes to the project that push undo history.
1731 // Meanwhile the returned object can accumulate other changes for a deferred
1732 // push, and temporarily shadow the actual project track for display purposes.
1733 // The Updater function, if not null, merges state (from the actual project
1734 // into the pending track) which is not meant to be overridden by the
1735 // accumulated pending changes.
1736 // To keep the display consistent, the Y and Height values, minimized state,
1737 // and Linked state must be copied, and this will be done even if the
1738 // Updater does not do it.
1739 // Pending track will have the same TrackId as the actual.
1740 // Pending changed tracks will not occur in iterations.
1741 std::shared_ptr<Track> RegisterPendingChangedTrack(
1742 Updater updater,
1743 Track *src
1744 );
1745
1746 // Like the previous, but for a NEW track, not a replacement track. Caller
1747 // supplies the track, and there are no updates.
1748 // Pending track will have an unassigned TrackId.
1749 // Pending changed tracks WILL occur in iterations, always after actual
1750 // tracks, and in the sequence that they were added. They can be
1751 // distinguished from actual tracks by TrackId.
1752 void RegisterPendingNewTrack( const std::shared_ptr<Track> &pTrack );
1753
1754 // Invoke the updaters of pending tracks. Pass any exceptions from the
1755 // updater functions.
1756 void UpdatePendingTracks();
1757
1758 // Forget pending track additions and changes;
1759 // if requested, give back the pending added tracks.
1760 void ClearPendingTracks( ListOfTracks *pAdded = nullptr );
1761
1762 // Change the state of the project.
1763 // Strong guarantee for project state in case of exceptions.
1764 // Will always clear the pending updates.
1765 // Return true if the state of the track list really did change.
1766 bool ApplyPendingTracks();
1767
1768 bool HasPendingTracks() const;
1769
1770private:
1772
1774
1777 std::vector< Updater > mUpdaters;
1778};
1779
1780#endif
Utility ClientData::Site to register hooks into a host class that attach client data.
std::vector< Track * > TrackArray
ClientData::Site< Track, TrackAttachment, ClientData::ShallowCopying, std::shared_ptr > AttachedTrackObjects
Template generated base class for Track lets it host opaque UI related objects.
Definition: Track.h:218
#define ENUMERATE_TRACK_TYPE(T)
This macro should be called immediately after each definition of a track subtype.
Definition: Track.h:125
bool operator==(const TrackNodePointer &a, const TrackNodePointer &b)
Definition: Track.h:50
bool operator!=(const TrackNodePointer &a, const TrackNodePointer &b)
Definition: Track.h:53
std::pair< ListOfTracks::iterator, ListOfTracks * > TrackNodePointer
Pairs a std::list iterator and a pointer to a list, for comparison purposes.
Definition: Track.h:48
std::list< std::shared_ptr< Track > > ListOfTracks
Definition: Track.h:42
std::enable_if_t< std::is_pointer_v< T >, T > track_cast(Track *track)
Encapsulate the checked down-casting of track pointers.
Definition: Track.h:965
abstract base class for structures that user interface associates with tracks
int id
static std::once_flag flag
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:89
Track subclass holding data representing sound (as notes, or samples, or ...)
Definition: Track.h:897
bool HandleXMLAttribute(const std::string_view &, const XMLAttributeValueView &)
Definition: Track.h:908
void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const
Definition: Track.h:905
Utility to register hooks into a host class that attach client data.
Definition: ClientData.h:220
A start and an end time, and non-mutative access to optional extra information.
Definition: Track.h:178
double start
Definition: Track.h:197
ConstTrackInterval(ConstTrackInterval &&)=default
std::unique_ptr< TrackIntervalData > pExtra
Definition: Track.h:200
ConstTrackInterval(double start, double end, std::unique_ptr< TrackIntervalData > pExtra={})
Definition: Track.h:182
const TrackIntervalData * Extra() const
Definition: Track.h:194
double Start() const
Definition: Track.h:192
ConstTrackInterval & operator=(ConstTrackInterval &&)=default
double End() const
Definition: Track.h:193
An object that sends messages to an open-ended list of subscribed callbacks.
Definition: Observer.h:108
AudioTrack subclass that can also be audibly replayed by the program.
Definition: Track.h:916
bool GetSolo() const
Definition: Track.h:924
bool GetNotMute() const
Definition: Track.h:925
bool GetNotSolo() const
Definition: Track.h:926
bool GetMute() const
Definition: Track.h:923
Holds various per-project settings values, and sends events to the project when certain values change...
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:225
static void checkTrackType()
Definition: Track.h:731
std::function< R() > Continuation
Type of arguments passed as optional second parameter to TypeSwitch() cases.
Definition: Track.h:539
bool GetSelected() const
Definition: Track.h:469
void Offset(double t)
Definition: Track.h:482
Track()
Definition: Track.cpp:44
virtual void SetPan(float)
Definition: Track.h:485
virtual void SetOffset(double o)
Definition: Track.h:483
static R DoTypeSwitch(std::conditional_t< IsConst, const Track, Track > &track, std::tuple< TrackTypes... > *, const Functions &...functions)
Definition: Track.h:784
bool SameKindAs(const Track &track) const
Definition: Track.h:534
static R CallExecutor(R *, std::tuple<> *, TrackType &, const Functions &...)
Definition: Track.h:738
virtual void Paste(double WXUNUSED(t), const Track *WXUNUSED(src))=0
virtual Holder Cut(double WXUNUSED(t0), double WXUNUSED(t1))=0
virtual Holder PasteInto(AudacityProject &) const =0
Find or create the destination track for a paste, maybe in a different project.
bool IsSelected() const
Definition: Track.cpp:402
virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1))=0
virtual const TypeInfo & GetTypeInfo() const =0
ChannelType
Definition: Track.h:281
virtual double GetStartTime() const =0
virtual Holder Clone() const =0
bool IsSelectedLeader() const
Definition: Track.cpp:410
virtual Holder Copy(double WXUNUSED(t0), double WXUNUSED(t1), bool forClipboard=true) const =0
static R CallExecutor(R *, std::tuple< Executor, Executors... > *, TrackType &track, const Functions &...functions)
Definition: Track.h:753
std::pair< int, int > vrulerSize
Definition: Track.h:386
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:409
bool mSelected
Definition: Track.h:273
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
Definition: Track.h:832
static std::shared_ptr< Subclass > SharedPointer(Track *pTrack)
Definition: Track.h:317
bool HasOwner() const
Definition: Track.h:407
virtual const TypeNames & GetTypeNames() const
Definition: Track.h:362
auto SharedPointer() const -> std::enable_if_t< std::is_const_v< Subclass >, std::shared_ptr< Subclass > >
Definition: Track.h:305
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:297
TrackId GetId() const
Definition: Track.h:287
std::shared_ptr< Track > Holder
Definition: Track.h:368
wxString mName
Definition: Track.h:270
void SetId(TrackId id)
Definition: Track.h:289
bool LinkConsistencyCheck(bool completeList)
Do the non-mutating part of consistency fix only and return status.
Definition: Track.h:404
virtual void SetPanFromChannelType()
Definition: Track.h:486
virtual void WriteXML(XMLWriter &xmlFile) const =0
R TypeSwitch(const Functions &...functions) const
Use this function rather than testing track type explicitly and making down-casts.
Definition: Track.h:849
virtual void Silence(double WXUNUSED(t0), double WXUNUSED(t1))=0
virtual ChannelType GetChannel() const
Definition: Track.h:479
Continuation<> Fallthrough
Type of arguments passed as optional second parameter to TypeSwitch<void>() cases.
Definition: Track.h:541
std::weak_ptr< TrackList > mList
Definition: Track.h:265
virtual double GetOffset() const =0
virtual double GetEndTime() const =0
std::vector< Interval > Intervals
Definition: Track.h:335
bool IsLeader() const
Definition: Track.cpp:405
virtual void InsertSilence(double WXUNUSED(t), double WXUNUSED(len))=0
static constexpr unsigned UsedCases(std::tuple< Executors... > *)
Definition: Track.h:772
LinkType
For two tracks describes the type of the linkage.
Definition: Track.h:236
virtual bool GetErrorOpening()
Definition: Track.h:864
int mIndex
0-based position of this track in its TrackList
Definition: Track.h:269
static std::shared_ptr< Subclass > SharedPointer(const Track *pTrack)
Definition: Track.h:321
std::unique_ptr< ChannelGroupData > mpGroupData
Definition: Track.h:262
std::vector< ConstInterval > ConstIntervals
Definition: Track.h:337
bool Any() const
Definition: Track.cpp:399
TrackId mId
Identifies the track only in-session, not persistently.
Definition: Track.h:260
An in-session identifier of track objects across undo states. It does not persist between sessions.
Definition: Track.h:151
bool operator!=(const TrackId &other) const
Definition: Track.h:159
TrackId()
Definition: Track.h:153
bool operator<(const TrackId &other) const
Definition: Track.h:164
TrackId(long value)
Definition: Track.h:154
long mValue
Definition: Track.h:168
bool operator==(const TrackId &other) const
Definition: Track.h:156
A start and an end time, and mutative access to optional extra information.
Definition: Track.h:205
TrackIntervalData * Extra() const
Definition: Track.h:212
TrackInterval(TrackInterval &&)=default
TrackInterval & operator=(TrackInterval &&)=default
Iterator over only members of a TrackList of the specified subtype, optionally filtered by a predicat...
Definition: Track.h:1006
const FunctionType & GetPredicate() const
Definition: Track.h:1052
TrackNodePointer mIter
Current position.
Definition: Track.h:1157
TrackType * operator*() const
Safe to call even when at the end.
Definition: Track.h:1099
TrackIter & operator--()
Safe to call even when at the beginning.
Definition: Track.h:1076
friend bool operator!=(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
Definition: Track.h:1132
auto Filter() const -> std::enable_if_t< std::is_base_of_v< TrackType, TrackType2 > &&(!std::is_const_v< TrackType >||std::is_const_v< TrackType2 >), TrackIter< TrackType2 > >
Return an iterator for a subclass of TrackType (and not removing const) with same predicate.
Definition: Track.h:1041
TrackNodePointer mBegin
Allows end of reverse iteration to be detected without comparison to other TrackIter.
Definition: Track.h:1156
friend bool operator==(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
Definition: Track.h:1121
TrackIter Filter(const Predicate2 &pred2) const
Return an iterator that replaces the predicate.
Definition: Track.h:1032
TrackIter & operator++()
Safe to call even when at the end.
Definition: Track.h:1057
std::function< bool(std::add_pointer_t< std::add_const_t< std::remove_pointer_t< TrackType > > >) > FunctionType
Type of predicate taking pointer to const TrackType.
Definition: Track.h:1011
TrackIter advance(long amount) const
This might be called operator + , but it's not constant-time as with a random access iterator.
Definition: Track.h:1111
FunctionType mPred
Optional filter
Definition: Track.h:1159
TrackIter(TrackNodePointer begin, TrackNodePointer iter, TrackNodePointer end, FunctionType pred={})
Constructor, usually not called directly except by methods of TrackList.
Definition: Track.h:1014
bool valid() const
Test satisfaction of the invariant, while initializing, incrementing, or decrementing.
Definition: Track.h:1143
TrackNodePointer mEnd
Allows end of iteration to be detected without comparison to other TrackIter.
Definition: Track.h:1158
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1338
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1603
static auto SingletonRange(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1505
auto Selected() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1461
AudacityProject * mOwner
Definition: Track.h:1771
static long sCounter
Definition: Track.h:1723
bool Move(Track *t, bool up)
Definition: Track.h:1595
const_iterator begin() const
Definition: Track.h:1392
auto Find(const Track *pTrack) const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIter< TrackType > >
Turn a pointer into a TrackIter (constant time); get end iterator if this does not own the track.
Definition: Track.h:1411
auto SelectedLeaders() -> TrackIterRange< TrackType >
Definition: Track.h:1488
std::vector< Updater > mUpdaters
This is in correspondence with mPendingUpdates.
Definition: Track.h:1777
TrackNodePointer getBegin() const
Definition: Track.h:1681
iterator end()
Definition: Track.h:1391
auto Tracks(const Pred &pred={}) const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1643
TrackIter< const Track > FindLeader(const Track *pTrack) const
Definition: Track.h:1429
auto Leaders() -> TrackIterRange< TrackType >
Definition: Track.h:1471
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1564
auto Tracks(const Pred &pred={}) -> TrackIterRange< TrackType >
Definition: Track.h:1630
bool isNull(TrackNodePointer p) const
Definition: Track.h:1675
TrackNodePointer getNext(TrackNodePointer p) const
Move an iterator to the next node, if any; else stay at end.
Definition: Track.h:1686
auto Find(Track *pTrack) -> TrackIter< TrackType >
Turn a pointer into a TrackIter (constant time); get end iterator if this does not own the track.
Definition: Track.h:1399
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1437
TrackNodePointer getEnd() const
Definition: Track.h:1678
std::function< void(Track &dest, const Track &src) > Updater
Definition: Track.h:1726
TrackIter< TrackType > EndIterator() const
Definition: Track.h:1667
auto Any() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1444
auto Leaders() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1478
static TrackIterRange< TrackType > Channels_(TrackIter< InTrackType > iter1)
Definition: Track.h:1519
void clear()=delete
const AudacityProject * GetOwner() const
Definition: Track.h:1374
iterator begin()
Definition: Track.h:1390
const_iterator cend() const
Definition: Track.h:1395
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1454
const_iterator cbegin() const
Definition: Track.h:1394
AudacityProject * GetOwner()
Definition: Track.h:1373
TrackIter< TrackType > MakeTrackIterator(TrackNodePointer iter) const
Definition: Track.h:1658
TrackList(const TrackList &that)=delete
TrackList(TrackList &&that)=delete
TrackNodePointer getPrev(TrackNodePointer p) const
Move an iterator to the previous node, if any; else wrap to end.
Definition: Track.h:1696
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1541
ListOfTracks mPendingUpdates
Shadow tracks holding append-recording in progress; need to put them into a list so that GetLink() wo...
Definition: Track.h:1775
TrackKind * AddToHead(const std::shared_ptr< TrackKind > &t)
Add a Track, giving it a fresh id.
Definition: Track.h:1560
const_iterator end() const
Definition: Track.h:1393
auto SelectedLeaders() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1495
Holds a msgid for the translation catalog; may also bind format arguments.
A view into an attribute value. The class does not take the ownership of the data.
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:42
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:26
Embedded type member is the tuple of track types so far declared in the compilation unit.
Definition: Track.h:97
typename Accumulate< 0 >::type type
Definition: Track.h:111
Embedded value member counts track types so far declared in the compilation unit.
Definition: Track.h:76
void Remove(const FilePath &path)
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:194
@ ShallowCopying
copy pointers only; won't compile for std::unique_ptr
@ DeepCopying
point to new sub-objects; these must define a Clone() member; won't compile for std::weak_ptr
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150
void FinishCopy(const Track *n, const Track::Holder &dest, TrackList &list)
Definition: EditMenus.cpp:35
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:753
void Notify(AudacityProject &project, ProjectSettings::EventCode code, long previousValue)
auto enumerateTrackTypes(TrackTypeCountTag,...) -> void
std::remove_reference_t< decltype(enumerateTrackTypes(Tag{}, std::integral_constant< unsigned, U >{})) > EnumeratedTrackType
What type is associated with U (at the point of instantiation for Tag)?
Definition: Track.h:69
STL namespace.
A convenient default parameter for class template Site.
Definition: ClientData.h:28
A convenient base class defining abstract virtual Clone() for a given kind of pointer.
Definition: ClientData.h:48
A convenience for use with range-for.
Definition: MemoryX.h:260
iterator find(const T &t) const
Definition: MemoryX.h:283
IteratorRange< reverse_iterator > reversal() const
Definition: MemoryX.h:270
TrackIter< TrackType > end() const
Definition: MemoryX.h:274
TrackIter< TrackType > begin() const
Definition: MemoryX.h:273
static auto test() -> inapplicable< Tag, R, ArgumentType, Function, Functions... >
No BaseClass of ArgumentType is acceptable to Function.
std::conditional_t< std::is_const_v< ArgumentType >, const BaseClass, BaseClass > QualifiedBaseClass
Definition: Track.h:646
static auto test(const void *) -> decltype(Retry::template test< Function, Functions... >())
Catch-all overload of undefined function used in decltype only.
static auto test(std::true_type *) -> decltype((void) std::declval< Function >()((QualifiedBaseClass *) nullptr), applicable1< R, BaseClass, ArgumentType, Function >{})
overload when upcast of ArgumentType* works, with sfinae'd return type
static auto test() -> decltype(test< Function, Functions... >((std::integral_constant< bool, Compatible > *) nullptr))
undefined function used in decltype only to compute a type, using other overloads
static auto test(std::true_type *) -> decltype((void) std::declval< Function >()((QualifiedBaseClass *) nullptr, std::declval< Continuation< R > >()), applicable2< Tag, R, BaseClass, ArgumentType, Function, Functions... >{})
overload when upcast of ArgumentType* works, with sfinae'd return type
Variadic template implements metafunction with specializations, to choose among implementations of op...
Definition: Track.h:625
Second, nonrecursive case of metafunction, generates operator () that calls function without fallthro...
Definition: Track.h:576
std::conditional_t< std::is_const_v< ArgumentType >, const BaseClass, BaseClass > QualifiedBaseClass
Definition: Track.h:582
std::conditional_t< std::is_const_v< ArgumentType >, const Track, Track > QualifiedTrackType
Definition: Track.h:579
Third, recursive case of metafunction, generates operator () that calls function with fallthrough.
Definition: Track.h:598
std::conditional_t< std::is_const_v< ArgumentType >, const Track, Track > QualifiedTrackType
Definition: Track.h:601
std::conditional_t< std::is_const_v< ArgumentType >, const BaseClass, BaseClass > QualifiedBaseClass
Definition: Track.h:604
First, recursive case of metafunction, defers generation of operator ()
Definition: Track.h:555
std::conditional_t< std::is_const_v< ArgumentType >, const Track, Track > QualifiedTrackType
Definition: Track.h:558
Helper for recursive case of metafunction implementing Track::TypeSwitch.
Definition: Track.h:550
Variadic template implements metafunction with specializations, to dispatch Track::TypeSwitch.
Definition: Track.h:546
Empty argument passed to some public constructors.
Definition: Track.h:232
TypeNames names
Definition: Track.h:347
bool IsBaseOf(const TypeInfo &other) const
Definition: Track.h:351
const TypeInfo * pBaseInfo
Definition: Track.h:349
Names of a track type for various purposes.
Definition: Track.h:341
wxString info
short, like "wave", in macro output, not internationalized
Definition: Track.h:342
TranslatableString name
long, like "Wave Track"
Definition: Track.h:344
wxString property
short, like "wave", as a Lisp symbol property, not internationalized
Definition: Track.h:343
Optional extra information about an interval, appropriate to a subtype of Track.
Definition: Track.h:172
virtual ~TrackIntervalData()
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
Definition: Track.h:1167
TrackIterRange EndingAfter(const Track *pTrack) const
Definition: Track.h:1243
void VisitWhile(Flag &flag, const Functions &...functions)
See Track::TypeSwitch.
Definition: Track.h:1275
TrackIterRange operator+(const Predicate2 &pred2) const
Definition: Track.h:1178
TrackIterRange(const TrackIter< TrackType > &begin, const TrackIter< TrackType > &end)
Definition: Track.h:1169
void Visit(const Functions &...functions)
See Track::TypeSwitch.
Definition: Track.h:1266
TrackIterRange< TrackType2 > Filter() const
Definition: Track.h:1221
TrackIterRange Excluding(const TrackType *pExcluded) const
Definition: Track.h:1258
TrackIterRange operator-(const Predicate2 &pred2) const
Definition: Track.h:1204
TrackIterRange StartingWith(const Track *pTrack) const
Definition: Track.h:1229
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
Definition: Track.h:1288
TrackListEvent(const TrackListEvent &)=default
const int mExtra
Definition: Track.h:1327
const std::weak_ptr< Track > mpTrack
Definition: Track.h:1326
const Type mType
Definition: Track.h:1325
@ RESIZING
Posted when some track changed its height.
Definition: Track.h:1304
@ SELECTION_CHANGE
Posted when the set of selected tracks changes.
Definition: Track.h:1291
@ DELETION
Posted when a track has been deleted from a tracklist. Also posted when one track replaces another.
Definition: Track.h:1313
@ ADDITION
Posted when a track has been added to a tracklist. Also posted when one track replaces another.
Definition: Track.h:1307
@ PERMUTED
Posted when tracks are reordered but otherwise unchanged.
Definition: Track.h:1301
@ TRACK_REQUEST_VISIBLE
Posted when a track needs to be scrolled into view.
Definition: Track.h:1297
@ TRACK_DATA_CHANGE
Posted when certain fields of a track change.
Definition: Track.h:1294
TrackListEvent(Type type, const std::weak_ptr< Track > &pTrack={}, int extra=-1)
Definition: Track.h:1316
A convenience for defining iterators that return rvalue types, so that they cooperate correctly with ...
Definition: MemoryX.h:246
Empty class which will have subclasses.
Definition: Track.h:59
Implements the ENUMERATE_TRACK_TYPE macro.
Definition: Track.h:116