1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-02 16:49:41 +02:00

Reimplement Track::Pointer using std::enable_shared_from_this...

... now the Track need not be owned yet by a TrackList
This commit is contained in:
Paul Licameli 2018-11-18 20:50:24 -05:00
parent 3dba70120c
commit 6f89c48873
19 changed files with 74 additions and 73 deletions

View File

@ -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)

View File

@ -989,7 +989,7 @@ void MixerBoard::UpdateTrackClusters()
for (auto pPlayableTrack: mTracks->Leaders<PlayableTrack>()) {
// TODO: more-than-two-channels
auto spTrack = Track::Pointer<PlayableTrack>( pPlayableTrack );
auto spTrack = pPlayableTrack->SharedPointer<PlayableTrack>();
if (nClusterIndex < nClusterCount)
{
// Already showing it.

View File

@ -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 >() );
});
}
}

View File

@ -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 );

View File

@ -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> 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<Array>( subRange.begin(), subRange.end(),
[]( Type *t ){ return Track::Pointer<Type>( t ); } );
[]( Type *t ){ return t->template SharedPointer<Type>(); }
);
}
}
@ -1375,7 +1376,7 @@ std::shared_ptr<const Track> Track::SubstitutePendingChangedTrack() const
if (it != end)
return *it;
}
return Pointer( this );
return SharedPointer();
}
std::shared_ptr<const Track> Track::SubstituteOriginalTrack() const
@ -1395,7 +1396,7 @@ std::shared_ptr<const Track> Track::SubstituteOriginalTrack() const
return *it2;
}
}
return Pointer( this );
return SharedPointer();
}
bool TrackList::HasPendingTracks() const

View File

@ -190,6 +190,7 @@ private:
class AUDACITY_DLL_API Track /* not final */
: public CommonTrackPanelCell, public XMLTagHandler
, public std::enable_shared_from_this<Track> // 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<typename Subclass = Track>
inline static std::shared_ptr<Subclass> Pointer( Track *t )
inline std::shared_ptr<Subclass> SharedPointer()
{
if (t) {
auto pList = t->mList.lock();
if (pList)
return std::static_pointer_cast<Subclass>(*t->mNode.first);
}
return {};
// shared_from_this is injected into class scope by base class
// std::enable_shared_from_this<Track>
if (!this) return {};
return std::static_pointer_cast<Subclass>( shared_from_this() );
}
template<typename Subclass = const Track>
inline static std::shared_ptr<Subclass> Pointer( const Track *t )
inline auto SharedPointer() const -> typename
std::enable_if<
std::is_const<Subclass>::value, std::shared_ptr<Subclass>
>::type
{
if (t) {
auto pList = t->mList.lock();
if (pList) {
std::shared_ptr<const Track> p{ *t->mNode.first };
// Let you change the type, but not cast away the const
return std::static_pointer_cast<Subclass>(p);
}
}
return {};
// shared_from_this is injected into class scope by base class
// std::enable_shared_from_this<Track>
if (!this) return {};
return std::static_pointer_cast<Subclass>( shared_from_this() );
}
// Find anything registered with TrackList::RegisterPendingChangedTrack and

View File

@ -2022,7 +2022,7 @@ void TrackArt::DrawSpectrum( TrackPanelDrawingContext &context,
DrawBackgroundWithSelection(
context, rect, track, blankSelectedBrush, blankBrush );
WaveTrackCache cache(Track::Pointer<const WaveTrack>(track));
WaveTrackCache cache(track->SharedPointer<const WaveTrack>());
for (const auto &clip: track->GetClips())
DrawClipSpectrum( context, cache, clip.get(), rect );
}

View File

@ -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);

View File

