1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-06 23:02:42 +02:00

Reimplement prohibitions on moving clips by throwing exceptions...

... Also comment some strong and weak guarantees
This commit is contained in:
Paul Licameli 2017-03-24 15:01:19 -04:00
parent 8e2e4a53b8
commit 608dcc9b3f
3 changed files with 96 additions and 78 deletions

View File

@ -1539,6 +1539,7 @@ void WaveClip::WriteXML(XMLWriter &xmlFile) const
} }
bool WaveClip::Paste(double t0, const WaveClip* other) bool WaveClip::Paste(double t0, const WaveClip* other)
// STRONG-GUARANTEE
{ {
const bool clipNeedsResampling = other->mRate != mRate; const bool clipNeedsResampling = other->mRate != mRate;
const bool clipNeedsNewFormat = const bool clipNeedsNewFormat =
@ -1558,34 +1559,42 @@ bool WaveClip::Paste(double t0, const WaveClip* other)
// Force sample formats to match. // Force sample formats to match.
newClip->ConvertToSampleFormat(mSequence->GetSampleFormat()); newClip->ConvertToSampleFormat(mSequence->GetSampleFormat());
pastedClip = newClip.get(); pastedClip = newClip.get();
} else }
else
{ {
// No resampling or format change needed, just use original clip without making a copy // No resampling or format change needed, just use original clip without making a copy
pastedClip = other; pastedClip = other;
} }
// Paste cut lines contained in pasted clip
WaveClipHolders newCutlines;
for (const auto &cutline: pastedClip->mCutLines)
{
newCutlines.push_back(
make_movable<WaveClip>
( *cutline, mSequence->GetDirManager(),
// Recursively copy cutlines of cutlines. They don't need
// their offsets adjusted.
true));
newCutlines.back()->Offset(t0 - mOffset);
}
sampleCount s0; sampleCount s0;
TimeToSamplesClip(t0, &s0); TimeToSamplesClip(t0, &s0);
bool result = false; bool result = false;
// Assume STRONG-GUARANTEE from Sequence::Paste
if (mSequence->Paste(s0, pastedClip->mSequence.get())) if (mSequence->Paste(s0, pastedClip->mSequence.get()))
{ {
// Assume NOFAIL-GUARANTEE in the remaining
MarkChanged(); MarkChanged();
mEnvelope->Paste(s0.as_double()/mRate + mOffset, pastedClip->mEnvelope.get()); mEnvelope->Paste(s0.as_double()/mRate + mOffset, pastedClip->mEnvelope.get());
mEnvelope->RemoveUnneededPoints(); mEnvelope->RemoveUnneededPoints();
OffsetCutLines(t0, pastedClip->GetEndTime() - pastedClip->GetStartTime()); OffsetCutLines(t0, pastedClip->GetEndTime() - pastedClip->GetStartTime());
// Paste cut lines contained in pasted clip for (auto &holder : newCutlines)
for (const auto &cutline: pastedClip->mCutLines) mCutLines.push_back(std::move(holder));
{
mCutLines.push_back(
make_movable<WaveClip>
( *cutline, mSequence->GetDirManager(),
// Recursively copy cutlines of cutlines. They don't need
// their offsets adjusted.
true));
mCutLines.back()->Offset(t0 - mOffset);
}
result = true; result = true;
} }
@ -1745,28 +1754,33 @@ bool WaveClip::FindCutLine(double cutLinePosition,
} }
bool WaveClip::ExpandCutLine(double cutLinePosition) bool WaveClip::ExpandCutLine(double cutLinePosition)
// STRONG-GUARANTEE
{ {
for (auto it = mCutLines.begin(); it != mCutLines.end(); ++it) auto end = mCutLines.end();
{ auto it = std::find_if( mCutLines.begin(), end,
WaveClip *const cutline = it->get(); [&](const WaveClipHolder &cutline) {
if (fabs(mOffset + cutline->GetOffset() - cutLinePosition) < 0.0001) return fabs(mOffset + cutline->GetOffset() - cutLinePosition) < 0.0001;
{ } );
if (!Paste(mOffset+cutline->GetOffset(), cutline))
return false; if ( it != end ) {
// Now erase the cutline, auto cutline = it->get();
// but be careful to find it again, because Paste above may // assume STRONG-GUARANTEE from Paste
// have modified the array of cutlines (if our cutline contained if (!Paste(mOffset+cutline->GetOffset(), cutline))
// another cutline!), invalidating the iterator we had. return false;
auto begin = mCutLines.begin(), end = mCutLines.end(); // Now erase the cutline,
it = std::find_if(begin, end, // but be careful to find it again, because Paste above may
[=](decltype(*begin) &p){ return p.get() == cutline; }); // have modified the array of cutlines (if our cutline contained
if (it != end) // another cutline!), invalidating the iterator we had.
mCutLines.erase(it); // deletes cutline! end = mCutLines.end();
else { it = std::find_if(mCutLines.begin(), end,
wxASSERT(false); [=](const WaveClipHolder &p) { return p.get() == cutline; });
} if (it != end)
return true; mCutLines.erase(it); // deletes cutline!
else {
// THROW_INCONSISTENCY_EXCEPTION;
wxASSERT(false);
} }
return true;
} }
return false; return false;
@ -1788,6 +1802,7 @@ bool WaveClip::RemoveCutLine(double cutLinePosition)
} }
void WaveClip::OffsetCutLines(double t0, double len) void WaveClip::OffsetCutLines(double t0, double len)
// NOFAIL-GUARANTEE
{ {
for (const auto &cutLine : mCutLines) for (const auto &cutLine : mCutLines)
{ {

View File

@ -141,7 +141,8 @@ public:
class WaveClip; class WaveClip;
// Array of pointers that assume ownership // Array of pointers that assume ownership
using WaveClipHolders = std::vector < movable_ptr< WaveClip > >; using WaveClipHolder = movable_ptr< WaveClip >;
using WaveClipHolders = std::vector < WaveClipHolder >;
using WaveClipConstHolders = std::vector < movable_ptr< const WaveClip > >; using WaveClipConstHolders = std::vector < movable_ptr< const WaveClip > >;
// Temporary arrays of mere pointers // Temporary arrays of mere pointers

View File

@ -1202,6 +1202,7 @@ bool WaveTrack::SyncLockAdjust(double oldT1, double newT1)
} }
bool WaveTrack::Paste(double t0, const Track *src) bool WaveTrack::Paste(double t0, const Track *src)
// WEAK-GUARANTEE
{ {
bool editClipCanMove = true; bool editClipCanMove = true;
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove); gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove);
@ -1287,7 +1288,8 @@ bool WaveTrack::Paste(double t0, const Track *src)
insideClip = clip.get(); insideClip = clip.get();
break; break;
} }
} else }
else
{ {
// If clips are immovable we also allow prepending to clips // If clips are immovable we also allow prepending to clips
if (clip->WithinClip(t0) || if (clip->WithinClip(t0) ||
@ -1312,12 +1314,11 @@ bool WaveTrack::Paste(double t0, const Track *src)
if (clip->GetStartTime() > insideClip->GetStartTime() && if (clip->GetStartTime() > insideClip->GetStartTime() &&
insideClip->GetEndTime() + insertDuration > insideClip->GetEndTime() + insertDuration >
clip->GetStartTime()) clip->GetStartTime())
{ // STRONG-GUARANTEE in case of this path
wxMessageBox( // not that it matters.
_("There is not enough room available to paste the selection"), throw SimpleMessageBoxException{
_("Error"), wxICON_STOP); _("There is not enough room available to paste the selection")
return false; };
}
} }
} }
@ -1331,12 +1332,11 @@ bool WaveTrack::Paste(double t0, const Track *src)
//printf("paste: multi clip mode!\n"); //printf("paste: multi clip mode!\n");
if (!editClipCanMove && !IsEmpty(t0, t0+insertDuration-1.0/mRate)) if (!editClipCanMove && !IsEmpty(t0, t0+insertDuration-1.0/mRate))
{ // STRONG-GUARANTEE in case of this path
wxMessageBox( // not that it matters.
_("There is not enough room available to paste the selection"), throw SimpleMessageBoxException{
_("Error"), wxICON_STOP); _("There is not enough room available to paste the selection")
return false; };
}
for (const auto &clip : other->mClips) for (const auto &clip : other->mClips)
{ {
@ -2447,50 +2447,52 @@ void WaveTrack::UpdateLocationsCache() const
// Expand cut line (that is, re-insert audio, then DELETE audio saved in cut line) // Expand cut line (that is, re-insert audio, then DELETE audio saved in cut line)
bool WaveTrack::ExpandCutLine(double cutLinePosition, double* cutlineStart, bool WaveTrack::ExpandCutLine(double cutLinePosition, double* cutlineStart,
double* cutlineEnd) double* cutlineEnd)
// STRONG-GUARANTEE
{ {
bool editClipCanMove = true; bool editClipCanMove = true;
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove); gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove);
// Find clip which contains this cut line // Find clip which contains this cut line
for (const auto &clip : mClips) double start = 0, end = 0;
auto pEnd = mClips.end();
auto pClip = std::find_if( mClips.begin(), pEnd,
[&](const WaveClipHolder &clip) {
return clip->FindCutLine(cutLinePosition, &start, &end); } );
if (pClip != pEnd)
{ {
double start = 0, end = 0; auto &clip = *pClip;
if (!editClipCanMove)
if (clip->FindCutLine(cutLinePosition, &start, &end))
{ {
if (!editClipCanMove) // We are not allowed to move the other clips, so see if there
// is enough room to expand the cut line
for (const auto &clip2: mClips)
{ {
// We are not allowed to move the other clips, so see if there if (clip2->GetStartTime() > clip->GetStartTime() &&
// is enough room to expand the cut line clip->GetEndTime() + end - start > clip2->GetStartTime())
for (const auto &clip2: mClips) // STRONG-GUARANTEE in case of this path
{ throw SimpleMessageBoxException{
if (clip2->GetStartTime() > clip->GetStartTime() && _("There is not enough room available to expand the cut line")
clip->GetEndTime() + end - start > clip2->GetStartTime()) };
{ }
wxMessageBox( }
_("There is not enough room available to expand the cut line"),
_("Error"), wxICON_STOP);
return false;
}
}
}
if (!clip->ExpandCutLine(cutLinePosition)) if (!clip->ExpandCutLine(cutLinePosition))
return false; return false;
if (cutlineStart) // STRONG-GUARANTEE provided that the following gives NOFAIL-GUARANTEE
*cutlineStart = start;
if (cutlineEnd)
*cutlineEnd = end;
// Move clips which are to the right of the cut line if (cutlineStart)
if (editClipCanMove) *cutlineStart = start;
if (cutlineEnd)
*cutlineEnd = end;
// Move clips which are to the right of the cut line
if (editClipCanMove)
{
for (const auto &clip2 : mClips)
{ {
for (const auto &clip2 : mClips) if (clip2->GetStartTime() > clip->GetStartTime())
{ clip2->Offset(end - start);
if (clip2->GetStartTime() > clip->GetStartTime())
clip2->Offset(end - start);
}
} }
return true; return true;