mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-22 15:38:02 +02:00
Back-pointer from Track to TrackList is weak (fixes crashes)
This commit is contained in:
parent
9489fed04e
commit
16645f6b95
@ -922,6 +922,8 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
|
||||
mbLoadedFromAup( false )
|
||||
{
|
||||
|
||||
mTracks->SetSelf(mTracks);
|
||||
|
||||
#ifdef EXPERIMENTAL_DA2
|
||||
SetBackgroundColour(theTheme.Colour( clrMedium ));
|
||||
#endif
|
||||
|
@ -48,7 +48,6 @@ Track::Track(const std::shared_ptr<DirManager> &projDirManager)
|
||||
: vrulerSize(36,0),
|
||||
mDirManager(projDirManager)
|
||||
{
|
||||
mList = NULL;
|
||||
mSelected = false;
|
||||
mLinked = false;
|
||||
|
||||
@ -72,7 +71,6 @@ Track::Track(const std::shared_ptr<DirManager> &projDirManager)
|
||||
Track::Track(const Track &orig)
|
||||
: vrulerSize( orig.vrulerSize )
|
||||
{
|
||||
mList = NULL;
|
||||
mY = 0;
|
||||
mIndex = 0;
|
||||
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
|
||||
@ -119,11 +117,12 @@ Track::~Track()
|
||||
|
||||
TrackNodePointer Track::GetNode() const
|
||||
{
|
||||
wxASSERT(mList == NULL || this == mNode->get());
|
||||
wxASSERT(mList.lock() == NULL || this == mNode->get());
|
||||
return mNode;
|
||||
}
|
||||
|
||||
void Track::SetOwner(TrackList *list, TrackNodePointer node)
|
||||
void Track::SetOwner
|
||||
(const std::weak_ptr<TrackList> &list, TrackNodePointer node)
|
||||
{
|
||||
mList = list;
|
||||
mNode = node;
|
||||
@ -207,9 +206,10 @@ int Track::GetHeight() const
|
||||
void Track::SetHeight(int h)
|
||||
{
|
||||
mHeight = h;
|
||||
if (mList) {
|
||||
mList->RecalcPositions(mNode);
|
||||
mList->ResizingEvent(mNode);
|
||||
auto pList = mList.lock();
|
||||
if (pList) {
|
||||
pList->RecalcPositions(mNode);
|
||||
pList->ResizingEvent(mNode);
|
||||
}
|
||||
}
|
||||
#endif // EXPERIMENTAL_OUTPUT_DISPLAY
|
||||
@ -221,37 +221,40 @@ bool Track::GetMinimized() const
|
||||
|
||||
void Track::SetMinimized(bool isMinimized)
|
||||
{
|
||||
auto pList = mList.lock();
|
||||
mMinimized = isMinimized;
|
||||
if (mList) {
|
||||
mList->RecalcPositions(mNode);
|
||||
mList->ResizingEvent(mNode);
|
||||
if (pList) {
|
||||
pList->RecalcPositions(mNode);
|
||||
pList->ResizingEvent(mNode);
|
||||
}
|
||||
}
|
||||
|
||||
void Track::SetLinked(bool l)
|
||||
{
|
||||
auto pList = mList.lock();
|
||||
mLinked = l;
|
||||
if (mList) {
|
||||
mList->RecalcPositions(mNode);
|
||||
mList->ResizingEvent(mNode);
|
||||
if (pList) {
|
||||
pList->RecalcPositions(mNode);
|
||||
pList->ResizingEvent(mNode);
|
||||
}
|
||||
}
|
||||
|
||||
Track *Track::GetLink() const
|
||||
{
|
||||
if (!mList)
|
||||
auto pList = mList.lock();
|
||||
if (!pList)
|
||||
return nullptr;
|
||||
|
||||
if (!mList->isNull(mNode)) {
|
||||
if (!pList->isNull(mNode)) {
|
||||
if (mLinked) {
|
||||
auto next = mNode;
|
||||
++next;
|
||||
if (!mList->isNull(next)) {
|
||||
if (!pList->isNull(next)) {
|
||||
return next->get();
|
||||
}
|
||||
}
|
||||
|
||||
if (mList->hasPrev(mNode)) {
|
||||
if (pList->hasPrev(mNode)) {
|
||||
auto prev = mNode;
|
||||
--prev;
|
||||
auto track = prev->get();
|
||||
@ -282,7 +285,8 @@ bool Track::IsSyncLockSelected() const
|
||||
if (!p || !p->IsSyncLocked())
|
||||
return false;
|
||||
|
||||
SyncLockedTracksIterator git(mList);
|
||||
auto pList = mList.lock();
|
||||
SyncLockedTracksIterator git(pList.get());
|
||||
Track *t = git.StartWith(const_cast<Track*>(this));
|
||||
|
||||
if (!t) {
|
||||
@ -384,7 +388,7 @@ Track *TrackListIterator::StartWith(Track * val)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (val->mList == NULL)
|
||||
if (val->mList.lock() == NULL)
|
||||
return nullptr;
|
||||
|
||||
cur = val->GetNode();
|
||||
@ -790,9 +794,9 @@ void TrackList::Swap(TrackList &that)
|
||||
{
|
||||
ListOfTracks::swap(that);
|
||||
for (auto it = begin(), last = end(); it != last; ++it)
|
||||
(*it)->SetOwner(this, it);
|
||||
(*it)->SetOwner(this->mSelf, it);
|
||||
for (auto it = that.begin(), last = that.end(); it != last; ++it)
|
||||
(*it)->SetOwner(&that, it);
|
||||
(*it)->SetOwner(that.mSelf, it);
|
||||
}
|
||||
|
||||
TrackList::~TrackList()
|
||||
@ -886,7 +890,7 @@ void TrackList::Permute(const std::vector<TrackNodePointer> &permutation)
|
||||
value_type track = std::move(*iter);
|
||||
erase(iter);
|
||||
Track *pTrack = track.get();
|
||||
pTrack->SetOwner(this, insert(end(), std::move(track)));
|
||||
pTrack->SetOwner(mSelf, insert(end(), std::move(track)));
|
||||
}
|
||||
auto n = begin();
|
||||
RecalcPositions(n);
|
||||
@ -900,7 +904,7 @@ Track *TrackList::Add(std::unique_ptr<TrackKind> &&t)
|
||||
push_back(value_type(pTrack = t.release()));
|
||||
auto n = end();
|
||||
--n;
|
||||
pTrack->SetOwner(this, n);
|
||||
pTrack->SetOwner(mSelf, n);
|
||||
RecalcPositions(n);
|
||||
ResizingEvent(n);
|
||||
return back().get();
|
||||
@ -921,7 +925,7 @@ Track *TrackList::AddToHead(std::unique_ptr<TrackKind> &&t)
|
||||
Track *pTrack;
|
||||
push_front(value_type(pTrack = t.release()));
|
||||
auto n = begin();
|
||||
pTrack->SetOwner(this, n);
|
||||
pTrack->SetOwner(mSelf, n);
|
||||
RecalcPositions(n);
|
||||
ResizingEvent(n);
|
||||
return front().get();
|
||||
@ -936,7 +940,7 @@ Track *TrackList::Add(std::shared_ptr<TrackKind> &&t)
|
||||
push_back(t);
|
||||
auto n = end();
|
||||
--n;
|
||||
t->SetOwner(this, n);
|
||||
t->SetOwner(mSelf, n);
|
||||
RecalcPositions(n);
|
||||
ResizingEvent(n);
|
||||
return back().get();
|
||||
@ -951,13 +955,13 @@ auto TrackList::Replace(Track * t, value_type &&with) -> value_type
|
||||
value_type holder;
|
||||
if (t && with) {
|
||||
auto node = t->GetNode();
|
||||
t->SetOwner(nullptr, {});
|
||||
t->SetOwner({}, {});
|
||||
|
||||
holder = std::move(*node);
|
||||
|
||||
Track *pTrack = with.get();
|
||||
*node = std::move(with);
|
||||
pTrack->SetOwner(this, node);
|
||||
pTrack->SetOwner(mSelf, node);
|
||||
RecalcPositions(node);
|
||||
|
||||
DeletionEvent();
|
||||
@ -971,7 +975,7 @@ TrackNodePointer TrackList::Remove(Track *t)
|
||||
TrackNodePointer result(end());
|
||||
if (t) {
|
||||
auto node = t->GetNode();
|
||||
t->SetOwner(nullptr, {});
|
||||
t->SetOwner({}, {});
|
||||
|
||||
if (!isNull(node)) {
|
||||
value_type holder = std::move( *node );
|
||||
@ -1152,12 +1156,12 @@ void TrackList::SwapNodes(TrackNodePointer s1, TrackNodePointer s2)
|
||||
// Reinsert them
|
||||
Track *pTrack;
|
||||
if (save22)
|
||||
pTrack = save22.get(), pTrack->SetOwner(this, s1 = insert(s1, std::move(save22)));
|
||||
pTrack = save21.get(), pTrack->SetOwner(this, s1 = insert(s1, std::move(save21)));
|
||||
pTrack = save22.get(), pTrack->SetOwner(mSelf, s1 = insert(s1, std::move(save22)));
|
||||
pTrack = save21.get(), pTrack->SetOwner(mSelf, s1 = insert(s1, std::move(save21)));
|
||||
|
||||
if (save12)
|
||||
pTrack = save12.get(), pTrack->SetOwner(this, s2 = insert(s2, std::move(save12)));
|
||||
pTrack = save11.get(), pTrack->SetOwner(this, s2 = insert(s2, std::move(save11)));
|
||||
pTrack = save12.get(), pTrack->SetOwner(mSelf, s2 = insert(s2, std::move(save12)));
|
||||
pTrack = save11.get(), pTrack->SetOwner(mSelf, s2 = insert(s2, std::move(save11)));
|
||||
|
||||
// Now correct the Index in the tracks, and other things
|
||||
RecalcPositions(s1);
|
||||
|
25
src/Track.h
25
src/Track.h
@ -91,7 +91,7 @@ class AUDACITY_DLL_API Track /* not final */
|
||||
|
||||
// To be TrackDisplay
|
||||
protected:
|
||||
TrackList *mList;
|
||||
std::weak_ptr<TrackList> mList;
|
||||
TrackNodePointer mNode{};
|
||||
int mIndex;
|
||||
int mY;
|
||||
@ -113,23 +113,29 @@ class AUDACITY_DLL_API Track /* not final */
|
||||
public:
|
||||
|
||||
// Given a bare pointer, find a shared_ptr. But this is not possible for
|
||||
// a track not owned by any list, so the result can be null.
|
||||
// a track not owned by any project, so the result can be null.
|
||||
template<typename Subclass = Track>
|
||||
inline static std::shared_ptr<Subclass> Pointer( Track *t )
|
||||
{
|
||||
if (t && t->mList)
|
||||
if (t) {
|
||||
auto pList = t->mList.lock();
|
||||
if (pList)
|
||||
return std::static_pointer_cast<Subclass>(*t->mNode);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename Subclass = const Track>
|
||||
inline static std::shared_ptr<Subclass> Pointer( const Track *t )
|
||||
{
|
||||
if (t && t->mList) {
|
||||
if (t) {
|
||||
auto pList = t->mList.lock();
|
||||
if (pList) {
|
||||
std::shared_ptr<const Track> p{ *t->mNode };
|
||||
// Let you change the type, but not cast away the const
|
||||
return std::static_pointer_cast<Subclass>(p);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -192,7 +198,8 @@ class AUDACITY_DLL_API Track /* not final */
|
||||
|
||||
private:
|
||||
TrackNodePointer GetNode() const;
|
||||
void SetOwner(TrackList *list, TrackNodePointer node);
|
||||
void SetOwner
|
||||
(const std::weak_ptr<TrackList> &list, TrackNodePointer node);
|
||||
|
||||
// Keep in Track
|
||||
|
||||
@ -542,6 +549,9 @@ class TrackList final : public wxEvtHandler, public ListOfTracks
|
||||
// Move is defined in terms of Swap
|
||||
void Swap(TrackList &that);
|
||||
|
||||
void SetSelf( const std::shared_ptr<TrackList> &self )
|
||||
{ mSelf = self; }
|
||||
|
||||
|
||||
// Destructor
|
||||
virtual ~TrackList();
|
||||
@ -618,7 +628,8 @@ class TrackList final : public wxEvtHandler, public ListOfTracks
|
||||
std::shared_ptr<Subclass> Lock(const std::weak_ptr<Subclass> &wTrack)
|
||||
{
|
||||
auto pTrack = wTrack.lock();
|
||||
if (pTrack && this == pTrack->mList)
|
||||
auto pList = pTrack->mList.lock();
|
||||
if (pTrack && this == pList.get())
|
||||
return pTrack;
|
||||
return {};
|
||||
}
|
||||
@ -654,6 +665,8 @@ private:
|
||||
void ResizingEvent(TrackNodePointer node);
|
||||
|
||||
void SwapNodes(TrackNodePointer s1, TrackNodePointer s2);
|
||||
|
||||
std::weak_ptr<TrackList> mSelf;
|
||||
};
|
||||
|
||||
class AUDACITY_DLL_API TrackFactory
|
||||
|
Loading…
x
Reference in New Issue
Block a user