summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2016-07-07 14:26:55 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2016-09-27 14:59:30 -0500
commit2aec2161f9a0124fc5ad5a7843e03a1507a24627 (patch)
tree1e828528b15510f8c218749c6039238683230096 /libs
parent597c737ab57fda950768de19fffd6dd70fb2df49 (diff)
push2: initial sort of working pad remapping
Diffstat (limited to 'libs')
-rw-r--r--libs/surfaces/push2/buttons.cc3
-rw-r--r--libs/surfaces/push2/gui.cc153
-rw-r--r--libs/surfaces/push2/gui.h15
-rw-r--r--libs/surfaces/push2/mode.cc75
-rw-r--r--libs/surfaces/push2/mode.h11
-rw-r--r--libs/surfaces/push2/push2.cc133
-rw-r--r--libs/surfaces/push2/push2.h20
-rw-r--r--libs/surfaces/push2/wscript3
8 files changed, 323 insertions, 90 deletions
diff --git a/libs/surfaces/push2/buttons.cc b/libs/surfaces/push2/buttons.cc
index 0c443cb1ec..7bcdff0d77 100644
--- a/libs/surfaces/push2/buttons.cc
+++ b/libs/surfaces/push2/buttons.cc
@@ -42,13 +42,14 @@ Push2::build_maps ()
nn_pad_map.insert (std::make_pair (pad->extra(), pad)); \
coord_pad_map.insert (std::make_pair (pad->coord(), pad));
+ MAKE_PAD (0, 0, 92);
MAKE_PAD (0, 1, 93);
MAKE_PAD (0, 2, 94);
MAKE_PAD (0, 3, 95);
MAKE_PAD (0, 4, 96);
MAKE_PAD (0, 5, 97);
MAKE_PAD (0, 6, 98);
- MAKE_PAD (0, 7, 90);
+ MAKE_PAD (0, 7, 99);
MAKE_PAD (1, 0, 84);
MAKE_PAD (1, 1, 85);
MAKE_PAD (1, 2, 86);
diff --git a/libs/surfaces/push2/gui.cc b/libs/surfaces/push2/gui.cc
index 78772aeefd..8398132d3e 100644
--- a/libs/surfaces/push2/gui.cc
+++ b/libs/surfaces/push2/gui.cc
@@ -84,6 +84,12 @@ P2GUI::P2GUI (Push2& p)
, action_table (5, 4)
, ignore_active_change (false)
, pad_table (8, 8)
+ , root_note_octave_adjustment (3, 0, 10, 1, 1)
+ , root_note_octave (root_note_octave_adjustment)
+ , root_note_octave_label (X_("Octave"))
+ , root_note_label (X_("Root"))
+ , mode_label (X_("Mode (Scale)"))
+ , mode_packer (3, 2)
{
set_border_width (12);
@@ -132,17 +138,32 @@ P2GUI::P2GUI (Push2& p)
root_note_selector.set_model (build_note_columns());
root_note_selector.pack_start (note_columns.name);
+ root_note_selector.set_active (0);
mode_selector.set_model (build_mode_columns());
mode_selector.pack_start (mode_columns.name);
+ mode_selector.set_active (0);
- mode_packer.pack_start (root_note_selector, false, false);
- mode_packer.pack_start (mode_selector, false, false);
+ mode_packer.set_border_width (12);
+ mode_packer.set_spacings (12);
+
+ mode_packer.attach (root_note_label, 0, 1, 0, 1, AttachOptions (FILL|EXPAND), SHRINK);
+ mode_packer.attach (root_note_selector, 1, 2, 0, 1, AttachOptions (FILL|EXPAND), SHRINK);
+
+ mode_packer.attach (root_note_octave_label, 0, 1, 1, 2, AttachOptions (FILL|EXPAND), SHRINK);
+ mode_packer.attach (root_note_octave, 1, 2, 1, 2, AttachOptions (FILL|EXPAND), SHRINK);
+
+ mode_packer.attach (mode_label, 0, 1, 2, 3, AttachOptions (FILL|EXPAND), SHRINK);
+ mode_packer.attach (mode_selector, 1, 2, 2, 3, AttachOptions (FILL|EXPAND), SHRINK);
pad_notebook.append_page (pad_table, _("Pad Layout"));
pad_notebook.append_page (mode_packer, _("Modes/Scales"));
pad_notebook.append_page (custom_packer, _("Custom"));
+ root_note_octave_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &P2GUI::reprogram_pad_scale));
+ root_note_selector.signal_changed().connect (sigc::mem_fun (*this, &P2GUI::reprogram_pad_scale));
+ mode_selector.signal_changed().connect (sigc::mem_fun (*this, &P2GUI::reprogram_pad_scale));
+
set_spacing (12);
pack_start (hpacker, false, false);
@@ -446,16 +467,28 @@ P2GUI::build_mode_columns ()
TreeModel::Row row;
row = *store->append();
- row[mode_columns.name] = _("Random");
- row[mode_columns.mode] = MusicalMode::Random;
-
- row = *store->append();
row[mode_columns.name] = _("Dorian");
row[mode_columns.mode] = MusicalMode::Dorian;
row = *store->append();
- row[mode_columns.name] = _("Ionian (\"Minor\")");
- row[mode_columns.mode] = MusicalMode::Ionian;
+ row[mode_columns.name] = _("Ionian (\"Major\")");
+ row[mode_columns.mode] = MusicalMode::IonianMajor;
+
+ row = *store->append();
+ row[mode_columns.name] = _("Minor");
+ row[mode_columns.mode] = MusicalMode::Minor;
+
+ row = *store->append();
+ row[mode_columns.name] = _("Harmonic Minor");
+ row[mode_columns.mode] = MusicalMode::HarmonicMinor;
+
+ row = *store->append();
+ row[mode_columns.name] = _("Melodic Minor Ascending");
+ row[mode_columns.mode] = MusicalMode::MelodicMinorAscending;
+
+ row = *store->append();
+ row[mode_columns.name] = _("Melodic Minor Descending");
+ row[mode_columns.mode] = MusicalMode::MelodicMinorDescending;
row = *store->append();
row[mode_columns.name] = _("Phrygian");
@@ -486,22 +519,6 @@ P2GUI::build_mode_columns ()
row[mode_columns.mode] = MusicalMode::PentatonicMinor;
row = *store->append();
- row[mode_columns.name] = _("Major Chord");
- row[mode_columns.mode] = MusicalMode::MajorChord;
-
- row = *store->append();
- row[mode_columns.name] = _("Minor Chord");
- row[mode_columns.mode] = MusicalMode::MinorChord;
-
- row = *store->append();
- row[mode_columns.name] = _("Min7");
- row[mode_columns.mode] = MusicalMode::Min7;
-
- row = *store->append();
- row[mode_columns.name] = _("Sus4");
- row[mode_columns.mode] = MusicalMode::Sus4;
-
- row = *store->append();
row[mode_columns.name] = _("Chromatic");
row[mode_columns.mode] = MusicalMode::Chromatic;
@@ -610,11 +627,89 @@ P2GUI::build_note_columns ()
Glib::RefPtr<Gtk::ListStore> store = ListStore::create (note_columns);
TreeModel::Row row;
- for (int n = 0; n < 127; ++n) {
- row = *store->append ();
- row[note_columns.number] = n;
- row[note_columns.name] = Evoral::midi_note_name (n);
- }
+ row = *store->append ();
+ row[note_columns.number] = 0;
+ row[note_columns.name] = "C";
+
+ row = *store->append ();
+ row[note_columns.number] = 1;
+ row[note_columns.name] = "C#";
+
+ row = *store->append ();
+ row[note_columns.number] = 2;
+ row[note_columns.name] = "D";
+
+ row = *store->append ();
+ row[note_columns.number] = 3;
+ row[note_columns.name] = "D#";
+
+ row = *store->append ();
+ row[note_columns.number] = 4;
+ row[note_columns.name] = "E";
+
+ row = *store->append ();
+ row[note_columns.number] = 5;
+ row[note_columns.name] = "F";
+
+ row = *store->append ();
+ row[note_columns.number] = 6;
+ row[note_columns.name] = "F#";
+
+ row = *store->append ();
+ row[note_columns.number] = 7;
+ row[note_columns.name] = "G";
+
+ row = *store->append ();
+ row[note_columns.number] = 8;
+ row[note_columns.name] = "G#";
+
+ row = *store->append ();
+ row[note_columns.number] = 9;
+ row[note_columns.name] = "A";
+
+ row = *store->append ();
+ row[note_columns.number] = 10;
+ row[note_columns.name] = "A#";
+
+ row = *store->append ();
+ row[note_columns.number] = 11;
+ row[note_columns.name] = "B";
return store;
}
+
+void
+P2GUI::reprogram_pad_scale ()
+{
+ int root;
+ int octave;
+ MusicalMode::Type mode;
+
+ Gtk::TreeModel::iterator iter = root_note_selector.get_active();
+ if (iter) {
+ Gtk::TreeModel::Row row = *iter;
+ if (row) {
+ root = row[note_columns.number];
+ } else {
+ root = 5;
+ }
+ } else {
+ root = 5;
+ }
+
+ octave = (int) floor (root_note_octave_adjustment.get_value ());
+
+ iter = mode_selector.get_active();
+ if (iter) {
+ Gtk::TreeModel::Row row = *iter;
+ if (row) {
+ mode = row[mode_columns.mode];
+ } else {
+ mode = MusicalMode::IonianMajor;
+ }
+ } else {
+ mode = MusicalMode::IonianMajor;
+ }
+
+ p2.set_pad_scale (root, octave, mode);
+}
diff --git a/libs/surfaces/push2/gui.h b/libs/surfaces/push2/gui.h
index 2ec6281a52..1c38a16c2d 100644
--- a/libs/surfaces/push2/gui.h
+++ b/libs/surfaces/push2/gui.h
@@ -28,6 +28,7 @@
#include <gtkmm/image.h>
#include <gtkmm/table.h>
#include <gtkmm/treestore.h>
+#include <gtkmm/spinbutton.h>
#include <gtkmm/notebook.h>
namespace Gtk {
@@ -99,6 +100,12 @@ private:
/* root notes */
+ Gtk::Adjustment root_note_octave_adjustment;
+ Gtk::SpinButton root_note_octave;
+ Gtk::Label root_note_octave_label;
+
+ void root_note_octave_adjustment_changed ();
+
struct NoteColumns : public Gtk::TreeModel::ColumnRecord {
NoteColumns () {
add (number);
@@ -110,6 +117,9 @@ private:
NoteColumns note_columns;
Glib::RefPtr<Gtk::ListStore> build_note_columns ();
Gtk::ComboBox root_note_selector;
+ Gtk::Label root_note_label;
+
+ void root_note_changed ();
/* modes/scales */
@@ -124,10 +134,13 @@ private:
ModeColumns mode_columns;
Glib::RefPtr<Gtk::ListStore> build_mode_columns ();
Gtk::ComboBox mode_selector;
+ Gtk::Label mode_label;
Gtk::Notebook pad_notebook;
- Gtk::VBox mode_packer;
+ Gtk::Table mode_packer;
Gtk::VBox custom_packer;
+
+ void reprogram_pad_scale ();
};
}
diff --git a/libs/surfaces/push2/mode.cc b/libs/surfaces/push2/mode.cc
index 324c53caba..99efc86c02 100644
--- a/libs/surfaces/push2/mode.cc
+++ b/libs/surfaces/push2/mode.cc
@@ -19,9 +19,6 @@ MusicalMode::fill (MusicalMode& m, MusicalMode::Type t)
*/
switch (t) {
- case Random:
- m.steps.push_back (0.0); // sekrit code for "random"
- break;
case Dorian:
m.steps.push_back (1.0);
m.steps.push_back (1.5);
@@ -29,8 +26,9 @@ MusicalMode::fill (MusicalMode& m, MusicalMode::Type t)
m.steps.push_back (3.0);
m.steps.push_back (4.0);
m.steps.push_back (4.5);
+ m.steps.push_back (5.5);
break;
- case Ionian:
+ case IonianMajor:
m.steps.push_back (1.0);
m.steps.push_back (2.0);
m.steps.push_back (2.5);
@@ -38,6 +36,48 @@ MusicalMode::fill (MusicalMode& m, MusicalMode::Type t)
m.steps.push_back (4.5);
m.steps.push_back (5.5);
break;
+ case Minor:
+ m.steps.push_back (1.0);
+ m.steps.push_back (1.5);
+ m.steps.push_back (2.5);
+ m.steps.push_back (3.5);
+ m.steps.push_back (4.0);
+ m.steps.push_back (5.0);
+ break;
+ case HarmonicMinor:
+ m.steps.push_back (1.0);
+ m.steps.push_back (1.5);
+ m.steps.push_back (2.5);
+ m.steps.push_back (3.5);
+ m.steps.push_back (5.0);
+ m.steps.push_back (5.5);
+ break;
+ case BluesScale:
+ m.steps.push_back (1.0);
+ m.steps.push_back (1.5);
+ m.steps.push_back (2.5);
+ m.steps.push_back (3);
+ m.steps.push_back (3.5);
+ m.steps.push_back (4.5);
+ m.steps.push_back (5.0);
+ m.steps.push_back (5.5);
+ break;
+ case MelodicMinorAscending:
+ m.steps.push_back (1.0);
+ m.steps.push_back (1.5);
+ m.steps.push_back (2.5);
+ m.steps.push_back (3.5);
+ m.steps.push_back (4.5);
+ m.steps.push_back (5.5);
+ break;
+ case MelodicMinorDescending:
+ m.steps.push_back (1.0);
+ m.steps.push_back (2.0);
+ m.steps.push_back (2.5);
+ m.steps.push_back (3.5);
+ m.steps.push_back (4.5);
+ m.steps.push_back (5.0);
+ break;
case Phrygian:
m.steps.push_back (0.5);
m.steps.push_back (1.5);
@@ -90,23 +130,6 @@ MusicalMode::fill (MusicalMode& m, MusicalMode::Type t)
m.steps.push_back (3.5);
m.steps.push_back (5.0);
break;
- case MajorChord:
- m.steps.push_back (2.0);
- m.steps.push_back (3.5);
- break;
- case MinorChord:
- m.steps.push_back (1.5);
- m.steps.push_back (3.5);
- break;
- case Min7:
- m.steps.push_back (1.5);
- m.steps.push_back (3.5);
- m.steps.push_back (5.0);
- break;
- case Sus4:
- m.steps.push_back (2.5);
- m.steps.push_back (3.5);
- break;
case Chromatic:
m.steps.push_back (0.5);
m.steps.push_back (1.0);
@@ -120,16 +143,6 @@ MusicalMode::fill (MusicalMode& m, MusicalMode::Type t)
m.steps.push_back (5.0);
m.steps.push_back (5.5);
break;
- case BluesScale:
- m.steps.push_back (1.0);
- m.steps.push_back (1.5);
- m.steps.push_back (2.5);
- m.steps.push_back (3);
- m.steps.push_back (3.5);
- m.steps.push_back (4.5);
- m.steps.push_back (5.0);
- m.steps.push_back (5.5);
- break;
case NeapolitanMinor:
m.steps.push_back (0.5);
m.steps.push_back (1.5);
diff --git a/libs/surfaces/push2/mode.h b/libs/surfaces/push2/mode.h
index e638d53164..4f570f998d 100644
--- a/libs/surfaces/push2/mode.h
+++ b/libs/surfaces/push2/mode.h
@@ -7,9 +7,12 @@ class MusicalMode
{
public:
enum Type {
- Random,
Dorian,
- Ionian,
+ IonianMajor,
+ Minor,
+ HarmonicMinor,
+ MelodicMinorAscending,
+ MelodicMinorDescending,
Phrygian,
Lydian,
Mixolydian,
@@ -17,10 +20,6 @@ class MusicalMode
Locrian,
PentatonicMajor,
PentatonicMinor,
- MajorChord,
- MinorChord,
- Min7,
- Sus4,
Chromatic,
BluesScale,
NeapolitanMinor,
diff --git a/libs/surfaces/push2/push2.cc b/libs/surfaces/push2/push2.cc
index 40a454211f..a9de0aee01 100644
--- a/libs/surfaces/push2/push2.cc
+++ b/libs/surfaces/push2/push2.cc
@@ -107,13 +107,13 @@ Push2::Push2 (ARDOUR::Session& s)
StripableSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&Push2::stripable_selection_change, this, _1), this);
+ /* catch arrival and departure of Push2 itself */
ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect (port_reg_connection, MISSING_INVALIDATOR, boost::bind (&Push2::port_registration_handler, this), this);
/* Catch port connections and disconnections */
ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR, boost::bind (&Push2::connection_handler, this, _1, _2, _3, _4, _5), this);
/* ports might already be there */
-
port_registration_handler ();
}
@@ -848,9 +848,15 @@ Push2::handle_midi_note_on_message (MIDI::Parser& parser, MIDI::EventTwoBytes* e
Pad* pad = pi->second;
- pad->set_color (LED::White);
- pad->set_state (LED::OneShot24th);
- write (pad->state_msg());
+ if (pad->do_when_pressed == Pad::FlashOn) {
+ pad->set_color (LED::White);
+ pad->set_state (LED::OneShot24th);
+ write (pad->state_msg());
+ } else if (pad->do_when_pressed == Pad::FlashOff) {
+ pad->set_color (LED::Black);
+ pad->set_state (LED::OneShot24th);
+ write (pad->state_msg());
+ }
}
void
@@ -874,9 +880,15 @@ Push2::handle_midi_note_off_message (MIDI::Parser&, MIDI::EventTwoBytes* ev)
Pad* pad = pi->second;
- pad->set_color (LED::Black);
- pad->set_state (LED::OneShot24th);
- write (pad->state_msg());
+ if (pad->do_when_pressed == Pad::FlashOn) {
+ pad->set_color (LED::Black);
+ pad->set_state (LED::OneShot24th);
+ write (pad->state_msg());
+ } else if (pad->do_when_pressed == Pad::FlashOff) {
+ pad->set_color (pad->perma_color);
+ pad->set_state (LED::OneShot24th);
+ write (pad->state_msg());
+ }
}
void
@@ -1545,16 +1557,20 @@ Push2::pad_filter (MidiBuffer& in, MidiBuffer& out) const
if ((*ev).note() > 10 && (*ev).note() != 12) {
- int n = (*ev).note ();
-
- map<int,int>::const_iterator ni = pad_map.find (n);
+ const int n = (*ev).note ();
+ NNPadMap::const_iterator nni = nn_pad_map.find (n);
- if (ni != pad_map.end()) {
+ if (nni != nn_pad_map.end()) {
+ Pad const * pad = nni->second;
/* shift for output to the shadow port */
- (*ev).set_note (ni->second);
- out.push_back (*ev);
- /* shift back so that the pads light correctly */
- (*ev).set_note (n);
+ if (pad->filtered >= 0) {
+ (*ev).set_note (pad->filtered);
+ out.push_back (*ev);
+ /* shift back so that the pads light correctly */
+ (*ev).set_note (n);
+ } else {
+ /* no mapping, don't send event */
+ }
} else {
out.push_back (*ev);
}
@@ -1633,10 +1649,8 @@ Push2::input_port()
void
Push2::build_pad_table ()
{
- for (int row = 0; row < 8; ++row) {
- for (int col = 7; col >= 0; --col) {
- pad_map[row*8+col] = 99 - (row*8+(7-col)) + (octave_shift*12);
- }
+ for (int n = 36; n < 100; ++n) {
+ pad_map[n] = n + (octave_shift*12);
}
PadChange (); /* emit signal */
@@ -1653,3 +1667,84 @@ Push2::pad_note (int row, int col) const
return 0;
}
+
+void
+Push2::set_pad_scale (int root, int octave, MusicalMode::Type mode)
+{
+ cerr << "reset pad to r = " << root << " o = " << octave << " m = " << mode << endl;
+
+ MusicalMode m (mode);
+
+ if (mode == MusicalMode::Chromatic) {
+ /* back to "normal" */
+ for (int note = 36; note < 100; ++note) {
+ Pad* pad = nn_pad_map[note];
+ pad->do_when_pressed = Pad::FlashOn;
+ pad->set_color (LED::Black);
+ pad->perma_color = LED::Black;
+ pad->filtered = note;
+ write (pad->state_msg());
+ }
+
+ PadChange ();
+ return;
+ }
+
+ vector<float>::iterator interval;
+ int note;
+ int keep_root = root;
+
+ interval = m.steps.begin();
+ root += (octave*12);
+ note = root;
+
+ set<int> mode_map; /* contains only notes in mode */
+
+ mode_map.insert (note);
+
+ while (note < 128) {
+
+ if (interval == m.steps.end()) {
+
+ /* last distance was the end of the scale,
+ so wrap, adding the next note at one
+ octave above the last root.
+ */
+
+ interval = m.steps.begin();
+ root += 12;
+ mode_map.insert (root);
+
+ } else {
+ note = (int) floor (root + (2.0 * (*interval)));
+ interval++;
+ mode_map.insert (note);
+ }
+ }
+
+ for (note = 36; note < 100; ++note) {
+ Pad* pad = nn_pad_map[note];
+
+ if (mode_map.find (note) != mode_map.end()) {
+ if ((note % 12) == keep_root) {
+ pad->set_color (LED::Green);
+ pad->perma_color = LED::Green;
+ } else {
+ pad->set_color (LED::White);
+ pad->perma_color = LED::White;
+ }
+ pad->do_when_pressed = Pad::FlashOff;
+ /* Chromatic: all pads send their own note number */
+ pad->filtered = note;
+ } else {
+ /* note is not in mode, turn it off */
+ pad->do_when_pressed = Pad::Nothing;
+ pad->set_color (LED::Black);
+ pad->filtered = -1;
+ }
+
+ write (pad->state_msg());
+ }
+
+ PadChange (); /* EMIT SIGNAL */
+}
diff --git a/libs/surfaces/push2/push2.h b/libs/surfaces/push2/push2.h
index e065dc590a..806d5d0ad1 100644
--- a/libs/surfaces/push2/push2.h
+++ b/libs/surfaces/push2/push2.h
@@ -39,6 +39,7 @@
#include "control_protocol/types.h"
#include "midi_byte_array.h"
+#include "mode.h"
namespace Cairo {
class ImageSurface;
@@ -97,6 +98,8 @@ class Push2 : public ARDOUR::ControlProtocol
uint8_t pad_note (int row, int col) const;
PBD::Signal0<void> PadChange;
+ void set_pad_scale (int root, int octave, MusicalMode::Type mode);
+
private:
libusb_device_handle *handle;
uint8_t frame_header[16];
@@ -211,7 +214,7 @@ class Push2 : public ARDOUR::ControlProtocol
White = 122
};
- LED (uint8_t e) : _extra (e), _color_index (0), _state (NoTransition) {}
+ LED (uint8_t e) : _extra (e), _color_index (Black), _state (NoTransition) {}
virtual ~LED() {}
uint8_t extra () const { return _extra; }
@@ -230,10 +233,20 @@ class Push2 : public ARDOUR::ControlProtocol
};
struct Pad : public LED {
+ enum WhenPressed {
+ Nothing,
+ FlashOn,
+ FlashOff,
+ };
+
Pad (int xx, int yy, uint8_t ex)
: LED (ex)
, x (xx)
- , y (yy) {}
+ , y (yy)
+ , do_when_pressed (FlashOn)
+ , filtered (ex)
+ , perma_color (LED::Black)
+ {}
MidiByteArray state_msg () const { return MidiByteArray (3, 0x90|_state, _extra, _color_index); }
@@ -242,6 +255,9 @@ class Push2 : public ARDOUR::ControlProtocol
int x;
int y;
+ int do_when_pressed;
+ int filtered;
+ int perma_color;
};
struct Button : public LED {
diff --git a/libs/surfaces/push2/wscript b/libs/surfaces/push2/wscript
index 322b08f07e..b69d4a22ce 100644
--- a/libs/surfaces/push2/wscript
+++ b/libs/surfaces/push2/wscript
@@ -25,7 +25,8 @@ def build(bld):
interface.cc
midi_byte_array.cc
leds.cc
- gui.cc
+ gui.cc
+ mode.cc
'''
obj.export_includes = ['.']
obj.defines = [ 'PACKAGE="ardour_push2"' ]