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

More use of shared_ptr to Track, for safety...

... This even makes it possible to remove the prohibition of undo and redo
during transport, not that we want to though.  Playback and recording will
continue, using track objects that might not be in the current project.
This commit is contained in:
Paul Licameli 2017-08-24 11:44:36 -04:00
parent 0319d6ea68
commit c975de8c5e
15 changed files with 76 additions and 68 deletions

View File

@ -1857,7 +1857,7 @@ void AudioIO::StartMonitoring(double sampleRate)
}
}
int AudioIO::StartStream(const ConstWaveTrackArray &playbackTracks,
int AudioIO::StartStream(const WaveTrackConstArray &playbackTracks,
const WaveTrackArray &captureTracks,
#ifdef EXPERIMENTAL_MIDI_OUT
const NoteTrackArray &midiPlaybackTracks,
@ -1926,6 +1926,19 @@ int AudioIO::StartStream(const ConstWaveTrackArray &playbackTracks,
#ifdef EXPERIMENTAL_MIDI_OUT
mMidiPlaybackTracks = midiPlaybackTracks;
#endif
bool commit = false;
auto cleanupTracks = finally([&]{
if (!commit) {
// Don't keep unnecessary shared pointers to tracks
mPlaybackTracks.clear();
mCaptureTracks.clear();
#ifdef EXPERIMENTAL_MIDI_OUT
mMidiPlaybackTracks.clear();
#endif
}
});
mPlayMode = options.playLooped ? PLAY_LOOPED : PLAY_STRAIGHT;
mCutPreviewGapStart = options.cutPreviewGapStart;
mCutPreviewGapLen = options.cutPreviewGapLen;
@ -2109,8 +2122,10 @@ int AudioIO::StartStream(const ConstWaveTrackArray &playbackTracks,
mPlaybackBuffers[i] = std::make_unique<RingBuffer>(floatSample, playbackBufferSize);
// MB: use normal time for the end time, not warped time!
WaveTrackConstArray tracks;
tracks.push_back(mPlaybackTracks[i]);
mPlaybackMixers[i] = std::make_unique<Mixer>
(WaveTrackConstArray{ mPlaybackTracks[i] },
(tracks,
// Don't throw for read errors, just play silence:
false,
warpOptions,
@ -2184,7 +2199,7 @@ int AudioIO::StartStream(const ConstWaveTrackArray &playbackTracks,
int group = 0;
for (size_t i = 0, cnt = mPlaybackTracks.size(); i < cnt; i++)
{
const WaveTrack *vt = gAudioIO->mPlaybackTracks[i];
const WaveTrack *vt = gAudioIO->mPlaybackTracks[i].get();
unsigned chanCnt = 1;
if (vt->GetLinked())
@ -2319,6 +2334,7 @@ int AudioIO::StartStream(const ConstWaveTrackArray &playbackTracks,
// Enable warning popups for unfound aliased blockfiles.
wxGetApp().SetMissingAliasedFileWarningShouldShow(true);
commit = true;
return mStreamToken;
}
@ -2371,7 +2387,7 @@ void AudioIO::PrepareMidiIterator(bool send, double offset)
mIterator = std::make_unique<Alg_iterator>(nullptr, false);
// Iterator not yet intialized, must add each track...
for (i = 0; i < nTracks; i++) {
NoteTrack *t = mMidiPlaybackTracks[i];
NoteTrack *t = mMidiPlaybackTracks[i].get();
Alg_seq_ptr seq = &t->GetSeq();
// mark sequence tracks as "in use" since we're handing this
// off to another thread and want to make sure nothing happens
@ -2635,7 +2651,7 @@ void AudioIO::StopStream()
// set in_use flags to false
int nTracks = mMidiPlaybackTracks.size();
for (int i = 0; i < nTracks; i++) {
NoteTrack *t = mMidiPlaybackTracks[i];
NoteTrack *t = mMidiPlaybackTracks[i].get();
Alg_seq_ptr seq = &t->GetSeq();
seq->set_in_use(false);
}
@ -2709,7 +2725,7 @@ void AudioIO::StopStream()
// If the other track operations fail their strong guarantees, then
// the shift for latency correction may be skipped.
GuardedCall<void>( [&] {
WaveTrack* track = mCaptureTracks[i];
WaveTrack* track = mCaptureTracks[i].get();
// use NOFAIL-GUARANTEE that track is flushed,
// PARTIAL-GUARANTEE that some initial length of the recording
@ -2726,7 +2742,7 @@ void AudioIO::StopStream()
bool appendRecord = false;
for (unsigned int j = 0; j < playbackTracks.size(); j++)
{ // find if we are recording into an existing track (append-record)
WaveTrack* trackP = playbackTracks[j];
WaveTrack* trackP = playbackTracks[j].get();
if( track == trackP )
{
if( track->GetStartTime() != mT0 ) // in a NEW track if these are equal
@ -2794,6 +2810,10 @@ void AudioIO::StopStream()
mNumCaptureChannels = 0;
mNumPlaybackChannels = 0;
mPlaybackTracks.clear();
mCaptureTracks.clear();
mMidiPlaybackTracks.clear();
#ifdef EXPERIMENTAL_SCRUBBING_SUPPORT
mScrubQueue.reset();
#endif
@ -4908,7 +4928,7 @@ int audacityAudioCallback(const void *inputBuffer, void *outputBuffer,
decltype(framesPerBuffer) maxLen = 0;
for (unsigned t = 0; t < numPlaybackTracks; t++)
{
const WaveTrack *vt = gAudioIO->mPlaybackTracks[t];
const WaveTrack *vt = gAudioIO->mPlaybackTracks[t].get();
chans[chanCnt] = vt;

View File

@ -32,7 +32,7 @@
#include "../lib-src/header-substitutes/allegro.h"
class NoteTrack;
using NoteTrackArray = std::vector < NoteTrack* >;
using NoteTrackArray = std::vector < std::shared_ptr< NoteTrack > >;
#endif // EXPERIMENTAL_MIDI_OUT
@ -60,8 +60,8 @@ class SelectedRegion;
class AudacityProject;
class WaveTrack;
using WaveTrackArray = std::vector < WaveTrack* >;
using ConstWaveTrackArray = std::vector < const WaveTrack* >;
using WaveTrackArray = std::vector < std::shared_ptr < WaveTrack > >;
using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >;
extern AUDACITY_DLL_API AudioIO *gAudioIO;
@ -164,7 +164,7 @@ class AUDACITY_DLL_API AudioIO final {
* If successful, returns a token identifying this particular stream
* instance. For use with IsStreamActive() below */
int StartStream(const ConstWaveTrackArray &playbackTracks, const WaveTrackArray &captureTracks,
int StartStream(const WaveTrackConstArray &playbackTracks, const WaveTrackArray &captureTracks,
#ifdef EXPERIMENTAL_MIDI_OUT
const NoteTrackArray &midiTracks,
#endif
@ -637,7 +637,7 @@ private:
ArrayOf<std::unique_ptr<RingBuffer>> mCaptureBuffers;
WaveTrackArray mCaptureTracks;
ArrayOf<std::unique_ptr<RingBuffer>> mPlaybackBuffers;
ConstWaveTrackArray mPlaybackTracks;
WaveTrackConstArray mPlaybackTracks;
ArrayOf<std::unique_ptr<Mixer>> mPlaybackMixers;
volatile int mStreamToken;

View File

@ -327,7 +327,7 @@ bool RecordingRecoveryHandler::HandleXMLTag(const wxChar *tag,
return false;
}
WaveTrack* track = tracks[index];
WaveTrack* track = tracks[index].get();
WaveClip* clip = track->NewestOrNewClip();
Sequence* seq = clip->GetSequence();
@ -412,7 +412,7 @@ void RecordingRecoveryHandler::HandleXMLEndTag(const wxChar *tag)
wxASSERT(false);
}
else {
WaveTrack* track = tracks[index];
WaveTrack* track = tracks[index].get();
WaveClip* clip = track->NewestOrNewClip();
Sequence* seq = clip->GetSequence();

View File

@ -92,7 +92,7 @@ void MixAndRender(TrackList *tracks, TrackFactory *trackFactory,
while (t) {
if (t->GetSelected() && t->GetKind() == Track::Wave) {
waveArray.push_back(static_cast<const WaveTrack *>(t));
waveArray.push_back(Track::Pointer<const WaveTrack>(t));
tstart = t->GetStartTime();
tend = t->GetEndTime();
if (tend > mixEndTime)

View File

@ -23,6 +23,7 @@
#include "MemoryX.h"
#include <wx/string.h>
#include "SampleFormat.h"
#include <vector>
class Resample;
class DirManager;
@ -30,7 +31,7 @@ class TimeTrack;
class TrackFactory;
class TrackList;
class WaveTrack;
class WaveTrackConstArray;
using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >;
class WaveTrackCache;
/** @brief Mixes together all input tracks, applying any envelopes, amplitude

View File

@ -4136,9 +4136,12 @@ bool AudacityProject::Save(bool overwrite /* = true */ ,
#endif
void AudacityProject::AddImportedTracks(const wxString &fileName,
TrackHolders &&newTracks)
std::vector< std::shared_ptr< Track > >
AudacityProject::AddImportedTracks(const wxString &fileName,
TrackHolders &&newTracks)
{
std::vector< std::shared_ptr< Track > > results;
const auto numTracks = newTracks.size();
SelectNone();
@ -4151,6 +4154,7 @@ void AudacityProject::AddImportedTracks(const wxString &fileName,
++i;
auto newTrack = mTracks->Add(std::move(uNewTrack));
results.push_back(Track::Pointer(newTrack));
if (newRate == 0 && newTrack->GetKind() == Track::Wave) {
newRate = ((WaveTrack *)newTrack)->GetRate();
}
@ -4213,6 +4217,8 @@ void AudacityProject::AddImportedTracks(const wxString &fileName,
// HandleResize();
newTracks.clear();
return results;
}
void AudacityProject::ZoomAfterImport(Track *pTrack)
@ -4271,19 +4277,17 @@ bool AudacityProject::Import(const wxString &fileName, WaveTrackArray* pTrackArr
return false;
}
// Have to set up newTrackList before calling AddImportedTracks,
// because AddImportedTracks deletes newTracks.
// PRL: Undo history is incremented inside this:
auto newSharedTracks = AddImportedTracks(fileName, std::move(newTracks));
if (pTrackArray) {
for (const auto &newTrack : newTracks) {
if (newTrack->GetKind() == Track::Wave) {
pTrackArray->push_back(static_cast<WaveTrack *>(newTrack.get()));
}
for (const auto &newTrack : newSharedTracks) {
if (newTrack->GetKind() == Track::Wave)
pTrackArray->push_back(
std::static_pointer_cast<WaveTrack>(newTrack));
}
}
// PRL: Undo history is incremented inside this:
AddImportedTracks(fileName, std::move(newTracks));
int mode = gPrefs->Read(wxT("/AudioFiles/NormalizeOnLoad"), 0L);
if (mode == 1) {
//TODO: All we want is a SelectAll()

View File

@ -267,8 +267,10 @@ public:
void ZoomAfterImport(Track *pTrack);
void AddImportedTracks(const wxString &fileName,
TrackHolders &&newTracks);
// Takes array of unique pointers; returns array of shared
std::vector< std::shared_ptr<Track> >
AddImportedTracks(const wxString &fileName,
TrackHolders &&newTracks);
bool Save(bool overwrite = true, bool fromSaveAs = false, bool bWantSaveCompressed = false);
bool SaveAs(bool bWantSaveCompressed = false);

View File

@ -1324,7 +1324,8 @@ namespace {
if (track->GetKind() == Track::Wave &&
(includeMuted || !wt->GetMute()) &&
(track->GetSelected() || !selectionOnly)) {
waveTrackArray.push_back(static_cast<WaveTrack*>(track.get()));
waveTrackArray.push_back(
std::static_pointer_cast<WaveTrack>(track));
}
}
@ -1350,7 +1351,7 @@ NoteTrackArray TrackList::GetNoteTrackArray(bool selectionOnly)
for(const auto &track : *this) {
if (track->GetKind() == Track::Note &&
(track->GetSelected() || !selectionOnly)) {
noteTrackArray.push_back(static_cast<NoteTrack*>(track.get()));
noteTrackArray.push_back(std::static_pointer_cast<NoteTrack>(track));
}
}

View File

@ -48,27 +48,9 @@ class SelectHandle;
class TimeShiftHandle;
WX_DEFINE_USER_EXPORTED_ARRAY(Track*, TrackArray, class AUDACITY_DLL_API);
using WaveTrackArray = std::vector < WaveTrack* > ;
class WaveTrackConstArray : public std::vector < const WaveTrack* > {
public:
WaveTrackConstArray() {}
// I'd like to use an inherited constructor, but that's not here yet in MSVC compiler...
#ifdef __AUDACITY_OLD_STD__
WaveTrackConstArray
(std::initializer_list<value_type> tracks)
{
reserve(tracks.size());
for (const auto &track : tracks)
push_back(track);
}
#else
WaveTrackConstArray
(std::initializer_list<value_type> tracks) : std::vector<value_type>(tracks) {}
#endif
};
using NoteTrackArray = std::vector < NoteTrack* >;
using WaveTrackArray = std::vector < std::shared_ptr< WaveTrack > > ;
using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >;
using NoteTrackArray = std::vector < std::shared_ptr < NoteTrack > >;
#if defined(USE_MIDI)
class NoteTrack;

View File

@ -2126,7 +2126,7 @@ void TrackArtist::DrawSpectrum(const WaveTrack *track,
DrawBackgroundWithSelection(&dc, rect, track, blankSelectedBrush, blankBrush,
selectedRegion, zoomInfo);
WaveTrackCache cache(track);
WaveTrackCache cache(Track::Pointer<const WaveTrack>(track));
for (const auto &clip: track->GetClips()) {
DrawClipSpectrum(cache, clip.get(), dc, rect, selectedRegion, zoomInfo);
}

View File

@ -2691,7 +2691,7 @@ WaveTrackCache::~WaveTrackCache()
{
}
void WaveTrackCache::SetTrack(const WaveTrack *pTrack)
void WaveTrackCache::SetTrack(const std::shared_ptr<const WaveTrack> &pTrack)
{
if (mPTrack != pTrack) {
if (pTrack) {

View File

@ -684,16 +684,14 @@ protected:
class WaveTrackCache {
public:
WaveTrackCache()
: mPTrack(0)
, mBufferSize(0)
: mBufferSize(0)
, mOverlapBuffer()
, mNValidBuffers(0)
{
}
explicit WaveTrackCache(const WaveTrack *pTrack)
: mPTrack(0)
, mBufferSize(0)
explicit WaveTrackCache(const std::shared_ptr<const WaveTrack> &pTrack)
: mBufferSize(0)
, mOverlapBuffer()
, mNValidBuffers(0)
{
@ -701,8 +699,8 @@ public:
}
~WaveTrackCache();
const WaveTrack *GetTrack() const { return mPTrack; }
void SetTrack(const WaveTrack *pTrack);
const WaveTrack *GetTrack() const { return mPTrack.get(); }
void SetTrack(const std::shared_ptr<const WaveTrack> &pTrack);
// Uses fillZero always
// Returns null on failure
@ -731,7 +729,7 @@ private:
}
};
const WaveTrack *mPTrack;
std::shared_ptr<const WaveTrack> mPTrack;
size_t mBufferSize;
Buffer mBuffers[2];
GrowableSampleBuffer mOverlapBuffer;

View File

@ -2593,7 +2593,7 @@ void Effect::Preview(bool dryOnly)
SelectedTrackListOfKindIterator iter(Track::Wave, mTracks);
WaveTrack *src = (WaveTrack *) iter.First();
while (src) {
playbackTracks.push_back(src);
playbackTracks.push_back(Track::Pointer<WaveTrack>(src));
src = (WaveTrack *) iter.Next();
}
// Some effects (Paulstretch) may need to generate more

View File

@ -32,7 +32,7 @@ class TrackList;
class MixerSpec;
class TimeTrack;
class Mixer;
class WaveTrackConstArray;
using WaveTrackConstArray = std::vector < std::shared_ptr < const WaveTrack > >;
enum class ProgressResult : unsigned;
class AUDACITY_DLL_API FormatInfo

View File

@ -973,7 +973,7 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
if ( ! shifted ) {
// msmeyer: Delete recently added tracks if opening stream fails
for ( auto track : recordingTracks )
trackList->Remove(track);
trackList->Remove(track.get());
}
SetPlay(false);
@ -1066,7 +1066,7 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
// playback.
for (Track *tt = it.First(); tt; tt = it.Next()) {
if (tt->GetKind() == Track::Wave && (tt->GetSelected() || !sel)) {
WaveTrack *wt = static_cast<WaveTrack *>(tt);
auto wt = Track::Pointer<WaveTrack>(tt);
if (duplex) {
auto end = playbackTracks.end();
auto it = std::find(playbackTracks.begin(), end, wt);
@ -1184,7 +1184,7 @@ void ControlToolBar::OnRecord(wxCommandEvent &evt)
// Let the list hold the track, and keep a pointer to it
recordingTracks.push_back(
static_cast<WaveTrack*>(
Track::Pointer<WaveTrack>(
trackList->Add(
std::move(newTrack))));
}