@ -62,7 +62,8 @@ std::shared_ptr<Track> 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<Track> TrackPanelAx::SetFocus( std::shared_ptr<Track> 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<Track> TrackPanelAx::FindTrack( int num )
{
ndx++;
if( ndx == num )
return Track::Pointer( t );
return t->SharedPointer();
}
return {};

View File

@ -939,7 +939,7 @@ WaveTrackArray ControlToolBar::ChooseExistingRecordingTracks(
}
channelCounts.push_back(nChannels);
for ( auto channel : channels ) {
candidates.push_back(Track::Pointer<WaveTrack>(channel));
candidates.push_back(channel->SharedPointer<WaveTrack>());
if(candidates.size() == recordingChannels)
// Done!
return candidates;

View File

@ -37,7 +37,7 @@ void LabelDefaultClickHandle::SaveState( AudacityProject *pProject )
for (auto lt : tracks->Any<LabelTrack>())
pairs.push_back( std::make_pair(
Track::Pointer<LabelTrack>( lt ), lt->SaveFlags() ) );
lt->SharedPointer<LabelTrack>(), lt->SaveFlags() ) );
}
void LabelDefaultClickHandle::RestoreState( AudacityProject *pProject )

View File

@ -30,12 +30,12 @@ std::vector<UIHandlePtr> LabelTrack::DetailedHitTest
const wxMouseState &state = st.state;
result = LabelGlyphHandle::HitTest(
mGlyphHandle, state, Pointer<LabelTrack>(this), st.rect);
mGlyphHandle, state, SharedPointer<LabelTrack>(), st.rect);
if (result)
results.push_back(result);
result = LabelTextHandle::HitTest(
mTextHandle, state, Pointer<LabelTrack>(this));
mTextHandle, state, SharedPointer<LabelTrack>());
if (result)
results.push_back(result);
@ -44,10 +44,10 @@ std::vector<UIHandlePtr> LabelTrack::DetailedHitTest
std::shared_ptr<TrackControls> LabelTrack::GetControls()
{
return std::make_shared<LabelTrackControls>( Pointer( this ) );
return std::make_shared<LabelTrackControls>( SharedPointer() );
}
std::shared_ptr<TrackVRulerControls> LabelTrack::GetVRulerControls()
{
return std::make_shared<LabelTrackVRulerControls>( Pointer( this ) );
return std::make_shared<LabelTrackVRulerControls>( SharedPointer() );
}

View File

@ -43,11 +43,11 @@ std::vector<UIHandlePtr> NoteTrack::DetailedHitTest
std::shared_ptr<TrackControls> NoteTrack::GetControls()
{
return std::make_shared<NoteTrackControls>( Pointer( this ) );
return std::make_shared<NoteTrackControls>( SharedPointer() );
}
std::shared_ptr<TrackVRulerControls> NoteTrack::GetVRulerControls()
{
return std::make_shared<NoteTrackVRulerControls>( Pointer( this ) );
return std::make_shared<NoteTrackVRulerControls>( SharedPointer() );
}
#endif

View File

@ -41,7 +41,7 @@ std::vector<UIHandlePtr> 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<UIHandlePtr> WaveTrack::DetailedHitTest
if (NULL != (result = CutlineHandle::HitTest(
mCutlineHandle, st.state, st.rect,
pProject, Pointer<WaveTrack>(this))))
pProject, SharedPointer<WaveTrack>())))
// This overriding test applies in all tools
results.push_back(result);
if (bMultiTool) {
@ -63,16 +63,16 @@ std::vector<UIHandlePtr> WaveTrack::DetailedHitTest
// point, seems arbitrary
if (NULL != (result = EnvelopeHandle::WaveTrackHitTest(
mEnvelopeHandle, st.state, st.rect,
pProject, Pointer<WaveTrack>(this))))
pProject, SharedPointer<WaveTrack>())))
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<WaveTrack>(this))))
pProject, SharedPointer<WaveTrack>())))
results.push_back(result);
}
else {
@ -87,7 +87,7 @@ std::vector<UIHandlePtr> WaveTrack::DetailedHitTest
}
case drawTool:
result = SampleHandle::HitAnywhere(
mSampleHandle, st.state, Pointer<WaveTrack>(this));
mSampleHandle, st.state, SharedPointer<WaveTrack>());
break;
default:
result = {};
@ -103,10 +103,10 @@ std::vector<UIHandlePtr> WaveTrack::DetailedHitTest
std::shared_ptr<TrackControls> WaveTrack::GetControls()
{
return std::make_shared<WaveTrackControls>( Pointer( this ) );
return std::make_shared<WaveTrackControls>( SharedPointer() );
}
std::shared_ptr<TrackVRulerControls> WaveTrack::GetVRulerControls()
{
return std::make_shared<WaveTrackVRulerControls>( Pointer( this ) );
return std::make_shared<WaveTrackVRulerControls>( SharedPointer() );
}

