mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-25 15:53:52 +02:00
Sequence::Paste gives strong guarantee
This commit is contained in:
@@ -72,9 +72,7 @@ Sequence::Sequence(const Sequence &orig, const std::shared_ptr<DirManager> &proj
|
||||
, mMinSamples(orig.mMinSamples)
|
||||
, mMaxSamples(orig.mMaxSamples)
|
||||
{
|
||||
bool bResult = Paste(0, &orig);
|
||||
wxASSERT(bResult); // TO DO: Actually handle this.
|
||||
(void)bResult;
|
||||
Paste(0, &orig);
|
||||
}
|
||||
|
||||
Sequence::~Sequence()
|
||||
@@ -451,7 +449,8 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
void Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
// STRONG-GUARANTEE
|
||||
{
|
||||
if ((s < 0) || (s > mNumSamples))
|
||||
{
|
||||
@@ -460,8 +459,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
// PRL: Why bother with Internat when the above is just wxT?
|
||||
Internat::ToString(s.as_double(), 0).c_str(),
|
||||
Internat::ToString(mNumSamples.as_double(), 0).c_str());
|
||||
wxASSERT(false);
|
||||
return false;
|
||||
//THROW_INCONSISTENCY_EXCEPTION
|
||||
;
|
||||
}
|
||||
|
||||
// Quick check to make sure that it doesn't overflow
|
||||
@@ -472,8 +471,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
// PRL: Why bother with Internat when the above is just wxT?
|
||||
Internat::ToString(mNumSamples.as_double(), 0).c_str(),
|
||||
Internat::ToString(src->mNumSamples.as_double(), 0).c_str());
|
||||
wxASSERT(false);
|
||||
return false;
|
||||
//THROW_INCONSISTENCY_EXCEPTION
|
||||
;
|
||||
}
|
||||
|
||||
if (src->mSampleFormat != mSampleFormat)
|
||||
@@ -481,8 +480,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
wxLogError(
|
||||
wxT("Sequence::Paste: Sample format to be pasted, %s, does not match destination format, %s."),
|
||||
GetSampleFormatStr(src->mSampleFormat), GetSampleFormatStr(src->mSampleFormat));
|
||||
wxASSERT(false);
|
||||
return false;
|
||||
//THROW_INCONSISTENCY_EXCEPTION
|
||||
;
|
||||
}
|
||||
|
||||
const BlockArray &srcBlock = src->mBlock;
|
||||
@@ -491,7 +490,7 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
auto sampleSize = SAMPLE_SIZE(mSampleFormat);
|
||||
|
||||
if (addedLen == 0 || srcNumBlocks == 0)
|
||||
return true;
|
||||
return;
|
||||
|
||||
const size_t numBlocks = mBlock.size();
|
||||
|
||||
@@ -501,12 +500,18 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
// onto the end because the current last block is longer than the
|
||||
// minimum size
|
||||
|
||||
// Build and swap a copy so there is a strong exception safety guarantee
|
||||
BlockArray newBlock{ mBlock };
|
||||
sampleCount samples = mNumSamples;
|
||||
for (unsigned int i = 0; i < srcNumBlocks; i++)
|
||||
AppendBlock(*mDirManager, mBlock, mNumSamples, srcBlock[i]);
|
||||
// AppendBlock may throw for limited disk space, if pasting from
|
||||
// one project into another.
|
||||
AppendBlock(*mDirManager, newBlock, samples, srcBlock[i]);
|
||||
// Increase ref count or duplicate file
|
||||
|
||||
ConsistencyCheck(wxT("Paste branch one"));
|
||||
return true;
|
||||
CommitChangesIfConsistent
|
||||
(newBlock, samples, wxT("Paste branch one"));
|
||||
return;
|
||||
}
|
||||
|
||||
const int b = (s == mNumSamples) ? mBlock.size() - 1 : FindBlock(s);
|
||||
@@ -541,6 +546,10 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
// largerBlockLen is not more than mMaxSamples...
|
||||
buffer.ptr(), largerBlockLen.as_size_t(), mSampleFormat);
|
||||
|
||||
// Don't make a duplicate array. We can still give STRONG-GUARANTEE
|
||||
// if we modify only one block in place.
|
||||
|
||||
// use NOFAIL-GUARANTEE in remaining steps
|
||||
block.f = file;
|
||||
|
||||
for (unsigned int i = b + 1; i < numBlocks; i++)
|
||||
@@ -548,8 +557,10 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
|
||||
mNumSamples += addedLen;
|
||||
|
||||
ConsistencyCheck(wxT("Paste branch two"));
|
||||
return true;
|
||||
// This consistency check won't throw, it asserts.
|
||||
// Proof that we kept consistency is not hard.
|
||||
ConsistencyCheck(wxT("Paste branch two"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Case three: if we are inserting four or fewer blocks,
|
||||
@@ -637,12 +648,8 @@ bool Sequence::Paste(sampleCount s, const Sequence *src)
|
||||
for (i = b + 1; i < numBlocks; i++)
|
||||
newBlock.push_back(mBlock[i].Plus(addedLen));
|
||||
|
||||
mBlock.swap(newBlock);
|
||||
|
||||
mNumSamples += addedLen;
|
||||
|
||||
ConsistencyCheck(wxT("Paste branch three"));
|
||||
return true;
|
||||
CommitChangesIfConsistent
|
||||
(newBlock, mNumSamples + addedLen, wxT("Paste branch three"));
|
||||
}
|
||||
|
||||
bool Sequence::SetSilence(sampleCount s0, sampleCount len)
|
||||
@@ -693,11 +700,9 @@ bool Sequence::InsertSilence(sampleCount s0, sampleCount len)
|
||||
|
||||
sTrack.mNumSamples = pos;
|
||||
|
||||
bool bResult = Paste(s0, &sTrack);
|
||||
wxASSERT(bResult);
|
||||
Paste(s0, &sTrack);
|
||||
|
||||
ConsistencyCheck(wxT("InsertSilence"));
|
||||
return bResult;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sequence::AppendAlias(const wxString &fullPath,
|
||||
@@ -737,13 +742,15 @@ bool Sequence::AppendCoded(const wxString &fName, sampleCount start,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Sequence::AppendBlock
|
||||
void Sequence::AppendBlock
|
||||
(DirManager &mDirManager,
|
||||
BlockArray &mBlock, sampleCount &mNumSamples, const SeqBlock &b)
|
||||
{
|
||||
// Quick check to make sure that it doesn't overflow
|
||||
if (Overflows((mNumSamples.as_double()) + ((double)b.f->GetLength())))
|
||||
return false;
|
||||
// THROW_INCONSISTENCY_EXCEPTION
|
||||
return
|
||||
;
|
||||
|
||||
SeqBlock newBlock(
|
||||
mDirManager.CopyBlockFile(b.f), // Bump ref count if not locked, else copy
|
||||
@@ -755,16 +762,11 @@ bool Sequence::AppendBlock
|
||||
return false;
|
||||
}
|
||||
|
||||
//Don't need to Ref because it was done by CopyBlockFile, above...
|
||||
//mDirManager->Ref(newBlock.f);
|
||||
|
||||
mBlock.push_back(newBlock);
|
||||
mNumSamples += newBlock.f->GetLength();
|
||||
|
||||
// Don't do a consistency check here because this
|
||||
// function gets called in an inner loop.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///gets an int with OD flags so that we can determine which ODTasks should be run on this track after save/open, etc.
|
||||
|
||||
@@ -104,7 +104,7 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
|
||||
size_t len, const sampleCount *where) const;
|
||||
|
||||
std::unique_ptr<Sequence> Copy(sampleCount s0, sampleCount s1) const;
|
||||
bool Paste(sampleCount s0, const Sequence *src);
|
||||
void Paste(sampleCount s0, const Sequence *src);
|
||||
|
||||
size_t GetIdealAppendLen() const;
|
||||
bool Append(samplePtr buffer, sampleFormat format, size_t len,
|
||||
@@ -245,7 +245,7 @@ class PROFILE_DLL_API Sequence final : public XMLTagHandler{
|
||||
|
||||
int FindBlock(sampleCount pos) const;
|
||||
|
||||
static bool AppendBlock
|
||||
static void AppendBlock
|
||||
(DirManager &dirManager,
|
||||
BlockArray &blocks, sampleCount &numSamples, const SeqBlock &b);
|
||||
|
||||
|
||||
@@ -1611,18 +1611,16 @@ void WaveClip::Paste(double t0, const WaveClip* other)
|
||||
TimeToSamplesClip(t0, &s0);
|
||||
|
||||
// Assume STRONG-GUARANTEE from Sequence::Paste
|
||||
if (mSequence->Paste(s0, pastedClip->mSequence.get()))
|
||||
{
|
||||
// Assume NOFAIL-GUARANTEE in the remaining
|
||||
MarkChanged();
|
||||
mEnvelope->Paste(s0.as_double()/mRate + mOffset, pastedClip->mEnvelope.get());
|
||||
mEnvelope->RemoveUnneededPoints();
|
||||
OffsetCutLines(t0, pastedClip->GetEndTime() - pastedClip->GetStartTime());
|
||||
mSequence->Paste(s0, pastedClip->mSequence.get());
|
||||
|
||||
for (auto &holder : newCutlines)
|
||||
mCutLines.push_back(std::move(holder));
|
||||
// Assume NOFAIL-GUARANTEE in the remaining
|
||||
MarkChanged();
|
||||
mEnvelope->Paste(s0.as_double()/mRate + mOffset, pastedClip->mEnvelope.get());
|
||||
mEnvelope->RemoveUnneededPoints();
|
||||
OffsetCutLines(t0, pastedClip->GetEndTime() - pastedClip->GetStartTime());
|
||||
|
||||
}
|
||||
for (auto &holder : newCutlines)
|
||||
mCutLines.push_back(std::move(holder));
|
||||
}
|
||||
|
||||
void WaveClip::InsertSilence(double t, double len)
|
||||
|
||||
Reference in New Issue
Block a user