Implement Section Delete/Insert
This commit is contained in:
parent
961c6ae8d7
commit
4529a17617
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -249,6 +249,13 @@ enum RecordMode {
|
||||
RecSoundOnSound
|
||||
};
|
||||
|
||||
enum SectionOperation {
|
||||
CopyPasteSection,
|
||||
CutPasteSection,
|
||||
InsertSection,
|
||||
DeleteSection,
|
||||
};
|
||||
|
||||
enum NoteMode {
|
||||
Sustained,
|
||||
Percussive
|
||||
|
@ -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 */
|
||||
|
@ -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))
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user