summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/audio_region_view.cc27
-rw-r--r--gtk2_ardour/automation_region_view.cc13
-rw-r--r--gtk2_ardour/automation_time_axis.cc17
-rw-r--r--gtk2_ardour/editor_drag.cc159
-rw-r--r--gtk2_ardour/editor_mouse.cc55
-rw-r--r--gtk2_ardour/editor_selection.cc14
-rw-r--r--gtk2_ardour/selection.cc2
-rw-r--r--libs/evoral/evoral/ControlList.hpp3
-rw-r--r--libs/evoral/src/ControlList.cpp20
9 files changed, 209 insertions, 101 deletions
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index 706611a81d..dd15529019 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -1334,25 +1334,40 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
gain_line->view_to_model_coord (x, y);
+ trackview.editor ().snap_to_with_modifier (fx, ev);
+
/* XXX STATEFUL: can't convert to stateful diff until we
can represent automation data with it.
*/
- trackview.editor().begin_reversible_command (_("add gain control point"));
XMLNode &before = audio_region()->envelope()->get_state();
+ MementoCommand<AudioRegion>* region_memento = 0;
if (!audio_region()->envelope_active()) {
XMLNode &region_before = audio_region()->get_state();
audio_region()->set_envelope_active(true);
XMLNode &region_after = audio_region()->get_state();
- trackview.session()->add_command (new MementoCommand<AudioRegion>(*(audio_region().get()), &region_before, &region_after));
+ region_memento = new MementoCommand<AudioRegion>(*(audio_region().get()), &region_before, &region_after);
}
- audio_region()->envelope()->editor_add (fx, y, with_guard_points);
+ if (audio_region()->envelope()->editor_add (fx, y, with_guard_points)) {
+ XMLNode &after = audio_region()->envelope()->get_state();
+ std::list<Selectable*> results;
+
+ trackview.editor().begin_reversible_command (_("add gain control point"));
+
+ if (region_memento) {
+ trackview.session()->add_command (region_memento);
+ }
- XMLNode &after = audio_region()->envelope()->get_state();
- trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after));
- trackview.editor().commit_reversible_command ();
+ trackview.session()->add_command (new MementoCommand<AutomationList>(*audio_region()->envelope().get(), &before, &after));
+
+ gain_line->get_selectables (fx, fx, 0.0, 1.0, results);
+ trackview.editor ().get_selection ().set (results);
+
+ trackview.editor ().commit_reversible_command ();
+ trackview.session ()->set_dirty ();
+ }
}
void
diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc
index 5450815329..f1f9d68b98 100644
--- a/gtk2_ardour/automation_region_view.cc
+++ b/gtk2_ardour/automation_region_view.cc
@@ -187,17 +187,18 @@ AutomationRegionView::add_automation_event (GdkEvent *, framepos_t when, double
double when_d = when;
_line->view_to_model_coord (when_d, y);
- view->editor().begin_reversible_command (_("add automation event"));
XMLNode& before = _line->the_list()->get_state();
- _line->the_list()->editor_add (when_d, y, with_guard_points);
+ if (_line->the_list()->editor_add (when_d, y, with_guard_points)) {
+ view->editor().begin_reversible_command (_("add automation event"));
- XMLNode& after = _line->the_list()->get_state();
+ XMLNode& after = _line->the_list()->get_state();
- view->session()->add_command (new MementoCommand<ARDOUR::AutomationList> (_line->memento_command_binder(), &before, &after));
- view->editor().commit_reversible_command ();
+ view->session()->add_command (new MementoCommand<ARDOUR::AutomationList> (_line->memento_command_binder(), &before, &after));
+ view->editor().commit_reversible_command ();
- view->session()->set_dirty ();
+ view->session()->set_dirty ();
+ }
}
bool
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index 1c79593b34..1ff3024ac6 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -638,18 +638,21 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when,
_line->view_to_model_coord (x, y);
-
_editor.snap_to_with_modifier (when, event);
- _editor.begin_reversible_command (_("add automation event"));
XMLNode& before = list->get_state();
+ std::list<Selectable*> results;
+ if (list->editor_add (when, y, with_guard_points)) {
+ XMLNode& after = list->get_state();
+ _editor.begin_reversible_command (_("add automation event"));
+ _session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
- list->editor_add (when, y, with_guard_points);
+ _line->get_selectables (when, when, 0.0, 1.0, results);
+ _editor.get_selection ().set (results);
- XMLNode& after = list->get_state();
- _session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
- _editor.commit_reversible_command ();
- _session->set_dirty ();
+ _editor.commit_reversible_command ();
+ _session->set_dirty ();
+ }
}
bool
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 90e4dc48e4..d3e40adf12 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -5557,108 +5557,123 @@ AutomationRangeDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
}
}
- } else {
+ }
- for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) {
+ if (_nothing_to_drag) {
+ return;
+ }
+}
- framecnt_t const half = (i->start + i->end) / 2;
+void
+AutomationRangeDrag::motion (GdkEvent*, bool first_move)
+{
+ if (_nothing_to_drag && !first_move) {
+ return;
+ }
- /* find the line that this audio range starts in */
- list<Line>::iterator j = _lines.begin();
- while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) {
- ++j;
- }
+ if (first_move) {
+ _editor->begin_reversible_command (_("automation range move"));
+
+ if (!_ranges.empty()) {
- if (j != _lines.end()) {
- boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
+ for (list<AudioRange>::const_iterator i = _ranges.begin(); i != _ranges.end(); ++i) {
+
+ framecnt_t const half = (i->start + i->end) / 2;
+
+ /* find the line that this audio range starts in */
+ list<Line>::iterator j = _lines.begin();
+ while (j != _lines.end() && (j->range.first > i->start || j->range.second < i->start)) {
+ ++j;
+ }
+
+ if (j != _lines.end()) {
+ boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
/* j is the line that this audio range starts in; fade into it;
64 samples length plucked out of thin air.
*/
- framepos_t a = i->start + 64;
- if (a > half) {
- a = half;
- }
+ framepos_t a = i->start + 64;
+ if (a > half) {
+ a = half;
+ }
- 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 ());
+ 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), false);
- the_list->editor_add (q, value (the_list, q), false);
- }
+ XMLNode &before = the_list->get_state();
+ bool const add_p = the_list->editor_add (p, value (the_list, p), false);
+ bool const add_q = the_list->editor_add (q, value (the_list, q), false);
- /* same thing for the end */
+ if (add_p || add_q) {
+ _editor->session()->add_command (
+ new MementoCommand<AutomationList>(*the_list.get (), &before, &the_list->get_state()));
+ }
+ }
- j = _lines.begin();
- while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) {
- ++j;
- }
+ /* same thing for the end */
- if (j != _lines.end()) {
- boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
+ j = _lines.begin();
+ while (j != _lines.end() && (j->range.first > i->end || j->range.second < i->end)) {
+ ++j;
+ }
- /* j is the line that this audio range starts in; fade out of it;
- 64 samples length plucked out of thin air.
- */
+ if (j != _lines.end()) {
+ boost::shared_ptr<AutomationList> the_list = j->line->the_list ();
- framepos_t b = i->end - 64;
- if (b < half) {
- b = half;
- }
+ /* j is the line that this audio range starts in; fade out of it;
+ 64 samples length plucked out of thin air.
+ */
- 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 ());
+ framepos_t b = i->end - 64;
+ if (b < half) {
+ b = half;
+ }
+
+ 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), false);
- the_list->editor_add (q, value (the_list, q), false);
+ XMLNode &before = the_list->get_state();
+ bool const add_p = the_list->editor_add (p, value (the_list, p), false);
+ bool const add_q = the_list->editor_add (q, value (the_list, q), false);
+
+ if (add_p || add_q) {
+ _editor->session()->add_command (
+ new MementoCommand<AutomationList>(*the_list.get (), &before, &the_list->get_state()));
+ }
+ }
}
- }
- _nothing_to_drag = true;
+ _nothing_to_drag = true;
- /* Find all the points that should be dragged and put them in the relevant
- points lists in the Line structs.
- */
+ /* Find all the points that should be dragged and put them in the relevant
+ points lists in the Line structs.
+ */
- for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
+ for (list<Line>::iterator i = _lines.begin(); i != _lines.end(); ++i) {
- uint32_t const N = i->line->npoints ();
- for (uint32_t j = 0; j < N; ++j) {
+ uint32_t const N = i->line->npoints ();
+ for (uint32_t j = 0; j < N; ++j) {
- /* here's a control point on this line */
- ControlPoint* p = i->line->nth (j);
- double const w = i->line->time_converter().to ((*p->model())->when) + i->line->time_converter().origin_b ();
+ /* here's a control point on this line */
+ ControlPoint* p = i->line->nth (j);
+ double const w = i->line->time_converter().to ((*p->model())->when) + i->line->time_converter().origin_b ();
- /* see if it's inside a range */
- list<AudioRange>::const_iterator k = _ranges.begin ();
- while (k != _ranges.end() && (k->start >= w || k->end <= w)) {
- ++k;
- }
+ /* see if it's inside a range */
+ list<AudioRange>::const_iterator k = _ranges.begin ();
+ while (k != _ranges.end() && (k->start >= w || k->end <= w)) {
+ ++k;
+ }
- if (k != _ranges.end()) {
- /* dragging this point */
- _nothing_to_drag = false;
- i->points.push_back (p);
+ if (k != _ranges.end()) {
+ /* dragging this point */
+ _nothing_to_drag = false;
+ i->points.push_back (p);
+ }
}
}
}
- }
- if (_nothing_to_drag) {
- return;
- }
-}
-
-void
-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);
}
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index ccf63839e2..b4e4cc81af 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -399,8 +399,9 @@ Editor::step_mouse_mode (bool next)
}
void
-Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemType item_type)
+Editor::button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
+
/* in object/audition/timefx/gain-automation mode,
any button press sets the selection if the object
can be selected. this is a bit of hack, because
@@ -472,6 +473,9 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
switch (item_type) {
case RegionItem:
+ if (eff_mouse_mode == MouseDraw) {
+ break;
+ }
if (press) {
if (eff_mouse_mode != MouseRange) {
_mouse_changed_selection = set_selected_regionview_from_click (press, op);
@@ -519,6 +523,51 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
}
break;
+ case GainLineItem:
+ case AutomationLineItem:
+ if (eff_mouse_mode != MouseRange) {
+ AutomationLine* al;
+ std::list<Selectable*> selectables;
+ uint32_t before, after;
+ framecnt_t const where = (framecnt_t) floor (event->button.x * samples_per_pixel);
+
+ if ((al = reinterpret_cast<AutomationLine*> (item->get_data ("line")))) {
+
+ if (!al->control_points_adjacent (where, before, after)) {
+ break;
+ }
+ }
+
+ selectables.push_back (al->nth (before));
+ selectables.push_back (al->nth (after));
+
+ switch (op) {
+ case Selection::Set:
+ if (press) {
+ selection->set (selectables);
+ _mouse_changed_selection = true;
+ }
+ break;
+ case Selection::Add:
+ if (press) {
+ selection->add (selectables);
+ _mouse_changed_selection = true;
+ }
+ break;
+ case Selection::Toggle:
+ if (press) {
+ selection->toggle (selectables);
+ _mouse_changed_selection = true;
+ }
+ break;
+
+ case Selection::Extend:
+ /* XXX */
+ break;
+ }
+ }
+ break;
+
case StreamItem:
/* for context click, select track */
if (event->button.button == 3) {
@@ -532,7 +581,9 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
break;
case AutomationTrackItem:
- set_selected_track_as_side_effect (op);
+ if (eff_mouse_mode != MouseDraw) {
+ set_selected_track_as_side_effect (op);
+ }
break;
default:
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index 3a6277ecec..27e17d5fcc 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -327,15 +327,27 @@ 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) {
+ if (!selection->selected (clicked_control_point)) {
selection->set (clicked_control_point);
ret = true;
+ } else {
+ /* clicked on an already selected point */
+ if (press) {
+ break;
+ } else {
+ if (selection->points.size() > 1) {
+ selection->set (clicked_control_point);
+ ret = true;
+ }
+ }
}
break;
+
case Selection::Add:
if (press) {
selection->add (clicked_control_point);
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
index 784f646f39..822aca0384 100644
--- a/gtk2_ardour/selection.cc
+++ b/gtk2_ardour/selection.cc
@@ -1113,7 +1113,7 @@ Selection::set (ControlPoint* cp)
clear_time (); //enforce region/object exclusivity
clear_tracks(); //enforce object/track exclusivity
- if (cp->get_selected()) {
+ if (cp->get_selected () && points.size () == 1) {
return;
}
diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp
index 3784b25720..80096b65a4 100644
--- a/libs/evoral/evoral/ControlList.hpp
+++ b/libs/evoral/evoral/ControlList.hpp
@@ -125,7 +125,8 @@ public:
void shift (double before, double distance);
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);
+
+ virtual bool 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 d8665d3396..d9c1b993bd 100644
--- a/libs/evoral/src/ControlList.cpp
+++ b/libs/evoral/src/ControlList.cpp
@@ -451,12 +451,19 @@ ControlList::in_write_pass () const
return _in_write_pass;
}
-void
+bool
ControlList::editor_add (double when, double value, bool with_guard)
{
/* this is for making changes from a graphical line editor
*/
+ ControlEvent cp (when, 0.0f);
+ iterator i = lower_bound (_events.begin(), _events.end(), &cp, time_comparator);
+
+ if (i != _events.end () && (*i)->when == when) {
+ return false;
+ }
+
if (_events.empty()) {
/* as long as the point we're adding is not at zero,
@@ -477,15 +484,18 @@ ControlList::editor_add (double when, double value, bool with_guard)
maybe_add_insert_guard (when);
}
- ControlEvent cp (when, 0.0f);
- iterator i = lower_bound (_events.begin(), _events.end(), &cp, time_comparator);
+ iterator result;
DEBUG_TRACE (DEBUG::ControlList, string_compose ("editor_add: actually add when= %1 value= %2\n", when, value));
- _events.insert (i, new ControlEvent (when, value));
+ result = _events.insert (i, new ControlEvent (when, value));
- mark_dirty ();
+ if (i == result) {
+ return false;
+ }
+ mark_dirty ();
maybe_signal_changed ();
+ return true;
}
void