diff --git a/gtk2_ardour/editing_context.cc b/gtk2_ardour/editing_context.cc index 956bc3fb01..bda77d8341 100644 --- a/gtk2_ardour/editing_context.cc +++ b/gtk2_ardour/editing_context.cc @@ -28,6 +28,7 @@ #include "ardour/rc_configuration.h" #include "ardour/transpose.h" #include "ardour/quantize.h" +#include "ardour/strum.h" #include "gtkmm2ext/bindings.h" @@ -632,6 +633,9 @@ EditingContext::register_midi_actions (Bindings* midi_bindings, std::string cons ActionManager::register_action (_midi_actions, X_("split-notes-less"), _("Split Selected Notes into less pieces"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::split_notes_less)); ActionManager::register_action (_midi_actions, X_("join-notes"), _("Join Selected Notes"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::join_notes)); + ActionManager::register_action (_midi_actions, X_("strum-forward"), _("Strum notes forward"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::strum_notes_forward)); + ActionManager::register_action (_midi_actions, X_("strum-backward"), _("Strum notes backward"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::strum_notes_backward)); + ActionManager::register_action (_midi_actions, X_("edit-channels"), _("Edit Note Channels"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::channel_edit)); ActionManager::register_action (_midi_actions, X_("edit-velocities"), _("Edit Note Velocities"), sigc::bind (sigc::mem_fun (*this, &EditingContext::midi_action), &MidiView::velocity_edit)); @@ -1813,6 +1817,14 @@ EditingContext::get_quantize_op () quantize_dialog->threshold()); } +Strum* +EditingContext::get_strum_op (bool forward, bool fine) +{ + EC_LOCAL_TEMPO_SCOPE; + + return new Strum (forward, fine); +} + timecnt_t EditingContext::relative_distance (timepos_t const & origin, timecnt_t const & duration, Temporal::TimeDomain domain) { @@ -1938,6 +1950,9 @@ EditingContext::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* eve items.back().set_sensitive (false); } items.push_back(MenuElem(_("Transform..."), sigc::bind(sigc::mem_fun(*this, &EditingContext::transform_regions), mvs))); + items.push_back (SeparatorElem()); + items.push_back(MenuElem(_("Strum forward"), sigc::bind(sigc::mem_fun(*this, &EditingContext::strum_notes), mvs, true))); + items.push_back(MenuElem(_("Strum backward"), sigc::bind(sigc::mem_fun(*this, &EditingContext::strum_notes), mvs, false))); _note_context_menu.popup (event->button.button, event->button.time); } @@ -2128,6 +2143,19 @@ EditingContext::transpose_regions (const MidiViews& rs) } } +void +EditingContext::strum_notes (const MidiViews& rs, bool forward) +{ + EC_LOCAL_TEMPO_SCOPE; + + if (rs.empty()) { + return; + } + + Strum strum (forward, false); + apply_midi_note_edit_op (strum, rs); +} + void EditingContext::edit_notes (MidiView* mrv) { diff --git a/gtk2_ardour/editing_context.h b/gtk2_ardour/editing_context.h index 31624b4da7..aae91114ee 100644 --- a/gtk2_ardour/editing_context.h +++ b/gtk2_ardour/editing_context.h @@ -59,6 +59,10 @@ namespace Temporal { class TempoMap; } +namespace ARDOUR { + class Strum; +} + class XMLNode; class ControlPoint; @@ -388,6 +392,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, /* MIDI actions, proxied to selected MidiRegionView(s) */ ARDOUR::Quantize* get_quantize_op (); + ARDOUR::Strum* get_strum_op (bool, bool); 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); @@ -402,6 +407,7 @@ class EditingContext : public ARDOUR::SessionHandlePtr, public AxisViewProvider, void quantize_regions (const MidiViews& rs); void legatize_regions (const MidiViews& rs, bool shrink_only); + void strum_notes (const MidiViews& rs, bool forward); void transform_regions (const MidiViews& rs); void transpose_regions (const MidiViews& rs); diff --git a/gtk2_ardour/midi_view.cc b/gtk2_ardour/midi_view.cc index c1c28ab5c0..4287e3ddd5 100644 --- a/gtk2_ardour/midi_view.cc +++ b/gtk2_ardour/midi_view.cc @@ -47,6 +47,7 @@ #include "ardour/operations.h" #include "ardour/quantize.h" #include "ardour/session.h" +#include "ardour/strum.h" #include "evoral/Parameter.h" #include "evoral/Event.h" @@ -5010,6 +5011,28 @@ MidiView::quantize_selected_notes () delete quant; } +void +MidiView::strum_notes (bool forward, bool fine) +{ + Strum* strum = _editing_context.get_strum_op (forward, fine); + + if (!strum) { + return; + } + + PBD::Command* cmd = _editing_context.apply_midi_note_edit_op_to_region (*strum, *this); + + if (cmd) { + _editing_context.begin_reversible_command (strum->name ()); + (*cmd)(); + _editing_context.add_command (cmd); + _editing_context.commit_reversible_command (); + _editing_context.session()->set_dirty (); + } + + delete strum; +} + void MidiView::sync_velocity_drag (double factor) { diff --git a/gtk2_ardour/midi_view.h b/gtk2_ardour/midi_view.h index caf5c9a5a6..262209584f 100644 --- a/gtk2_ardour/midi_view.h +++ b/gtk2_ardour/midi_view.h @@ -301,6 +301,7 @@ class MidiView : public virtual sigc::trackable, public LineMerger bool set_velocities_for_notes (std::vector& notes, std::vector& velocities); void transpose (bool up, bool fine, bool allow_smush); void nudge_notes (bool forward, bool fine); + void strum_notes (bool forward, bool fine); void channel_edit (); void velocity_edit (); @@ -431,6 +432,9 @@ class MidiView : public virtual sigc::trackable, public LineMerger void quantize_selected_notes (); + void strum_notes_forward () { strum_notes (true, false); } + void strum_notes_backward () { strum_notes (false, false); } + protected: friend class MidiRubberbandSelectDrag; friend class MidiVerticalSelectDrag;