MIDI Draw: provide a menu for Channel and Velocity

This commit is contained in:
Ben Loftis 2021-11-16 12:06:13 -06:00
parent 2a6da0113f
commit 93e68a5a00
9 changed files with 299 additions and 20 deletions

View File

@ -51,6 +51,10 @@ enum GridType {
#include "editing_syms.h"
};
static const int DRAW_VEL_AUTO = -1;
static const int DRAW_CHAN_AUTO = -1;
static const GridType DRAW_LEN_AUTO = GridTypeNone; //special case: use the Grid's value instead of the note-length selection
extern const char *gridtypestrs[];
inline const char* enum2str(GridType m) {return gridtypestrs[m];}
GridType str2gridtype(const std::string &);

View File

@ -369,8 +369,10 @@ Editor::Editor ()
, have_pending_keyboard_selection (false)
, pending_keyboard_selection_start (0)
, _grid_type (GridTypeBeat)
, _draw_length (GridTypeNone)
, _snap_mode (SnapOff)
, _draw_length (GridTypeNone)
, _draw_velocity (-2)
, _draw_channel (-2)
, ignore_gui_changes (false)
, _drags (new DragManager (this))
, lock_dialog (0)
@ -855,8 +857,11 @@ Editor::Editor ()
setup_fade_images ();
/* these are defaults; instant.xml will replace these with user's recent selection */
set_grid_to (GridTypeNone);
set_draw_length_to (GridTypeBeat);
set_draw_velocity_to (82);
set_draw_channel_to (0);
}
Editor::~Editor()
@ -2103,6 +2108,18 @@ Editor::draw_length() const
return _draw_length;
}
int
Editor::draw_velocity() const
{
return _draw_velocity;
}
int
Editor::draw_channel() const
{
return _draw_channel;
}
bool
Editor::grid_musical() const
{
@ -2201,10 +2218,6 @@ Editor::set_draw_length_to (GridType gt)
gt = GridTypeBeat;
}
if (_draw_length == gt) { // already set
return;
}
_draw_length = gt;
unsigned int grid_index = (unsigned int)gt;
@ -2214,6 +2227,44 @@ Editor::set_draw_length_to (GridType gt)
}
}
void
Editor::set_draw_velocity_to (int v)
{
if ( v<0 || v>127 ) { //range-check midi channel
v = DRAW_VEL_AUTO;
}
_draw_velocity = v;
if (DRAW_VEL_AUTO==v) {
draw_velocity_selector.set_text (_("Auto"));
return;
}
char buf[64];
sprintf(buf, "%d", v );
draw_velocity_selector.set_text (buf);
}
void
Editor::set_draw_channel_to (int c)
{
if ( c<0 || c>15 ) { //range-check midi channel
c = DRAW_CHAN_AUTO;
}
_draw_channel = c;
if (DRAW_CHAN_AUTO==c) {
draw_channel_selector.set_text (_("Auto"));
return;
}
char buf[64];
sprintf(buf, "%d", c+1 );
draw_channel_selector.set_text (buf);
}
void
Editor::set_grid_to (GridType gt)
{
@ -2389,6 +2440,18 @@ Editor::set_state (const XMLNode& node, int version)
}
set_draw_length_to (draw_length);
int draw_vel;
if (!node.get_property ("draw-velocity", draw_vel)) {
draw_vel = DRAW_VEL_AUTO;
}
set_draw_velocity_to (draw_vel);
int draw_chan;
if (!node.get_property ("draw-channel", draw_chan)) {
draw_chan = DRAW_CHAN_AUTO;
}
set_draw_channel_to (draw_chan);
SnapMode sm;
if (node.get_property ("snap-mode", sm)) {
snap_mode_selection_done(sm);
@ -2557,7 +2620,6 @@ Editor::get_state ()
node->set_property ("zoom", samples_per_pixel);
node->set_property ("grid-type", _grid_type);
node->set_property ("draw-length", _draw_length);
node->set_property ("snap-mode", _snap_mode);
node->set_property ("internal-grid-type", internal_grid_type);
node->set_property ("internal-snap-mode", internal_snap_mode);
@ -2566,6 +2628,10 @@ Editor::get_state ()
node->set_property ("edit-point", _edit_point);
node->set_property ("visible-track-count", _visible_track_count);
node->set_property ("draw-length", _draw_length);
node->set_property ("draw-velocity", _draw_velocity);
node->set_property ("draw-channel", _draw_channel);
node->set_property ("playhead", _playhead_cursor->current_sample ());
node->set_property ("left-frame", _leftmost_sample);
node->set_property ("y-origin", vertical_adjustment.get_value ());
@ -3079,6 +3145,8 @@ Editor::setup_toolbar ()
mouse_mode_size_group->add_widget (grid_type_selector);
mouse_mode_size_group->add_widget (draw_length_selector);
mouse_mode_size_group->add_widget (draw_velocity_selector);
mouse_mode_size_group->add_widget (draw_channel_selector);
mouse_mode_size_group->add_widget (snap_mode_button);
mouse_mode_size_group->add_widget (edit_point_selector);
@ -3190,6 +3258,11 @@ Editor::setup_toolbar ()
grid_type_selector.set_name ("mouse mode button");
draw_length_selector.set_name ("mouse mode button");
draw_velocity_selector.set_name ("mouse mode button");
draw_channel_selector.set_name ("mouse mode button");
draw_velocity_selector.disable_scrolling ();
draw_velocity_selector.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::on_velocity_scroll_event), false);
snap_mode_button.set_name ("mouse mode button");
@ -3214,7 +3287,12 @@ Editor::setup_toolbar ()
/* Draw - these MIDI tools are only visible when in Draw mode */
draw_box.set_spacing (2);
draw_box.set_border_width (2);
draw_box.pack_start (draw_length_selector, false, false);
draw_box.pack_start (*manage (new Label (_("Len:"))), false, false);
draw_box.pack_start (draw_length_selector, false, false, 4);
draw_box.pack_start (*manage (new Label (_("Ch:"))), false, false);
draw_box.pack_start (draw_channel_selector, false, false, 4);
draw_box.pack_start (*manage (new Label (_("Vel:"))), false, false);
draw_box.pack_start (draw_velocity_selector, false, false, 4);
/* Pack everything in... */
@ -3251,6 +3329,25 @@ Editor::setup_toolbar ()
toolbar_hbox.show_all ();
}
bool
Editor::on_velocity_scroll_event (GdkEventScroll* ev)
{
int v = PBD::atoi (draw_velocity_selector.get_text ());
switch (ev->direction) {
case GDK_SCROLL_DOWN:
v = std::min (127, v + 1);
break;
case GDK_SCROLL_UP:
v = std::max (1, v - 1);
break;
default:
return false;
}
set_draw_velocity_to(v);
return true;
}
void
Editor::build_edit_point_menu ()
{
@ -3331,8 +3428,7 @@ Editor::build_grid_type_menu ()
grid_type_selector.AddMenuElem (MenuElem (grid_type_strings[(int)GridTypeCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeCDFrame)));
/* main grid: bars, quarter-notes, etc */
draw_length_selector.AddMenuElem (MenuElem (grid_type_strings[(int)GridTypeBar], sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_selection_done), (GridType) GridTypeBar)));
/* Note-Length when drawing */
draw_length_selector.AddMenuElem (MenuElem (grid_type_strings[(int)GridTypeBeat], sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_selection_done), (GridType) GridTypeBeat)));
draw_length_selector.AddMenuElem (MenuElem (grid_type_strings[(int)GridTypeBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_selection_done), (GridType) GridTypeBeatDiv2)));
draw_length_selector.AddMenuElem (MenuElem (grid_type_strings[(int)GridTypeBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_selection_done), (GridType) GridTypeBeatDiv4)));
@ -3340,6 +3436,24 @@ Editor::build_grid_type_menu ()
draw_length_selector.AddMenuElem (MenuElem (grid_type_strings[(int)GridTypeBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_selection_done), (GridType) GridTypeBeatDiv16)));
draw_length_selector.AddMenuElem (MenuElem (grid_type_strings[(int)GridTypeBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_selection_done), (GridType) GridTypeBeatDiv32)));
/* Note-Velocity when drawing */
{
draw_velocity_selector.AddMenuElem (MenuElem ("8", sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_selection_done), 8)));
draw_velocity_selector.AddMenuElem (MenuElem ("32", sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_selection_done), 32)));
draw_velocity_selector.AddMenuElem (MenuElem ("64", sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_selection_done), 64)));
draw_velocity_selector.AddMenuElem (MenuElem ("82", sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_selection_done), 82)));
draw_velocity_selector.AddMenuElem (MenuElem ("100", sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_selection_done), 100)));
draw_velocity_selector.AddMenuElem (MenuElem ("127", sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_selection_done), 127)));
}
draw_velocity_selector.AddMenuElem (MenuElem (_("Auto"), sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_selection_done), DRAW_VEL_AUTO)));
/* Note-Channel when drawing */
for (int i = 0; i<= 15; i++) {
char buf[64];
sprintf(buf, "%d", i+1);
draw_channel_selector.AddMenuElem (MenuElem (buf, sigc::bind (sigc::mem_fun(*this, &Editor::draw_channel_selection_done), i)));
}
draw_channel_selector.AddMenuElem (MenuElem (_("Auto"), sigc::bind (sigc::mem_fun(*this, &Editor::draw_channel_selection_done), DRAW_CHAN_AUTO)));
}
void
@ -3365,6 +3479,8 @@ Editor::setup_tooltips ()
set_tooltip (tav_shrink_button, _("Shrink Tracks"));
set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
set_tooltip (draw_length_selector, _("Note Length to Draw"));
set_tooltip (draw_velocity_selector, _("Note Velocity to Draw"));
set_tooltip (draw_channel_selector, _("Note Channel to Draw"));
set_tooltip (grid_type_selector, _("Grid Mode"));
set_tooltip (snap_mode_button, _("Snap Mode\n\nRight-click to visit Snap preferences."));
set_tooltip (edit_point_selector, _("Edit Point"));
@ -3779,6 +3895,24 @@ Editor::draw_length_selection_done (GridType gridtype)
}
}
void
Editor::draw_velocity_selection_done (int v)
{
RefPtr<RadioAction> ract = draw_velocity_action (v);
if (ract) {
ract->set_active ();
}
}
void
Editor::draw_channel_selection_done (int c)
{
RefPtr<RadioAction> ract = draw_channel_action (c);
if (ract) {
ract->set_active ();
}
}
void
Editor::snap_mode_selection_done (SnapMode mode)
{

View File

@ -185,15 +185,23 @@ public:
void next_grid_choice ();
void prev_grid_choice ();
void set_grid_to (Editing::GridType);
void set_draw_length_to (Editing::GridType);
void set_snap_mode (Editing::SnapMode);
void set_draw_length_to (Editing::GridType);
void set_draw_velocity_to (int);
void set_draw_channel_to (int);
Editing::SnapMode snap_mode () const;
Editing::GridType grid_type () const;
Editing::GridType draw_length () const;
bool grid_type_is_musical (Editing::GridType) const;
bool grid_musical () const;
bool on_velocity_scroll_event (GdkEventScroll*);
Editing::GridType draw_length () const;
int draw_velocity () const;
int draw_channel () const;
void undo (uint32_t n = 1);
void redo (uint32_t n = 1);
@ -1591,9 +1599,12 @@ private:
void move_range_selection_start_or_end_to_region_boundary (bool, bool);
Editing::GridType _grid_type;
Editing::GridType _draw_length;
Editing::SnapMode _snap_mode;
Editing::GridType _draw_length;
int _draw_velocity;
int _draw_channel;
bool ignore_gui_changes;
DragManager* _drags;
@ -1883,9 +1894,12 @@ private:
void cycle_edit_mode ();
ArdourWidgets::ArdourDropdown grid_type_selector;
ArdourWidgets::ArdourDropdown draw_length_selector;
void build_grid_type_menu ();
ArdourWidgets::ArdourDropdown draw_length_selector;
ArdourWidgets::ArdourDropdown draw_velocity_selector;
ArdourWidgets::ArdourDropdown draw_channel_selector;
ArdourWidgets::ArdourButton snap_mode_button;
bool snap_mode_button_clicked (GdkEventButton*);
@ -1901,16 +1915,26 @@ private:
std::vector<std::string> snap_mode_strings;
void grid_type_selection_done (Editing::GridType);
void draw_length_selection_done (Editing::GridType);
void snap_mode_selection_done (Editing::SnapMode);
void snap_mode_chosen (Editing::SnapMode);
void grid_type_chosen (Editing::GridType);
void draw_length_selection_done (Editing::GridType);
void draw_length_chosen (Editing::GridType);
void draw_velocity_selection_done (int);
void draw_velocity_chosen (int);
void draw_channel_selection_done (int);
void draw_channel_chosen (int);
Glib::RefPtr<Gtk::RadioAction> grid_type_action (Editing::GridType);
Glib::RefPtr<Gtk::RadioAction> draw_length_action (Editing::GridType);
Glib::RefPtr<Gtk::RadioAction> snap_mode_action (Editing::SnapMode);
Glib::RefPtr<Gtk::RadioAction> draw_length_action (Editing::GridType);
Glib::RefPtr<Gtk::RadioAction> draw_velocity_action (int);
Glib::RefPtr<Gtk::RadioAction> draw_channel_action (int);
//zoom focus meu stuff
ArdourWidgets::ArdourDropdown zoom_focus_selector;
void zoom_focus_selection_done (Editing::ZoomFocus);

View File

@ -622,6 +622,28 @@ Editor::register_actions ()
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-beat"), grid_type_strings[(int)GridTypeBeat].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBeat)));
ActionManager::register_radio_action (length_actions, draw_length_group, X_("draw-length-bar"), grid_type_strings[(int)GridTypeBar].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_length_chosen), Editing::GridTypeBar)));
Glib::RefPtr<ActionGroup> velocity_actions = ActionManager::create_action_group (bindings, X_("DrawVelocity"));
RadioAction::Group draw_velocity_group;
ActionManager::register_radio_action (velocity_actions, draw_velocity_group, X_("draw-velocity-auto"), _("Auto"), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_chosen), DRAW_VEL_AUTO)));
for (int i = 1; i <= 127; i++) {
char buf[64];
sprintf(buf, X_("draw-velocity-%d"), i);
char vel[64];
sprintf(vel, X_("%d"), i);
ActionManager::register_radio_action (velocity_actions, draw_velocity_group, buf, vel, (sigc::bind (sigc::mem_fun(*this, &Editor::draw_velocity_chosen), i)));
}
Glib::RefPtr<ActionGroup> channel_actions = ActionManager::create_action_group (bindings, X_("DrawChannel"));
RadioAction::Group draw_channel_group;
ActionManager::register_radio_action (channel_actions, draw_channel_group, X_("draw-channel-auto"), _("Auto"), (sigc::bind (sigc::mem_fun(*this, &Editor::draw_channel_chosen), DRAW_CHAN_AUTO)));
for (int i = 0; i <= 15; i++) {
char buf[64];
sprintf(buf, X_("draw-channel-%d"), i+1);
char ch[64];
sprintf(ch, X_("%d"), i+1);
ActionManager::register_radio_action (channel_actions, draw_channel_group, buf, ch, (sigc::bind (sigc::mem_fun(*this, &Editor::draw_channel_chosen), i)));
}
Glib::RefPtr<ActionGroup> snap_actions = ActionManager::create_action_group (bindings, X_("Snap"));
RadioAction::Group grid_choice_group;
@ -1083,6 +1105,54 @@ Editor::edit_current_tempo ()
edit_tempo_section (Temporal::TempoMap::use()->metric_at (ARDOUR_UI::instance()->primary_clock->absolute_time()).get_editable_tempo());
}
RefPtr<RadioAction>
Editor::draw_velocity_action (int v)
{
const char* action = 0;
RefPtr<Action> act;
if (v==DRAW_VEL_AUTO) {
action = "draw-velocity-auto";
} else if (v>=1 && v<=127) {
char buf[64];
sprintf(buf, X_("draw-velocity-%d"), v); //we don't allow drawing a velocity 0; some synths use that as note-off
action = buf;
}
act = ActionManager::get_action (X_("DrawVelocity"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;
} else {
error << string_compose (_("programming error: %1"), "Editor::draw_velocity_action could not find action to match velocity.") << endmsg;
return RefPtr<RadioAction>();
}
}
RefPtr<RadioAction>
Editor::draw_channel_action (int c)
{
const char* action = 0;
RefPtr<Action> act;
if (c==DRAW_CHAN_AUTO) {
action = "draw-channel-auto";
} else if (c>=0 && c<=15) {
char buf[64];
sprintf(buf, X_("draw-channel-%d"), c+1);
action = buf;
}
act = ActionManager::get_action (X_("DrawChannel"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;
} else {
error << string_compose (_("programming error: %1"), "Editor::draw_channel_action could not find action to match channel.") << endmsg;
return RefPtr<RadioAction>();
}
}
RefPtr<RadioAction>
Editor::draw_length_action (GridType type)
{
@ -1353,6 +1423,7 @@ Editor::grid_type_chosen (GridType type)
set_grid_to (type);
}
}
void
Editor::draw_length_chosen (GridType type)
{
@ -1368,6 +1439,36 @@ Editor::draw_length_chosen (GridType type)
}
}
void
Editor::draw_velocity_chosen (int v)
{
/* this is driven by a toggle on a radio group, and so is invoked twice,
once for the item that became inactive and once for the one that became
active.
*/
RefPtr<RadioAction> ract = draw_velocity_action (v);
if (ract && ract->get_active()) {
set_draw_velocity_to (v);
}
}
void
Editor::draw_channel_chosen (int c)
{
/* this is driven by a toggle on a radio group, and so is invoked twice,
once for the item that became inactive and once for the one that became
active.
*/
RefPtr<RadioAction> ract = draw_channel_action (c);
if (ract && ract->get_active()) {
set_draw_channel_to (c);
}
}
RefPtr<RadioAction>
Editor::snap_mode_action (SnapMode mode)
{

View File

@ -7033,6 +7033,8 @@ NoteCreateDrag::finished (GdkEvent* ev, bool had_movement)
length = length.round_to_subdivision (div, RoundUpMaybe);
}
#warning NUTEMPO ALERT not snapping correctly
_editor->begin_reversible_command (_("Create Note"));
_region_view->create_note_at (timepos_t (start), _drag_rect->y0(), length, ev->button.state, false);
_editor->commit_reversible_command ();
@ -7116,6 +7118,8 @@ HitCreateDrag::motion (GdkEvent* event, bool)
return;
}
#warning NUTEMPO ALERT not snapping correctly
_region_view->create_note_at (timepos_t (start), _y, length, event->button.state, false);
_last_pos = timepos_t (start);

