+ 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 */
+
+ uint8_t index;
+
+ if (color_map_free_list.empty()) {
+ /* random replacement of any entry above zero and below 122 (where the
+ * Ableton standard colors live)
+ */
+ index = 1 + (random() % 121);
+ } else {
+ index = color_map_free_list.top();
+ color_map_free_list.pop();
+ }
+
+ 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 & 0x80) >> 7;
+ palette_msg[10] = g & 0x7f;
+ palette_msg[11] = (g & 0x80) >> 7;
+ palette_msg[12] = b & 0x7f;
+ palette_msg[13] = (b & 0x80) >> 7;
+ palette_msg[14] = w & 0x7f;
+ 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[rgba] = index;
+
+ return index;
+}
+
+void
+Push2::build_color_map ()
+{
+ /* These are "standard" colors that Ableton docs suggest will always be
+ there. Put them in our color map so that when we look up these
+ colors, we will use the Ableton indices for them.
+ */
+
+ color_map.insert (make_pair (RGB_TO_UINT (0,0,0), 0));
+ color_map.insert (make_pair (RGB_TO_UINT (204,204,204), 122));
+ color_map.insert (make_pair (RGB_TO_UINT (64,64,64), 123));
+ color_map.insert (make_pair (RGB_TO_UINT (20,20,20), 124));
+ color_map.insert (make_pair (RGB_TO_UINT (0,0,255), 125));
+ color_map.insert (make_pair (RGB_TO_UINT (0,255,0), 126));
+ color_map.insert (make_pair (RGB_TO_UINT (255,0,0), 127));
+
+ for (uint8_t n = 1; n < 122; ++n) {
+ color_map_free_list.push (n);
+ }
+}
+
+void
+Push2::fill_color_table ()
+{
+ colors.insert (make_pair (DarkBackground, ArdourCanvas::rgba_to_color (0, 0, 0, 1)));
+ colors.insert (make_pair (LightBackground, ArdourCanvas::rgba_to_color (0.98, 0.98, 0.98, 1)));
+
+ colors.insert (make_pair (ParameterName, ArdourCanvas::rgba_to_color (0.98, 0.98, 0.98, 1)));
+
+ colors.insert (make_pair (KnobArcBackground, ArdourCanvas::rgba_to_color (0.3, 0.3, 0.3, 1.0)));
+ colors.insert (make_pair (KnobArcStart, ArdourCanvas::rgba_to_color (1.0, 0.0, 0.0, 1.0)));
+ colors.insert (make_pair (KnobArcEnd, ArdourCanvas::rgba_to_color (0.0, 1.0, 0.0, 1.0)));
+
+ colors.insert (make_pair (KnobLineShadow, ArdourCanvas::rgba_to_color (0, 0, 0, 0.3)));
+ colors.insert (make_pair (KnobLine, ArdourCanvas::rgba_to_color (1, 1, 1, 1)));
+
+ colors.insert (make_pair (KnobForeground, ArdourCanvas::rgba_to_color (0.2, 0.2, 0.2, 1)));
+ colors.insert (make_pair (KnobBackground, ArdourCanvas::rgba_to_color (0.2, 0.2, 0.2, 1)));
+ colors.insert (make_pair (KnobShadow, ArdourCanvas::rgba_to_color (0, 0, 0, 0.1)));
+ colors.insert (make_pair (KnobBorder, ArdourCanvas::rgba_to_color (0, 0, 0, 1)));
+
+}
+
+ArdourCanvas::Color
+Push2::get_color (ColorName name)
+{
+ Colors::iterator c = colors.find (name);
+ if (c != colors.end()) {
+ return c->second;
+ }
+
+ return random();
+}
+
+void
+Push2::set_current_layout (Push2Layout* layout)
+{
+ if (_current_layout) {
+ _current_layout->hide ();
+ _canvas->root()->remove (_current_layout);
+ _previous_layout = _current_layout;
+ }
+
+ _current_layout = layout;
+
+ if (_current_layout) {
+ _canvas->root()->add (_current_layout);
+ _current_layout->show ();
+ }
+
+ _canvas->request_redraw ();
+}
+
+void
+Push2::use_previous_layout ()
+{
+ if (_previous_layout) {
+ set_current_layout (_previous_layout);
+ }
+}
+
+void
+Push2::request_pressure_mode ()
+{
+ MidiByteArray msg (8, 0xF0, 0x00, 0x21, 0x1D, 0x01, 0x01, 0x1F, 0xF7);
+ write (msg);
+}
+
+void
+Push2::set_pressure_mode (PressureMode pm)
+{
+ MidiByteArray msg (9, 0xF0, 0x00, 0x21, 0x1D, 0x01, 0x01, 0x1E, 0x0, 0xF7);
+
+ switch (pm) {
+ case AfterTouch:
+ /* nothing to do, message is correct */
+ break;
+ case PolyPressure:
+ msg[7] = 0x1;
+ break;
+ default:
+ return;
+ }
+
+ write (msg);
+ cerr << "Sent PM message " << msg << endl;