13
0

Implement Section Delete/Insert

This commit is contained in:
Robin Gareus 2023-06-06 02:11:09 +02:00
parent 961c6ae8d7
commit 4529a17617
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
9 changed files with 106 additions and 36 deletions

View File

@ -121,6 +121,9 @@ public:
bool is_xrun() const { return _flags & IsXrun; }
bool matches (Flags f) const { return _flags & f; }
/* any range with start < end -- not a marker */
bool is_range() const { return _flags & (IsSessionRange | IsRangeMarker | IsAutoLoop | IsAutoPunch | IsCDMarker); }
Flags flags () const { return _flags; }
std::shared_ptr<SceneChange> scene_change() const { return _scene_change; }
@ -258,7 +261,7 @@ public:
bool clear_cue_markers (samplepos_t start, samplepos_t end);
void cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy);
void cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op);
void ripple (timepos_t const & at, timecnt_t const & distance, bool include_locked, bool notify);

View File

@ -167,7 +167,7 @@ public:
/* end of vfunc-based API */
void shift (timepos_t const &, timecnt_t const &);
void cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy);
void cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op);
/* controls use set_solo() to modify this route's solo state */

View File

@ -1169,7 +1169,7 @@ public:
void clear_range_selection ();
void clear_object_selection ();
void cut_copy_section (Temporal::timepos_t const& start, Temporal::timepos_t const& end, Temporal::timepos_t const& to, bool const copy = false);
void cut_copy_section (Temporal::timepos_t const& start, Temporal::timepos_t const& end, Temporal::timepos_t const& to, SectionOperation const op);
/* buffers for gain and pan */

View File

