diff --git a/gtk2_ardour/editing_context.cc b/gtk2_ardour/editing_context.cc index 460cf7157e..f786cd9dbc 100644 --- a/gtk2_ardour/editing_context.cc +++ b/gtk2_ardour/editing_context.cc @@ -1783,8 +1783,12 @@ EditingContext::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* eve entered_regionview. */ MidiView& mrv = note->midi_view(); - const RegionSelection rs = region_selection (); const uint32_t sel_size = mrv.selection_size (); + MidiViews mvs (midiviews_from_region_selection (region_selection ())); + + if (std::find (mvs.begin(), mvs.end(), &mrv) == mvs.end()) { + mvs.push_back (&mrv); + } MenuList& items = _note_context_menu.items(); items.clear(); @@ -1794,17 +1798,17 @@ EditingContext::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* eve } items.push_back(MenuElem(_("Edit..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::edit_notes), &mrv))); - items.push_back(MenuElem(_("Transpose..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transpose_regions), rs))); - items.push_back(MenuElem(_("Legatize"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), rs, false))); + items.push_back(MenuElem(_("Transpose..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transpose_regions), mvs))); + items.push_back(MenuElem(_("Legatize"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), mvs, false))); if (sel_size < 2) { items.back().set_sensitive (false); } - items.push_back(MenuElem(_("Quantize..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::quantize_regions), rs))); - items.push_back(MenuElem(_("Remove Overlap"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), rs, true))); + items.push_back(MenuElem(_("Quantize..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::quantize_regions), mvs))); + items.push_back(MenuElem(_("Remove Overlap"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), mvs, true))); if (sel_size < 2) { items.back().set_sensitive (false); } - items.push_back(MenuElem(_("Transform..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transform_regions), rs))); + items.push_back(MenuElem(_("Transform..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transform_regions), mvs))); _note_context_menu.popup (event->button.button, event->button.time); } @@ -1822,13 +1826,19 @@ EditingContext::button_settings () const return node; } -std::vector +EditingContext::MidiViews EditingContext::filter_to_unique_midi_region_views (RegionSelection const & rs) const +{ + return filter_to_unique_midi_region_views (midiviews_from_region_selection (rs)); +} + +EditingContext::MidiViews +EditingContext::filter_to_unique_midi_region_views (MidiViews const & mvs) const { typedef std::pair,timepos_t> MapEntry; std::set single_region_set; - std::vector views; + MidiViews views; /* build a list of regions that are unique with respect to their source * and start position. Note: this is non-exhaustive... if someone has a @@ -1839,17 +1849,26 @@ EditingContext::filter_to_unique_midi_region_views (RegionSelection const & rs) * Solution: user should not select both regions, or should fork one of them. */ - for (auto const & rv : rs) { + for (auto const & mv : mvs) { - MidiView* mrv = dynamic_cast (rv); - - if (!mrv) { - continue; - } - - MapEntry entry = make_pair (mrv->midi_region()->midi_source(), mrv->midi_region()->start()); + MapEntry entry = make_pair (mv->midi_region()->midi_source(), mv->midi_region()->start()); if (single_region_set.insert (entry).second) { + views.push_back (mv); + } + } + + return views; +} + +EditingContext::MidiViews +EditingContext::midiviews_from_region_selection (RegionSelection const & rs) const +{ + MidiViews views; + + for (auto & rv : rs) { + MidiView* mrv = dynamic_cast (rv); + if (mrv) { views.push_back (mrv); } } @@ -1861,14 +1880,15 @@ void EditingContext::quantize_region () { if (_session) { - quantize_regions(region_selection ()); + quantize_regions (midiviews_from_region_selection (region_selection())); } } void -EditingContext::quantize_regions (const RegionSelection& rs) +EditingContext::quantize_regions (const MidiViews& rs) { - if (rs.n_midi_regions() == 0) { + if (rs.empty()) { + std::cerr << "no regions\n"; return; } @@ -1889,18 +1909,18 @@ void EditingContext::legatize_region (bool shrink_only) { if (_session) { - legatize_regions(region_selection (), shrink_only); + legatize_regions (midiviews_from_region_selection (region_selection ()), shrink_only); } } void -EditingContext::legatize_regions (const RegionSelection& rs, bool shrink_only) +EditingContext::legatize_regions (const MidiViews& rs, bool shrink_only) { - if (rs.n_midi_regions() == 0) { + if (rs.empty()) { return; } - Legatize legatize(shrink_only); + Legatize legatize (shrink_only); apply_midi_note_edit_op (legatize, rs); } @@ -1908,14 +1928,14 @@ void EditingContext::transform_region () { if (_session) { - transform_regions(region_selection ()); + transform_regions (midiviews_from_region_selection (region_selection ())); } } void -EditingContext::transform_regions (const RegionSelection& rs) +EditingContext::transform_regions (const MidiViews& rs) { - if (rs.n_midi_regions() == 0) { + if (rs.empty()) { return; } @@ -1935,14 +1955,14 @@ void EditingContext::transpose_region () { if (_session) { - transpose_regions(region_selection ()); + transpose_regions (midiviews_from_region_selection (region_selection ())); } } void -EditingContext::transpose_regions (const RegionSelection& rs) +EditingContext::transpose_regions (const MidiViews& rs) { - if (rs.n_midi_regions() == 0) { + if (rs.empty()) { return; } @@ -1987,8 +2007,6 @@ EditingContext::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiView& m return 0; } - std::cerr << "Apply op to " << selected.size() << std::endl; - std::vector::Notes> v; v.push_back (selected); @@ -1999,6 +2017,12 @@ EditingContext::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiView& m void EditingContext::apply_midi_note_edit_op (MidiOperator& op, const RegionSelection& rs) +{ + apply_midi_note_edit_op (op, midiviews_from_region_selection (rs)); +} + +void +EditingContext::apply_midi_note_edit_op (MidiOperator& op, const MidiViews& rs) { if (rs.empty()) { return; diff --git a/gtk2_ardour/editing_context.h b/gtk2_ardour/editing_context.h index 20cb4911df..36ebfe6a73 100644 --- a/gtk2_ardour/editing_context.h +++ b/gtk2_ardour/editing_context.h @@ -395,18 +395,29 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, PBD::Signal SnapChanged; PBD::Signal MouseModeChanged; + typedef std::vector MidiViews; + /* MIDI actions, proxied to selected MidiRegionView(s) */ ARDOUR::Quantize* get_quantize_op (); void apply_midi_note_edit_op (ARDOUR::MidiOperator& op, const RegionSelection& rs); + void apply_midi_note_edit_op (ARDOUR::MidiOperator& op, const MidiViews& rs); PBD::Command* apply_midi_note_edit_op_to_region (ARDOUR::MidiOperator& op, MidiView& mrv); virtual void midi_action (void (MidiView::*method)()); - std::vector filter_to_unique_midi_region_views (RegionSelection const & ms) const; + std::vector filter_to_unique_midi_region_views (RegionSelection const & rs) const; + std::vector filter_to_unique_midi_region_views (MidiViews const & ms) const; void quantize_region (); void transform_region (); void legatize_region (bool shrink_only); void transpose_region (); + void quantize_regions (const MidiViews& rs); + void legatize_regions (const MidiViews& rs, bool shrink_only); + void transform_regions (const MidiViews& rs); + void transpose_regions (const MidiViews& rs); + + void edit_notes (MidiView*); + static bool need_shared_actions; void register_midi_actions (Gtkmm2ext::Bindings*, std::string const &); void register_common_actions (Gtkmm2ext::Bindings*, std::string const &); @@ -666,13 +677,9 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, virtual RegionSelection region_selection() = 0; - void edit_notes (MidiView*); void note_edit_done (int, EditNoteDialog*); - void quantize_regions (const RegionSelection& rs); - void legatize_regions (const RegionSelection& rs, bool shrink_only); - void transform_regions (const RegionSelection& rs); - void transpose_regions (const RegionSelection& rs); + MidiViews midiviews_from_region_selection (RegionSelection const &) const; /** the adjustment that controls the overall editing vertical scroll position */ friend class EditorSummary; diff --git a/gtk2_ardour/pianoroll.cc b/gtk2_ardour/pianoroll.cc index 129714401a..c4b5a50b2e 100644 --- a/gtk2_ardour/pianoroll.cc +++ b/gtk2_ardour/pianoroll.cc @@ -1133,9 +1133,9 @@ Pianoroll::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, It return true; } } - } - if (Keyboard::is_context_menu_event (&event->button)) { + } else { + switch (item_type) { case NoteItem: if (internal_editing()) { @@ -1143,14 +1143,58 @@ Pianoroll::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, It return true; } break; + case RegionItem: + if (internal_editing()) { + popup_region_context_menu (item, event); + return true; + } + break; default: break; } + + popup_note_context_menu (item, event); + return true; } return false; } +void +Pianoroll::popup_region_context_menu (ArdourCanvas::Item* item, GdkEvent* event) +{ + using namespace Gtk::Menu_Helpers; + + if (!view) { + return; + } + + const uint32_t sel_size = view->selection_size (); + MidiViews mvs ({view}); + + MenuList& items = _region_context_menu.items(); + items.clear(); + + if (sel_size > 0) { + items.push_back (MenuElem(_("Delete"), sigc::mem_fun (*view, &MidiView::delete_selection))); + } + + items.push_back(MenuElem(_("Edit..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::edit_notes), view))); + items.push_back(MenuElem(_("Transpose..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transpose_regions), mvs))); + items.push_back(MenuElem(_("Legatize"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), mvs, false))); + if (sel_size < 2) { + items.back().set_sensitive (false); + } + items.push_back(MenuElem(_("Quantize..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::quantize_regions), mvs))); + items.push_back(MenuElem(_("Remove Overlap"), sigc::bind(sigc::mem_fun(*this, &EditingContext::legatize_regions), mvs, true))); + if (sel_size < 2) { + items.back().set_sensitive (false); + } + items.push_back(MenuElem(_("Transform..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transform_regions), mvs))); + + _region_context_menu.popup (event->button.button, event->button.time); +} + bool Pianoroll::button_press_dispatch (GdkEventButton* ev) { @@ -1233,6 +1277,7 @@ RegionSelection Pianoroll::region_selection() { RegionSelection rs; + /* there is never any region-level selection in a pianoroll */ return rs; } diff --git a/gtk2_ardour/pianoroll.h b/gtk2_ardour/pianoroll.h index 816e05c7ce..bfde56746e 100644 --- a/gtk2_ardour/pianoroll.h +++ b/gtk2_ardour/pianoroll.h @@ -349,4 +349,7 @@ class Pianoroll : public CueEditor void ruler_locate (GdkEventButton*); void scrolled (); void update_tempo_based_rulers (); + + Gtk::Menu _region_context_menu; + void popup_region_context_menu (ArdourCanvas::Item* item, GdkEvent* event); };