Towards arranging sections

This allows to move or copy whole sections of the timline (everything
you hear) to a differnt position on the timeline.

NB. Markers and tempo-map are not yet moved, and interpolated MIDI
events are lost.
This commit is contained in:
Robin Gareus 2023-01-23 03:57:53 +01:00
parent c24c210cce
commit 38c613cd9a
6 changed files with 100 additions and 0 deletions

View File

@ -167,6 +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);
/* controls use set_solo() to modify this route's solo state */

View File

@ -1169,6 +1169,8 @@ 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);
/* buffers for gain and pan */
gain_t* gain_automation_buffer () const;

View File

@ -2902,6 +2902,7 @@ LuaBindings::common (lua_State* L)
.addFunction ("session_range_is_free", &Session::session_range_is_free)
.addFunction ("set_session_range_is_free", &Session::set_session_range_is_free)
.addFunction ("remove_route_group", (void (Session::*)(RouteGroup*))&Session::remove_route_group)
.addFunction ("cut_copy_section", &Session::cut_copy_section)
.addFunction ("vca_manager", &Session::vca_manager_ptr)
.addExtCFunction ("timecode_to_sample_lua", ARDOUR::LuaAPI::timecode_to_sample_lua)
.addExtCFunction ("sample_to_timecode_lua", ARDOUR::LuaAPI::sample_to_timecode_lua)

View File

@ -4540,6 +4540,36 @@ 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)
{
ControllableSet acs;
automatables (acs);
for (auto& ec : acs) {
boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (ec);
if (!ac) {
continue;
}
boost::shared_ptr<AutomationList> al = ac->alist();
if (!al || al->empty ()) {
continue;
}
XMLNode &before = al->get_state ();
boost::shared_ptr<Evoral::ControlList> cl = copy ? al->copy (start, end) : al->cut (start, end);
if (!copy) {
/* 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);
XMLNode &after = al->get_state ();
_session.add_command (new MementoCommand<AutomationList> (*al.get(), &before, &after));
}
}
void
Route::set_plugin_state_dir (boost::weak_ptr<Processor> p, const std::string& d)
{

View File

@ -7186,6 +7186,64 @@ Session::clear_object_selection ()
_object_selection = Temporal::Range (timepos_t::max (Temporal::AudioTime), timepos_t::max (Temporal::AudioTime));
}
void
Session::cut_copy_section (timepos_t const& start, timepos_t const& end, timepos_t const& to, bool const copy)
{
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"));
}
{
/* disable DiskReader::playlist_ranges_moved moving automation */
bool automation_follows = Config->get_automation_follows_regions ();
Config->set_automation_follows_regions (false);
for (auto& pl : _playlists->playlists) {
pl->freeze ();
pl->clear_changes ();
pl->clear_owned_changes ();
boost::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);
}
/* now make space at the insertion-point */
pl->ripple (to, start.distance(end), NULL);
pl->paste (p, to, 1);
vector<Command*> cmds;
pl->rdiff (cmds);
add_commands (cmds);
add_command (new StatefulDiffCommand (pl));
}
for (auto& pl : _playlists->playlists) {
pl->thaw ();
}
Config->set_automation_follows_regions (automation_follows);
}
for (auto& r : *(routes.reader())) {
r->cut_copy_section (start, end, to, copy);
}
// TODO: update ranges and Tempo-Map
if (!abort_empty_reversible_command ()) {
commit_reversible_command ();
}
}
void
Session::auto_connect_route (boost::shared_ptr<Route> route,
bool connect_inputs,

View File

@ -0,0 +1,8 @@
ardour { ["type"] = "Snippet", name = "Move Section" }
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)
end end