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{
226public:
227
229 enum class LinkType : int {
230 None = 0, //< No linkage
231 Group = 2, //< Tracks are grouped together
232 Aligned, //< Tracks are grouped and changes should be synchronized
233 };
234
235 struct ChannelGroupData;
236
240 >;
241
242 // Structure describing data common to channels of a group of tracks
243 // Should be deep-copyable (think twice before adding shared pointers!)
245 LinkType mLinkType{ LinkType::None };
246 };
247
248private:
249
250 friend class TrackList;
251
252 private:
254
255 std::unique_ptr<ChannelGroupData> mpGroupData;
256
257 protected:
258 std::weak_ptr<TrackList> mList;
260
262 int mIndex;
263 wxString mName;
264
265 private:
267
268 public:
269
272
274 {
275 LeftChannel = 0,
276 RightChannel = 1,
277 MonoChannel = 2
278 };
279
280 TrackId GetId() const { return mId; }
281 private:
282 void SetId( TrackId id ) { mId = id; }
283 public:
284
285 // Given a bare pointer, find a shared_ptr. Undefined results if the track
286 // is not yet managed by a shared_ptr. Undefined results if the track is
287 // not really of the subclass. (That is, trusts the caller and uses static
288 // not dynamic casting.)
289 template<typename Subclass = Track>
290 inline std::shared_ptr<Subclass> SharedPointer()
291 {
292 // shared_from_this is injected into class scope by base class
293 // std::enable_shared_from_this<Track>
294 return std::static_pointer_cast<Subclass>( shared_from_this() );
295 }
296
297 template<typename Subclass = const Track>
298 inline auto SharedPointer() const ->
299 std::enable_if_t<
300 std::is_const_v<Subclass>, std::shared_ptr<Subclass>
301 >
302 {
303 // shared_from_this is injected into class scope by base class
304 // std::enable_shared_from_this<Track>
305 return std::static_pointer_cast<Subclass>( shared_from_this() );
306 }
307
308 // Static overloads of SharedPointer for when the pointer may be null
309 template<typename Subclass = Track>
310 static inline std::shared_ptr<Subclass> SharedPointer( Track *pTrack )
311 { return pTrack ? pTrack->SharedPointer<Subclass>() : nullptr; }
312
313 template<typename Subclass = const Track>
314 static inline std::shared_ptr<Subclass> SharedPointer( const Track *pTrack )
315 { return pTrack ? pTrack->SharedPointer<Subclass>() : nullptr; }
316
317 // Find anything registered with TrackList::RegisterPendingChangedTrack and
318 // not yet cleared or applied; if no such exists, return this track
319 std::shared_ptr<Track> SubstitutePendingChangedTrack();
320 std::shared_ptr<const Track> SubstitutePendingChangedTrack() const;
321
322 // If this track is a pending changed track, return the corresponding
323 // original; else return this track
324 std::shared_ptr<const Track> SubstituteOriginalTrack() const;
325
328 using Intervals = std::vector< Interval >;
330 using ConstIntervals = std::vector< ConstInterval >;
331
333
334 struct TypeNames {
335 wxString info;
336 wxString property;
338 };
339 struct TypeInfo {
341 bool concrete = false;
342 const TypeInfo *pBaseInfo = nullptr;
343
344 bool IsBaseOf(const TypeInfo &other) const
345 {
346 for (auto pInfo = &other;
347 pInfo; pInfo = pInfo->pBaseInfo)
348 if (this == pInfo)
349 return true;
350 return false;
351 }
352 };
353 virtual const TypeInfo &GetTypeInfo() const = 0;
354 static const TypeInfo &ClassTypeInfo();
355 virtual const TypeNames &GetTypeNames() const
356 { return GetTypeInfo().names; }
357
359 virtual bool SupportsBasicEditing() const;
360
361 using Holder = std::shared_ptr<Track>;
362
364
365 virtual Holder PasteInto( AudacityProject & ) const = 0;
366
368
371 virtual ConstIntervals GetIntervals() const;
372
376 virtual Intervals GetIntervals();
377
378 public:
379 mutable std::pair<int, int> vrulerSize;
380
381 int GetIndex() const;
382 void SetIndex(int index);
383
384public:
385 static void FinishCopy (const Track *n, Track *dest);
386
388
394 virtual bool LinkConsistencyFix(bool doFix = true, bool completeList = true);
395
397 bool LinkConsistencyCheck(bool completeList)
398 { return const_cast<Track*>(this)->LinkConsistencyFix(false, completeList); }
399
400 bool HasOwner() const { return static_cast<bool>(GetOwner());}
401
402 std::shared_ptr<TrackList> GetOwner() const { return mList.lock(); }
403
404 LinkType GetLinkType() const noexcept;
406 bool IsAlignedWithLeader() const;
407
408 ChannelGroupData &GetGroupData();
409 const ChannelGroupData &GetGroupData() const;
410
411protected:
412
416 void SetLinkType(LinkType linkType, bool completeList = true);
417 void SetChannel(ChannelType c) noexcept;
418
419private:
420 ChannelGroupData &MakeGroupData();
424 void DoSetLinkType(LinkType linkType, bool completeList = true);
425
426 Track* GetLinkedTrack() const;
428 bool HasLinkedTrack() const noexcept;
429
431 TrackNodePointer GetNode() const;
433 void SetOwner
434 (const std::weak_ptr<TrackList> &list, TrackNodePointer node);
435
436 // Keep in Track
437
438 protected:
439 ChannelType mChannel;
440 double mOffset;
441
442 public:
443
444 Track();
445 Track(const Track &orig);
446
447 virtual ~ Track();
448
449 void Init(const Track &orig);
450
451 // public nonvirtual duplication function that invokes Clone():
452 virtual Holder Duplicate() const;
453
454 // Called when this track is merged to stereo with another, and should
455 // take on some parameters of its partner.
456 virtual void Merge(const Track &orig);
457
458 wxString GetName() const { return mName; }
459 void SetName( const wxString &n );
460
461 bool GetSelected() const { return mSelected; }
462
463 virtual void SetSelected(bool s);
464
465 // The argument tells whether the last undo history state should be
466 // updated for the appearance change
467 void EnsureVisible( bool modifyState = false );
468
469public:
470
471 virtual ChannelType GetChannel() const { return mChannel;}
472 virtual double GetOffset() const = 0;
473
474 void Offset(double t) { SetOffset(GetOffset() + t); }
475 virtual void SetOffset (double o) { mOffset = o; }
476
477 virtual void SetPan( float ){ ;}
478 virtual void SetPanFromChannelType(){ ;};
479
480 // Create a NEW track and modify this track
481 // Return non-NULL or else throw
482 // May assume precondition: t0 <= t1
483 virtual Holder Cut(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
484
485 // Create a NEW track and don't modify this track
486 // Return non-NULL or else throw
487 // Note that subclasses may want to distinguish tracks stored in a clipboard
488 // from those stored in a project
489 // May assume precondition: t0 <= t1
490 // Should invoke Track::Init
491 virtual Holder Copy
492 (double WXUNUSED(t0), double WXUNUSED(t1), bool forClipboard = true) const = 0;
493
494 // May assume precondition: t0 <= t1
495 virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
496
497 virtual void Paste(double WXUNUSED(t), const Track * WXUNUSED(src)) = 0;
498
499 // This can be used to adjust a sync-lock selected track when the selection
500 // is replaced by one of a different length.
501 virtual void SyncLockAdjust(double oldT1, double newT1);
502
503 // May assume precondition: t0 <= t1
504 virtual void Silence(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
505
506 // May assume precondition: t0 <= t1
507 virtual void InsertSilence(double WXUNUSED(t), double WXUNUSED(len)) = 0;
508
509private:
510 // Subclass responsibility implements only a part of Duplicate(), copying
511 // the track data proper (not associated data such as for groups and views):
512 virtual Holder Clone() const = 0;
513
514 template<typename T>
515 friend std::enable_if_t< std::is_pointer_v<T>, T >
516 track_cast(Track *track);
517 template<typename T>
518 friend std::enable_if_t<
519 std::is_pointer_v<T> &&
520 std::is_const_v< std::remove_pointer_t< T > >,
521 T
522 >
523 track_cast(const Track *track);
524
525public:
526 bool SameKindAs(const Track &track) const
527 { return &GetTypeInfo() == &track.GetTypeInfo(); }
528
530 template < typename R = void >
531 using Continuation = std::function< R() >;
534
535private:
537 template< typename ...Params >
538 struct Executor{};
539
541
542 struct Dispatcher {
544 template< typename Tag, typename R, typename ArgumentType,
545 typename Function, typename ...Functions >
547 {
549 std::conditional_t< std::is_const_v<ArgumentType>,
550 const Track, Track >;
551
553 using Tail = Executor< Tag, R, ArgumentType, Functions... >;
555 enum : unsigned { SetUsed = Tail::SetUsed << 1 };
556
558 R operator ()
559 (QualifiedTrackType *pTrack,
560 const Function &, const Functions &...functions) const
561 { return Tail{}( pTrack, functions... ); }
562 };
563
565 template< typename R, typename BaseClass, typename ArgumentType,
566 typename Function >
568 {
570 std::conditional_t< std::is_const_v<ArgumentType>,
571 const Track, Track >;
573 std::conditional_t< std::is_const_v<ArgumentType>,
574 const BaseClass, BaseClass >;
575
577 enum : unsigned { SetUsed = 1u };
578
580 R operator ()
581 (QualifiedTrackType *pTrack, const Function &function, ...) const
582 { return function( static_cast<QualifiedBaseClass *>(pTrack) ); }
583 };
584
586 template< typename Tag,
587 typename R, typename BaseClass, typename ArgumentType,
588 typename Function, typename ...Functions >
590 {
592 std::conditional_t< std::is_const_v<ArgumentType>,
593 const Track, Track >;
595 std::conditional_t< std::is_const_v<ArgumentType>,
596 const BaseClass, BaseClass >;
597
599 using Tail = Executor< Tag, R, ArgumentType, Functions... >;
601 enum : unsigned { SetUsed = (Tail::SetUsed << 1) | 1u };
602
604 R operator ()
605 (QualifiedTrackType *pTrack, const Function &function,
606 const Functions &...functions) const
607 {
608 auto continuation = Continuation<R>{ [&] {
609 return Tail{}( pTrack, functions... );
610 } };
611 return function( static_cast<QualifiedBaseClass *>(pTrack),
612 continuation );
613 }
614 };
615
617 template< typename ... > struct Switch {};
618
620
621 template< typename Tag, typename R, typename ArgumentType >
622 struct Switch< Tag, R, ArgumentType, std::tuple<> >
623 {
625 template< typename Function, typename ...Functions >
626 static auto test()
627 -> inapplicable< Tag, R, ArgumentType, Function, Functions... >;
628 };
629
631
632 template< typename Tag, typename R, typename ArgumentType,
633 typename BaseClass, typename ...BaseClasses >
634 struct Switch< Tag, R, ArgumentType, std::tuple<BaseClass, BaseClasses...> >
635 {
637 std::conditional_t< std::is_const_v<ArgumentType>,
638 const BaseClass, BaseClass >;
639
641 using Retry =
642 Switch< Tag, R, ArgumentType, std::tuple<BaseClasses...> >;
643
645
647 template< typename Function, typename ...Functions >
648 static auto test( const void * )
649 -> decltype( Retry::template test< Function, Functions... >() );
650
652
655 template< typename Function, typename ...Functions >
656 static auto test( std::true_type * )
657 -> decltype(
658 (void) std::declval<Function>()
659 ( (QualifiedBaseClass*)nullptr ),
661 );
662
664
668 template< typename Function, typename ...Functions >
669 static auto test( std::true_type * )
670 -> decltype(
671 (void) std::declval<Function>()
672 ( (QualifiedBaseClass*)nullptr,
673 std::declval< Continuation<R> >() ),
674 applicable2< Tag, R, BaseClass, ArgumentType,
675 Function, Functions... >{}
676 );
677
679 static constexpr bool Compatible =
680 std::is_base_of_v<BaseClass, ArgumentType>;
682 template< typename Function, typename ...Functions >
683 static auto test()
684 -> decltype(
685 test< Function, Functions... >(
686 (std::integral_constant<bool, Compatible>*)nullptr) );
687 };
688 };
689
691 template< typename Tag, typename R, typename ArgumentType >
692 struct Executor< Tag, R, ArgumentType >
693 {
694 using NominalType = ArgumentType;
696 enum : unsigned { SetUsed = 0 };
698 R operator () (const void *, ...)
699 {
700 if constexpr (std::is_void_v<R>)
701 return;
702 else
703 return R{};
704 }
705 };
706
708
709 template< typename Tag, typename R, typename ArgumentType,
710 typename Function, typename ...Functions >
711 struct Executor< Tag, R, ArgumentType, Function, Functions... >
712 : decltype(
713 Dispatcher::Switch< Tag, R, ArgumentType,
714 typename CollectTrackTypes<Tag>::type >
715 ::template test<Function, Functions... >())
716 {
717 using NominalType = ArgumentType;
718 };
719
720public:
721
722 template<typename TrackType>
723 static void checkTrackType()
724 {
725 static_assert(
726 std::is_same_v<Track, TrackType> ||
727 std::is_same_v<const Track, TrackType>, "Error" );
728 }
729 template<typename R, typename TrackType, typename... Functions>
730 static R CallExecutor(R*, std::tuple<>*, TrackType&, const Functions&...)
731 {
732 // This overload is needed so that the other overload of CallExecutor
733 // compiles, but it should never be reached at run-time, because an
734 // Executor generated for (const) Track should have been the catch-all.
735 wxASSERT(false);
736 checkTrackType<TrackType>();
737 if constexpr (std::is_void_v<R>)
738 return;
739 else
740 return R{};
741 }
742 template<
743 typename R, typename TrackType, typename... Functions,
744 typename Executor, typename... Executors>
745 static R CallExecutor(
746 R*, std::tuple<Executor, Executors...>*, TrackType &track,
747 const Functions &...functions)
748 {
749 checkTrackType<TrackType>();
750 const auto &info = Executor::NominalType::ClassTypeInfo();
751 // Dynamic type test of track
752 // Assumes Executor classes are sequenced with more specific accepted
753 // types earlier
754 if ( info.IsBaseOf(track.GetTypeInfo()) )
755 // Dispatch to an Executor that knows which of functions applies
756 return Executor{}(&track, functions...);
757 else
758 // Recur, with fewer candidate Executors and all of functions
759 return CallExecutor( (R*)nullptr,
760 (std::tuple<Executors...>*)nullptr, track, functions...);
761 }
762
763 template<typename ...Executors>
764 static constexpr unsigned UsedCases(std::tuple<Executors...>*)
765 {
766 return (Executors::SetUsed | ...); // My very first fold expression :-)
767 }
768
769 template<
770 typename Tag,
771 bool IsConst,
772 typename R,
773 typename ...TrackTypes,
774 typename ...Functions
775 >
776 static R DoTypeSwitch(
777 std::conditional_t<IsConst, const Track, Track> &track,
778 std::tuple<TrackTypes...>*,
779 const Functions &...functions )
780 {
781 // Generate Executor classes, for each of TrackTypes,
782 // each zero-sized and with an operator () that calls the correct
783 // one of functions, assuming the track is of the corresponding type
784 using Executors = std::tuple< Executor<
785 Tag, R,
786 std::conditional_t<IsConst, const TrackTypes, TrackTypes>,
787 Functions...
788 >... >;
789 // Don't even construct the tuple of zero-sized types, just point
790 constexpr Executors *executors = nullptr;
791
792 // Compile time reachability check of the given functions
793 enum { All = sizeof...( functions ) };
794 static_assert( (1u << All) - 1u == UsedCases(executors),
795 "Uncallable case in Track::TypeSwitch");
796
797 // Do dynamic dispatch to one of the Executors
798 return CallExecutor((R *)nullptr, executors, track, functions...);
799 }
800
802
820 template<
821 typename R = void,
822 typename ...Functions
823 >
824 R TypeSwitch(const Functions &...functions)
825 {
826 struct Tag : TrackTypeCountTag {};
827 // Collect all concrete and abstract track types known at compile time
828 using TrackTypes = typename CollectTrackTypes<Tag>::type;
829 TrackTypes *const trackTypes = nullptr;
830 // Generate a function that dispatches dynamically on track type
831 return DoTypeSwitch<Tag, false, R>(*this, trackTypes, functions...);
832 }
833
837 template<
838 typename R = void,
839 typename ...Functions
840 >
841 R TypeSwitch(const Functions &...functions) const
842 {
843 struct Tag : TrackTypeCountTag {};
844 // Collect all concrete and abstract track types known at compile time
845 using TrackTypes = typename CollectTrackTypes<Tag>::type;
846 TrackTypes *const trackTypes = nullptr;
847 // Generate a function that dispatches dynamically on track type
848 return DoTypeSwitch<Tag, true, R>(*this, trackTypes, functions...);
849 }
850
851 // XMLTagHandler callback methods -- NEW virtual for writing
852 virtual void WriteXML(XMLWriter &xmlFile) const = 0;
853
854 // Returns true if an error was encountered while trying to
855 // open the track from XML
856 virtual bool GetErrorOpening() { return false; }
857
858 virtual double GetStartTime() const = 0;
859 virtual double GetEndTime() const = 0;
860
861 // Send a notification to subscribers when state of the track changes
862 // To do: define values for the argument to distinguish different parts
863 // of the state
864 void Notify( int code = -1 );
865
866 // An always-true predicate useful for defining iterators
867 bool Any() const;
868
869 // Frequently useful operands for + and -
870 bool IsSelected() const;
871 bool IsLeader() const;
872 bool IsSelectedLeader() const;
873
874 // Cause this track and following ones in its TrackList to adjust
875 void AdjustPositions();
876
877 // Serialize, not with tags of its own, but as attributes within a tag.
878 void WriteCommonXMLAttributes(
879 XMLWriter &xmlFile, bool includeNameAndSelected = true) const;
880
881 // Return true iff the attribute is recognized.
882 bool HandleCommonXMLAttribute(const std::string_view& attr, const XMLAttributeValueView& valueView);
883};
884
886
888class TRACK_API AudioTrack /* not final */ : public Track
889{
890public:
892 : Track{} {}
893 AudioTrack(const Track &orig) : Track{ orig } {}
894
895 static const TypeInfo &ClassTypeInfo();
896
897 // Serialize, not with tags of its own, but as attributes within a tag.
898 void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const {}
899
900 // Return true iff the attribute is recognized.
901 bool HandleXMLAttribute(const std::string_view & /*attr*/, const XMLAttributeValueView &/*value*/)
902 { return false; }
903};
904
906
908class TRACK_API PlayableTrack /* not final */ : public AudioTrack
909{
910public:
912 : AudioTrack{} {}
913 PlayableTrack(const PlayableTrack &orig) : AudioTrack{ orig } {}
914
915 static const TypeInfo &ClassTypeInfo();
916
917 bool GetMute () const { return DoGetMute(); }
918 bool GetSolo () const { return DoGetSolo(); }
919 bool GetNotMute () const { return !DoGetMute(); }
920 bool GetNotSolo () const { return !DoGetSolo(); }
921 void SetMute (bool m);
922 void SetSolo (bool s);
923
924 void Init( const PlayableTrack &init );
925 void Merge( const Track &init ) override;
926
927 // Serialize, not with tags of its own, but as attributes within a tag.
928 void WriteXMLAttributes(XMLWriter &xmlFile) const;
929
930 // Return true iff the attribute is recognized.
931 bool HandleXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &value);
932
933protected:
934 // These just abbreviate load and store with relaxed memory ordering
935 bool DoGetMute() const;
936 void DoSetMute(bool value);
937 bool DoGetSolo() const;
938 void DoSetSolo(bool value);
939
941 std::atomic<bool> mMute { false };
943 std::atomic<bool> mSolo { false };
944};
945
947
948
950
957template<typename T>
958 inline std::enable_if_t< std::is_pointer_v<T>, T >
960{
961 using BareType = std::remove_pointer_t< T >;
962 if (track &&
963 BareType::ClassTypeInfo().IsBaseOf(track->GetTypeInfo() ))
964 return reinterpret_cast<T>(track);
965 else
966 return nullptr;
967}
968
971template<typename T>
972 inline std::enable_if_t<
973 std::is_pointer_v<T> && std::is_const_v< std::remove_pointer_t< T > >,
974 T
975 >
976 track_cast(const Track *track)
977{
978 using BareType = std::remove_pointer_t< T >;
979 if (track &&
980 BareType::ClassTypeInfo().IsBaseOf(track->GetTypeInfo() ))
981 return reinterpret_cast<T>(track);
982 else
983 return nullptr;
984}
985
986template < typename TrackType > struct TrackIterRange;
987
989
996template <
997 typename TrackType
999 : public ValueIterator< TrackType *, std::bidirectional_iterator_tag >
1000{
1001public:
1003 using FunctionType = std::function< bool(
1004 std::add_pointer_t< std::add_const_t< std::remove_pointer_t<TrackType> > >
1005 ) >;
1006
1010 TrackNodePointer iter,
1012 FunctionType pred = {}
1013 )
1014 : mBegin( begin ), mIter( iter ), mEnd( end )
1015 , mPred( std::move(pred) )
1016 {
1017 // Establish the class invariant
1018 if (this->mIter != this->mEnd && !this->valid())
1019 this->operator ++ ();
1020 }
1021
1023
1025 template < typename Predicate2 >
1026 TrackIter Filter( const Predicate2 &pred2 ) const
1027 {
1028 return { this->mBegin, this->mIter, this->mEnd, pred2 };
1029 }
1030
1032
1034 template < typename TrackType2 >
1035 auto Filter() const
1036 -> std::enable_if_t<
1037 std::is_base_of_v< TrackType, TrackType2 > &&
1038 (!std::is_const_v<TrackType> ||
1039 std::is_const_v<TrackType2>),
1040 TrackIter< TrackType2 >
1041 >
1042 {
1043 return { this->mBegin, this->mIter, this->mEnd, this->mPred };
1044 }
1045
1047 { return this->mPred; }
1048
1050
1052 {
1053 // Maintain the class invariant
1054 if (this->mIter != this->mEnd) do
1055 ++this->mIter.first;
1056 while (this->mIter != this->mEnd && !this->valid() );
1057 return *this;
1058 }
1059
1062 {
1063 TrackIter result { *this };
1064 this-> operator ++ ();
1065 return result;
1066 }
1067
1069
1071 {
1072 // Maintain the class invariant
1073 do {
1074 if (this->mIter == this->mBegin)
1075 // Go circularly
1076 this->mIter = this->mEnd;
1077 else
1078 --this->mIter.first;
1079 } while (this->mIter != this->mEnd && !this->valid() );
1080 return *this;
1081 }
1082
1085 {
1086 TrackIter result { *this };
1087 this->operator -- ();
1088 return result;
1089 }
1090
1092
1093 TrackType *operator * () const
1094 {
1095 if (this->mIter == this->mEnd)
1096 return nullptr;
1097 else
1098 // Other methods guarantee that the cast is correct
1099 // (provided no operations on the TrackList invalidated
1100 // underlying iterators or replaced the tracks there)
1101 return static_cast< TrackType * >( &**this->mIter.first );
1102 }
1103
1106 long amount
1107 ) const
1108 {
1109 auto copy = *this;
1110 std::advance( copy, amount );
1111 return copy;
1112 }
1113
1115 friend inline bool operator == (TrackIter a, TrackIter b)
1116 {
1117 // Assume the predicate is not stateful. Just compare the iterators.
1118 return
1119 a.mIter == b.mIter
1120 // Assume this too:
1121 // && a.mBegin == b.mBegin && a.mEnd == b.mEnd
1122 ;
1123 }
1124
1126 friend inline bool operator != (TrackIter a, TrackIter b)
1127 {
1128 return !(a == b);
1129 }
1130
1131private:
1137 bool valid() const
1138 {
1139 // assume mIter != mEnd
1140 const auto pTrack = track_cast< TrackType * >( &**this->mIter.first );
1141 if (!pTrack)
1142 return false;
1143 return !this->mPred || this->mPred( pTrack );
1144 }
1145
1148
1154};
1155
1157template <
1158 typename TrackType // Track or a subclass, maybe const-qualified
1160 : public IteratorRange< TrackIter< TrackType > >
1161{
1165 : IteratorRange< TrackIter< TrackType > >
1166 ( begin, end )
1167 {}
1168
1169 // Conjoin the filter predicate with another predicate
1170 // Read + as "and"
1171 template< typename Predicate2 >
1172 TrackIterRange operator + ( const Predicate2 &pred2 ) const
1173 {
1174 const auto &pred1 = this->first.GetPredicate();
1175 using Function = typename TrackIter<TrackType>::FunctionType;
1176 const auto &newPred = pred1
1177 ? Function{ [=] (typename Function::argument_type track) {
1178 return pred1(track) && pred2(track);
1179 } }
1180 : Function{ pred2 };
1181 return {
1182 this->first.Filter( newPred ),
1183 this->second.Filter( newPred )
1184 };
1185 }
1186
1187 // Specify the added conjunct as a pointer to member function
1188 // Read + as "and"
1189 template< typename R, typename C >
1190 TrackIterRange operator + ( R ( C ::* pmf ) () const ) const
1191 {
1192 return this->operator + ( std::mem_fn( pmf ) );
1193 }
1194
1195 // Conjoin the filter predicate with the negation of another predicate
1196 // Read - as "and not"
1197 template< typename Predicate2 >
1198 TrackIterRange operator - ( const Predicate2 &pred2 ) const
1199 {
1200 using ArgumentType =
1201 typename TrackIterRange::iterator::FunctionType::argument_type;
1202 auto neg = [=] (ArgumentType track) { return !pred2( track ); };
1203 return this->operator + ( neg );
1204 }
1205
1206 // Specify the negated conjunct as a pointer to member function
1207 // Read - as "and not"
1208 template< typename R, typename C >
1209 TrackIterRange operator - ( R ( C ::* pmf ) () const ) const
1210 {
1211 return this->operator + ( std::not1( std::mem_fn( pmf ) ) );
1212 }
1213
1214 template< typename TrackType2 >
1216 {
1217 return {
1218 this-> first.template Filter< TrackType2 >(),
1219 this->second.template Filter< TrackType2 >()
1220 };
1221 }
1222
1223 TrackIterRange StartingWith( const Track *pTrack ) const
1224 {
1225 auto newBegin = this->find( pTrack );
1226 // More careful construction is needed so that the independent
1227 // increment and decrement of each iterator in the NEW pair
1228 // has the expected behavior at boundaries of the range
1229 return {
1230 { newBegin.mIter, newBegin.mIter, this->second.mEnd,
1231 this->first.GetPredicate() },
1232 { newBegin.mIter, this->second.mIter, this->second.mEnd,
1233 this->second.GetPredicate() }
1234 };
1235 }
1236
1237 TrackIterRange EndingAfter( const Track *pTrack ) const
1238 {
1239 const auto newEnd = this->reversal().find( pTrack ).base();
1240 // More careful construction is needed so that the independent
1241 // increment and decrement of each iterator in the NEW pair
1242 // has the expected behavior at boundaries of the range
1243 return {
1244 { this->first.mBegin, this->first.mIter, newEnd.mIter,
1245 this->first.GetPredicate() },
1246 { this->first.mBegin, newEnd.mIter, newEnd.mIter,
1247 this->second.GetPredicate() }
1248 };
1249 }
1250
1251 // Exclude one given track
1252 TrackIterRange Excluding ( const TrackType *pExcluded ) const
1253 {
1254 return this->operator - (
1255 [=](const Track *pTrack){ return pExcluded == pTrack; } );
1256 }
1257
1259 template< typename ...Functions >
1260 void Visit(const Functions &...functions)
1261 {
1262 for (auto track : *this)
1263 track->TypeSwitch(functions...);
1264 }
1265
1267
1268 template< typename Flag, typename ...Functions >
1269 void VisitWhile(Flag &flag, const Functions &...functions)
1270 {
1271 if ( flag ) for (auto track : *this) {
1272 track->TypeSwitch(functions...);
1273 if (!flag)
1274 break;
1275 }
1276 }
1277};
1278
1279
1282{
1283 enum Type {
1286
1289
1292
1294
1296
1299
1302
1304
1306 };
1307
1309 const std::weak_ptr<Track> &pTrack = {}, int extra = -1)
1310 : mType{ type }
1311 , mpTrack{ pTrack }
1312 , mExtra{ extra }
1313 {}
1314
1315 TrackListEvent( const TrackListEvent& ) = default;
1316
1318 const std::weak_ptr<Track> mpTrack;
1319 const int mExtra;
1320};
1321
1325class TRACK_API TrackList final
1326 : public Observer::Publisher<TrackListEvent>
1327 , public ListOfTracks
1328 , public std::enable_shared_from_this<TrackList>
1329 , public ClientData::Base
1330{
1331 // privatize this, make you use Add instead:
1332 using ListOfTracks::push_back;
1333
1334 // privatize this, make you use Swap instead:
1335 using ListOfTracks::swap;
1336
1337 // Disallow copy
1338 TrackList(const TrackList &that) = delete;
1339 TrackList &operator= (const TrackList&) = delete;
1340
1341 // No need for move, disallow it
1342 TrackList(TrackList &&that) = delete;
1343 TrackList& operator= (TrackList&&) = delete;
1344
1345 void clear() = delete;
1346
1347 public:
1348 static TrackList &Get( AudacityProject &project );
1349 static const TrackList &Get( const AudacityProject &project );
1350
1351 // Create an empty TrackList
1352 // Don't call directly -- use Create() instead
1353 explicit TrackList( AudacityProject *pOwner );
1354
1355 // Create an empty TrackList
1356 static std::shared_ptr<TrackList> Create( AudacityProject *pOwner );
1357
1358 // Move is defined in terms of Swap
1359 void Swap(TrackList &that);
1360
1361 // Destructor
1362 virtual ~TrackList();
1363
1364 // Find the owning project, which may be null
1365 AudacityProject *GetOwner() { return mOwner; }
1366 const AudacityProject *GetOwner() const { return mOwner; }
1367
1374 wxString MakeUniqueTrackName(const wxString& baseTrackName) const;
1375
1376 // Iteration
1377
1378 // Hide the inherited begin() and end()
1382 iterator begin() { return Any().begin(); }
1383 iterator end() { return Any().end(); }
1384 const_iterator begin() const { return Any().begin(); }
1385 const_iterator end() const { return Any().end(); }
1386 const_iterator cbegin() const { return begin(); }
1387 const_iterator cend() const { return end(); }
1388
1390 template < typename TrackType = Track >
1391 auto Find(Track *pTrack)
1393 {
1394 if (!pTrack || pTrack->GetOwner().get() != this)
1395 return EndIterator<TrackType>();
1396 else
1397 return MakeTrackIterator<TrackType>( pTrack->GetNode() );
1398 }
1399
1401
1402 template < typename TrackType = const Track >
1403 auto Find(const Track *pTrack) const
1404 -> std::enable_if_t< std::is_const_v<TrackType>,
1406 >
1407 {
1408 if (!pTrack || pTrack->GetOwner().get() != this)
1409 return EndIterator<TrackType>();
1410 else
1411 return MakeTrackIterator<TrackType>( pTrack->GetNode() );
1412 }
1413
1414 // If the track is not an audio track, or not one of a group of channels,
1415 // return the track itself; else return the first channel of its group --
1416 // in either case as an iterator that will only visit other leader tracks.
1417 // (Generalizing away from the assumption of at most stereo)
1418 TrackIter< Track > FindLeader( Track *pTrack );
1419
1421 FindLeader( const Track *pTrack ) const
1422 {
1423 return const_cast<TrackList*>(this)->
1424 FindLeader( const_cast<Track*>(pTrack) ).Filter< const Track >();
1425 }
1426
1427
1428 template < typename TrackType = Track >
1429 auto Any()
1431 {
1432 return Tracks< TrackType >();
1433 }
1434
1435 template < typename TrackType = const Track >
1436 auto Any() const
1437 -> std::enable_if_t< std::is_const_v<TrackType>,
1438 TrackIterRange< TrackType >
1439 >
1440 {
1441 return Tracks< TrackType >();
1442 }
1443
1444 // Abbreviating some frequently used cases
1445 template < typename TrackType = Track >
1448 {
1449 return Tracks< TrackType >( &Track::IsSelected );
1450 }
1451
1452 template < typename TrackType = const Track >
1453 auto Selected() const
1454 -> std::enable_if_t< std::is_const_v<TrackType>,
1455 TrackIterRange< TrackType >
1456 >
1457 {
1458 return Tracks< TrackType >( &Track::IsSelected );
1459 }
1460
1461
1462 template < typename TrackType = Track >
1463 auto Leaders()
1465 {
1466 return Tracks< TrackType >( &Track::IsLeader );
1467 }
1468
1469 template < typename TrackType = const Track >
1470 auto Leaders() const
1471 -> std::enable_if_t< std::is_const_v<TrackType>,
1472 TrackIterRange< TrackType >
1473 >
1474 {
1475 return Tracks< TrackType >( &Track::IsLeader );
1476 }
1477
1478
1479 template < typename TrackType = Track >
1482 {
1483 return Tracks< TrackType >( &Track::IsSelectedLeader );
1484 }
1485
1486 template < typename TrackType = const Track >
1487 auto SelectedLeaders() const
1488 -> std::enable_if_t< std::is_const_v<TrackType>,
1489 TrackIterRange< TrackType >
1490 >
1491 {
1492 return Tracks< TrackType >( &Track::IsSelectedLeader );
1493 }
1494
1495
1496 template<typename TrackType>
1497 static auto SingletonRange( TrackType *pTrack )
1499 {
1500 return pTrack->GetOwner()->template Any<TrackType>()
1501 .StartingWith( pTrack ).EndingAfter( pTrack );
1502 }
1503
1504
1505private:
1506 Track *DoAddToHead(const std::shared_ptr<Track> &t);
1507 Track *DoAdd(const std::shared_ptr<Track> &t);
1508
1509 template< typename TrackType, typename InTrackType >
1512 {
1513 // Assume iterator filters leader tracks
1514 if (*iter1) {
1515 return {
1516 iter1.Filter( &Track::Any )
1517 .template Filter<TrackType>(),
1518 (++iter1).Filter( &Track::Any )
1519 .template Filter<TrackType>()
1520 };
1521 }
1522 else
1523 // empty range
1524 return {
1525 iter1.template Filter<TrackType>(),
1526 iter1.template Filter<TrackType>()
1527 };
1528 }
1529
1530public:
1531 // Find an iterator range of channels including the given track.
1532 template< typename TrackType >
1533 static auto Channels( TrackType *pTrack )
1535 {
1536 return Channels_<TrackType>( pTrack->GetOwner()->FindLeader(pTrack) );
1537 }
1538
1540
1541 static bool SwapChannels(Track &track);
1542
1543 friend class Track;
1544
1546 void Permute(const std::vector<TrackNodePointer> &permutation);
1547
1548 Track *FindById( TrackId id );
1549
1551 template<typename TrackKind>
1552 TrackKind *AddToHead( const std::shared_ptr< TrackKind > &t )
1553 { return static_cast< TrackKind* >( DoAddToHead( t ) ); }
1554
1555 template<typename TrackKind>
1556 TrackKind *Add( const std::shared_ptr< TrackKind > &t )
1557 { return static_cast< TrackKind* >( DoAdd( t ) ); }
1558
1560 void UnlinkChannels(Track& track);
1569 bool MakeMultiChannelTrack(Track& first, int nChannels, bool aligned);
1570
1573 ListOfTracks::value_type Replace(
1574 Track * t, const ListOfTracks::value_type &with);
1575
1578
1580 void Clear(bool sendEvent = true);
1581
1582 bool CanMoveUp(Track * t) const;
1583 bool CanMoveDown(Track * t) const;
1584
1585 bool MoveUp(Track * t);
1586 bool MoveDown(Track * t);
1587 bool Move(Track * t, bool up) { return up ? MoveUp(t) : MoveDown(t); }
1588
1590 bool Contains(const Track * t) const;
1591
1592 // Return non-null only if the weak pointer is not, and the track is
1593 // owned by this list; constant time.
1594 template <typename Subclass>
1595 std::shared_ptr<Subclass> Lock(const std::weak_ptr<Subclass> &wTrack)
1596 {
1597 auto pTrack = wTrack.lock();
1598 if (pTrack) {
1599 auto pList = pTrack->mList.lock();
1600 if (pTrack && this == pList.get())
1601 return pTrack;
1602 }
1603 return {};
1604 }
1605
1606 bool empty() const;
1607 size_t size() const;
1608
1609 double GetStartTime() const;
1610 double GetEndTime() const;
1611
1612 double GetMinOffset() const;
1613
1614private:
1615
1616 // Visit all tracks satisfying a predicate, mutative access
1617 template <
1618 typename TrackType = Track,
1619 typename Pred =
1621 >
1622 auto Tracks( const Pred &pred = {} )
1624 {
1625 auto b = getBegin(), e = getEnd();
1626 return { { b, b, e, pred }, { b, e, e, pred } };
1627 }
1628
1629 // Visit all tracks satisfying a predicate, const access
1630 template <
1631 typename TrackType = const Track,
1632 typename Pred =
1634 >
1635 auto Tracks( const Pred &pred = {} ) const
1636 -> std::enable_if_t< std::is_const_v<TrackType>,
1638 >
1639 {
1640 auto b = const_cast<TrackList*>(this)->getBegin();
1641 auto e = const_cast<TrackList*>(this)->getEnd();
1642 return { { b, b, e, pred }, { b, e, e, pred } };
1643 }
1644
1645 Track *GetPrev(Track * t, bool linked = false) const;
1646 Track *GetNext(Track * t, bool linked = false) const;
1647
1648 template < typename TrackType >
1651 {
1652 auto b = const_cast<TrackList*>(this)->getBegin();
1653 auto e = const_cast<TrackList*>(this)->getEnd();
1654 return { b, iter, e };
1655 }
1656
1657 template < typename TrackType >
1660 {
1661 auto e = const_cast<TrackList*>(this)->getEnd();
1662 return { e, e, e };
1663 }
1664
1665 TrackIterRange< Track > EmptyRange() const;
1666
1668 { return (p.second == this && p.first == ListOfTracks::end())
1669 || (p.second == &mPendingUpdates && p.first == mPendingUpdates.end()); }
1671 { return { const_cast<TrackList*>(this)->ListOfTracks::end(),
1672 const_cast<TrackList*>(this)}; }
1674 { return { const_cast<TrackList*>(this)->ListOfTracks::begin(),
1675 const_cast<TrackList*>(this)}; }
1676
1679 {
1680 if ( isNull(p) )
1681 return p;
1682 auto q = p;
1683 ++q.first;
1684 return q;
1685 }
1686
1689 {
1690 if (p == getBegin())
1691 return getEnd();
1692 else {
1693 auto q = p;
1694 --q.first;
1695 return q;
1696 }
1697 }
1698
1699 void RecalcPositions(TrackNodePointer node);
1700 void QueueEvent(TrackListEvent event);
1701 void SelectionEvent( const std::shared_ptr<Track> &pTrack );
1702 void PermutationEvent(TrackNodePointer node);
1703 void DataEvent( const std::shared_ptr<Track> &pTrack, int code );
1704 void EnsureVisibleEvent(
1705 const std::shared_ptr<Track> &pTrack, bool modifyState );
1706 void DeletionEvent(TrackNodePointer node = {});
1707 void AdditionEvent(TrackNodePointer node);
1708 void ResizingEvent(TrackNodePointer node);
1709
1710 void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);
1711
1712 // Nondecreasing during the session.
1713 // Nonpersistent.
1714 // Used to assign ids to added tracks.
1715 static long sCounter;
1716
1717public:
1718 using Updater = std::function< void(Track &dest, const Track &src) >;
1719 // Start a deferred update of the project.
1720 // The return value is a duplicate of the given track.
1721 // While ApplyPendingTracks or ClearPendingTracks is not yet called,
1722 // there may be other direct changes to the project that push undo history.
1723 // Meanwhile the returned object can accumulate other changes for a deferred
1724 // push, and temporarily shadow the actual project track for display purposes.
1725 // The Updater function, if not null, merges state (from the actual project
1726 // into the pending track) which is not meant to be overridden by the
1727 // accumulated pending changes.
1728 // To keep the display consistent, the Y and Height values, minimized state,
1729 // and Linked state must be copied, and this will be done even if the
1730 // Updater does not do it.
1731 // Pending track will have the same TrackId as the actual.
1732 // Pending changed tracks will not occur in iterations.
1733 std::shared_ptr<Track> RegisterPendingChangedTrack(
1734 Updater updater,
1735 Track *src
1736 );
1737
1738 // Like the previous, but for a NEW track, not a replacement track. Caller
1739 // supplies the track, and there are no updates.
1740 // Pending track will have an unassigned TrackId.
1741 // Pending changed tracks WILL occur in iterations, always after actual
1742 // tracks, and in the sequence that they were added. They can be
1743 // distinguished from actual tracks by TrackId.
1744 void RegisterPendingNewTrack( const std::shared_ptr<Track> &pTrack );
1745
1746 // Invoke the updaters of pending tracks. Pass any exceptions from the
1747 // updater functions.
1748 void UpdatePendingTracks();
1749
1750 // Forget pending track additions and changes;
1751 // if requested, give back the pending added tracks.
1752 void ClearPendingTracks( ListOfTracks *pAdded = nullptr );
1753
1754 // Change the state of the project.
1755 // Strong guarantee for project state in case of exceptions.
1756 // Will always clear the pending updates.
1757 // Return true if the state of the track list really did change.
1758 bool ApplyPendingTracks();
1759
1760 bool HasPendingTracks() const;
1761
1762private:
1764
1766
1769 std::vector< Updater > mUpdaters;
1770};
1771
1772#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:959
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:889
AudioTrack(const Track &orig)
Definition: Track.h:893
bool HandleXMLAttribute(const std::string_view &, const XMLAttributeValueView &)
Definition: Track.h:901
AudioTrack()
Definition: Track.h:891
void WriteXMLAttributes(XMLWriter &WXUNUSED(xmlFile)) const
Definition: Track.h:898
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:909
bool GetSolo() const
Definition: Track.h:918
bool GetNotMute() const
Definition: Track.h:919
PlayableTrack(const PlayableTrack &orig)
Definition: Track.h:913
PlayableTrack()
Definition: Track.h:911
bool GetNotSolo() const
Definition: Track.h:920
bool GetMute() const
Definition: Track.h:917
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:723
std::function< R() > Continuation
Type of arguments passed as optional second parameter to TypeSwitch() cases.
Definition: Track.h:531
bool GetSelected() const
Definition: Track.h:461
void Offset(double t)
Definition: Track.h:474
Track()
Definition: Track.cpp:44
virtual void SetPan(float)
Definition: Track.h:477
virtual void SetOffset(double o)
Definition: Track.h:475
static R DoTypeSwitch(std::conditional_t< IsConst, const Track, Track > &track, std::tuple< TrackTypes... > *, const Functions &...functions)
Definition: Track.h:776
bool SameKindAs(const Track &track) const
Definition: Track.h:526
static R CallExecutor(R *, std::tuple<> *, TrackType &, const Functions &...)
Definition: Track.h:730
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:384
virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1))=0
virtual const TypeInfo & GetTypeInfo() const =0
ChannelType
Definition: Track.h:274
virtual double GetStartTime() const =0
virtual Holder Clone() const =0
bool IsSelectedLeader() const
Definition: Track.cpp:392
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:745
std::pair< int, int > vrulerSize
Definition: Track.h:379
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:402
bool mSelected
Definition: Track.h:266
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
Definition: Track.h:824
static std::shared_ptr< Subclass > SharedPointer(Track *pTrack)
Definition: Track.h:310
bool HasOwner() const
Definition: Track.h:400
virtual const TypeNames & GetTypeNames() const
Definition: Track.h:355
auto SharedPointer() const -> std::enable_if_t< std::is_const_v< Subclass >, std::shared_ptr< Subclass > >
Definition: Track.h:298
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:290
TrackId GetId() const
Definition: Track.h:280
std::shared_ptr< Track > Holder
Definition: Track.h:361
wxString mName
Definition: Track.h:263
void SetId(TrackId id)
Definition: Track.h:282
bool LinkConsistencyCheck(bool completeList)
Do the non-mutating part of consistency fix only and return status.
Definition: Track.h:397
virtual void SetPanFromChannelType()
Definition: Track.h:478
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:841
virtual void Silence(double WXUNUSED(t0), double WXUNUSED(t1))=0
virtual ChannelType GetChannel() const
Definition: Track.h:471
Continuation<> Fallthrough
Type of arguments passed as optional second parameter to TypeSwitch<void>() cases.
Definition: Track.h:533
std::weak_ptr< TrackList > mList
Definition: Track.h:258
virtual double GetOffset() const =0
virtual double GetEndTime() const =0
std::vector< Interval > Intervals
Definition: Track.h:328
bool IsLeader() const
Definition: Track.cpp:387
virtual void InsertSilence(double WXUNUSED(t), double WXUNUSED(len))=0
static constexpr unsigned UsedCases(std::tuple< Executors... > *)
Definition: Track.h:764
LinkType
For two tracks describes the type of the linkage.
Definition: Track.h:229
virtual bool GetErrorOpening()
Definition: Track.h:856
int mIndex
0-based position of this track in its TrackList
Definition: Track.h:262
static std::shared_ptr< Subclass > SharedPointer(const Track *pTrack)
Definition: Track.h:314
std::unique_ptr< ChannelGroupData > mpGroupData
Definition: Track.h:255
std::vector< ConstInterval > ConstIntervals
Definition: Track.h:330
bool Any() const
Definition: Track.cpp:381
TrackId mId
Identifies the track only in-session, not persistently.
Definition: Track.h:253
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:1000
const FunctionType & GetPredicate() const
Definition: Track.h:1046
TrackNodePointer mIter
Current position.
Definition: Track.h:1151
TrackType * operator*() const
Safe to call even when at the end.
Definition: Track.h:1093
TrackIter & operator--()
Safe to call even when at the beginning.
Definition: Track.h:1070
friend bool operator!=(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
Definition: Track.h:1126
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:1035
TrackNodePointer mBegin
Allows end of reverse iteration to be detected without comparison to other TrackIter.
Definition: Track.h:1150
friend bool operator==(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
Definition: Track.h:1115
TrackIter Filter(const Predicate2 &pred2) const
Return an iterator that replaces the predicate.
Definition: Track.h:1026
TrackIter & operator++()
Safe to call even when at the end.
Definition: Track.h:1051
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:1005
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:1105
FunctionType mPred
Optional filter
Definition: Track.h:1153
TrackIter(TrackNodePointer begin, TrackNodePointer iter, TrackNodePointer end, FunctionType pred={})
Constructor, usually not called directly except by methods of TrackList.
Definition: Track.h:1008
bool valid() const
Test satisfaction of the invariant, while initializing, incrementing, or decrementing.
Definition: Track.h:1137
TrackNodePointer mEnd
Allows end of iteration to be detected without comparison to other TrackIter.
Definition: Track.h:1152
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1330
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1595
static auto SingletonRange(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1497
auto Selected() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1453
AudacityProject * mOwner
Definition: Track.h:1763
static long sCounter
Definition: Track.h:1715
bool Move(Track *t, bool up)
Definition: Track.h:1587
const_iterator begin() const
Definition: Track.h:1384
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:1403
auto SelectedLeaders() -> TrackIterRange< TrackType >
Definition: Track.h:1480
std::vector< Updater > mUpdaters
This is in correspondence with mPendingUpdates.
Definition: Track.h:1769
TrackNodePointer getBegin() const
Definition: Track.h:1673
iterator end()
Definition: Track.h:1383
auto Tracks(const Pred &pred={}) const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1635
TrackIter< const Track > FindLeader(const Track *pTrack) const
Definition: Track.h:1421
auto Leaders() -> TrackIterRange< TrackType >
Definition: Track.h:1463
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1556
auto Tracks(const Pred &pred={}) -> TrackIterRange< TrackType >
Definition: Track.h:1622
bool isNull(TrackNodePointer p) const
Definition: Track.h:1667
TrackNodePointer getNext(TrackNodePointer p) const
Move an iterator to the next node, if any; else stay at end.
Definition: Track.h:1678
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:1391
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1429
TrackNodePointer getEnd() const
Definition: Track.h:1670
std::function< void(Track &dest, const Track &src) > Updater
Definition: Track.h:1718
TrackIter< TrackType > EndIterator() const
Definition: Track.h:1659
auto Any() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1436
auto Leaders() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1470
static TrackIterRange< TrackType > Channels_(TrackIter< InTrackType > iter1)
Definition: Track.h:1511
void clear()=delete
const AudacityProject * GetOwner() const
Definition: Track.h:1366
iterator begin()
Definition: Track.h:1382
const_iterator cend() const
Definition: Track.h:1387
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1446
const_iterator cbegin() const
Definition: Track.h:1386
AudacityProject * GetOwner()
Definition: Track.h:1365
TrackIter< TrackType > MakeTrackIterator(TrackNodePointer iter) const
Definition: Track.h:1650
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:1688
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1533
ListOfTracks mPendingUpdates
Shadow tracks holding append-recording in progress; need to put them into a list so that GetLink() wo...
Definition: Track.h:1767
TrackKind * AddToHead(const std::shared_ptr< TrackKind > &t)
Add a Track, giving it a fresh id.
Definition: Track.h:1552
const_iterator end() const
Definition: Track.h:1385
auto SelectedLeaders() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1487
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:26
@ 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:252
iterator find(const T &t) const
Definition: MemoryX.h:275
IteratorRange< reverse_iterator > reversal() const
Definition: MemoryX.h:262
TrackIter< TrackType > end() const
Definition: MemoryX.h:266
TrackIter< TrackType > begin() const
Definition: MemoryX.h:265
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:638
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:617
Second, nonrecursive case of metafunction, generates operator () that calls function without fallthro...
Definition: Track.h:568
std::conditional_t< std::is_const_v< ArgumentType >, const BaseClass, BaseClass > QualifiedBaseClass
Definition: Track.h:574
std::conditional_t< std::is_const_v< ArgumentType >, const Track, Track > QualifiedTrackType
Definition: Track.h:571
Third, recursive case of metafunction, generates operator () that calls function with fallthrough.
Definition: Track.h:590
std::conditional_t< std::is_const_v< ArgumentType >, const Track, Track > QualifiedTrackType
Definition: Track.h:593
std::conditional_t< std::is_const_v< ArgumentType >, const BaseClass, BaseClass > QualifiedBaseClass
Definition: Track.h:596
First, recursive case of metafunction, defers generation of operator ()
Definition: Track.h:547
std::conditional_t< std::is_const_v< ArgumentType >, const Track, Track > QualifiedTrackType
Definition: Track.h:550
Helper for recursive case of metafunction implementing Track::TypeSwitch.
Definition: Track.h:542
Variadic template implements metafunction with specializations, to dispatch Track::TypeSwitch.
Definition: Track.h:538
TypeNames names
Definition: Track.h:340
bool IsBaseOf(const TypeInfo &other) const
Definition: Track.h:344
const TypeInfo * pBaseInfo
Definition: Track.h:342
Names of a track type for various purposes.
Definition: Track.h:334
wxString info
short, like "wave", in macro output, not internationalized
Definition: Track.h:335
TranslatableString name
long, like "Wave Track"
Definition: Track.h:337
wxString property
short, like "wave", as a Lisp symbol property, not internationalized
Definition: Track.h:336
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:1161
TrackIterRange EndingAfter(const Track *pTrack) const
Definition: Track.h:1237
void VisitWhile(Flag &flag, const Functions &...functions)
See Track::TypeSwitch.
Definition: Track.h:1269
TrackIterRange operator+(const Predicate2 &pred2) const
Definition: Track.h:1172
TrackIterRange(const TrackIter< TrackType > &begin, const TrackIter< TrackType > &end)
Definition: Track.h:1163
void Visit(const Functions &...functions)
See Track::TypeSwitch.
Definition: Track.h:1260
TrackIterRange< TrackType2 > Filter() const
Definition: Track.h:1215
TrackIterRange Excluding(const TrackType *pExcluded) const
Definition: Track.h:1252
TrackIterRange operator-(const Predicate2 &pred2) const
Definition: Track.h:1198
TrackIterRange StartingWith(const Track *pTrack) const
Definition: Track.h:1223
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
Definition: Track.h:1282
TrackListEvent(const TrackListEvent &)=default
const int mExtra
Definition: Track.h:1319
const std::weak_ptr< Track > mpTrack
Definition: Track.h:1318
const Type mType
Definition: Track.h:1317
@ RESIZING
Posted when some track changed its height.
Definition: Track.h:1298
@ SELECTION_CHANGE
Posted when the set of selected tracks changes.
Definition: Track.h:1285
@ DELETION
Posted when a track has been deleted from a tracklist. Also posted when one track replaces another.
Definition: Track.h:1305
@ ADDITION
Posted when a track has been added to a tracklist. Also posted when one track replaces another.
Definition: Track.h:1301
@ PERMUTED
Posted when tracks are reordered but otherwise unchanged.
Definition: Track.h:1295
@ TRACK_REQUEST_VISIBLE
Posted when a track needs to be scrolled into view.
Definition: Track.h:1291
@ TRACK_DATA_CHANGE
Posted when certain fields of a track change.
Definition: Track.h:1288
TrackListEvent(Type type, const std::weak_ptr< Track > &pTrack={}, int extra=-1)
Definition: Track.h:1308
A convenience for defining iterators that return rvalue types, so that they cooperate correctly with ...
Definition: MemoryX.h:238
Empty class which will have subclasses.
Definition: Track.h:59
Implements the ENUMERATE_TRACK_TYPE macro.
Definition: Track.h:116