1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-16 00:27:42 +02:00

TrackList holds smart pointers to tracks, Add() only takes rvalue refs to such

This commit is contained in:
Paul Licameli 2016-03-13 11:08:21 -04:00
parent 7d1ea7b82e
commit a6ca36cdab
10 changed files with 209 additions and 183 deletions

View File

@ -319,9 +319,9 @@ bool LabelDialog::TransferDataFromWindow()
wxString name = mTrackNames[tndx + 1].AfterFirst(wxT('-')).Mid(1);
// Create the NEW track and add to track list
LabelTrack *newTrack = mFactory.NewLabelTrack().release();
auto newTrack = mFactory.NewLabelTrack();
newTrack->SetName(name);
mTracks->Add(newTrack);
mTracks->Add(std::move(newTrack));
tndx++;
}

View File

@ -3341,7 +3341,7 @@ bool AudacityProject::OnEffect(const PluginID & ID, int flags)
TrackListIterator iter(mTracks);
Track *t = iter.First();
WaveTrack *newTrack = NULL;
WaveTrack *newTrack{};
wxWindow *focus = wxWindow::FindFocus();
//double prevEndTime = mTracks->GetEndTime();
@ -3359,8 +3359,7 @@ bool AudacityProject::OnEffect(const PluginID & ID, int flags)
// No tracks were selected...
if (type == EffectTypeGenerate) {
// Create a NEW track for the generated audio...
newTrack = mTrackFactory->NewWaveTrack().release();
mTracks->Add(newTrack);
newTrack = static_cast<WaveTrack*>(mTracks->Add(mTrackFactory->NewWaveTrack()));
newTrack->SetSelected(true);
}
}
@ -3851,7 +3850,7 @@ void AudacityProject::OnCut()
dest->SetChannel(n->GetChannel());
dest->SetLinked(n->GetLinked());
dest->SetName(n->GetName());
msClipboard->Add(dest.release());
msClipboard->Add(std::move(dest));
}
}
n = iter.Next();
@ -3925,7 +3924,7 @@ void AudacityProject::OnSplitCut()
dest->SetChannel(n->GetChannel());
dest->SetLinked(n->GetLinked());
dest->SetName(n->GetName());
msClipboard->Add(dest.release());
msClipboard->Add(std::move(dest));
}
}
n = iter.Next();
@ -3970,7 +3969,7 @@ void AudacityProject::OnCopy()
dest->SetChannel(n->GetChannel());
dest->SetLinked(n->GetLinked());
dest->SetName(n->GetName());
msClipboard->Add(dest.release());
msClipboard->Add(std::move(dest));
}
}
n = iter.Next();
@ -4251,7 +4250,7 @@ bool AudacityProject::HandlePasteNothingSelected()
if (!pClip)
return true; // nothing to paste
Track* pNewTrack;
Track::Holder pNewTrack;
Track* pFirstNewTrack = NULL;
while (pClip) {
if ((msClipProject != this) && (pClip->GetKind() == Track::Wave))
@ -4261,19 +4260,19 @@ bool AudacityProject::HandlePasteNothingSelected()
case Track::Wave:
{
WaveTrack *w = (WaveTrack *)pClip;
pNewTrack = mTrackFactory->NewWaveTrack(w->GetSampleFormat(), w->GetRate()).release();
pNewTrack = mTrackFactory->NewWaveTrack(w->GetSampleFormat(), w->GetRate());
}
break;
#ifdef USE_MIDI
case Track::Note:
pNewTrack = mTrackFactory->NewNoteTrack().release();
pNewTrack = mTrackFactory->NewNoteTrack();
break;
#endif // USE_MIDI
case Track::Label:
pNewTrack = mTrackFactory->NewLabelTrack().release();
pNewTrack = mTrackFactory->NewLabelTrack();
break;
case Track::Time:
pNewTrack = mTrackFactory->NewTimeTrack().release();
pNewTrack = mTrackFactory->NewTimeTrack();
break;
default:
pClip = iterClip.Next();
@ -4288,14 +4287,16 @@ bool AudacityProject::HandlePasteNothingSelected()
bool bResult = pNewTrack->Paste(0.0, pClip);
wxASSERT(bResult); // TO DO: Actually handle this.
wxUnusedVar(bResult);
mTracks->Add(pNewTrack);
if (!pFirstNewTrack)
pFirstNewTrack = pNewTrack.get();
pNewTrack->SetSelected(true);
mTracks->Add(std::move(pNewTrack));
if (msClipProject != this && pClip->GetKind() == Track::Wave)
((WaveTrack *) pClip)->Unlock();
if (!pFirstNewTrack)
pFirstNewTrack = pNewTrack;
pClip = iterClip.Next();
}
@ -4352,8 +4353,7 @@ void AudacityProject::OnPasteNewLabel()
// If no match found, add one
if (!t) {
t = GetTrackFactory()->NewLabelTrack().release();
mTracks->Add(t);
t = mTracks->Add(GetTrackFactory()->NewLabelTrack());
}
// Select this track so the loop picks it up
@ -4562,7 +4562,7 @@ void AudacityProject::OnDuplicate()
if (dest) {
dest->Init(*n);
dest->SetOffset(wxMax(mViewInfo.selectedRegion.t0(), n->GetOffset()));
mTracks->Add(dest.release());
mTracks->Add(std::move(dest));
}
}
@ -4840,7 +4840,7 @@ void AudacityProject::OnSplitNew()
dest->SetLinked(n->GetLinked());
dest->SetName(n->GetName());
dest->SetOffset(wxMax(newt0, offset));
mTracks->Add(dest.release());
mTracks->Add(std::move(dest));
}
}
@ -5489,7 +5489,7 @@ void AudacityProject::OnImportLabels()
return;
}
LabelTrack *newTrack = GetTrackFactory()->NewLabelTrack().release();
auto newTrack = GetTrackFactory()->NewLabelTrack();
wxString sTrackName;
wxFileName::SplitPath(fileName, NULL, NULL, &sTrackName, NULL);
newTrack->SetName(sTrackName);
@ -5497,8 +5497,8 @@ void AudacityProject::OnImportLabels()
newTrack->Import(f);
SelectNone();
mTracks->Add(newTrack);
newTrack->SetSelected(true);
mTracks->Add(std::move(newTrack));
PushState(wxString::
Format(_("Imported labels from '%s'"), fileName.c_str()),
@ -5532,22 +5532,20 @@ void AudacityProject::OnImportMIDI()
void AudacityProject::DoImportMIDI(const wxString &fileName)
{
NoteTrack *newTrack = GetTrackFactory()->NewNoteTrack().release();
auto newTrack = GetTrackFactory()->NewNoteTrack();
if (::ImportMIDI(fileName, newTrack)) {
if (::ImportMIDI(fileName, newTrack.get())) {
SelectNone();
mTracks->Add(newTrack);
newTrack->SetSelected(true);
auto pTrack = mTracks->Add(std::move(newTrack));
pTrack->SetSelected(true);
PushState(wxString::Format(_("Imported MIDI from '%s'"),
fileName.c_str()), _("Import MIDI"));
RedrawProject();
mTrackPanel->EnsureVisible(newTrack);
mTrackPanel->EnsureVisible(pTrack);
}
else
delete newTrack;
}
#endif // USE_MIDI
@ -5611,10 +5609,8 @@ void AudacityProject::HandleMixAndRender(bool toNewTrack)
auto results =
::MixAndRender(mTracks, mTrackFactory, mRate, mDefaultFormat, 0.0, 0.0);
auto &uNewLeft = results.first, &uNewRight = results.second;
const auto newLeft = uNewLeft.get();
const auto newRight = uNewRight.get();
if (newLeft) {
if (uNewLeft) {
// Remove originals, get stats on what tracks were mixed
TrackListIterator iter(mTracks);
@ -5644,15 +5640,16 @@ void AudacityProject::HandleMixAndRender(bool toNewTrack)
// Add NEW tracks
mTracks->Add(uNewLeft.release());
if (newRight)
mTracks->Add(uNewRight.release());
auto pNewLeft = mTracks->Add(std::move(uNewLeft));
decltype(pNewLeft) pNewRight{};
if (uNewRight)
pNewRight = mTracks->Add(std::move(uNewRight));
// If we're just rendering (not mixing), keep the track name the same
if (selectedCount==1) {
newLeft->SetName(firstName);
if (newRight)
newRight->SetName(firstName);
pNewLeft->SetName(firstName);
if (pNewRight)
pNewRight->SetName(firstName);
}
// Smart history/undo message
@ -5665,7 +5662,7 @@ void AudacityProject::HandleMixAndRender(bool toNewTrack)
}
else {
wxString msg;
if (newRight)
if (pNewRight)
msg.Printf(_("Mixed and rendered %d tracks into one new stereo track"),
selectedCount);
else
@ -5675,8 +5672,8 @@ void AudacityProject::HandleMixAndRender(bool toNewTrack)
}
mTrackPanel->SetFocus();
mTrackPanel->SetFocusedTrack(newLeft);
mTrackPanel->EnsureVisible(newLeft);
mTrackPanel->SetFocusedTrack(pNewLeft);
mTrackPanel->EnsureVisible(pNewLeft);
RedrawProject();
}
}
@ -6247,10 +6244,9 @@ void AudacityProject::OnScoreAlign()
void AudacityProject::OnNewWaveTrack()
{
WaveTrack *t = mTrackFactory->NewWaveTrack(mDefaultFormat, mRate).release();
auto t = mTracks->Add(mTrackFactory->NewWaveTrack(mDefaultFormat, mRate));
SelectNone();
mTracks->Add(t);
t->SetSelected(true);
PushState(_("Created new audio track"), _("New Track"));
@ -6261,18 +6257,16 @@ void AudacityProject::OnNewWaveTrack()
void AudacityProject::OnNewStereoTrack()
{
WaveTrack *t = mTrackFactory->NewWaveTrack(mDefaultFormat, mRate).release();
auto t = mTracks->Add(mTrackFactory->NewWaveTrack(mDefaultFormat, mRate));
t->SetChannel(Track::LeftChannel);
SelectNone();
mTracks->Add(t);
t->SetSelected(true);
t->SetLinked (true);
t = mTrackFactory->NewWaveTrack(mDefaultFormat, mRate).release();
t = mTracks->Add(mTrackFactory->NewWaveTrack(mDefaultFormat, mRate));
t->SetChannel(Track::RightChannel);
mTracks->Add(t);
t->SetSelected(true);
PushState(_("Created new stereo audio track"), _("New Track"));
@ -6283,11 +6277,10 @@ void AudacityProject::OnNewStereoTrack()
void AudacityProject::OnNewLabelTrack()
{
LabelTrack *t = GetTrackFactory()->NewLabelTrack().release();
auto t = mTracks->Add(GetTrackFactory()->NewLabelTrack());
SelectNone();
mTracks->Add(t);
t->SetSelected(true);
PushState(_("Created new label track"), _("New Track"));
@ -6303,11 +6296,10 @@ void AudacityProject::OnNewTimeTrack()
return;
}
TimeTrack *t = mTrackFactory->NewTimeTrack().release();
auto t = mTracks->AddToHead(mTrackFactory->NewTimeTrack());
SelectNone();
mTracks->AddToHead(t);
t->SetSelected(true);
PushState(_("Created new time track"), _("New Track"));
@ -6379,8 +6371,8 @@ int AudacityProject::DoAddLabel(const SelectedRegion &region, bool preserveFocus
// If none found, start a NEW label track and use it
if (!lt) {
lt = GetTrackFactory()->NewLabelTrack().release();
mTracks->Add(lt);
lt = static_cast<LabelTrack*>
(mTracks->Add(GetTrackFactory()->NewLabelTrack()));
}
// LLL: Commented as it seemed a little forceful to remove users

View File

@ -2751,7 +2751,7 @@ void AudacityProject::OpenFile(const wxString &fileNameArg, bool addtohistory)
}
}
mLastSavedTracks->Add(t->Duplicate().release());
mLastSavedTracks->Add(t->Duplicate());
t = iter.Next();
}
@ -3147,29 +3147,21 @@ XMLTagHandler *AudacityProject::HandleXMLChild(const wxChar *tag)
}
if (!wxStrcmp(tag, wxT("wavetrack"))) {
WaveTrack *newTrack = mTrackFactory->NewWaveTrack().release();
mTracks->Add(newTrack);
return newTrack;
return mTracks->Add(mTrackFactory->NewWaveTrack());
}
#ifdef USE_MIDI
if (!wxStrcmp(tag, wxT("notetrack"))) {
NoteTrack *newTrack = mTrackFactory->NewNoteTrack().release();
mTracks->Add(newTrack);
return newTrack;
return mTracks->Add(mTrackFactory->NewNoteTrack());
}
#endif // USE_MIDI
if (!wxStrcmp(tag, wxT("labeltrack"))) {
LabelTrack *newTrack = mTrackFactory->NewLabelTrack().release();
mTracks->Add(newTrack);
return newTrack;
return mTracks->Add(mTrackFactory->NewLabelTrack());
}
if (!wxStrcmp(tag, wxT("timetrack"))) {
TimeTrack *newTrack = mTrackFactory->NewTimeTrack().release();
mTracks->Add(newTrack);
return newTrack;
return mTracks->Add(mTrackFactory->NewTimeTrack());
}
if (!wxStrcmp(tag, wxT("recordingrecovery"))) {
@ -3547,10 +3539,8 @@ bool AudacityProject::Save(bool overwrite /* = true */ ,
TrackListIterator iter(mTracks);
Track *t = iter.First();
Track *dupT;
while (t) {
dupT = t->Duplicate().release();
mLastSavedTracks->Add(dupT);
mLastSavedTracks->Add(t->Duplicate());
//only after the xml has been saved we can mark it saved.
//thus is because the OD blockfiles change on background thread while this is going on.
@ -3582,19 +3572,17 @@ bool AudacityProject::Save(bool overwrite /* = true */ ,
// but that code is really tied into the dialogs.
// Copy the tracks because we're going to do some state changes before exporting.
Track* pSavedTrack;
Track* pTrack;
WaveTrack* pWaveTrack;
TrackListOfKindIterator iter(Track::Wave, mTracks);
unsigned int numWaveTracks = 0;
TrackList pSavedTrackList{};
TrackList pSavedTrackList;
for (pTrack = iter.First(); pTrack != NULL; pTrack = iter.Next())
{
numWaveTracks++;
pWaveTrack = (WaveTrack*)pTrack;
pSavedTrack = mTrackFactory->DuplicateWaveTrack(*pWaveTrack).release();
pSavedTrackList.Add(pSavedTrack);
pSavedTrackList.Add(mTrackFactory->DuplicateWaveTrack(*pWaveTrack));
}
if (numWaveTracks == 0)
@ -3652,6 +3640,7 @@ bool AudacityProject::Save(bool overwrite /* = true */ ,
// Restore the saved track states and clean up.
TrackListIterator savedTrackIter(&pSavedTrackList);
Track *pSavedTrack;
for (pTrack = iter.First(), pSavedTrack = savedTrackIter.First();
((pTrack != NULL) && (pSavedTrack != NULL));
pTrack = iter.Next(), pSavedTrack = savedTrackIter.Next())
@ -3684,8 +3673,7 @@ void AudacityProject::AddImportedTracks(const wxString &fileName,
for (auto &uNewTrack : newTracks) {
++i;
Track *newTrack; // TO DO: use unique_ptr, not bare pointer
mTracks->Add(newTrack = ((Track*)(uNewTrack.get()))->Duplicate().release()); // Ack! Once mTracks holds a smart pointer, Duplicate() won't be needed.
auto newTrack = mTracks->Add(std::move(uNewTrack));
if (newRate == 0 && newTrack->GetKind() == Track::Wave) {
newRate = ((WaveTrack *)newTrack)->GetRate();
}
@ -4066,11 +4054,10 @@ void AudacityProject::PopState(const UndoState &state)
Track *t = iter.First();
bool odUsed = false;
ODComputeSummaryTask* computeTask = NULL;
Track* copyTrack;
while (t)
{
mTracks->Add(copyTrack = t->Duplicate().release());
auto copyTrack = mTracks->Add(t->Duplicate());
//add the track to OD if the manager exists. later we might do a more rigorous check...
if (copyTrack->GetKind() == Track::Wave)
@ -4627,7 +4614,7 @@ void AudacityProject::EditClipboardByLabel( EditDestFunction action )
regions.at(i + 1).start - region.end);
}
if( merged )
msClipboard->Add( merged.release() );
msClipboard->Add( std::move(merged) );
}
}

View File

@ -26,6 +26,7 @@ and TimeTrack.
#include "TimeTrack.h"
#include "WaveTrack.h"
#include "NoteTrack.h"
#include "LabelTrack.h"
#include "Project.h"
#include "DirManager.h"
@ -135,7 +136,7 @@ Track::~Track()
TrackNodePointer Track::GetNode() const
{
wxASSERT(mList == NULL || this == *mNode);
wxASSERT(mList == NULL || this == mNode->get());
return mNode;
}
@ -266,14 +267,14 @@ Track *Track::GetLink() const
auto next = mNode;
++next;
if (!mList->isNull(next)) {
return *next;
return next->get();
}
}
if (mList->hasPrev(mNode)) {
auto prev = mNode;
--prev;
auto track = *prev;
auto track = prev->get();
if (track && track->GetLinked()) {
return track;
}
@ -366,7 +367,7 @@ Track *TrackListIterator::StartWith(Track * val)
return nullptr;
cur = val->GetNode();
return *cur;
return cur->get();
}
Track *TrackListIterator::First(TrackList * val)
@ -382,7 +383,7 @@ Track *TrackListIterator::First(TrackList * val)
cur = l->begin();
if (!l->isNull(cur)) {
return *cur;
return cur->get();
}
return NULL;
@ -407,7 +408,7 @@ Track *TrackListIterator::Last(bool skiplinked)
(*cur)->GetLink())
--cur;
return *cur;
return cur->get();
}
Track *TrackListIterator::Next(bool skipLinked)
@ -437,7 +438,7 @@ Track *TrackListIterator::Next(bool skipLinked)
#endif
if (!l->isNull(cur)) {
return *cur;
return cur->get();
}
return NULL;
@ -462,7 +463,7 @@ Track *TrackListIterator::Prev(bool skiplinked)
cur = prev;
}
return *cur;
return cur->get();
}
Track *TrackListIterator::RemoveCurrent()
@ -470,14 +471,14 @@ Track *TrackListIterator::RemoveCurrent()
if (!l || l->isNull(cur))
return nullptr;
cur = l->Remove(*cur);
cur = l->Remove(cur->get());
#ifdef DEBUG_TLI // if we are debugging this bit
wxASSERT_MSG((!cur || (*l).Contains((*cur).t)), wxT("cur invalid after deletion of track.")); // check that cur is in the list
#endif
if (!l->isNull(cur)) {
return *cur;
return cur->get();
}
return NULL;
@ -687,7 +688,7 @@ Track *SyncLockedTracksIterator::Last(bool skiplinked)
if (!l || l->isNull(cur))
return NULL;
Track *t = *cur;
Track *t = cur->get();
while (l->GetNext(t)) {
// Check if this is the last track in the sync-locked group.
@ -723,7 +724,7 @@ TrackList::TrackList()
}
TrackList::TrackList(const TrackList &that)
: ListOfTracks()
: ListOfTracks{}
{
DoAssign(that);
}
@ -755,7 +756,7 @@ void TrackList::DoAssign(const TrackList &that)
{
TrackListConstIterator it(&that);
for (const Track *track = it.First(); track; track = it.Next())
Add(track->Duplicate().release());
Add(track->Duplicate());
}
void TrackList::Swap(TrackList &that)
@ -812,14 +813,14 @@ void TrackList::RecalcPositions(TrackNodePointer node)
if (hasPrev(node)) {
auto prev = node;
--prev;
t = *prev;
t = prev->get();
i = t->GetIndex() + 1;
y = t->GetY() + t->GetHeight();
}
const auto theEnd = end();
for (auto n = node; n != theEnd; ++n) {
t = *n;
t = n->get();
t->SetIndex(i++);
t->SetY(y);
y += t->GetHeight();
@ -831,7 +832,7 @@ void TrackList::UpdatedEvent(TrackNodePointer node)
{
wxCommandEvent e(EVT_TRACKLIST_UPDATED);
if (!isNull(node)) {
e.SetClientData(*node);
e.SetClientData(node->get());
}
else {
e.SetClientData(NULL);
@ -843,7 +844,7 @@ void TrackList::ResizedEvent(TrackNodePointer node)
{
if (!isNull(node)) {
wxCommandEvent e(EVT_TRACKLIST_RESIZED);
e.SetClientData(*node);
e.SetClientData(node->get());
ProcessEvent(e);
}
}
@ -851,9 +852,10 @@ void TrackList::ResizedEvent(TrackNodePointer node)
void TrackList::Permute(const std::vector<TrackNodePointer> &permutation)
{
for (const auto iter : permutation) {
Track *track = *iter;
value_type track = std::move(*iter);
erase(iter);
track->SetOwner(this, insert(end(), track));
Track *pTrack = track.get();
pTrack->SetOwner(this, insert(end(), std::move(track)));
}
auto n = begin();
RecalcPositions(n);
@ -861,7 +863,45 @@ void TrackList::Permute(const std::vector<TrackNodePointer> &permutation)
ResizedEvent(n);
}
void TrackList::Add(Track * t)
template<typename TrackKind>
Track *TrackList::Add(std::unique_ptr<TrackKind> &&t)
{
Track *pTrack;
push_back(value_type(pTrack = t.release()));
auto n = end();
--n;
pTrack->SetOwner(this, n);
RecalcPositions(n);
UpdatedEvent(n);
return back().get();
}
// Make instantiations for the linker to find
template Track *TrackList::Add<TimeTrack>(std::unique_ptr<TimeTrack> &&);
template Track *TrackList::Add<NoteTrack>(std::unique_ptr<NoteTrack> &&);
template Track *TrackList::Add<WaveTrack>(std::unique_ptr<WaveTrack> &&);
template Track *TrackList::Add<LabelTrack>(std::unique_ptr<LabelTrack> &&);
template<typename TrackKind>
Track *TrackList::AddToHead(std::unique_ptr<TrackKind> &&t)
{
Track *pTrack;
push_front(value_type(pTrack = t.release()));
auto n = begin();
pTrack->SetOwner(this, n);
RecalcPositions(n);
UpdatedEvent(n);
ResizedEvent(n);
return front().get();
}
// Make instantiations for the linker to find
template Track *TrackList::AddToHead<TimeTrack>(std::unique_ptr<TimeTrack> &&);
#ifdef __AUDACITY_OLD_STD__
template<typename TrackKind>
Track *TrackList::Add(std::shared_ptr<TrackKind> &&t)
{
push_back(t);
auto n = end();
@ -869,34 +909,30 @@ void TrackList::Add(Track * t)
t->SetOwner(this, n);
RecalcPositions(n);
UpdatedEvent(n);
return back().get();
}
void TrackList::AddToHead(Track * t)
{
push_front(t);
auto n = begin();
t->SetOwner(this, n);
RecalcPositions(n);
UpdatedEvent(n);
ResizedEvent(n);
}
// 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::Replace(Track * t, Track * with, bool deletetrack)
#endif
auto TrackList::Replace(Track * t, value_type &&with) -> value_type
{
value_type holder;
if (t && with) {
auto node = t->GetNode();
holder = std::move(*node);
if (deletetrack)
delete t;
else
t->SetOwner(NULL, TrackNodePointer{});
*node = with;
with->SetOwner(this, node);
Track *pTrack = with.get();
*node = std::move(with);
pTrack->SetOwner(this, node);
RecalcPositions(node);
UpdatedEvent(node);
ResizedEvent(node);
}
return holder;
}
TrackNodePointer TrackList::Remove(Track *t)
@ -905,8 +941,6 @@ TrackNodePointer TrackList::Remove(Track *t)
if (t) {
auto node = t->GetNode();
delete t;
if (!isNull(node)) {
result = erase(node);
if (!isNull(result)) {
@ -922,8 +956,6 @@ TrackNodePointer TrackList::Remove(Track *t)
void TrackList::Clear()
{
for (auto track : *this)
delete track;
ListOfTracks::clear();
UpdatedEvent(end());
}
@ -974,7 +1006,7 @@ Track *TrackList::GetNext(Track * t, bool linked) const
}
if (!isNull(node)) {
return *node;
return node->get();
}
}
}
@ -1002,7 +1034,7 @@ Track *TrackList::GetPrev(Track * t, bool linked) const
!(*node)->GetLinked() && (*node)->GetLink())
--node;
return *node;
return node->get();
}
}
}
@ -1074,31 +1106,32 @@ void TrackList::SwapNodes(TrackNodePointer s1, TrackNodePointer s2)
}
// Remove tracks
Track *save11 = *s1, *save12{};
value_type save11 = std::move(*s1), save12{};
s1 = erase(s1);
if (linked1) {
wxASSERT(s1 != s2);
save12 = *s1, s1 = erase(s1);
save12 = std::move(*s1), s1 = erase(s1);
}
const bool same = (s1 == s2);
Track *save21 = *s2, *save22{};
value_type save21 = std::move(*s2), save22{};
s2 = erase(s2);
if (linked2)
save22 = *s2, s2 = erase(s2);
save22 = std::move(*s2), s2 = erase(s2);
if (same)
// We invalidated s1!
s1 = s2;
// Reinsert them
Track *pTrack;
if (save22)
save22->SetOwner(this, s1 = insert(s1, save22));
save21->SetOwner(this, s1 = insert(s1, save21));
pTrack = save22.get(), pTrack->SetOwner(this, s1 = insert(s1, std::move(save22)));
pTrack = save21.get(), pTrack->SetOwner(this, s1 = insert(s1, std::move(save21)));
if (save12)
save12->SetOwner(this, s2 = insert(s2, save12));
save11->SetOwner(this, s2 = insert(s2, save11));
pTrack = save12.get(), pTrack->SetOwner(this, s2 = insert(s2, std::move(save12)));
pTrack = save11.get(), pTrack->SetOwner(this, s2 = insert(s2, std::move(save11)));
// Now correct the Index in the tracks, and other things
RecalcPositions(s1);
@ -1134,7 +1167,9 @@ bool TrackList::MoveDown(Track * t)
bool TrackList::Contains(Track * t) const
{
return std::find(begin(), end(), t) != end();
return std::find_if(begin(), end(),
[=](const value_type &track) { return t == track.get(); }
) != end();
}
bool TrackList::IsEmpty() const
@ -1156,12 +1191,12 @@ int TrackList::GetCount() const
TimeTrack *TrackList::GetTimeTrack()
{
auto iter = std::find_if(begin(), end(),
[] (Track *t) { return t->GetKind() == Track::Time; }
[] (const value_type &t) { return t->GetKind() == Track::Time; }
);
if (iter == end())
return nullptr;
else
return static_cast<TimeTrack*>(*iter);
return static_cast<TimeTrack*>(iter->get());
}
const TimeTrack *TrackList::GetTimeTrack() const
@ -1238,11 +1273,11 @@ namespace {
Array waveTrackArray;
for (; p != end; ++p) {
auto track = *p;
const auto &track = *p;
if (track->GetKind() == Track::Wave &&
(includeMuted || !track->GetMute()) &&
(track->GetSelected() || !selectionOnly)) {
waveTrackArray.push_back(static_cast<WaveTrack*>(track));
waveTrackArray.push_back(static_cast<WaveTrack*>(track.get()));
}
}
@ -1268,7 +1303,7 @@ NoteTrackArray TrackList::GetNoteTrackArray(bool selectionOnly)
for(const auto &track : *this) {
if (track->GetKind() == Track::Note &&
(track->GetSelected() || !selectionOnly)) {
noteTrackArray.Add(static_cast<NoteTrack*>(track));
noteTrackArray.Add(static_cast<NoteTrack*>(track.get()));
}
}

View File

@ -67,7 +67,8 @@ WX_DEFINE_USER_EXPORTED_ARRAY(NoteTrack*, NoteTrackArray, class AUDACITY_DLL_API
class TrackList;
using ListOfTracks = std::list<Track*>;
using ListOfTracks = std::list<movable_ptr<Track>>;
using TrackNodePointer = ListOfTracks::iterator;
class AUDACITY_DLL_API Track /* not final */ : public XMLTagHandler
@ -257,7 +258,7 @@ class AUDACITY_DLL_API TrackListIterator /* not final */
virtual Track *Prev(bool skiplinked = false);
virtual Track *Last(bool skiplinked = false);
Track *RemoveCurrent(); // returns next
Track *RemoveCurrent(); // deletes track, returns next
protected:
friend TrackList;
@ -398,7 +399,7 @@ DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_RESIZED, -1);
// track that was added.
DECLARE_EXPORTED_EVENT_TYPE(AUDACITY_DLL_API, EVT_TRACKLIST_UPDATED, -1);
class AUDACITY_DLL_API TrackList final : public wxEvtHandler, public ListOfTracks
class TrackList final : public wxEvtHandler, public ListOfTracks
{
public:
// Create an empty TrackList
@ -427,11 +428,18 @@ class AUDACITY_DLL_API TrackList final : public wxEvtHandler, public ListOfTrack
void Permute(const std::vector<TrackNodePointer> &permutation);
/// Add this Track or all children of this TrackList.
void Add(Track * t);
void AddToHead(Track * t);
template<typename TrackKind>
Track *Add(std::unique_ptr<TrackKind> &&t);
template<typename TrackKind>
Track *AddToHead(std::unique_ptr<TrackKind> &&t);
/// Replace first track with second track
void Replace(Track * t, Track * with, bool deletetrack = false);
#ifdef __AUDACITY_OLD_STD__
template<typename TrackKind>
Track *Add(std::shared_ptr<TrackKind> &&t);
#endif
/// Replace first track with second track, give back a holder
value_type Replace(Track * t, value_type &&with);
/// Remove this Track or all children of this TrackList.
/// Return an iterator to what followed the removed track.

View File

@ -214,7 +214,7 @@ void UndoManager::ModifyState(const TrackList * l,
TrackListConstIterator iter(l);
const Track *t = iter.First();
while (t) {
tracksCopy->Add(t->Duplicate().release());
tracksCopy->Add(t->Duplicate());
t = iter.Next();
}
@ -259,7 +259,7 @@ void UndoManager::PushState(const TrackList * l,
TrackListConstIterator iter(l);
const Track *t = iter.First();
while (t) {
tracksCopy->Add(t->Duplicate().release());
tracksCopy->Add(t->Duplicate());
t = iter.Next();
}

View File

@ -2104,19 +2104,18 @@ void Effect::CopyInputTracks(int trackType)
if (aTrack->GetSelected() ||
(trackType == Track::All && aTrack->IsSyncLockSelected()))
{
Track *o = aTrack->Duplicate().release();
mOutputTracks->Add(o);
Track *o = mOutputTracks->Add(aTrack->Duplicate());
mIMap.Add(aTrack);
mOMap.Add(o);
}
}
}
void Effect::AddToOutputTracks(Track *t)
Track *Effect::AddToOutputTracks(std::unique_ptr<Track> &&t)
{
mOutputTracks->Add(t);
mIMap.Add(NULL);
mOMap.Add(t);
mOMap.Add(t.get());
return mOutputTracks->Add(std::move(t));
}
Effect::AddedAnalysisTrack::AddedAnalysisTrack(Effect *pEffect, const wxString &name)
@ -2126,7 +2125,7 @@ Effect::AddedAnalysisTrack::AddedAnalysisTrack(Effect *pEffect, const wxString &
mpTrack = pTrack.get();
if (!name.empty())
pTrack->SetName(name);
pEffect->mTracks->Add(pTrack.release());
pEffect->mTracks->Add(std::move(pTrack));
}
Effect::AddedAnalysisTrack::AddedAnalysisTrack(AddedAnalysisTrack &&that)
@ -2158,7 +2157,6 @@ auto Effect::AddAnalysisTrack(const wxString &name) -> std::shared_ptr<AddedAnal
Effect::ModifiedAnalysisTrack::ModifiedAnalysisTrack
(Effect *pEffect, const LabelTrack *pOrigTrack, const wxString &name)
: mpEffect(pEffect)
, mpOrigTrack(pOrigTrack)
{
// copy LabelTrack here, so it can be undone on cancel
auto newTrack = pOrigTrack->Copy(pOrigTrack->GetStartTime(), pOrigTrack->GetEndTime());
@ -2172,14 +2170,21 @@ Effect::ModifiedAnalysisTrack::ModifiedAnalysisTrack
// mpOrigTrack came from mTracks which we own but expose as const to subclasses
// So it's okay that we cast it back to const
pEffect->mTracks->Replace(const_cast<LabelTrack*>(mpOrigTrack), newTrack.release(), false);
mpOrigTrack =
pEffect->mTracks->Replace(const_cast<LabelTrack*>(pOrigTrack),
#ifdef __AUDACITY_OLD_STD__
std::shared_ptr<Track>(newTrack.release())
#else
std::move(newTrack)
#endif
);
}
Effect::ModifiedAnalysisTrack::ModifiedAnalysisTrack(ModifiedAnalysisTrack &&that)
{
mpEffect = that.mpEffect;
mpTrack = that.mpTrack;
mpOrigTrack = that.mpOrigTrack;
mpOrigTrack = std::move(that.mpOrigTrack);
that.Commit();
}
@ -2194,7 +2199,7 @@ Effect::ModifiedAnalysisTrack::~ModifiedAnalysisTrack()
// not committed -- DELETE the label track
// mpOrigTrack came from mTracks which we own but expose as const to subclasses
// So it's okay that we cast it back to const
mpEffect->mTracks->Replace(mpTrack, const_cast<LabelTrack*>(mpOrigTrack), true);
mpEffect->mTracks->Replace(mpTrack, std::move(mpOrigTrack));
}
}
@ -2228,10 +2233,10 @@ void Effect::ReplaceProcessedTracks(const bool bGoodResult)
size_t i = 0;
for (; iterOut != iterEnd; ++i) {
Track *o = std::move(*iterOut);
ListOfTracks::value_type o = std::move(*iterOut);
// If tracks were removed from mOutputTracks, then there will be
// tracks in the map that must be removed from mTracks.
while (i < cnt && mOMap[i] != o) {
while (i < cnt && mOMap[i] != o.get()) {
Track *t = (Track *) mIMap[i];
if (t) {
mTracks->Remove(t);
@ -2249,22 +2254,20 @@ void Effect::ReplaceProcessedTracks(const bool bGoodResult)
if (t == NULL)
{
// This track is a NEW addition to output tracks; add it to mTracks
mTracks->Add(o);
mTracks->Add(std::move(o));
}
else
{
// Replace mTracks entry with the NEW track
mTracks->Replace(t, o, false);
WaveTrack *newTrack = static_cast<WaveTrack*>(o.get());
mTracks->Replace(t, std::move(o));
// Swap the wavecache track the ondemand task uses, since now the NEW
// one will be kept in the project
if (ODManager::IsInstanceCreated()) {
ODManager::Instance()->ReplaceWaveTrack((WaveTrack *)t,
(WaveTrack *)o);
newTrack);
}
// No longer need the original track
delete t;
}
}
@ -2579,12 +2582,12 @@ void Effect::Preview(bool dryOnly)
mixLeft->InsertSilence(0.0, mT0);
mixLeft->SetSelected(true);
mixLeft->SetDisplay(WaveTrack::NoDisplay);
mTracks->Add(mixLeft.release());
mTracks->Add(std::move(mixLeft));
if (mixRight) {
mixRight->Offset(-mixRight->GetStartTime());
mixRight->InsertSilence(0.0, mT0);
mixRight->SetSelected(true);
mTracks->Add(mixRight.release());
mTracks->Add(std::move(mixRight));
}
}
else {
@ -2597,7 +2600,7 @@ void Effect::Preview(bool dryOnly)
dest->InsertSilence(0.0, mT0);
dest->SetSelected(src->GetSelected());
static_cast<WaveTrack*>(dest.get())->SetDisplay(WaveTrack::NoDisplay);
mTracks->Add(dest.release());
mTracks->Add(std::move(dest));
}
src = (WaveTrack *) iter.Next();
}

View File

@ -16,6 +16,7 @@
#include "../MemoryX.h"
#include <set>
#include "../MemoryX.h"
#include <wx/bmpbuttn.h>
#include <wx/dynarray.h>
#include <wx/intl.h>
@ -37,6 +38,8 @@ class wxWindow;
#include "../Internat.h"
#include "../widgets/ProgressDialog.h"
#include "../Track.h"
class ShuttleGui;
#define BUILTIN_EFFECT_PREFIX wxT("Built-in Effect: ")
@ -409,7 +412,7 @@ protected:
private:
Effect *mpEffect{};
LabelTrack *mpTrack{};
const LabelTrack *mpOrigTrack{};
movable_ptr<Track> mpOrigTrack{};
};
// Set name to given value if that is not empty, else use default name
@ -422,7 +425,7 @@ protected:
void ReplaceProcessedTracks(const bool bGoodResult);
// Use this to append a NEW output track.
void AddToOutputTracks(Track *t);
Track *AddToOutputTracks(std::unique_ptr<Track> &&t);
//
// protected data

View File

@ -1120,8 +1120,7 @@ bool NyquistEffect::ProcessOne()
}
if (!ltrack) {
ltrack = mFactory->NewLabelTrack().release();
AddToOutputTracks((Track *)ltrack);
ltrack = static_cast<LabelTrack*>(AddToOutputTracks(mFactory->NewLabelTrack()));
}
for (l = 0; l < numLabels; l++) {

View File

@ -920,7 +920,7 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
wxString baseTrackName = recordingNameCustom? defaultRecordingTrackName : defaultTrackName;
for (int c = 0; c < recordingChannels; c++) {
WaveTrack *newTrack = p->GetTrackFactory()->NewWaveTrack().release();
auto newTrack = p->GetTrackFactory()->NewWaveTrack();
newTrack->SetOffset(t0);
wxString nameSuffix = wxString(wxT(""));
@ -972,14 +972,12 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
newTrack->SetChannel( Track::MonoChannel );
}
newRecordingTracks.push_back(newTrack);
// Let the list hold the track, and keep a pointer to it
newRecordingTracks.push_back(
static_cast<WaveTrack*>(
trackList->Add(
std::move(newTrack))));
}
// msmeyer: StartStream calls a callback which triggers auto-save, so
// we add the tracks where recording is done into now. We remove them
// later if starting the stream fails
for (unsigned int i = 0; i < newRecordingTracks.size(); i++)
trackList->Add(newRecordingTracks[i]);
}
//Automated Input Level Adjustment Initialization
@ -1096,18 +1094,19 @@ void ControlToolBar::SetupCutPreviewTracks(double WXUNUSED(playStart), double cu
if (track1)
{
// Duplicate and change tracks
track1 = track1->Duplicate().release();
track1->Clear(cutStart, cutEnd);
auto new1 = track1->Duplicate();
new1->Clear(cutStart, cutEnd);
decltype(new1) new2{};
if (track2)
{
track2 = track2->Duplicate().release();
track2->Clear(cutStart, cutEnd);
new2 = track2->Duplicate();
new2->Clear(cutStart, cutEnd);
}
mCutPreviewTracks = new TrackList();
mCutPreviewTracks->Add(track1);
mCutPreviewTracks->Add(std::move(new1));
if (track2)
mCutPreviewTracks->Add(track2);
mCutPreviewTracks->Add(std::move(new2));
}
}
}