From e4e874bed04eb47849b41bcee4766d3b57024458 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 19 Jun 2021 15:12:12 -0400 Subject: [PATCH] Push2: Add "fixed" and "rooted" note grid option --- libs/surfaces/push2/push2.cc | 31 +++++++++++++++++------ libs/surfaces/push2/push2.h | 16 ++++++++++++ libs/surfaces/push2/scale.cc | 49 +++++++++++++++++++++++++++++++++--- libs/surfaces/push2/scale.h | 3 +++ 4 files changed, 89 insertions(+), 10 deletions(-) diff --git a/libs/surfaces/push2/push2.cc b/libs/surfaces/push2/push2.cc index 62f9dd1d90..5087ecabbf 100644 --- a/libs/surfaces/push2/push2.cc +++ b/libs/surfaces/push2/push2.cc @@ -214,7 +214,7 @@ Push2::begin_using_device () init_buttons (true); init_touch_strip (); - set_pad_scale (_scale_root, _root_octave, _mode, _row_interval, _in_key); + set_pad_scale (_scale_root, _root_octave, _mode, _note_grid_origin, _row_interval, _in_key); splash (); /* catch current selection, if any so that we can wire up the pads if appropriate */ @@ -1318,7 +1318,7 @@ Push2::update_selection_color () void Push2::reset_pad_colors () { - set_pad_scale (_scale_root, _root_octave, _mode, _row_interval, _in_key); + set_pad_scale (_scale_root, _root_octave, _mode, _note_grid_origin, _row_interval, _in_key); } void @@ -1437,13 +1437,17 @@ void Push2::set_pad_scale_in_key (const int scale_root, const int octave, const MusicalMode::Type mode, + const NoteGridOrigin origin, const int ideal_vertical_semitones) { const std::vector notes = mode_notes_vector (scale_root, octave, mode); + const int ideal_first_note = origin == Fixed ? 36 : scale_root + (12 * octave); + for (int row = 0; row < 8; ++row) { // The ideal leftmost note in a row is based only on the "tuning" - const int ideal_leftmost_note = 36 + (ideal_vertical_semitones * row); + const int ideal_leftmost_note = + ideal_first_note + (ideal_vertical_semitones * row); // If that's in the scale, use it, otherwise use the closest higher note std::vector::const_iterator n = @@ -1472,13 +1476,16 @@ void Push2::set_pad_scale_chromatic (const int scale_root, const int octave, const MusicalMode::Type mode, + const NoteGridOrigin origin, const int vertical_semitones) { const std::bitset<128> notes = mode_notes_bitset (scale_root, octave, mode); + const int first_note = origin == Fixed ? 36 : scale_root + (12 * octave); + for (int row = 0; row < 8; ++row) { // The leftmost note in a row is just based only on the "tuning" - const int leftmost_note = 36 + (vertical_semitones * row); + const int leftmost_note = first_note + (vertical_semitones * row); // Set up the the following columns in the row using the scale for (int col = 0; col < 8; ++col) { @@ -1505,6 +1512,7 @@ void Push2::set_pad_scale (const int scale_root, const int octave, const MusicalMode::Type mode, + const NoteGridOrigin origin, const RowInterval row_interval, const bool inkey) { @@ -1514,9 +1522,9 @@ Push2::set_pad_scale (const int scale_root, const int vertical_semitones = row_interval_semitones(row_interval); if (inkey) { - set_pad_scale_in_key(scale_root, octave, mode, vertical_semitones); + set_pad_scale_in_key(scale_root, octave, mode, origin, vertical_semitones); } else { - set_pad_scale_chromatic(scale_root, octave, mode, vertical_semitones); + set_pad_scale_chromatic(scale_root, octave, mode, origin, vertical_semitones); } // Store state @@ -1539,6 +1547,10 @@ Push2::set_pad_scale (const int scale_root, _mode = mode; changed = true; } + if (_note_grid_origin != origin) { + _note_grid_origin = origin; + changed = true; + } if (_row_interval != row_interval) { _row_interval = row_interval; changed = true; @@ -1553,7 +1565,12 @@ void Push2::set_percussive_mode (bool yn) { if (!yn) { - set_pad_scale (_scale_root, _root_octave, _mode, _row_interval, _in_key); + set_pad_scale (_scale_root, + _root_octave, + _mode, + _note_grid_origin, + _row_interval, + _in_key); _percussion = false; return; } diff --git a/libs/surfaces/push2/push2.h b/libs/surfaces/push2/push2.h index 6113093b0d..58c7ff3f51 100644 --- a/libs/surfaces/push2/push2.h +++ b/libs/surfaces/push2/push2.h @@ -325,6 +325,17 @@ class Push2 : public ARDOUR::ControlProtocol void update_selection_color (); + /** The "origin" or "root" of the note grid. + * + * This controls whether the grid is "fixed" in terms of the notes that it + * plays (so changing the scale is effectively just an overlay), or + * "rooted" so the root note of the scale is in the bottom left. + */ + enum NoteGridOrigin { + Fixed, ///< Bottom left pad is always C, or as close as possible + Rooted, ///< Bottom left pad is the scale root + }; + /** Interval between vertically adjacent note pads ("layout"). * * The comments describe the ideal interval that is used in chromatic mode. @@ -367,6 +378,7 @@ class Push2 : public ARDOUR::ControlProtocol void set_pad_scale_in_key (int root, int octave, MusicalMode::Type mode, + NoteGridOrigin origin, int ideal_vertical_semitones); /** Set a "chromatic" scale on the pads. @@ -389,17 +401,20 @@ class Push2 : public ARDOUR::ControlProtocol void set_pad_scale_chromatic (int root, int octave, MusicalMode::Type mode, + NoteGridOrigin origin, int vertical_semitones); void set_pad_scale (int root, int octave, MusicalMode::Type mode, + NoteGridOrigin origin, RowInterval row_interval, bool inkey); PBD::Signal0 ScaleChange; MusicalMode::Type mode() const { return _mode; } + NoteGridOrigin note_grid_origin() { return _note_grid_origin; } RowInterval row_interval() const { return _row_interval; } int scale_root() const { return _scale_root; } int root_octave() const { return _root_octave; } @@ -640,6 +655,7 @@ class Push2 : public ARDOUR::ControlProtocol void stripable_selection_changed (); MusicalMode::Type _mode; + NoteGridOrigin _note_grid_origin; RowInterval _row_interval; int _scale_root; int _root_octave; diff --git a/libs/surfaces/push2/scale.cc b/libs/surfaces/push2/scale.cc index e3236343b1..47591e745d 100644 --- a/libs/surfaces/push2/scale.cc +++ b/libs/surfaces/push2/scale.cc @@ -101,6 +101,18 @@ ScaleLayout::ScaleLayout (Push2& p, Session & s, std::string const & name) _chromatic_text->set_color (_p2.get_color (Push2::LightBackground)); _chromatic_text->set (_("Chromatic")); + _fixed_text = new Text (this); + _fixed_text->set_font_description (fd2); + _fixed_text->set_position (Duple (10 + (7 * Push2Canvas::inter_button_spacing()), 140)); + _fixed_text->set_color (_p2.get_color (Push2::LightBackground)); + _fixed_text->set (_("Fixed")); + + _rooted_text = new Text (this); + _rooted_text->set_font_description (fd2); + _rooted_text->set_position (Duple (45 + (7 * Push2Canvas::inter_button_spacing()), 140)); + _rooted_text->set_color (_p2.get_color (Push2::LightBackground)); + _rooted_text->set (_("Rooted")); + _row_interval_text = new Text (this); _row_interval_text->set_font_description (fd); _row_interval_text->set_position (Duple (10, 70)); @@ -241,6 +253,7 @@ ScaleLayout::button_upper (uint32_t n) _p2.set_pad_scale (root, _p2.root_octave (), _p2.mode (), + _p2.note_grid_origin (), _p2.row_interval (), _p2.in_key ()); } @@ -252,12 +265,14 @@ ScaleLayout::button_lower (uint32_t n) _p2.set_pad_scale (_p2.scale_root (), _p2.root_octave (), _p2.mode (), + _p2.note_grid_origin (), _p2.row_interval (), !_p2.in_key ()); return; } - int root = 0; + int root = _p2.scale_root(); + Push2::NoteGridOrigin origin = _p2.note_grid_origin (); switch (n) { case 1: @@ -286,12 +301,14 @@ ScaleLayout::button_lower (uint32_t n) break; case 7: /* fixed mode */ - return; + origin = (origin == Push2::Fixed) ? Push2::Rooted : Push2::Fixed; + break; } _p2.set_pad_scale (root, _p2.root_octave (), _p2.mode (), + origin, _p2.row_interval (), _p2.in_key ()); } @@ -356,6 +373,7 @@ ScaleLayout::show () } show_root_state (); + show_fixed_state (); Container::show (); } @@ -409,6 +427,7 @@ ScaleLayout::strip_vpot (int n, int delta) _p2.set_pad_scale (_p2.scale_root (), _p2.root_octave (), _p2.mode (), + _p2.note_grid_origin (), row_interval, _p2.in_key ()); @@ -629,13 +648,37 @@ ScaleLayout::show_root_state () } _scale_menu->set_active ((uint32_t) _p2.mode ()); + + show_fixed_state (); +} + +void +ScaleLayout::show_fixed_state () +{ + if (!parent()) { + /* don't do this stuff if we're not visible */ + return; + } + + if (_p2.note_grid_origin() == Push2::Fixed) { + _rooted_text->set_color (change_alpha (_fixed_text->color(), unselected_root_alpha)); + _fixed_text->set_color (change_alpha (_rooted_text->color(), 1.0)); + } else { + _fixed_text->set_color (change_alpha (_fixed_text->color(), unselected_root_alpha)); + _rooted_text->set_color (change_alpha (_rooted_text->color(), 1.0)); + } } void ScaleLayout::mode_changed () { MusicalMode::Type m = (MusicalMode::Type) _scale_menu->active(); - _p2.set_pad_scale (_p2.scale_root(), _p2.root_octave(), m, _p2.row_interval(), _p2.in_key()); + _p2.set_pad_scale (_p2.scale_root (), + _p2.root_octave (), + m, + _p2.note_grid_origin (), + _p2.row_interval (), + _p2.in_key ()); } void diff --git a/libs/surfaces/push2/scale.h b/libs/surfaces/push2/scale.h index ca6bce40c3..dc593a9717 100644 --- a/libs/surfaces/push2/scale.h +++ b/libs/surfaces/push2/scale.h @@ -59,6 +59,8 @@ class ScaleLayout : public Push2Layout ArdourCanvas::Text* _right_scroll_text; ArdourCanvas::Text* _inkey_text; ArdourCanvas::Text* _chromatic_text; + ArdourCanvas::Text* _fixed_text; + ArdourCanvas::Text* _rooted_text; ArdourCanvas::Text* _row_interval_text; ArdourCanvas::Text* _close_text; Push2Menu* _scale_menu; @@ -72,6 +74,7 @@ class ScaleLayout : public Push2Layout void mode_changed (); void menu_rearranged (); void show_root_state (); + void show_fixed_state (); void update_cursor_buttons (); };