summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Loftis <ben@harrisonconsoles.com>2015-07-16 16:13:24 -0500
committerBen Loftis <ben@harrisonconsoles.com>2015-07-16 16:13:24 -0500
commit46c83693284ece4a732d26e62113ea4ac584d539 (patch)
tree6e191e809b84b1c4d2aa36af6e8878996a109332
parentedce75973c076ab1fa66cc6d601a30fcbbcd5dd4 (diff)
parentd9c0aa4236796d981a5d939bbc5d0d5a2e1910fe (diff)
merge fix
-rw-r--r--gtk2_ardour/audio_region_view.cc2
-rw-r--r--gtk2_ardour/audio_streamview.cc12
-rw-r--r--gtk2_ardour/audio_streamview.h2
-rw-r--r--gtk2_ardour/automation_controller.cc2
-rw-r--r--gtk2_ardour/automation_line.cc8
-rw-r--r--gtk2_ardour/automation_region_view.cc2
-rw-r--r--gtk2_ardour/automation_time_axis.cc6
-rw-r--r--gtk2_ardour/editor_canvas.cc2
-rw-r--r--gtk2_ardour/editor_canvas_events.cc5
-rw-r--r--gtk2_ardour/editor_drag.cc181
-rw-r--r--gtk2_ardour/editor_drag.h2
-rw-r--r--gtk2_ardour/editor_mouse.cc22
-rw-r--r--gtk2_ardour/editor_ops.cc439
-rw-r--r--gtk2_ardour/editor_selection.cc8
-rw-r--r--gtk2_ardour/editor_timefx.cc2
-rw-r--r--gtk2_ardour/midi_time_axis.cc5
-rw-r--r--gtk2_ardour/region_editor.cc33
-rw-r--r--gtk2_ardour/route_time_axis.cc5
-rw-r--r--libs/ardour/ardour/automation_control.h1
-rw-r--r--libs/ardour/automation_control.cc27
-rw-r--r--libs/ardour/automation_list.cc6
-rw-r--r--libs/ardour/automation_watch.cc2
-rw-r--r--libs/evoral/evoral/ControlList.hpp4
-rw-r--r--libs/evoral/src/ControlList.cpp73
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/pixfader.h1
-rw-r--r--libs/gtkmm2ext/pixfader.cc14
26 files changed, 611 insertions, 255 deletions
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<AudioRegion>(*(audio_region().get()), &region_before, &region_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<AutomationList>(*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<RegionView *>::iterator i = region_views.begin(); i != region_views.end(); ++i) {
+ AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*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 <boost/weak_ptr.hpp>
#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<AudioRegionView*>, std::list<AudioRegionView*> > hide_xfades_with (boost::shared_ptr<ARDOUR::AudioRegion> ar);
RegionView* create_region_view (boost::shared_ptr<ARDOUR::Region>, 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<AutomationList> (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<AutomationList> (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<ControlPoint*> cp, float fraction, XMLNode* state)
{
- trackview.editor().begin_reversible_command (_("automation range move"));
trackview.editor().session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), state, 0));
@@ -678,6 +675,7 @@ AutomationLine::drag_motion (double const x, float fraction, bool ignore_x, bool
for (vector<CCP>::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<double, float> (_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<ControlPoint*>::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<ARDOUR::AutomationList> (*list, &before, &after));
+ _session->add_command (new MementoCommand<ARDOUR::AutomationList> (*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<RouteTimeAxisView*>(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<DraggingView> 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<RouteTimeAxisView*> 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<boost::shared_ptr<Playlist>, 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<MidiRegionView*>(*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<MidiRegionView*>(*r);
+ if (mrv) {
+ mrv->begin_resizing (at_front);
+ }
+ r = next;
+ }
+ }
+
for (MidiRegionSelection::iterator r = ms.begin(); r != ms.end(); ++r) {
NoteBase* nb = reinterpret_cast<NoteBase*> (_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<NoteBase*> (_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<DraggingView>::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<AutomationList>(*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<DraggingView>::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<AutomationList>(*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<Locations>(*(_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<Locations>(*(_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<AutomationTimeAxisView*>(_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<Line>::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<Line>::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<Line>::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> 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<Location>(*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<Location>(*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<Region> 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<Locations>(*(_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<Locations>(*(_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<Locations>(*(_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<Locations>(*(_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<boost::shared_ptr<Playlist> >::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<Playlist> 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<RouteTimeAxisView*> (&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<RouteTimeAxisView*> (*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<Region> next_region;
@@ -3746,7 +3801,7 @@ Editor::trim_to_region(bool forward)
AudioTimeAxisView* atav = dynamic_cast<AudioTimeAxisView*> (&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> 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<Command*> 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<boost::shared_ptr<Region> > regions_to_remove;
for (RegionSelection::iterator i = rs.begin(); i != rs.end(); ++i) {
@@ -4360,6 +4424,7 @@ Editor::remove_selected_regions ()
}
vector<boost::shared_ptr<Playlist> >::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<Command*> 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> 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<Command*> 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<double>::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<AudioRegionView*> (*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<AudioRegionView*>(*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<AudioRegionView*>(*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> playlist = mrv->region()->playlist();
boost::shared_ptr<MidiSource> new_source = _session->create_midi_source_by_stealing_name (mrv->midi_view()->track());
boost::shared_ptr<MidiRegion> 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<Command*> 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<AudioRegionView*>(*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<AutomationList>(*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<AudioRegionView*>(*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<AudioRegionView*> (*x);
if (!tmp) {
- return;
+ continue;
}
boost::shared_ptr<AutomationList> 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<AutomationList>(*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<AudioRegionView*> (*x);
if (!tmp) {
- return;
+ continue;
}
boost::shared_ptr<AutomationList> 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<AutomationList>(*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<AudioRegionView*> (*x);
if (!tmp) {
- return;
+ continue;
}
boost::shared_ptr<AutomationList> 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<AutomationList>(*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<AudioRegionView*> (*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<AudioRegionView*> (*x);
if (!tmp) {
- return;
+ continue;
}
boost::shared_ptr<AudioRegion> 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<AudioRegion>((*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<Command*> cmds;
(*i)->rdiff (cmds);
_session->add_commands (cmds);
_session->add_command (new StatefulDiffCommand (*i));
- commit = true;
}
/* automation */
RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*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<Locations>(*_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<TempoMap>(_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<Playlist> (*pl, &before, &after));
- commit = true;
}
/* automation */
RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*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<Locations>(*_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<TempoMap>(_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<MidiRegion>
MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit)
{
Editor* real_editor = dynamic_cast<Editor*> (&_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<Playlist> 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<Playlist> 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<Playlist> 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<AudioStreamView*>(_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 <iostream>
-
#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<AutomationList> (*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<AutomationList> (*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 {
@@ -366,6 +366,18 @@ PixFader::on_size_allocate (Gtk::Allocation& alloc)
}
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)
{
if (ev->type != GDK_BUTTON_PRESS) {