From 65f7a6a9388d8462a08dd8da7a218baca099649f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 16 Apr 2020 12:16:45 -0600 Subject: changes to deal with region/note selection when changing into/out of internal edit mode Also, activate MIDI editing actions so that they are effective in internal edit mode --- gtk2_ardour/editor.h | 1 + gtk2_ardour/editor_mouse.cc | 35 +++++++++++++++++++++++++++++++++++ gtk2_ardour/editor_ops.cc | 41 ++++++++++++++++++++++++++++++++--------- gtk2_ardour/editor_selection.cc | 31 ++++++++++++++++++++++++++++--- gtk2_ardour/midi_streamview.cc | 17 +++++++++++++++++ gtk2_ardour/midi_streamview.h | 2 +- gtk2_ardour/midi_time_axis.cc | 6 ++++++ gtk2_ardour/midi_time_axis.h | 2 ++ gtk2_ardour/public_editor.h | 1 + 9 files changed, 123 insertions(+), 13 deletions(-) diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 9d2e860030..5381951ab7 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1883,6 +1883,7 @@ private: void update_time_selection_display (); void presentation_info_changed (PBD::PropertyChange const &); void region_selection_changed (); + void catch_up_on_midi_selection (); sigc::connection editor_regions_selection_changed_connection; void sensitize_all_region_actions (bool); void sensitize_the_right_region_actions (bool because_canvas_crossing); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 7d63c4925d..2437dc31b8 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -347,6 +347,38 @@ Editor::mouse_mode_toggled (MouseMode m) update_time_selection_display (); + if (internal_editing()) { + + /* reinstate any existing MIDI note (and by extension, MIDI + * region) selection for internal edit mode. This allows a user + * to enter/exit/enter this mode without losing a selection of + * notes. + */ + + catch_up_on_midi_selection (); + + /* ensure that the track canvas has focus, so that key events + will get directed to the correct place. + */ + _track_canvas->grab_focus (); + + /* enable MIDI editing actions, which in turns enables their + bindings + */ + ActionManager::set_sensitive (_midi_actions, true); + + /* mark "magic widget focus" so that we handle key events + * correctly + */ + Keyboard::magic_widget_grab_focus (); + } else { + /* undo some of the above actions, since we're not in internal + edit mode. + */ + ActionManager::set_sensitive (_midi_actions, false); + Keyboard::magic_widget_drop_focus (); + } + update_all_enter_cursors (); MouseModeChanged (); /* EMIT SIGNAL */ @@ -2627,6 +2659,9 @@ Editor::escape () if (_drags->active ()) { _drags->abort (); } else if (_session) { + + midi_action (&MidiRegionView::clear_note_selection); + selection->clear (); /* if session is playing a range, cancel that */ diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 92385e41b7..813ff303de 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -4437,17 +4437,21 @@ void Editor::cut_copy_midi (CutCopyOp op) { Temporal::Beats earliest = std::numeric_limits::max(); - for (MidiRegionSelection::iterator i = selection->midi_regions.begin(); i != selection->midi_regions.end(); ++i) { - MidiRegionView* mrv = dynamic_cast(*i); - if (mrv) { - if (!mrv->selection().empty()) { - earliest = std::min(earliest, (*mrv->selection().begin())->note()->time()); - } - mrv->cut_copy_clear (op); - /* XXX: not ideal, as there may be more than one track involved in the selection */ - _last_cut_copy_source_track = &mrv->get_time_axis_view(); + MidiRegionSelection ms = selection->midi_regions (); + cerr << "CCM, mrv = " << ms.size() << endl; + + for (MidiRegionSelection::iterator i = ms.begin(); i != ms.end(); ++i) { + + MidiRegionView* mrv = dynamic_cast (*i); + + if (!mrv->selection().empty()) { + earliest = std::min(earliest, (*mrv->selection().begin())->note()->time()); } + mrv->cut_copy_clear (op); + + /* XXX: not ideal, as there may be more than one track involved in the selection */ + _last_cut_copy_source_track = &mrv->get_time_axis_view(); } if (!selection->points.empty()) { @@ -8562,3 +8566,22 @@ Editor::toggle_layer_display () } } + +void +Editor::midi_action (void (MidiRegionView::*method)()) +{ + MidiRegionSelection ms = selection->midi_regions(); + + cerr << "MIDI action with " << ms.size() << " midi regions\n"; + + for (MidiRegionSelection::iterator i = ms.begin(); i != ms.end(); ++i) { + + MidiRegionView* mrv = dynamic_cast (*i); + + if (!mrv) { + continue; + } + + (mrv->*method) (); + } +} diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc index fa67ea4ab1..e8326ae643 100644 --- a/gtk2_ardour/editor_selection.cc +++ b/gtk2_ardour/editor_selection.cc @@ -49,6 +49,7 @@ #include "control_point.h" #include "editor_regions.h" #include "editor_cursors.h" +#include "keyboard.h" #include "midi_region_view.h" #include "sfdb_ui.h" @@ -1618,8 +1619,8 @@ Editor::region_selection_changed () //there are a few global Editor->Select actions which select regions even if you aren't in Object mode. //if regions are selected, we must always force the mouse mode to Object... //... otherwise the user is confusingly left with selected regions that can't be manipulated. - if (!selection->regions.empty()) { - set_mouse_mode( MouseObject, false ); + if (!selection->regions.empty() && !internal_editing()) { + set_mouse_mode (MouseObject, false); } } @@ -1746,7 +1747,8 @@ Editor::invert_selection () { if (internal_editing()) { - for (MidiRegionSelection::iterator i = selection->midi_regions.begin(); i != selection->midi_regions.end(); ++i) { + MidiRegionSelection ms = selection->midi_regions(); + for (MidiRegionSelection::iterator i = ms.begin(); i != ms.end(); ++i) { MidiRegionView* mrv = dynamic_cast(*i); if (mrv) { mrv->invert_selection (); @@ -2217,3 +2219,26 @@ Editor::select_range (samplepos_t s, samplepos_t e) commit_reversible_selection_op (); return ret; } + +void +Editor::catch_up_on_midi_selection () +{ + RegionSelection regions; + + for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) { + if ((*iter)->hidden()) { + continue; + } + + MidiTimeAxisView* matv = dynamic_cast (*iter); + if (!matv) { + continue; + } + + matv->get_regions_with_selected_data (regions); + } + + if (!regions.empty()) { + selection->set (regions); + } +} diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index fe3ecd9685..b638a64999 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -711,3 +711,20 @@ MidiStreamView::paste (ARDOUR::samplepos_t pos, const Selection& selection, Past MidiRegionView* mrv = dynamic_cast (*prev); return mrv ? mrv->paste(pos, selection, ctx, sub_num) : false; } + +void +MidiStreamView::get_regions_with_selected_data (RegionSelection& rs) +{ + for (list::const_iterator i = region_views.begin(); i != region_views.end(); ++i) { + MidiRegionView* mrv = dynamic_cast (*i); + + if (!mrv) { + continue; + } + + if (!mrv->selection().empty()) { + rs.add (*i); + cerr << "added region " << mrv->get_item_name() << " to RwSD\n"; + } + } +} diff --git a/gtk2_ardour/midi_streamview.h b/gtk2_ardour/midi_streamview.h index 20cf7b88fe..b333ff33e8 100644 --- a/gtk2_ardour/midi_streamview.h +++ b/gtk2_ardour/midi_streamview.h @@ -63,8 +63,8 @@ public: MidiStreamView (MidiTimeAxisView&); ~MidiStreamView (); - void set_selected_regionviews (RegionSelection&); void get_inverted_selectables (Selection&, std::list& results); + void get_regions_with_selected_data (RegionSelection&); enum VisibleNoteRange { FullRange, diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index 71732123bd..395ce6d012 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -1700,3 +1700,9 @@ MidiTimeAxisView::paste (samplepos_t pos, const Selection& selection, PasteConte return midi_view()->paste(pos, selection, ctx, sub_num); } + +void +MidiTimeAxisView::get_regions_with_selected_data (RegionSelection& rs) +{ + midi_view()->get_regions_with_selected_data (rs); +} diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h index 0f0724fe32..78a7f95cee 100644 --- a/gtk2_ardour/midi_time_axis.h +++ b/gtk2_ardour/midi_time_axis.h @@ -93,6 +93,8 @@ public: void show_existing_automation (bool apply_to_selection = false); void create_automation_child (const Evoral::Parameter& param, bool show); + void get_regions_with_selected_data (RegionSelection&); + bool paste (ARDOUR::samplepos_t, const Selection&, PasteContext& ctx, const int32_t sub_num); ARDOUR::NoteMode note_mode() const { return _note_mode; } diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 9709f88722..be6f900d3d 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -390,6 +390,7 @@ public: Glib::RefPtr editor_actions; Glib::RefPtr editor_menu_actions; Glib::RefPtr _region_actions; + Glib::RefPtr _midi_actions; virtual bool canvas_scroll_event (GdkEventScroll* event, bool from_canvas) = 0; virtual bool canvas_control_point_event (GdkEvent* event, ArdourCanvas::Item*, ControlPoint*) = 0; -- cgit v1.2.3