mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
Merge branch 'ripple-mode-cc' into cairocanvas
Fix up merge conflicts in gtk2_ardour/editor_mouse.cc gtk2_ardour/editor_ops.cc Also fix up compile errors.
This commit is contained in:
commit
e5e12acc56
14 changed files with 473 additions and 35 deletions
|
|
@ -2825,12 +2825,6 @@ Editor::setup_toolbar ()
|
||||||
|
|
||||||
mouse_mode_box->pack_start (*mouse_mode_align, false, false);
|
mouse_mode_box->pack_start (*mouse_mode_align, false, false);
|
||||||
|
|
||||||
edit_mode_strings.push_back (edit_mode_to_string (Slide));
|
|
||||||
if (!Profile->get_sae()) {
|
|
||||||
edit_mode_strings.push_back (edit_mode_to_string (Splice));
|
|
||||||
}
|
|
||||||
edit_mode_strings.push_back (edit_mode_to_string (Lock));
|
|
||||||
|
|
||||||
edit_mode_selector.set_name ("mouse mode button");
|
edit_mode_selector.set_name ("mouse mode button");
|
||||||
edit_mode_selector.set_size_request (65, -1);
|
edit_mode_selector.set_size_request (65, -1);
|
||||||
edit_mode_selector.add_elements (ArdourButton::Inset);
|
edit_mode_selector.add_elements (ArdourButton::Inset);
|
||||||
|
|
@ -3047,6 +3041,7 @@ Editor::build_edit_mode_menu ()
|
||||||
|
|
||||||
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Slide), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
|
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Slide), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
|
||||||
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Splice), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
|
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Splice), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
|
||||||
|
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Ripple), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
|
||||||
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Lock), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
|
edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Lock), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3358,10 +3353,11 @@ Editor::cycle_edit_mode ()
|
||||||
if (Profile->get_sae()) {
|
if (Profile->get_sae()) {
|
||||||
Config->set_edit_mode (Lock);
|
Config->set_edit_mode (Lock);
|
||||||
} else {
|
} else {
|
||||||
Config->set_edit_mode (Splice);
|
Config->set_edit_mode (Ripple);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Splice:
|
case Splice:
|
||||||
|
case Ripple:
|
||||||
Config->set_edit_mode (Lock);
|
Config->set_edit_mode (Lock);
|
||||||
break;
|
break;
|
||||||
case Lock:
|
case Lock:
|
||||||
|
|
|
||||||
|
|
@ -1626,7 +1626,6 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||||
void edit_mode_selection_done ( ARDOUR::EditMode m );
|
void edit_mode_selection_done ( ARDOUR::EditMode m );
|
||||||
void build_edit_mode_menu ();
|
void build_edit_mode_menu ();
|
||||||
Gtk::VBox edit_mode_box;
|
Gtk::VBox edit_mode_box;
|
||||||
std::vector<std::string> edit_mode_strings;
|
|
||||||
|
|
||||||
void set_edit_mode (ARDOUR::EditMode);
|
void set_edit_mode (ARDOUR::EditMode);
|
||||||
void cycle_edit_mode ();
|
void cycle_edit_mode ();
|
||||||
|
|
@ -2102,6 +2101,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||||
friend class RegionDrag;
|
friend class RegionDrag;
|
||||||
friend class RegionMoveDrag;
|
friend class RegionMoveDrag;
|
||||||
friend class RegionSpliceDrag;
|
friend class RegionSpliceDrag;
|
||||||
|
friend class RegionRippleDrag;
|
||||||
friend class TrimDrag;
|
friend class TrimDrag;
|
||||||
friend class MeterMarkerDrag;
|
friend class MeterMarkerDrag;
|
||||||
friend class TempoMarkerDrag;
|
friend class TempoMarkerDrag;
|
||||||
|
|
|
||||||
|
|
@ -482,6 +482,7 @@ Editor::register_actions ()
|
||||||
ActionManager::register_action (editor_actions, "cycle-edit-point-with-marker", _("Change Edit Point Including Marker"), sigc::bind (sigc::mem_fun (*this, &Editor::cycle_edit_point), true));
|
ActionManager::register_action (editor_actions, "cycle-edit-point-with-marker", _("Change Edit Point Including Marker"), sigc::bind (sigc::mem_fun (*this, &Editor::cycle_edit_point), true));
|
||||||
if (!Profile->get_sae()) {
|
if (!Profile->get_sae()) {
|
||||||
ActionManager::register_action (editor_actions, "set-edit-splice", _("Splice"), sigc::bind (sigc::mem_fun (*this, &Editor::set_edit_mode), Splice));
|
ActionManager::register_action (editor_actions, "set-edit-splice", _("Splice"), sigc::bind (sigc::mem_fun (*this, &Editor::set_edit_mode), Splice));
|
||||||
|
ActionManager::register_action (editor_actions, "set-edit-ripple", _("Ripple"), bind (mem_fun (*this, &Editor::set_edit_mode), Ripple));
|
||||||
}
|
}
|
||||||
ActionManager::register_action (editor_actions, "set-edit-slide", _("Slide"), sigc::bind (sigc::mem_fun (*this, &Editor::set_edit_mode), Slide));
|
ActionManager::register_action (editor_actions, "set-edit-slide", _("Slide"), sigc::bind (sigc::mem_fun (*this, &Editor::set_edit_mode), Slide));
|
||||||
ActionManager::register_action (editor_actions, "set-edit-lock", _("Lock"), sigc::bind (sigc::mem_fun (*this, &Editor::set_edit_mode), Lock));
|
ActionManager::register_action (editor_actions, "set-edit-lock", _("Lock"), sigc::bind (sigc::mem_fun (*this, &Editor::set_edit_mode), Lock));
|
||||||
|
|
|
||||||
|
|
@ -893,6 +893,9 @@ Editor::finish_bringing_in_material (boost::shared_ptr<Region> region, uint32_t
|
||||||
boost::shared_ptr<Region> copy (RegionFactory::create (region, region->properties()));
|
boost::shared_ptr<Region> copy (RegionFactory::create (region, region->properties()));
|
||||||
playlist->clear_changes ();
|
playlist->clear_changes ();
|
||||||
playlist->add_region (copy, pos);
|
playlist->add_region (copy, pos);
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
playlist->ripple (pos, copy->length(), copy);
|
||||||
|
|
||||||
_session->add_command (new StatefulDiffCommand (playlist));
|
_session->add_command (new StatefulDiffCommand (playlist));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -595,7 +595,6 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_last_frame_position = *pending_region_position;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dx;
|
return dx;
|
||||||
|
|
@ -668,6 +667,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
|
||||||
/* Work out the change in x */
|
/* Work out the change in x */
|
||||||
framepos_t pending_region_position;
|
framepos_t pending_region_position;
|
||||||
double const x_delta = compute_x_delta (event, &pending_region_position);
|
double const x_delta = compute_x_delta (event, &pending_region_position);
|
||||||
|
_last_frame_position = pending_region_position;
|
||||||
|
|
||||||
/* Verify change in y */
|
/* Verify change in y */
|
||||||
if (!y_movement_allowed (delta_time_axis_view, delta_layer)) {
|
if (!y_movement_allowed (delta_time_axis_view, delta_layer)) {
|
||||||
|
|
@ -1281,7 +1281,7 @@ RegionMoveDrag::remove_region_from_playlist (
|
||||||
playlist->clear_changes ();
|
playlist->clear_changes ();
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist->remove_region (region);
|
playlist->remove_region (region); // should be no need to ripple; we better already have rippled the playlist in RegionRippleDrag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1451,6 +1451,12 @@ RegionInsertDrag::finished (GdkEvent *, bool)
|
||||||
_editor->begin_reversible_command (Operations::insert_region);
|
_editor->begin_reversible_command (Operations::insert_region);
|
||||||
playlist->clear_changes ();
|
playlist->clear_changes ();
|
||||||
playlist->add_region (_primary->region (), _last_frame_position);
|
playlist->add_region (_primary->region (), _last_frame_position);
|
||||||
|
|
||||||
|
// Mixbus doesn't seem to ripple when inserting regions from the list: should we? yes, probably
|
||||||
|
if (Config->get_edit_mode() == Ripple) {
|
||||||
|
playlist->ripple (_last_frame_position, _primary->region()->length(), _primary->region());
|
||||||
|
}
|
||||||
|
|
||||||
_editor->session()->add_command (new StatefulDiffCommand (playlist));
|
_editor->session()->add_command (new StatefulDiffCommand (playlist));
|
||||||
_editor->commit_reversible_command ();
|
_editor->commit_reversible_command ();
|
||||||
|
|
||||||
|
|
@ -1493,7 +1499,7 @@ RegionSpliceDrag::motion (GdkEvent* event, bool)
|
||||||
|
|
||||||
if (!tv || !tv->is_track()) {
|
if (!tv || !tv->is_track()) {
|
||||||
/* To make sure we hide the verbose canvas cursor when the mouse is
|
/* To make sure we hide the verbose canvas cursor when the mouse is
|
||||||
not held over and audiotrack.
|
not held over an audio track.
|
||||||
*/
|
*/
|
||||||
_editor->verbose_cursor()->hide ();
|
_editor->verbose_cursor()->hide ();
|
||||||
return;
|
return;
|
||||||
|
|
@ -1509,10 +1515,8 @@ RegionSpliceDrag::motion (GdkEvent* event, bool)
|
||||||
dir = -1;
|
dir = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionSelection copy (_editor->selection->regions);
|
RegionSelection copy;
|
||||||
|
_editor->selection->regions.by_position(copy);
|
||||||
RegionSelectionByPosition cmp;
|
|
||||||
copy.sort (cmp);
|
|
||||||
|
|
||||||
framepos_t const pf = adjusted_current_frame (event);
|
framepos_t const pf = adjusted_current_frame (event);
|
||||||
|
|
||||||
|
|
@ -1561,6 +1565,289 @@ RegionSpliceDrag::aborted (bool)
|
||||||
/* XXX: TODO */
|
/* XXX: TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* ripple mode...
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
RegionRippleDrag::add_all_after_to_views(TimeAxisView *tav, framepos_t where, const RegionSelection &exclude, bool drag_in_progress)
|
||||||
|
{
|
||||||
|
RegionSelection to_ripple;
|
||||||
|
TrackViewList tracks;
|
||||||
|
tracks.push_back (tav);
|
||||||
|
_editor->get_regions_after (to_ripple, where, tracks);
|
||||||
|
|
||||||
|
for (RegionSelection::iterator i = to_ripple.begin(); i != to_ripple.end(); ++i) {
|
||||||
|
if (!exclude.contains (*i)) {
|
||||||
|
// the selection has already been added to _views
|
||||||
|
|
||||||
|
if (drag_in_progress) {
|
||||||
|
// do the same things that RegionMotionDrag::motion does when first_move
|
||||||
|
// is true for the region views that we're adding to _views this time
|
||||||
|
|
||||||
|
(*i)->drag_start();
|
||||||
|
ArdourCanvas::Item* rvg = (*i)->get_canvas_group();
|
||||||
|
Duple rv_canvas_offset = rvg->item_to_canvas (Duple (0,0));
|
||||||
|
Duple dmg_canvas_offset = _editor->_drag_motion_group->canvas_origin ();
|
||||||
|
rvg->reparent (_editor->_drag_motion_group);
|
||||||
|
|
||||||
|
// XXX without the following, things jump in the y direction during drags
|
||||||
|
// with it, they jump in the x direction
|
||||||
|
// so we need to do the move in the y direction only
|
||||||
|
// rvg->move (rv_canvas_offset - dmg_canvas_offset);
|
||||||
|
std::cerr << "rv_canvas_offset = " << rv_canvas_offset << ", dmg_canvas_offset = " << dmg_canvas_offset << std::endl;
|
||||||
|
Duple fudge = rv_canvas_offset - dmg_canvas_offset;
|
||||||
|
fudge.x = 0;
|
||||||
|
rvg->move (fudge);
|
||||||
|
|
||||||
|
}
|
||||||
|
_views.push_back (DraggingView (*i, this, tav));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RegionRippleDrag::remove_unselected_from_views(framecnt_t amount, bool move_regions)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (std::list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ) {
|
||||||
|
// we added all the regions after the selection
|
||||||
|
|
||||||
|
std::list<DraggingView>::iterator to_erase = i++;
|
||||||
|
if (!_editor->selection->regions.contains (to_erase->view)) {
|
||||||
|
// restore the non-selected regions to their original playlist & positions,
|
||||||
|
// and then ripple them back by the length of the regions that were dragged away
|
||||||
|
// do the same things as RegionMotionDrag::aborted
|
||||||
|
|
||||||
|
RegionView *rv = to_erase->view;
|
||||||
|
TimeAxisView* tv = &(rv->get_time_axis_view ());
|
||||||
|
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
|
||||||
|
assert (rtv);
|
||||||
|
|
||||||
|
std::cerr << "rtv = " << rtv->name() << std::endl;
|
||||||
|
|
||||||
|
// plonk them back onto their own track
|
||||||
|
rv->get_canvas_group()->reparent(rtv->view()->canvas_item());
|
||||||
|
rv->get_canvas_group()->set_y_position (0);
|
||||||
|
rv->drag_end ();
|
||||||
|
|
||||||
|
if (move_regions) {
|
||||||
|
// move the underlying region to match the view
|
||||||
|
rv->region()->set_position (rv->region()->position() + amount);
|
||||||
|
} else {
|
||||||
|
// restore the view to match the underlying region's original position
|
||||||
|
rv->move(-amount, 0); // second parameter is y delta - seems 0 is OK
|
||||||
|
}
|
||||||
|
|
||||||
|
rv->set_height (rtv->view()->child_height ());
|
||||||
|
_views.erase (to_erase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
RegionRippleDrag::y_movement_allowed (int delta_track, double delta_layer) const
|
||||||
|
{
|
||||||
|
if (RegionMotionDrag::y_movement_allowed (delta_track, delta_layer)) {
|
||||||
|
if (delta_track) {
|
||||||
|
return allow_moves_across_tracks;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegionRippleDrag::RegionRippleDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
|
||||||
|
: RegionMoveDrag (e, i, p, v, false, false)
|
||||||
|
{
|
||||||
|
DEBUG_TRACE (DEBUG::Drags, "New RegionRippleDrag\n");
|
||||||
|
// compute length of selection
|
||||||
|
RegionSelection selected_regions = _editor->selection->regions;
|
||||||
|
selection_length = selected_regions.end_frame() - selected_regions.start();
|
||||||
|
|
||||||
|
// we'll only allow dragging to another track in ripple mode if all the regions
|
||||||
|
// being dragged start off on the same track
|
||||||
|
allow_moves_across_tracks = (selected_regions.playlists().size() == 1);
|
||||||
|
prev_tav = NULL;
|
||||||
|
prev_amount = 0;
|
||||||
|
exclude = new RegionList;
|
||||||
|
for (RegionSelection::iterator i =selected_regions.begin(); i != selected_regions.end(); ++i) {
|
||||||
|
exclude->push_back((*i)->region());
|
||||||
|
}
|
||||||
|
|
||||||
|
// also add regions before start of selection to exclude, to be consistent with how Mixbus does ripple
|
||||||
|
RegionSelection copy;
|
||||||
|
selected_regions.by_position(copy); // get selected regions sorted by position into copy
|
||||||
|
|
||||||
|
std::set<boost::shared_ptr<ARDOUR::Playlist> > playlists = copy.playlists();
|
||||||
|
std::set<boost::shared_ptr<ARDOUR::Playlist> >::const_iterator pi;
|
||||||
|
|
||||||
|
for (pi = playlists.begin(); pi != playlists.end(); ++pi) {
|
||||||
|
// find ripple start point on each applicable playlist
|
||||||
|
RegionView *first_selected_on_this_track = NULL;
|
||||||
|
for (RegionSelection::iterator i = copy.begin(); i != copy.end(); ++i) {
|
||||||
|
if ((*i)->region()->playlist() == (*pi)) {
|
||||||
|
// region is on this playlist - it's the first, because they're sorted
|
||||||
|
first_selected_on_this_track = *i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert (first_selected_on_this_track); // we should always find the region in one of the playlists...
|
||||||
|
add_all_after_to_views (
|
||||||
|
&first_selected_on_this_track->get_time_axis_view(),
|
||||||
|
first_selected_on_this_track->region()->position() + first_selected_on_this_track->region()->length(),
|
||||||
|
selected_regions, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allow_moves_across_tracks) {
|
||||||
|
orig_tav = &(*selected_regions.begin())->get_time_axis_view();
|
||||||
|
} else {
|
||||||
|
orig_tav = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RegionRippleDrag::motion (GdkEvent* event, bool first_move)
|
||||||
|
{
|
||||||
|
/* Which trackview is this ? */
|
||||||
|
|
||||||
|
pair<TimeAxisView*, double> const tvp = _editor->trackview_by_y_position (current_pointer_y ());
|
||||||
|
RouteTimeAxisView* tv = dynamic_cast<RouteTimeAxisView*> (tvp.first);
|
||||||
|
|
||||||
|
/* The region motion is only processed if the pointer is over
|
||||||
|
an audio track.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!tv || !tv->is_track()) {
|
||||||
|
/* To make sure we hide the verbose canvas cursor when the mouse is
|
||||||
|
not held over an audiotrack.
|
||||||
|
*/
|
||||||
|
_editor->verbose_cursor()->hide ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
framepos_t where = adjusted_current_frame (event);
|
||||||
|
assert (where >= 0);
|
||||||
|
framepos_t after;
|
||||||
|
double delta = compute_x_delta (event, &after);
|
||||||
|
|
||||||
|
framecnt_t amount = _editor->pixel_to_sample (delta);
|
||||||
|
|
||||||
|
if (allow_moves_across_tracks) {
|
||||||
|
// all the originally selected regions were on the same track
|
||||||
|
|
||||||
|
framecnt_t adjust = 0;
|
||||||
|
if (prev_tav && tv != prev_tav) {
|
||||||
|
// dragged onto a different track
|
||||||
|
// remove the unselected regions from _views, restore them to their original positions
|
||||||
|
// and add the regions after the drop point on the new playlist to _views instead.
|
||||||
|
// undo the effect of rippling the previous playlist, and include the effect of removing
|
||||||
|
// the dragged region(s) from this track
|
||||||
|
std::cerr << "dragged from " << prev_tav->name() << " to " << tv->name() << std::endl;
|
||||||
|
|
||||||
|
remove_unselected_from_views (prev_amount, false);
|
||||||
|
// ripple previous playlist according to the regions that have been removed onto the new playlist
|
||||||
|
prev_tav->playlist()->ripple(prev_position, -selection_length, exclude);
|
||||||
|
prev_amount = 0;
|
||||||
|
|
||||||
|
// move just the selected regions
|
||||||
|
RegionMoveDrag::motion(event, first_move);
|
||||||
|
|
||||||
|
// ensure that the ripple operation on the new playlist inserts selection_length time
|
||||||
|
adjust = selection_length;
|
||||||
|
// ripple the new current playlist
|
||||||
|
tv->playlist()->ripple (where, amount+adjust, exclude);
|
||||||
|
|
||||||
|
// add regions after point where drag entered this track to subsequent ripples
|
||||||
|
add_all_after_to_views (tv, where, _editor->selection->regions, true);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// motion on same track
|
||||||
|
RegionMoveDrag::motion(event, first_move);
|
||||||
|
}
|
||||||
|
prev_tav = tv;
|
||||||
|
|
||||||
|
// remember what we've done to this playlist so we can undo it if the selection is dragged to another track
|
||||||
|
prev_position = where;
|
||||||
|
} else {
|
||||||
|
// selection encompasses multiple tracks - just drag
|
||||||
|
// cross-track drags are forbidden
|
||||||
|
RegionMoveDrag::motion(event, first_move);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_x_constrained) {
|
||||||
|
prev_amount += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
_last_frame_position = after;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RegionRippleDrag::finished (GdkEvent* event, bool movement_occurred)
|
||||||
|
{
|
||||||
|
if (!movement_occurred) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_editor->begin_reversible_command(_("Ripple drag"));
|
||||||
|
|
||||||
|
// remove the regions being rippled from the dragging view, updating them to
|
||||||
|
// their new positions
|
||||||
|
remove_unselected_from_views (prev_amount, true);
|
||||||
|
|
||||||
|
if (allow_moves_across_tracks) {
|
||||||
|
if (orig_tav) {
|
||||||
|
// if regions were dragged across tracks, we've rippled any later
|
||||||
|
// regions on the track the regions were dragged off, so we need
|
||||||
|
// to add the original track to the undo record
|
||||||
|
std::cerr << "adding orig_tav " << orig_tav->name() << " to undo" << std::endl;
|
||||||
|
orig_tav->playlist()->clear_changes();
|
||||||
|
vector<Command*> cmds;
|
||||||
|
orig_tav->playlist()->rdiff (cmds);
|
||||||
|
_editor->session()->add_commands (cmds);
|
||||||
|
}
|
||||||
|
if (prev_tav && prev_tav != orig_tav) {
|
||||||
|
std::cerr << "adding prev_tav " << prev_tav->name() << " to undo" << std::endl;
|
||||||
|
prev_tav->playlist()->clear_changes();
|
||||||
|
vector<Command*> cmds;
|
||||||
|
prev_tav->playlist()->rdiff (cmds);
|
||||||
|
_editor->session()->add_commands (cmds);
|
||||||
|
} else if (prev_tav) {
|
||||||
|
std::cerr << "prev_tav == orig_tav" << std::endl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// selection spanned multiple tracks - all will need adding to undo record
|
||||||
|
|
||||||
|
std::set<boost::shared_ptr<ARDOUR::Playlist> > playlists = _editor->selection->regions.playlists();
|
||||||
|
std::set<boost::shared_ptr<ARDOUR::Playlist> >::const_iterator pi;
|
||||||
|
|
||||||
|
for (pi = playlists.begin(); pi != playlists.end(); ++pi) {
|
||||||
|
|
||||||
|
std::cerr << "adding playlist with selection " << (*pi)->name() << " to undo" << std::endl;
|
||||||
|
(*pi)->clear_changes();
|
||||||
|
vector<Command*> cmds;
|
||||||
|
(*pi)->rdiff (cmds);
|
||||||
|
_editor->session()->add_commands (cmds);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// other modified playlists are added to undo by RegionMoveDrag::finished()
|
||||||
|
RegionMoveDrag::finished (event, movement_occurred);
|
||||||
|
_editor->commit_reversible_command();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RegionRippleDrag::aborted (bool movement_occurred)
|
||||||
|
{
|
||||||
|
RegionMoveDrag::aborted (movement_occurred);
|
||||||
|
_views.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RegionCreateDrag::RegionCreateDrag (Editor* e, ArdourCanvas::Item* i, TimeAxisView* v)
|
RegionCreateDrag::RegionCreateDrag (Editor* e, ArdourCanvas::Item* i, TimeAxisView* v)
|
||||||
: Drag (e, i),
|
: Drag (e, i),
|
||||||
_view (dynamic_cast<MidiTimeAxisView*> (v))
|
_view (dynamic_cast<MidiTimeAxisView*> (v))
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
double compute_x_delta (GdkEvent const *, ARDOUR::framepos_t *);
|
double compute_x_delta (GdkEvent const *, ARDOUR::framepos_t *);
|
||||||
bool y_movement_allowed (int, double) const;
|
virtual bool y_movement_allowed (int, double) const;
|
||||||
|
|
||||||
bool _brushing;
|
bool _brushing;
|
||||||
ARDOUR::framepos_t _last_frame_position; ///< last position of the thing being dragged
|
ARDOUR::framepos_t _last_frame_position; ///< last position of the thing being dragged
|
||||||
|
|
@ -349,9 +349,11 @@ public:
|
||||||
|
|
||||||
void setup_pointer_frame_offset ();
|
void setup_pointer_frame_offset ();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet;
|
typedef std::set<boost::shared_ptr<ARDOUR::Playlist> > PlaylistSet;
|
||||||
|
void add_stateful_diff_commands_for_playlists (PlaylistSet const &);
|
||||||
|
|
||||||
|
private:
|
||||||
void finished_no_copy (
|
void finished_no_copy (
|
||||||
bool const,
|
bool const,
|
||||||
bool const,
|
bool const,
|
||||||
|
|
@ -378,7 +380,6 @@ private:
|
||||||
PlaylistSet& modified_playlists
|
PlaylistSet& modified_playlists
|
||||||
);
|
);
|
||||||
|
|
||||||
void add_stateful_diff_commands_for_playlists (PlaylistSet const &);
|
|
||||||
|
|
||||||
void collect_new_region_view (RegionView *);
|
void collect_new_region_view (RegionView *);
|
||||||
RouteTimeAxisView* create_destination_time_axis (boost::shared_ptr<ARDOUR::Region>, TimeAxisView* original);
|
RouteTimeAxisView* create_destination_time_axis (boost::shared_ptr<ARDOUR::Region>, TimeAxisView* original);
|
||||||
|
|
@ -412,6 +413,33 @@ public:
|
||||||
void aborted (bool);
|
void aborted (bool);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Region drag in ripple mode */
|
||||||
|
|
||||||
|
class RegionRippleDrag : public RegionMoveDrag
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RegionRippleDrag (Editor *, ArdourCanvas::Item *, RegionView *, std::list<RegionView*> const &);
|
||||||
|
~RegionRippleDrag () { delete exclude; }
|
||||||
|
|
||||||
|
void motion (GdkEvent *, bool);
|
||||||
|
void finished (GdkEvent *, bool);
|
||||||
|
void aborted (bool);
|
||||||
|
protected:
|
||||||
|
bool y_movement_allowed (int delta_track, double delta_layer) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TimeAxisView *prev_tav; // where regions were most recently dragged from
|
||||||
|
TimeAxisView *orig_tav; // where drag started
|
||||||
|
framecnt_t prev_amount;
|
||||||
|
framepos_t prev_position;
|
||||||
|
framecnt_t selection_length;
|
||||||
|
bool allow_moves_across_tracks; // only if all selected regions are on one track
|
||||||
|
ARDOUR::RegionList *exclude;
|
||||||
|
void add_all_after_to_views (TimeAxisView *tav, framepos_t where, const RegionSelection &exclude, bool drag_in_progress);
|
||||||
|
void remove_unselected_from_views (framecnt_t amount, bool move_regions);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/** Drags to create regions */
|
/** Drags to create regions */
|
||||||
class RegionCreateDrag : public Drag
|
class RegionCreateDrag : public Drag
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2400,10 +2400,17 @@ Editor::add_region_drag (ArdourCanvas::Item* item, GdkEvent*, RegionView* region
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config->get_edit_mode() == Splice) {
|
switch (Config->get_edit_mode()) {
|
||||||
_drags->add (new RegionSpliceDrag (this, item, region_view, selection->regions.by_layer()));
|
case Splice:
|
||||||
} else {
|
_drags->add (new RegionSpliceDrag (this, item, region_view, selection->regions.by_layer()));
|
||||||
_drags->add (new RegionMoveDrag (this, item, region_view, selection->regions.by_layer(), false, false));
|
break;
|
||||||
|
case Ripple:
|
||||||
|
_drags->add (new RegionRippleDrag (this, item, region_view, selection->regions.by_layer()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_drags->add (new RegionMoveDrag (this, item, region_view, selection->regions.by_layer(), false, false));
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2428,7 +2435,7 @@ Editor::add_region_brush_drag (ArdourCanvas::Item* item, GdkEvent*, RegionView*
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config->get_edit_mode() == Splice) {
|
if (Config->get_edit_mode() == Splice || Config->get_edit_mode() == Ripple) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2110,6 +2110,8 @@ Editor::unhide_ranges ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* INSERT/REPLACE */
|
||||||
|
|
||||||
void
|
void
|
||||||
Editor::insert_region_list_selection (float times)
|
Editor::insert_region_list_selection (float times)
|
||||||
{
|
{
|
||||||
|
|
@ -2142,6 +2144,9 @@ Editor::insert_region_list_selection (float times)
|
||||||
begin_reversible_command (_("insert region"));
|
begin_reversible_command (_("insert region"));
|
||||||
playlist->clear_changes ();
|
playlist->clear_changes ();
|
||||||
playlist->add_region ((RegionFactory::create (region, true)), get_preferred_edit_position(), times);
|
playlist->add_region ((RegionFactory::create (region, true)), get_preferred_edit_position(), times);
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
playlist->ripple (get_preferred_edit_position(), region->length() * times, boost::shared_ptr<Region>());
|
||||||
|
|
||||||
_session->add_command(new StatefulDiffCommand (playlist));
|
_session->add_command(new StatefulDiffCommand (playlist));
|
||||||
commit_reversible_command ();
|
commit_reversible_command ();
|
||||||
}
|
}
|
||||||
|
|
@ -3726,7 +3731,7 @@ Editor::can_cut_copy () const
|
||||||
|
|
||||||
|
|
||||||
/** Cut, copy or clear selected regions, automation points or a time range.
|
/** Cut, copy or clear selected regions, automation points or a time range.
|
||||||
* @param op Operation (Cut, Copy or Clear)
|
* @param op Operation (Delete, Cut, Copy or Clear)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Editor::cut_copy (CutCopyOp op)
|
Editor::cut_copy (CutCopyOp op)
|
||||||
|
|
@ -3762,7 +3767,7 @@ Editor::cut_copy (CutCopyOp op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( op != Clear ) //"Delete" doesn't change copy/paste buf
|
if ( op != Delete ) //"Delete" doesn't change copy/paste buf
|
||||||
cut_buffer->clear ();
|
cut_buffer->clear ();
|
||||||
|
|
||||||
if (entered_marker) {
|
if (entered_marker) {
|
||||||
|
|
@ -4002,10 +4007,11 @@ Editor::remove_clicked_region ()
|
||||||
|
|
||||||
boost::shared_ptr<Playlist> playlist = clicked_routeview->playlist();
|
boost::shared_ptr<Playlist> playlist = clicked_routeview->playlist();
|
||||||
|
|
||||||
begin_reversible_command (_("remove region"));
|
|
||||||
playlist->clear_changes ();
|
playlist->clear_changes ();
|
||||||
playlist->clear_owned_changes ();
|
playlist->clear_owned_changes ();
|
||||||
playlist->remove_region (clicked_regionview->region());
|
playlist->remove_region (clicked_regionview->region());
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
playlist->ripple (clicked_regionview->region()->position(), -clicked_regionview->region()->length(), boost::shared_ptr<Region>());
|
||||||
|
|
||||||
/* We might have removed regions, which alters other regions' layering_index,
|
/* We might have removed regions, which alters other regions' layering_index,
|
||||||
so we need to do a recursive diff here.
|
so we need to do a recursive diff here.
|
||||||
|
|
@ -4068,6 +4074,9 @@ Editor::remove_selected_regions ()
|
||||||
playlist->clear_owned_changes ();
|
playlist->clear_owned_changes ();
|
||||||
playlist->freeze ();
|
playlist->freeze ();
|
||||||
playlist->remove_region (*rl);
|
playlist->remove_region (*rl);
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
playlist->ripple ((*rl)->position(), -(*rl)->length(), boost::shared_ptr<Region>());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<boost::shared_ptr<Playlist> >::iterator pl;
|
vector<boost::shared_ptr<Playlist> >::iterator pl;
|
||||||
|
|
@ -4197,12 +4206,16 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Delete:
|
case Delete:
|
||||||
pl->remove_region (r);
|
pl->remove_region (r);
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
pl->ripple (r->position(), -r->length(), boost::shared_ptr<Region>());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Cut:
|
case Cut:
|
||||||
_xx = RegionFactory::create (r);
|
_xx = RegionFactory::create (r);
|
||||||
npl->add_region (_xx, r->position() - first_position);
|
npl->add_region (_xx, r->position() - first_position);
|
||||||
pl->remove_region (r);
|
pl->remove_region (r);
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
pl->ripple (r->position(), -r->length(), boost::shared_ptr<Region>());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Copy:
|
case Copy:
|
||||||
|
|
@ -4211,7 +4224,9 @@ Editor::cut_copy_regions (CutCopyOp op, RegionSelection& rs)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Clear:
|
case Clear:
|
||||||
pl->remove_region (r);
|
pl->remove_region (r);
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
pl->ripple (r->position(), -r->length(), boost::shared_ptr<Region>());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1413,6 +1413,10 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Delete:
|
case Delete:
|
||||||
if (playlist->cut (time) != 0) {
|
if (playlist->cut (time) != 0) {
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
playlist->ripple(time.start(), -time.length(), NULL);
|
||||||
|
// no need to exclude any regions from rippling here
|
||||||
|
|
||||||
vector<Command*> cmds;
|
vector<Command*> cmds;
|
||||||
playlist->rdiff (cmds);
|
playlist->rdiff (cmds);
|
||||||
_session->add_commands (cmds);
|
_session->add_commands (cmds);
|
||||||
|
|
@ -1424,6 +1428,10 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
|
||||||
case Cut:
|
case Cut:
|
||||||
if ((what_we_got = playlist->cut (time)) != 0) {
|
if ((what_we_got = playlist->cut (time)) != 0) {
|
||||||
_editor.get_cut_buffer().add (what_we_got);
|
_editor.get_cut_buffer().add (what_we_got);
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
playlist->ripple(time.start(), -time.length(), NULL);
|
||||||
|
// no need to exclude any regions from rippling here
|
||||||
|
|
||||||
vector<Command*> cmds;
|
vector<Command*> cmds;
|
||||||
playlist->rdiff (cmds);
|
playlist->rdiff (cmds);
|
||||||
_session->add_commands (cmds);
|
_session->add_commands (cmds);
|
||||||
|
|
@ -1439,6 +1447,9 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
|
||||||
|
|
||||||
case Clear:
|
case Clear:
|
||||||
if ((what_we_got = playlist->cut (time)) != 0) {
|
if ((what_we_got = playlist->cut (time)) != 0) {
|
||||||
|
if (Config->get_edit_mode() == Ripple)
|
||||||
|
playlist->ripple(time.start(), -time.length(), NULL);
|
||||||
|
// no need to exclude any regions from rippling here
|
||||||
|
|
||||||
vector<Command*> cmds;
|
vector<Command*> cmds;
|
||||||
playlist->rdiff (cmds);
|
playlist->rdiff (cmds);
|
||||||
|
|
@ -1473,8 +1484,18 @@ RouteTimeAxisView::paste (framepos_t pos, float times, Selection& selection, siz
|
||||||
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("modified paste to %1\n", pos));
|
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("modified paste to %1\n", pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
pl->clear_changes ();
|
pl->clear_changes ();
|
||||||
|
if (Config->get_edit_mode() == Ripple) {
|
||||||
|
std::pair<framepos_t, framepos_t> extent = (*p)->get_extent();
|
||||||
|
framecnt_t amount = extent.second - extent.first;
|
||||||
|
pl->ripple(pos, amount * times, boost::shared_ptr<Region>());
|
||||||
|
}
|
||||||
pl->paste (*p, pos, times);
|
pl->paste (*p, pos, times);
|
||||||
|
|
||||||
|
vector<Command*> cmds;
|
||||||
|
pl->rdiff (cmds);
|
||||||
|
_session->add_commands (cmds);
|
||||||
|
|
||||||
_session->add_command (new StatefulDiffCommand (pl));
|
_session->add_command (new StatefulDiffCommand (pl));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,14 @@ public:
|
||||||
void uncombine (boost::shared_ptr<Region>);
|
void uncombine (boost::shared_ptr<Region>);
|
||||||
|
|
||||||
void shuffle (boost::shared_ptr<Region>, int dir);
|
void shuffle (boost::shared_ptr<Region>, int dir);
|
||||||
|
void ripple (framepos_t at, framecnt_t distance, RegionList *exclude);
|
||||||
|
void ripple (framepos_t at, framecnt_t distance, boost::shared_ptr<Region> exclude) {
|
||||||
|
RegionList el;
|
||||||
|
if (exclude)
|
||||||
|
el.push_back (exclude);
|
||||||
|
ripple (at, distance, &el);
|
||||||
|
}
|
||||||
|
|
||||||
void update_after_tempo_map_change ();
|
void update_after_tempo_map_change ();
|
||||||
|
|
||||||
boost::shared_ptr<Playlist> cut (std::list<AudioRange>&, bool result_is_hidden = true);
|
boost::shared_ptr<Playlist> cut (std::list<AudioRange>&, bool result_is_hidden = true);
|
||||||
|
|
@ -283,6 +291,7 @@ public:
|
||||||
bool first_set_state;
|
bool first_set_state;
|
||||||
bool _hidden;
|
bool _hidden;
|
||||||
bool _splicing;
|
bool _splicing;
|
||||||
|
bool _rippling;
|
||||||
bool _shuffling;
|
bool _shuffling;
|
||||||
bool _nudging;
|
bool _nudging;
|
||||||
uint32_t _refcnt;
|
uint32_t _refcnt;
|
||||||
|
|
@ -337,6 +346,11 @@ public:
|
||||||
void splice_locked (framepos_t at, framecnt_t distance, boost::shared_ptr<Region> exclude);
|
void splice_locked (framepos_t at, framecnt_t distance, boost::shared_ptr<Region> exclude);
|
||||||
void splice_unlocked (framepos_t at, framecnt_t distance, boost::shared_ptr<Region> exclude);
|
void splice_unlocked (framepos_t at, framecnt_t distance, boost::shared_ptr<Region> exclude);
|
||||||
|
|
||||||
|
void core_ripple (framepos_t at, framecnt_t distance, RegionList *exclude);
|
||||||
|
void ripple_locked (framepos_t at, framecnt_t distance, RegionList *exclude);
|
||||||
|
void ripple_unlocked (framepos_t at, framecnt_t distance, RegionList *exclude);
|
||||||
|
|
||||||
|
|
||||||
virtual void remove_dependents (boost::shared_ptr<Region> /*region*/) {}
|
virtual void remove_dependents (boost::shared_ptr<Region> /*region*/) {}
|
||||||
|
|
||||||
virtual XMLNode& state (bool);
|
virtual XMLNode& state (bool);
|
||||||
|
|
|
||||||
|
|
@ -341,6 +341,7 @@ namespace ARDOUR {
|
||||||
enum EditMode {
|
enum EditMode {
|
||||||
Slide,
|
Slide,
|
||||||
Splice,
|
Splice,
|
||||||
|
Ripple,
|
||||||
Lock
|
Lock
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,7 @@ setup_enum_writer ()
|
||||||
|
|
||||||
REGISTER_ENUM (Slide);
|
REGISTER_ENUM (Slide);
|
||||||
REGISTER_ENUM (Splice);
|
REGISTER_ENUM (Splice);
|
||||||
|
REGISTER_ENUM (Ripple); // XXX do the old enum values have to stay in order?
|
||||||
REGISTER_ENUM (Lock);
|
REGISTER_ENUM (Lock);
|
||||||
REGISTER (_EditMode);
|
REGISTER (_EditMode);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ Playlist::Playlist (boost::shared_ptr<const Playlist> other, string namestr, boo
|
||||||
in_set_state--;
|
in_set_state--;
|
||||||
|
|
||||||
_splicing = other->_splicing;
|
_splicing = other->_splicing;
|
||||||
|
_rippling = other->_rippling;
|
||||||
_nudging = other->_nudging;
|
_nudging = other->_nudging;
|
||||||
_edit_mode = other->_edit_mode;
|
_edit_mode = other->_edit_mode;
|
||||||
|
|
||||||
|
|
@ -302,6 +303,7 @@ Playlist::init (bool hide)
|
||||||
_refcnt = 0;
|
_refcnt = 0;
|
||||||
_hidden = hide;
|
_hidden = hide;
|
||||||
_splicing = false;
|
_splicing = false;
|
||||||
|
_rippling = false;
|
||||||
_shuffling = false;
|
_shuffling = false;
|
||||||
_nudging = false;
|
_nudging = false;
|
||||||
in_set_state = 0;
|
in_set_state = 0;
|
||||||
|
|
@ -706,7 +708,7 @@ Playlist::flush_notifications (bool from_undo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
possibly_splice_unlocked (position, (pos + length) - position, boost::shared_ptr<Region>());
|
possibly_splice_unlocked (position, (pos + length) - position, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1399,7 +1401,7 @@ Playlist::flush_notifications (bool from_undo)
|
||||||
|
|
||||||
if (_edit_mode == Splice) {
|
if (_edit_mode == Splice) {
|
||||||
splice_locked (at, distance, exclude);
|
splice_locked (at, distance, exclude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1456,12 +1458,63 @@ Playlist::flush_notifications (bool from_undo)
|
||||||
_splicing = false;
|
_splicing = false;
|
||||||
|
|
||||||
notify_contents_changed ();
|
notify_contents_changed ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Playlist::region_bounds_changed (const PropertyChange& what_changed, boost::shared_ptr<Region> region)
|
Playlist::ripple_locked (framepos_t at, framecnt_t distance, RegionList *exclude)
|
||||||
{
|
{
|
||||||
if (in_set_state || _splicing || _nudging || _shuffling) {
|
{
|
||||||
|
RegionWriteLock rl (this);
|
||||||
|
core_ripple (at, distance, exclude);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Playlist::ripple_unlocked (framepos_t at, framecnt_t distance, RegionList *exclude)
|
||||||
|
{
|
||||||
|
core_ripple (at, distance, exclude);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Playlist::core_ripple (framepos_t at, framecnt_t distance, RegionList *exclude)
|
||||||
|
{
|
||||||
|
if (distance == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_rippling = true;
|
||||||
|
RegionListProperty copy = regions;
|
||||||
|
for (RegionList::iterator i = copy.begin(); i != copy.end(); ++i) {
|
||||||
|
assert (i != copy.end());
|
||||||
|
|
||||||
|
if (exclude) {
|
||||||
|
if (std::find(exclude->begin(), exclude->end(), (*i)) != exclude->end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*i)->position() >= at) {
|
||||||
|
framepos_t new_pos = (*i)->position() + distance;
|
||||||
|
framepos_t limit = max_framepos - (*i)->length();
|
||||||
|
if (new_pos < 0) {
|
||||||
|
new_pos = 0;
|
||||||
|
} else if (new_pos >= limit ) {
|
||||||
|
new_pos = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*i)->set_position (new_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_rippling = false;
|
||||||
|
notify_contents_changed ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Playlist::region_bounds_changed (const PropertyChange& what_changed, boost::shared_ptr<Region> region)
|
||||||
|
{
|
||||||
|
if (in_set_state || _splicing || _rippling || _nudging || _shuffling) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2694,6 +2747,12 @@ Playlist::region_is_shuffle_constrained (boost::shared_ptr<Region>)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Playlist::ripple (framepos_t at, framecnt_t distance, RegionList *exclude)
|
||||||
|
{
|
||||||
|
ripple_locked (at, distance, exclude);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Playlist::update_after_tempo_map_change ()
|
Playlist::update_after_tempo_map_change ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -423,6 +423,8 @@ ARDOUR::string_to_edit_mode (string str)
|
||||||
return Splice;
|
return Splice;
|
||||||
} else if (str == _("Slide")) {
|
} else if (str == _("Slide")) {
|
||||||
return Slide;
|
return Slide;
|
||||||
|
} else if (str == _("Ripple")) {
|
||||||
|
return Ripple;
|
||||||
} else if (str == _("Lock")) {
|
} else if (str == _("Lock")) {
|
||||||
return Lock;
|
return Lock;
|
||||||
}
|
}
|
||||||
|
|
@ -441,6 +443,9 @@ ARDOUR::edit_mode_to_string (EditMode mode)
|
||||||
case Lock:
|
case Lock:
|
||||||
return _("Lock");
|
return _("Lock");
|
||||||
|
|
||||||
|
case Ripple:
|
||||||
|
return _("Ripple");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case Splice:
|
case Splice:
|
||||||
return _("Splice");
|
return _("Splice");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue