From 291bd7258f6f0a6ea4615d9730c59bfc01eaa615 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 6 Jun 2019 09:27:35 -0400 Subject: [PATCH] Track.cpp does not depend directly on its subclasses --- src/AutoRecovery.cpp | 21 ++++--- src/Mix.cpp | 2 +- src/ProjectAudioManager.cpp | 4 +- src/Track.cpp | 104 -------------------------------- src/Track.h | 18 ------ src/WaveTrack.cpp | 2 +- src/WaveTrack.h | 2 +- src/export/Export.cpp | 11 +++- src/export/ExportMultiple.cpp | 53 +++++++++++++++- src/menus/EditMenus.cpp | 2 +- src/menus/TrackMenus.cpp | 6 +- src/toolbars/ControlToolBar.cpp | 21 ++++++- 12 files changed, 101 insertions(+), 145 deletions(-) diff --git a/src/AutoRecovery.cpp b/src/AutoRecovery.cpp index cb54f2a74..4ba2bc40b 100644 --- a/src/AutoRecovery.cpp +++ b/src/AutoRecovery.cpp @@ -45,13 +45,14 @@ RecordingRecoveryHandler::RecordingRecoveryHandler(AudacityProject* proj) int RecordingRecoveryHandler::FindTrack() const { - WaveTrackArray tracks = TrackList::Get( *mProject ).GetWaveTrackArray(false); - int index; + auto tracks = TrackList::Get( *mProject ).Any< const WaveTrack >(); + int index = 0; if (mAutoSaveIdent) { - for (index = 0; index < (int)tracks.size(); index++) + auto iter = tracks.begin(), end = tracks.end(); + for (; iter != end; ++iter, ++index) { - if (tracks[index]->GetAutoSaveIdent() == mAutoSaveIdent) + if ((*iter)->GetAutoSaveIdent() == mAutoSaveIdent) { break; } @@ -78,7 +79,7 @@ bool RecordingRecoveryHandler::HandleXMLTag(const wxChar *tag, return false; } - WaveTrackArray tracks = TrackList::Get( *mProject ).GetWaveTrackArray(false); + auto tracks = TrackList::Get( *mProject ).Any< WaveTrack >(); int index = FindTrack(); // We need to find the track and sequence where the blockfile belongs @@ -89,7 +90,9 @@ bool RecordingRecoveryHandler::HandleXMLTag(const wxChar *tag, return false; } - WaveTrack* track = tracks[index].get(); + auto iter = tracks.begin(); + std::advance( iter, index ); + WaveTrack* track = *iter; WaveClip* clip = track->NewestOrNewClip(); Sequence* seq = clip->GetSequence(); @@ -164,7 +167,7 @@ void RecordingRecoveryHandler::HandleXMLEndTag(const wxChar *tag) // Still in inner loop return; - WaveTrackArray tracks = TrackList::Get( *mProject ).GetWaveTrackArray(false); + auto tracks = TrackList::Get( *mProject ).Any< WaveTrack >(); int index = FindTrack(); // We need to find the track and sequence where the blockfile belongs @@ -173,7 +176,9 @@ void RecordingRecoveryHandler::HandleXMLEndTag(const wxChar *tag) wxASSERT(false); } else { - WaveTrack* track = tracks[index].get(); + auto iter = tracks.begin(); + std::advance( iter, index ); + WaveTrack* track = *iter; WaveClip* clip = track->NewestOrNewClip(); Sequence* seq = clip->GetSequence(); diff --git a/src/Mix.cpp b/src/Mix.cpp index 5fcd72a97..c181308b7 100644 --- a/src/Mix.cpp +++ b/src/Mix.cpp @@ -144,7 +144,7 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory, endTime = mixEndTime; } - auto timeTrack = tracks->GetTimeTrack(); + auto timeTrack = *tracks->Any().begin(); Mixer mixer(waveArray, // Throw to abort mix-and-render if read fails: true, diff --git a/src/ProjectAudioManager.cpp b/src/ProjectAudioManager.cpp index 219ebd47e..7a79a969f 100644 --- a/src/ProjectAudioManager.cpp +++ b/src/ProjectAudioManager.cpp @@ -176,7 +176,7 @@ DefaultPlayOptions( AudacityProject &project ) ProjectSettings::Get( project ).GetRate() }; options.captureMeter = projectAudioIO.GetCaptureMeter(); options.playbackMeter = projectAudioIO.GetPlaybackMeter(); - auto timeTrack = TrackList::Get( project ).GetTimeTrack(); + auto timeTrack = *TrackList::Get( project ).Any().begin(); options.envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr; options.listener = &ProjectAudioManager::Get( project ); return options; @@ -195,7 +195,7 @@ DefaultSpeedPlayOptions( AudacityProject &project ) AudioIOStartStreamOptions options{ &project, PlayAtSpeedRate }; options.captureMeter = projectAudioIO.GetCaptureMeter(); options.playbackMeter = projectAudioIO.GetPlaybackMeter(); - auto timeTrack = TrackList::Get( project ).GetTimeTrack(); + auto timeTrack = *TrackList::Get( project ).Any().begin(); options.envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr; options.listener = &ProjectAudioManager::Get( project ); return options; diff --git a/src/Track.cpp b/src/Track.cpp index f37a00983..4d8c19e32 100644 --- a/src/Track.cpp +++ b/src/Track.cpp @@ -35,10 +35,6 @@ and TimeTrack. #include #include -#include "TimeTrack.h" -#include "WaveTrack.h" -#include "NoteTrack.h" -#include "LabelTrack.h" #include "Project.h" #include "ProjectSettings.h" #include "DirManager.h" @@ -1070,106 +1066,6 @@ size_t TrackList::size() const return cnt; } -TimeTrack *TrackList::GetTimeTrack() -{ - return *Any().begin(); -} - -const TimeTrack *TrackList::GetTimeTrack() const -{ - return const_cast(this)->GetTimeTrack(); -} - -unsigned TrackList::GetNumExportChannels(bool selectionOnly) const -{ - /* counters for tracks panned different places */ - int numLeft = 0; - int numRight = 0; - //int numMono = 0; - /* track iteration kit */ - - // Want only unmuted wave tracks. - for (auto tr : - Any< const WaveTrack >() - + (selectionOnly ? &Track::IsSelected : &Track::Any) - - &WaveTrack::GetMute - ) { - // Found a left channel - if (tr->GetChannel() == Track::LeftChannel) { - numLeft++; - } - - // Found a right channel - else if (tr->GetChannel() == Track::RightChannel) { - numRight++; - } - - // Found a mono channel, but it may be panned - else if (tr->GetChannel() == Track::MonoChannel) { - float pan = tr->GetPan(); - - // Figure out what kind of channel it should be - if (pan == -1.0) { // panned hard left - numLeft++; - } - else if (pan == 1.0) { // panned hard right - numRight++; - } - else if (pan == 0) { // panned dead center - // numMono++; - } - else { // panned somewhere else - numLeft++; - numRight++; - } - } - } - - // if there is stereo content, report 2, else report 1 - if (numRight > 0 || numLeft > 0) { - return 2; - } - - return 1; -} - -namespace { - template - Array GetTypedTracks(const TrackRange &trackRange, - bool selectionOnly, bool includeMuted) - { - using Type = typename std::remove_reference< - decltype( *std::declval()[0] ) - >::type; - auto subRange = - trackRange.template Filter(); - if ( selectionOnly ) - subRange = subRange + &Track::IsSelected; - if ( ! includeMuted ) - subRange = subRange - &Type::GetMute; - return transform_range( subRange.begin(), subRange.end(), - []( Type *t ){ return t->template SharedPointer(); } - ); - } -} - -WaveTrackArray TrackList::GetWaveTrackArray(bool selectionOnly, bool includeMuted) -{ - return GetTypedTracks(Any(), selectionOnly, includeMuted); -} - -WaveTrackConstArray TrackList::GetWaveTrackConstArray(bool selectionOnly, bool includeMuted) const -{ - return GetTypedTracks(Any(), selectionOnly, includeMuted); -} - -#if defined(USE_MIDI) -NoteTrackConstArray TrackList::GetNoteTrackConstArray(bool selectionOnly) const -{ - return GetTypedTracks(Any(), selectionOnly, true); -} -#endif - int TrackList::GetHeight() const { int height = 0; diff --git a/src/Track.h b/src/Track.h index ddbecc4c4..0fb08527e 100644 --- a/src/Track.h +++ b/src/Track.h @@ -1416,24 +1416,6 @@ public: bool MoveDown(Track * t); bool Move(Track * t, bool up) { return up ? MoveUp(t) : MoveDown(t); } - TimeTrack *GetTimeTrack(); - const TimeTrack *GetTimeTrack() const; - - /** \brief Find out how many channels this track list mixes to - * - * This is used in exports of the tracks to work out whether to export in - * Mono, Stereo etc. @param selectionOnly Whether to consider the entire track - * list or only the selected members of it - */ - unsigned GetNumExportChannels(bool selectionOnly) const; - - WaveTrackArray GetWaveTrackArray(bool selectionOnly, bool includeMuted = true); - WaveTrackConstArray GetWaveTrackConstArray(bool selectionOnly, bool includeMuted = true) const; - -#if defined(USE_MIDI) - NoteTrackConstArray GetNoteTrackConstArray(bool selectionOnly) const; -#endif - /// Mainly a test function. Uses a linear search, so could be slow. bool Contains(const Track * t) const; diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index ab0836d7d..4053bfec5 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -2624,7 +2624,7 @@ void WaveTrack::AddInvalidRegion(sampleCount startSample, sampleCount endSample) clip->AddInvalidRegion(startSample, endSample); } -int WaveTrack::GetAutoSaveIdent() +int WaveTrack::GetAutoSaveIdent() const { return mAutoSaveIdent; } diff --git a/src/WaveTrack.h b/src/WaveTrack.h index b8cac7ead..c8939d13f 100644 --- a/src/WaveTrack.h +++ b/src/WaveTrack.h @@ -553,7 +553,7 @@ private: // AutoSave related // // Retrieve the unique autosave ID - int GetAutoSaveIdent(); + int GetAutoSaveIdent() const; // Set the unique autosave ID void SetAutoSaveIdent(int id); diff --git a/src/export/Export.cpp b/src/export/Export.cpp index da42dd0e7..1ab73df04 100644 --- a/src/export/Export.cpp +++ b/src/export/Export.cpp @@ -248,9 +248,14 @@ std::unique_ptr ExportPlugin::CreateMixer(const TrackList &tracks, double outRate, sampleFormat outFormat, bool highQuality, MixerSpec *mixerSpec) { - const WaveTrackConstArray inputTracks = - tracks.GetWaveTrackConstArray(selectionOnly, false); - const TimeTrack *timeTrack = tracks.GetTimeTrack(); + WaveTrackConstArray inputTracks; + auto range = tracks.Any< const WaveTrack >() + + (selectionOnly ? &Track::IsSelected : &Track::Any ) + - &WaveTrack::GetMute; + for (auto pTrack: range) + inputTracks.push_back( + pTrack->SharedPointer< const WaveTrack >() ); + const auto timeTrack = *tracks.Any().begin(); auto envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr; // MB: the stop time should not be warped, this was a bug. return std::make_unique(inputTracks, diff --git a/src/export/ExportMultiple.cpp b/src/export/ExportMultiple.cpp index 47d29797d..399189676 100644 --- a/src/export/ExportMultiple.cpp +++ b/src/export/ExportMultiple.cpp @@ -646,6 +646,57 @@ bool ExportMultiple::DirOk() return fn.Mkdir(0777, wxPATH_MKDIR_FULL); } +static unsigned GetNumExportChannels( const TrackList &tracks ) +{ + /* counters for tracks panned different places */ + int numLeft = 0; + int numRight = 0; + //int numMono = 0; + /* track iteration kit */ + + // Want only unmuted wave tracks. + for (auto tr : + tracks.Any< const WaveTrack >() - &WaveTrack::GetMute + ) { + // Found a left channel + if (tr->GetChannel() == Track::LeftChannel) { + numLeft++; + } + + // Found a right channel + else if (tr->GetChannel() == Track::RightChannel) { + numRight++; + } + + // Found a mono channel, but it may be panned + else if (tr->GetChannel() == Track::MonoChannel) { + float pan = tr->GetPan(); + + // Figure out what kind of channel it should be + if (pan == -1.0) { // panned hard left + numLeft++; + } + else if (pan == 1.0) { // panned hard right + numRight++; + } + else if (pan == 0) { // panned dead center + // numMono++; + } + else { // panned somewhere else + numLeft++; + numRight++; + } + } + } + + // if there is stereo content, report 2, else report 1 + if (numRight > 0 || numLeft > 0) { + return 2; + } + + return 1; +} + // TODO: JKC July2016: Merge labels/tracks duplicated export code. // TODO: JKC Apr2019: Doubly so merge these! Too much duplication. ProgressResult ExportMultiple::ExportMultipleByLabel(bool byName, @@ -664,7 +715,7 @@ ProgressResult ExportMultiple::ExportMultipleByLabel(bool byName, } // Figure out how many channels we should export. - auto channels = mTracks->GetNumExportChannels(false); + auto channels = GetNumExportChannels( *mTracks ); FilePaths otherNames; // keep track of file names we will use, so we // don't duplicate them diff --git a/src/menus/EditMenus.cpp b/src/menus/EditMenus.cpp index 433c9c63e..501ea396c 100644 --- a/src/menus/EditMenus.cpp +++ b/src/menus/EditMenus.cpp @@ -118,7 +118,7 @@ bool DoPasteNothingSelected(AudacityProject &project) }, [&](const TimeTrack *) { // Maintain uniqueness of the time track! - pNewTrack = tracks.GetTimeTrack(); + pNewTrack = *tracks.Any().begin(); if (!pNewTrack) uNewTrack = trackFactory.NewTimeTrack(), pNewTrack = uNewTrack.get(); diff --git a/src/menus/TrackMenus.cpp b/src/menus/TrackMenus.cpp index 460a31a66..261ad06f1 100644 --- a/src/menus/TrackMenus.cpp +++ b/src/menus/TrackMenus.cpp @@ -889,7 +889,7 @@ void OnNewTimeTrack(const CommandContext &context) auto &trackPanel = TrackPanel::Get( project ); auto &window = ProjectWindow::Get( project ); - if (tracks.GetTimeTrack()) { + if ( *tracks.Any().begin() ) { AudacityMessageBox(_("This version of Audacity only allows one time track for each project window.")); return; } @@ -1205,7 +1205,9 @@ void OnScoreAlign(const CommandContext &context) Mixer mix( waveTracks, // const WaveTrackConstArray &inputTracks false, // mayThrow -- is this right? - Mixer::WarpOptions{ tracks->GetTimeTrack() }, // const WarpOptions &warpOptions + Mixer::WarpOptions{ + *tracks->Any().begin() + }, // const WarpOptions &warpOptions 0.0, // double startTime endTime, // double stopTime 2, // int numOutChannels diff --git a/src/toolbars/ControlToolBar.cpp b/src/toolbars/ControlToolBar.cpp index 56010d960..99889aeb2 100644 --- a/src/toolbars/ControlToolBar.cpp +++ b/src/toolbars/ControlToolBar.cpp @@ -1545,13 +1545,28 @@ void ControlToolBar::CancelRecording() TrackList::Get( *project ).ClearPendingTracks(); } +#ifdef EXPERIMENTAL_MIDI_OUT +#include "NoteTrack.h" +#endif + TransportTracks GetAllPlaybackTracks(TrackList &trackList, bool selectedOnly, bool useMidi) { TransportTracks result; - result.playbackTracks = trackList.GetWaveTrackArray(selectedOnly); + { + auto range = trackList.Any< WaveTrack >() + + (selectedOnly ? &Track::IsSelected : &Track::Any ); + for (auto pTrack: range) + result.playbackTracks.push_back( + pTrack->SharedPointer< WaveTrack >() ); + } #ifdef EXPERIMENTAL_MIDI_OUT - if (useMidi) - result.midiTracks = trackList.GetNoteTrackConstArray(selectedOnly); + if (useMidi) { + auto range = trackList.Any< const NoteTrack >() + + (selectedOnly ? &Track::IsSelected : &Track::Any ); + for (auto pTrack: range) + result.midiTracks.push_back( + pTrack->SharedPointer< const NoteTrack >() ); + } #else WXUNUSED(useMidi); #endif