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:
parent
8e2e4a53b8
commit
608dcc9b3f
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user