From: Ben Loftis Date: Thu, 16 Jul 2015 21:13:24 +0000 (-0500) Subject: merge fix X-Git-Tag: 4.2~229 X-Git-Url: https://git.carlh.net/gitweb/?a=commitdiff_plain;h=46c83693284ece4a732d26e62113ea4ac584d539;hp=edce75973c076ab1fa66cc6d601a30fcbbcd5dd4;p=ardour.git merge fix --- diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc index f9af7f98d2..4f963a290d 100644 --- a/gtk2_ardour/audio_region_view.cc +++ b/gtk2_ardour/audio_region_view.cc @@ -1261,7 +1261,7 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b trackview.session()->add_command (new MementoCommand(*(audio_region().get()), ®ion_before, ®ion_after)); } - audio_region()->envelope()->add (fx, y, with_guard_points); + audio_region()->envelope()->editor_add (fx, y, with_guard_points); XMLNode &after = audio_region()->envelope()->get_state(); trackview.session()->add_command (new MementoCommand(*audio_region()->envelope().get(), &before, &after)); diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index 7951848c59..ed7bfc238d 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -41,6 +41,7 @@ #include "tape_region_view.h" #include "audio_time_axis.h" #include "region_selection.h" +#include "region_gain_line.h" #include "selection.h" #include "public_editor.h" #include "ardour_ui.h" @@ -471,3 +472,14 @@ AudioStreamView::color_handler () } } } + +void +AudioStreamView::set_selected_points (PointSelection& points) +{ + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + AudioRegionView* const arv = dynamic_cast(*i); + if (arv && arv->get_gain_line ()) { + arv->get_gain_line ()->set_selected_points (points); + } + } +} diff --git a/gtk2_ardour/audio_streamview.h b/gtk2_ardour/audio_streamview.h index 8e9b095537..443a39063b 100644 --- a/gtk2_ardour/audio_streamview.h +++ b/gtk2_ardour/audio_streamview.h @@ -26,6 +26,7 @@ #include #include "ardour/location.h" +#include "point_selection.h" #include "editing.h" #include "streamview.h" @@ -61,6 +62,7 @@ class AudioStreamView : public StreamView std::pair, std::list > hide_xfades_with (boost::shared_ptr ar); RegionView* create_region_view (boost::shared_ptr, bool, bool); + void set_selected_points (PointSelection&); private: void setup_rec_box (); diff --git a/gtk2_ardour/automation_controller.cc b/gtk2_ardour/automation_controller.cc index f57f2a737a..44c03159a4 100644 --- a/gtk2_ardour/automation_controller.cc +++ b/gtk2_ardour/automation_controller.cc @@ -204,7 +204,7 @@ AutomationController::toggled () _controllable->set_automation_state(Write); } if (_controllable->list()) { - _controllable->list()->set_in_write_pass(true, false, _controllable->session().audible_frame()); + _controllable->list()->set_in_write_pass(true, true, _controllable->session().audible_frame()); } } const bool was_active = _controllable->get_value() >= 0.5; diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 069a823155..d0dc933759 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -466,7 +466,6 @@ AutomationLine::string_to_fraction (string const & s) const void AutomationLine::start_drag_single (ControlPoint* cp, double x, float fraction) { - trackview.editor().begin_reversible_command (_("automation event move")); trackview.editor().session()->add_command ( new MementoCommand (memento_command_binder(), &get_state(), 0)); @@ -492,7 +491,6 @@ AutomationLine::start_drag_single (ControlPoint* cp, double x, float fraction) void AutomationLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction) { - trackview.editor().begin_reversible_command (_("automation range move")); trackview.editor().session()->add_command ( new MementoCommand (memento_command_binder (), &get_state(), 0)); @@ -512,7 +510,6 @@ AutomationLine::start_drag_line (uint32_t i1, uint32_t i2, float fraction) void AutomationLine::start_drag_multiple (list cp, float fraction, XMLNode* state) { - trackview.editor().begin_reversible_command (_("automation range move")); trackview.editor().session()->add_command ( new MementoCommand (memento_command_binder(), state, 0)); @@ -678,6 +675,7 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool for (vector::iterator ccp = contiguous_points.begin(); ccp != contiguous_points.end(); ++ccp) { (*ccp)->compute_x_bounds (trackview.editor()); } + _drag_had_movement = true; } /* OK, now on to the stuff related to *this* motion event. First, for @@ -738,7 +736,6 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool _drag_distance += dx; _drag_x += dx; _last_drag_fraction = fraction; - _drag_had_movement = true; did_push = with_push; return pair (_drag_x + dx, _last_drag_fraction + dy); @@ -951,7 +948,8 @@ AutomationLine::set_selected_points (PointSelection const & points) set_colors (); } -void AutomationLine::set_colors () +void +AutomationLine::set_colors () { set_line_color (ARDOUR_UI::config()->color ("automation line")); for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc index 7e330949de..b418d096f2 100644 --- a/gtk2_ardour/automation_region_view.cc +++ b/gtk2_ardour/automation_region_view.cc @@ -190,7 +190,7 @@ AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double view->editor().begin_reversible_command (_("add automation event")); XMLNode& before = _line->the_list()->get_state(); - _line->the_list()->add (when_d, y, with_guard_points, false); + _line->the_list()->editor_add (when_d, y, with_guard_points); XMLNode& after = _line->the_list()->get_state(); diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 01f2ebb514..d5276e0cc5 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -449,7 +449,7 @@ AutomationTimeAxisView::clear_clicked () } else if (_view) { _view->clear (); } - + set_automation_state ((AutoState) ARDOUR::Off); _editor.commit_reversible_command (); _session->set_dirty (); } @@ -644,10 +644,10 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when, _editor.begin_reversible_command (_("add automation event")); XMLNode& before = list->get_state(); - list->add (when, y, with_guard_points); + list->editor_add (when, y, with_guard_points); XMLNode& after = list->get_state(); - _session->add_command (new MementoCommand (*list, &before, &after)); + _session->add_command (new MementoCommand (*list.get (), &before, &after)); _editor.commit_reversible_command (); _session->set_dirty (); } diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index 8e2f78fb93..6413b6d691 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -1236,7 +1236,7 @@ Editor::which_canvas_cursor(ItemType type) const cursor = _cursors->fader; break; case GainLineItem: - cursor = which_track_cursor (); + cursor = _cursors->cross_hair; break; case AutomationLineItem: cursor = _cursors->cross_hair; diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index 8af5389e70..92ebbd976d 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -695,6 +695,11 @@ Editor::canvas_line_event (GdkEvent *event, ArdourCanvas::Item* item, Automation type = AutomationLineItem; } + clicked_control_point = 0; + clicked_axisview = &al->trackview; + clicked_routeview = dynamic_cast(clicked_axisview); + clicked_regionview = 0; + return typed_event (item, event, type); } diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 99b8ff6283..0877a8b4be 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -617,6 +617,11 @@ RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) assert(_last_pointer_time_axis_view >= 0); _last_pointer_layer = tv.first->layer_display() == Overlaid ? 0 : tv.second; } + + if (_brushing) { + /* cross track dragging seems broken here. disabled for now. */ + _y_constrained = true; + } } double @@ -1221,13 +1226,13 @@ void RegionMoveDrag::motion (GdkEvent* event, bool first_move) { if (_copy && first_move) { - - if (_x_constrained) { + if (_x_constrained && !_brushing) { _editor->begin_reversible_command (Operations::fixed_time_region_copy); - } else { + } else if (!_brushing) { _editor->begin_reversible_command (Operations::region_copy); + } else if (_brushing) { + _editor->begin_reversible_command (Operations::drag_region_brush); } - /* duplicate the regionview(s) and region(s) */ list new_regionviews; @@ -1285,14 +1290,14 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move) } } else if (!_copy && first_move) { - - if (_x_constrained) { + if (_x_constrained && !_brushing) { _editor->begin_reversible_command (_("fixed time region drag")); - } else { + } else if (!_brushing) { _editor->begin_reversible_command (Operations::region_drag); + } else if (_brushing) { + _editor->begin_reversible_command (Operations::drag_region_brush); } } - RegionMotionDrag::motion (event, first_move); } @@ -1500,12 +1505,6 @@ RegionMoveDrag::finished_no_copy ( set views_to_update; RouteTimeAxisView* new_time_axis_view = 0; - if (_brushing) { - /* all changes were made during motion event handlers */ - _editor->commit_reversible_command (); - return; - } - typedef map, RouteTimeAxisView*> PlaylistMapping; PlaylistMapping playlist_mapping; @@ -1619,7 +1618,6 @@ RegionMoveDrag::finished_no_copy ( } rv->region()->set_position (where); - _editor->session()->add_command (new StatefulDiffCommand (rv->region())); } @@ -1668,7 +1666,7 @@ RegionMoveDrag::finished_no_copy ( /* write commands for the accumulated diffs for all our modified playlists */ add_stateful_diff_commands_for_playlists (modified_playlists); - + /* applies to _brushing */ _editor->commit_reversible_command (); /* We have futzed with the layering of canvas items on our streamviews. @@ -2334,6 +2332,8 @@ RegionCreateDrag::aborted (bool) NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i) : Drag (e, i) , region (0) + , relative (false) + , at_front (true) , _snap_delta (0) { DEBUG_TRACE (DEBUG::Drags, "New NoteResizeDrag\n"); @@ -2370,37 +2370,36 @@ NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/) } else { relative = true; } - MidiRegionSelection& ms (_editor->get_selection().midi_regions); - if (ms.size() > 1) { /* has to be relative, may make no sense otherwise */ relative = true; } - /* select this note; if it is already selected, preserve the existing selection, otherwise make this note the only one selected. */ region->note_selected (cnote, cnote->selected ()); - - _editor->begin_reversible_command (_("resize notes")); - - for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ) { - MidiRegionSelection::iterator next; - next = r; - ++next; - MidiRegionView* mrv = dynamic_cast(*r); - if (mrv) { - mrv->begin_resizing (at_front); - } - r = next; - } } void -NoteResizeDrag::motion (GdkEvent* event, bool /*first_move*/) +NoteResizeDrag::motion (GdkEvent* event, bool first_move) { MidiRegionSelection& ms (_editor->get_selection().midi_regions); + if (first_move) { + _editor->begin_reversible_command (_("resize notes")); + + for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ) { + MidiRegionSelection::iterator next; + next = r; + ++next; + MidiRegionView* mrv = dynamic_cast(*r); + if (mrv) { + mrv->begin_resizing (at_front); + } + r = next; + } + } + for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) { NoteBase* nb = reinterpret_cast (_item->get_data ("notebase")); assert (nb); @@ -2434,8 +2433,12 @@ NoteResizeDrag::motion (GdkEvent* event, bool /*first_move*/) } void -NoteResizeDrag::finished (GdkEvent* event, bool /*movement_occurred*/) +NoteResizeDrag::finished (GdkEvent* event, bool movement_occurred) { + if (!movement_occurred) { + return; + } + MidiRegionSelection& ms (_editor->get_selection().midi_regions); for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) { NoteBase* nb = reinterpret_cast (_item->get_data ("notebase")); @@ -2458,9 +2461,11 @@ NoteResizeDrag::finished (GdkEvent* event, bool /*movement_occurred*/) } } } + if (apply_snap_delta) { sd = _snap_delta; } + mrv->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, sd, snap); } } @@ -3479,7 +3484,7 @@ FadeInDrag::finished (GdkEvent* event, bool movement_occurred) fade_length = pos - region->position(); } - _editor->begin_reversible_command (_("change fade in length")); + bool in_command = false; for (list::iterator i = _views.begin(); i != _views.end(); ++i) { @@ -3495,11 +3500,17 @@ FadeInDrag::finished (GdkEvent* event, bool movement_occurred) tmp->audio_region()->set_fade_in_length (fade_length); tmp->audio_region()->set_fade_in_active (true); + if (!in_command) { + _editor->begin_reversible_command (_("change fade in length")); + in_command = true; + } XMLNode &after = alist->get_state(); _editor->session()->add_command(new MementoCommand(*alist.get(), &before, &after)); } - _editor->commit_reversible_command (); + if (in_command) { + _editor->commit_reversible_command (); + } } void @@ -3598,7 +3609,7 @@ FadeOutDrag::finished (GdkEvent* event, bool movement_occurred) fade_length = region->last_frame() - pos; } - _editor->begin_reversible_command (_("change fade out length")); + bool in_command = false; for (list::iterator i = _views.begin(); i != _views.end(); ++i) { @@ -3614,11 +3625,17 @@ FadeOutDrag::finished (GdkEvent* event, bool movement_occurred) tmp->audio_region()->set_fade_out_length (fade_length); tmp->audio_region()->set_fade_out_active (true); + if (!in_command) { + _editor->begin_reversible_command (_("change fade out length")); + in_command = false; + } XMLNode &after = alist->get_state(); _editor->session()->add_command(new MementoCommand(*alist.get(), &before, &after)); } - _editor->commit_reversible_command (); + if (in_command) { + _editor->commit_reversible_command (); + } } void @@ -3952,8 +3969,8 @@ MarkerDrag::finished (GdkEvent* event, bool movement_occurred) _editor->_dragging_edit_point = false; - _editor->begin_reversible_command ( _("move marker") ); XMLNode &before = _editor->session()->locations()->get_state(); + bool in_command = false; MarkerSelection::iterator i; CopiedLocationInfo::iterator x; @@ -3968,9 +3985,12 @@ MarkerDrag::finished (GdkEvent* event, bool movement_occurred) if (location) { if (location->locked()) { - return; + continue; + } + if (!in_command) { + _editor->begin_reversible_command ( _("move marker") ); + in_command = true; } - if (location->is_mark()) { location->set_start (((*x).location)->start()); } else { @@ -3979,9 +3999,11 @@ MarkerDrag::finished (GdkEvent* event, bool movement_occurred) } } - XMLNode &after = _editor->session()->locations()->get_state(); - _editor->session()->add_command(new MementoCommand(*(_editor->session()->locations()), &before, &after)); - _editor->commit_reversible_command (); + if (in_command) { + XMLNode &after = _editor->session()->locations()->get_state(); + _editor->session()->add_command(new MementoCommand(*(_editor->session()->locations()), &before, &after)); + _editor->commit_reversible_command (); + } } void @@ -4044,9 +4066,6 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) setup_snap_delta (pos); float const fraction = 1 - (_point->get_y() / _point->line().height()); - - _point->line().start_drag_single (_point, _fixed_grab_x, fraction); - show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction)); _pushing = Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::push_points_modifier ()); @@ -4057,7 +4076,7 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) } void -ControlPointDrag::motion (GdkEvent* event, bool) +ControlPointDrag::motion (GdkEvent* event, bool first_motion) { double dx = _drags->current_pointer_x() - last_pointer_x(); double dy = current_pointer_y() - last_pointer_y(); @@ -4076,11 +4095,6 @@ ControlPointDrag::motion (GdkEvent* event, bool) // positive side of zero double const zero_gain_y = (1.0 - _zero_gain_fraction) * _point->line().height() - .01; - // make sure we hit zero when passing through - if ((cy < zero_gain_y && (cy - dy) > zero_gain_y) || (cy > zero_gain_y && (cy - dy) < zero_gain_y)) { - cy = zero_gain_y; - } - if (_x_constrained) { cx = _fixed_grab_x; } @@ -4091,6 +4105,11 @@ ControlPointDrag::motion (GdkEvent* event, bool) _cumulative_x_drag = cx - _fixed_grab_x; _cumulative_y_drag = cy - _fixed_grab_y; + // make sure we hit zero when passing through + if ((cy < zero_gain_y && (cy - dy) > zero_gain_y) || (cy > zero_gain_y && (cy - dy) < zero_gain_y)) { + cy = zero_gain_y; + } + cx = max (0.0, cx); cy = max (0.0, cy); cy = min ((double) _point->line().height(), cy); @@ -4106,6 +4125,11 @@ ControlPointDrag::motion (GdkEvent* event, bool) float const fraction = 1.0 - (cy / _point->line().height()); + if (first_motion) { + _editor->begin_reversible_command (_("automation event move")); + _point->line().start_drag_single (_point, _fixed_grab_x, fraction); + } + _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_frames), fraction, false, _pushing, _final_index); show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction)); @@ -4123,10 +4147,9 @@ ControlPointDrag::finished (GdkEvent* event, bool movement_occurred) } else { motion (event, false); + _point->line().end_drag (_pushing, _final_index); + _editor->commit_reversible_command (); } - - _point->line().end_drag (_pushing, _final_index); - _editor->commit_reversible_command (); } void @@ -4151,6 +4174,8 @@ LineDrag::LineDrag (Editor* e, ArdourCanvas::Item* i) : Drag (e, i) , _line (0) , _cumulative_y_drag (0) + , _before (0) + , _after (0) { DEBUG_TRACE (DEBUG::Drags, "New LineDrag\n"); } @@ -4174,10 +4199,7 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) framecnt_t const frame_within_region = (framecnt_t) floor (cx * _editor->samples_per_pixel); - uint32_t before; - uint32_t after; - - if (!_line->control_points_adjacent (frame_within_region, before, after)) { + if (!_line->control_points_adjacent (frame_within_region, _before, _after)) { /* no adjacent points */ return; } @@ -4191,13 +4213,11 @@ LineDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/) double fraction = 1.0 - (cy / _line->height()); - _line->start_drag_line (before, after, fraction); - show_verbose_cursor_text (_line->get_verbose_cursor_string (fraction)); } void -LineDrag::motion (GdkEvent* event, bool) +LineDrag::motion (GdkEvent* event, bool first_move) { double dy = current_pointer_y() - last_pointer_y(); @@ -4215,6 +4235,11 @@ LineDrag::motion (GdkEvent* event, bool) double const fraction = 1.0 - (cy / _line->height()); uint32_t ignored; + if (first_move) { + _editor->begin_reversible_command (_("automation range move")); + _line->start_drag_line (_before, _after, fraction); + } + /* we are ignoring x position for this drag, so we can just pass in anything */ _line->drag_motion (0, fraction, true, false, ignored); @@ -4227,20 +4252,17 @@ LineDrag::finished (GdkEvent* event, bool movement_occured) if (movement_occured) { motion (event, false); _line->end_drag (false, 0); + _editor->commit_reversible_command (); } else { /* add a new control point on the line */ AutomationTimeAxisView* atv; - _line->end_drag (false, 0); - if ((atv = dynamic_cast(_editor->clicked_axisview)) != 0) { framepos_t where = _editor->window_event_sample (event, 0, 0); atv->add_automation_event (event, where, event->button.y, false); } } - - _editor->commit_reversible_command (); } void @@ -5525,8 +5547,8 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) double const p = j->line->time_converter().from (i->start - j->line->time_converter().origin_b ()); double const q = j->line->time_converter().from (a - j->line->time_converter().origin_b ()); - the_list->editor_add (p, value (the_list, p)); - the_list->editor_add (q, value (the_list, q)); + the_list->editor_add (p, value (the_list, p), false); + the_list->editor_add (q, value (the_list, q), false); } /* same thing for the end */ @@ -5551,8 +5573,8 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) double const p = j->line->time_converter().from (b - j->line->time_converter().origin_b ()); double const q = j->line->time_converter().from (i->end - j->line->time_converter().origin_b ()); - the_list->editor_add (p, value (the_list, p)); - the_list->editor_add (q, value (the_list, q)); + the_list->editor_add (p, value (the_list, p), false); + the_list->editor_add (q, value (the_list, q), false); } } @@ -5589,19 +5611,22 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor) if (_nothing_to_drag) { return; } - - for (list::iterator i = _lines.begin(); i != _lines.end(); ++i) { - i->line->start_drag_multiple (i->points, y_fraction (i->line, current_pointer_y()), i->state); - } } void -AutomationRangeDrag::motion (GdkEvent*, bool /*first_move*/) +AutomationRangeDrag::motion (GdkEvent*, bool first_move) { if (_nothing_to_drag) { return; } + if (first_move) { + _editor->begin_reversible_command (_("automation range move")); + for (list::iterator i = _lines.begin(); i != _lines.end(); ++i) { + i->line->start_drag_multiple (i->points, y_fraction (i->line, current_pointer_y()), i->state); + } + } + for (list::iterator l = _lines.begin(); l != _lines.end(); ++l) { float const f = y_fraction (l->line, current_pointer_y()); /* we are ignoring x position for this drag, so we can just pass in anything */ @@ -5612,9 +5637,9 @@ AutomationRangeDrag::motion (GdkEvent*, bool /*first_move*/) } void -AutomationRangeDrag::finished (GdkEvent* event, bool) +AutomationRangeDrag::finished (GdkEvent* event, bool motion_occurred) { - if (_nothing_to_drag) { + if (_nothing_to_drag || !motion_occurred) { return; } diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 1e0161fd71..e5acbaad44 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -877,6 +877,8 @@ private: double _fixed_grab_x; double _fixed_grab_y; double _cumulative_y_drag; + uint32_t _before; + uint32_t _after; }; /** Transient feature line drags*/ diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 5c106785e2..26e8dd2872 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -446,7 +446,8 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp if (((mouse_mode != MouseObject) && (mouse_mode != MouseAudition || item_type != RegionItem) && (mouse_mode != MouseTimeFX || item_type != RegionItem) && - (mouse_mode != MouseDraw)) || + (mouse_mode != MouseDraw) && + (mouse_mode != MouseContent || item_type == RegionItem)) || ((event->type != GDK_BUTTON_PRESS && event->type != GDK_BUTTON_RELEASE) || event->button.button > 3)) { return; } @@ -512,7 +513,8 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp break; case ControlPointItem: - set_selected_track_as_side_effect (op); + /* for object/track exclusivity, we don't call set_selected_track_as_side_effect (op); */ + if (eff_mouse_mode != MouseRange) { _mouse_changed_selection |= set_selected_control_point_from_click (press, op); } @@ -761,11 +763,21 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT } return true; + case GainLineItem: + _drags->set (new LineDrag (this, item), event); + return true; + break; + case ControlPointItem: _drags->set (new ControlPointDrag (this, item), event); return true; break; + case AutomationLineItem: + _drags->set (new LineDrag (this, item), event); + return true; + break; + case StreamItem: //in the past, we created a new midi region here, but perhaps that is best left to the Draw mode break; @@ -2200,7 +2212,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, framepos_t pos) // playlist is frozen, so we have to update manually XXX this is disgusting - playlist->RegionAdded (new_region); /* EMIT SIGNAL */ + //playlist->RegionAdded (new_region); /* EMIT SIGNAL */ } gint @@ -2262,8 +2274,6 @@ Editor::add_region_brush_drag (ArdourCanvas::Item* item, GdkEvent*, RegionView* } _drags->add (new RegionMoveDrag (this, item, region_view, selection->regions.by_layer(), true, false)); - - begin_reversible_command (Operations::drag_region_brush); } /** Start a grab where a time range is selected, track(s) are selected, and the @@ -2303,7 +2313,6 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event) /* A selection grab currently creates two undo/redo operations, one for creating the new region and another for moving it. */ - begin_reversible_command (Operations::selection_grab); boost::shared_ptr playlist = clicked_axisview->playlist(); @@ -2316,6 +2325,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* /*item*/, GdkEvent* event) if (latest_regionviews.empty()) { /* something went wrong */ + abort_reversible_command (); return; } diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 2d26a90a86..50b7c81b44 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -336,9 +336,9 @@ Editor::move_range_selection_start_or_end_to_region_boundary (bool move_end, boo return; } - begin_reversible_command (_("alter selection")); + begin_reversible_selection_op (_("alter selection")); selection->set_preserving_all_ranges (start, end); - commit_reversible_command (); + commit_reversible_selection_op (); } bool @@ -400,8 +400,7 @@ Editor::nudge_forward (bool next, bool force_playhead) } else if (!force_playhead && !selection->markers.empty()) { bool is_start; - - begin_reversible_command (_("nudge location forward")); + bool in_command = false; for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) { @@ -432,13 +431,18 @@ Editor::nudge_forward (bool next, bool force_playhead) loc->set_end (max_framepos); } } + if (!in_command) { + begin_reversible_command (_("nudge location forward")); + in_command = true; + } XMLNode& after (loc->get_state()); _session->add_command (new MementoCommand(*loc, &before, &after)); } } - commit_reversible_command (); - + if (in_command) { + commit_reversible_command (); + } } else { distance = get_nudge_distance (playhead_cursor->current_frame (), next_distance); _session->request_locate (playhead_cursor->current_frame () + distance); @@ -485,8 +489,7 @@ Editor::nudge_backward (bool next, bool force_playhead) } else if (!force_playhead && !selection->markers.empty()) { bool is_start; - - begin_reversible_command (_("nudge location forward")); + bool in_command = false; for (MarkerSelection::iterator i = selection->markers.begin(); i != selection->markers.end(); ++i) { @@ -519,13 +522,17 @@ Editor::nudge_backward (bool next, bool force_playhead) loc->set_end (loc->length()); } } - + if (!in_command) { + begin_reversible_command (_("nudge location forward")); + in_command = true; + } XMLNode& after (loc->get_state()); _session->add_command (new MementoCommand(*loc, &before, &after)); } } - - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } else { @@ -615,7 +622,8 @@ Editor::sequence_regions () if (!rs.empty()) { - begin_reversible_command (_("sequence regions")); + bool in_command = false; + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { boost::shared_ptr r ((*i)->region()); @@ -635,13 +643,20 @@ Editor::sequence_regions () r->set_position(r_end_prev); } + if (!in_command) { + begin_reversible_command (_("sequence regions")); + in_command = true; + } _session->add_command (new StatefulDiffCommand (r)); r_end=r->position() + r->length(); iCount++; } - commit_reversible_command (); + + if (in_command) { + commit_reversible_command (); + } } } @@ -2172,10 +2187,7 @@ void Editor::remove_location_at_playhead_cursor () { if (_session) { - //set up for undo - begin_reversible_command (_("remove marker")); - XMLNode &before = _session->locations()->get_state(); bool removed = false; @@ -2191,9 +2203,9 @@ Editor::remove_location_at_playhead_cursor () //store undo if (removed) { + begin_reversible_command (_("remove marker")); XMLNode &after = _session->locations()->get_state(); _session->add_command(new MementoCommand(*(_session->locations()), &before, &after)); - commit_reversible_command (); } } @@ -2208,8 +2220,7 @@ Editor::add_locations_from_region () if (rs.empty()) { return; } - - begin_reversible_command (selection->regions.size () > 1 ? _("add markers") : _("add marker")); + bool commit = false; XMLNode &before = _session->locations()->get_state(); @@ -2220,12 +2231,15 @@ Editor::add_locations_from_region () Location *location = new Location (*_session, region->position(), region->last_frame(), region->name(), Location::IsRangeMarker); _session->locations()->add (location, true); + commit = true; } - XMLNode &after = _session->locations()->get_state(); - _session->add_command (new MementoCommand(*(_session->locations()), &before, &after)); - - commit_reversible_command (); + if (commit) { + begin_reversible_command (selection->regions.size () > 1 ? _("add markers") : _("add marker")); + XMLNode &after = _session->locations()->get_state(); + _session->add_command (new MementoCommand(*(_session->locations()), &before, &after)); + commit_reversible_command (); + } } /** Add a single range marker around all selected regions */ @@ -2238,8 +2252,6 @@ Editor::add_location_from_region () return; } - begin_reversible_command (_("add marker")); - XMLNode &before = _session->locations()->get_state(); string markername; @@ -2260,9 +2272,9 @@ Editor::add_location_from_region () Location *location = new Location (*_session, selection->regions.start(), selection->regions.end_frame(), markername, Location::IsRangeMarker); _session->locations()->add (location, true); + begin_reversible_command (_("add marker")); XMLNode &after = _session->locations()->get_state(); _session->add_command (new MementoCommand(*(_session->locations()), &before, &after)); - commit_reversible_command (); } @@ -3264,8 +3276,7 @@ Editor::crop_region_to (framepos_t start, framepos_t end) framepos_t the_start; framepos_t the_end; framepos_t cnt; - - begin_reversible_command (_("trim to selection")); + bool in_command = false; for (vector >::iterator i = playlists.begin(); i != playlists.end(); ++i) { @@ -3290,12 +3301,18 @@ Editor::crop_region_to (framepos_t start, framepos_t end) the_end = min (end, the_end); cnt = the_end - the_start + 1; + if(!in_command) { + begin_reversible_command (_("trim to selection")); + in_command = true; + } region->clear_changes (); region->trim_to (the_start, cnt); _session->add_command (new StatefulDiffCommand (region)); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -3308,8 +3325,8 @@ Editor::region_fill_track () } framepos_t const end = _session->current_end_frame (); - - begin_reversible_command (Operations::region_fill); + RegionSelection foo; + bool in_command = false; for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { @@ -3318,21 +3335,39 @@ Editor::region_fill_track () boost::shared_ptr pl = region->playlist(); if (end <= region->last_frame()) { - return; + continue; } double times = (double) (end - region->last_frame()) / (double) region->length(); if (times == 0) { - return; + continue; + } + + if (!in_command) { + begin_reversible_command (Operations::region_fill); + in_command = true; } + TimeAxisView& tv = (*i)->get_time_axis_view(); + RouteTimeAxisView* rtv = dynamic_cast (&tv); + latest_regionviews.clear (); + sigc::connection c = rtv->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view)); pl->clear_changes (); pl->add_region (RegionFactory::create (region, true), region->last_frame(), times); _session->add_command (new StatefulDiffCommand (pl)); + + c.disconnect (); + + foo.insert (foo.end(), latest_regionviews.begin(), latest_regionviews.end()); } - commit_reversible_command (); + if (in_command) { + if (!foo.empty()) { + selection->set (foo); + } + commit_reversible_command (); + } } void @@ -3362,10 +3397,10 @@ Editor::region_fill_selection () framepos_t selection_length = end - start; float times = (float)selection_length / region->length(); - - begin_reversible_command (Operations::fill_selection); + bool in_command = false; TrackViewList ts = selection->tracks.filter_to_unique_playlists (); + RegionSelection foo; for (TrackViewList::iterator i = ts.begin(); i != ts.end(); ++i) { @@ -3373,12 +3408,27 @@ Editor::region_fill_selection () continue; } + if (!in_command) { + begin_reversible_command (Operations::fill_selection); + in_command = true; + } + RouteTimeAxisView* rtv = dynamic_cast (*i); + latest_regionviews.clear (); + sigc::connection c = rtv->view()->RegionViewAdded.connect (sigc::mem_fun(*this, &Editor::collect_new_region_view)); + playlist->clear_changes (); playlist->add_region (RegionFactory::create (region, true), start, times); _session->add_command (new StatefulDiffCommand (playlist)); + c.disconnect (); + foo.insert (foo.end(), latest_regionviews.begin(), latest_regionviews.end()); } - commit_reversible_command (); + if (in_command) { + if (!foo.empty()) { + selection->set (foo); + } + commit_reversible_command (); + } } void @@ -3676,8 +3726,7 @@ void Editor::trim_region_to_location (const Location& loc, const char* str) { RegionSelection rs = get_regions_from_selection_and_entered (); - - begin_reversible_command (str); + bool in_command = false; for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { RegionView* rv = (*x); @@ -3708,10 +3757,17 @@ Editor::trim_region_to_location (const Location& loc, const char* str) rv->region()->clear_changes (); rv->region()->trim_to (start, (end - start)); + + if (!in_command) { + begin_reversible_command (str); + in_command = true; + } _session->add_command(new StatefulDiffCommand (rv->region())); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -3730,8 +3786,7 @@ void Editor::trim_to_region(bool forward) { RegionSelection rs = get_regions_from_selection_and_entered (); - - begin_reversible_command (_("trim to region")); + bool in_command = false; boost::shared_ptr next_region; @@ -3746,7 +3801,7 @@ Editor::trim_to_region(bool forward) AudioTimeAxisView* atav = dynamic_cast (&arv->get_time_axis_view()); if (!atav) { - return; + continue; } float speed = 1.0; @@ -3785,10 +3840,16 @@ Editor::trim_to_region(bool forward) arv->region_changed (ARDOUR::bounds_change); } + if (!in_command) { + begin_reversible_command (_("trim to region")); + in_command = true; + } _session->add_command(new StatefulDiffCommand (region)); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -3913,8 +3974,7 @@ Editor::bounce_range_selection (bool replace, bool enable_processing) framepos_t start = selection->time[clicked_selection].start; framepos_t end = selection->time[clicked_selection].end; framepos_t cnt = end - start + 1; - - begin_reversible_command (_("bounce range")); + bool in_command = false; for (TrackViewList::iterator i = views.begin(); i != views.end(); ++i) { @@ -3927,7 +3987,7 @@ Editor::bounce_range_selection (bool replace, bool enable_processing) boost::shared_ptr playlist; if ((playlist = rtv->playlist()) == 0) { - return; + continue; } InterThreadInfo itt; @@ -3954,6 +4014,10 @@ Editor::bounce_range_selection (bool replace, bool enable_processing) playlist->add_region (r, start); } + if (!in_command) { + begin_reversible_command (_("bounce range")); + in_command = true; + } vector cmds; playlist->rdiff (cmds); _session->add_commands (cmds); @@ -3961,7 +4025,9 @@ Editor::bounce_range_selection (bool replace, bool enable_processing) _session->add_command (new StatefulDiffCommand (playlist)); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } /** Delete selected regions, automation points or a time range */ @@ -4315,8 +4381,6 @@ Editor::remove_selected_regions () return; } - begin_reversible_command (_("remove region")); - list > regions_to_remove; for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { @@ -4360,6 +4424,7 @@ Editor::remove_selected_regions () } vector >::iterator pl; + bool in_command = false; for (pl = playlists.begin(); pl != playlists.end(); ++pl) { (*pl)->thaw (); @@ -4367,6 +4432,11 @@ Editor::remove_selected_regions () /* We might have removed regions, which alters other regions' layering_index, so we need to do a recursive diff here. */ + + if (!in_command) { + begin_reversible_command (_("remove region")); + in_command = true; + } vector cmds; (*pl)->rdiff (cmds); _session->add_commands (cmds); @@ -4374,7 +4444,9 @@ Editor::remove_selected_regions () _session->add_command(new StatefulDiffCommand (*pl)); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } /** Cut, copy or clear selected regions. @@ -4710,6 +4782,10 @@ Editor::paste_internal (framepos_t position, float times) void Editor::duplicate_some_regions (RegionSelection& regions, float times) { + if (regions.empty ()) { + return; + } + boost::shared_ptr playlist; RegionSelection sel = regions; // clear (below) may clear the argument list if its the current region selection RegionSelection foo; @@ -4764,11 +4840,10 @@ Editor::duplicate_selection (float times) return; } - begin_reversible_command (_("duplicate selection")); - ri = new_regions.begin(); TrackViewList ts = selection->tracks.filter_to_unique_playlists (); + bool in_command = false; for (TrackViewList::iterator i = ts.begin(); i != ts.end(); ++i) { if ((playlist = (*i)->playlist()) == 0) { @@ -4782,6 +4857,11 @@ Editor::duplicate_selection (float times) end = selection->time.end_frame(); } playlist->duplicate (*ri, end, times); + + if (!in_command) { + begin_reversible_command (_("duplicate selection")); + in_command = true; + } _session->add_command (new StatefulDiffCommand (playlist)); ++ri; @@ -4790,7 +4870,9 @@ Editor::duplicate_selection (float times) } } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } /** Reset all selected points to the relevant default value */ @@ -4848,9 +4930,8 @@ Editor::nudge_track (bool use_edit, bool forwards) return; } - begin_reversible_command (_("nudge track")); - TrackViewList ts = selection->tracks.filter_to_unique_playlists (); + bool in_command = false; for (TrackViewList::iterator i = ts.begin(); i != ts.end(); ++i) { @@ -4863,6 +4944,10 @@ Editor::nudge_track (bool use_edit, bool forwards) playlist->nudge_after (start, distance, forwards); + if (!in_command) { + begin_reversible_command (_("nudge track")); + in_command = true; + } vector cmds; playlist->rdiff (cmds); @@ -4871,7 +4956,9 @@ Editor::nudge_track (bool use_edit, bool forwards) _session->add_command (new StatefulDiffCommand (playlist)); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -4951,9 +5038,8 @@ Editor::normalize_region () } } - begin_reversible_command (_("normalize")); - list::const_iterator a = max_amps.begin (); + bool in_command = false; for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { AudioRegionView* const arv = dynamic_cast (*r); @@ -4966,12 +5052,19 @@ Editor::normalize_region () double const amp = dialog.normalize_individually() ? *a : max_amp; arv->audio_region()->normalize (amp, dialog.target ()); + + if (!in_command) { + begin_reversible_command (_("normalize")); + in_command = true; + } _session->add_command (new StatefulDiffCommand (arv->region())); ++a; } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } @@ -4988,7 +5081,7 @@ Editor::reset_region_scale_amplitude () return; } - begin_reversible_command ("reset gain"); + bool in_command = false; for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { AudioRegionView* const arv = dynamic_cast(*r); @@ -4996,10 +5089,17 @@ Editor::reset_region_scale_amplitude () continue; arv->region()->clear_changes (); arv->audio_region()->set_scale_amplitude (1.0f); + + if(!in_command) { + begin_reversible_command ("reset gain"); + in_command = true; + } _session->add_command (new StatefulDiffCommand (arv->region())); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -5011,7 +5111,7 @@ Editor::adjust_region_gain (bool up) return; } - begin_reversible_command ("adjust region gain"); + bool in_command = false; for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ++r) { AudioRegionView* const arv = dynamic_cast(*r); @@ -5030,10 +5130,17 @@ Editor::adjust_region_gain (bool up) } arv->audio_region()->set_scale_amplitude (dB_to_coefficient (dB)); + + if (!in_command) { + begin_reversible_command ("adjust region gain"); + in_command = true; + } _session->add_command (new StatefulDiffCommand (arv->region())); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } @@ -5105,7 +5212,7 @@ Editor::apply_midi_note_edit_op (MidiOperator& op, const RegionSelection& rs) return; } - begin_reversible_command (op.name ()); + bool in_command = false; for (RegionSelection::const_iterator r = rs.begin(); r != rs.end(); ) { RegionSelection::const_iterator tmp = r; @@ -5116,6 +5223,10 @@ Editor::apply_midi_note_edit_op (MidiOperator& op, const RegionSelection& rs) if (mrv) { Command* cmd = apply_midi_note_edit_op_to_region (op, *mrv); if (cmd) { + if (!in_command) { + begin_reversible_command (op.name ()); + in_command = true; + } (*cmd)(); _session->add_command (cmd); } @@ -5124,7 +5235,9 @@ Editor::apply_midi_note_edit_op (MidiOperator& op, const RegionSelection& rs) r = tmp; } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -5136,9 +5249,9 @@ Editor::fork_region () return; } - begin_reversible_command (_("Fork Region(s)")); - CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait); + bool in_command = false; + gdk_flush (); for (RegionSelection::iterator r = rs.begin(); r != rs.end(); ) { @@ -5152,7 +5265,11 @@ Editor::fork_region () boost::shared_ptr playlist = mrv->region()->playlist(); boost::shared_ptr new_source = _session->create_midi_source_by_stealing_name (mrv->midi_view()->track()); boost::shared_ptr newregion = mrv->midi_region()->clone (new_source); - + + if (!in_command) { + begin_reversible_command (_("Fork Region(s)")); + in_command = true; + } playlist->clear_changes (); playlist->replace_region (mrv->region(), newregion, mrv->region()->position()); _session->add_command(new StatefulDiffCommand (playlist)); @@ -5164,7 +5281,9 @@ Editor::fork_region () r = tmp; } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -5292,9 +5411,9 @@ Editor::apply_filter (Filter& filter, string command, ProgressReporter* progress return; } - begin_reversible_command (command); - CursorContext::Handle cursor_ctx = CursorContext::create(*this, _cursors->wait); + bool in_command = false; + gdk_flush (); int n = 0; @@ -5337,17 +5456,22 @@ Editor::apply_filter (Filter& filter, string command, ProgressReporter* progress } } - /* We might have removed regions, which alters other regions' layering_index, so we need to do a recursive diff here. */ + + if (!in_command) { + begin_reversible_command (command); + in_command = true; + } vector cmds; playlist->rdiff (cmds); _session->add_commands (cmds); _session->add_command(new StatefulDiffCommand (playlist)); + } else { - return; + continue; } if (progress) { @@ -5359,7 +5483,9 @@ Editor::apply_filter (Filter& filter, string command, ProgressReporter* progress ++n; } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -5377,7 +5503,7 @@ Editor::reset_region_gain_envelopes () return; } - begin_reversible_command (_("reset region gain")); + bool in_command = false; for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { AudioRegionView* const arv = dynamic_cast(*i); @@ -5386,11 +5512,18 @@ Editor::reset_region_gain_envelopes () XMLNode& before (alist->get_state()); arv->audio_region()->set_default_envelope (); + + if (!in_command) { + begin_reversible_command (_("reset region gain")); + in_command = true; + } _session->add_command (new MementoCommand(*arv->audio_region()->envelope().get(), &before, &alist->get_state())); } } - - commit_reversible_command (); + + if (in_command) { + commit_reversible_command (); + } } void @@ -5430,18 +5563,25 @@ Editor::toggle_gain_envelope_active () return; } - begin_reversible_command (_("region gain envelope active")); - + bool in_command = false; + for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { AudioRegionView* const arv = dynamic_cast(*i); if (arv) { arv->region()->clear_changes (); arv->audio_region()->set_envelope_active (!arv->audio_region()->envelope_active()); + + if (!in_command) { + begin_reversible_command (_("region gain envelope active")); + in_command = true; + } _session->add_command (new StatefulDiffCommand (arv->region())); } } - - commit_reversible_command (); + + if (in_command) { + commit_reversible_command (); + } } void @@ -5671,13 +5811,13 @@ Editor::set_fade_length (bool in) cmd = _("set fade out length"); } - begin_reversible_command (cmd); + bool in_command = false; for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { AudioRegionView* tmp = dynamic_cast (*x); if (!tmp) { - return; + continue; } boost::shared_ptr alist; @@ -5697,11 +5837,17 @@ Editor::set_fade_length (bool in) tmp->audio_region()->set_fade_out_active (true); } + if (!in_command) { + begin_reversible_command (cmd); + in_command = true; + } XMLNode &after = alist->get_state(); _session->add_command(new MementoCommand(*alist, &before, &after)); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -5712,14 +5858,13 @@ Editor::set_fade_in_shape (FadeShape shape) if (rs.empty()) { return; } - - begin_reversible_command (_("set fade in shape")); + bool in_command = false; for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { AudioRegionView* tmp = dynamic_cast (*x); if (!tmp) { - return; + continue; } boost::shared_ptr alist = tmp->audio_region()->fade_in(); @@ -5727,12 +5872,17 @@ Editor::set_fade_in_shape (FadeShape shape) tmp->audio_region()->set_fade_in_shape (shape); + if (!in_command) { + begin_reversible_command (_("set fade in shape")); + in_command = true; + } XMLNode &after = alist->get_state(); _session->add_command(new MementoCommand(*alist.get(), &before, &after)); } - commit_reversible_command (); - + if (in_command) { + commit_reversible_command (); + } } void @@ -5743,14 +5893,13 @@ Editor::set_fade_out_shape (FadeShape shape) if (rs.empty()) { return; } - - begin_reversible_command (_("set fade out shape")); + bool in_command = false; for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { AudioRegionView* tmp = dynamic_cast (*x); if (!tmp) { - return; + continue; } boost::shared_ptr alist = tmp->audio_region()->fade_out(); @@ -5758,11 +5907,17 @@ Editor::set_fade_out_shape (FadeShape shape) tmp->audio_region()->set_fade_out_shape (shape); + if(!in_command) { + begin_reversible_command (_("set fade out shape")); + in_command = true; + } XMLNode &after = alist->get_state(); _session->add_command(new MementoCommand(*alist.get(), &before, &after)); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -5773,14 +5928,13 @@ Editor::set_fade_in_active (bool yn) if (rs.empty()) { return; } - - begin_reversible_command (_("set fade in active")); + bool in_command = false; for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { AudioRegionView* tmp = dynamic_cast (*x); if (!tmp) { - return; + continue; } @@ -5788,10 +5942,17 @@ Editor::set_fade_in_active (bool yn) ar->clear_changes (); ar->set_fade_in_active (yn); + + if (!in_command) { + begin_reversible_command (_("set fade in active")); + in_command = true; + } _session->add_command (new StatefulDiffCommand (ar)); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -5802,24 +5963,30 @@ Editor::set_fade_out_active (bool yn) if (rs.empty()) { return; } - - begin_reversible_command (_("set fade out active")); + bool in_command = false; for (RegionSelection::iterator x = rs.begin(); x != rs.end(); ++x) { AudioRegionView* tmp = dynamic_cast (*x); if (!tmp) { - return; + continue; } boost::shared_ptr ar (tmp->audio_region()); ar->clear_changes (); ar->set_fade_out_active (yn); + + if (!in_command) { + begin_reversible_command (_("set fade out active")); + in_command = true; + } _session->add_command(new StatefulDiffCommand (ar)); } - commit_reversible_command (); + if (in_command) { + commit_reversible_command (); + } } void @@ -5855,11 +6022,14 @@ Editor::toggle_region_fades (int dir) } /* XXX should this undo-able? */ + bool in_command = false; for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) { if ((ar = boost::dynamic_pointer_cast((*i)->region())) == 0) { continue; } + ar->clear_changes (); + if (dir == 1 || dir == 0) { ar->set_fade_in_active (!yn); } @@ -5867,6 +6037,15 @@ Editor::toggle_region_fades (int dir) if (dir == -1 || dir == 0) { ar->set_fade_out_active (!yn); } + if (!in_command) { + begin_reversible_command (_("toggle fade active")); + in_command = true; + } + _session->add_command(new StatefulDiffCommand (ar)); + } + + if (in_command) { + commit_reversible_command (); } } @@ -6964,13 +7143,11 @@ Editor::insert_time ( bool all_playlists, bool ignore_music_glue, bool markers_too, bool glued_markers_too, bool locked_markers_too, bool tempo_too ) { - bool commit = false; if (Config->get_edit_mode() == Lock) { return; } - - begin_reversible_command (_("insert time")); + bool in_command = false; TrackViewList ts = selection->tracks.filter_to_unique_playlists (); @@ -7010,19 +7187,25 @@ Editor::insert_time ( (*i)->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue); + if (!in_command) { + begin_reversible_command (_("insert time")); + in_command = true; + } vector cmds; (*i)->rdiff (cmds); _session->add_commands (cmds); _session->add_command (new StatefulDiffCommand (*i)); - commit = true; } /* automation */ RouteTimeAxisView* rtav = dynamic_cast (*x); if (rtav) { + if (!in_command) { + begin_reversible_command (_("insert time")); + in_command = true; + } rtav->route ()->shift (pos, frames); - commit = true; } } @@ -7058,16 +7241,27 @@ Editor::insert_time ( } if (moved) { + if (!in_command) { + begin_reversible_command (_("insert time")); + in_command = true; + } XMLNode& after (_session->locations()->get_state()); _session->add_command (new MementoCommand(*_session->locations(), &before, &after)); } } if (tempo_too) { + if (!in_command) { + begin_reversible_command (_("insert time")); + in_command = true; + } + XMLNode& before (_session->tempo_map().get_state()); _session->tempo_map().insert_time (pos, frames); + XMLNode& after (_session->tempo_map().get_state()); + _session->add_command (new MementoCommand(_session->tempo_map(), &before, &after)); } - if (commit) { + if (in_command) { commit_reversible_command (); } } @@ -7110,14 +7304,11 @@ void Editor::remove_time (framepos_t pos, framecnt_t frames, InsertTimeOption opt, bool ignore_music_glue, bool markers_too, bool glued_markers_too, bool locked_markers_too, bool tempo_too) { - bool commit = false; - if (Config->get_edit_mode() == Lock) { error << (_("Cannot insert or delete time when in Lock edit.")) << endmsg; return; } - - begin_reversible_command (_("cut time")); + bool in_command = false; for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) { /* regions */ @@ -7133,17 +7324,23 @@ Editor::remove_time (framepos_t pos, framecnt_t frames, InsertTimeOption opt, pl->cut (rl); pl->shift (pos, -frames, true, ignore_music_glue); + if (!in_command) { + begin_reversible_command (_("cut time")); + in_command = true; + } XMLNode &after = pl->get_state(); _session->add_command (new MementoCommand (*pl, &before, &after)); - commit = true; } /* automation */ RouteTimeAxisView* rtav = dynamic_cast (*x); if (rtav) { + if (!in_command) { + begin_reversible_command (_("cut time")); + in_command = true; + } rtav->route ()->shift (pos, -frames); - commit = true; } } @@ -7212,23 +7409,29 @@ Editor::remove_time (framepos_t pos, framecnt_t frames, InsertTimeOption opt, } if (moved) { + if (!in_command) { + begin_reversible_command (_("cut time")); + in_command = true; + } XMLNode& after (_session->locations()->get_state()); _session->add_command (new MementoCommand(*_session->locations(), &before, &after)); - commit = true; } } if (tempo_too) { XMLNode& before (_session->tempo_map().get_state()); - if (_session->tempo_map().remove_time (pos, frames) ) { + if (_session->tempo_map().cut_time (pos, frames) ) { + if (!in_command) { + begin_reversible_command (_("cut time")); + in_command = true; + } XMLNode& after (_session->tempo_map().get_state()); _session->add_command (new MementoCommand(_session->tempo_map(), &before, &after)); - commit = true; } } - if (commit) { + if (in_command) { commit_reversible_command (); } } diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc index 5bb777d739..44794313a0 100644 --- a/gtk2_ardour/editor_selection.cc +++ b/gtk2_ardour/editor_selection.cc @@ -326,19 +326,23 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation if (!clicked_control_point) { return false; } + bool ret = false; switch (op) { case Selection::Set: if (press) { selection->set (clicked_control_point); + ret = true; } break; case Selection::Add: if (press) { selection->add (clicked_control_point); + ret = true; } break; case Selection::Toggle: + /* This is a bit of a hack; if we Primary-Click-Drag a control point (for push drag) we want the point we clicked on to be selected, otherwise we end up confusingly dragging an @@ -353,9 +357,11 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation */ selection->toggle (clicked_control_point); _control_point_toggled_on_press = true; + ret = true; } else if (!press && !_control_point_toggled_on_press) { /* This is the release, and the point wasn't toggled on the press, so do it now */ selection->toggle (clicked_control_point); + ret = true; } else { /* Reset our flag */ _control_point_toggled_on_press = false; @@ -366,7 +372,7 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation break; } - return true; + return ret; } void diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc index 2025ec70c3..5908e50249 100644 --- a/gtk2_ardour/editor_timefx.cc +++ b/gtk2_ardour/editor_timefx.cc @@ -133,6 +133,8 @@ Editor::pitch_shift (RegionSelection& regions, float fraction) if (ret == 0) { commit_reversible_command (); + } else { + abort_reversible_command (); } return ret; diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index be475216c1..e412b82c32 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -1509,8 +1509,9 @@ boost::shared_ptr MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit) { Editor* real_editor = dynamic_cast (&_editor); - - real_editor->begin_reversible_command (Operations::create_region); + if (commit) { + real_editor->begin_reversible_command (Operations::create_region); + } playlist()->clear_changes (); real_editor->snap_to (pos, RoundNearest); diff --git a/gtk2_ardour/region_editor.cc b/gtk2_ardour/region_editor.cc index 16888fb688..e41e012ce6 100644 --- a/gtk2_ardour/region_editor.cc +++ b/gtk2_ardour/region_editor.cc @@ -270,33 +270,41 @@ RegionEditor::connect_editor_events () void RegionEditor::position_clock_changed () { - PublicEditor::instance().begin_reversible_command (_("change region start position")); - + bool in_command = false; boost::shared_ptr pl = _region->playlist(); if (pl) { + PublicEditor::instance().begin_reversible_command (_("change region start position")); + in_command = true; + _region->clear_changes (); _region->set_position (position_clock.current_time()); _session->add_command(new StatefulDiffCommand (_region)); } - PublicEditor::instance().commit_reversible_command (); + if (in_command) { + PublicEditor::instance().commit_reversible_command (); + } } void RegionEditor::end_clock_changed () { - PublicEditor::instance().begin_reversible_command (_("change region end position")); - + bool in_command = false; boost::shared_ptr pl = _region->playlist(); if (pl) { + PublicEditor::instance().begin_reversible_command (_("change region end position")); + in_command = true; + _region->clear_changes (); _region->trim_end (end_clock.current_time()); _session->add_command(new StatefulDiffCommand (_region)); } - PublicEditor::instance().commit_reversible_command (); + if (in_command) { + PublicEditor::instance().commit_reversible_command (); + } end_clock.set (_region->position() + _region->length() - 1, true); } @@ -305,18 +313,21 @@ void RegionEditor::length_clock_changed () { framecnt_t frames = length_clock.current_time(); - - PublicEditor::instance().begin_reversible_command (_("change region length")); - + bool in_command = false; boost::shared_ptr pl = _region->playlist(); if (pl) { - _region->clear_changes (); + PublicEditor::instance().begin_reversible_command (_("change region length")); + in_command = true; + + _region->clear_changes (); _region->trim_end (_region->position() + frames - 1); _session->add_command(new StatefulDiffCommand (_region)); } - PublicEditor::instance().commit_reversible_command (); + if (in_command) { + PublicEditor::instance().commit_reversible_command (); + } length_clock.set (_region->length()); } diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index 7f112b9546..94ed2a86f0 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -59,6 +59,7 @@ #include "ardour_ui.h" #include "ardour_button.h" +#include "audio_streamview.h" #include "debug.h" #include "global_signals.h" #include "route_time_axis.h" @@ -1342,6 +1343,10 @@ RouteTimeAxisView::set_selected_points (PointSelection& points) for (Children::iterator i = children.begin(); i != children.end(); ++i) { (*i)->set_selected_points (points); } + AudioStreamView* asv = dynamic_cast(_view); + if (asv) { + asv->set_selected_points (points); + } } void diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h index 24a9e0de3e..5d73e4aef9 100644 --- a/libs/ardour/ardour/automation_control.h +++ b/libs/ardour/ardour/automation_control.h @@ -101,6 +101,7 @@ protected: ARDOUR::Session& _session; const ParameterDescriptor _desc; + XMLNode* _before; //used for undo of touch start/stop pairs. }; diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc index 21952038cf..bfb1046849 100644 --- a/libs/ardour/automation_control.cc +++ b/libs/ardour/automation_control.cc @@ -19,12 +19,15 @@ */ #include - #include "ardour/automation_control.h" #include "ardour/automation_watch.h" #include "ardour/event_type_map.h" #include "ardour/session.h" +#include "pbd/memento_command.h" + +#include "i18n.h" + using namespace std; using namespace ARDOUR; using namespace PBD; @@ -85,6 +88,8 @@ AutomationControl::set_automation_state (AutoState as) } if (as == Write) { + /* get state for undo */ + _before = &alist ()->get_state (); AutomationWatch::instance().add_automation_watch (shared_from_this()); } else if (as == Touch) { if (!touching()) { @@ -113,9 +118,16 @@ AutomationControl::set_automation_style (AutoStyle as) void AutomationControl::start_touch(double when) { - if (!_list) return; + if (!_list) { + return; + } + if (!touching()) { + if (alist()->automation_state() == Touch) { + /* subtle. aligns the user value with the playback */ + set_value (get_value ()); + _before = &alist ()->get_state (); alist()->start_touch (when); if (!_desc.toggled) { AutomationWatch::instance().add_automation_watch (shared_from_this()); @@ -131,11 +143,22 @@ AutomationControl::stop_touch(bool mark, double when) if (!_list) return; if (touching()) { set_touching (false); + + if (alist()->automation_state() == Write) { + _session.begin_reversible_command (string_compose (_("write %1 automation"), name ())); + _session.add_command (new MementoCommand (*alist ().get (), _before, &alist ()->get_state ())); + _session.commit_reversible_command (); + } + if (alist()->automation_state() == Touch) { alist()->stop_touch (mark, when); if (!_desc.toggled) { AutomationWatch::instance().remove_automation_watch (shared_from_this()); } + + _session.begin_reversible_command (string_compose (_("touch %1 automation"), name ())); + _session.add_command (new MementoCommand (*alist ().get (), _before, &alist ()->get_state ())); + _session.commit_reversible_command (); } } } diff --git a/libs/ardour/automation_list.cc b/libs/ardour/automation_list.cc index 7f7599f8ca..706a3330a7 100644 --- a/libs/ardour/automation_list.cc +++ b/libs/ardour/automation_list.cc @@ -276,7 +276,11 @@ AutomationList::state (bool full) if (_state != Write) { root->add_property ("state", auto_state_to_string (_state)); } else { - root->add_property ("state", auto_state_to_string (Off)); + if (_events.empty ()) { + root->add_property ("state", auto_state_to_string (Off)); + } else { + root->add_property ("state", auto_state_to_string (Touch)); + } } } else { /* never save anything but Off for automation state to a template */ diff --git a/libs/ardour/automation_watch.cc b/libs/ardour/automation_watch.cc index 4e833fceb5..3714f17502 100644 --- a/libs/ardour/automation_watch.cc +++ b/libs/ardour/automation_watch.cc @@ -128,7 +128,7 @@ AutomationWatch::timer () (*aw)->list()->add (time, (*aw)->user_double(), true); } } - } else { //transport stopped or reversed. stop the automation pass and start a new one (for bonus points, someday store the previous pass in an undo record) + } else if (time != _last_time) { //transport stopped or reversed. stop the automation pass and start a new one (for bonus points, someday store the previous pass in an undo record) for (AutomationWatches::iterator aw = automation_watches.begin(); aw != automation_watches.end(); ++aw) { DEBUG_TRACE (DEBUG::Automation, string_compose ("%1: transport in rewind, speed %2, in write pass ? %3 writing ? %4\n", (*aw)->name(), _session->transport_speed(), _session->transport_rolling(), diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp index 7a828264bd..82868cd24c 100644 --- a/libs/evoral/evoral/ControlList.hpp +++ b/libs/evoral/evoral/ControlList.hpp @@ -124,8 +124,8 @@ public: void slide (iterator before, double distance); void shift (double before, double distance); - virtual void add (double when, double value, bool with_guards=true, bool with_default=true); - virtual void editor_add (double when, double value); + virtual void add (double when, double value, bool with_guards=true, bool with_initial=true); + virtual void editor_add (double when, double value, bool with_guard); void fast_simple_add (double when, double value); diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp index a2f3aa4f33..5118744c05 100644 --- a/libs/evoral/src/ControlList.cpp +++ b/libs/evoral/src/ControlList.cpp @@ -399,7 +399,7 @@ ControlList::add_guard_point (double when) most_recent_insert_iterator = lower_bound (_events.begin(), _events.end(), &cp, time_comparator); double eval_value = unlocked_eval (insert_position); - + if (most_recent_insert_iterator == _events.end()) { DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 insert iterator at end, adding eval-value there %2\n", this, eval_value)); @@ -407,7 +407,7 @@ ControlList::add_guard_point (double when) /* leave insert iterator at the end */ } else if ((*most_recent_insert_iterator)->when == when) { - + DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 insert iterator at existing point, setting eval-value there %2\n", this, eval_value)); /* most_recent_insert_iterator points to a control event @@ -415,15 +415,15 @@ ControlList::add_guard_point (double when) nothing to do. ... except ... - + advance most_recent_insert_iterator so that the "real" insert occurs in the right place, since it points to the control event just inserted. */ - + ++most_recent_insert_iterator; } else { - + /* insert a new control event at the right spot */ @@ -431,7 +431,7 @@ ControlList::add_guard_point (double when) this, eval_value, (*most_recent_insert_iterator)->when)); most_recent_insert_iterator = _events.insert (most_recent_insert_iterator, new ControlEvent (when, eval_value)); - + /* advance most_recent_insert_iterator so that the "real" * insert occurs in the right place, since it * points to the control event just inserted. @@ -452,7 +452,7 @@ ControlList::in_write_pass () const } void -ControlList::editor_add (double when, double value) +ControlList::editor_add (double when, double value, bool with_guard) { /* this is for making changes from a graphical line editor */ @@ -464,11 +464,19 @@ ControlList::editor_add (double when, double value) */ if (when >= 1) { - _events.insert (_events.end(), new ControlEvent (0, _default_value)); - DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 added default value %2 at zero\n", this, _default_value)); + _events.insert (_events.end(), new ControlEvent (0, value)); + DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 added value %2 at zero\n", this, value)); } } + insert_position = when; + if (with_guard) { + if (when > 64) { + add_guard_point (when - 64); + } + maybe_add_insert_guard (when); + } + ControlEvent cp (when, 0.0f); iterator i = lower_bound (_events.begin(), _events.end(), &cp, time_comparator); DEBUG_TRACE (DEBUG::ControlList, string_compose ("editor_add: actually add when= %1 value= %2\n", when, value)); @@ -491,9 +499,9 @@ ControlList::maybe_add_insert_guard (double when) new control point so that our insert will happen correctly. */ most_recent_insert_iterator = _events.insert ( most_recent_insert_iterator, - new ControlEvent (when + 1, (*most_recent_insert_iterator)->value)); + new ControlEvent (when + 64, (*most_recent_insert_iterator)->value)); DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 added insert guard point @ %2 = %3\n", - this, when+1, + this, when + 64, (*most_recent_insert_iterator)->value)); } } @@ -546,7 +554,7 @@ ControlList::erase_from_iterator_to (iterator iter, double when) } void -ControlList::add (double when, double value, bool with_guards, bool with_default) +ControlList::add (double when, double value, bool with_guards, bool with_initial) { /* this is for making changes from some kind of user interface or control surface (GUI, MIDI, OSC etc) @@ -561,12 +569,12 @@ ControlList::add (double when, double value, bool with_guards, bool with_default ControlEvent cp (when, 0.0f); iterator insertion_point; - if (_events.empty() && with_default) { + if (_events.empty() && with_initial) { /* empty: add an "anchor" point if the point we're adding past time 0 */ if (when >= 1) { - _events.insert (_events.end(), new ControlEvent (0, _default_value)); + _events.insert (_events.end(), new ControlEvent (0, value)); DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 added default value %2 at zero\n", this, _default_value)); } } @@ -628,10 +636,10 @@ ControlList::add (double when, double value, bool with_guards, bool with_default if ((*most_recent_insert_iterator)->value != value) { DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 reset existing point to new value %2\n", this, value)); - /* only one point allowed per time point, so just - * reset the value here. + /* only one point allowed per time point, so add a guard point + * before it if needed then reset the value of the point. */ - + (*most_recent_insert_iterator)->value = value; /* if we modified the final value, then its as @@ -649,10 +657,35 @@ ControlList::add (double when, double value, bool with_guards, bool with_default } else { DEBUG_TRACE (DEBUG::ControlList, string_compose ("@%1 insert new point at %2 at iterator at %3\n", this, when, (*most_recent_insert_iterator)->when)); - - const bool done = maybe_insert_straight_line (when, value); + bool done = false; + /* check for possible straight line here until maybe_insert_straight_line () handles the insert iterator properly*/ + if (most_recent_insert_iterator != _events.begin ()) { + bool have_point2 = false; + --most_recent_insert_iterator; + const bool have_point1 = (*most_recent_insert_iterator)->value == value; + + if (most_recent_insert_iterator != _events.begin ()) { + --most_recent_insert_iterator; + have_point2 = (*most_recent_insert_iterator)->value == value; + ++most_recent_insert_iterator; + } + + if (have_point1 && have_point2) { + (*most_recent_insert_iterator)->when = when; + done = true; + } else { + ++most_recent_insert_iterator; + } + } + //done = maybe_insert_straight_line (when, value) || done; + /* if the transport is stopped, add guard points (?) */ + if (!done && !_in_write_pass && when > 64) { + add_guard_point (when - 64); + maybe_add_insert_guard (when); + } + if (with_guards) { - maybe_add_insert_guard(when); + maybe_add_insert_guard (when); } if (!done) { diff --git a/libs/gtkmm2ext/gtkmm2ext/pixfader.h b/libs/gtkmm2ext/gtkmm2ext/pixfader.h index f137a4ed65..0a316340b4 100644 --- a/libs/gtkmm2ext/gtkmm2ext/pixfader.h +++ b/libs/gtkmm2ext/gtkmm2ext/pixfader.h @@ -58,6 +58,7 @@ class LIBGTKMM2EXT_API PixFader : public CairoWidget void on_size_allocate (Gtk::Allocation& alloc); void render (cairo_t *, cairo_rectangle_t*); + bool on_grab_broken_event (GdkEventGrabBroken*); bool on_button_press_event (GdkEventButton*); bool on_button_release_event (GdkEventButton*); bool on_motion_notify_event (GdkEventMotion*); diff --git a/libs/gtkmm2ext/pixfader.cc b/libs/gtkmm2ext/pixfader.cc index b140d7b56b..1e814fd147 100644 --- a/libs/gtkmm2ext/pixfader.cc +++ b/libs/gtkmm2ext/pixfader.cc @@ -71,7 +71,7 @@ PixFader::PixFader (Gtk::Adjustment& adj, int orientation, int fader_length, int _adjustment.signal_value_changed().connect (mem_fun (*this, &PixFader::adjustment_changed)); _adjustment.signal_changed().connect (mem_fun (*this, &PixFader::adjustment_changed)); - + signal_grab_broken_event ().connect (mem_fun (*this, &PixFader::on_grab_broken_event)); if (_orien == VERT) { CairoWidget::set_size_request(_girth, _span); } else { @@ -365,6 +365,18 @@ PixFader::on_size_allocate (Gtk::Allocation& alloc) update_unity_position (); } +bool +PixFader::on_grab_broken_event (GdkEventGrabBroken* ev) +{ + if (_dragging) { + remove_modal_grab(); + _dragging = false; + gdk_pointer_ungrab (GDK_CURRENT_TIME); + StopGesture (); + } + return (_tweaks & NoButtonForward) ? true : false; +} + bool PixFader::on_button_press_event (GdkEventButton* ev) {