Implement cut/paste section markers

This does not include partial ranges (selection only
include either range-start or range-end).

Copy/paste also remains to be done
This commit is contained in:
Robin Gareus 2023-05-02 23:24:39 +02:00
parent 3f15a3a402
commit 2bdf51e02d
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
3 changed files with 92 additions and 2 deletions

View File

@ -258,6 +258,8 @@ 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 ripple (timepos_t const & at, timecnt_t const & distance, bool include_locked, bool notify);
XMLNode& get_state () const;

View File

@ -1680,6 +1680,87 @@ 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)
{
LocationList ll;
{
Glib::Threads::RWLock::WriterLock lm (_lock);
ll = locations;
}
for (auto const& i : ll) {
if (i->is_session_range () || i->is_auto_punch () || i->is_auto_loop ()) {
continue;
}
if (i->locked ()) {
continue;
}
if (!i->is_mark ()) {
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 {
// TODO - How do we handle ranges that intersect start/end ?
continue;
}
}
if (!copy) {
timecnt_t distance = timecnt_t (i->start ().time_domain ());
if (i->start () < start) {
/* Not affected, unless paste-point `to` is earlier,
* in which case we need to make space there
*/
if (i->start () >= to) {
distance = start.distance(end);
}
}
else if (i->start () >= end) {
/* data before this mark is "cut", so move it towards 0, unless
* the whole cut/paste operation is earlier, in which case this mark
* is not affected.
*/
if (i->start () <= to + start.distance(end)) {
distance = end.distance(start);
}
}
else {
/* process cut/paste */
distance = start.distance (to);
}
if (i->is_mark ()) {
i->set_start (i->start () + distance);
continue;
}
/* process range-end, by default use same distance as i->start
* to retain the range length, but additionally consider the following.
*/
timecnt_t dist_end = distance;
if (i->end () >= end) {
if (i->end () > to + start.distance(end)) {
/* paste inside range, extend range: keep range end */
dist_end = timecnt_t (i->end ().time_domain ());
}
}
i->set (i->start () + distance, i->end () + dist_end);
} else {
// TODO Copy/Paste: add new markers, disambiugate names
}
}
}
bool
Locations::clear_cue_markers (samplepos_t start, samplepos_t end)
{

View File

@ -7206,7 +7206,6 @@ Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos
pl->clear_owned_changes ();
std::shared_ptr<Playlist> p = copy ? pl->copy (ltr) : pl->cut (ltr);
// TODO copy interpolated MIDI events
if (!copy) {
pl->ripple (start, end.distance(start), NULL);
}
@ -7230,11 +7229,19 @@ Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos
Config->set_automation_follows_regions (automation_follows);
}
/* automation */
for (auto& r : *(routes.reader())) {
r->cut_copy_section (start, end, to, copy);
}
// TODO: update ranges and Tempo-Map
{
XMLNode &before = _locations->get_state();
_locations->cut_copy_section (start, end, to, copy);
XMLNode &after = _locations->get_state();
add_command (new MementoCommand<Locations> (*_locations, &before, &after));
}
// TODO: update Tempo-Map
if (!abort_empty_reversible_command ()) {
commit_reversible_command ();