1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-16 16:10:06 +02:00

Track.cpp does not depend directly on its subclasses

This commit is contained in:
Paul Licameli 2019-06-06 09:27:35 -04:00
parent 98960c4fc3
commit 291bd7258f
12 changed files with 101 additions and 145 deletions

View File

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

View File

@ -144,7 +144,7 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
endTime = mixEndTime;
}
auto timeTrack = tracks->GetTimeTrack();
auto timeTrack = *tracks->Any<TimeTrack>().begin();
Mixer mixer(waveArray,
// Throw to abort mix-and-render if read fails:
true,

View File

@ -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<TimeTrack>().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<TimeTrack>().begin();
options.envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr;
options.listener = &ProjectAudioManager::Get( project );
return options;

View File

@ -35,10 +35,6 @@ and TimeTrack.
#include <wx/textfile.h>
#include <wx/log.h>
#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<TimeTrack>().begin();
}
const TimeTrack *TrackList::GetTimeTrack() const
{
return const_cast<TrackList*>(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<typename Array, typename TrackRange>
Array GetTypedTracks(const TrackRange &trackRange,
bool selectionOnly, bool includeMuted)
{
using Type = typename std::remove_reference<
decltype( *std::declval<Array>()[0] )
>::type;
auto subRange =
trackRange.template Filter<Type>();
if ( selectionOnly )
subRange = subRange + &Track::IsSelected;
if ( ! includeMuted )
subRange = subRange - &Type::GetMute;
return transform_range<Array>( subRange.begin(), subRange.end(),
[]( Type *t ){ return t->template SharedPointer<Type>(); }
);
}
}
WaveTrackArray TrackList::GetWaveTrackArray(bool selectionOnly, bool includeMuted)
{
return GetTypedTracks<WaveTrackArray>(Any(), selectionOnly, includeMuted);
}
WaveTrackConstArray TrackList::GetWaveTrackConstArray(bool selectionOnly, bool includeMuted) const
{
return GetTypedTracks<WaveTrackConstArray>(Any(), selectionOnly, includeMuted);
}
#if defined(USE_MIDI)
NoteTrackConstArray TrackList::GetNoteTrackConstArray(bool selectionOnly) const
{
return GetTypedTracks<NoteTrackConstArray>(Any(), selectionOnly, true);
}
#endif
int TrackList::GetHeight() const
{
int height = 0;

View File

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

View File

@ -2624,7 +2624,7 @@ void WaveTrack::AddInvalidRegion(sampleCount startSample, sampleCount endSample)
clip->AddInvalidRegion(startSample, endSample);
}
int WaveTrack::GetAutoSaveIdent()
int WaveTrack::GetAutoSaveIdent() const
{
return mAutoSaveIdent;
}

View File

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

View File

@ -248,9 +248,14 @@ std::unique_ptr<Mixer> 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<const TimeTrack>().begin();
auto envelope = timeTrack ? timeTrack->GetEnvelope() : nullptr;
// MB: the stop time should not be warped, this was a bug.
return std::make_unique<Mixer>(inputTracks,

View File

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

View File

@ -118,7 +118,7 @@ bool DoPasteNothingSelected(AudacityProject &project)
},
[&](const TimeTrack *) {
// Maintain uniqueness of the time track!
pNewTrack = tracks.GetTimeTrack();
pNewTrack = *tracks.Any<TimeTrack>().begin();
if (!pNewTrack)
uNewTrack = trackFactory.NewTimeTrack(),
pNewTrack = uNewTrack.get();

View File

@ -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<TimeTrack>().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<const TimeTrack >().begin()
}, // const WarpOptions &warpOptions
0.0, // double startTime
endTime, // double stopTime
2, // int numOutChannels

View File

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