Push2: Add UI for changing the vertical interval

This commit is contained in:
David Robillard 2021-06-19 02:14:58 -04:00 committed by Paul Davis
parent d5ca05edff
commit e93b7e2507
4 changed files with 125 additions and 29 deletions

View File

@ -78,6 +78,23 @@ using namespace Gtkmm2ext;
#define ABLETON 0x2982
#define PUSH2 0x1967
static int
row_interval_semitones (const Push2::RowInterval row_interval)
{
switch (row_interval) {
case Push2::Third:
return 4;
case Push2::Fourth:
return 5;
case Push2::Fifth:
return 7;
case Push2::Sequential:
return 8;
}
return 5;
}
Push2::Push2 (ARDOUR::Session& s)
: ControlProtocol (s, std::string (X_("Ableton Push 2")))
, AbstractUI<Push2Request> (name())
@ -90,6 +107,7 @@ Push2::Push2 (ARDOUR::Session& s)
, _connection_state (ConnectionState (0))
, _gui (0)
, _mode (MusicalMode::IonianMajor)
, _row_interval (Fourth)
, _scale_root (0)
, _root_octave (3)
, _in_key (true)
@ -196,7 +214,7 @@ Push2::begin_using_device ()
init_buttons (true);
init_touch_strip ();
set_pad_scale (_scale_root, _root_octave, _mode, _in_key);
set_pad_scale (_scale_root, _root_octave, _mode, _row_interval, _in_key);
splash ();
/* catch current selection, if any so that we can wire up the pads if appropriate */
@ -1306,7 +1324,7 @@ Push2::update_selection_color ()
void
Push2::reset_pad_colors ()
{
set_pad_scale (_scale_root, _root_octave, _mode, _in_key);
set_pad_scale (_scale_root, _root_octave, _mode, _row_interval, _in_key);
}
void
@ -1493,16 +1511,18 @@ void
Push2::set_pad_scale (const int scale_root,
const int octave,
const MusicalMode::Type mode,
const RowInterval row_interval,
const bool inkey)
{
// Clear the pad map and call the appropriate method to set them up again
_fn_pad_map.clear ();
const int vertical_semitones = row_interval_semitones(row_interval);
if (inkey) {
set_pad_scale_in_key(scale_root, octave, mode, 5);
set_pad_scale_in_key(scale_root, octave, mode, vertical_semitones);
} else {
set_pad_scale_chromatic(scale_root, octave, mode, 5);
set_pad_scale_chromatic(scale_root, octave, mode, vertical_semitones);
}
// Store state
@ -1525,6 +1545,10 @@ Push2::set_pad_scale (const int scale_root,
_mode = mode;
changed = true;
}
if (_row_interval != row_interval) {
_row_interval = row_interval;
changed = true;
}
if (changed) {
ScaleChange (); /* EMIT SIGNAL */
@ -1536,7 +1560,7 @@ Push2::set_percussive_mode (bool yn)
{
if (!yn) {
cerr << "back to scale\n";
set_pad_scale (_scale_root, _root_octave, _mode, _in_key);
set_pad_scale (_scale_root, _root_octave, _mode, _row_interval, _in_key);
_percussion = false;
return;
}

View File

@ -325,6 +325,19 @@ class Push2 : public ARDOUR::ControlProtocol
void update_selection_color ();
/** Interval between vertically adjacent note pads ("layout").
*
* The comments describe the ideal interval that is used in chromatic mode.
* For in-scale mode, they may be slightly adjusted, hence the more general
* enumerator names.
*/
enum RowInterval {
Third, /// Major third or 4 semitones
Fourth, /// Perfect fourth or 5 semitones
Fifth, /// Perfect fifth or 7 semitones
Sequential, /// Sequential from the last row, or 8 semitones
};
/// "Kind" of pad that plays a note
enum PadNoteKind { RootNote, InScaleNote, OutOfScaleNote };
@ -378,10 +391,16 @@ class Push2 : public ARDOUR::ControlProtocol
MusicalMode::Type mode,
int vertical_semitones);
void set_pad_scale (int root, int octave, MusicalMode::Type mode, bool inkey);
void set_pad_scale (int root,
int octave,
MusicalMode::Type mode,
RowInterval row_interval,
bool inkey);
PBD::Signal0<void> ScaleChange;
MusicalMode::Type mode() const { return _mode; }
RowInterval row_interval() const { return _row_interval; }
int scale_root() const { return _scale_root; }
int root_octave() const { return _root_octave; }
bool in_key() const { return _in_key; }
@ -621,6 +640,7 @@ class Push2 : public ARDOUR::ControlProtocol
void stripable_selection_changed ();
MusicalMode::Type _mode;
RowInterval _row_interval;
int _scale_root;
int _root_octave;
bool _in_key;

View File

@ -42,6 +42,23 @@ using namespace ArdourCanvas;
static double unselected_root_alpha = 0.5;
static const char*
row_interval_string (const Push2::RowInterval row_interval)
{
switch (row_interval) {
case Push2::Third:
return _("3rd \u2191");
case Push2::Fourth:
return _("4th \u2191");
case Push2::Fifth:
return _("5th \u2191");
case Push2::Sequential:
return _("Sequential \u21C9");
}
return "";
}
ScaleLayout::ScaleLayout (Push2& p, Session & s, std::string const & name)
: Push2Layout (p, s, name)
, _last_vpot (-1)
@ -62,7 +79,7 @@ ScaleLayout::ScaleLayout (Push2& p, Session & s, std::string const & name)
_close_text = new Text (this);
_close_text->set_font_description (fd);
_close_text->set_position (Duple (25, 5));
_close_text->set_position (Duple (10, 5));
_close_text->set_color (_p2.get_color (Push2::LightBackground));
_close_text->set (_("Close"));
@ -84,6 +101,12 @@ ScaleLayout::ScaleLayout (Push2& p, Session & s, std::string const & name)
_chromatic_text->set_color (_p2.get_color (Push2::LightBackground));
_chromatic_text->set (_("Chromatic"));
_row_interval_text = new Text (this);
_row_interval_text->set_font_description (fd);
_row_interval_text->set_position (Duple (10, 70));
_row_interval_text->set_color (_p2.get_color (Push2::LightBackground));
_row_interval_text->set (row_interval_string (_p2.row_interval ()));
for (int n = 0; n < 8; ++n) {
/* text labels for root notes etc.*/
@ -215,14 +238,22 @@ ScaleLayout::button_upper (uint32_t n)
return;
}
_p2.set_pad_scale (root, _p2.root_octave(), _p2.mode(), _p2.in_key());
_p2.set_pad_scale (root,
_p2.root_octave (),
_p2.mode (),
_p2.row_interval (),
_p2.in_key ());
}
void
ScaleLayout::button_lower (uint32_t n)
{
if (n == 0) {
_p2.set_pad_scale (_p2.scale_root(), _p2.root_octave(), _p2.mode(), !_p2.in_key());
_p2.set_pad_scale (_p2.scale_root (),
_p2.root_octave (),
_p2.mode (),
_p2.row_interval (),
!_p2.in_key ());
return;
}
@ -258,7 +289,11 @@ ScaleLayout::button_lower (uint32_t n)
return;
}
_p2.set_pad_scale (root, _p2.root_octave(), _p2.mode(), _p2.in_key());
_p2.set_pad_scale (root,
_p2.root_octave (),
_p2.mode (),
_p2.row_interval (),
_p2.in_key ());
}
void
@ -328,22 +363,18 @@ ScaleLayout::show ()
void
ScaleLayout::strip_vpot (int n, int delta)
{
/* menu starts under the 2nd-from-left vpot */
if (n == 0) {
return;
}
if (_last_vpot != n) {
uint32_t effective_column = n - 1;
uint32_t active = _scale_menu->active ();
if (n > 0) {
uint32_t effective_column = n - 1;
uint32_t active = _scale_menu->active ();
if (active / _scale_menu->rows() != effective_column) {
/* knob turned is different than the current active column.
Just change that.
*/
_scale_menu->set_active (effective_column * _scale_menu->rows()); /* top entry of that column */
return;
if (active / _scale_menu->rows() != effective_column) {
/* knob turned is different than the current active column.
Just change that.
*/
_scale_menu->set_active (effective_column * _scale_menu->rows()); /* top entry of that column */
return;
}
}
/* new vpot, reset delta cnt */
@ -365,10 +396,30 @@ ScaleLayout::strip_vpot (int n, int delta)
const int vpot_slowdown_factor = 4;
if ((_vpot_delta_cnt < 0) && (_vpot_delta_cnt % vpot_slowdown_factor == 0)) {
_scale_menu->scroll (Push2Menu::DirectionUp);
} else if (_vpot_delta_cnt % vpot_slowdown_factor == 0) {
_scale_menu->scroll (Push2Menu::DirectionDown);
const bool moved_enough = _vpot_delta_cnt % vpot_slowdown_factor == 0;
if (moved_enough) {
if (n == 0) {
Push2::RowInterval row_interval = _p2.row_interval();
if (_vpot_delta_cnt < 0 && row_interval > Push2::Third) {
row_interval = (Push2::RowInterval)(row_interval - 1);
} else if (_vpot_delta_cnt > 0 && row_interval < Push2::Sequential) {
row_interval = (Push2::RowInterval)(row_interval + 1);
}
_p2.set_pad_scale (_p2.scale_root (),
_p2.root_octave (),
_p2.mode (),
row_interval,
_p2.in_key ());
_row_interval_text->set(row_interval_string(row_interval));
} else {
if (_vpot_delta_cnt < 0) {
_scale_menu->scroll (Push2Menu::DirectionUp);
} else {
_scale_menu->scroll (Push2Menu::DirectionDown);
}
}
}
}
@ -584,7 +635,7 @@ void
ScaleLayout::mode_changed ()
{
MusicalMode::Type m = (MusicalMode::Type) _scale_menu->active();
_p2.set_pad_scale (_p2.scale_root(), _p2.root_octave(), m, _p2.in_key());
_p2.set_pad_scale (_p2.scale_root(), _p2.root_octave(), m, _p2.row_interval(), _p2.in_key());
}
void

View File

@ -59,6 +59,7 @@ class ScaleLayout : public Push2Layout
ArdourCanvas::Text* _right_scroll_text;
ArdourCanvas::Text* _inkey_text;
ArdourCanvas::Text* _chromatic_text;
ArdourCanvas::Text* _row_interval_text;
ArdourCanvas::Text* _close_text;
Push2Menu* _scale_menu;
int _last_vpot;