11#ifndef __AUDACITY_TRACK__
12#define __AUDACITY_TRACK__
20#include <wx/longlong.h>
32#pragma warning(disable:4284)
51std::pair< ListOfTracks::iterator, ListOfTracks* >;
56{
return a.second == b.second && a.first == b.first; }
67#define ENUMERATE_TRACK_TYPE(T) ENUMERATE_TYPE(TrackTypeTag, T)
71 std::enable_if_t< std::is_pointer_v<T>, T >
76 std::is_pointer_v<T> &&
77 std::is_const_v< std::remove_pointer_t< T > >,
120 ,
public std::enable_shared_from_this<Track>
159 template<
typename Sub
class = Track>
164 return std::static_pointer_cast<Subclass>( shared_from_this() );
167 template<
typename Sub
class = const Track>
170 std::is_const_v<Subclass>,
std::shared_ptr<Subclass>
175 return std::static_pointer_cast<Subclass>( shared_from_this() );
179 template<
typename Sub
class = Track>
181 {
return pTrack ? pTrack->
SharedPointer<Subclass>() :
nullptr; }
183 template<
typename Sub
class = const Track>
185 {
return pTrack ? pTrack->
SharedPointer<Subclass>() :
nullptr; }
189 std::shared_ptr<Track> SubstitutePendingChangedTrack();
190 std::shared_ptr<const Track> SubstitutePendingChangedTrack()
const;
194 std::shared_ptr<const Track> SubstituteOriginalTrack()
const;
205 bool concrete =
false;
210 for (
auto pInfo = &other;
218 static const TypeInfo &ClassTypeInfo();
220 {
return GetTypeInfo().names; }
223 virtual bool SupportsBasicEditing()
const;
246 virtual bool LinkConsistencyFix(
bool doFix =
true);
250 {
return const_cast<Track*
>(
this)->LinkConsistencyFix(
false); }
252 bool HasOwner()
const {
return static_cast<bool>(GetOwner());}
254 std::shared_ptr<TrackList>
GetOwner()
const {
return mList.lock(); }
257 LinkType GetLinkType() const noexcept;
259 ChannelGroupData &GetGroupData();
261 const ChannelGroupData &GetGroupData() const;
268 void SetLinkType(LinkType linkType,
bool completeList = true);
271 int GetIndex() const;
272 void SetIndex(
int index);
277 void DoSetLinkType(LinkType linkType,
bool completeList = true);
279 Track* GetLinkedTrack() const;
281 bool HasLinkedTrack() const noexcept;
292 Track(const
Track &orig, ProtectedCreationArg&&);
307 const wxString &GetName() const;
308 void SetName( const wxString &n );
311 bool GetSelected() const;
312 virtual
void SetSelected(
bool s);
320 void OnProjectTempoChange(
double newTempo);
348 virtual
void Clear(
double t0,
double t1) = 0;
356 virtual
void Paste(
double t, const
Track &src) = 0;
364 void Paste(
double t, const
TrackList &src);
371 virtual
void SyncLockAdjust(
double oldT1,
double newT1);
399 friend std::enable_if_t< std::is_pointer_v<T>, T >
402 friend std::enable_if_t<
403 std::is_pointer_v<T> &&
404 std::is_const_v< std::remove_pointer_t< T > >,
417 template<
typename R = void,
typename ...Functions>
420 struct Here : TrackTypeTag {};
424 return TypeSwitch::VDispatch<R, TrackTypes>(*
this, functions...);
428 template<
typename R = void,
typename ...Functions>
431 struct Here : TrackTypeTag {};
436 return TypeSwitch::VDispatch<R, TrackTypes>(*
this, functions...);
448 virtual std::optional<TranslatableString> GetErrorOpening()
const;
453 void Notify(
bool allChannels,
int code = -1);
459 bool IsSelected()
const;
461 bool IsSelectedLeader()
const;
464 void AdjustPositions();
467 void WriteCommonXMLAttributes(
468 XMLWriter &xmlFile,
bool includeNameAndSelected =
true)
const;
473 const std::optional<double>& GetProjectTempo()
const;
480 const std::optional<double>& oldTempo,
double newTempo) = 0;
486template<
typename Base = Track>
499 return { this->shared_from_this(), alias };
505 const Track &track = *
this;
506 return const_cast<Track&
>(track);
515 std::function<std::shared_ptr<TrackAttachment>(
Track &,
size_t)>;
521 void CopyTo(
Track &track)
const override;
522 void Reparent(
const std::shared_ptr<Track> &parent)
override;
523 void WriteXMLAttributes(
XMLWriter &writer)
const override;
524 bool HandleXMLAttribute(
548template<
typename Attachment>
551 static_assert(std::is_base_of_v<TrackAttachment, Attachment>);
562 return static_cast<Attachment&
>(
572 return static_cast<Attachment*
>(
586 typename sfinae = std::enable_if_t<std::is_convertible_v<
587 std::invoke_result_t<F, Track&, size_t>, std::shared_ptr<Attachment>
604 inline std::enable_if_t< std::is_pointer_v<T>, T >
607 using BareType = std::remove_pointer_t< T >;
609 BareType::ClassTypeInfo().IsBaseOf(track->
GetTypeInfo() ))
610 return reinterpret_cast<T
>(track);
618 inline std::enable_if_t<
619 std::is_pointer_v<T> && std::is_const_v< std::remove_pointer_t< T > >,
624 using BareType = std::remove_pointer_t< T >;
626 BareType::ClassTypeInfo().IsBaseOf(track->
GetTypeInfo() ))
627 return reinterpret_cast<T
>(track);
645 :
public ValueIterator< TrackType *, std::bidirectional_iterator_tag >
650 std::add_pointer_t< std::add_const_t< std::remove_pointer_t<TrackType> > >
661 ,
mPred( std::move(pred) )
671 template <
typename Predicate2 >
680 template <
typename TrackType2 >
683 std::is_base_of_v< TrackType, TrackType2 > &&
684 (!
std::is_const_v<TrackType> ||
685 std::is_const_v<TrackType2>),
693 {
return this->
mPred; }
747 return static_cast< TrackType *
>( &**this->
mIter.first );
756 std::advance(
copy, amount );
786 const auto pTrack = track_cast< TrackType * >( &**this->
mIter.first );
817 template<
typename Predicate2 >
820 const auto &pred1 = this->first.GetPredicate();
822 const auto &newPred = pred1
823 ? Function{ [=] (
typename Function::argument_type track) {
824 return pred1(track) && pred2(track);
828 this->first.Filter( newPred ),
829 this->second.Filter( newPred )
835 template<
typename R,
typename C >
838 return this->
operator + ( std::mem_fn( pmf ) );
843 template<
typename Predicate2 >
847 typename TrackIterRange::iterator::FunctionType::argument_type;
848 auto neg = [=] (ArgumentType track) {
return !pred2( track ); };
854 template<
typename R,
typename C >
857 return this->
operator + ( std::not1( std::mem_fn( pmf ) ) );
860 template<
typename TrackType2 >
871 auto newBegin = this->
find( pTrack );
876 { newBegin.mIter, newBegin.mIter, this->second.mEnd,
877 this->first.GetPredicate() },
878 { newBegin.mIter, this->second.mIter, this->second.mEnd,
879 this->second.GetPredicate() }
885 const auto newEnd = this->
reversal().find( pTrack ).base();
890 { this->first.mBegin, this->first.mIter, newEnd.mIter,
891 this->first.GetPredicate() },
892 { this->first.mBegin, newEnd.mIter, newEnd.mIter,
893 this->second.GetPredicate() }
901 [=](
const Track *pTrack){
return pExcluded == pTrack; } );
905 template<
typename ...Functions >
906 void Visit(
const Functions &...functions)
908 for (
auto track : *
this)
909 track->TypeSwitch(functions...);
914 template<
typename Flag,
typename ...Functions >
917 if (
flag )
for (
auto track : *
this) {
918 track->TypeSwitch(functions...);
954 const std::weak_ptr<Track> &pTrack = {},
int extra = -1)
973 ,
public std::enable_shared_from_this<TrackList>
977 using ListOfTracks::push_back;
1023 wxString MakeUniqueTrackName(
const wxString& baseTrackName)
const;
1078 template <
typename TrackType = Track >
1085 template <
typename TrackType = const Track >
1087 ->
std::enable_if_t<
std::is_const_v<TrackType>,
1095 template <
typename TrackType = Track>
1101 template <
typename TrackType = const Track>
1109 template<
typename TrackType>
1113 return pTrack->GetOwner()->template Tracks<TrackType>()
1119 Track *DoAddToHead(
const std::shared_ptr<Track> &t);
1120 Track *DoAdd(
const std::shared_ptr<Track> &t);
1122 template<
typename TrackType,
typename InTrackType >
1145 template<
typename TrackType >
1149 return Channels_<TrackType>(pTrack->GetHolder()->Find(pTrack));
1173 void Permute(
const std::vector<Track *> &
tracks);
1178 template<
typename TrackKind>
1179 TrackKind *
AddToHead(
const std::shared_ptr< TrackKind > &t )
1180 {
return static_cast< TrackKind*
>( DoAddToHead( t ) ); }
1182 template<
typename TrackKind>
1183 TrackKind *
Add(
const std::shared_ptr< TrackKind > &t )
1184 {
return static_cast< TrackKind*
>( DoAdd( t ) ); }
1187 std::vector<Track*> UnlinkChannels(
Track& track);
1194 bool MakeMultiChannelTrack(
Track& first,
int nChannels);
1216 void Clear(
bool sendEvent =
true);
1218 bool CanMoveUp(
Track * t)
const;
1219 bool CanMoveDown(
Track * t)
const;
1221 bool MoveUp(
Track * t);
1222 bool MoveDown(
Track * t);
1223 bool Move(
Track * t,
bool up) {
return up ? MoveUp(t) : MoveDown(t); }
1227 template <
typename Sub
class>
1228 std::shared_ptr<Subclass>
Lock(
const std::weak_ptr<Subclass> &wTrack)
1230 auto pTrack = wTrack.lock();
1232 auto pList = pTrack->mList.lock();
1233 if (pTrack &&
this == pList.get())
1262 AudacityProject *pProject,
const std::vector<Track::Holder> &channels);
1268 template<
typename T>
1271 const std::vector<std::shared_ptr<T>> &channels)
1273 std::vector<Track::Holder> temp;
1274 static const auto convert = [](
auto &pChannel){
1275 return std::static_pointer_cast<Track>(pChannel);
1277 transform(channels.begin(), channels.end(), back_inserter(temp), convert);
1278 return Temporary(pProject, temp);
1291 void RegisterPendingNewTracks(
TrackList &&list);
1302 typename TrackType =
Track,
1309 auto b = getBegin(), e = getEnd();
1310 return { { b, b, e, pred }, { b, e, e, pred } };
1315 typename TrackType =
const Track,
1320 -> std::enable_if_t< std::is_const_v<TrackType>,
1324 auto b =
const_cast<TrackList*
>(
this)->getBegin();
1325 auto e =
const_cast<TrackList*
>(
this)->getEnd();
1326 return { { b, b, e, pred }, { b, e, e, pred } };
1329 Track *GetPrev(
Track * t,
bool linked =
false)
const;
1330 Track *GetNext(
Track * t,
bool linked =
false)
const;
1332 template <
typename TrackType >
1336 auto b =
const_cast<TrackList*
>(
this)->getBegin();
1337 auto e =
const_cast<TrackList*
>(
this)->getEnd();
1338 return { b, iter, e };
1341 template <
typename TrackType >
1345 auto e =
const_cast<TrackList*
>(
this)->getEnd();
1353 || (mPendingUpdates && p.second == &*mPendingUpdates &&
1354 p.first == mPendingUpdates->ListOfTracks::end()); }
1375 if (p == getBegin())
1386 void SelectionEvent(
Track &track);
1389 const std::shared_ptr<Track> &pTrack,
bool allChannels,
int code );
1390 void DeletionEvent(std::weak_ptr<Track> node,
bool duringReplace);
1424 Track* RegisterPendingChangedTrack(
1431 void UpdatePendingTracks();
1438 void ClearPendingTracks(
ListOfTracks *pAdded =
nullptr);
1444 bool ApplyPendingTracks();
1446 bool HasPendingTracks()
const;
1459 bool mAssignsIds{
true };
Abstract class ChannelGroup with two discrete iterable dimensions, channels and intervals; subclasses...
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.
std::function< void(double)> ProgressReporter
#define ENUMERATE_TRACK_TYPE(T)
Empty class which will have subclasses.
bool operator==(const TrackNodePointer &a, const TrackNodePointer &b)
bool operator!=(const TrackNodePointer &a, const TrackNodePointer &b)
std::pair< ListOfTracks::iterator, ListOfTracks * > TrackNodePointer
Pairs a std::list iterator and a pointer to a list, for comparison purposes.
std::list< std::shared_ptr< Track > > ListOfTracks
std::enable_if_t< std::is_pointer_v< T >, T > track_cast(Track *track)
Encapsulate the checked down-casting of track pointers.
std::shared_ptr< TrackList > TrackListHolder
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::Get(track);menu.Check(id, view.GetMultiView());}) :nullptr;}))
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Holds multiple objects as a single attachment to Track.
static TrackAttachment & Get(const AttachedTrackObjects::RegisteredFactory &key, Track &track, size_t iChannel)
std::vector< std::shared_ptr< TrackAttachment > > mAttachments
~ChannelAttachmentsBase() override
static TrackAttachment * Find(const AttachedTrackObjects::RegisteredFactory &key, Track *pTrack, size_t iChannel)
std::function< std::shared_ptr< TrackAttachment >(Track &, size_t)> Factory
Holds multiple objects of the parameter type as a single attachment to Track.
~ChannelAttachments() override=default
static Attachment * Find(const AttachedTrackObjects::RegisteredFactory &key, Track *pTrack, size_t iChannel)
ChannelAttachments(Track &track, F &&f)
Type-erasing constructor.
static Attachment & Get(const AttachedTrackObjects::RegisteredFactory &key, Track &track, size_t iChannel)
double GetEndTime() const
Get the maximum of End() values of intervals, or 0 when none.
double GetStartTime() const
Get the minimum of Start() values of intervals, or 0 when none.
virtual bool IsLeader() const =0
IteratorRange< ChannelIterator< ChannelType > > Channels()
Get range of channels with mutative access.
virtual size_t NChannels() const =0
Report the number of channels.
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Utility to register hooks into a host class that attach client data.
Site & operator=(const Site &other)
Subclass * DoFind(Locked< DataContainer > &data, const RegisteredFactory &key)
An object that sends messages to an open-ended list of subscribed callbacks.
Abstract base class for an object holding data associated with points on a time axis.
virtual TrackListHolder Clone() const =0
virtual Holder PasteInto(AudacityProject &project, TrackList &list) const =0
bool SameKindAs(const Track &track) const
virtual const TypeInfo & GetTypeInfo() const =0
virtual void InsertSilence(double t, double len)=0
bool IsSelectedLeader() const
TrackList * GetHolder() const
virtual void DoOnProjectTempoChange(const std::optional< double > &oldTempo, double newTempo)=0
std::shared_ptr< TrackList > GetOwner() const
R TypeSwitch(const Functions &...functions)
static std::shared_ptr< Subclass > SharedPointer(Track *pTrack)
virtual const TypeNames & GetTypeNames() const
auto SharedPointer() const -> std::enable_if_t< std::is_const_v< Subclass >, std::shared_ptr< Subclass > >
std::shared_ptr< Subclass > SharedPointer()
virtual void Clear(double t0, double t1)=0
bool IsLeader() const override
std::shared_ptr< Track > Holder
virtual void WriteXML(XMLWriter &xmlFile) const =0
R TypeSwitch(const Functions &...functions) const
std::weak_ptr< TrackList > mList
TrackNodePointer mNode
Holds iterator to self, so that TrackList::Find can be constant-time.
int mIndex
0-based position of this track in its TrackList
static std::shared_ptr< Subclass > SharedPointer(const Track *pTrack)
bool LinkConsistencyCheck()
Do the non-mutating part of consistency fix only and return status.
TrackId mId
Identifies the track only in-session, not persistently.
An in-session identifier of track objects across undo states. It does not persist between sessions.
bool operator!=(const TrackId &other) const
bool operator<(const TrackId &other) const
bool operator==(const TrackId &other) const
Iterator over only members of a TrackList of the specified subtype, optionally filtered by a predicat...
const FunctionType & GetPredicate() const
TrackNodePointer mIter
Current position.
TrackType * operator*() const
Safe to call even when at the end.
TrackIter & operator--()
Safe to call even when at the beginning.
friend bool operator!=(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
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.
TrackNodePointer mBegin
Allows end of reverse iteration to be detected without comparison to other TrackIter.
friend bool operator==(TrackIter a, TrackIter b)
Compares only current positions, assuming same beginnings and ends.
TrackIter Filter(const Predicate2 &pred2) const
Return an iterator that replaces the predicate.
TrackIter & operator++()
Safe to call even when at the end.
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.
TrackIter advance(long amount) const
This might be called operator + , but it's not constant-time as with a random access iterator.
FunctionType mPred
Optional filter
TrackIter(TrackNodePointer begin, TrackNodePointer iter, TrackNodePointer end, FunctionType pred={})
Constructor, usually not called directly except by methods of TrackList.
bool valid() const
Test satisfaction of the invariant, while initializing, incrementing, or decrementing.
TrackNodePointer mEnd
Allows end of iteration to be detected without comparison to other TrackIter.
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
const_reverse_iterator crbegin() const
std::shared_ptr< Subclass > Lock(const std::weak_ptr< Subclass > &wTrack)
static auto SingletonRange(TrackType *pTrack) -> TrackIterRange< TrackType >
auto Selected() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
std::function< void(Track &dest, const Track &src)> Updater
const_reverse_iterator rend() const
static TrackListHolder Temporary(AudacityProject *pProject, const std::vector< std::shared_ptr< T > > &channels)
std::reverse_iterator< const_iterator > const_reverse_iterator
std::shared_ptr< TrackList > mPendingUpdates
const_iterator End() const
This private function still iterates channels not tracks.
bool Move(Track *t, bool up)
const_iterator begin() const
std::vector< Updater > mUpdaters
This is in correspondence with leader tracks in mPendingUpdates.
TrackNodePointer getBegin() const
auto Tracks(const Pred &pred={}) const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
TrackIter< const Track > Find(const Track *pTrack) const
static size_t NChannels(const Track &track)
Count channels of a track.
TrackKind * Add(const std::shared_ptr< TrackKind > &t)
auto Tracks(const Pred &pred={}) -> TrackIterRange< TrackType >
bool isNull(TrackNodePointer p) const
const_reverse_iterator crend() const
TrackNodePointer getNext(TrackNodePointer p) const
Move an iterator to the next node, if any; else stay at end.
auto Any() -> TrackIterRange< TrackType >
TrackNodePointer getEnd() const
TrackIter< TrackType > EndIterator() const
auto Any() const -> std::enable_if_t< std::is_const_v< TrackType >, TrackIterRange< TrackType > >
reverse_iterator rbegin()
static TrackIterRange< TrackType > Channels_(TrackIter< InTrackType > iter1)
const AudacityProject * GetOwner() const
std::reverse_iterator< iterator > reverse_iterator
const_iterator cend() const
auto Selected() -> TrackIterRange< TrackType >
iterator Begin()
This private function still iterates channels not tracks.
const_iterator cbegin() const
const_iterator Begin() const
This private function still iterates channels not tracks.
iterator End()
This private function still iterates channels not tracks.
AudacityProject * GetOwner()
TrackIter< TrackType > MakeTrackIterator(TrackNodePointer iter) const
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.
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
const_reverse_iterator rbegin() const
TrackKind * AddToHead(const std::shared_ptr< TrackKind > &t)
Add a Track, giving it a fresh id.
const_iterator end() const
Holds a msgid for the translation catalog; may also bind format arguments.
typename Accumulate< 0 >::type type
Generates overrides of channel-related functions.
std::shared_ptr< Channel > DoGetChannel(size_t iChannel) override
Retrieve a channel.
size_t NChannels() const override
Report the number of channels.
ChannelGroup & DoGetChannelGroup() const override
Subclass must override.
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...
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
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.
@ ShallowCopying
copy pointers only; won't compile for std::unique_ptr
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Utilities for compile-time type manipulation. Some terminology as in Lisp.
typename Map< Metafunction, TypeList >::type Map_t
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)
static RegisteredToolbarFactory factory
void copy(const T *src, T *dst, int32_t n)
A convenient default parameter for class template Site.
A convenience for use with range-for.
iterator find(const T &t) const
IteratorRange< reverse_iterator > reversal() const
TrackIter< TrackType > end() const
TrackIter< TrackType > begin() const
Empty argument passed to some public constructors.
bool IsBaseOf(const TypeInfo &other) const
const TypeInfo * pBaseInfo
Names of a track type for various purposes.
wxString info
short, like "wave", in macro output, not internationalized
TranslatableString name
long, like "Wave Track"
wxString property
short, like "wave", as a Lisp symbol property, not internationalized
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
TrackIterRange EndingAfter(const Track *pTrack) const
void VisitWhile(Flag &flag, const Functions &...functions)
See Track::TypeSwitch.
TrackIterRange operator+(const Predicate2 &pred2) const
TrackIterRange(const TrackIter< TrackType > &begin, const TrackIter< TrackType > &end)
void Visit(const Functions &...functions)
See Track::TypeSwitch.
TrackIterRange< TrackType2 > Filter() const
TrackIterRange Excluding(const TrackType *pExcluded) const
TrackIterRange operator-(const Predicate2 &pred2) const
TrackIterRange StartingWith(const Track *pTrack) const
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
TrackListEvent(const TrackListEvent &)=default
const std::weak_ptr< Track > mpTrack
@ RESIZING
Posted when some track changed its height.
@ SELECTION_CHANGE
Posted when the set of selected tracks changes.
@ DELETION
Posted when a track has been deleted from a tracklist. Also posted when one track replaces another.
@ ADDITION
Posted when a track has been added to a tracklist. Also posted when one track replaces another.
@ PERMUTED
Posted when tracks are reordered but otherwise unchanged.
@ TRACK_DATA_CHANGE
Posted when certain fields of a track change.
TrackListEvent(Type type, const std::weak_ptr< Track > &pTrack={}, int extra=-1)
Select only the subsequence of the type list satisfying the predicate.
Holds one item with description and time range for the UndoManager.
A convenience for defining iterators that return rvalue types, so that they cooperate correctly with ...