diff --git a/src/Mix.cpp b/src/Mix.cpp index 1621cec64..0732d065d 100644 --- a/src/Mix.cpp +++ b/src/Mix.cpp @@ -85,7 +85,7 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory, WaveTrackConstArray waveArray; for(auto wt : trackRange) { - waveArray.push_back( Track::Pointer< const WaveTrack >( wt ) ); + waveArray.push_back( wt->SharedPointer< const WaveTrack >() ); tstart = wt->GetStartTime(); tend = wt->GetEndTime(); if (tend > mixEndTime) diff --git a/src/MixerBoard.cpp b/src/MixerBoard.cpp index 28e7e15d2..4635230a7 100644 --- a/src/MixerBoard.cpp +++ b/src/MixerBoard.cpp @@ -989,7 +989,7 @@ void MixerBoard::UpdateTrackClusters() for (auto pPlayableTrack: mTracks->Leaders()) { // TODO: more-than-two-channels - auto spTrack = Track::Pointer( pPlayableTrack ); + auto spTrack = pPlayableTrack->SharedPointer(); if (nClusterIndex < nClusterCount) { // Already showing it. diff --git a/src/Project.cpp b/src/Project.cpp index b6f233dc5..9250fad86 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -4198,7 +4198,7 @@ AudacityProject::AddImportedTracks(const FilePath &fileName, auto nChannels = group.size(); for (auto &uNewTrack : group) { auto newTrack = mTracks->Add(std::move(uNewTrack)); - results.push_back(Track::Pointer(newTrack)); + results.push_back(newTrack->SharedPointer()); } mTracks->GroupChannels(*first, nChannels); } @@ -4337,7 +4337,7 @@ bool AudacityProject::Import(const FilePath &fileName, WaveTrackArray* pTrackArr if (pTrackArray) { for (const auto &newTrack : newSharedTracks) { newTrack->TypeSwitch( [&](WaveTrack *wt) { - pTrackArray->push_back( Track::Pointer< WaveTrack >( wt ) ); + pTrackArray->push_back( wt->SharedPointer< WaveTrack >() ); }); } } diff --git a/src/SelectionState.cpp b/src/SelectionState.cpp index 80fef8404..d376aff60 100644 --- a/src/SelectionState.cpp +++ b/src/SelectionState.cpp @@ -42,7 +42,7 @@ void SelectionState::SelectTrack( channel->SetSelected(selected); if (updateLastPicked) - mLastPickedTrack = Track::Pointer( &track ); + mLastPickedTrack = track.SharedPointer(); //The older code below avoids an anchor on an unselected track. @@ -92,11 +92,11 @@ void SelectionState::ChangeSelectionOnShiftClick // If our track is at or after the first, extend from the first. if( pFirst && track.GetIndex() >= pFirst->GetIndex() ) - pExtendFrom = Track::Pointer( pFirst ); + pExtendFrom = pFirst->SharedPointer(); // Our track was earlier than the first. Extend from the last. if( !pExtendFrom ) - pExtendFrom = Track::Pointer( *trackRange.rbegin() ); + pExtendFrom = (*trackRange.rbegin())->SharedPointer(); } SelectNone( tracks ); diff --git a/src/Track.cpp b/src/Track.cpp index 30eb10296..72a245a59 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -105,7 +105,7 @@ void Track::SetSelected(bool s) mSelected = s; auto pList = mList.lock(); if (pList) - pList->SelectionEvent( Pointer( this ) ); + pList->SelectionEvent( SharedPointer() ); } } @@ -351,7 +351,7 @@ void Track::Notify( int code ) { auto pList = mList.lock(); if (pList) - pList->DataEvent( Pointer(this), code ); + pList->DataEvent( SharedPointer(), code ); } void Track::SyncLockAdjust(double oldT1, double newT1) @@ -374,7 +374,7 @@ void Track::SyncLockAdjust(double oldT1, double newT1) std::shared_ptr Track::FindTrack() { - return Pointer( this ); + return SharedPointer(); } void PlayableTrack::Init( const PlayableTrack &orig ) @@ -1162,7 +1162,8 @@ namespace { if ( ! includeMuted ) subRange = subRange - &Type::GetMute; return transform_range( subRange.begin(), subRange.end(), - []( Type *t ){ return Track::Pointer( t ); } ); + []( Type *t ){ return t->template SharedPointer(); } + ); } } @@ -1375,7 +1376,7 @@ std::shared_ptr Track::SubstitutePendingChangedTrack() const if (it != end) return *it; } - return Pointer( this ); + return SharedPointer(); } std::shared_ptr Track::SubstituteOriginalTrack() const @@ -1395,7 +1396,7 @@ std::shared_ptr Track::SubstituteOriginalTrack() const return *it2; } } - return Pointer( this ); + return SharedPointer(); } bool TrackList::HasPendingTracks() const diff --git a/src/Track.h b/src/Track.h index 0c9cb4ea2..b2af7f7d5 100644 --- a/src/Track.h +++ b/src/Track.h @@ -190,6 +190,7 @@ private: class AUDACITY_DLL_API Track /* not final */ : public CommonTrackPanelCell, public XMLTagHandler + , public std::enable_shared_from_this // see SharedPointer() { friend class TrackList; @@ -227,31 +228,29 @@ class AUDACITY_DLL_API Track /* not final */ void SetId( TrackId id ) { mId = id; } public: - // Given a bare pointer, find a shared_ptr. But this is not possible for - // a track not owned by any project, so the result can be null. + // Given a bare pointer, find a shared_ptr. Undefined results if the track + // is not yet managed by a shared_ptr. Undefined results if the track is + // not really of the subclass. (That is, trusts the caller and uses static + // not dynamic casting.) template - inline static std::shared_ptr Pointer( Track *t ) + inline std::shared_ptr SharedPointer() { - if (t) { - auto pList = t->mList.lock(); - if (pList) - return std::static_pointer_cast(*t->mNode.first); - } - return {}; + // shared_from_this is injected into class scope by base class + // std::enable_shared_from_this + if (!this) return {}; + return std::static_pointer_cast( shared_from_this() ); } template - inline static std::shared_ptr Pointer( const Track *t ) + inline auto SharedPointer() const -> typename + std::enable_if< + std::is_const::value, std::shared_ptr + >::type { - if (t) { - auto pList = t->mList.lock(); - if (pList) { - std::shared_ptr p{ *t->mNode.first }; - // Let you change the type, but not cast away the const - return std::static_pointer_cast(p); - } - } - return {}; + // shared_from_this is injected into class scope by base class + // std::enable_shared_from_this + if (!this) return {}; + return std::static_pointer_cast( shared_from_this() ); } // Find anything registered with TrackList::RegisterPendingChangedTrack and diff --git a/src/TrackArtist.cpp b/src/TrackArtist.cpp index 63db748e3..7115368a3 100644 --- a/src/TrackArtist.cpp +++ b/src/TrackArtist.cpp @@ -2022,7 +2022,7 @@ void TrackArt::DrawSpectrum( TrackPanelDrawingContext &context, DrawBackgroundWithSelection( context, rect, track, blankSelectedBrush, blankBrush ); - WaveTrackCache cache(Track::Pointer(track)); + WaveTrackCache cache(track->SharedPointer()); for (const auto &clip: track->GetClips()) DrawClipSpectrum( context, cache, clip.get(), rect ); } diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 3610d9e03..91b1e1f9b 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -2054,10 +2054,10 @@ struct ChannelGroup final : TrackPanelGroup { for ( auto channel : channels ) { refinement.emplace_back( yy, std::make_shared< VRulerAndChannel >( - Track::Pointer( channel ), mLeftOffset ) ); + channel->SharedPointer(), mLeftOffset ) ); if ( channel != pLast ) { const auto substitute = - Track::Pointer( channel )->SubstitutePendingChangedTrack(); + channel->SubstitutePendingChangedTrack(); yy += substitute->GetHeight(); refinement.emplace_back( yy - kSeparatorThickness, channel->GetResizer() ); @@ -2120,12 +2120,12 @@ struct Subgroup final : TrackPanelGroup { wxCoord height = 0; for ( auto channel : TrackList::Channels( leader ) ) { auto substitute = - Track::Pointer( channel )->SubstitutePendingChangedTrack(); + channel->SubstitutePendingChangedTrack(); height += substitute->GetHeight(); } refinement.emplace_back( yy, std::make_shared< ResizingChannelGroup >( - Track::Pointer( leader ), mPanel.GetLeftOffset() ) + leader->SharedPointer(), mPanel.GetLeftOffset() ) ); yy += height; } @@ -2241,7 +2241,7 @@ void TrackPanel::SetFocusedTrack( Track *t ) // Make sure we always have the first linked track of a stereo track t = *GetTracks()->FindLeader(t); - auto cell = mAx->SetFocus( Track::Pointer( t ) ).get(); + auto cell = mAx->SetFocus( t->SharedPointer() ).get(); if (cell) { AudacityProject::CaptureKeyboard(this); diff --git a/src/TrackPanelAx.cpp b/src/TrackPanelAx.cpp index a9c9d3697..a66385c6c 100644 --- a/src/TrackPanelAx.cpp +++ b/src/TrackPanelAx.cpp @@ -62,7 +62,8 @@ std::shared_ptr TrackPanelAx::GetFocus() focusedTrack = FindTrack(mNumFocusedTrack); } if (!focusedTrack) { - focusedTrack = Track::Pointer( *mTrackPanel->GetTracks()->Any().first ); + focusedTrack = + (*mTrackPanel->GetTracks()->Any().first)->SharedPointer(); // only call SetFocus if the focus has changed to avoid // unnecessary focus events if (focusedTrack) @@ -97,7 +98,7 @@ std::shared_ptr TrackPanelAx::SetFocus( std::shared_ptr track ) #endif if( !track ) - track = Track::Pointer( *mTrackPanel->GetTracks()->Any().begin() ); + track = (*mTrackPanel->GetTracks()->Any().begin())->SharedPointer(); mFocusedTrack = track; mNumFocusedTrack = TrackNum(track); @@ -175,7 +176,7 @@ std::shared_ptr TrackPanelAx::FindTrack( int num ) { ndx++; if( ndx == num ) - return Track::Pointer( t ); + return t->SharedPointer(); } return {}; diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index f0fcb61ed..4bf454ad4 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -939,7 +939,7 @@ WaveTrackArray ControlToolBar::ChooseExistingRecordingTracks( } channelCounts.push_back(nChannels); for ( auto channel : channels ) { - candidates.push_back(Track::Pointer(channel)); + candidates.push_back(channel->SharedPointer()); if(candidates.size() == recordingChannels) // Done! return candidates; diff --git a/src/tracks/labeltrack/ui/LabelDefaultClickHandle.cpp b/src/tracks/labeltrack/ui/LabelDefaultClickHandle.cpp index 84bc458c7..82c56e078 100644 --- a/src/tracks/labeltrack/ui/LabelDefaultClickHandle.cpp +++ b/src/tracks/labeltrack/ui/LabelDefaultClickHandle.cpp @@ -37,7 +37,7 @@ void LabelDefaultClickHandle::SaveState( AudacityProject *pProject ) for (auto lt : tracks->Any()) pairs.push_back( std::make_pair( - Track::Pointer( lt ), lt->SaveFlags() ) ); + lt->SharedPointer(), lt->SaveFlags() ) ); } void LabelDefaultClickHandle::RestoreState( AudacityProject *pProject ) diff --git a/src/tracks/labeltrack/ui/LabelTrackUI.cpp b/src/tracks/labeltrack/ui/LabelTrackUI.cpp index fb3e96920..1d73d0c18 100644 --- a/src/tracks/labeltrack/ui/LabelTrackUI.cpp +++ b/src/tracks/labeltrack/ui/LabelTrackUI.cpp @@ -30,12 +30,12 @@ std::vector LabelTrack::DetailedHitTest const wxMouseState &state = st.state; result = LabelGlyphHandle::HitTest( - mGlyphHandle, state, Pointer(this), st.rect); + mGlyphHandle, state, SharedPointer(), st.rect); if (result) results.push_back(result); result = LabelTextHandle::HitTest( - mTextHandle, state, Pointer(this)); + mTextHandle, state, SharedPointer()); if (result) results.push_back(result); @@ -44,10 +44,10 @@ std::vector LabelTrack::DetailedHitTest std::shared_ptr LabelTrack::GetControls() { - return std::make_shared( Pointer( this ) ); + return std::make_shared( SharedPointer() ); } std::shared_ptr LabelTrack::GetVRulerControls() { - return std::make_shared( Pointer( this ) ); + return std::make_shared( SharedPointer() ); } diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackUI.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackUI.cpp index 7839ec8d5..a218848e5 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackUI.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackUI.cpp @@ -43,11 +43,11 @@ std::vector NoteTrack::DetailedHitTest std::shared_ptr NoteTrack::GetControls() { - return std::make_shared( Pointer( this ) ); + return std::make_shared( SharedPointer() ); } std::shared_ptr NoteTrack::GetVRulerControls() { - return std::make_shared( Pointer( this ) ); + return std::make_shared( SharedPointer() ); } #endif diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackUI.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackUI.cpp index f1f1af187..f56c77581 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackUI.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackUI.cpp @@ -41,7 +41,7 @@ std::vector WaveTrack::DetailedHitTest // (But this does not do the time shift constrained to the vertical only, // which is what happens when you hold Ctrl in the Time Shift tool mode) result = TimeShiftHandle::HitAnywhere( - mTimeShiftHandle, Pointer(this), false); + mTimeShiftHandle, SharedPointer(), false); if (result) results.push_back(result); return results; @@ -53,7 +53,7 @@ std::vector WaveTrack::DetailedHitTest if (NULL != (result = CutlineHandle::HitTest( mCutlineHandle, st.state, st.rect, - pProject, Pointer(this)))) + pProject, SharedPointer()))) // This overriding test applies in all tools results.push_back(result); if (bMultiTool) { @@ -63,16 +63,16 @@ std::vector WaveTrack::DetailedHitTest // point, seems arbitrary if (NULL != (result = EnvelopeHandle::WaveTrackHitTest( mEnvelopeHandle, st.state, st.rect, - pProject, Pointer(this)))) + pProject, SharedPointer()))) results.push_back(result); if (NULL != (result = TimeShiftHandle::HitTest( - mTimeShiftHandle, st.state, st.rect, Pointer(this)))) + mTimeShiftHandle, st.state, st.rect, SharedPointer()))) // This is the hit test on the "grips" drawn left and // right in Multi only results.push_back(result); if (NULL != (result = SampleHandle::HitTest( mSampleHandle, st.state, st.rect, - pProject, Pointer(this)))) + pProject, SharedPointer()))) results.push_back(result); } else { @@ -87,7 +87,7 @@ std::vector WaveTrack::DetailedHitTest } case drawTool: result = SampleHandle::HitAnywhere( - mSampleHandle, st.state, Pointer(this)); + mSampleHandle, st.state, SharedPointer()); break; default: result = {}; @@ -103,10 +103,10 @@ std::vector WaveTrack::DetailedHitTest std::shared_ptr WaveTrack::GetControls() { - return std::make_shared( Pointer( this ) ); + return std::make_shared( SharedPointer() ); } std::shared_ptr WaveTrack::GetVRulerControls() { - return std::make_shared( Pointer( this ) ); + return std::make_shared( SharedPointer() ); } diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackVRulerControls.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackVRulerControls.cpp index 38231bb4c..e8c9f403c 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackVRulerControls.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackVRulerControls.cpp @@ -33,7 +33,7 @@ std::vector WaveTrackVRulerControls::HitTest std::vector results; if ( st.state.GetX() <= st.rect.GetRight() - kGuard ) { - auto pTrack = Track::Pointer( FindTrack().get() ); + auto pTrack = FindTrack()->SharedPointer( ); if (pTrack) { auto result = std::make_shared( pTrack, st.rect, st.state.m_y ); diff --git a/src/tracks/timetrack/ui/TimeTrackUI.cpp b/src/tracks/timetrack/ui/TimeTrackUI.cpp index 10ad047a2..3500beef9 100644 --- a/src/tracks/timetrack/ui/TimeTrackUI.cpp +++ b/src/tracks/timetrack/ui/TimeTrackUI.cpp @@ -23,8 +23,8 @@ std::vector TimeTrack::DetailedHitTest const AudacityProject *pProject, int, bool) { std::vector results; - auto result = EnvelopeHandle::TimeTrackHitTest - ( mEnvelopeHandle, st.state, st.rect, pProject, Pointer(this) ); + auto result = EnvelopeHandle::TimeTrackHitTest( + mEnvelopeHandle, st.state, st.rect, pProject, SharedPointer() ); if (result) results.push_back(result); return results; @@ -32,10 +32,10 @@ std::vector TimeTrack::DetailedHitTest std::shared_ptr TimeTrack::GetControls() { - return std::make_shared( Pointer( this ) ); + return std::make_shared( SharedPointer() ); } std::shared_ptr TimeTrack::GetVRulerControls() { - return std::make_shared( Pointer( this ) ); + return std::make_shared( SharedPointer() ); } diff --git a/src/tracks/ui/SelectHandle.cpp b/src/tracks/ui/SelectHandle.cpp index 307140f06..e059c408e 100644 --- a/src/tracks/ui/SelectHandle.cpp +++ b/src/tracks/ui/SelectHandle.cpp @@ -639,7 +639,7 @@ UIHandle::Result SelectHandle::Click case SBBottom: case SBTop: { - mFreqSelTrack = Track::Pointer( pTrack ); + mFreqSelTrack = pTrack->SharedPointer(); mFreqSelPin = value; mFreqSelMode = (boundary == SBBottom) @@ -694,7 +694,7 @@ UIHandle::Result SelectHandle::Click // Ignore whether we are inside the time selection. // Exit center-snapping, start dragging the width. mFreqSelMode = FREQ_SEL_PINNED_CENTER; - mFreqSelTrack = Track::Pointer( pTrack ); + mFreqSelTrack = pTrack->SharedPointer(); mFreqSelPin = viewInfo.selectedRegion.fc(); // Do not adjust time boundaries mSelStartValid = false; @@ -736,7 +736,7 @@ UIHandle::Result SelectHandle::Click startNewSelection = false; // Disable time selection mSelStartValid = false; - mFreqSelTrack = Track::Pointer( pTrack ); + mFreqSelTrack = pTrack->SharedPointer(); mFreqSelPin = value; mFreqSelMode = (boundary == SBWidth) ? FREQ_SEL_PINNED_CENTER : @@ -1143,7 +1143,7 @@ void SelectHandle::AdjustSelection std::max(0.0, viewInfo.PositionToTime(mouseXCoordinate, trackLeftEdge)); double origSelend = selend; - auto pTrack = Track::Pointer( track ); + auto pTrack = track->SharedPointer(); if (!pTrack) pTrack = pProject->GetTracks()->Lock(mpTrack); @@ -1205,7 +1205,7 @@ void SelectHandle::StartFreqSelection(ViewInfo &viewInfo, if (isSpectralSelectionTrack(pTrack)) { // Spectral selection track is always wave - auto shTrack = Track::Pointer( pTrack ); + auto shTrack = pTrack->SharedPointer(); mFreqSelTrack = shTrack; mFreqSelMode = FREQ_SEL_FREE; mFreqSelPin = @@ -1304,7 +1304,7 @@ void SelectHandle::HandleCenterFrequencyClick if (shiftDown) { // Disable time selection mSelStartValid = false; - mFreqSelTrack = Track::Pointer( pTrack ); + mFreqSelTrack = pTrack->SharedPointer(); mFreqSelPin = value; mFreqSelMode = FREQ_SEL_DRAG_CENTER; } @@ -1405,7 +1405,7 @@ void SelectHandle::MoveSnappingFreqSelection // A change here would affect what AdjustFreqSelection() does // in the prototype version where you switch from moving center to // dragging width with a click. No effect now. - mFreqSelTrack = Track::Pointer( wt ); + mFreqSelTrack = wt->SharedPointer(); // SelectNone(); // SelectTrack(pTrack, true); diff --git a/src/tracks/ui/TimeShiftHandle.cpp b/src/tracks/ui/TimeShiftHandle.cpp index 3bd5b2891..5cc3140bd 100644 --- a/src/tracks/ui/TimeShiftHandle.cpp +++ b/src/tracks/ui/TimeShiftHandle.cpp @@ -693,7 +693,7 @@ UIHandle::Result TimeShiftHandle::Drag } // May need a shared_ptr to reassign mCapturedTrack below - auto pTrack = Track::Pointer( track ); + auto pTrack = track->SharedPointer(); if (!pTrack) return RefreshCode::RefreshNone; diff --git a/src/tracks/ui/TrackUI.cpp b/src/tracks/ui/TrackUI.cpp index 037fcfa68..5d34ef1e6 100644 --- a/src/tracks/ui/TrackUI.cpp +++ b/src/tracks/ui/TrackUI.cpp @@ -53,7 +53,7 @@ std::vector Track::HitTest // Sliding applies in more than one track type. if ( !isMultiTool && currentTool == slideTool ) { result = TimeShiftHandle::HitAnywhere( - mTimeShiftHandle, Pointer(this), false); + mTimeShiftHandle, SharedPointer(), false); if (result) results.push_back(result); } @@ -70,7 +70,7 @@ std::vector Track::HitTest // Finally, default of all is adjustment of the selection box. if ( isMultiTool || currentTool == selectTool ) { result = SelectHandle::HitTest( - mSelectHandle, st, pProject, Pointer(this)); + mSelectHandle, st, pProject, SharedPointer()); if (result) results.push_back(result); } @@ -99,6 +99,6 @@ std::shared_ptr Track::GetResizer() { if (!mpResizer) // create on demand - mpResizer = std::make_shared( Pointer( this ) ); + mpResizer = std::make_shared( SharedPointer() ); return mpResizer; }