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 <atomic>
15#include <utility>
16#include <vector>
17#include <list>
18#include <functional>
19#include <wx/longlong.h>
20
21#include "ClientData.h"
22#include "Observer.h"
23// TrackAttachment needs to be a complete type for the Windows build, though
24// not the others, so there is a nested include here:
25#include "TrackAttachment.h"
26#include "TypeEnumerator.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;
41struct UndoStackElem;
42
43using ListOfTracks = std::list< std::shared_ptr< Track > >;
44
46
49std::pair< ListOfTracks::iterator, ListOfTracks* >;
50
51inline bool operator == (const TrackNodePointer &a, const TrackNodePointer &b)
52{ return a.second == b.second && a.first == b.first; }
53
54inline bool operator != (const TrackNodePointer &a, const TrackNodePointer &b)
55{ return !(a == b); }
56
58BEGIN_TYPE_ENUMERATION(TrackTypeTag)
59
60
62
63#define ENUMERATE_TRACK_TYPE(T) ENUMERATE_TYPE(TrackTypeTag, T)
64
65// forward declarations, so we can make them friends
66template<typename T>
67 std::enable_if_t< std::is_pointer_v<T>, T >
68 track_cast(Track *track);
69
70template<typename T>
71 std::enable_if_t<
72 std::is_pointer_v<T> &&
73 std::is_const_v< std::remove_pointer_t< T > >,
74 T
75 >
76 track_cast(const Track *track);
77
79
87{
88public:
89 TrackId() : mValue(-1) {}
90 explicit TrackId (long value) : mValue(value) {}
91
92 bool operator == (const TrackId &other) const
93 { return mValue == other.mValue; }
94
95 bool operator != (const TrackId &other) const
96 { return mValue != other.mValue; }
97
98 // Define this in case you want to key a std::map on TrackId
99 // The operator does not mean anything else
100 bool operator < (const TrackId &other) const
101 { return mValue < other.mValue; }
102
103private:
104 long mValue;
105};
106
108struct TRACK_API TrackIntervalData {
110};
111
113
115public:
116
118 ConstTrackInterval( double start, double end,
119 std::unique_ptr<TrackIntervalData> pExtra = {} )
120 : start{ start }, end{ end }, pExtra{ std::move( pExtra ) }
121 {
122 wxASSERT( start <= end );
123 }
124
127
128 double Start() const { return start; }
129 double End() const { return end; }
130 const TrackIntervalData *Extra() const { return pExtra.get(); }
131
132private:
133 double start, end;
134protected:
135 // TODO C++17: use std::any instead
136 std::unique_ptr< TrackIntervalData > pExtra;
137};
138
140
142public:
144
147
148 TrackIntervalData *Extra() const { return pExtra.get(); }
149};
150
154>;
155
157class TRACK_API Track /* not final */
158 : public XMLTagHandler
159 , public AttachedTrackObjects
160 , public std::enable_shared_from_this<Track> // see SharedPointer()
161{
162protected:
164
169public:
170
172 enum class LinkType : int {
173 None = 0, //< No linkage
174 Group = 2, //< Tracks are grouped together
175 Aligned, //< Tracks are grouped and changes should be synchronized
176 };
177
178 struct ChannelGroupData;
179
183 >;
184
185 // Structure describing data common to channels of a group of tracks
186 // Should be deep-copyable (think twice before adding shared pointers!)
188 wxString mName;
189 LinkType mLinkType{ LinkType::None };
190 bool mSelected{ false };
191 };
192
193private:
194
195 friend class TrackList;
196
197 private:
199
200 std::unique_ptr<ChannelGroupData> mpGroupData;
201
202 protected:
203 std::weak_ptr<TrackList> mList;
205
207 int mIndex;
208
209 public:
210
213
214 TrackId GetId() const { return mId; }
215 private:
216 void SetId( TrackId id ) { mId = id; }
217 public:
218
219 // Given a bare pointer, find a shared_ptr. Undefined results if the track
220 // is not yet managed by a shared_ptr. Undefined results if the track is
221 // not really of the subclass. (That is, trusts the caller and uses static
222 // not dynamic casting.)
223 template<typename Subclass = Track>
224 inline std::shared_ptr<Subclass> SharedPointer()
225 {
226 // shared_from_this is injected into class scope by base class
227 // std::enable_shared_from_this<Track>
228 return std::static_pointer_cast<Subclass>( shared_from_this() );
229 }
230
231 template<typename Subclass = const Track>
232 inline auto SharedPointer() const ->
233 std::enable_if_t<
234 std::is_const_v<Subclass>, std::shared_ptr<Subclass>
235 >
236 {
237 // shared_from_this is injected into class scope by base class
238 // std::enable_shared_from_this<Track>
239 return std::static_pointer_cast<Subclass>( shared_from_this() );
240 }
241
242 // Static overloads of SharedPointer for when the pointer may be null
243 template<typename Subclass = Track>
244 static inline std::shared_ptr<Subclass> SharedPointer( Track *pTrack )
245 { return pTrack ? pTrack->SharedPointer<Subclass>() : nullptr; }
246
247 template<typename Subclass = const Track>
248 static inline std::shared_ptr<Subclass> SharedPointer( const Track *pTrack )
249 { return pTrack ? pTrack->SharedPointer<Subclass>() : nullptr; }
250
251 // Find anything registered with TrackList::RegisterPendingChangedTrack and
252 // not yet cleared or applied; if no such exists, return this track
253 std::shared_ptr<Track> SubstitutePendingChangedTrack();
254 std::shared_ptr<const Track> SubstitutePendingChangedTrack() const;
255
256 // If this track is a pending changed track, return the corresponding
257 // original; else return this track
258 std::shared_ptr<const Track> SubstituteOriginalTrack() const;
259
262 using Intervals = std::vector< Interval >;
264 using ConstIntervals = std::vector< ConstInterval >;
265
267
268 struct TypeNames {
269 wxString info;
270 wxString property;
272 };
273 struct TypeInfo {
275 bool concrete = false;
276 const TypeInfo *pBaseInfo = nullptr;
277
278 bool IsBaseOf(const TypeInfo &other) const
279 {
280 for (auto pInfo = &other;
281 pInfo; pInfo = pInfo->pBaseInfo)
282 if (this == pInfo)
283 return true;
284 return false;
285 }
286 };
287 virtual const TypeInfo &GetTypeInfo() const = 0;
288 static const TypeInfo &ClassTypeInfo();
289 virtual const TypeNames &GetTypeNames() const
290 { return GetTypeInfo().names; }
291
293 virtual bool SupportsBasicEditing() const;
294
295 using Holder = std::shared_ptr<Track>;
296
298
299 virtual Holder PasteInto( AudacityProject & ) const = 0;
300
302
305 virtual ConstIntervals GetIntervals() const;
306
310 virtual Intervals GetIntervals();
311
312 public:
313 mutable std::pair<int, int> vrulerSize;
314
315public:
316 static void FinishCopy (const Track *n, Track *dest);
317
319
325 virtual bool LinkConsistencyFix(bool doFix = true, bool completeList = true);
326
328 bool LinkConsistencyCheck(bool completeList)
329 { return const_cast<Track*>(this)->LinkConsistencyFix(false, completeList); }
330
331 bool HasOwner() const { return static_cast<bool>(GetOwner());}
332
333 std::shared_ptr<TrackList> GetOwner() const { return mList.lock(); }
334
335 LinkType GetLinkType() const noexcept;
337 bool IsAlignedWithLeader() const;
338
339 ChannelGroupData &GetGroupData();
340 const ChannelGroupData &GetGroupData() const;
341
342protected:
343
347 void SetLinkType(LinkType linkType, bool completeList = true);
348
349private:
350 int GetIndex() const;
351 void SetIndex(int index);
352
353 ChannelGroupData &MakeGroupData();
357 void DoSetLinkType(LinkType linkType, bool completeList = true);
358
359 Track* GetLinkedTrack() const;
361 bool HasLinkedTrack() const noexcept;
362
364 TrackNodePointer GetNode() const;
366 void SetOwner
367 (const std::weak_ptr<TrackList> &list, TrackNodePointer node);
368
369 // Keep in Track
370
371 protected:
372 double mOffset;
373
374 public:
375
376 Track();
377 Track(const Track &orig, ProtectedCreationArg&&);
378 Track& operator =(const Track &orig) = delete;
379
380 virtual ~ Track();
381
382 void Init(const Track &orig);
383
384 // public nonvirtual duplication function that invokes Clone():
385 virtual Holder Duplicate() const;
386
388 const wxString &GetName() const;
389 void SetName( const wxString &n );
390
392 bool GetSelected() const;
393 virtual void SetSelected(bool s);
394
395 // The argument tells whether the last undo history state should be
396 // updated for the appearance change
397 void EnsureVisible( bool modifyState = false );
398
399public:
400
401 virtual double GetOffset() const = 0;
402
403 void Offset(double t) { SetOffset(GetOffset() + t); }
404 virtual void SetOffset (double o) { mOffset = o; }
405
406 // Create a NEW track and modify this track
407 // Return non-NULL or else throw
408 // May assume precondition: t0 <= t1
409 virtual Holder Cut(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
410
411 // Create a NEW track and don't modify this track
412 // Return non-NULL or else throw
413 // Note that subclasses may want to distinguish tracks stored in a clipboard
414 // from those stored in a project
415 // May assume precondition: t0 <= t1
416 // Should invoke Track::Init
417 virtual Holder Copy
418 (double WXUNUSED(t0), double WXUNUSED(t1), bool forClipboard = true) const = 0;
419
420 // May assume precondition: t0 <= t1
421 virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
422
423 virtual void Paste(double WXUNUSED(t), const Track * WXUNUSED(src)) = 0;
424
425 // This can be used to adjust a sync-lock selected track when the selection
426 // is replaced by one of a different length.
427 virtual void SyncLockAdjust(double oldT1, double newT1);
428
429 // May assume precondition: t0 <= t1
430 virtual void Silence(double WXUNUSED(t0), double WXUNUSED(t1)) = 0;
431
432 // May assume precondition: t0 <= t1
433 virtual void InsertSilence(double WXUNUSED(t), double WXUNUSED(len)) = 0;
434
435private:
436 // Subclass responsibility implements only a part of Duplicate(), copying
437 // the track data proper (not associated data such as for groups and views):
438 virtual Holder Clone() const = 0;
439
440 template<typename T>
441 friend std::enable_if_t< std::is_pointer_v<T>, T >
442 track_cast(Track *track);
443 template<typename T>
444 friend std::enable_if_t<
445 std::is_pointer_v<T> &&
446 std::is_const_v< std::remove_pointer_t< T > >,
447 T
448 >
449 track_cast(const Track *track);
450
451public:
452 bool SameKindAs(const Track &track) const
453 { return &GetTypeInfo() == &track.GetTypeInfo(); }
454
456 template < typename R = void >
457 using Continuation = std::function< R() >;
460
461private:
463 template< typename ...Params >
464 struct Executor{};
465
467
468 struct Dispatcher {
470 template< typename Tag, typename R, typename ArgumentType,
471 typename Function, typename ...Functions >
473 {
475 std::conditional_t< std::is_const_v<ArgumentType>,
476 const Track, Track >;
477
479 using Tail = Executor< Tag, R, ArgumentType, Functions... >;
481 enum : unsigned { SetUsed = Tail::SetUsed << 1 };
482
484 R operator ()
485 (QualifiedTrackType *pTrack,
486 const Function &, const Functions &...functions) const
487 { return Tail{}( pTrack, functions... ); }
488 };
489
491 template< typename R, typename BaseClass, typename ArgumentType,
492 typename Function >
494 {
496 std::conditional_t< std::is_const_v<ArgumentType>,
497 const Track, Track >;
499 std::conditional_t< std::is_const_v<ArgumentType>,
500 const BaseClass, BaseClass >;
501
503 enum : unsigned { SetUsed = 1u };
504
506 R operator ()
507 (QualifiedTrackType *pTrack, const Function &function, ...) const
508 { return function( static_cast<QualifiedBaseClass *>(pTrack) ); }
509 };
510
512 template< typename Tag,
513 typename R, typename BaseClass, typename ArgumentType,
514 typename Function, typename ...Functions >
516 {
518 std::conditional_t< std::is_const_v<ArgumentType>,
519 const Track, Track >;
521 std::conditional_t< std::is_const_v<ArgumentType>,
522 const BaseClass, BaseClass >;
523
525 using Tail = Executor< Tag, R, ArgumentType, Functions... >;
527 enum : unsigned { SetUsed = (Tail::SetUsed << 1) | 1u };
528
530 R operator ()
531 (QualifiedTrackType *pTrack, const Function &function,
532 const Functions &...functions) const
533 {
534 auto continuation = Continuation<R>{ [&] {
535 return Tail{}( pTrack, functions... );
536 } };
537 return function( static_cast<QualifiedBaseClass *>(pTrack),
538 continuation );
539 }
540 };
541
543 template< typename ... > struct Switch {};
544
546
547 template<typename Tag, typename R, typename ArgumentType>
548 struct Switch<Tag, R, ArgumentType, TypeList::Nil>
549 {
551 template< typename Function, typename ...Functions >
552 static auto test()
553 -> inapplicable< Tag, R, ArgumentType, Function, Functions... >;
554 };
555
557
558 template<typename Tag, typename R, typename ArgumentType,
559 typename BaseClass, typename ...BaseClasses>
560 struct Switch<Tag, R, ArgumentType,
561 TypeList::List<BaseClass, BaseClasses...>>
562 {
564 std::conditional_t< std::is_const_v<ArgumentType>,
565 const BaseClass, BaseClass >;
566
568 using Retry =
569 Switch<Tag, R, ArgumentType, TypeList::List<BaseClasses...>>;
570
572
574 template< typename Function, typename ...Functions >
575 static auto test( const void * )
576 -> decltype( Retry::template test< Function, Functions... >() );
577
579
582 template< typename Function, typename ...Functions >
583 static auto test( std::true_type * )
584 -> decltype(
585 (void) std::declval<Function>()
586 ( (QualifiedBaseClass*)nullptr ),
588 );
589
591
595 template< typename Function, typename ...Functions >
596 static auto test( std::true_type * )
597 -> decltype(
598 (void) std::declval<Function>()
599 ( (QualifiedBaseClass*)nullptr,
600 std::declval< Continuation<R> >() ),
601 applicable2< Tag, R, BaseClass, ArgumentType,
602 Function, Functions... >{}
603 );
604
606 static constexpr bool Compatible =
607 std::is_base_of_v<BaseClass, ArgumentType>;
609 template< typename Function, typename ...Functions >
610 static auto test()
611 -> decltype(
612 test< Function, Functions... >(
613 (std::integral_constant<bool, Compatible>*)nullptr) );
614 };
615 };
616
618 template< typename Tag, typename R, typename ArgumentType >
619 struct Executor< Tag, R, ArgumentType >
620 {
621 using NominalType = ArgumentType;
623 enum : unsigned { SetUsed = 0 };
625 R operator () (const void *, ...)
626 {
627 if constexpr (std::is_void_v<R>)
628 return;
629 else
630 return R{};
631 }
632 };
633
635
636 template< typename Tag, typename R, typename ArgumentType,
637 typename Function, typename ...Functions >
638 struct Executor< Tag, R, ArgumentType, Function, Functions... >
639 : decltype(
640 Dispatcher::Switch<Tag, R, ArgumentType,
641 // Each track subtype occurs earlier than its base classes in this
642 // list of types
643 TypeList::Reverse_t<
644 typename TypeEnumerator::CollectTypes<TrackTypeTag, Tag>::type>
645 >::template test<Function, Functions... >())
646 {
647 using NominalType = ArgumentType;
648 };
649
650public:
651
652 template<typename TrackType>
653 static void checkTrackType()
654 {
655 static_assert(
656 std::is_same_v<Track, TrackType> ||
657 std::is_same_v<const Track, TrackType>, "Error" );
658 }
659 template<typename R, typename TrackType, typename... Functions>
660 static R CallExecutor(R*, std::tuple<>*, TrackType&, const Functions&...)
661 {
662 // This overload is needed so that the other overload of CallExecutor
663 // compiles, but it should never be reached at run-time, because an
664 // Executor generated for (const) Track should have been the catch-all.
665 wxASSERT(false);
666 checkTrackType<TrackType>();
667 if constexpr (std::is_void_v<R>)
668 return;
669 else
670 return R{};
671 }
672 template<
673 typename R, typename TrackType, typename... Functions,
674 typename Executor, typename... Executors>
675 static R CallExecutor(
676 R*, std::tuple<Executor, Executors...>*, TrackType &track,
677 const Functions &...functions)
678 {
679 checkTrackType<TrackType>();
680 const auto &info = Executor::NominalType::ClassTypeInfo();
681 // Dynamic type test of track
682 // Assumes Executor classes are sequenced with more specific accepted
683 // types earlier
684 if ( info.IsBaseOf(track.GetTypeInfo()) )
685 // Dispatch to an Executor that knows which of functions applies
686 return Executor{}(&track, functions...);
687 else
688 // Recur, with fewer candidate Executors and all of functions
689 return CallExecutor( (R*)nullptr,
690 (std::tuple<Executors...>*)nullptr, track, functions...);
691 }
692
693 template<typename ...Executors>
694 static constexpr unsigned UsedCases(std::tuple<Executors...>*)
695 {
696 return (Executors::SetUsed | ...); // My very first fold expression :-)
697 }
698
700 template<
701 typename Tag,
702 bool IsConst,
703 typename R,
704 typename ...TrackTypes,
705 typename ...Functions
706 >
707 static R DoTypeSwitch(
708 std::conditional_t<IsConst, const Track, Track> &track,
710 const Functions &...functions )
711 {
712 // Generate Executor classes, for each of TrackTypes,
713 // each zero-sized and with an operator () that calls the correct
714 // one of functions, assuming the track is of the corresponding type
715 using Executors = std::tuple< Executor<
716 Tag, R,
717 std::conditional_t<IsConst, const TrackTypes, TrackTypes>,
718 Functions...
719 >... >;
720 // Don't even construct the tuple of zero-sized types, just point
721 constexpr Executors *executors = nullptr;
722
723 // Compile time reachability check of the given functions
724 enum { All = sizeof...( functions ) };
725 static_assert( (1u << All) - 1u == UsedCases(executors),
726 "Uncallable case in Track::TypeSwitch");
727
728 // Do dynamic dispatch to one of the Executors
729 return CallExecutor((R *)nullptr, executors, track, functions...);
730 }
731
733
751 template<
752 typename R = void,
753 typename ...Functions
754 >
755 R TypeSwitch(const Functions &...functions)
756 {
757 struct Tag : TrackTypeTag {};
758 // Collect all concrete and abstract track types known at compile time
759 using TrackTypes = TypeList::Reverse_t<
761 // Generate a function that dispatches dynamically on track type
762 return DoTypeSwitch<Tag, false, R>(*this, TrackTypes{}, functions...);
763 }
764
768 template<
769 typename R = void,
770 typename ...Functions
771 >
772 R TypeSwitch(const Functions &...functions) const
773 {
774 struct Tag : TrackTypeTag {};
775 // Collect all concrete and abstract track types known at compile time
776 using TrackTypes = TypeList::Reverse_t<
778 // Generate a function that dispatches dynamically on track type
779 return DoTypeSwitch<Tag, true, R>(*this, TrackTypes{}, functions...);
780 }
781
782 // XMLTagHandler callback methods -- NEW virtual for writing
783 virtual void WriteXML(XMLWriter &xmlFile) const = 0;
784
785 // Returns true if an error was encountered while trying to
786 // open the track from XML
787 virtual bool GetErrorOpening() { return false; }
788
789 virtual double GetStartTime() const = 0;
790 virtual double GetEndTime() const = 0;
791
792 // Send a notification to subscribers when state of the track changes
793 // To do: define values for the argument to distinguish different parts
794 // of the state
795 void Notify(bool allChannels, int code = -1);
796
797 // An always-true predicate useful for defining iterators
798 bool Any() const;
799
800 // Frequently useful operands for + and -
801 bool IsSelected() const;
802 bool IsLeader() const;
803 bool IsSelectedLeader() const;
804
805 // Cause this track and following ones in its TrackList to adjust
806 void AdjustPositions();
807
808 // Serialize, not with tags of its own, but as attributes within a tag.
809 void WriteCommonXMLAttributes(
810 XMLWriter &xmlFile, bool includeNameAndSelected = true) const;
811
812 // Return true iff the attribute is recognized.
813 bool HandleCommonXMLAttribute(const std::string_view& attr, const XMLAttributeValueView& valueView);
814};
815
817
819
826template<typename T>
827 inline std::enable_if_t< std::is_pointer_v<T>, T >
829{
830 using BareType = std::remove_pointer_t< T >;
831 if (track &&
832 BareType::ClassTypeInfo().IsBaseOf(track->GetTypeInfo() ))
833 return reinterpret_cast<T>(track);
834 else
835 return nullptr;
836}
837
840template<typename T>
841 inline std::enable_if_t<
842 std::is_pointer_v<T> && std::is_const_v< std::remove_pointer_t< T > >,
843 T
844 >
845 track_cast(const Track *track)
846{
847 using BareType = std::remove_pointer_t< T >;
848 if (track &&
849 BareType::ClassTypeInfo().IsBaseOf(track->GetTypeInfo() ))
850 return reinterpret_cast<T>(track);
851 else
852 return nullptr;
853}
854
855template < typename TrackType > struct TrackIterRange;
856
858
865template <
866 typename TrackType
868 : public ValueIterator< TrackType *, std::bidirectional_iterator_tag >
869{
870public:
872 using FunctionType = std::function< bool(
873 std::add_pointer_t< std::add_const_t< std::remove_pointer_t<TrackType> > >
874 ) >;
875
879 TrackNodePointer iter,
881 FunctionType pred = {}
882 )
883 : mBegin( begin ), mIter( iter ), mEnd( end )
884 , mPred( std::move(pred) )
885 {
886 // Establish the class invariant
887 if (this->mIter != this->mEnd && !this->valid())
888 this->operator ++ ();
889 }
890
892
894 template < typename Predicate2 >
895 TrackIter Filter( const Predicate2 &pred2 ) const
896 {
897 return { this->mBegin, this->mIter, this->mEnd, pred2 };
898 }
899
901
903 template < typename TrackType2 >
904 auto Filter() const
905 -> std::enable_if_t<
906 std::is_base_of_v< TrackType, TrackType2 > &&
907 (!std::is_const_v<TrackType> ||
908 std::is_const_v<TrackType2>),
909 TrackIter< TrackType2 >
910 >
911 {
912 return { this->mBegin, this->mIter, this->mEnd, this->mPred };
913 }
914
916 { return this->mPred; }
917
919
921 {
922 // Maintain the class invariant
923 if (this->mIter != this->mEnd) do
924 ++this->mIter.first;
925 while (this->mIter != this->mEnd && !this->valid() );
926 return *this;
927 }
928
931 {
932 TrackIter result { *this };
933 this-> operator ++ ();
934 return result;
935 }
936
938
940 {
941 // Maintain the class invariant
942 do {
943 if (this->mIter == this->mBegin)
944 // Go circularly
945 this->mIter = this->mEnd;
946 else
947 --this->mIter.first;
948 } while (this->mIter != this->mEnd && !this->valid() );
949 return *this;
950 }
951
954 {
955 TrackIter result { *this };
956 this->operator -- ();
957 return result;
958 }
959
961
962 TrackType *operator * () const
963 {
964 if (this->mIter == this->mEnd)
965 return nullptr;
966 else
967 // Other methods guarantee that the cast is correct
968 // (provided no operations on the TrackList invalidated
969 // underlying iterators or replaced the tracks there)
970 return static_cast< TrackType * >( &**this->mIter.first );
971 }
972
975 long amount
976 ) const
977 {
978 auto copy = *this;
979 std::advance( copy, amount );
980 return copy;
981 }
982
984 friend inline bool operator == (TrackIter a, TrackIter b)
985 {
986 // Assume the predicate is not stateful. Just compare the iterators.
987 return
988 a.mIter == b.mIter
989 // Assume this too:
990 // && a.mBegin == b.mBegin && a.mEnd == b.mEnd
991 ;
992 }
993
995 friend inline bool operator != (TrackIter a, TrackIter b)
996 {
997 return !(a == b);
998 }
999
1000private:
1006 bool valid() const
1007 {
1008 // assume mIter != mEnd
1009 const auto pTrack = track_cast< TrackType * >( &**this->mIter.first );
1010 if (!pTrack)
1011 return false;
1012 return !this->mPred || this->mPred( pTrack );
1013 }
1014
1017
1023};
1024
1026template <
1027 typename TrackType // Track or a subclass, maybe const-qualified
1029 : public IteratorRange< TrackIter< TrackType > >
1030{
1034 : IteratorRange< TrackIter< TrackType > >
1035 ( begin, end )
1036 {}
1037
1038 // Conjoin the filter predicate with another predicate
1039 // Read + as "and"
1040 template< typename Predicate2 >
1041 TrackIterRange operator + ( const Predicate2 &pred2 ) const
1042 {
1043 const auto &pred1 = this->first.GetPredicate();
1044 using Function = typename TrackIter<TrackType>::FunctionType;
1045 const auto &newPred = pred1
1046 ? Function{ [=] (typename Function::argument_type track) {
1047 return pred1(track) && pred2(track);
1048 } }
1049 : Function{ pred2 };
1050 return {
1051 this->first.Filter( newPred ),
1052 this->second.Filter( newPred )
1053 };
1054 }
1055
1056 // Specify the added conjunct as a pointer to member function
1057 // Read + as "and"
1058 template< typename R, typename C >
1059 TrackIterRange operator + ( R ( C ::* pmf ) () const ) const
1060 {
1061 return this->operator + ( std::mem_fn( pmf ) );
1062 }
1063
1064 // Conjoin the filter predicate with the negation of another predicate
1065 // Read - as "and not"
1066 template< typename Predicate2 >
1067 TrackIterRange operator - ( const Predicate2 &pred2 ) const
1068 {
1069 using ArgumentType =
1070 typename TrackIterRange::iterator::FunctionType::argument_type;
1071 auto neg = [=] (ArgumentType track) { return !pred2( track ); };
1072 return this->operator + ( neg );
1073 }
1074
1075 // Specify the negated conjunct as a pointer to member function
1076 // Read - as "and not"
1077 template< typename R, typename C >
1078 TrackIterRange operator - ( R ( C ::* pmf ) () const ) const
1079 {
1080 return this->operator + ( std::not1( std::mem_fn( pmf ) ) );
1081 }
1082
1083 template< typename TrackType2 >
1085 {
1086 return {
1087 this-> first.template Filter< TrackType2 >(),
1088 this->second.template Filter< TrackType2 >()
1089 };
1090 }
1091
1092 TrackIterRange StartingWith( const Track *pTrack ) const
1093 {
1094 auto newBegin = this->find( pTrack );
1095 // More careful construction is needed so that the independent
1096 // increment and decrement of each iterator in the NEW pair
1097 // has the expected behavior at boundaries of the range
1098 return {
1099 { newBegin.mIter, newBegin.mIter, this->second.mEnd,
1100 this->first.GetPredicate() },
1101 { newBegin.mIter, this->second.mIter, this->second.mEnd,
1102 this->second.GetPredicate() }
1103 };
1104 }
1105
1106 TrackIterRange EndingAfter( const Track *pTrack ) const
1107 {
1108 const auto newEnd = this->reversal().find( pTrack ).base();
1109 // More careful construction is needed so that the independent
1110 // increment and decrement of each iterator in the NEW pair
1111 // has the expected behavior at boundaries of the range
1112 return {
1113 { this->first.mBegin, this->first.mIter, newEnd.mIter,
1114 this->first.GetPredicate() },
1115 { this->first.mBegin, newEnd.mIter, newEnd.mIter,
1116 this->second.GetPredicate() }
1117 };
1118 }
1119
1120 // Exclude one given track
1121 TrackIterRange Excluding ( const TrackType *pExcluded ) const
1122 {
1123 return this->operator - (
1124 [=](const Track *pTrack){ return pExcluded == pTrack; } );
1125 }
1126
1128 template< typename ...Functions >
1129 void Visit(const Functions &...functions)
1130 {
1131 for (auto track : *this)
1132 track->TypeSwitch(functions...);
1133 }
1134
1136
1137 template< typename Flag, typename ...Functions >
1138 void VisitWhile(Flag &flag, const Functions &...functions)
1139 {
1140 if ( flag ) for (auto track : *this) {
1141 track->TypeSwitch(functions...);
1142 if (!flag)
1143 break;
1144 }
1145 }
1146};
1147
1148
1151{
1152 enum Type {
1155
1158
1161
1163
1165
1168
1171
1173
1177 };
1178
1180 const std::weak_ptr<Track> &pTrack = {}, int extra = -1)
1181 : mType{ type }
1182 , mpTrack{ pTrack }
1183 , mExtra{ extra }
1184 {}
1185
1186 TrackListEvent( const TrackListEvent& ) = default;
1187
1189 const std::weak_ptr<Track> mpTrack;
1190 const int mExtra;
1191};
1192
1196class TRACK_API TrackList final
1197 : public Observer::Publisher<TrackListEvent>
1198 , public ListOfTracks
1199 , public std::enable_shared_from_this<TrackList>
1200 , public ClientData::Base
1201{
1202 // privatize this, make you use Add instead:
1203 using ListOfTracks::push_back;
1204
1205 // privatize this, make you use Swap instead:
1206 using ListOfTracks::swap;
1207
1208 // Disallow copy
1209 TrackList(const TrackList &that) = delete;
1210 TrackList &operator= (const TrackList&) = delete;
1211
1212 // No need for move, disallow it
1213 TrackList(TrackList &&that) = delete;
1214 TrackList& operator= (TrackList&&) = delete;
1215
1216 void clear() = delete;
1217
1218 public:
1219 static TrackList &Get( AudacityProject &project );
1220 static const TrackList &Get( const AudacityProject &project );
1221
1222 static TrackList *FindUndoTracks(const UndoStackElem &state);
1223
1224 // Create an empty TrackList
1225 // Don't call directly -- use Create() instead
1226 explicit TrackList( AudacityProject *pOwner );
1227
1228 // Create an empty TrackList
1229 static std::shared_ptr<TrackList> Create( AudacityProject *pOwner );
1230
1231 // Move is defined in terms of Swap
1232 void Swap(TrackList &that);
1233
1234 // Destructor
1235 virtual ~TrackList();
1236
1237 // Find the owning project, which may be null
1238 AudacityProject *GetOwner() { return mOwner; }
1239 const AudacityProject *GetOwner() const { return mOwner; }
1240
1247 wxString MakeUniqueTrackName(const wxString& baseTrackName) const;
1248
1249 // Iteration
1250
1251 // Hide the inherited begin() and end()
1255 iterator begin() { return Any().begin(); }
1256 iterator end() { return Any().end(); }
1257 const_iterator begin() const { return Any().begin(); }
1258 const_iterator end() const { return Any().end(); }
1259 const_iterator cbegin() const { return begin(); }
1260 const_iterator cend() const { return end(); }
1261
1263 template < typename TrackType = Track >
1264 auto Find(Track *pTrack)
1266 {
1267 if (!pTrack || pTrack->GetOwner().get() != this)
1268 return EndIterator<TrackType>();
1269 else
1270 return MakeTrackIterator<TrackType>( pTrack->GetNode() );
1271 }
1272
1274
1275 template < typename TrackType = const Track >
1276 auto Find(const Track *pTrack) const
1277 -> std::enable_if_t< std::is_const_v<TrackType>,
1279 >
1280 {
1281 if (!pTrack || pTrack->GetOwner().get() != this)
1282 return EndIterator<TrackType>();
1283 else
1284 return MakeTrackIterator<TrackType>( pTrack->GetNode() );
1285 }
1286
1287 // If the track is not an audio track, or not one of a group of channels,
1288 // return the track itself; else return the first channel of its group --
1289 // in either case as an iterator that will only visit other leader tracks.
1290 // (Generalizing away from the assumption of at most stereo)
1291 TrackIter< Track > FindLeader( Track *pTrack );
1292
1294 FindLeader( const Track *pTrack ) const
1295 {
1296 return const_cast<TrackList*>(this)->
1297 FindLeader( const_cast<Track*>(pTrack) ).Filter< const Track >();
1298 }
1299
1300
1301 template < typename TrackType = Track >
1302 auto Any()
1304 {
1305 return Tracks< TrackType >();
1306 }
1307
1308 template < typename TrackType = const Track >
1309 auto Any() const
1310 -> std::enable_if_t< std::is_const_v<TrackType>,
1311 TrackIterRange< TrackType >
1312 >
1313 {
1314 return Tracks< TrackType >();
1315 }
1316
1317 // Abbreviating some frequently used cases
1318 template < typename TrackType = Track >
1321 {
1322 return Tracks< TrackType >( &Track::IsSelected );
1323 }
1324
1325 template < typename TrackType = const Track >
1326 auto Selected() const
1327 -> std::enable_if_t< std::is_const_v<TrackType>,
1328 TrackIterRange< TrackType >
1329 >
1330 {
1331 return Tracks< TrackType >( &Track::IsSelected );
1332 }
1333
1334
1335 template < typename TrackType = Track >
1336 auto Leaders()
1338 {
1339 return Tracks< TrackType >( &Track::IsLeader );
1340 }
1341
1342 template < typename TrackType = const Track >
1343 auto Leaders() const
1344 -> std::enable_if_t< std::is_const_v<TrackType>,
1345 TrackIterRange< TrackType >
1346 >
1347 {
1348 return Tracks< TrackType >( &Track::IsLeader );
1349 }
1350
1351
1352 template < typename TrackType = Track >
1355 {
1356 return Tracks< TrackType >( &Track::IsSelectedLeader );
1357 }
1358
1359 template < typename TrackType = const Track >
1360 auto SelectedLeaders() const
1361 -> std::enable_if_t< std::is_const_v<TrackType>,
1362 TrackIterRange< TrackType >
1363 >
1364 {
1365 return Tracks< TrackType >( &Track::IsSelectedLeader );
1366 }
1367
1368
1369 template<typename TrackType>
1370 static auto SingletonRange( TrackType *pTrack )
1372 {
1373 return pTrack->GetOwner()->template Any<TrackType>()
1374 .StartingWith( pTrack ).EndingAfter( pTrack );
1375 }
1376
1377
1378private:
1379 Track *DoAddToHead(const std::shared_ptr<Track> &t);
1380 Track *DoAdd(const std::shared_ptr<Track> &t);
1381
1382 template< typename TrackType, typename InTrackType >
1385 {
1386 // Assume iterator filters leader tracks
1387 if (*iter1) {
1388 return {
1389 iter1.Filter( &Track::Any )
1390 .template Filter<TrackType>(),
1391 (++iter1).Filter( &Track::Any )
1392 .template Filter<TrackType>()
1393 };
1394 }
1395 else
1396 // empty range
1397 return {
1398 iter1.template Filter<TrackType>(),
1399 iter1.template Filter<TrackType>()
1400 };
1401 }
1402
1403public:
1404 // Find an iterator range of channels including the given track.
1405 template< typename TrackType >
1406 static auto Channels( TrackType *pTrack )
1408 {
1409 return Channels_<TrackType>( pTrack->GetOwner()->FindLeader(pTrack) );
1410 }
1411
1413 static size_t NChannels(const Track &track)
1414 {
1415 return Channels(&track).size();
1416 }
1417
1419
1420 static bool SwapChannels(Track &track);
1421
1422 friend class Track;
1423
1425 void Permute(const std::vector<TrackNodePointer> &permutation);
1426
1427 Track *FindById( TrackId id );
1428
1430 template<typename TrackKind>
1431 TrackKind *AddToHead( const std::shared_ptr< TrackKind > &t )
1432 { return static_cast< TrackKind* >( DoAddToHead( t ) ); }
1433
1434 template<typename TrackKind>
1435 TrackKind *Add( const std::shared_ptr< TrackKind > &t )
1436 { return static_cast< TrackKind* >( DoAdd( t ) ); }
1437
1439 void UnlinkChannels(Track& track);
1448 bool MakeMultiChannelTrack(Track& first, int nChannels, bool aligned);
1449
1452 ListOfTracks::value_type Replace(
1453 Track * t, const ListOfTracks::value_type &with);
1454
1457
1459 void Clear(bool sendEvent = true);
1460
1461 bool CanMoveUp(Track * t) const;
1462 bool CanMoveDown(Track * t) const;
1463
1464 bool MoveUp(Track * t);
1465 bool MoveDown(Track * t);
1466 bool Move(Track * t, bool up) { return up ? MoveUp(t) : MoveDown(t); }
1467
1469 bool Contains(const Track * t) const;
1470
1471 // Return non-null only if the weak pointer is not, and the track is
1472 // owned by this list; constant time.
1473 template <typename Subclass>
1474 std::shared_ptr<Subclass> Lock(const std::weak_ptr<Subclass> &wTrack)
1475 {
1476 auto pTrack = wTrack.lock();
1477 if (pTrack) {
1478 auto pList = pTrack->mList.lock();
1479 if (pTrack && this == pList.get())
1480 return pTrack;
1481 }
1482 return {};
1483 }
1484
1485 bool empty() const;
1486 size_t NChannels() const;
1487 size_t Size() const { return Leaders().size(); }
1488
1489 double GetStartTime() const;
1490 double GetEndTime() const;
1491
1492 double GetMinOffset() const;
1493
1494private:
1495 using ListOfTracks::size;
1496
1497 // Visit all tracks satisfying a predicate, mutative access
1498 template <
1499 typename TrackType = Track,
1500 typename Pred =
1502 >
1503 auto Tracks( const Pred &pred = {} )
1505 {
1506 auto b = getBegin(), e = getEnd();
1507 return { { b, b, e, pred }, { b, e, e, pred } };
1508 }
1509
1510 // Visit all tracks satisfying a predicate, const access
1511 template <
1512 typename TrackType = const Track,
1513 typename Pred =
1515 >
1516 auto Tracks( const Pred &pred = {} ) const
1517 -> std::enable_if_t< std::is_const_v<TrackType>,
1519 >
1520 {
1521 auto b = const_cast<TrackList*>(this)->getBegin();
1522 auto e = const_cast<TrackList*>(this)->getEnd();
1523 return { { b, b, e, pred }, { b, e, e, pred } };
1524 }
1525
1526 Track *GetPrev(Track * t, bool linked = false) const;
1527 Track *GetNext(Track * t, bool linked = false) const;
1528
1529 template < typename TrackType >
1532 {
1533 auto b = const_cast<TrackList*>(this)->getBegin();
1534 auto e = const_cast<TrackList*>(this)->getEnd();
1535 return { b, iter, e };
1536 }
1537
1538 template < typename TrackType >
1541 {
1542 auto e = const_cast<TrackList*>(this)->getEnd();
1543 return { e, e, e };
1544 }
1545
1546 TrackIterRange< Track > EmptyRange() const;
1547
1549 { return (p.second == this && p.first == ListOfTracks::end())
1550 || (p.second == &mPendingUpdates && p.first == mPendingUpdates.end()); }
1552 { return { const_cast<TrackList*>(this)->ListOfTracks::end(),
1553 const_cast<TrackList*>(this)}; }
1555 { return { const_cast<TrackList*>(this)->ListOfTracks::begin(),
1556 const_cast<TrackList*>(this)}; }
1557
1560 {
1561 if ( isNull(p) )
1562 return p;
1563 auto q = p;
1564 ++q.first;
1565 return q;
1566 }
1567
1570 {
1571 if (p == getBegin())
1572 return getEnd();
1573 else {
1574 auto q = p;
1575 --q.first;
1576 return q;
1577 }
1578 }
1579
1580 void RecalcPositions(TrackNodePointer node);
1581 void QueueEvent(TrackListEvent event);
1582 void SelectionEvent(Track &track);
1583 void PermutationEvent(TrackNodePointer node);
1584 void DataEvent(
1585 const std::shared_ptr<Track> &pTrack, bool allChannels, int code );
1586 void EnsureVisibleEvent(
1587 const std::shared_ptr<Track> &pTrack, bool modifyState );
1588 void DeletionEvent(std::weak_ptr<Track> node, bool duringReplace);
1589 void AdditionEvent(TrackNodePointer node);
1590 void ResizingEvent(TrackNodePointer node);
1591
1592 void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);
1593
1594 // Nondecreasing during the session.
1595 // Nonpersistent.
1596 // Used to assign ids to added tracks.
1597 static long sCounter;
1598
1599public:
1600 using Updater = std::function< void(Track &dest, const Track &src) >;
1601 // Start a deferred update of the project.
1602 // The return value is a duplicate of the given track.
1603 // While ApplyPendingTracks or ClearPendingTracks is not yet called,
1604 // there may be other direct changes to the project that push undo history.
1605 // Meanwhile the returned object can accumulate other changes for a deferred
1606 // push, and temporarily shadow the actual project track for display purposes.
1607 // The Updater function, if not null, merges state (from the actual project
1608 // into the pending track) which is not meant to be overridden by the
1609 // accumulated pending changes.
1610 // To keep the display consistent, the Y and Height values, minimized state,
1611 // and Linked state must be copied, and this will be done even if the
1612 // Updater does not do it.
1613 // Pending track will have the same TrackId as the actual.
1614 // Pending changed tracks will not occur in iterations.
1615 std::shared_ptr<Track> RegisterPendingChangedTrack(
1617 Track *src
1618 );
1619
1620 // Like the previous, but for a NEW track, not a replacement track. Caller
1621 // supplies the track, and there are no updates.
1622 // Pending track will have an unassigned TrackId.
1623 // Pending changed tracks WILL occur in iterations, always after actual
1624 // tracks, and in the sequence that they were added. They can be
1625 // distinguished from actual tracks by TrackId.
1626 void RegisterPendingNewTrack( const std::shared_ptr<Track> &pTrack );
1627
1628 // Invoke the updaters of pending tracks. Pass any exceptions from the
1629 // updater functions.
1630 void UpdatePendingTracks();
1631
1632 // Forget pending track additions and changes;
1633 // if requested, give back the pending added tracks.
1634 void ClearPendingTracks( ListOfTracks *pAdded = nullptr );
1635
1636 // Change the state of the project.
1637 // Strong guarantee for project state in case of exceptions.
1638 // Will always clear the pending updates.
1639 // Return true if the state of the track list really did change.
1640 bool ApplyPendingTracks();
1641
1642 bool HasPendingTracks() const;
1643
1644private:
1646
1648
1651 std::vector< Updater > mUpdaters;
1652};
1653
1654#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:154
#define ENUMERATE_TRACK_TYPE(T)
Empty class which will have subclasses.
Definition: Track.h:63
bool operator==(const TrackNodePointer &a, const TrackNodePointer &b)
Definition: Track.h:51
bool operator!=(const TrackNodePointer &a, const TrackNodePointer &b)
Definition: Track.h:54
std::pair< ListOfTracks::iterator, ListOfTracks * > TrackNodePointer
Pairs a std::list iterator and a pointer to a list, for comparison purposes.
Definition: Track.h:49
std::list< std::shared_ptr< Track > > ListOfTracks
Definition: Track.h:43
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:828
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)
int id
static CustomUpdaterValue updater
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
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:114
double start
Definition: Track.h:133
ConstTrackInterval(ConstTrackInterval &&)=default
std::unique_ptr< TrackIntervalData > pExtra
Definition: Track.h:136
ConstTrackInterval(double start, double end, std::unique_ptr< TrackIntervalData > pExtra={})
Definition: Track.h:118
const TrackIntervalData * Extra() const
Definition: Track.h:130
double Start() const
Definition: Track.h:128
ConstTrackInterval & operator=(ConstTrackInterval &&)=default
double End() const
Definition: Track.h:129
An object that sends messages to an open-ended list of subscribed callbacks.
Definition: Observer.h:108
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:161
static void checkTrackType()
Definition: Track.h:653
std::function< R() > Continuation
Type of arguments passed as optional second parameter to TypeSwitch() cases.
Definition: Track.h:457
Track()
Definition: Track.cpp:39
virtual void SetOffset(double o)
Definition: Track.h:404
bool SameKindAs(const Track &track) const
Definition: Track.h:452
static R CallExecutor(R *, std::tuple<> *, TrackType &, const Functions &...)
Definition: Track.h:660
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:293
virtual void Clear(double WXUNUSED(t0), double WXUNUSED(t1))=0
virtual const TypeInfo & GetTypeInfo() const =0
virtual double GetStartTime() const =0
virtual Holder Clone() const =0
bool IsSelectedLeader() const
Definition: Track.cpp:301
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:675
std::pair< int, int > vrulerSize
Definition: Track.h:313
std::shared_ptr< TrackList > GetOwner() const
Definition: Track.h:333
R TypeSwitch(const Functions &...functions)
Use this function rather than testing track type explicitly and making down-casts.
Definition: Track.h:755
static std::shared_ptr< Subclass > SharedPointer(Track *pTrack)
Definition: Track.h:244
bool HasOwner() const
Definition: Track.h:331
virtual const TypeNames & GetTypeNames() const
Definition: Track.h:289
auto SharedPointer() const -> std::enable_if_t< std::is_const_v< Subclass >, std::shared_ptr< Subclass > >
Definition: Track.h:232
std::shared_ptr< Subclass > SharedPointer()
Definition: Track.h:224
TrackId GetId() const
Definition: Track.h:214
std::shared_ptr< Track > Holder
Definition: Track.h:295
void SetId(TrackId id)
Definition: Track.h:216
bool LinkConsistencyCheck(bool completeList)
Do the non-mutating part of consistency fix only and return status.
Definition: Track.h:328
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:772
virtual void Silence(double WXUNUSED(t0), double WXUNUSED(t1))=0
Continuation<> Fallthrough
Type of arguments passed as optional second parameter to TypeSwitch<void>() cases.
Definition: Track.h:459
static R DoTypeSwitch(std::conditional_t< IsConst, const Track, Track > &track, TypeList::List< TrackTypes... >, const Functions &...functions)
Deduce two packs from arguments.
Definition: Track.h:707
std::weak_ptr< TrackList > mList
Definition: Track.h:203
virtual double GetEndTime() const =0
std::vector< Interval > Intervals
Definition: Track.h:262
bool IsLeader() const
Definition: Track.cpp:296
virtual void InsertSilence(double WXUNUSED(t), double WXUNUSED(len))=0
static constexpr unsigned UsedCases(std::tuple< Executors... > *)
Definition: Track.h:694
LinkType
For two tracks describes the type of the linkage.
Definition: Track.h:172
virtual bool GetErrorOpening()
Definition: Track.h:787
int mIndex
0-based position of this track in its TrackList
Definition: Track.h:207
static std::shared_ptr< Subclass > SharedPointer(const Track *pTrack)
Definition: Track.h:248
std::unique_ptr< ChannelGroupData > mpGroupData
Definition: Track.h:200
std::vector< ConstInterval > ConstIntervals
Definition: Track.h:264
bool Any() const
Definition: Track.cpp:290
TrackId mId
Identifies the track only in-session, not persistently.
Definition: Track.h:198
An in-session identifier of track objects across undo states. It does not persist between sessions.
Definition: Track.h:87
bool operator!=(const TrackId &other) const
Definition: Track.h:95
TrackId()
Definition: Track.h:89
bool operator<(const TrackId &other) const
Definition: Track.h:100
TrackId(long value)
Definition: Track.h:90
long mValue
Definition: Track.h:104
bool operator==(const TrackId &other) const
Definition: Track.h:92
A start and an end time, and mutative access to optional extra information.
Definition: Track.h:141
TrackIntervalData * Extra() const
Definition: Track.h:148
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:869
const FunctionType & GetPredicate() const
Definition: Track.h:915
TrackNodePointer mIter
Current position.
Definition: Track.h:1020
TrackType * operator*() const
Safe to call even when at the end.
Definition: Track.h:962
TrackIter & operator--()
Safe to call even when at the beginning.
Definition: Track.h:939
friend bool operator!=(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
Definition: Track.h:995
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:904
TrackNodePointer mBegin
Allows end of reverse iteration to be detected without comparison to other TrackIter.
Definition: Track.h:1019
friend bool operator==(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
Definition: Track.h:984
TrackIter Filter(const Predicate2 &pred2) const
Return an iterator that replaces the predicate.
Definition: Track.h:895
TrackIter & operator++()
Safe to call even when at the end.
Definition: Track.h:920
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:874
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:974
FunctionType mPred
Optional filter
Definition: Track.h:1022
TrackIter(TrackNodePointer begin, TrackNodePointer iter, TrackNodePointer end, FunctionType pred={})
Constructor, usually not called directly except by methods of TrackList.
Definition: Track.h:877
bool valid() const
Test satisfaction of the invariant, while initializing, incrementing, or decrementing.
Definition: Track.h:1006
TrackNodePointer mEnd
Allows end of iteration to be detected without comparison to other TrackIter.
Definition: Track.h:1021
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
Definition: Track.h:1201
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
Definition: Track.h:1474
static auto SingletonRange(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1370
auto Selected() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1326
AudacityProject * mOwner
Definition: Track.h:1645
static long sCounter
Definition: Track.h:1597
bool Move(Track *t, bool up)
Definition: Track.h:1466
const_iterator begin() const
Definition: Track.h:1257
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:1276
auto SelectedLeaders() -> TrackIterRange< TrackType >
Definition: Track.h:1353
std::vector< Updater > mUpdaters
This is in correspondence with mPendingUpdates.
Definition: Track.h:1651
TrackNodePointer getBegin() const
Definition: Track.h:1554
iterator end()
Definition: Track.h:1256
auto Tracks(const Pred &pred={}) const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1516
TrackIter< const Track > FindLeader(const Track *pTrack) const
Definition: Track.h:1294
auto Leaders() -> TrackIterRange< TrackType >
Definition: Track.h:1336
static size_t NChannels(const Track &track)
Count channels of a track.
Definition: Track.h:1413
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
Definition: Track.h:1435
auto Tracks(const Pred &pred={}) -> TrackIterRange< TrackType >
Definition: Track.h:1503
size_t Size() const
Definition: Track.h:1487
bool isNull(TrackNodePointer p) const
Definition: Track.h:1548
TrackNodePointer getNext(TrackNodePointer p) const
Move an iterator to the next node, if any; else stay at end.
Definition: Track.h:1559
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:1264
auto Any() -> TrackIterRange< TrackType >
Definition: Track.h:1302
TrackNodePointer getEnd() const
Definition: Track.h:1551
std::function< void(Track &dest, const Track &src) > Updater
Definition: Track.h:1600
TrackIter< TrackType > EndIterator() const
Definition: Track.h:1540
auto Any() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1309
auto Leaders() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1343
static TrackIterRange< TrackType > Channels_(TrackIter< InTrackType > iter1)
Definition: Track.h:1384
void clear()=delete
const AudacityProject * GetOwner() const
Definition: Track.h:1239
iterator begin()
Definition: Track.h:1255
const_iterator cend() const
Definition: Track.h:1260
auto Selected() -> TrackIterRange< TrackType >
Definition: Track.h:1319
const_iterator cbegin() const
Definition: Track.h:1259
AudacityProject * GetOwner()
Definition: Track.h:1238
TrackIter< TrackType > MakeTrackIterator(TrackNodePointer iter) const
Definition: Track.h:1531
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:1569
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Definition: Track.h:1406
ListOfTracks mPendingUpdates
Shadow tracks holding append-recording in progress; need to put them into a list so that GetLink() wo...
Definition: Track.h:1649
TrackKind * AddToHead(const std::shared_ptr< TrackKind > &t)
Add a Track, giving it a fresh id.
Definition: Track.h:1431
const_iterator end() const
Definition: Track.h:1258
auto SelectedLeaders() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
Definition: Track.h:1360
Holds a msgid for the translation catalog; may also bind format arguments.
typename Accumulate< 0 >::type type
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)
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:196
@ 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
Utilities for compile-time type manipulation. Some terminology as in Lisp.
Definition: TypeList.h:20
List<> Nil
Definition: TypeList.h:70
typename Reverse< TypeList >::type Reverse_t
Definition: TypeList.h:284
void FinishCopy(const Track *n, const Track::Holder &dest, TrackList &list)
Definition: EditMenus.cpp:38
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
Definition: NoteTrack.cpp:752
void Notify(AudacityProject &project, ProjectSettings::EventCode code, long previousValue)
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:32
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:277
iterator find(const T &t) const
Definition: MemoryX.h:300
IteratorRange< reverse_iterator > reversal() const
Definition: MemoryX.h:287
TrackIter< TrackType > end() const
Definition: MemoryX.h:291
TrackIter< TrackType > begin() const
Definition: MemoryX.h:290
std::conditional_t< std::is_const_v< ArgumentType >, const BaseClass, BaseClass > QualifiedBaseClass
Definition: Track.h:565
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(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, std::declval< Continuation< R > >()), applicable2< Tag, R, BaseClass, ArgumentType, Function, Functions... >{})
overload when upcast of ArgumentType* works, with sfinae'd return type
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() -> inapplicable< Tag, R, ArgumentType, Function, Functions... >
No BaseClass of ArgumentType is acceptable to Function.
Variadic template implements metafunction with specializations, to choose among implementations of op...
Definition: Track.h:543
Second, nonrecursive case of metafunction, generates operator () that calls function without fallthro...
Definition: Track.h:494
std::conditional_t< std::is_const_v< ArgumentType >, const BaseClass, BaseClass > QualifiedBaseClass
Definition: Track.h:500
std::conditional_t< std::is_const_v< ArgumentType >, const Track, Track > QualifiedTrackType
Definition: Track.h:497
Third, recursive case of metafunction, generates operator () that calls function with fallthrough.
Definition: Track.h:516
std::conditional_t< std::is_const_v< ArgumentType >, const Track, Track > QualifiedTrackType
Definition: Track.h:519
std::conditional_t< std::is_const_v< ArgumentType >, const BaseClass, BaseClass > QualifiedBaseClass
Definition: Track.h:522
First, recursive case of metafunction, defers generation of operator ()
Definition: Track.h:473
std::conditional_t< std::is_const_v< ArgumentType >, const Track, Track > QualifiedTrackType
Definition: Track.h:476
Helper for recursive case of metafunction implementing Track::TypeSwitch.
Definition: Track.h:468
Variadic template implements metafunction with specializations, to dispatch Track::TypeSwitch.
Definition: Track.h:464
Empty argument passed to some public constructors.
Definition: Track.h:168
TypeNames names
Definition: Track.h:274
bool IsBaseOf(const TypeInfo &other) const
Definition: Track.h:278
const TypeInfo * pBaseInfo
Definition: Track.h:276
Names of a track type for various purposes.
Definition: Track.h:268
wxString info
short, like "wave", in macro output, not internationalized
Definition: Track.h:269
TranslatableString name
long, like "Wave Track"
Definition: Track.h:271
wxString property
short, like "wave", as a Lisp symbol property, not internationalized
Definition: Track.h:270
Optional extra information about an interval, appropriate to a subtype of Track.
Definition: Track.h:108
virtual ~TrackIntervalData()
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
Definition: Track.h:1030
TrackIterRange EndingAfter(const Track *pTrack) const
Definition: Track.h:1106
void VisitWhile(Flag &flag, const Functions &...functions)
See Track::TypeSwitch.
Definition: Track.h:1138
TrackIterRange operator+(const Predicate2 &pred2) const
Definition: Track.h:1041
TrackIterRange(const TrackIter< TrackType > &begin, const TrackIter< TrackType > &end)
Definition: Track.h:1032
void Visit(const Functions &...functions)
See Track::TypeSwitch.
Definition: Track.h:1129
TrackIterRange< TrackType2 > Filter() const
Definition: Track.h:1084
TrackIterRange Excluding(const TrackType *pExcluded) const
Definition: Track.h:1121
TrackIterRange operator-(const Predicate2 &pred2) const
Definition: Track.h:1067
TrackIterRange StartingWith(const Track *pTrack) const
Definition: Track.h:1092
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
Definition: Track.h:1151
TrackListEvent(const TrackListEvent &)=default
const int mExtra
Definition: Track.h:1190
const std::weak_ptr< Track > mpTrack
Definition: Track.h:1189
const Type mType
Definition: Track.h:1188
@ RESIZING
Posted when some track changed its height.
Definition: Track.h:1167
@ SELECTION_CHANGE
Posted when the set of selected tracks changes.
Definition: Track.h:1154
@ DELETION
Posted when a track has been deleted from a tracklist. Also posted when one track replaces another.
Definition: Track.h:1176
@ ADDITION
Posted when a track has been added to a tracklist. Also posted when one track replaces another.
Definition: Track.h:1170
@ PERMUTED
Posted when tracks are reordered but otherwise unchanged.
Definition: Track.h:1164
@ TRACK_REQUEST_VISIBLE
Posted when a track needs to be scrolled into view.
Definition: Track.h:1160
@ TRACK_DATA_CHANGE
Posted when certain fields of a track change.
Definition: Track.h:1157
TrackListEvent(Type type, const std::weak_ptr< Track > &pTrack={}, int extra=-1)
Definition: Track.h:1179
Primary template for a list of arbitrary types.
Definition: TypeList.h:56
Holds one item with description and time range for the UndoManager.
Definition: UndoManager.h:117
A convenience for defining iterators that return rvalue types, so that they cooperate correctly with ...
Definition: MemoryX.h:263