summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authornick_m <mainsbridge@gmail.com>2015-01-11 04:07:31 +1100
committernick_m <mainsbridge@gmail.com>2015-01-11 04:07:31 +1100
commit44203ce955f33135065456f55f1f685131174ba6 (patch)
tree623864e0e94e7d1fb59c5ee24bdbd16f551aee4b /gtk2_ardour
parent9e873acedb35ee0077f128a2da1648b65c78eeeb (diff)
Fix AutomationTrackItem rubberband click thinking it was unhandled.
Fix several other cases where a single mouse click could cause several (not nested) selection ops. Fix missing selection memento for midi notes and midi commands. Rename some variables. Fix random style issues.
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/automation_line.cc2
-rw-r--r--gtk2_ardour/editor.cc56
-rw-r--r--gtk2_ardour/editor.h4
-rw-r--r--gtk2_ardour/editor_canvas_events.cc4
-rw-r--r--gtk2_ardour/editor_drag.cc26
-rw-r--r--gtk2_ardour/editor_mouse.cc25
-rw-r--r--gtk2_ardour/editor_selection.cc14
-rw-r--r--gtk2_ardour/midi_region_view.cc102
-rw-r--r--gtk2_ardour/midi_region_view.h7
-rw-r--r--gtk2_ardour/midi_time_axis.cc41
-rw-r--r--gtk2_ardour/midi_time_axis.h11
-rw-r--r--gtk2_ardour/public_editor.h6
-rw-r--r--gtk2_ardour/selection.cc141
-rw-r--r--gtk2_ardour/selection.h2
14 files changed, 375 insertions, 66 deletions
diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc
index c0ed14f7f9..d5ed529ad8 100644
--- a/gtk2_ardour/automation_line.cc
+++ b/gtk2_ardour/automation_line.cc
@@ -156,7 +156,7 @@ void
AutomationLine::update_visibility ()
{
if (_visible & Line) {
- /* Only show the line there are some points, otherwise we may show an out-of-date line
+ /* Only show the line when there are some points, otherwise we may show an out-of-date line
when automation points have been removed (the line will still follow the shape of the
old points).
*/
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index da1c25f374..b18d6d6fb8 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -81,7 +81,6 @@
#include "control_protocol/control_protocol.h"
#include "actions.h"
-#include "actions.h"
#include "analysis_window.h"
#include "audio_clock.h"
#include "audio_region_view.h"
@@ -251,6 +250,7 @@ pane_size_watcher (Paned* pane)
Editor::Editor ()
: _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
+ , _mouse_changed_selection (false)
/* time display buttons */
, minsec_label (_("Mins:Secs"))
, bbt_label (_("Bars:Beats"))
@@ -3336,7 +3336,7 @@ void
Editor::begin_reversible_selection_op (string name)
{
if (_session) {
- //cerr << name << endl;
+ cerr << name << endl;
/* begin/commit pairs can be nested */
selection_op_cmd_depth++;
}
@@ -3349,20 +3349,22 @@ Editor::commit_reversible_selection_op ()
if (selection_op_cmd_depth == 1) {
if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
+ /* the user has undone some selection ops and then made a new one */
list<XMLNode *>::iterator it = selection_op_history.begin();
advance (it, selection_op_history_it);
selection_op_history.erase (selection_op_history.begin(), it);
}
+
selection_op_history.push_front (&_selection_memento->get_state ());
selection_op_history_it = 0;
+
+ selection_undo_action->set_sensitive (true);
+ selection_redo_action->set_sensitive (false);
}
if (selection_op_cmd_depth > 0) {
selection_op_cmd_depth--;
}
-
- selection_undo_action->set_sensitive (true);
- selection_redo_action->set_sensitive (false);
}
}
@@ -3378,7 +3380,6 @@ Editor::undo_selection_op ()
selection_redo_action->set_sensitive (true);
}
++n;
-
}
/* is there an earlier entry? */
if ((selection_op_history_it + 1) >= selection_op_history.size()) {
@@ -3401,7 +3402,6 @@ Editor::redo_selection_op ()
selection_undo_action->set_sensitive (true);
}
++n;
-
}
if (selection_op_history_it == 0) {
@@ -4899,17 +4899,17 @@ Editor::get_regions_from_selection_and_entered ()
}
void
-Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) const
+Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
{
for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
- RouteTimeAxisView* tatv;
+ RouteTimeAxisView* rtav;
- if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
+ if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
boost::shared_ptr<Playlist> pl;
std::vector<boost::shared_ptr<Region> > results;
boost::shared_ptr<Track> tr;
- if ((tr = tatv->track()) == 0) {
+ if ((tr = rtav->track()) == 0) {
/* bus */
continue;
}
@@ -4917,9 +4917,9 @@ Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) co
if ((pl = (tr->playlist())) != 0) {
boost::shared_ptr<Region> r = pl->region_by_id (id);
if (r) {
- RegionView* marv = tatv->view()->find_view (r);
- if (marv) {
- regions.push_back (marv);
+ RegionView* rv = rtav->view()->find_view (r);
+ if (rv) {
+ regions.push_back (rv);
}
}
}
@@ -4928,6 +4928,21 @@ Editor::get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) co
}
void
+Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
+{
+
+ for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ MidiTimeAxisView* mtav;
+
+ if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
+
+ mtav->get_per_region_note_selection (selection);
+ }
+ }
+
+}
+
+void
Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
{
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
@@ -5102,6 +5117,19 @@ Editor::region_view_added (RegionView * rv)
break;
}
}
+
+ MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
+ if (mrv) {
+ list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
+ for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
+ if (rv->region()->id () == (*rnote).first) {
+ mrv->select_notes ((*rnote).second);
+ selection->pending_midi_note_selection.erase(rnote);
+ break;
+ }
+ }
+ }
+
_summary->set_background_dirty ();
}
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 77d28f4e12..7e1d1702f0 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -421,7 +421,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void get_regions_corresponding_to (boost::shared_ptr<ARDOUR::Region> region, std::vector<RegionView*>& regions, bool src_comparison);
- void get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) const;
+ void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const;
+ void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >&) const;
void center_screen (framepos_t);
@@ -706,6 +707,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);
bool button_release_can_deselect;
+ bool _mouse_changed_selection;
void catch_vanishing_regionview (RegionView *);
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
index 93c0abea35..c1696c9f6c 100644
--- a/gtk2_ardour/editor_canvas_events.cc
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -178,7 +178,9 @@ Editor::canvas_scroll_event (GdkEventScroll *event, bool from_canvas)
bool
Editor::track_canvas_button_press_event (GdkEventButton */*event*/)
{
+ begin_reversible_selection_op (_("Clear Selection Click (track canvas)"));
selection->clear ();
+ commit_reversible_selection_op();
_track_canvas->grab_focus();
return false;
}
@@ -1105,8 +1107,10 @@ Editor::canvas_drop_zone_event (GdkEvent* event)
switch (event->type) {
case GDK_BUTTON_RELEASE:
if (event->button.button == 1) {
+ begin_reversible_selection_op (_("Nowhere Click"));
selection->clear_objects ();
selection->clear_tracks ();
+ commit_reversible_selection_op ();
}
break;
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 9cf0f05b60..aef59ed19e 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -4718,6 +4718,9 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
} else {
_region->unique_select (_primary);
}
+
+ _editor->begin_reversible_selection_op(_("Select Note Press"));
+ _editor->commit_reversible_selection_op();
}
}
}
@@ -4799,14 +4802,17 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
{
if (!moved) {
/* no motion - select note */
-
+
if (_editor->current_mouse_mode() == Editing::MouseObject ||
_editor->current_mouse_mode() == Editing::MouseDraw) {
-
+
+ bool changed = false;
+
if (_was_selected) {
bool add = Keyboard::modifier_state_equals (ev->button.state, Keyboard::PrimaryModifier);
if (add) {
_region->note_deselected (_primary);
+ changed = true;
}
} else {
bool extend = Keyboard::modifier_state_equals (ev->button.state, Keyboard::TertiaryModifier);
@@ -4814,12 +4820,19 @@ NoteDrag::finished (GdkEvent* ev, bool moved)
if (!extend && !add && _region->selection_size() > 1) {
_region->unique_select (_primary);
+ changed = true;
} else if (extend) {
_region->note_selected (_primary, true, true);
+ changed = true;
} else {
/* it was added during button press */
}
}
+
+ if (changed) {
+ _editor->begin_reversible_selection_op(_("Select Note Release"));
+ _editor->commit_reversible_selection_op();
+ }
}
} else {
_region->note_dropped (_primary, total_dx(), total_dy());
@@ -5204,12 +5217,15 @@ EditorRubberbandSelectDrag::select_things (int button_state, framepos_t x1, fram
void
EditorRubberbandSelectDrag::deselect_things ()
{
- if (!getenv("ARDOUR_SAE")) {
- _editor->selection->clear_tracks();
- }
+ _editor->begin_reversible_selection_op (_("Clear Selection (rubberband)"));
+
+ _editor->selection->clear_tracks();
_editor->selection->clear_regions();
_editor->selection->clear_points ();
_editor->selection->clear_lines ();
+ _editor->selection->clear_midi_notes ();
+
+ _editor->commit_reversible_selection_op();
}
NoteCreateDrag::NoteCreateDrag (Editor* e, ArdourCanvas::Item* i, MidiRegionView* rv)
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index e093eb5426..b781832618 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -448,11 +448,15 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
bool press = (event->type == GDK_BUTTON_PRESS);
+ if (press) {
+ _mouse_changed_selection = false;
+ }
+
switch (item_type) {
case RegionItem:
if (press) {
if (eff_mouse_mode != MouseRange) {
- set_selected_regionview_from_click (press, op);
+ _mouse_changed_selection = set_selected_regionview_from_click (press, op);
} else {
/* don't change the selection unless the
clicked track is not currently selected. if
@@ -465,7 +469,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
}
} else {
if (eff_mouse_mode != MouseRange) {
- set_selected_regionview_from_click (press, op);
+ _mouse_changed_selection = set_selected_regionview_from_click (press, op);
}
}
break;
@@ -483,7 +487,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
case StartCrossFadeItem:
case EndCrossFadeItem:
if (get_smart_mode() || eff_mouse_mode != MouseRange) {
- set_selected_regionview_from_click (press, op);
+ _mouse_changed_selection = set_selected_regionview_from_click (press, op);
} else if (event->type == GDK_BUTTON_PRESS) {
set_selected_track_as_side_effect (op);
}
@@ -492,7 +496,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
case ControlPointItem:
set_selected_track_as_side_effect (op);
if (eff_mouse_mode != MouseRange) {
- set_selected_control_point_from_click (press, op);
+ _mouse_changed_selection = set_selected_control_point_from_click (press, op);
}
break;
@@ -501,6 +505,7 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
if (event->button.button == 3) {
selection->clear_tracks ();
set_selected_track_as_side_effect (op);
+ _mouse_changed_selection = true;
}
break;
@@ -511,6 +516,12 @@ Editor::button_selection (ArdourCanvas::Item* /*item*/, GdkEvent* event, ItemTyp
default:
break;
}
+
+ if ((!press) && _mouse_changed_selection) {
+ begin_reversible_selection_op (_("Button Selection"));
+ commit_reversible_selection_op ();
+ _mouse_changed_selection = false;
+ }
}
bool
@@ -744,6 +755,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case AutomationTrackItem:
/* rubberband drag to select automation points */
_drags->set (new EditorRubberbandSelectDrag (this, item), event);
+ return true;
break;
default:
@@ -1465,10 +1477,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
}
/* do any (de)selection operations that should occur on button release */
-
- begin_reversible_selection_op (_("Button Select"));
- button_selection (item, event, item_type);
- commit_reversible_selection_op ();
+ button_selection (item, event, item_type);
return true;
break;
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index 60f8b0433b..c46ef04a64 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -202,8 +202,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
}
} else if (group && group->is_active()) {
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
- if ((*i)->route_group() == group)
+ if ((*i)->route_group() == group) {
selection->remove(*i);
+ }
}
} else {
selection->remove (clicked_axisview);
@@ -215,8 +216,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
}
} else if (group && group->is_active()) {
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
- if ( (*i)->route_group() == group)
+ if ((*i)->route_group() == group) {
selection->add(*i);
+ }
}
} else {
selection->add (clicked_axisview);
@@ -234,8 +236,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
}
} else if (group && group->is_active()) {
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
- if ((*i)->route_group() == group)
+ if ((*i)->route_group() == group) {
selection->add(*i);
+ }
}
} else {
selection->add (clicked_axisview);
@@ -253,8 +256,9 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
}
} else if (group && group->is_active()) {
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
- if ((*i)->route_group() == group)
+ if ((*i)->route_group() == group) {
selection->add(*i);
+ }
}
} else {
selection->set (clicked_axisview);
@@ -1953,7 +1957,7 @@ Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const
void
Editor::deselect_all ()
{
- begin_reversible_selection_op(_("Clear Selection"));
+ begin_reversible_selection_op(_("Deselect All"));
selection->clear ();
commit_reversible_selection_op ();
}
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index 97cb11529e..6e257cc0ee 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -123,6 +123,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
+ , _mouse_changed_selection (false)
{
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
_note_group->raise_to_top();
@@ -169,6 +170,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
+ , _mouse_changed_selection (false)
{
CANVAS_DEBUG_NAME (_note_group, string_compose ("note group for %1", get_item_name()));
_note_group->raise_to_top();
@@ -220,6 +222,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
+ , _mouse_changed_selection (false)
{
init (false);
}
@@ -250,6 +253,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
, _last_event_y (0)
, _grabbed_keyboard (false)
, _entered (false)
+ , _mouse_changed_selection (false)
{
init (true);
}
@@ -502,6 +506,7 @@ MidiRegionView::button_press (GdkEventButton* ev)
}
_pressed_button = ev->button;
+ _mouse_changed_selection = false;
return true;
}
@@ -532,12 +537,14 @@ MidiRegionView::button_release (GdkEventButton* ev)
case MouseRange:
/* no motion occured - simple click */
clear_selection ();
+ _mouse_changed_selection = true;
break;
case MouseContent:
case MouseTimeFX:
{
clear_selection();
+ _mouse_changed_selection = true;
if (Keyboard::is_insert_note_event(ev)) {
@@ -591,6 +598,11 @@ MidiRegionView::button_release (GdkEventButton* ev)
break;
}
+ if(_mouse_changed_selection) {
+ trackview.editor().begin_reversible_selection_op (_("Mouse Selection Change"));
+ trackview.editor().commit_reversible_selection_op ();
+ }
+
return false;
}
@@ -643,6 +655,7 @@ MidiRegionView::motion (GdkEventMotion* ev)
editor.drags()->set (new MidiRubberbandSelectDrag (dynamic_cast<Editor *> (&editor), this), (GdkEvent *) ev);
if (!Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
clear_selection ();
+ _mouse_changed_selection = true;
}
_mouse_state = SelectRectDragging;
return true;
@@ -747,22 +760,32 @@ MidiRegionView::key_press (GdkEventKey* ev)
} else if (ev->keyval == GDK_Tab) {
+ trackview.editor().begin_reversible_selection_op (_("Select Adjacent Note"));
+
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
} else {
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
}
+
+ trackview.editor().commit_reversible_selection_op();
+
return true;
} else if (ev->keyval == GDK_ISO_Left_Tab) {
/* Shift-TAB generates ISO Left Tab, for some reason */
+ trackview.editor().begin_reversible_selection_op (_("Select Adjacent Note"));
+
if (Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier)) {
goto_previous_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
} else {
goto_next_note (Keyboard::modifier_state_contains (ev->state, Keyboard::TertiaryModifier));
}
+
+ trackview.editor().commit_reversible_selection_op();
+
return true;
@@ -946,9 +969,11 @@ MidiRegionView::create_note_at (framepos_t t, double y, Evoral::Beats length, bo
view->update_note_range(new_note->note());
+ trackview.editor().begin_reversible_command(_("add note"));
MidiModel::NoteDiffCommand* cmd = _model->new_note_diff_command(_("add note"));
cmd->add (new_note);
_model->apply_command(*trackview.session(), cmd);
+ trackview.editor().commit_reversible_command();
play_midi_note (new_note);
}
@@ -982,8 +1007,8 @@ MidiRegionView::display_model(boost::shared_ptr<MidiModel> model)
content_connection.disconnect ();
_model->ContentsChanged.connect (content_connection, invalidator (*this), boost::bind (&MidiRegionView::redisplay_model, this), gui_context());
-
- clear_events ();
+ /* Don't signal as nobody else needs to know until selection has been altered.*/
+ clear_events (false);
if (_enable_display) {
redisplay_model();
@@ -994,6 +1019,7 @@ void
MidiRegionView::start_note_diff_command (string name)
{
if (!_note_diff_command) {
+ trackview.editor().begin_reversible_command (name);
_note_diff_command = _model->new_note_diff_command (name);
}
}
@@ -1044,6 +1070,7 @@ void
MidiRegionView::apply_diff (bool as_subcommand)
{
bool add_or_remove;
+ bool commit = false;
if (!_note_diff_command) {
return;
@@ -1060,6 +1087,7 @@ MidiRegionView::apply_diff (bool as_subcommand)
_model->apply_command_as_subcommand (*trackview.session(), _note_diff_command);
} else {
_model->apply_command (*trackview.session(), _note_diff_command);
+ commit = true;
}
_note_diff_command = 0;
@@ -1070,6 +1098,9 @@ MidiRegionView::apply_diff (bool as_subcommand)
}
_marked_for_velocity.clear();
+ if (commit) {
+ trackview.editor().commit_reversible_command ();
+ }
}
void
@@ -1100,6 +1131,27 @@ MidiRegionView::find_canvas_note (boost::shared_ptr<NoteType> note)
return 0;
}
+/** This version finds any canvas note matching the supplied note.*/
+NoteBase*
+MidiRegionView::find_canvas_note (NoteType note)
+{
+ if (_optimization_iterator != _events.end()) {
+ ++_optimization_iterator;
+ }
+
+ if (_optimization_iterator != _events.end() && (*(*_optimization_iterator)->note()) == note) {
+ return *_optimization_iterator;
+ }
+
+ for (_optimization_iterator = _events.begin(); _optimization_iterator != _events.end(); ++_optimization_iterator) {
+ if (*((*_optimization_iterator)->note()) == note) {
+ return *_optimization_iterator;
+ }
+ }
+
+ return 0;
+}
+
void
MidiRegionView::get_events (Events& e, Evoral::Sequence<Evoral::Beats>::NoteOperator op, uint8_t val, int chan_mask)
{
@@ -1173,6 +1225,13 @@ MidiRegionView::redisplay_model()
add_note (note, visible);
}
+ set<boost::shared_ptr<NoteType> >::iterator it;
+ for (it = _pending_note_selection.begin(); it != _pending_note_selection.end(); ++it) {
+ if (*(*it) == *note) {
+ add_to_selection (cne);
+ }
+ }
+
} else {
if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) {
@@ -1182,7 +1241,6 @@ MidiRegionView::redisplay_model()
}
}
-
/* remove note items that are no longer valid */
if (!empty_when_starting) {
@@ -1213,6 +1271,7 @@ MidiRegionView::redisplay_model()
_marked_for_selection.clear ();
_marked_for_velocity.clear ();
+ _pending_note_selection.clear ();
/* we may have caused _events to contain things out of order (e.g. if a note
moved earlier or later). we don't generally need them in time order, but
@@ -1909,7 +1968,9 @@ MidiRegionView::get_patch_key_at (Evoral::Beats time, uint8_t channel, MIDI::Nam
void
MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPrimaryKey& new_patch)
{
- MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("alter patch change"));
+ string name = _("alter patch change");
+ trackview.editor().begin_reversible_command (name);
+ MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
if (pc.patch()->program() != new_patch.program()) {
c->change_program (pc.patch (), new_patch.program());
@@ -1921,6 +1982,7 @@ MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPri
}
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -1929,7 +1991,9 @@ MidiRegionView::change_patch_change (PatchChange& pc, const MIDI::Name::PatchPri
void
MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const Evoral::PatchChange<Evoral::Beats> & new_change)
{
- MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("alter patch change"));
+ string name = _("alter patch change");
+ trackview.editor().begin_reversible_command (name);
+ MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
if (old_change->time() != new_change.time()) {
c->change_time (old_change, new_change.time());
@@ -1948,6 +2012,7 @@ MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const
}
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -1962,8 +2027,10 @@ void
MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beats> const & patch)
{
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
+ string name = _("add patch change");
- MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("add patch change"));
+ trackview.editor().begin_reversible_command (name);
+ MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
c->add (MidiModel::PatchChangePtr (
new Evoral::PatchChange<Evoral::Beats> (
absolute_frames_to_source_beats (_region->position() + t),
@@ -1973,6 +2040,7 @@ MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beat
);
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -1981,9 +2049,11 @@ MidiRegionView::add_patch_change (framecnt_t t, Evoral::PatchChange<Evoral::Beat
void
MidiRegionView::move_patch_change (PatchChange& pc, Evoral::Beats t)
{
+ trackview.editor().begin_reversible_command (_("move patch change"));
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("move patch change"));
c->change_time (pc.patch (), t);
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -1992,9 +2062,11 @@ MidiRegionView::move_patch_change (PatchChange& pc, Evoral::Beats t)
void
MidiRegionView::delete_patch_change (PatchChange* pc)
{
+ trackview.editor().begin_reversible_command (_("delete patch change"));
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (_("delete patch change"));
c->remove (pc->patch ());
_model->apply_command (*trackview.session(), c);
+ trackview.editor().commit_reversible_command ();
_patch_changes.clear ();
display_patch_changes ();
@@ -2143,6 +2215,24 @@ MidiRegionView::invert_selection ()
}
}
+/** Used for selection undo/redo.
+ The requested notes most likely won't exist in the view until the next model redisplay.
+*/
+void
+MidiRegionView::select_notes (list<boost::shared_ptr<NoteType> > notes)
+{
+ NoteBase* cne;
+ list<boost::shared_ptr<NoteType> >::iterator n;
+
+ for (n = notes.begin(); n != notes.end(); ++n) {
+ if ((cne = find_canvas_note(*(*n))) != 0) {
+ add_to_selection (cne);
+ } else {
+ _pending_note_selection.insert(*n);
+ }
+ }
+}
+
void
MidiRegionView::select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend)
{
diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h
index 4f64e4410f..6ffdf98c25 100644
--- a/gtk2_ardour/midi_region_view.h
+++ b/gtk2_ardour/midi_region_view.h
@@ -203,6 +203,7 @@ public:
void move_selection(double dx, double dy, double cumulative_dy);
void note_dropped (NoteBase* ev, ARDOUR::frameoffset_t, int8_t d_note);
+ void select_notes (std::list<boost::shared_ptr<NoteType> >);
void select_matching_notes (uint8_t notenum, uint16_t channel_mask, bool add, bool extend);
void toggle_matching_notes (uint8_t notenum, uint16_t channel_mask);
@@ -438,6 +439,9 @@ private:
* when they appear after the command is applied. */
std::set< boost::shared_ptr<NoteType> > _marked_for_selection;
+ /** Notes that should be selected when the model is redisplayed. */
+ std::set< boost::shared_ptr<NoteType> > _pending_note_selection;
+
/** New notes (created in the current command) which should have visible velocity
* when they appear after the command is applied. */
std::set< boost::shared_ptr<NoteType> > _marked_for_velocity;
@@ -448,6 +452,7 @@ private:
PBD::ScopedConnection content_connection;
NoteBase* find_canvas_note (boost::shared_ptr<NoteType>);
+ NoteBase* find_canvas_note (NoteType);
Events::iterator _optimization_iterator;
void update_note (NoteBase*, bool update_ghost_regions = true);
@@ -499,6 +504,8 @@ private:
bool _grabbed_keyboard;
bool _entered;
+ bool _mouse_changed_selection;
+
framepos_t snap_frame_to_grid_underneath (framepos_t p, framecnt_t &) const;
PBD::ScopedConnection _mouse_mode_connection;
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 5d8dc83bc1..33d192aa1c 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -1308,6 +1308,8 @@ MidiTimeAxisView::set_note_selection (uint8_t note)
{
uint16_t chn_mask = midi_track()->get_playback_channel_mask();
+ _editor.begin_reversible_selection_op(_("Set Note Selection"));
+
if (_view->num_selected_regionviews() == 0) {
_view->foreach_regionview (
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_selection_region_view),
@@ -1317,6 +1319,8 @@ MidiTimeAxisView::set_note_selection (uint8_t note)
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_note_selection_region_view),
note, chn_mask));
}
+
+ _editor.commit_reversible_selection_op();
}
void
@@ -1324,6 +1328,8 @@ MidiTimeAxisView::add_note_selection (uint8_t note)
{
const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
+ _editor.begin_reversible_selection_op(_("Add Note Selection"));
+
if (_view->num_selected_regionviews() == 0) {
_view->foreach_regionview (
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view),
@@ -1333,6 +1339,8 @@ MidiTimeAxisView::add_note_selection (uint8_t note)
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::add_note_selection_region_view),
note, chn_mask));
}
+
+ _editor.commit_reversible_selection_op();
}
void
@@ -1340,6 +1348,8 @@ MidiTimeAxisView::extend_note_selection (uint8_t note)
{
const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
+ _editor.begin_reversible_selection_op(_("Extend Note Selection"));
+
if (_view->num_selected_regionviews() == 0) {
_view->foreach_regionview (
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view),
@@ -1349,6 +1359,8 @@ MidiTimeAxisView::extend_note_selection (uint8_t note)
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::extend_note_selection_region_view),
note, chn_mask));
}
+
+ _editor.commit_reversible_selection_op();
}
void
@@ -1356,6 +1368,8 @@ MidiTimeAxisView::toggle_note_selection (uint8_t note)
{
const uint16_t chn_mask = midi_track()->get_playback_channel_mask();
+ _editor.begin_reversible_selection_op(_("Toggle Note Selection"));
+
if (_view->num_selected_regionviews() == 0) {
_view->foreach_regionview (
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view),
@@ -1365,6 +1379,15 @@ MidiTimeAxisView::toggle_note_selection (uint8_t note)
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_note_selection_region_view),
note, chn_mask));
}
+
+ _editor.commit_reversible_selection_op();
+}
+
+void
+MidiTimeAxisView::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >& selection)
+{
+ _view->foreach_regionview (
+ sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::get_per_region_note_selection_region_view), sigc::ref(selection)));
}
void
@@ -1392,6 +1415,24 @@ MidiTimeAxisView::toggle_note_selection_region_view (RegionView* rv, uint8_t not
}
void
+MidiTimeAxisView::get_per_region_note_selection_region_view (RegionView* rv, list<pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection)
+{
+ Evoral::Sequence<Evoral::Beats>::Notes selected;
+ dynamic_cast<MidiRegionView*>(rv)->selection_as_notelist (selected, false);
+
+ std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > notes;
+
+ Evoral::Sequence<Evoral::Beats>::Notes::iterator sel_it;
+ for (sel_it = selected.begin(); sel_it != selected.end(); ++sel_it) {
+ notes.insert (*sel_it);
+ }
+
+ if (!notes.empty()) {
+ selection.push_back (make_pair ((rv)->region()->id(), notes));
+ }
+}
+
+void
MidiTimeAxisView::set_channel_mode (ChannelMode, uint16_t)
{
/* hide all automation tracks that use the wrong channel(s) and show all those that use
diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h
index 1897174e11..9963ac420c 100644
--- a/gtk2_ardour/midi_time_axis.h
+++ b/gtk2_ardour/midi_time_axis.h
@@ -30,6 +30,8 @@
#include <gtkmm2ext/selector.h>
#include <list>
+#include "evoral/Note.hpp"
+
#include "ardour/types.h"
#include "ardour/region.h"
@@ -65,7 +67,7 @@ class MidiChannelSelectorWindow;
class MidiTimeAxisView : public RouteTimeAxisView
{
- public:
+public:
MidiTimeAxisView (PublicEditor&, ARDOUR::Session*, ArdourCanvas::Canvas& canvas);
virtual ~MidiTimeAxisView ();
@@ -100,11 +102,13 @@ class MidiTimeAxisView : public RouteTimeAxisView
uint8_t get_channel_for_add () const;
- protected:
+ void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >&);
+
+protected:
void start_step_editing ();
void stop_step_editing ();
- private:
+private:
sigc::signal<void, std::string, std::string> _midi_patch_settings_changed;
void model_changed(const std::string& model);
@@ -165,6 +169,7 @@ class MidiTimeAxisView : public RouteTimeAxisView
void add_note_selection_region_view (RegionView* rv, uint8_t note, uint16_t chn_mask);
void extend_note_selection_region_view (RegionView*, uint8_t note, uint16_t chn_mask);
void toggle_note_selection_region_view (RegionView*, uint8_t note, uint16_t chn_mask);
+ void get_per_region_note_selection_region_view (RegionView*, std::list<std::pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >&);
void ensure_step_editor ();
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index 69a3b13fcd..b7263756a6 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -34,6 +34,7 @@
#include <gtkmm/actiongroup.h>
#include <sigc++/signal.h>
+#include "evoral/Note.hpp"
#include "evoral/types.hpp"
#include "pbd/statefuldestructible.h"
@@ -391,6 +392,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
virtual void stop_canvas_autoscroll () = 0;
virtual bool autoscroll_active() const = 0;
+ virtual void begin_reversible_selection_op (std::string cmd_name) = 0;
+ virtual void commit_reversible_selection_op () = 0;
virtual void begin_reversible_command (std::string cmd_name) = 0;
virtual void begin_reversible_command (GQuark) = 0;
virtual void commit_reversible_command () = 0;
@@ -412,7 +415,8 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
virtual void get_regions_at (RegionSelection &, framepos_t where, TrackViewList const &) const = 0;
virtual RegionSelection get_regions_from_selection_and_mouse (framepos_t) = 0;
- virtual void get_regionviews_by_id (PBD::ID const & id, RegionSelection & regions) const = 0;
+ virtual void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const = 0;
+ virtual void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >&) const = 0;
/// Singleton instance, set up by Editor::Editor()
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
index 4a619e1b03..39ade0fadf 100644
--- a/gtk2_ardour/selection.cc
+++ b/gtk2_ardour/selection.cc
@@ -109,6 +109,7 @@ Selection::clear ()
clear_midi_notes ();
clear_midi_regions ();
clear_markers ();
+ pending_midi_note_selection.clear();
}
void
@@ -506,9 +507,9 @@ Selection::add (RegionView* r)
if (find (regions.begin(), regions.end(), r) == regions.end()) {
bool changed = regions.add (r);
- if (changed) {
- RegionsChanged ();
- }
+ if (changed) {
+ RegionsChanged ();
+ }
}
}
@@ -1229,12 +1230,45 @@ Selection::get_state () const
for (RegionSelection::const_iterator i = regions.begin(); i != regions.end(); ++i) {
XMLNode* r = node->add_child (X_("Region"));
r->add_property (X_("id"), atoi ((*i)->region ()->id ().to_s ().c_str()));
-
+ }
+
+ /* midi region views have thir own internal selection. */
+ XMLNode* n;
+ list<pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > rid_notes;
+ editor->get_per_region_note_selection (rid_notes);
+ if (!rid_notes.empty()) {
+ n = node->add_child (X_("MIDINote"));
+ }
+ list<pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rn_it;
+ for (rn_it = rid_notes.begin(); rn_it != rid_notes.end(); ++rn_it) {
+ n->add_property (X_("region_id"), atoi((*rn_it).first.to_s().c_str()));
+
+ for (std::set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > >::iterator i = (*rn_it).second.begin(); i != (*rn_it).second.end(); ++i) {
+ XMLNode* nc = n->add_child(X_("note"));
+ snprintf(buf, sizeof(buf), "%d", (*i)->channel());
+ nc->add_property(X_("channel"), string(buf));
+
+ snprintf(buf, sizeof(buf), "%f", (*i)->time().to_double());
+ nc->add_property(X_("time"), string(buf));
+
+ snprintf(buf, sizeof(buf), "%d", (*i)->note());
+ nc->add_property(X_("note"), string(buf));
+
+ snprintf(buf, sizeof(buf), "%f", (*i)->length().to_double());
+ nc->add_property(X_("length"), string(buf));
+
+ snprintf(buf, sizeof(buf), "%d", (*i)->velocity());
+ nc->add_property(X_("velocity"), string(buf));
+
+ snprintf(buf, sizeof(buf), "%d", (*i)->off_velocity());
+ nc->add_property(X_("off-velocity"), string(buf));
+ }
}
for (PointSelection::const_iterator i = points.begin(); i != points.end(); ++i) {
AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (&(*i)->line().trackview);
if (atv) {
+
XMLNode* r = node->add_child (X_("ControlPoint"));
r->add_property (X_("type"), "track");
r->add_property (X_("route-id"), atoi (atv->parent_route()->id ().to_s ().c_str()));
@@ -1243,6 +1277,7 @@ Selection::get_state () const
snprintf(buf, sizeof(buf), "%d", (*i)->view_index());
r->add_property (X_("view-index"), string(buf));
+
}
}
@@ -1304,44 +1339,106 @@ Selection::set_state (XMLNode const & node, int)
add (rs);
} else {
/*
- regionviews are being constructed - stash the region IDs
+ regionviews haven't been constructed - stash the region IDs
so we can identify them in Editor::region_view_added ()
*/
regions.pending.push_back (id);
}
+ } else if ((*i)->name() == X_("MIDINote")) {
+ XMLProperty* prop_region_id = (*i)->property (X_("region-id"));
+
+ assert (prop_region_id);
+
+ PBD::ID const id (prop_region_id->value ());
+ RegionSelection rs;
+
+ editor->get_regionviews_by_id (id, rs); // there could be more than one
+
+ std::list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > notes;
+ XMLNodeList children = (*i)->children ();
+
+ for (XMLNodeList::const_iterator ci = children.begin(); ci != children.end(); ++ci) {
+ XMLProperty* prop_channel = (*ci)->property (X_("channel"));
+ XMLProperty* prop_time = (*ci)->property (X_("time"));
+ XMLProperty* prop_note = (*ci)->property (X_("note"));
+ XMLProperty* prop_length = (*ci)->property (X_("length"));
+ XMLProperty* prop_velocity = (*ci)->property (X_("velocity"));
+ XMLProperty* prop_off_velocity = (*ci)->property (X_("off-velocity"));
+
+ assert (prop_channel);
+ assert (prop_time);
+ assert (prop_note);
+ assert (prop_length);
+ assert (prop_velocity);
+ assert (prop_off_velocity);
+
+ uint8_t channel = atoi(prop_channel->value());
+ Evoral::Beats time (atof(prop_time->value()));
+ Evoral::Beats length (atof(prop_length->value()));
+ uint8_t note = atoi(prop_note->value());
+ uint8_t velocity = atoi(prop_velocity->value());
+ uint8_t off_velocity = atoi(prop_off_velocity->value());
+ boost::shared_ptr<Evoral::Note<Evoral::Beats> > the_note
+ (new Evoral::Note<Evoral::Beats> (channel, time, length, note, velocity));
+ the_note->set_off_velocity (off_velocity);
+
+ notes.push_back (the_note);
+ }
+
+ for (RegionSelection::iterator rsi = rs.begin(); rsi != rs.end(); ++rsi) {
+ MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (*rsi);
+ if (mrv) {
+ mrv->select_notes(notes);
+ }
+ }
+
+ if (rs.empty()) {
+ /* regionviews containing these notes don't yet exist on the canvas.*/
+ pending_midi_note_selection.push_back (make_pair (id, notes));
+ }
+
} else if ((*i)->name() == X_("ControlPoint")) {
XMLProperty* prop_type = (*i)->property (X_("type"));
- XMLProperty* prop_route_id = (*i)->property (X_("route-id"));
- XMLProperty* prop_alist_id = (*i)->property (X_("automation-list-id"));
- XMLProperty* prop_parameter = (*i)->property (X_("parameter"));
- XMLProperty* prop_view_index = (*i)->property (X_("view-index"));
-
- assert (prop_type);
- assert (prop_route_id);
- assert (prop_alist_id);
- assert (prop_parameter);
- assert (prop_view_index);
+
+ assert(prop_type);
if (prop_type->value () == "track") {
- PBD::ID id (prop_route_id->value ());
- RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (id);
+
+ XMLProperty* prop_route_id = (*i)->property (X_("route-id"));
+ XMLProperty* prop_alist_id = (*i)->property (X_("automation-list-id"));
+ XMLProperty* prop_parameter = (*i)->property (X_("parameter"));
+ XMLProperty* prop_view_index = (*i)->property (X_("view-index"));
+
+ assert (prop_type);
+ assert (prop_route_id);
+ assert (prop_alist_id);
+ assert (prop_parameter);
+ assert (prop_view_index);
+
+ PBD::ID route_id (prop_route_id->value ());
+ RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (route_id);
+ vector <ControlPoint *> cps;
if (rtv) {
boost::shared_ptr<AutomationTimeAxisView> atv = rtv->automation_child (EventTypeMap::instance().from_symbol (prop_parameter->value ()));
if (atv) {
list<boost::shared_ptr<AutomationLine> > lines = atv->lines();
- for (list<boost::shared_ptr<AutomationLine> > ::iterator i = lines.begin(); i != lines.end(); ++i) {
- if ((*i)->the_list()->id() == prop_alist_id->value()) {
- ControlPoint* cp = (*i)->nth(atol(prop_view_index->value().c_str()));
+ for (list<boost::shared_ptr<AutomationLine> > ::iterator li = lines.begin(); li != lines.end(); ++li) {
+ if ((*li)->the_list()->id() == prop_alist_id->value()) {
+ ControlPoint* cp = (*li)->nth(atol(prop_view_index->value().c_str()));
if (cp) {
- add (cp);
+ cps.push_back (cp);
+ cp->show();
}
}
}
}
}
- }
+ if (!cps.empty()) {
+ add (cps);
+ }
+ }
} else if ((*i)->name() == X_("AudioRange")) {
XMLProperty* prop_start = (*i)->property (X_("start"));
diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h
index fe2be2e6e4..7585c0ae56 100644
--- a/gtk2_ardour/selection.h
+++ b/gtk2_ardour/selection.h
@@ -223,6 +223,8 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
PBD::Signal0<void> ClearMidiNoteSelection;
+ std::list<std::pair<PBD::ID const, std::list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > pending_midi_note_selection;
+
private:
PublicEditor const * editor;
uint32_t next_time_id;