make it possible to do certain basic MIDI editing from a context menu in a pianoroll

Quantize, Legatize, Transform and Remove Overlaps (negative legatize) are all handy, and should be accessible
here. There may be other operations to add to this menu in the future
This commit is contained in:
Paul Davis
2025-12-11 14:03:36 -07:00
parent 78a59db334
commit d61a4ba493
6 changed files with 66 additions and 2 deletions

View File

@@ -3973,3 +3973,9 @@ EditingContext::scroll_right_half_page ()
reset_x_origin (max_samplepos - current_page_samples());
}
}
Gtk::Menu*
EditingContext::get_single_region_context_menu ()
{
return nullptr;
}

View File

@@ -520,6 +520,8 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
std::shared_ptr<Evoral::ControlList> copy; ///< copied events for the cut buffer
};
virtual Gtk::Menu* get_single_region_context_menu ();
protected:
std::string _name;
bool within_track_canvas;
@@ -702,7 +704,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider,
void note_edit_done (int, EditNoteDialog*);
MidiViews midiviews_from_region_selection (RegionSelection const &) const;
virtual MidiViews midiviews_from_region_selection (RegionSelection const &) const;
/** the adjustment that controls the overall editing vertical scroll position */
friend class EditorSummary;

View File

@@ -556,9 +556,28 @@ MidiView::leave_internal()
_entered_note = 0;
}
bool
MidiView::show_context_menu (GdkEventButton* ev)
{
if (_on_timeline) {
/* this is handled at a higher level, so that operations apply
* to all selected regions.
*/
return false;
}
Gtk::Menu* context_menu = _editing_context.get_single_region_context_menu ();
context_menu->popup (ev->button, ev->time);
return true;
}
bool
MidiView::button_press (GdkEventButton* ev)
{
if (Keyboard::is_context_menu_event (ev)) {
return show_context_menu (ev);
}
if (ev->button != 1) {
return false;
}

View File

@@ -664,7 +664,7 @@ class MidiView : public virtual sigc::trackable, public LineMerger
void start_note_splitting ();
void end_note_splitting ();
void split_notes_grid ();
void split_notes_more ();
void split_notes_less ();
@@ -684,6 +684,7 @@ class MidiView : public virtual sigc::trackable, public LineMerger
void color_note (NoteBase*, int channel);
virtual bool post_paste (Temporal::timepos_t const & pos, const ::Selection& selection, PasteContext& ctx) { return false; }
bool show_context_menu (GdkEventButton*);
};

View File

@@ -2106,3 +2106,36 @@ Pianoroll::source_to_timeline (timepos_t const & source_pos) const
return source_pos;
}
Gtk::Menu*
Pianoroll::get_single_region_context_menu ()
{
using namespace Gtk;
using namespace Menu_Helpers;
Menu* m = new Menu;
MenuList& items (m->items());
items.push_back (MenuElem (_("Quantize..."), sigc::mem_fun (*this, &EditingContext::quantize_region)));
items.push_back (MenuElem (_("Legatize"), sigc::bind(sigc::mem_fun (*this, &EditingContext::legatize_region), false)));
items.push_back (MenuElem (_("Transform..."), sigc::mem_fun (*this, &EditingContext::transform_region)));
items.push_back (MenuElem (_("Remove Overlap"), sigc::bind(sigc::mem_fun (*this, &EditingContext::legatize_region), true)));
// items.push_back (MenuElem (_("Insert Patch Change..."), sigc::bind (sigc::mem_fun (*this, &EditingContext::insert_patch_change), false)));
// items.push_back (MenuElem (_("Insert Patch Change..."), sigc::bind (sigc::mem_fun (*this, &EditingContext::insert_patch_change), true)));
return m;
}
EditingContext::MidiViews
Pianoroll::midiviews_from_region_selection (RegionSelection const &) const
{
/* there is no region selection */
MidiViews mv;
if (midi_view()) {
mv.push_back (midi_view());
}
return mv;
}

View File

@@ -253,4 +253,7 @@ class Pianoroll : public CueEditor
void instant_save ();
void parameter_changed (std::string param);
void set_from_rsu (RegionUISettings&);
Gtk::Menu* get_single_region_context_menu ();
MidiViews midiviews_from_region_selection (RegionSelection const &) const;
};