View File

@ -33,7 +33,7 @@ std::vector<UIHandlePtr> WaveTrackVRulerControls::HitTest
std::vector<UIHandlePtr> results;
if ( st.state.GetX() <= st.rect.GetRight() - kGuard ) {
auto pTrack = Track::Pointer<WaveTrack>( FindTrack().get() );
auto pTrack = FindTrack()->SharedPointer<WaveTrack>( );
if (pTrack) {
auto result = std::make_shared<WaveTrackVZoomHandle>(
pTrack, st.rect, st.state.m_y );

View File

@ -23,8 +23,8 @@ std::vector<UIHandlePtr> TimeTrack::DetailedHitTest
const AudacityProject *pProject, int, bool)
{
std::vector<UIHandlePtr> results;
auto result = EnvelopeHandle::TimeTrackHitTest
( mEnvelopeHandle, st.state, st.rect, pProject, Pointer<TimeTrack>(this) );
auto result = EnvelopeHandle::TimeTrackHitTest(
mEnvelopeHandle, st.state, st.rect, pProject, SharedPointer<TimeTrack>() );
if (result)
results.push_back(result);
return results;
@ -32,10 +32,10 @@ std::vector<UIHandlePtr> TimeTrack::DetailedHitTest
std::shared_ptr<TrackControls> TimeTrack::GetControls()
{
return std::make_shared<TimeTrackControls>( Pointer( this ) );
return std::make_shared<TimeTrackControls>( SharedPointer() );
}
std::shared_ptr<TrackVRulerControls> TimeTrack::GetVRulerControls()
{
return std::make_shared<TimeTrackVRulerControls>( Pointer( this ) );
return std::make_shared<TimeTrackVRulerControls>( SharedPointer() );
}

View File

@ -639,7 +639,7 @@ UIHandle::Result SelectHandle::Click
case SBBottom:
case SBTop:
{
mFreqSelTrack = Track::Pointer<const WaveTrack>( pTrack );
mFreqSelTrack = pTrack->SharedPointer<const WaveTrack>();
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<const WaveTrack>( pTrack );
mFreqSelTrack = pTrack->SharedPointer<const WaveTrack>();
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<const WaveTrack>( pTrack );
mFreqSelTrack = pTrack->SharedPointer<const WaveTrack>();
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<const WaveTrack>( pTrack );
auto shTrack = pTrack->SharedPointer<const WaveTrack>();
mFreqSelTrack = shTrack;
mFreqSelMode = FREQ_SEL_FREE;
mFreqSelPin =
@ -1304,7 +1304,7 @@ void SelectHandle::HandleCenterFrequencyClick
if (shiftDown) {
// Disable time selection
mSelStartValid = false;
mFreqSelTrack = Track::Pointer<const WaveTrack>( pTrack );
mFreqSelTrack = pTrack->SharedPointer<const WaveTrack>();
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<const WaveTrack>( wt );
mFreqSelTrack = wt->SharedPointer<const WaveTrack>();
// SelectNone();
// SelectTrack(pTrack, true);

View File

@ -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;

View File

@ -53,7 +53,7 @@ std::vector<UIHandlePtr> 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<UIHandlePtr> 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<TrackPanelCell> Track::GetResizer()
{
if (!mpResizer)
// create on demand
mpResizer = std::make_shared<TrackPanelResizerCell>( Pointer( this ) );
mpResizer = std::make_shared<TrackPanelResizerCell>( SharedPointer() );
return mpResizer;
}