#include "timecode/time.h"
#include "timecode/bbt_time.h"
+#include "ardour/amp.h"
#include "ardour/async_midi_port.h"
#include "ardour/audioengine.h"
#include "ardour/debug.h"
, octave_shift (0)
, percussion (false)
, _pressure_mode (AfterTouch)
+ , selection_color (LED::Green)
+ , contrast_color (LED::Green)
{
build_maps ();
error << _("Cannot construct Canvas for display") << endmsg;
libusb_release_interface (handle, 0x00);
libusb_close (handle);
+ handle = 0;
return -1;
}
Push2::close ()
{
init_buttons (false);
+ strip_buttons_off ();
/* wait for button data to be flushed */
AsyncMIDIPort* asp;
write (b->state_msg());
}
- /* Strip buttons should all be off (black) by default. They will change
- * color to reflect various conditions
- */
-
- strip_buttons_off ();
-
if (startup) {
/* all other buttons are off (black) */
}
}
+ if (_current_layout) {
+ _current_layout->update_meters ();
+ _current_layout->update_clocks ();
+ }
+
_canvas->vblank();
return true;
Push2::handle_midi_sysex (MIDI::Parser&, MIDI::byte* raw_bytes, size_t sz)
{
DEBUG_TRACE (DEBUG::Push2, string_compose ("Sysex, %1 bytes\n", sz));
+
+ if (sz < 8) {
+ return;
+ }
+
MidiByteArray msg (sz, raw_bytes);
- MidiByteArray aftertouch_mode_response (9, 0xF0, 0x00, 0x21, 0x1D, 0x01, 0x01, 0x1F, 0x0, 0xF7);
- MidiByteArray polypress_mode_response (9, 0xF0, 0x00, 0x21, 0x1D, 0x01, 0x01, 0x1F, 0x1, 0xF7);
-
- if (msg == aftertouch_mode_response) {
- _pressure_mode = AfterTouch;
- PressureModeChange (AfterTouch);
- cerr << "Pressure mod eis after\n";
- } else if (msg == polypress_mode_response) {
- _pressure_mode = PolyPressure;
- PressureModeChange (PolyPressure);
- cerr << "Pressure mod eis poly\n";
+ MidiByteArray push2_sysex_header (6, 0xF0, 0x00, 0x21, 0x1D, 0x01, 0x01);
+
+ if (!push2_sysex_header.compare_n (msg, 6)) {
+ return;
+ }
+
+ switch (msg[6]) {
+ case 0x1f: /* pressure mode */
+ if (msg[7] == 0x0) {
+ _pressure_mode = AfterTouch;
+ PressureModeChange (AfterTouch);
+ cerr << "Pressure mode is after\n";
+ } else {
+ _pressure_mode = PolyPressure;
+ PressureModeChange (PolyPressure);
+ cerr << "Pressure mode is poly\n";
+ }
+ break;
}
}
return;
}
- /* Pad */
+ /* Pad illuminations */
- NNPadMap::iterator pi = nn_pad_map.find (ev->note_number);
+ NNPadMap::const_iterator pm = nn_pad_map.find (ev->note_number);
- if (pi == nn_pad_map.end()) {
+ if (pm == nn_pad_map.end()) {
return;
}
- Pad* pad = pi->second;
+ const Pad * const pad_pressed = pm->second;
- 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);
+ pair<FNPadMap::iterator,FNPadMap::iterator> pads_with_note = fn_pad_map.equal_range (pad_pressed->filtered);
+
+ if (pads_with_note.first == fn_pad_map.end()) {
+ return;
+ }
+
+ for (FNPadMap::iterator pi = pads_with_note.first; pi != pads_with_note.second; ++pi) {
+ Pad* pad = pi->second;
+
+ pad->set_color (contrast_color);
pad->set_state (LED::OneShot24th);
write (pad->state_msg());
}
return;
}
- NNPadMap::iterator pi = nn_pad_map.find (ev->note_number);
+ /* Pad illuminations */
+
+ NNPadMap::const_iterator pm = nn_pad_map.find (ev->note_number);
- if (pi == nn_pad_map.end()) {
+ if (pm == nn_pad_map.end()) {
return;
}
- Pad* pad = pi->second;
+ const Pad * const pad_pressed = pm->second;
- 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());
+ pair<FNPadMap::iterator,FNPadMap::iterator> pads_with_note = fn_pad_map.equal_range (pad_pressed->filtered);
+
+ if (pads_with_note.first == fn_pad_map.end()) {
+ return;
+ }
+
+ for (FNPadMap::iterator pi = pads_with_note.first; pi != pads_with_note.second; ++pi) {
+ Pad* pad = pi->second;
+
+ 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
Push2::other_vpot (int n, int delta)
{
+ boost::shared_ptr<Amp> click_gain;
switch (n) {
case 0:
+ /* tempo control */
break;
case 1:
+ /* metronome gain control */
+ click_gain = session->click_gain();
+ if (click_gain) {
+ boost::shared_ptr<AutomationControl> ac = click_gain->gain_control();
+ if (ac) {
+ ac->set_value (ac->interface_to_internal (
+ min (ac->upper(), max (ac->lower(), ac->internal_to_interface (ac->get_value()) + (delta/256.0)))),
+ PBD::Controllable::UseGroup);
+ }
+ }
break;
case 2:
/* master gain control */
if (master) {
boost::shared_ptr<AutomationControl> ac = master->gain_control();
if (ac) {
- ac->set_value (ac->get_value() + ((2.0/64.0) * delta), PBD::Controllable::UseGroup);
+ ac->set_value (ac->interface_to_internal (
+ min (ac->upper(), max (ac->lower(), ac->internal_to_interface (ac->get_value()) + (delta/256.0)))),
+ PBD::Controllable::UseGroup);
}
}
break;
return 0;
}
+void
+Push2::update_selection_color ()
+{
+ boost::shared_ptr<MidiTrack> current_midi_track = current_pad_target.lock();
+
+ if (!current_midi_track) {
+ return;
+ }
+
+ selection_color = get_color_index (current_midi_track->presentation_info().color());
+ contrast_color = get_color_index (ArdourCanvas::HSV (current_midi_track->presentation_info().color()).opposite().color());
+
+ reset_pad_colors ();
+}
+
+void
+Push2::reset_pad_colors ()
+{
+ set_pad_scale (_scale_root, _root_octave, _mode, _in_key);
+}
+
void
Push2::set_pad_scale (int root, int octave, MusicalMode::Type mode, bool inkey)
{
}
}
+ fn_pad_map.clear ();
+
if (inkey) {
vector<int>::iterator notei;
int row_offset = 0;
+
for (int row = 0; row < 8; ++row) {
/* Ableton's grid layout wraps the available notes in the scale
notenum = *notei;
pad->filtered = notenum;
+ fn_pad_map.insert (make_pair (notenum, pad));
+
if ((notenum % 12) == original_root) {
- pad->set_color (LED::Green);
- pad->perma_color = LED::Green;
+ pad->set_color (selection_color);
+ pad->perma_color = selection_color;
} else {
pad->set_color (LED::White);
pad->perma_color = LED::White;
pad->filtered = -1;
}
+ pad->set_state (LED::OneShot24th);
write (pad->state_msg());
}
}
pad->filtered = root_start + (note - 36);
+ fn_pad_map.insert (make_pair (pad->filtered, pad));
+
if (mode_map.find (note) != mode_map.end()) {
if ((note % 12) == original_root) {
- pad->set_color (LED::Green);
- pad->perma_color = LED::Green;
+ pad->set_color (selection_color);
+ pad->perma_color = selection_color;
} else {
pad->set_color (LED::White);
pad->perma_color = LED::White;
}
+ pad->set_state (LED::OneShot24th);
write (pad->state_msg());
}
}
/* store state */
- _scale_root = original_root;
- _root_octave = octave;
- _in_key = inkey;
- _mode = mode;
+ bool changed = false;
+
+ if (_scale_root != original_root) {
+ _scale_root = original_root;
+ changed = true;
+ }
+ if (_root_octave != octave) {
+ _root_octave = octave;
+ changed = true;
+ }
+ if (_in_key != inkey) {
+ _in_key = inkey;
+ changed = true;
+ }
+ if (_mode != mode) {
+ _mode = mode;
+ changed = true;
+ }
- ScaleChange (); /* EMIT SIGNAL */
+ if (changed) {
+ ScaleChange (); /* EMIT SIGNAL */
+ }
}
void
int drum_note = 36;
+ fn_pad_map.clear ();
+
for (int row = 0; row < 8; ++row) {
for (int col = 0; col < 4; ++col) {
/* disconnect from pad port, if appropriate */
if (current_midi_track && pad_port) {
+
+ /* XXX this could possibly leave dangling MIDI notes.
+ *
+ * A general libardour fix is required. It isn't obvious
+ * how note resolution can be done unless disconnecting
+ * becomes "slow" (i.e. deferred for as long as it takes
+ * to resolve notes).
+ */
current_midi_track->input()->disconnect (current_midi_track->input()->nth(0), pad_port->name(), this);
}
if (new_pad_target && pad_port) {
new_pad_target->input()->connect (new_pad_target->input()->nth (0), pad_port->name(), this);
current_pad_target = new_pad_target;
+ selection_color = get_color_index (new_pad_target->presentation_info().color());
+ contrast_color = get_color_index (ArdourCanvas::HSV (new_pad_target->presentation_info().color()).opposite().color());
} else {
current_pad_target.reset ();
+ selection_color = LED::Green;
+ contrast_color = LED::Green;
}
+
+ reset_pad_colors ();
}
Push2::Button*
}
uint8_t
-Push2::get_color_index (uint32_t rgb)
+Push2::get_color_index (ArdourCanvas::Color rgba)
{
- ColorMap::iterator i = color_map.find (rgb);
+ ColorMap::iterator i = color_map.find (rgba);
if (i != color_map.end()) {
return i->second;
}
- int r, g, b, a;
- UINT_TO_RGBA (rgb, &r, &g, &b, &a);
- int w = 204; /* not sure where/when we should get this value */
+ double dr, dg, db, da;
+ int r, g, b;
+ ArdourCanvas::color_to_rgba (rgba, dr, dg, db, da);
+ int w = 126; /* not sure where/when we should get this value */
+
+
+ r = (int) floor (255.0 * dr);
+ g = (int) floor (255.0 * dg);
+ b = (int) floor (255.0 * db);
/* get a free index */
color_map_free_list.pop();
}
- MidiByteArray palette_msg (17, 0xf0, 0x00 , 0x21, 0x1d, 0x01, 0x01, 0x03, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x01, 0x7E, 0x00, 0xF7);
- MidiByteArray update_pallette_msg (8, 0xf0, 0x00, 0x21, 0x1d, 0x01, 0x01, 0x05, 0xF7);
-
+ MidiByteArray palette_msg (17,
+ 0xf0,
+ 0x00 , 0x21, 0x1d, 0x01, 0x01, 0x03, /* reset palette header */
+ 0x00, /* index = 7 */
+ 0x00, 0x00, /* r = 8 & 9 */
+ 0x00, 0x00, /* g = 10 & 11 */
+ 0x00, 0x00, /* b = 12 & 13 */
+ 0x00, 0x00, /* w (a?) = 14 & 15*/
+ 0xf7);
palette_msg[7] = index;
palette_msg[8] = r & 0x7f;
- palette_msg[9] = r & 0x1;
+ palette_msg[9] = (r & 0x80) >> 7;
palette_msg[10] = g & 0x7f;
- palette_msg[11] = g & 0x1;
+ palette_msg[11] = (g & 0x80) >> 7;
palette_msg[12] = b & 0x7f;
- palette_msg[13] = b & 0x1;
+ palette_msg[13] = (b & 0x80) >> 7;
palette_msg[14] = w & 0x7f;
- palette_msg[15] = w & 0x1;
+ palette_msg[15] = w & 0x80;
write (palette_msg);
+
+ MidiByteArray update_pallette_msg (8, 0xf0, 0x00, 0x21, 0x1d, 0x01, 0x01, 0x05, 0xF7);
write (update_pallette_msg);
- color_map[index] = rgb;
+ color_map[rgba] = index;
return index;
}
_previous_layout = _current_layout;
}
- /* turn off all strip buttons - let new layout set them if it
- * wants/needs to
- */
-
- strip_buttons_off ();
-
_current_layout = layout;
if (_current_layout) {