View File

@ -370,9 +370,9 @@ Editor::mouse_mode_toggled (MouseMode m)
update_time_selection_display ();
if (mouse_mode == MouseDraw) {
draw_length_selector.set_sensitive(true);
draw_box.show();
} else {
draw_length_selector.set_sensitive(false);
draw_box.hide();
}

View File

@ -4214,11 +4214,11 @@ MidiRegionView::get_note_name (boost::shared_ptr<NoteType> n, uint8_t note_value
}
char buf[128];
snprintf (buf, sizeof (buf), "%d %s\nCh %d Vel %d",
(int) note_value,
snprintf (buf, sizeof (buf), "%s #%d\nCh %d Vel %d",
name.empty() ? ParameterDescriptor::midi_note_name (note_value).c_str() : name.c_str(),
(int) note_value,
(int) n->channel() + 1,
(int) n->velocity());
(int) n->velocity()); //we display velocity 0-based; velocity 0 is a 'note-off' so the user just sees values 1..127 which 'looks' 1-based
return buf;
}
@ -4252,6 +4252,11 @@ MidiRegionView::show_verbose_cursor (string const & text, double xoffset, double
uint8_t
MidiRegionView::get_velocity_for_add (MidiModel::TimeType time) const
{
PublicEditor& editor = trackview.editor();
if (editor.draw_velocity() != Editing::DRAW_VEL_AUTO) {
return editor.draw_velocity();
}
if (_model->notes().empty()) {
return 0x40; // No notes, use default
}

View File

@ -1726,6 +1726,10 @@ MidiTimeAxisView::stop_step_editing ()
uint8_t
MidiTimeAxisView::get_channel_for_add () const
{
if (_editor.draw_channel() != Editing::DRAW_CHAN_AUTO) {
return _editor.draw_channel();
}
uint16_t const chn_mask = midi_track()->get_playback_channel_mask();
int chn_cnt = 0;
uint8_t channel = 0;

View File

@ -372,6 +372,9 @@ public:
virtual Temporal::Beats get_grid_type_as_beats (bool& success, Temporal::timepos_t const & position) = 0;
virtual Temporal::Beats get_draw_length_as_beats (bool& success, Temporal::timepos_t const & position) = 0;
virtual int draw_velocity () const = 0;
virtual int draw_channel () const = 0;
virtual unsigned get_grid_beat_divisions (Editing::GridType gt) = 0;
virtual int32_t get_grid_music_divisions (Editing::GridType gt, uint32_t event_state) = 0;