X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fsurfaces%2Fpush2%2Fpush2.cc;h=ec234be7128b4c7cf92fb756c36804a5a3e41e9d;hb=6d5878a92614304711fb77b0c863d68cb2d44d21;hp=24a11be29ddec18f7bb7167d0fe7db300b380d75;hpb=06683b1bda1b85febb77ab2e73c9ea0b7e8890fb;p=ardour.git diff --git a/libs/surfaces/push2/push2.cc b/libs/surfaces/push2/push2.cc index 24a11be29d..ec234be712 100644 --- a/libs/surfaces/push2/push2.cc +++ b/libs/surfaces/push2/push2.cc @@ -42,6 +42,8 @@ #include "gtkmm2ext/gui_thread.h" #include "gtkmm2ext/rgb_macros.h" +#include "canvas/colors.h" + #include "canvas.h" #include "gui.h" #include "layout.h" @@ -135,6 +137,8 @@ Push2::Push2 (ARDOUR::Session& s) , octave_shift (0) , percussion (false) , _pressure_mode (AfterTouch) + , selection_color (LED::Green) + , contrast_color (LED::Green) { build_maps (); @@ -298,6 +302,7 @@ int Push2::close () { init_buttons (false); + strip_buttons_off (); /* wait for button data to be flushed */ AsyncMIDIPort* asp; @@ -376,12 +381,6 @@ Push2::init_buttons (bool startup) 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) */ @@ -623,18 +622,30 @@ void 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; } } @@ -792,22 +803,26 @@ Push2::handle_midi_note_on_message (MIDI::Parser& parser, MIDI::EventTwoBytes* e 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 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()); } @@ -826,22 +841,34 @@ Push2::handle_midi_note_off_message (MIDI::Parser&, MIDI::EventTwoBytes* ev) 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 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()); + } } } @@ -1247,6 +1274,27 @@ Push2::pad_note (int row, int col) const return 0; } +void +Push2::update_selection_color () +{ + boost::shared_ptr 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) { @@ -1291,10 +1339,13 @@ Push2::set_pad_scale (int root, int octave, MusicalMode::Type mode, bool inkey) } } + fn_pad_map.clear (); + if (inkey) { vector::iterator notei; int row_offset = 0; + for (int row = 0; row < 8; ++row) { /* Ableton's grid layout wraps the available notes in the scale @@ -1314,9 +1365,11 @@ Push2::set_pad_scale (int root, int octave, MusicalMode::Type mode, bool inkey) 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; @@ -1332,6 +1385,7 @@ Push2::set_pad_scale (int root, int octave, MusicalMode::Type mode, bool inkey) pad->filtered = -1; } + pad->set_state (LED::OneShot24th); write (pad->state_msg()); } } @@ -1350,11 +1404,13 @@ Push2::set_pad_scale (int root, int octave, MusicalMode::Type mode, bool inkey) 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; @@ -1371,18 +1427,35 @@ Push2::set_pad_scale (int root, int octave, MusicalMode::Type mode, bool inkey) } + 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; - ScaleChange (); /* EMIT SIGNAL */ + 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; + } + + if (changed) { + ScaleChange (); /* EMIT SIGNAL */ + } } void @@ -1397,6 +1470,8 @@ Push2::set_percussive_mode (bool yn) int drum_note = 36; + fn_pad_map.clear (); + for (int row = 0; row < 8; ++row) { for (int col = 0; col < 4; ++col) { @@ -1462,6 +1537,14 @@ Push2::stripable_selection_change (StripableNotificationListPtr selected) /* 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); } @@ -1472,9 +1555,15 @@ Push2::stripable_selection_change (StripableNotificationListPtr selected) 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* @@ -1484,17 +1573,23 @@ Push2::button_by_id (ButtonID bid) } 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 */ @@ -1510,23 +1605,31 @@ Push2::get_color_index (uint32_t rgb) 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; } @@ -1594,12 +1697,6 @@ Push2::set_current_layout (Push2Layout* layout) _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) {