diff --git a/src/Track.cpp b/src/Track.cpp index 35e2f39f5..c8424e508 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -856,6 +856,9 @@ void TrackList::UpdatedEvent(TrackNodePointer node) else { e.SetClientData(NULL); } + + // PRL: ProcessEvent, not QueueEvent! Listeners may need their last + // chance to examine some removed tracks that are about to be destroyed. ProcessEvent(e); } @@ -951,6 +954,9 @@ auto TrackList::Replace(Track * t, value_type &&with) -> value_type *node = std::move(with); pTrack->SetOwner(this, node); RecalcPositions(node); + + // PRL: Note: Send the event while t (now in holder) is not yet + // destroyed, so pointers to t that listeners may have are not dangling. UpdatedEvent(node); ResizedEvent(node); } @@ -964,11 +970,15 @@ TrackNodePointer TrackList::Remove(Track *t) auto node = t->GetNode(); if (!isNull(node)) { + value_type holder = std::move( *node ); + result = erase(node); if (!isNull(result)) { RecalcPositions(result); } + // PRL: Note: Send the event while t (now in holder) is not yet + // destroyed, so pointers to t that listeners may have are not dangling. UpdatedEvent(end()); ResizedEvent(result); } @@ -978,8 +988,12 @@ TrackNodePointer TrackList::Remove(Track *t) void TrackList::Clear(bool sendEvent) { - ListOfTracks::clear(); + ListOfTracks tempList; + tempList.swap( *this ); if (sendEvent) + // PRL: Note: Send the event while tempList is not yet + // destroyed, so pointers to tracks that listeners may have are not + // dangling. UpdatedEvent(end()); } diff --git a/src/Track.h b/src/Track.h index 5144bb93c..da9614f32 100644 --- a/src/Track.h +++ b/src/Track.h @@ -444,6 +444,11 @@ DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_RESIZED, -1); // Posted when tracks have been added or deleted from a tracklist. The pointer // wxCommandEvent::GetClientData() returns will be NULL for deletions or the // track that was added. +// Also posted when one track replaces another +// Also posted when the list of tracks is permuted, but no addition or deletion +// When a track has been removed, the event is processed before the track +// is destroyed, so that listeners that stored a pointer to the track can still +// use it and correctly check whether the list still contains it. DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_UPDATED, -1); class TrackList final : public wxEvtHandler, public ListOfTracks