mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-15 15:49:36 +02:00
All tracks allocated with make_shared, no more make_unique...
... so that we can use Track::SharedPointer without undefined behavior even on tracks that don't yet belong to any TrackList. Also fix the return type of function template TrackList::Add and remove some casts.
This commit is contained in:
parent
6f89c48873
commit
a0aa69a248
@ -99,7 +99,7 @@ int LabelTrack::mFontHeight=-1;
|
||||
|
||||
LabelTrack::Holder TrackFactory::NewLabelTrack()
|
||||
{
|
||||
return std::make_unique<LabelTrack>(mDirManager);
|
||||
return std::make_shared<LabelTrack>(mDirManager);
|
||||
}
|
||||
|
||||
LabelTrack::LabelTrack(const std::shared_ptr<DirManager> &projDirManager):
|
||||
@ -1142,7 +1142,7 @@ double LabelTrack::GetEndTime() const
|
||||
|
||||
Track::Holder LabelTrack::Duplicate() const
|
||||
{
|
||||
return std::make_unique<LabelTrack>( *this );
|
||||
return std::make_shared<LabelTrack>( *this );
|
||||
}
|
||||
|
||||
void LabelTrack::SetSelected(bool s)
|
||||
@ -2489,7 +2489,7 @@ Track::Holder LabelTrack::SplitCut(double t0, double t1)
|
||||
|
||||
Track::Holder LabelTrack::Copy(double t0, double t1, bool) const
|
||||
{
|
||||
auto tmp = std::make_unique<LabelTrack>(GetDirManager());
|
||||
auto tmp = std::make_shared<LabelTrack>(GetDirManager());
|
||||
const auto lt = static_cast<LabelTrack*>(tmp.get());
|
||||
|
||||
for (auto &labelStruct: mLabels) {
|
||||
@ -2534,8 +2534,7 @@ Track::Holder LabelTrack::Copy(double t0, double t1, bool) const
|
||||
}
|
||||
lt->mClipLen = (t1 - t0);
|
||||
|
||||
// This std::move is needed to "upcast" the pointer type
|
||||
return std::move(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,7 +161,7 @@ class AUDACITY_DLL_API LabelTrack final : public Track
|
||||
double GetStartTime() const override;
|
||||
double GetEndTime() const override;
|
||||
|
||||
using Holder = std::unique_ptr<LabelTrack>;
|
||||
using Holder = std::shared_ptr<LabelTrack>;
|
||||
Track::Holder Duplicate() const override;
|
||||
|
||||
void SetSelected(bool s) override;
|
||||
|
@ -49,7 +49,8 @@ class WaveTrackCache;
|
||||
void MixAndRender(TrackList * tracks, TrackFactory *factory,
|
||||
double rate, sampleFormat format,
|
||||
double startTime, double endTime,
|
||||
std::unique_ptr<WaveTrack> &uLeft, std::unique_ptr<WaveTrack> &uRight);
|
||||
std::shared_ptr<WaveTrack> &uLeft,
|
||||
std::shared_ptr<WaveTrack> &uRight);
|
||||
|
||||
void MixBuffers(unsigned numChannels, int *channelFlags, float *gains,
|
||||
samplePtr src,
|
||||
|
@ -104,7 +104,7 @@ SONFNS(AutoSave)
|
||||
|
||||
NoteTrack::Holder TrackFactory::NewNoteTrack()
|
||||
{
|
||||
return std::make_unique<NoteTrack>(mDirManager);
|
||||
return std::make_shared<NoteTrack>(mDirManager);
|
||||
}
|
||||
|
||||
NoteTrack::NoteTrack(const std::shared_ptr<DirManager> &projDirManager)
|
||||
@ -155,7 +155,7 @@ Alg_seq &NoteTrack::GetSeq() const
|
||||
|
||||
Track::Holder NoteTrack::Duplicate() const
|
||||
{
|
||||
auto duplicate = std::make_unique<NoteTrack>(mDirManager);
|
||||
auto duplicate = std::make_shared<NoteTrack>(mDirManager);
|
||||
duplicate->Init(*this);
|
||||
// The duplicate begins life in serialized state. Often the duplicate is
|
||||
// pushed on the Undo stack. Then we want to un-serialize it (or a further
|
||||
@ -190,8 +190,7 @@ Track::Holder NoteTrack::Duplicate() const
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
duplicate->SetVelocity(GetVelocity());
|
||||
#endif
|
||||
// This std::move is needed to "upcast" the pointer type
|
||||
return std::move(duplicate);
|
||||
return duplicate;
|
||||
}
|
||||
|
||||
|
||||
@ -463,7 +462,7 @@ Track::Holder NoteTrack::Cut(double t0, double t1)
|
||||
//( std::min( t1, GetEndTime() ) ) - ( std::max( t0, GetStartTime() ) )
|
||||
//);
|
||||
|
||||
auto newTrack = std::make_unique<NoteTrack>(mDirManager);
|
||||
auto newTrack = std::make_shared<NoteTrack>(mDirManager);
|
||||
|
||||
newTrack->Init(*this);
|
||||
|
||||
@ -480,8 +479,7 @@ Track::Holder NoteTrack::Cut(double t0, double t1)
|
||||
//(mBottomNote, mDirManager,
|
||||
// mSerializationBuffer, mSerializationLength, mVisibleChannels)
|
||||
|
||||
// This std::move is needed to "upcast" the pointer type
|
||||
return std::move(newTrack);
|
||||
return newTrack;
|
||||
}
|
||||
|
||||
Track::Holder NoteTrack::Copy(double t0, double t1, bool) const
|
||||
@ -491,7 +489,7 @@ Track::Holder NoteTrack::Copy(double t0, double t1, bool) const
|
||||
|
||||
double len = t1-t0;
|
||||
|
||||
auto newTrack = std::make_unique<NoteTrack>(mDirManager);
|
||||
auto newTrack = std::make_shared<NoteTrack>(mDirManager);
|
||||
|
||||
newTrack->Init(*this);
|
||||
|
||||
@ -504,8 +502,7 @@ Track::Holder NoteTrack::Copy(double t0, double t1, bool) const
|
||||
// (mBottomNote, mDirManager, mSerializationBuffer,
|
||||
// mSerializationLength, mVisibleChannels)
|
||||
|
||||
// This std::move is needed to "upcast" the pointer type
|
||||
return std::move(newTrack);
|
||||
return newTrack;
|
||||
}
|
||||
|
||||
bool NoteTrack::Trim(double t0, double t1)
|
||||
|
@ -75,7 +75,7 @@ class AUDACITY_DLL_API NoteTrack final
|
||||
const AudacityProject *pProject, int currentTool, bool bMultiTool)
|
||||
override;
|
||||
|
||||
using Holder = std::unique_ptr<NoteTrack>;
|
||||
using Holder = std::shared_ptr<NoteTrack>;
|
||||
Track::Holder Duplicate() const override;
|
||||
|
||||
double GetOffset() const override;
|
||||
|
@ -33,9 +33,9 @@
|
||||
#define TIMETRACK_MIN 0.01
|
||||
#define TIMETRACK_MAX 10.0
|
||||
|
||||
std::unique_ptr<TimeTrack> TrackFactory::NewTimeTrack()
|
||||
std::shared_ptr<TimeTrack> TrackFactory::NewTimeTrack()
|
||||
{
|
||||
return std::make_unique<TimeTrack>(mDirManager, mZoomInfo);
|
||||
return std::make_shared<TimeTrack>(mDirManager, mZoomInfo);
|
||||
}
|
||||
|
||||
TimeTrack::TimeTrack(const std::shared_ptr<DirManager> &projDirManager, const ZoomInfo *zoomInfo):
|
||||
@ -108,8 +108,7 @@ Track::Holder TimeTrack::Cut( double t0, double t1 )
|
||||
|
||||
Track::Holder TimeTrack::Copy( double t0, double t1, bool ) const
|
||||
{
|
||||
auto result = std::make_unique<TimeTrack>( *this, &t0, &t1 );
|
||||
return Track::Holder{ std::move( result ) };
|
||||
return std::make_shared<TimeTrack>( *this, &t0, &t1 );
|
||||
}
|
||||
|
||||
void TimeTrack::Clear(double t0, double t1)
|
||||
@ -143,7 +142,7 @@ void TimeTrack::InsertSilence(double t, double len)
|
||||
|
||||
Track::Holder TimeTrack::Duplicate() const
|
||||
{
|
||||
return std::make_unique<TimeTrack>(*this);
|
||||
return std::make_shared<TimeTrack>(*this);
|
||||
}
|
||||
|
||||
bool TimeTrack::GetInterpolateLog() const
|
||||
|
@ -728,35 +728,10 @@ Track *TrackList::FindById( TrackId id )
|
||||
return it->get();
|
||||
}
|
||||
|
||||
template<typename TrackKind>
|
||||
Track *TrackList::Add(std::unique_ptr<TrackKind> &&t)
|
||||
Track *TrackList::DoAddToHead(const std::shared_ptr<Track> &t)
|
||||
{
|
||||
Track *pTrack;
|
||||
push_back(ListOfTracks::value_type(pTrack = t.release()));
|
||||
|
||||
auto n = getPrev( getEnd() );
|
||||
|
||||
pTrack->SetOwner(mSelf, n);
|
||||
pTrack->SetId( TrackId{ ++sCounter } );
|
||||
RecalcPositions(n);
|
||||
AdditionEvent(n);
|
||||
return back().get();
|
||||
}
|
||||
|
||||
// Make instantiations for the linker to find
|
||||
template Track *TrackList::Add<TimeTrack>(std::unique_ptr<TimeTrack> &&);
|
||||
#if defined(USE_MIDI)
|
||||
template Track *TrackList::Add<NoteTrack>(std::unique_ptr<NoteTrack> &&);
|
||||
#endif
|
||||
template Track *TrackList::Add<WaveTrack>(std::unique_ptr<WaveTrack> &&);
|
||||
template Track *TrackList::Add<LabelTrack>(std::unique_ptr<LabelTrack> &&);
|
||||
template Track *TrackList::Add<Track>(std::unique_ptr<Track> &&);
|
||||
|
||||
template<typename TrackKind>
|
||||
Track *TrackList::AddToHead(std::unique_ptr<TrackKind> &&t)
|
||||
{
|
||||
Track *pTrack;
|
||||
push_front(ListOfTracks::value_type(pTrack = t.release()));
|
||||
Track *pTrack = t.get();
|
||||
push_front(ListOfTracks::value_type(t));
|
||||
auto n = getBegin();
|
||||
pTrack->SetOwner(mSelf, n);
|
||||
pTrack->SetId( TrackId{ ++sCounter } );
|
||||
@ -765,11 +740,7 @@ Track *TrackList::AddToHead(std::unique_ptr<TrackKind> &&t)
|
||||
return front().get();
|
||||
}
|
||||
|
||||
// Make instantiations for the linker to find
|
||||
template Track *TrackList::AddToHead<TimeTrack>(std::unique_ptr<TimeTrack> &&);
|
||||
|
||||
template<typename TrackKind>
|
||||
Track *TrackList::Add(std::shared_ptr<TrackKind> &&t)
|
||||
Track *TrackList::DoAdd(const std::shared_ptr<Track> &t)
|
||||
{
|
||||
push_back(t);
|
||||
|
||||
@ -782,10 +753,6 @@ Track *TrackList::Add(std::shared_ptr<TrackKind> &&t)
|
||||
return back().get();
|
||||
}
|
||||
|
||||
// Make instantiations for the linker to find
|
||||
template Track *TrackList::Add<Track>(std::shared_ptr<Track> &&);
|
||||
template Track *TrackList::Add<WaveTrack>(std::shared_ptr<WaveTrack> &&);
|
||||
|
||||
void TrackList::GroupChannels(
|
||||
Track &track, size_t groupSize, bool resetChannels )
|
||||
{
|
||||
@ -1234,8 +1201,7 @@ TrackList::RegisterPendingChangedTrack( Updater updater, Track *src )
|
||||
{
|
||||
std::shared_ptr<Track> pTrack;
|
||||
if (src)
|
||||
// convert from unique_ptr to shared_ptr
|
||||
pTrack.reset( src->Duplicate().release() );
|
||||
pTrack = src->Duplicate();
|
||||
|
||||
if (pTrack) {
|
||||
mUpdaters.push_back( updater );
|
||||
|
26
src/Track.h
26
src/Track.h
@ -367,7 +367,7 @@ private:
|
||||
|
||||
void Init(const Track &orig);
|
||||
|
||||
using Holder = std::unique_ptr<Track>;
|
||||
using Holder = std::shared_ptr<Track>;
|
||||
virtual Holder Duplicate() const = 0;
|
||||
|
||||
// Called when this track is merged to stereo with another, and should
|
||||
@ -1330,6 +1330,9 @@ class TrackList final : public wxEvtHandler, public ListOfTracks
|
||||
}
|
||||
|
||||
private:
|
||||
Track *DoAddToHead(const std::shared_ptr<Track> &t);
|
||||
Track *DoAdd(const std::shared_ptr<Track> &t);
|
||||
|
||||
template< typename TrackType, typename InTrackType >
|
||||
static TrackIterRange< TrackType >
|
||||
Channels_( TrackIter< InTrackType > iter1 )
|
||||
@ -1369,15 +1372,12 @@ public:
|
||||
|
||||
/// Add a Track, giving it a fresh id
|
||||
template<typename TrackKind>
|
||||
Track *Add(std::unique_ptr<TrackKind> &&t);
|
||||
TrackKind *AddToHead( const std::shared_ptr< TrackKind > &t )
|
||||
{ return static_cast< TrackKind* >( DoAddToHead( t ) ); }
|
||||
|
||||
/// Add a Track, giving it a fresh id
|
||||
template<typename TrackKind>
|
||||
Track *AddToHead(std::unique_ptr<TrackKind> &&t);
|
||||
|
||||
/// Add a Track, giving it a fresh id
|
||||
template<typename TrackKind>
|
||||
Track *Add(std::shared_ptr<TrackKind> &&t);
|
||||
TrackKind *Add( const std::shared_ptr< TrackKind > &t )
|
||||
{ return static_cast< TrackKind* >( DoAdd( t ) ); }
|
||||
|
||||
/** \brief Define a group of channels starting at the given track
|
||||
*
|
||||
@ -1632,13 +1632,13 @@ class AUDACITY_DLL_API TrackFactory
|
||||
public:
|
||||
// These methods are defined in WaveTrack.cpp, NoteTrack.cpp,
|
||||
// LabelTrack.cpp, and TimeTrack.cpp respectively
|
||||
std::unique_ptr<WaveTrack> DuplicateWaveTrack(const WaveTrack &orig);
|
||||
std::unique_ptr<WaveTrack> NewWaveTrack(sampleFormat format = (sampleFormat)0,
|
||||
std::shared_ptr<WaveTrack> DuplicateWaveTrack(const WaveTrack &orig);
|
||||
std::shared_ptr<WaveTrack> NewWaveTrack(sampleFormat format = (sampleFormat)0,
|
||||
double rate = 0);
|
||||
std::unique_ptr<LabelTrack> NewLabelTrack();
|
||||
std::unique_ptr<TimeTrack> NewTimeTrack();
|
||||
std::shared_ptr<LabelTrack> NewLabelTrack();
|
||||
std::shared_ptr<TimeTrack> NewTimeTrack();
|
||||
#if defined(USE_MIDI)
|
||||
std::unique_ptr<NoteTrack> NewNoteTrack();
|
||||
std::shared_ptr<NoteTrack> NewNoteTrack();
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -70,15 +70,13 @@ using std::max;
|
||||
|
||||
WaveTrack::Holder TrackFactory::DuplicateWaveTrack(const WaveTrack &orig)
|
||||
{
|
||||
return std::unique_ptr<WaveTrack>
|
||||
{ static_cast<WaveTrack*>(orig.Duplicate().release()) };
|
||||
return std::static_pointer_cast<WaveTrack>( orig.Duplicate() );
|
||||
}
|
||||
|
||||
|
||||
WaveTrack::Holder TrackFactory::NewWaveTrack(sampleFormat format, double rate)
|
||||
{
|
||||
return std::unique_ptr<WaveTrack>
|
||||
{ safenew WaveTrack(mDirManager, format, rate) };
|
||||
return std::make_shared<WaveTrack> ( mDirManager, format, rate );
|
||||
}
|
||||
|
||||
WaveTrack::WaveTrack(const std::shared_ptr<DirManager> &projDirManager, sampleFormat format, double rate) :
|
||||
@ -395,7 +393,7 @@ int WaveTrack::ZeroLevelYCoordinate(wxRect rect) const
|
||||
|
||||
Track::Holder WaveTrack::Duplicate() const
|
||||
{
|
||||
return Track::Holder{ safenew WaveTrack{ *this } };
|
||||
return std::make_shared<WaveTrack>( *this );
|
||||
}
|
||||
|
||||
double WaveTrack::GetRate() const
|
||||
@ -629,9 +627,8 @@ Track::Holder WaveTrack::Copy(double t0, double t1, bool forClipboard) const
|
||||
if (t1 < t0)
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
|
||||
WaveTrack *newTrack;
|
||||
Track::Holder result
|
||||
{ newTrack = safenew WaveTrack{ mDirManager } };
|
||||
auto result = std::make_shared<WaveTrack>( mDirManager );
|
||||
WaveTrack *newTrack = result.get();
|
||||
|
||||
newTrack->Init(*this);
|
||||
|
||||
|
@ -58,28 +58,24 @@ using Regions = std::vector < Region >;
|
||||
class Envelope;
|
||||
|
||||
class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
|
||||
|
||||
private:
|
||||
public:
|
||||
|
||||
//
|
||||
// Constructor / Destructor / Duplicator
|
||||
//
|
||||
// Private since only factories are allowed to construct WaveTracks
|
||||
//
|
||||
|
||||
WaveTrack(const std::shared_ptr<DirManager> &projDirManager,
|
||||
sampleFormat format = (sampleFormat)0,
|
||||
double rate = 0);
|
||||
WaveTrack(const WaveTrack &orig);
|
||||
|
||||
void Init(const WaveTrack &orig);
|
||||
|
||||
public:
|
||||
// overwrite data excluding the sample sequence but including display
|
||||
// settings
|
||||
void Reinit(const WaveTrack &orig);
|
||||
|
||||
private:
|
||||
void Init(const WaveTrack &orig);
|
||||
|
||||
Track::Holder Duplicate() const override;
|
||||
|
||||
friend class TrackFactory;
|
||||
@ -87,7 +83,7 @@ private:
|
||||
public:
|
||||
|
||||
typedef WaveTrackLocation Location;
|
||||
using Holder = std::unique_ptr<WaveTrack>;
|
||||
using Holder = std::shared_ptr<WaveTrack>;
|
||||
|
||||
virtual ~WaveTrack();
|
||||
|
||||
|
@ -1207,7 +1207,7 @@ bool Effect::DoEffect(wxWindow *parent,
|
||||
// We don't yet know the effect type for code in the Nyquist Prompt, so
|
||||
// assume it requires a track and handle errors when the effect runs.
|
||||
if ((GetType() == EffectTypeGenerate || GetPath() == NYQUIST_PROMPT_ID) && (mNumTracks == 0)) {
|
||||
newTrack = static_cast<WaveTrack*>(mTracks->Add(mFactory->NewWaveTrack()));
|
||||
newTrack = mTracks->Add(mFactory->NewWaveTrack());
|
||||
newTrack->SetSelected(true);
|
||||
}
|
||||
|
||||
@ -1553,7 +1553,7 @@ bool Effect::ProcessTrack(int count,
|
||||
|
||||
auto chans = std::min<unsigned>(mNumAudioOut, mNumChannels);
|
||||
|
||||
std::unique_ptr<WaveTrack> genLeft, genRight;
|
||||
std::shared_ptr<WaveTrack> genLeft, genRight;
|
||||
|
||||
decltype(len) genLength = 0;
|
||||
bool isGenerator = GetType() == EffectTypeGenerate;
|
||||
@ -2073,11 +2073,11 @@ void Effect::CopyInputTracks(bool allSyncLockSelected)
|
||||
}
|
||||
}
|
||||
|
||||
Track *Effect::AddToOutputTracks(std::unique_ptr<Track> &&t)
|
||||
Track *Effect::AddToOutputTracks(const std::shared_ptr<Track> &t)
|
||||
{
|
||||
mIMap.push_back(NULL);
|
||||
mOMap.push_back(t.get());
|
||||
return mOutputTracks->Add(std::move(t));
|
||||
return mOutputTracks->Add(t);
|
||||
}
|
||||
|
||||
Effect::AddedAnalysisTrack::AddedAnalysisTrack(Effect *pEffect, const wxString &name)
|
||||
|
@ -443,7 +443,7 @@ protected:
|
||||
void ReplaceProcessedTracks(const bool bGoodResult);
|
||||
|
||||
// Use this to append a NEW output track.
|
||||
Track *AddToOutputTracks(std::unique_ptr<Track> &&t);
|
||||
Track *AddToOutputTracks(const std::shared_ptr<Track> &t);
|
||||
|
||||
//
|
||||
// protected data
|
||||
|
@ -59,8 +59,8 @@ public:
|
||||
// Not required by callbacks, but makes for easier cleanup
|
||||
std::unique_ptr<Resampler> resampler;
|
||||
std::unique_ptr<SBSMSQuality> quality;
|
||||
std::unique_ptr<WaveTrack> outputLeftTrack;
|
||||
std::unique_ptr<WaveTrack> outputRightTrack;
|
||||
std::shared_ptr<WaveTrack> outputLeftTrack;
|
||||
std::shared_ptr<WaveTrack> outputRightTrack;
|
||||
|
||||
std::exception_ptr mpException {};
|
||||
};
|
||||
|
@ -1419,7 +1419,7 @@ bool NyquistEffect::ProcessOne()
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<WaveTrack> outputTrack[2];
|
||||
std::shared_ptr<WaveTrack> outputTrack[2];
|
||||
|
||||
double rate = mCurTrack[0]->GetRate();
|
||||
for (int i = 0; i < outChannels; i++) {
|
||||
|
@ -23,7 +23,7 @@ class wxWindow;
|
||||
|
||||
// Newly constructed WaveTracks that are not yet owned by a TrackList
|
||||
// are held in unique_ptr not shared_ptr
|
||||
using NewChannelGroup = std::vector< std::unique_ptr<WaveTrack> >;
|
||||
using NewChannelGroup = std::vector< std::shared_ptr<WaveTrack> >;
|
||||
using TrackHolders = std::vector< NewChannelGroup >;
|
||||
|
||||
|
||||
|
@ -41,10 +41,8 @@ int DoAddLabel(
|
||||
auto lt = * iter.Filter< LabelTrack >();
|
||||
|
||||
// If none found, start a NEW label track and use it
|
||||
if (!lt) {
|
||||
lt = static_cast<LabelTrack*>
|
||||
(tracks->Add(trackFactory->NewLabelTrack()));
|
||||
}
|
||||
if (!lt)
|
||||
lt = tracks->Add(trackFactory->NewLabelTrack());
|
||||
|
||||
// LLL: Commented as it seemed a little forceful to remove users
|
||||
// selection when adding the label. This does not happen if
|
||||
@ -158,7 +156,7 @@ void EditByLabel(
|
||||
}
|
||||
}
|
||||
|
||||
using EditDestFunction = std::unique_ptr<Track> (WaveTrack::*)(double, double);
|
||||
using EditDestFunction = std::shared_ptr<Track> (WaveTrack::*)(double, double);
|
||||
|
||||
//Executes the edit function on all selected wave tracks with
|
||||
//regions specified by selected labels
|
||||
|
@ -1168,9 +1168,7 @@ bool ControlToolBar::DoRecord(AudacityProject &project,
|
||||
|
||||
Track *first {};
|
||||
for (int c = 0; c < recordingChannels; c++) {
|
||||
std::shared_ptr<WaveTrack> newTrack{
|
||||
p->GetTrackFactory()->NewWaveTrack().release()
|
||||
};
|
||||
auto newTrack = p->GetTrackFactory()->NewWaveTrack();
|
||||
if (!first)
|
||||
first = newTrack.get();
|
||||
|
||||
|
@ -156,7 +156,7 @@ class TranscriptionToolBar final : public ToolBar {
|
||||
int mBackgroundWidth;
|
||||
int mBackgroundHeight;
|
||||
|
||||
std::unique_ptr<TimeTrack> mTimeTrack;
|
||||
std::shared_ptr<TimeTrack> mTimeTrack;
|
||||
|
||||
public:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user