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:
parent
c24c210cce
commit
38c613cd9a
|
@ -167,6 +167,7 @@ public:
|
||||||
/* end of vfunc-based API */
|
/* end of vfunc-based API */
|
||||||
|
|
||||||
void shift (timepos_t const &, timecnt_t const &);
|
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 */
|
/* controls use set_solo() to modify this route's solo state */
|
||||||
|
|
||||||
|
|
|
@ -1169,6 +1169,8 @@ public:
|
||||||
void clear_range_selection ();
|
void clear_range_selection ();
|
||||||
void clear_object_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 */
|
/* buffers for gain and pan */
|
||||||
|
|
||||||
gain_t* gain_automation_buffer () const;
|
gain_t* gain_automation_buffer () const;
|
||||||
|
|
|
@ -2902,6 +2902,7 @@ LuaBindings::common (lua_State* L)
|
||||||
.addFunction ("session_range_is_free", &Session::session_range_is_free)
|
.addFunction ("session_range_is_free", &Session::session_range_is_free)
|
||||||
.addFunction ("set_session_range_is_free", &Session::set_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 ("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)
|
.addFunction ("vca_manager", &Session::vca_manager_ptr)
|
||||||
.addExtCFunction ("timecode_to_sample_lua", ARDOUR::LuaAPI::timecode_to_sample_lua)
|
.addExtCFunction ("timecode_to_sample_lua", ARDOUR::LuaAPI::timecode_to_sample_lua)
|
||||||
.addExtCFunction ("sample_to_timecode_lua", ARDOUR::LuaAPI::sample_to_timecode_lua)
|
.addExtCFunction ("sample_to_timecode_lua", ARDOUR::LuaAPI::sample_to_timecode_lua)
|
||||||
|
|
|
@ -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
|
void
|
||||||
Route::set_plugin_state_dir (boost::weak_ptr<Processor> p, const std::string& d)
|
Route::set_plugin_state_dir (boost::weak_ptr<Processor> p, const std::string& d)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7186,6 +7186,64 @@ Session::clear_object_selection ()
|
||||||
_object_selection = Temporal::Range (timepos_t::max (Temporal::AudioTime), timepos_t::max (Temporal::AudioTime));
|
_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
|
void
|
||||||
Session::auto_connect_route (boost::shared_ptr<Route> route,
|
Session::auto_connect_route (boost::shared_ptr<Route> route,
|
||||||
bool connect_inputs,
|
bool connect_inputs,
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue