25#include <wx/textfile.h>
35#pragma warning( disable : 4786 )
88 auto pList =
mList.lock();
90 pList->SelectionEvent(*
this);
103 src.AttachedTrackObjects::ForEach([&](
auto &attachment){
105 attachment.CopyTo(dst);
112 auto result = Clone(options.backup);
113 CopyAttachments(*result, *
this, !options.shallowCopyAttachments);
139 if (
const auto pList =
mList.lock()) {
140 pList->RecalcPositions(
mNode);
141 pList->ResizingEvent(
mNode);
154 if (linkType == oldType)
172 partner->CopyGroupProperties(*
this);
184 partner->CopyGroupProperties(*
this);
204 if (!pList->isNull(
mNode)) {
206 auto next = pList->getNext(
mNode );
207 if ( !pList->isNull( next ) )
211 if (
mNode != pList->ListOfTracks::begin()) {
212 auto prev = pList->getPrev(
mNode );
213 if ( !pList->isNull( prev ) ) {
214 auto track = prev->get();
215 if (track && track->HasLinkedTrack())
236 auto pList =
mList.lock();
244 if (newT1 > oldT1 && oldT1 > endTime)
247 auto cutChannels =
Cut(oldT1, endTime);
248 Paste(newT1, *cutChannels);
250 else if (newT1 < oldT1)
276 if (link->HasLinkedTrack()) {
280 L
"Left track %s had linked right track %s with extra right "
281 "track link.\n Removing extra link from right track.",
291 L
"Track %s had link to NULL track. Setting it to not be linked.",
332 return std::make_shared<TrackList>(pOwner);
349 ListOfTracks &a,
const std::weak_ptr< TrackList > &aSelf,
350 ListOfTracks &b,
const std::weak_ptr< TrackList > &bSelf )
353 for (
auto it = a.begin(), last = a.end(); it != last; ++it)
354 (*it)->SetOwner(aSelf, it);
355 for (
auto it = b.begin(), last = b.end(); it != last; ++it)
356 (*it)->SetOwner(bSelf, it);
359 const auto self = shared_from_this();
360 const auto otherSelf = that.shared_from_this();
361 SwapLOTs( *
this, self, that, otherSelf );
373 auto name = wxString::Format(
"%s %d", baseTrackName, n++);
376 for(
const auto track : Tracks<const Track>()) {
377 if(track->GetName() ==
name) {
398 const auto theEnd =
End();
399 for (
auto n =
DoFind(node->get()); n != theEnd; ++n)
406 if (
auto pThis = wThis.lock())
407 pThis->Publish(event);
413 for (
auto channel :
Channels(&track))
419 const std::shared_ptr<Track> &pTrack,
bool allChannels,
int code)
421 auto doQueueEvent = [
this, code](
const std::shared_ptr<Track> &theTrack){
425 for (
auto channel :
Channels(pTrack.get()))
426 doQueueEvent(channel->shared_from_this());
428 doQueueEvent(pTrack);
464 if (!pTrack || pTrack->GetOwner().get() !=
this)
465 return EndIterator<Track>();
467 return MakeTrackIterator<Track>(pTrack->GetNode());
472 auto iter = DoFind(pTrack);
473 while( *iter && ! ( *iter )->IsLeader() )
481 assert(before ==
nullptr ||
Find(before) != EndIterator<const Track>());
483 if(before ==
nullptr)
485 Add(pSrc, assignIds);
489 std::vector<Track *> arr;
490 arr.reserve(
Size() + 1);
491 for (
const auto track : *
this) {
493 arr.push_back(pSrc.get());
494 arr.push_back(track);
496 Add(pSrc, assignIds);
502 std::vector<TrackNodePointer> permutation;
503 for (
const auto pTrack :
tracks)
504 for (
const auto pChannel :
Channels(pTrack))
505 permutation.push_back(pChannel->GetNode());
506 for (
const auto iter : permutation) {
507 ListOfTracks::value_type track = *iter;
509 Track *pTrack = track.get();
522 [=](
const ListOfTracks::value_type &ptr){
return ptr->GetId() ==
id; } );
530 Track *pTrack = t.get();
531 push_front(ListOfTracks::value_type(t));
533 pTrack->
SetOwner(shared_from_this(), n);
537 return front().get();
542 if (!ListOfTracks::empty()) {
543 auto &pLast = *ListOfTracks::rbegin();
545 t->CopyGroupProperties(*pLast);
552 t->SetOwner(shared_from_this(), n);
563 assert(!with.empty());
565 auto save = t.shared_from_this();
572 const auto iter = with.ListOfTracks::begin();
573 const auto pTrack = *iter;
576 pTrack->SetOwner(shared_from_this(), node);
577 pTrack->SetId(save->GetId());
588 auto node = t->GetNode();
591 std::shared_ptr<Track> holder;
610 for (
auto pTrack: Tracks<Track>()) {
611 pTrack->SetOwner({}, {});
618 tempList.swap( *
this );
661 !(*node)->HasLinkedTrack() &&
662 (*node)->GetLinkedTrack())
674 return GetPrev(t,
true) !=
nullptr;
679 return GetNext(t,
true) !=
nullptr;
698 auto d1 = std::distance(
begin, s1);
699 auto d2 = std::distance(
begin, s2);
705 using Saved = ListOfTracks::value_type;
706 Saved saved1, saved2;
709 saved = *s, s = erase(s);
714 const bool same = (s1 == s2);
722 const auto pTrack = saved.get();
725 pTrack->SetOwner(shared_from_this(), s = insert(s, saved) );
728 doInsert(saved2, s1);
731 doInsert(saved1, s2);
767 const double &(*combine)(
const double&,
const double&))
774 return list.
Any().accumulate(
ident, combine, memfn);
781 std::numeric_limits<double>::max(),
std::min);
787 std::numeric_limits<double>::lowest(), std::max);
793 {
"generic",
"generic",
XO(
"Generic Track") },
false };
804 XMLWriter &xmlFile,
bool includeNameAndSelected)
const
806 if (includeNameAndSelected) {
814 attachment.WriteXMLAttributes( xmlFile );
824 bool handled =
false;
826 handled = handled || attachment.HandleXMLAttribute( attr, valueView );
833 else if (attr ==
"name") {
837 else if (attr ==
"isSelected" && valueView.
TryGet(nValue)) {
846 auto pList =
mList.lock();
848 pList->RecalcPositions(
mNode);
849 pList->ResizingEvent(
mNode);
861 assert(pTrack ==
nullptr || pTrack->GetOwner() ==
nullptr);
863 auto tempList =
Create(pProject);
865 tempList->Add(pTrack);
866 tempList->mAssignsIds =
false;
877 auto iter = list.ListOfTracks::begin(),
878 end = list.ListOfTracks::end();
879 while (iter !=
end) {
881 iter = list.erase(iter);
882 this->
Add(pTrack, assignIds);
888 const auto iter = list.ListOfTracks::begin(),
889 end = list.ListOfTracks::end();
902 result->SetOwner({}, {});
Toolkit-neutral facade for basic user interface services.
MessageBoxException for violation of preconditions or assertions.
static CommandHandlerObject & ident(AudacityProject &project)
static const AudacityProject::AttachedObjects::RegisteredFactory key
declares abstract base class Track, TrackList, and iterators over TrackList
ListOfTracks::iterator TrackNodePointer
std::list< std::shared_ptr< Track > > ListOfTracks
std::shared_ptr< TrackList > TrackListHolder
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
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.
LinkType
For two tracks describes the type of the linkage.
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.
void ForEach(const Function &function)
Invoke function on each ClientData object that has been created in this.
Abstract base class for an object holding data associated with points on a time axis.
bool GetSelected() const
Selectedness is always the same for all channels of a group.
virtual void Paste(double t, const Track &src)=0
Weak precondition allows overrides to replicate one channel into many.
virtual void SetSelected(bool s)
void Notify(bool allChannels, int code=-1)
virtual bool SupportsBasicEditing() const
Whether this track type implements cut-copy-paste; by default, true.
static const TypeInfo & ClassTypeInfo()
virtual void SyncLockAdjust(double oldT1, double newT1)
TrackNodePointer GetNode() const
Retrieve mNode with debug checks.
std::shared_ptr< TrackList > GetOwner() const
static void CopyAttachments(Track &dst, const Track &src, bool deep)
Copy (deep) or just share (!deep) AttachedTrackObjects.
virtual bool LinkConsistencyFix(bool doFix=true)
Check consistency of channel groups, and maybe fix it.
void SetLinkType(LinkType linkType, bool completeList=true)
std::shared_ptr< Subclass > SharedPointer()
bool HasLinkedTrack() const noexcept
During file loading only, true for leaders of multichannel groups.
void CopyGroupProperties(const Track &other)
virtual void Clear(double t0, double t1)=0
std::shared_ptr< Track > Holder
void SetOwner(const std::weak_ptr< TrackList > &list, TrackNodePointer node)
Update mNode when Track is added to TrackList, or removed from it.
void ReparentAllAttachments()
bool HandleCommonXMLAttribute(const std::string_view &attr, const XMLAttributeValueView &valueView)
const wxString & GetName() const
Name is always the same for all channels of a group.
void Init(const Track &orig)
virtual Holder Duplicate(DuplicateOptions={}) const
public nonvirtual duplication function that invokes Clone()
void WriteCommonXMLAttributes(XMLWriter &xmlFile, bool includeNameAndSelected=true) const
std::weak_ptr< TrackList > mList
TrackNodePointer mNode
Holds iterator to self, so that TrackList::Find can be constant-time.
Track * GetLinkedTrack() const
LinkType GetLinkType() const noexcept
virtual std::optional< TranslatableString > GetErrorOpening() const
void DoSetLinkType(LinkType linkType, bool completeList=true)
bool LinkConsistencyCheck()
Do the non-mutating part of consistency fix only and return status.
virtual Holder Cut(double t0, double t1)=0
Create tracks and modify this track.
void SetName(const wxString &n)
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.
Iterator over only members of a TrackList of the specified subtype, optionally filtered by a predicat...
A flat linked list of tracks supporting Add, Remove, Clear, and Contains, serialization of the list o...
void PermutationEvent(TrackNodePointer node)
bool CanMoveUp(Track &t) const
Track * DoAdd(const std::shared_ptr< Track > &t, bool assignIds)
static TrackListHolder Create(AudacityProject *pOwner)
void Insert(const Track *before, const Track::Holder &pSrc, bool assignIds=false)
Moves *pSrc to position where before is located. If before is nullptr the track is appended.
void AppendOne(TrackList &&list)
Remove first track (if any) from list and put it at the end of this
Track * GetNext(Track &, bool linked=false) const
Return a track in the list that comes after Track t.
void Permute(const std::vector< Track * > &tracks)
static void AssignUniqueId(const Track::Holder &track)
Assigns a new unique non-persistent id to a track.
double GetEndTime() const
Return the greatest end time of the tracks, or 0 when no tracks.
void ResizingEvent(TrackNodePointer node)
TrackNodePointer getBegin() const
TrackIter< Track > Find(Track *pTrack)
wxString MakeUniqueTrackName(const wxString &baseTrackName) const
Returns string that contains baseTrackName, but is guaranteed to be unique among other tracks in that...
TrackList & operator=(const TrackList &)=delete
double GetStartTime() const
Return the least start time of the tracks, or 0 when no tracks.
void Append(TrackList &&list, bool assignIds=true)
Remove all tracks from list and put them at the end of this
bool isNull(TrackNodePointer p) const
bool CanMoveDown(Track &t) const
TrackNodePointer getNext(TrackNodePointer p) const
Move an iterator to the next node, if any; else stay at end.
void Swap(TrackList &that)
void AdditionEvent(TrackNodePointer node)
void RecalcPositions(TrackNodePointer node)
auto Any() -> TrackIterRange< TrackType >
void SelectionEvent(Track &track)
TrackNodePointer getEnd() const
Track::Holder DetachFirst()
Remove and return the first track.
TrackIterRange< Track > EmptyRange() const
Track::Holder ReplaceOne(Track &t, TrackList &&with)
static TrackList & Get(AudacityProject &project)
Track * DoAddToHead(const std::shared_ptr< Track > &t)
Track::Holder Remove(Track &track)
Remove a track and return it.
Track * FindById(TrackId id)
TrackIter< Track > DoFind(Track *pTrack)
void DataEvent(const std::shared_ptr< Track > &pTrack, bool allChannels, int code)
iterator Begin()
This private function still iterates channels not tracks.
iterator End()
This private function still iterates channels not tracks.
void QueueEvent(TrackListEvent event)
void SwapNodes(TrackNodePointer s1, TrackNodePointer s2)
TrackList(const TrackList &that)=delete
TrackKind * Add(const std::shared_ptr< TrackKind > &t, bool assignIds=true)
void Clear(bool sendEvent=true)
Make the list empty.
void DeletionEvent(std::weak_ptr< Track > node, bool duringReplace)
TrackNodePointer getPrev(TrackNodePointer p) const
Move an iterator to the previous node, if any; else wrap to end.
static TrackListHolder Temporary(AudacityProject *pProject, const Track::Holder &pTrack={})
static auto Channels(TrackType *pTrack) -> TrackIterRange< TrackType >
Track * GetPrev(Track &, bool linked=false) const
A view into an attribute value. The class does not take the ownership of the data.
wxString ToWString() const
Convert the view value to wxString.
bool TryGet(bool &value) const noexcept
Try to get a boolean value from the view.
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
void WriteAttr(const wxString &name, const Identifier &value)
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
void swap(std::unique_ptr< Alg_seq > &a, std::unique_ptr< Alg_seq > &b)
double Accumulate(const TrackList &list, double(Track::*memfn)() const, double ident, const double &(*combine)(const double &, const double &))
const char * end(const char *str) noexcept
const char * begin(const char *str) noexcept
Choices when duplicating a track.
Empty argument passed to some public constructors.
Range between two TrackIters, usable in range-for statements, and with Visit member functions.
Notification of changes in individual tracks of TrackList, or of TrackList's composition.
@ 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.