@ -249,6 +249,13 @@ enum RecordMode {
RecSoundOnSound
};
enum SectionOperation {
CopyPasteSection,
CutPasteSection,
InsertSection,
DeleteSection,
};
enum NoteMode {
Sustained,
Percussive

View File

@ -1681,7 +1681,7 @@ Locations::ripple (timepos_t const & at, timecnt_t const & distance, bool includ
}
void
Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy)
Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op)
{
LocationList ll;
LocationList pastebuf;
@ -1699,20 +1699,38 @@ Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timep
continue;
}
if (!i->is_mark ()) {
if (i->is_range ()) {
if (i->start () >= start && i->end () <= end) {
/* range is inside the selction, process it */
} else if (i->start () < start && i->end () < start) {
/* range is entirely outside the selection, possible ripple it */
} else if (i->start () >= end && i->end () >= end) {
/* range is entirely outside the selection, possible ripple it */
} else if (i->start () < start && i->end () >= end) {
/* selection is inside the range, possible shorten or extend it */
if (op != DeleteSection && op != InsertSection) {
continue;
}
} else {
// TODO - How do we handle ranges that intersect start/end ?
continue;
}
}
if (!copy) {
if (op == DeleteSection) {
timecnt_t distance = end.distance(start);
if (i->start () >= start && i->start () < end) {
_session.locations()->remove (i);
} else if (i->start () >= end) {
if (i->is_range ()) {
i->set (i->start () + distance, i->end () + distance);
} else {
i->set_start (i->start () + distance);
}
} else if (i->end () >= start) {
i->set (i->start (), i->end () + distance);
}
} else if (op == CutPasteSection) {
timecnt_t distance = timecnt_t (i->start ().time_domain ());
if (i->start () < start) {
@ -1738,7 +1756,7 @@ Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timep
}
if (i->is_mark ()) {
if (!i->is_range ()) {
i->set_start (i->start () + distance);
continue;
}
@ -1756,7 +1774,7 @@ Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timep
i->set (i->start () + distance, i->end () + dist_end);
} else {
} else if (op == CopyPasteSection) {
if (i->start() >= start && i->start() < end) {
Location* copy = new Location (*i);
pastebuf.push_back (copy);
@ -1764,27 +1782,30 @@ Locations::cut_copy_section (timepos_t const& start, timepos_t const& end, timep
}
}
if (copy) {
if (op == CopyPasteSection || op == InsertSection) {
/* ripple */
timecnt_t distance = start.distance(end);
for (auto const& i : ll) {
if (i->start() >= to) {
if (i->is_mark ()) {
i->set_start (i->start () + distance);
} else {
if (i->is_range ()) {
i->set (i->start () + distance, i->end () + distance);
} else {
i->set_start (i->start () + distance);
}
} else if (!i->is_mark () && i->end() >= to) {
} else if (i->is_range () && i->end() >= to) {
i->set_end (i->end () + distance);
}
}
}
if (op == CopyPasteSection) {
/* paste */
timecnt_t distance = start.distance(end);
distance = start.distance (to);
for (auto const& i : pastebuf) {
if (i->is_mark ()) {
i->set_start (i->start () + distance);
} else {
if (i->is_range ()) {
i->set (i->start () + distance, i->end () + distance);
} else {
i->set_start (i->start () + distance);
}
locations.push_back (i);
added (i); /* EMIT SIGNAL */

View File

@ -2343,6 +2343,13 @@ LuaBindings::common (lua_State* L)
.addConst ("SrcBest", ARDOUR::SrcQuality(SrcBest))
.endNamespace ()
.beginNamespace ("SectionOperation")
.addConst ("CopyPaste", ARDOUR::SectionOperation(CopyPasteSection))
.addConst ("CutPaste", ARDOUR::SectionOperation(CutPasteSection))
.addConst ("Insert", ARDOUR::SectionOperation(InsertSection))
.addConst ("Delete", ARDOUR::SectionOperation(DeleteSection))
.endNamespace ()
.beginNamespace ("MeterType")
.addConst ("MeterMaxSignal", ARDOUR::MeterType(MeterMaxSignal))
.addConst ("MeterMaxPeak", ARDOUR::MeterType(MeterMaxPeak))

View File

@ -4556,7 +4556,7 @@ Route::shift (timepos_t const & pos, timecnt_t const & distance)
}
void
Route::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy)
Route::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op)
{
ControllableSet acs;
automatables (acs);
@ -4571,14 +4571,27 @@ Route::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t
}
XMLNode &before = al->get_state ();
std::shared_ptr<Evoral::ControlList> cl = copy ? al->copy (start, end) : al->cut (start, end);
if (!copy) {
std::shared_ptr<Evoral::ControlList> cl;
if (op == CopyPasteSection) {
cl = al->copy (start, end);
} else if (op == CutPasteSection) {
cl = al->cut (start, end);
} else if (op == DeleteSection) {
al->clear (start, end);
}
if (op == CutPasteSection || op == DeleteSection) {
/* remove time (negative distance), ripple */
al->shift (start, end.distance (start));
}
/* make space at the inserion point */
al->shift (to, start.distance (end));
al->paste (*cl, to);
if (op != DeleteSection) {
/* make space at the inserion point */
al->shift (to, start.distance (end));
}
if (op == CopyPasteSection || op == CutPasteSection) {
al->paste (*cl, to);
}
XMLNode &after = al->get_state ();
_session.add_command (new MementoCommand<AutomationList> (*al.get(), &before, &after));

View File

@ -7225,16 +7225,25 @@ Session::clear_object_selection ()
}
void
Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy)
Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, SectionOperation const op)
{
std::list<TimelineRange> ltr;
TimelineRange tlr (start, end, 0);
ltr.push_back (tlr);
if (copy) {
begin_reversible_command (_("Copy Section"));
} else {
begin_reversible_command (_("Move Section"));
switch (op) {
case CopyPasteSection:
begin_reversible_command (_("Copy Section"));
break;
case CutPasteSection:
begin_reversible_command (_("Move Section"));
break;
case InsertSection:
begin_reversible_command (_("Insert Section"));
break;
case DeleteSection:
begin_reversible_command (_("Delete Section"));
break;
}
{
@ -7247,16 +7256,26 @@ Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos
pl->clear_changes ();
pl->clear_owned_changes ();
std::shared_ptr<Playlist> p = copy ? pl->copy (ltr) : pl->cut (ltr);
if (!copy) {
std::shared_ptr<Playlist> p;
if (op == CopyPasteSection) {
p = pl->copy (ltr);
} else if (op == CutPasteSection || op == DeleteSection) {
p = pl->cut (ltr);
}
if (op == CutPasteSection || op == DeleteSection) {
pl->ripple (start, end.distance(start), NULL);
}
/* now make space at the insertion-point */
pl->split (to);
pl->ripple (to, start.distance(end), NULL);
if (op != DeleteSection) {
/* now make space at the insertion-point */
pl->split (to);
pl->ripple (to, start.distance(end), NULL);
}
pl->paste (p, to, 1);
if (op == CopyPasteSection || op == CutPasteSection) {
pl->paste (p, to, 1);
}
vector<Command*> cmds;
pl->rdiff (cmds);
@ -7273,12 +7292,12 @@ Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos
/* automation */
for (auto& r : *(routes.reader())) {
r->cut_copy_section (start, end, to, copy);
r->cut_copy_section (start, end, to, op);
}
{
XMLNode &before = _locations->get_state();
_locations->cut_copy_section (start, end, to, copy);
_locations->cut_copy_section (start, end, to, op);
XMLNode &after = _locations->get_state();
add_command (new MementoCommand<Locations> (*_locations, &before, &after));
}

View File

@ -4,5 +4,5 @@ function factory (params) return function ()
local start = Temporal.timepos_t(96000)
local _end = Temporal.timepos_t(144000)
local to = Temporal.timepos_t(480000)
Session:cut_copy_section (start, _end, to , true)
Session:cut_copy_section (start, _end, to , ARDOUR.SectionOperation.CopyPaste)
end end