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