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#ifndef __AUDACITY_TRACK__
12#define __AUDACITY_TRACK__
13
14#include <algorithm>
15#include <atomic>
16#include <utility>
17#include <list>
18#include <optional>
19#include <functional>
20#include <wx/longlong.h>
21
22#include "Channel.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 "TypeEnumerator.h"
28#include "TypeSwitch.h"
29#include "XMLTagHandler.h"
30
31#ifdef __WXMSW__
32#pragma warning(disable:4284)
33#endif
34
35class wxTextFile;
36class Track;
37class AudacityProject;
38
39using TrackArray = std::vector< Track* >;
40
41class TrackList;
42using TrackListHolder = std::shared_ptr<TrackList>;
43
44using ListOfTracks = std::list< std::shared_ptr< Track > >;
45
46using TrackNodePointer = ListOfTracks::iterator;
47
48using ProgressReporter = std::function<void(double)>;
49
51BEGIN_TYPE_ENUMERATION(TrackTypeTag)
52
53
55
56#define ENUMERATE_TRACK_TYPE(T) ENUMERATE_TYPE(TrackTypeTag, T)
57
58// forward declarations, so we can make them friends
59template<typename T>
60 std::enable_if_t< std::is_pointer_v<T>, T >
61 track_cast(Track *track);
62
63template<typename T>
64 std::enable_if_t<
65 std::is_pointer_v<T> &&
66 std::is_const_v< std::remove_pointer_t< T > >,
67 T
68 >
69 track_cast(const Track *track);
70
72
79{
80public:
81 TrackId() : mValue(-1) {}
82 explicit TrackId (long value) : mValue(value) {}
83
84 bool operator == (const TrackId &other) const
85 { return mValue == other.mValue; }
86
87 bool operator != (const TrackId &other) const
88 { return mValue != other.mValue; }
89
90 // Define this in case you want to key a std::map on TrackId
91 // The operator does not mean anything else
92 bool operator < (const TrackId &other) const
93 { return mValue < other.mValue; }
94
95private:
96 long mValue;
97};
98
102>;
103
105class TRACK_API Track /* not final */
106 : public XMLTagHandler
107 , public AttachedTrackObjects
108 , public std::enable_shared_from_this<Track> // see SharedPointer()
109 , public ChannelGroup
110{
111protected:
113
118
119private:
120
121 friend class TrackList;
122
123 private:
125
126 protected:
127 std::weak_ptr<TrackList> mList;
130
131 public:
132
135
136 TrackId GetId() const { return mId; }
137 private:
138 void SetId( TrackId id ) { mId = id; }
139 public:
140
141 // Given a bare pointer, find a shared_ptr. Undefined results if the track
142 // is not yet managed by a shared_ptr. Undefined results if the track is
143 // not really of the subclass. (That is, trusts the caller and uses static
144 // not dynamic casting.)
145 template<typename Subclass = Track>
146 inline std::shared_ptr<Subclass> SharedPointer()
147 {
148 // shared_from_this is injected into class scope by base class
149 // std::enable_shared_from_this<Track>
150 return std::static_pointer_cast<Subclass>( shared_from_this() );
151 }
152
153 template<typename Subclass = const Track>
154 inline auto SharedPointer() const ->
155 std::enable_if_t<
156 std::is_const_v<Subclass>, std::shared_ptr<Subclass>
157 >
158 {
159 // shared_from_this is injected into class scope by base class
160 // std::enable_shared_from_this<Track>
161 return std::static_pointer_cast<Subclass>( shared_from_this() );
162 }
163
164 // Static overloads of SharedPointer for when the pointer may be null
165 template<typename Subclass = Track>
166 static inline std::shared_ptr<Subclass> SharedPointer( Track *pTrack )
167 { return pTrack ? pTrack->SharedPointer<Subclass>() : nullptr; }
168
169 template<typename Subclass = const Track>
170 static inline std::shared_ptr<Subclass> SharedPointer( const Track *pTrack )
171 { return pTrack ? pTrack->SharedPointer<Subclass>() : nullptr; }
172
174
175 struct TypeNames {
176 wxString info;
177 wxString property;
179 };
180 struct TypeInfo {
182 bool concrete = false;
183 const TypeInfo *pBaseInfo = nullptr;
184
185 bool IsBaseOf(const TypeInfo &other) const
186 {
187 for (auto pInfo = &other;
188 pInfo; pInfo = pInfo->pBaseInfo)
189 if (this == pInfo)
190 return true;
191 return false;
192 }
193 };
194 virtual const TypeInfo &GetTypeInfo() const = 0;
195 static const TypeInfo &ClassTypeInfo();
196 virtual const TypeNames &GetTypeNames() const
197 { return GetTypeInfo().names; }
198
200 virtual bool SupportsBasicEditing() const;
201
202 using Holder = std::shared_ptr<Track>;
203
206
212 const = 0;
213
214public:
216
222 virtual bool LinkConsistencyFix(bool doFix = true);
223
226 { return const_cast<Track*>(this)->LinkConsistencyFix(false); }
227
228 bool HasOwner() const { return static_cast<bool>(GetOwner());}
229
230 std::shared_ptr<TrackList> GetOwner() const { return mList.lock(); }
231
232 LinkType GetLinkType() const noexcept;
233
234protected:
235
239 void SetLinkType(LinkType linkType, bool completeList = true);
240
241private:
245 void DoSetLinkType(LinkType linkType, bool completeList = true);
246
247 Track* GetLinkedTrack() const;
249 bool HasLinkedTrack() const noexcept;
250
252 TrackNodePointer GetNode() const;
254 void SetOwner(
255 const std::weak_ptr<TrackList> &list, TrackNodePointer node);
256
257 public:
258
259 Track();
260 Track(const Track &orig, ProtectedCreationArg&&);
261 Track& operator =(const Track &orig) = delete;
262
263 virtual ~ Track();
264
265 void Init(const Track &orig);
266
268 static void CopyAttachments(Track &dst, const Track &src, bool deep);
269
273 : shallowCopyAttachments{ false }
274 , backup{ false }
275 {}
276
279
281 bool backup;
282
283 // Supporting chain-call idiom
285 { shallowCopyAttachments = true; return std::move(*this); }
286
287 // Supporting chain-call idiom
289 { backup = true; return std::move(*this); }
290 };
291
293 virtual Holder Duplicate(DuplicateOptions = {}) const;
294
295 void ReparentAllAttachments();
296
298 const wxString &GetName() const;
299 void SetName( const wxString &n );
300
302 bool GetSelected() const;
303 virtual void SetSelected(bool s);
304
305public:
306
308
312 virtual Holder Cut(double t0, double t1) = 0;
313
315
322 virtual Holder Copy(double t0, double t1, bool forClipboard = true)
323 const = 0;
324
328 virtual void Clear(double t0, double t1) = 0;
329
331
335 virtual void Paste(double t, const Track &src) = 0;
336
339 virtual void SyncLockAdjust(double oldT1, double newT1);
340
341 // May assume precondition: t0 <= t1
342 virtual void
343 Silence(double t0, double t1, ProgressReporter reportProgress = {}) = 0;
344
348 virtual void InsertSilence(double t, double len) = 0;
349
350private:
354
359 virtual Holder Clone(bool backup) const = 0;
360
361 template<typename T>
362 friend std::enable_if_t< std::is_pointer_v<T>, T >
363 track_cast(Track *track);
364 template<typename T>
365 friend std::enable_if_t<
366 std::is_pointer_v<T> &&
367 std::is_const_v< std::remove_pointer_t< T > >,
368 T
369 >
370 track_cast(const Track *track);
371
372public:
373 bool SameKindAs(const Track &track) const
374 { return &GetTypeInfo() == &track.GetTypeInfo(); }
375
380 template<typename R = void, typename ...Functions>
381 R TypeSwitch(const Functions &...functions)
382 {
383 struct Here : TrackTypeTag {};
384 // List more derived classes later
385 using TrackTypes =
387 return TypeSwitch::VDispatch<R, TrackTypes>(*this, functions...);
388 }
389
391 template<typename R = void, typename ...Functions>
392 R TypeSwitch(const Functions &...functions) const
393 {
394 struct Here : TrackTypeTag {};
395 // List more derived classes later
396 using namespace TypeList;
397 using TrackTypes = Map_t<Fn<std::add_const_t>,
399 return TypeSwitch::VDispatch<R, TrackTypes>(*this, functions...);
400 }
401
402 // XMLTagHandler callback methods -- NEW virtual for writing
403 virtual void WriteXML(XMLWriter &xmlFile) const = 0;
404
407
410 virtual std::optional<TranslatableString> GetErrorOpening() const;
411
412 // Send a notification to subscribers when state of the track changes
413 // To do: define values for the argument to distinguish different parts
414 // of the state
415 void Notify(bool allChannels, int code = -1);
416
417 // An always-true predicate useful for defining iterators
418 bool Any() const;
419
420 // Frequently useful operands for + and -
421 bool IsSelected() const;
422 bool IsLeader() const;
423
424 // Cause this track and following ones in its TrackList to adjust
425 void AdjustPositions();
426
427 // Serialize, not with tags of its own, but as attributes within a tag.
428 void WriteCommonXMLAttributes(
429 XMLWriter &xmlFile, bool includeNameAndSelected = true) const;
430
431 // Return true iff the attribute is recognized.
432 bool HandleCommonXMLAttribute(const std::string_view& attr, const XMLAttributeValueView& valueView);
433
434private:
435 void CopyGroupProperties(const Track &other);
436
437 wxString mName;
438 // This is important only during loading of files
439 LinkType mLinkType{ LinkType::None };
440 bool mSelected{ false };
441};
442
444
446template<typename Base = Track>
448 : public Base
449 , public Channel
450{
451public:
452 using Base::Base;
453 size_t NChannels() const override { return 1; }
454 std::shared_ptr<Channel> DoGetChannel(size_t iChannel) override
455 {
456 if (iChannel == 0) {
457 // Use aliasing constructor of std::shared_ptr
458 Channel *alias = this;
459 return { this->shared_from_this(), alias };
460 }
461 return {};
462 }
463protected:
464 ChannelGroup &DoGetChannelGroup() const override {
465 const Track &track = *this;
466 return const_cast<Track&>(track);
467 }
468};
469
471
478template<typename T>
479 inline std::enable_if_t< std::is_pointer_v<T>, T >
481{
482 using BareType = std::remove_pointer_t< T >;
483 if (track &&
484 BareType::ClassTypeInfo().IsBaseOf(track->GetTypeInfo() ))
485 return reinterpret_cast<T>(track);
486 else
487 return nullptr;
488}
489
492template<typename T>
493 inline std::enable_if_t<
494 std::is_pointer_v<T> && std::is_const_v< std::remove_pointer_t< T > >,
495 T
496 >
497 track_cast(const Track *track)
498{
499 using BareType = std::remove_pointer_t< T >;
500 if (track &&
501 BareType::ClassTypeInfo().IsBaseOf(track->GetTypeInfo() ))
502 return reinterpret_cast<T>(track);
503 else
504 return nullptr;
505}
506
507template < typename TrackType > struct TrackIterRange;
508
510
517template <
518 typename TrackType
520 : public ValueIterator< TrackType *, std::bidirectional_iterator_tag >
521{
522public:
524 using FunctionType = std::function< bool(
525 std::add_pointer_t< std::add_const_t< std::remove_pointer_t<TrackType> > >
526 ) >;
527
531 TrackNodePointer iter,
533 FunctionType pred = {}
534 )
535 : mBegin( begin ), mIter( iter ), mEnd( end )
536 , mPred( std::move(pred) )
537 {
538 // Establish the class invariant
539 if (this->mIter != this->mEnd && !this->valid())
540 this->operator ++ ();
541 }
542
544
546 template < typename Predicate2 >
547 TrackIter Filter( const Predicate2 &pred2 ) const
548 {
549 return { this->mBegin, this->mIter, this->mEnd, pred2 };
550 }
551
553
555 template < typename TrackType2 >
556 auto Filter() const
557 -> std::enable_if_t<
558 std::is_base_of_v< TrackType, TrackType2 > &&
559 (!std::is_const_v<TrackType> ||
560 std::is_const_v<TrackType2>),
561 TrackIter< TrackType2 >
562 >
563 {
564 return { this->mBegin, this->mIter, this->mEnd, this->mPred };
565 }
566
568 { return this->mPred; }
569
571
573 {
574 // Maintain the class invariant
575 if (this->mIter != this->mEnd) do
576 ++this->mIter;
577 while (this->mIter != this->mEnd && !this->valid() );
578 return *this;
579 }
580
583 {
584 TrackIter result { *this };
585 this-> operator ++ ();
586 return result;
587 }
588
590
592 {
593 // Maintain the class invariant
594 do {
595 if (this->mIter == this->mBegin)
596 // Go circularly
597 this->mIter = this->mEnd;
598 else
599 --this->mIter;
600 } while (this->mIter != this->mEnd && !this->valid() );
601 return *this;
602 }
603
606 {
607 TrackIter result { *this };
608 this->operator -- ();
609 return result;
610 }
611
613
614 TrackType *operator * () const
615 {
616 if (this->mIter == this->mEnd)
617 return nullptr;
618 else
619 // Other methods guarantee that the cast is correct
620 // (provided no operations on the TrackList invalidated
621 // underlying iterators or replaced the tracks there)
622 return static_cast< TrackType * >( &**this->mIter );
623 }
624
627 long amount
628 ) const
629 {
630 auto copy = *this;
631 std::advance( copy, amount );
632 return copy;
633 }
634
636 friend inline bool operator == (TrackIter a, TrackIter b)
637 {
638 // Assume the predicate is not stateful. Just compare the iterators.
639 return
640 a.mIter == b.mIter
641 // Assume this too:
642 // && a.mBegin == b.mBegin && a.mEnd == b.mEnd
643 ;
644 }
645
647 friend inline bool operator != (TrackIter a, TrackIter b)
648 {
649 return !(a == b);
650 }
651
652private:
658 bool valid() const
659 {
660 // assume mIter != mEnd
661 const auto pTrack = track_cast< TrackType * >( &**this->mIter );
662 if (!pTrack)
663 return false;
664 return !this->mPred || this->mPred( pTrack );
665 }
666
669
675};
676
678template <
679 typename TrackType // Track or a subclass, maybe const-qualified
681 : public IteratorRange< TrackIter< TrackType > >
682{
686 : IteratorRange< TrackIter< TrackType > >
687 ( begin, end )
688 {}
689
690 // Conjoin the filter predicate with another predicate
691 // Read + as "and"
692 template< typename Predicate2 >
693 TrackIterRange operator + ( const Predicate2 &pred2 ) const
694 {
695 const auto &pred1 = this->first.GetPredicate();
696 using Function = typename TrackIter<TrackType>::FunctionType;
697 const auto &newPred = pred1
698 ? Function{ [=] (typename Function::argument_type track) {
699 return pred1(track) && pred2(track);
700 } }
701 : Function{ pred2 };
702 return {
703 this->first.Filter( newPred ),
704 this->second.Filter( newPred )
705 };
706 }
707
708 // Specify the added conjunct as a pointer to member function
709 // Read + as "and"
710 template< typename R, typename C >
711 TrackIterRange operator + ( R ( C ::* pmf ) () const ) const
712 {
713 return this->operator + ( std::mem_fn( pmf ) );
714 }
715
716 // Conjoin the filter predicate with the negation of another predicate
717 // Read - as "and not"
718 template< typename Predicate2 >
719 TrackIterRange operator - ( const Predicate2 &pred2 ) const
720 {
721 using ArgumentType =
722 typename TrackIterRange::iterator::FunctionType::argument_type;
723 auto neg = [=] (ArgumentType track) { return !pred2( track ); };
724 return this->operator + ( neg );
725 }
726
727 // Specify the negated conjunct as a pointer to member function
728 // Read - as "and not"
729 template< typename R, typename C >
730 TrackIterRange operator - ( R ( C ::* pmf ) () const ) const
731 {
732 return this->operator + ( std::not1( std::mem_fn( pmf ) ) );
733 }
734
735 template< typename TrackType2 >
737 {
738 return {
739 this-> first.template Filter< TrackType2 >(),
740 this->second.template Filter< TrackType2 >()
741 };
742 }
743
744 TrackIterRange StartingWith( const Track *pTrack ) const
745 {
746 auto newBegin = this->find( pTrack );
747 // More careful construction is needed so that the independent
748 // increment and decrement of each iterator in the NEW pair
749 // has the expected behavior at boundaries of the range
750 return {
751 { newBegin.mIter, newBegin.mIter, this->second.mEnd,
752 this->first.GetPredicate() },
753 { newBegin.mIter, this->second.mIter, this->second.mEnd,
754 this->second.GetPredicate() }
755 };
756 }
757
758 TrackIterRange EndingAfter( const Track *pTrack ) const
759 {
760 const auto newEnd = this->reversal().find( pTrack ).base();
761 // More careful construction is needed so that the independent
762 // increment and decrement of each iterator in the NEW pair
763 // has the expected behavior at boundaries of the range
764 return {
765 { this->first.mBegin, this->first.mIter, newEnd.mIter,
766 this->first.GetPredicate() },
767 { this->first.mBegin, newEnd.mIter, newEnd.mIter,
768 this->second.GetPredicate() }
769 };
770 }
771
772 // Exclude one given track
773 TrackIterRange Excluding ( const TrackType *pExcluded ) const
774 {
775 return this->operator - (
776 [=](const Track *pTrack){ return pExcluded == pTrack; } );
777 }
778
780 template< typename ...Functions >
781 void Visit(const Functions &...functions)
782 {
783 for (auto track : *this)
784 track->TypeSwitch(functions...);
785 }
786
788
789 template< typename Flag, typename ...Functions >
790 void VisitWhile(Flag &flag, const Functions &...functions)
791 {
792 if ( flag ) for (auto track : *this) {
793 track->TypeSwitch(functions...);
794 if (!flag)
795 break;
796 }
797 }
798};
799
800
803{
804 enum Type {
807
810
812
814
817
820
822
826 };
827
829 const std::weak_ptr<Track> &pTrack = {}, int extra = -1)
830 : mType{ type }
831 , mpTrack{ pTrack }
832 , mExtra{ extra }
833 {}
834
835 TrackListEvent( const TrackListEvent& ) = default;
836
837 const Type mType;
838 const std::weak_ptr<Track> mpTrack;
839 const int mExtra;
840};
841
845class TRACK_API TrackList final
846 : public Observer::Publisher<TrackListEvent>
847 , private ListOfTracks
848 , public std::enable_shared_from_this<TrackList>
849 , public ClientData::Base
850{
851 // privatize this, make you use Add instead:
852 using ListOfTracks::push_back;
853
854 // privatize this, make you use Swap instead:
855 using ListOfTracks::swap;
856
857 // Disallow copy
858 TrackList(const TrackList &that) = delete;
859 TrackList &operator= (const TrackList&) = delete;
860
861 // No need for move, disallow it
862 TrackList(TrackList &&that) = delete;
864
865 void clear() = delete;
866
867 public:
869 static const TrackList &Get( const AudacityProject &project );
870
871 // Create an empty TrackList
872 // Don't call directly -- use Create() instead
873 explicit TrackList( AudacityProject *pOwner );
874
875 // Create an empty TrackList
876 static TrackListHolder Create(AudacityProject *pOwner);
877
881 void Swap(TrackList &that);
882
883 // Destructor
884 virtual ~TrackList();
885
886 // Find the owning project, which may be null
887 AudacityProject *GetOwner() { return mOwner; }
888 const AudacityProject *GetOwner() const { return mOwner; }
889
896 wxString MakeUniqueTrackName(const wxString& baseTrackName) const;
897
898 // Iteration
899
900 // Hide the inherited begin() and end()
903
904 using value_type = Track *;
905 iterator begin() { return Any().begin(); }
906 iterator end() { return Any().end(); }
907 const_iterator begin() const { return Any().begin(); }
908 const_iterator end() const { return Any().end(); }
909 const_iterator cbegin() const { return begin(); }
910 const_iterator cend() const { return end(); }
911
912 // Reverse iteration
913 using reverse_iterator = std::reverse_iterator<iterator>;
914 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
915 reverse_iterator rbegin() { return Any().rbegin(); }
916 reverse_iterator rend() { return Any().rend(); }
917 const_reverse_iterator rbegin() const { return Any().rbegin(); }
918 const_reverse_iterator rend() const { return Any().rend(); }
919 const_reverse_iterator crbegin() const { return rbegin(); }
920 const_reverse_iterator crend() const { return rend(); }
921
925
926 // From a track, get an iterator into its owning TrackList. If it is not
927 // owned, get a default constructed iterator.
928 TrackIter<Track> Find(Track *pTrack);
929
930 TrackIter<const Track> Find(const Track *pTrack) const
931 {
932 return const_cast<TrackList*>(this)->
933 Find(const_cast<Track*>(pTrack)).Filter<const Track>();
934 }
935
936
937private:
939 iterator Begin() { return Tracks<Track>().begin(); }
941 iterator End() { return Tracks<Track>().end(); }
942
944 const_iterator Begin() const { return Tracks<const Track>().begin(); }
946 const_iterator End() const { return Tracks<const Track>().end(); }
947
948public:
949 template < typename TrackType = Track >
950 auto Any()
952 {
953 return Tracks< TrackType >( &Track::IsLeader );
954 }
955
956 template < typename TrackType = const Track >
957 auto Any() const
958 -> std::enable_if_t< std::is_const_v<TrackType>,
959 TrackIterRange< TrackType >
960 >
961 {
962 return Tracks< TrackType >( &Track::IsLeader );
963 }
964
965
966 template <typename TrackType = Track>
968 {
969 return Tracks<TrackType>(&Track::IsSelected);
970 }
971
972 template <typename TrackType = const Track>
973 auto Selected() const
974 -> std::enable_if_t<std::is_const_v<TrackType>, TrackIterRange<TrackType>>
975 {
976 return Tracks<TrackType>(&Track::IsSelected);
977 }
978
979
980 template<typename TrackType>
981 static auto SingletonRange( TrackType *pTrack )
983 {
984 return pTrack->GetOwner()->template Tracks<TrackType>()
985 .StartingWith( pTrack ).EndingAfter( pTrack );
986 }
987
988
989private:
990 Track *DoAddToHead(const std::shared_ptr<Track> &t);
991 Track *DoAdd(const std::shared_ptr<Track> &t, bool assignIds);
992
993 template< typename TrackType, typename InTrackType >
996 {
997 if (*iter1) {
998 return {
999 iter1.Filter( &Track::Any )
1000 .template Filter<TrackType>(),
1001 (++iter1).Filter( &Track::Any )
1002 .template Filter<TrackType>()
1003 };
1004 }
1005 else
1006 // empty range
1007 return {
1008 iter1.template Filter<TrackType>(),
1009 iter1.template Filter<TrackType>()
1010 };
1011 }
1012
1013public:
1014 // Find an iterator range of channels including the given track.
1015 template< typename TrackType >
1016 static auto Channels( TrackType *pTrack )
1018 {
1019 return Channels_<TrackType>(pTrack->GetOwner()->Find(pTrack));
1020 }
1021
1022 friend class Track;
1023
1029 void Insert(
1030 const Track* before, const Track::Holder &pSrc, bool assignIds = false);
1031
1036 void Permute(const std::vector<Track *> &tracks);
1037
1038 Track *FindById( TrackId id );
1039
1041 template<typename TrackKind>
1042 TrackKind *AddToHead( const std::shared_ptr<TrackKind> &t )
1043 { return static_cast<TrackKind*>(DoAddToHead(t)); }
1044
1047 template<typename TrackKind>
1048 TrackKind *Add(const std::shared_ptr<TrackKind> &t,
1049 bool assignIds = true)
1050 { return static_cast<TrackKind*>(DoAdd(t, assignIds)); }
1051
1061 Track::Holder ReplaceOne(Track &t, TrackList &&with);
1062
1064 Track::Holder Remove(Track &track);
1065
1067 void Clear(bool sendEvent = true);
1068
1069 bool CanMoveUp(Track &t) const;
1070 bool CanMoveDown(Track &t) const;
1071
1072 bool MoveUp(Track &t);
1073 bool MoveDown(Track &t);
1074 bool Move(Track &t, bool up) { return up ? MoveUp(t) : MoveDown(t); }
1075
1076 // Return non-null only if the weak pointer is not, and the track is
1077 // owned by this list; constant time.
1078 template <typename Subclass>
1079 std::shared_ptr<Subclass> Lock(const std::weak_ptr<Subclass> &wTrack)
1080 {
1081 auto pTrack = wTrack.lock();
1082 if (pTrack) {
1083 auto pList = pTrack->mList.lock();
1084 if (pTrack && this == pList.get())
1085 return pTrack;
1086 }
1087 return {};
1088 }
1089
1090 bool empty() const;
1091 size_t Size() const { return Any().size(); }
1092
1094 double GetStartTime() const;
1096 double GetEndTime() const;
1097
1101
1104 static TrackListHolder Temporary(AudacityProject *pProject,
1105 const Track::Holder &pTrack = {});
1106
1108
1112 void Append(TrackList &&list, bool assignIds = true);
1113
1115 void AppendOne(TrackList &&list);
1116
1118 Track::Holder DetachFirst();
1119
1120private:
1121 using ListOfTracks::size;
1122
1123 // Visit all tracks satisfying a predicate, mutative access
1124 template <
1125 typename TrackType = Track,
1126 typename Pred =
1128 >
1129 auto Tracks( const Pred &pred = {} )
1131 {
1132 auto b = getBegin(), e = getEnd();
1133 return { { b, b, e, pred }, { b, e, e, pred } };
1134 }
1135
1136 // Visit all tracks satisfying a predicate, const access
1137 template <
1138 typename TrackType = const Track,
1139 typename Pred =
1141 >
1142 auto Tracks( const Pred &pred = {} ) const
1143 -> std::enable_if_t< std::is_const_v<TrackType>,
1145 >
1146 {
1147 auto b = const_cast<TrackList*>(this)->getBegin();
1148 auto e = const_cast<TrackList*>(this)->getEnd();
1149 return { { b, b, e, pred }, { b, e, e, pred } };
1150 }
1151
1152 Track *GetPrev(Track &, bool linked = false) const;
1153 Track *GetNext(Track &, bool linked = false) const;
1154
1155 template < typename TrackType >
1158 {
1159 auto b = const_cast<TrackList*>(this)->getBegin();
1160 auto e = const_cast<TrackList*>(this)->getEnd();
1161 return { b, iter, e };
1162 }
1163
1164 template < typename TrackType >
1167 {
1168 auto e = const_cast<TrackList*>(this)->getEnd();
1169 return { e, e, e };
1170 }
1171
1172 TrackIterRange< Track > EmptyRange() const;
1173
1174 bool isNull(TrackNodePointer p) const { return p == ListOfTracks::end(); }
1176 { return const_cast<TrackList*>(this)->ListOfTracks::end(); }
1178 { return const_cast<TrackList*>(this)->ListOfTracks::begin(); }
1179
1182 {
1183 if ( isNull(p) )
1184 return p;
1185 auto q = p;
1186 ++q;
1187 return q;
1188 }
1189
1192 {
1193 if (p == getBegin())
1194 return getEnd();
1195 else {
1196 auto q = p;
1197 --q;
1198 return q;
1199 }
1200 }
1201
1202 void RecalcPositions(TrackNodePointer node);
1203 void QueueEvent(TrackListEvent event);
1204 void SelectionEvent(Track &track);
1205 void PermutationEvent(TrackNodePointer node);
1206 void DataEvent(
1207 const std::shared_ptr<Track> &pTrack, bool allChannels, int code );
1208 void DeletionEvent(std::weak_ptr<Track> node, bool duringReplace);
1209 void AdditionEvent(TrackNodePointer node);
1210 void ResizingEvent(TrackNodePointer node);
1211
1212 void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);
1213
1214 // Nondecreasing during the session.
1215 // Nonpersistent.
1216 // Used to assign ids to added tracks.
1217 static long sCounter;
1218
1220
1223 bool mAssignsIds{ true };
1224};
1225
1226#endif
Abstract class ChannelGroup with two discrete iterable dimensions, channels and intervals; subclasses...
const auto tracks
const auto project
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:102
std::function< void(double)> ProgressReporter
Definition: Track.h:48
#define ENUMERATE_TRACK_TYPE(T)
Empty class which will have subclasses.
Definition: Track.h:56
ListOfTracks::iterator TrackNodePointer
Definition: Track.h:46
std::list< std::shared_ptr< Track > > ListOfTracks
Definition: Track.h:44
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:480
std::shared_ptr< TrackList > TrackListHolder
Definition: Track.h:42
abstract base class for structures that user interface associates with tracks
Make a list of all distinct types so far mentioned in calls of a certain macro.
#define BEGIN_TYPE_ENUMERATION(Tag)
Dispatch to one of a set of functions by the run-time type of an object.
Append(Adapt< My >([](My &table) { return(WaveChannelSubViews::numFactories() > 1) ? std::make_unique< Entry >("MultiView", Entry::CheckItem, OnMultiViewID, XXO("&Multi-view"), POPUP_MENU_FN(OnMultiView), table, [](PopupMenuHandler &handler, wxMenu &menu, int id){ auto &table=static_cast< WaveTrackMenuTable & >(handler);auto &track=table.FindWaveTrack();const auto &view=WaveChannelView::GetFirst(track);menu.Check(id, view.GetMultiView());}) :nullptr;}))
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:90
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
Definition: Channel.cpp:61
double GetStartTime() const
Get the minimum of Start() values of intervals, or 0 when none.
Definition: Channel.cpp:50
LinkType
For two tracks describes the type of the linkage.
Definition: Channel.h:512
Utility to register hooks into a host class that attach client data.
Definition: ClientData.h:229
Site & operator=(const Site &other)
Definition: ClientData.h:251
Subclass * DoFind(Locked< DataContainer > &data, const RegisteredFactory &key)
Definition: ClientData.h:599
An object that sends messages to an open-ended list of subscribed callbacks.
Definition: Observer.h:108
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:110
virtual Holder Clone(bool backup) const =0
virtual void Paste(double t, const Track &src)=0
Weak precondition allows overrides to replicate one channel into many.
Track()
Definition: Track.cpp:38
virtual Holder PasteInto(AudacityProject &project, TrackList &list) const =0
bool SameKindAs(const Track &track) const
Definition: Track.h:373
bool IsSelected() const
Definition: Track.cpp:258
virtual Holder Copy(double t0, double t1, bool forClipboard=true) const =0
Create new tracks and don't modify this track.
virtual const TypeInfo & GetTypeInfo() const =0
virtual void InsertSilence(double t, double len)=0
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:230
R TypeSwitch(const Functions &...functions)
Definition: Track.h:381
static std::shared_ptr< Subclass > SharedPointer(Track *pTrack)
Definition: Track.h:166
bool HasOwner() const
Definition: Track.h:228
virtual const TypeNames & GetTypeNames() const
Definition: Track.h:196
auto SharedPointer() const -> std::enable_if_t< std::is_const_v< Subclass >, std::shared_ptr< Subclass > >
Definition: Track.h:154
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:146
TrackId GetId() const
Definition: Track.h:136
virtual void Clear(double t0, double t1)=0
std::shared_ptr< Track > Holder
Definition: Track.h:202
wxString mName
Definition: Track.h:437
void SetId(TrackId id)
Definition: Track.h:138
virtual void WriteXML(XMLWriter &xmlFile) const =0
R TypeSwitch(const Functions &...functions) const
Definition: Track.h:392
virtual void Silence(double t0, double t1, ProgressReporter reportProgress={})=0
std::weak_ptr< TrackList > mList
Definition: Track.h:127
bool IsLeader() const
Definition: Track.cpp:261
static std::shared_ptr< Subclass > SharedPointer(const Track *pTrack)
Definition: Track.h:170
bool LinkConsistencyCheck()
Do the non-mutating part of consistency fix only and return status.
Definition: Track.h:225
virtual Holder Cut(double t0, double t1)=0
Create tracks and modify this track.
bool Any() const
Definition: Track.cpp:255
TrackId mId
Identifies the track only in-session, not persistently.
Definition: Track.h:124
An in-session identifier of track objects across undo states. It does not persist between sessions.
Definition: Track.h:79
bool operator!=(const TrackId &other) const
Definition: Track.h:87
TrackId()
Definition: Track.h:81
bool operator<(const TrackId &other) const
Definition: Track.h:92
TrackId(long value)
Definition: Track.h:82
long mValue
Definition: Track.h:96
bool operator==(const TrackId &other) const
Definition: Track.h:84
Iterator over only members of a TrackList of the specified subtype, optionally filtered by a predicat...
Definition: Track.h:521
const FunctionType & GetPredicate() const
Definition: Track.h:567
TrackNodePointer mIter
Current position.
Definition: Track.h:672
TrackType * operator*() const
Safe to call even when at the end.
Definition: Track.h:614
TrackIter & operator--()
Safe to call even when at the beginning.
Definition: Track.h:591
friend bool operator!=(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
Definition: Track.h:647
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:556
TrackNodePointer mBegin
Allows end of reverse iteration to be detected without comparison to other TrackIter.
Definition: Track.h:671
friend bool operator==(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
Definition: Track.h:636
TrackIter Filter(const Predicate2 &pred2) const
Return an iterator that replaces the predicate.
Definition: Track.h:547
TrackIter & operator++()
Safe to call even when at the end.
Definition: Track.h:572
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:526
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:626
FunctionType mPred
Optional filter
Definition: Track.h:674
TrackIter(TrackNodePointer begin, TrackNodePointer iter, TrackNodePointer end, FunctionType pred={})
Constructor, usually not called directly except by methods of TrackList.
Definition: Track.h:529
bool valid() const
Test satisfaction of the invariant, while initializing, incrementing, or decrementing.
Definition: Track.h:658
TrackNodePointer mEnd
Allows end of iteration to be detected without comparison to other TrackIter.
Definition: Track.h:673
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:850
const_reverse_iterator crbegin() const
Definition: Track.h:919
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1079
static auto SingletonRange(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:981
auto Selected() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:973
const_reverse_iterator rend() const
Definition: Track.h:918
AudacityProject * mOwner
Definition: Track.h:1219
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: Track.h:914
static long sCounter
Definition: Track.h:1217
const_iterator End() const
This private function still iterates channels not tracks.
Definition: Track.h:946
const_iterator begin() const
Definition: Track.h:907
reverse_iterator rend()
Definition: Track.h:916
TrackNodePointer getBegin() const
Definition: Track.h:1177
iterator end()
Definition: Track.h:906
auto Tracks(const Pred &pred={}) const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1142
TrackIter< const Track > Find(const Track *pTrack) const
Definition: Track.h:930
auto Tracks(const Pred &pred={}) -> TrackIterRange< TrackType >
Definition: Track.h:1129
size_t Size() const
Definition: Track.h:1091
bool isNull(TrackNodePointer p) const
Definition: Track.h:1174
bool Move(Track &t, bool up)
Definition: Track.h:1074
const_reverse_iterator crend() const
Definition: Track.h:920
TrackNodePointer getNext(TrackNodePointer p) const
Move an iterator to the next node, if any; else stay at end.
Definition: Track.h:1181
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:950
TrackNodePointer getEnd() const
Definition: Track.h:1175
TrackIter< TrackType > EndIterator() const
Definition: Track.h:1166
auto Any() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:957
reverse_iterator rbegin()
Definition: Track.h:915
static TrackIterRange< TrackType > Channels_(TrackIter< InTrackType > iter1)
Definition: Track.h:995
void clear()=delete
const AudacityProject * GetOwner() const
Definition: Track.h:888
iterator begin()
Definition: Track.h:905
std::reverse_iterator< iterator > reverse_iterator
Definition: Track.h:913
const_iterator cend() const
Definition: Track.h:910
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:967
iterator Begin()
This private function still iterates channels not tracks.
Definition: Track.h:939
const_iterator cbegin() const
Definition: Track.h:909
const_iterator Begin() const
This private function still iterates channels not tracks.
Definition: Track.h:944
iterator End()
This private function still iterates channels not tracks.
Definition: Track.h:941
AudacityProject * GetOwner()
Definition: Track.h:887
TrackIter< TrackType > MakeTrackIterator(TrackNodePointer iter) const
Definition: Track.h:1157
TrackList(const TrackList &that)=delete
TrackList(TrackList &&that)=delete
TrackKind * Add(const std::shared_ptr< TrackKind > &t, bool assignIds=true)
Definition: Track.h:1048
TrackNodePointer getPrev(TrackNodePointer p) const
Move an iterator to the previous node, if any; else wrap to end.
Definition: Track.h:1191
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1016
const_reverse_iterator rbegin() const
Definition: Track.h:917
TrackKind * AddToHead(const std::shared_ptr< TrackKind > &t)
Add a Track, giving it a fresh id if this is not temporary.
Definition: Track.h:1042
const_iterator end() const
Definition: Track.h:908
Holds a msgid for the translation catalog; may also bind format arguments.
typename Accumulate< 0 >::type type
Generates overrides of channel-related functions.
Definition: Track.h:450
std::shared_ptr< Channel > DoGetChannel(size_t iChannel) override
Definition: Track.h:454
size_t NChannels() const override
Report the number of channels.
Definition: Track.h:453
ChannelGroup & DoGetChannelGroup() const override
Subclass must override.
Definition: Track.h:464
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:25
PROJECT_FILE_IO_API void Remove(const FilePath &path)
PROJECT_FILE_IO_API wxString Find(const FilePath &path)
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:201
@ ShallowCopying
copy pointers only; won't compile for std::unique_ptr
Utilities for compile-time type manipulation. Some terminology as in Lisp.
Definition: TypeList.h:22
typename Map< Metafunction, TypeList >::type Map_t
Definition: TypeList.h:262
std::vector< std::vector< float > > Duplicate(const std::vector< float > &audio, size_t numChannels)
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:628
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40
STL namespace.
A convenient default parameter for class template Site.
Definition: ClientData.h:29
A convenience for use with range-for.
Definition: IteratorX.h:39
iterator find(const T &t) const
Definition: IteratorX.h:62
IteratorRange< reverse_iterator > reversal() const
Definition: IteratorX.h:49
TrackIter< TrackType > end() const
Definition: IteratorX.h:53
TrackIter< TrackType > begin() const
Definition: IteratorX.h:52
Choices when duplicating a track.
Definition: Track.h:271
bool shallowCopyAttachments
if true, then share AttachedTrackObjects
Definition: Track.h:278
bool backup
passed to Track::Clone()
Definition: Track.h:281
DuplicateOptions ShallowCopyAttachments() &&
Definition: Track.h:284
DuplicateOptions Backup() &&
Definition: Track.h:288
Empty argument passed to some public constructors.
Definition: Track.h:117
TypeNames names
Definition: Track.h:181
bool IsBaseOf(const TypeInfo &other) const
Definition: Track.h:185
const TypeInfo * pBaseInfo
Definition: Track.h:183
Names of a track type for various purposes.
Definition: Track.h:175
wxString info
short, like "wave", in macro output, not internationalized
Definition: Track.h:176
TranslatableString name
long, like "Wave Track"
Definition: Track.h:178
wxString property
short, like "wave", as a Lisp symbol property, not internationalized
Definition: Track.h:177
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
Definition: Track.h:682
TrackIterRange EndingAfter(const Track *pTrack) const
Definition: Track.h:758
void VisitWhile(Flag &flag, const Functions &...functions)
See Track::TypeSwitch.
Definition: Track.h:790
TrackIterRange operator+(const Predicate2 &pred2) const
Definition: Track.h:693
TrackIterRange(const TrackIter< TrackType > &begin, const TrackIter< TrackType > &end)
Definition: Track.h:684
void Visit(const Functions &...functions)
See Track::TypeSwitch.
Definition: Track.h:781
TrackIterRange< TrackType2 > Filter() const
Definition: Track.h:736
TrackIterRange Excluding(const TrackType *pExcluded) const
Definition: Track.h:773
TrackIterRange operator-(const Predicate2 &pred2) const
Definition: Track.h:719
TrackIterRange StartingWith(const Track *pTrack) const
Definition: Track.h:744
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
Definition: Track.h:803
TrackListEvent(const TrackListEvent &)=default
const int mExtra
Definition: Track.h:839
const std::weak_ptr< Track > mpTrack
Definition: Track.h:838
const Type mType
Definition: Track.h:837
@ RESIZING
Posted when some track changed its height.
Definition: Track.h:816
@ SELECTION_CHANGE
Posted when the set of selected tracks changes.
Definition: Track.h:806
@ DELETION
Posted when a track has been deleted from a tracklist. Also posted when one track replaces another.
Definition: Track.h:825
@ ADDITION
Posted when a track has been added to a tracklist. Also posted when one track replaces another.
Definition: Track.h:819
@ PERMUTED
Posted when tracks are reordered but otherwise unchanged.
Definition: Track.h:813
@ TRACK_DATA_CHANGE
Posted when certain fields of a track change.
Definition: Track.h:809
TrackListEvent(Type type, const std::weak_ptr< Track > &pTrack={}, int extra=-1)
Definition: Track.h:828
Select only the subsequence of the type list satisfying the predicate.
Definition: TypeList.h:500
A convenience for defining iterators that return rvalue types, so that they cooperate correctly with ...
Definition: IteratorX.h:25