update pad colors when selected track colors chane
[ardour.git] / libs / surfaces / push2 / push2.cc
1 /*
2   Copyright (C) 2016 Paul Davis
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program; if not, write to the Free Software
16   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #include <stdlib.h>
20
21 #include "pbd/compose.h"
22 #include "pbd/convert.h"
23 #include "pbd/debug.h"
24 #include "pbd/failed_constructor.h"
25 #include "pbd/file_utils.h"
26 #include "pbd/search_path.h"
27 #include "pbd/enumwriter.h"
28
29 #include "midi++/parser.h"
30 #include "timecode/time.h"
31 #include "timecode/bbt_time.h"
32
33 #include "ardour/async_midi_port.h"
34 #include "ardour/audioengine.h"
35 #include "ardour/debug.h"
36 #include "ardour/midiport_manager.h"
37 #include "ardour/midi_track.h"
38 #include "ardour/midi_port.h"
39 #include "ardour/session.h"
40 #include "ardour/tempo.h"
41
42 #include "gtkmm2ext/gui_thread.h"
43 #include "gtkmm2ext/rgb_macros.h"
44
45 #include "canvas/colors.h"
46
47 #include "canvas.h"
48 #include "gui.h"
49 #include "layout.h"
50 #include "menu.h"
51 #include "mix.h"
52 #include "push2.h"
53 #include "scale.h"
54 #include "splash.h"
55 #include "track_mix.h"
56
57 #include "pbd/i18n.h"
58
59 using namespace ARDOUR;
60 using namespace std;
61 using namespace PBD;
62 using namespace Glib;
63 using namespace ArdourSurface;
64
65 #include "pbd/abstract_ui.cc" // instantiate template
66
67 #define ABLETON 0x2982
68 #define PUSH2   0x1967
69
70 __attribute__((constructor)) static void
71 register_enums ()
72 {
73         EnumWriter& enum_writer (EnumWriter::instance());
74         vector<int> i;
75         vector<string> s;
76
77         MusicalMode::Type mode;
78
79 #define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
80 #define REGISTER_CLASS_ENUM(t,e) i.push_back (t::e); s.push_back (#e)
81
82         REGISTER_CLASS_ENUM (MusicalMode,Dorian);
83         REGISTER_CLASS_ENUM (MusicalMode, IonianMajor);
84         REGISTER_CLASS_ENUM (MusicalMode, Minor);
85         REGISTER_CLASS_ENUM (MusicalMode, HarmonicMinor);
86         REGISTER_CLASS_ENUM (MusicalMode, MelodicMinorAscending);
87         REGISTER_CLASS_ENUM (MusicalMode, MelodicMinorDescending);
88         REGISTER_CLASS_ENUM (MusicalMode, Phrygian);
89         REGISTER_CLASS_ENUM (MusicalMode, Lydian);
90         REGISTER_CLASS_ENUM (MusicalMode, Mixolydian);
91         REGISTER_CLASS_ENUM (MusicalMode, Aeolian);
92         REGISTER_CLASS_ENUM (MusicalMode, Locrian);
93         REGISTER_CLASS_ENUM (MusicalMode, PentatonicMajor);
94         REGISTER_CLASS_ENUM (MusicalMode, PentatonicMinor);
95         REGISTER_CLASS_ENUM (MusicalMode, Chromatic);
96         REGISTER_CLASS_ENUM (MusicalMode, BluesScale);
97         REGISTER_CLASS_ENUM (MusicalMode, NeapolitanMinor);
98         REGISTER_CLASS_ENUM (MusicalMode, NeapolitanMajor);
99         REGISTER_CLASS_ENUM (MusicalMode, Oriental);
100         REGISTER_CLASS_ENUM (MusicalMode, DoubleHarmonic);
101         REGISTER_CLASS_ENUM (MusicalMode, Enigmatic);
102         REGISTER_CLASS_ENUM (MusicalMode, Hirajoshi);
103         REGISTER_CLASS_ENUM (MusicalMode, HungarianMinor);
104         REGISTER_CLASS_ENUM (MusicalMode, HungarianMajor);
105         REGISTER_CLASS_ENUM (MusicalMode, Kumoi);
106         REGISTER_CLASS_ENUM (MusicalMode, Iwato);
107         REGISTER_CLASS_ENUM (MusicalMode, Hindu);
108         REGISTER_CLASS_ENUM (MusicalMode, Spanish8Tone);
109         REGISTER_CLASS_ENUM (MusicalMode, Pelog);
110         REGISTER_CLASS_ENUM (MusicalMode, HungarianGypsy);
111         REGISTER_CLASS_ENUM (MusicalMode, Overtone);
112         REGISTER_CLASS_ENUM (MusicalMode, LeadingWholeTone);
113         REGISTER_CLASS_ENUM (MusicalMode, Arabian);
114         REGISTER_CLASS_ENUM (MusicalMode, Balinese);
115         REGISTER_CLASS_ENUM (MusicalMode, Gypsy);
116         REGISTER_CLASS_ENUM (MusicalMode, Mohammedan);
117         REGISTER_CLASS_ENUM (MusicalMode, Javanese);
118         REGISTER_CLASS_ENUM (MusicalMode, Persian);
119         REGISTER_CLASS_ENUM (MusicalMode, Algerian);
120         REGISTER (mode);
121 }
122
123 Push2::Push2 (ARDOUR::Session& s)
124         : ControlProtocol (s, string (X_("Ableton Push 2")))
125         , AbstractUI<Push2Request> (name())
126         , handle (0)
127         , _modifier_state (None)
128         , splash_start (0)
129         , _current_layout (0)
130         , _previous_layout (0)
131         , connection_state (ConnectionState (0))
132         , gui (0)
133         , _mode (MusicalMode::IonianMajor)
134         , _scale_root (0)
135         , _root_octave (3)
136         , _in_key (true)
137         , octave_shift (0)
138         , percussion (false)
139         , _pressure_mode (AfterTouch)
140         , selection_color (LED::Green)
141         , contrast_color (LED::Green)
142 {
143
144         build_maps ();
145         build_color_map ();
146         fill_color_table ();
147
148         /* master cannot be removed, so no need to connect to going-away signal */
149         master = session->master_out ();
150
151         if (open ()) {
152                 throw failed_constructor ();
153         }
154
155         ControlProtocol::StripableSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&Push2::stripable_selection_change, this, _1), this);
156
157         /* catch current selection, if any */
158         {
159                 StripableNotificationListPtr sp (new StripableNotificationList (ControlProtocol::last_selected()));
160                 stripable_selection_change (sp);
161         }
162
163         /* catch arrival and departure of Push2 itself */
164         ARDOUR::AudioEngine::instance()->PortRegisteredOrUnregistered.connect (port_reg_connection, MISSING_INVALIDATOR, boost::bind (&Push2::port_registration_handler, this), this);
165
166         /* Catch port connections and disconnections */
167         ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR, boost::bind (&Push2::connection_handler, this, _1, _2, _3, _4, _5), this);
168
169         /* ports might already be there */
170         port_registration_handler ();
171 }
172
173 Push2::~Push2 ()
174 {
175         stop ();
176
177         delete track_mix_layout;
178         delete mix_layout;
179         delete scale_layout;
180 }
181
182 void
183 Push2::port_registration_handler ()
184 {
185         if (!_async_in && !_async_out) {
186                 /* ports not registered yet */
187                 return;
188         }
189
190         if (_async_in->connected() && _async_out->connected()) {
191                 /* don't waste cycles here */
192                 return;
193         }
194
195         string input_port_name = X_("Ableton Push 2 MIDI 1 in");
196         string output_port_name = X_("Ableton Push 2 MIDI 1 out");
197         vector<string> in;
198         vector<string> out;
199
200         AudioEngine::instance()->get_ports (string_compose (".*%1", input_port_name), DataType::MIDI, PortFlags (IsPhysical|IsOutput), in);
201         AudioEngine::instance()->get_ports (string_compose (".*%1", output_port_name), DataType::MIDI, PortFlags (IsPhysical|IsInput), out);
202
203         if (!in.empty() && !out.empty()) {
204                 cerr << "Push2: both ports found\n";
205                 cerr << "\tconnecting to " << in.front() <<  " + " << out.front() << endl;
206                 if (!_async_in->connected()) {
207                         AudioEngine::instance()->connect (_async_in->name(), in.front());
208                 }
209                 if (!_async_out->connected()) {
210                         AudioEngine::instance()->connect (_async_out->name(), out.front());
211                 }
212         }
213 }
214
215 int
216 Push2::open ()
217 {
218         int err;
219
220         if (handle) {
221                 /* already open */
222                 return 0;
223         }
224
225         if ((handle = libusb_open_device_with_vid_pid (NULL, ABLETON, PUSH2)) == 0) {
226                 return -1;
227         }
228
229         if ((err = libusb_claim_interface (handle, 0x00))) {
230                 return -1;
231         }
232
233         try {
234                 _canvas = new Push2Canvas (*this, 960, 160);
235                 mix_layout = new MixLayout (*this, *session);
236                 scale_layout = new ScaleLayout (*this, *session);
237                 track_mix_layout = new TrackMixLayout (*this, *session);
238                 splash_layout = new SplashLayout (*this, *session);
239         } catch (...) {
240                 error << _("Cannot construct Canvas for display") << endmsg;
241                 libusb_release_interface (handle, 0x00);
242                 libusb_close (handle);
243                 return -1;
244         }
245
246         /* setup ports */
247
248         _async_in  = AudioEngine::instance()->register_input_port (DataType::MIDI, X_("Push 2 in"), true);
249         _async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, X_("Push 2 out"), true);
250
251         if (_async_in == 0 || _async_out == 0) {
252                 return -1;
253         }
254
255         /* We do not add our ports to the input/output bundles because we don't
256          * want users wiring them by hand. They could use JACK tools if they
257          * really insist on that.
258          */
259
260         _input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in).get();
261         _output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out).get();
262
263         /* Create a shadow port where, depending on the state of the surface,
264          * we will make pad note on/off events appear. The surface code will
265          * automatically this port to the first selected MIDI track.
266          */
267
268         boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->add_shadow_port (string_compose (_("%1 Pads"), X_("Push 2")), boost::bind (&Push2::pad_filter, this, _1, _2));
269         boost::shared_ptr<MidiPort> shadow_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->shadow_port();
270
271         if (shadow_port) {
272
273                 _output_bundle.reset (new ARDOUR::Bundle (_("Push 2 Pads"), false));
274
275                 _output_bundle->add_channel (
276                         shadow_port->name(),
277                         ARDOUR::DataType::MIDI,
278                         session->engine().make_port_name_non_relative (shadow_port->name())
279                         );
280         }
281
282         session->BundleAddedOrRemoved ();
283
284         connect_to_parser ();
285
286         return 0;
287 }
288
289 list<boost::shared_ptr<ARDOUR::Bundle> >
290 Push2::bundles ()
291 {
292         list<boost::shared_ptr<ARDOUR::Bundle> > b;
293
294         if (_output_bundle) {
295                 b.push_back (_output_bundle);
296         }
297
298         return b;
299 }
300
301 int
302 Push2::close ()
303 {
304         init_buttons (false);
305         strip_buttons_off ();
306
307         /* wait for button data to be flushed */
308         AsyncMIDIPort* asp;
309         asp = dynamic_cast<AsyncMIDIPort*> (_output_port);
310         asp->drain (10000, 500000);
311
312         AudioEngine::instance()->unregister_port (_async_in);
313         AudioEngine::instance()->unregister_port (_async_out);
314
315         _async_in.reset ((ARDOUR::Port*) 0);
316         _async_out.reset ((ARDOUR::Port*) 0);
317         _input_port = 0;
318         _output_port = 0;
319
320         periodic_connection.disconnect ();
321         session_connections.drop_connections ();
322
323         if (_current_layout) {
324                 _canvas->root()->remove (_current_layout);
325                 _current_layout = 0;
326         }
327
328         delete mix_layout;
329         mix_layout = 0;
330         delete scale_layout;
331         scale_layout = 0;
332         delete splash_layout;
333         splash_layout = 0;
334
335         if (handle) {
336                 libusb_release_interface (handle, 0x00);
337                 libusb_close (handle);
338                 handle = 0;
339         }
340
341         return 0;
342 }
343
344 void
345 Push2::strip_buttons_off ()
346 {
347         ButtonID strip_buttons[] = { Upper1, Upper2, Upper3, Upper4, Upper5, Upper6, Upper7, Upper8,
348                                      Lower1, Lower2, Lower3, Lower4, Lower5, Lower6, Lower7, Lower8, };
349
350         for (size_t n = 0; n < sizeof (strip_buttons) / sizeof (strip_buttons[0]); ++n) {
351                 Button* b = id_button_map[strip_buttons[n]];
352
353                 b->set_color (LED::Black);
354                 b->set_state (LED::OneShot24th);
355                 write (b->state_msg());
356         }
357 }
358
359
360 void
361 Push2::init_buttons (bool startup)
362 {
363         /* This is a list of buttons that we want lit because they do something
364            in ardour related (loosely, sometimes) to their illuminated label.
365         */
366
367         ButtonID buttons[] = { Mute, Solo, Master, Up, Right, Left, Down, Note, Session, Mix, AddTrack, Delete, Undo,
368                                Metronome, Shift, Select, Play, RecordEnable, Automate, Repeat, Note, Session, DoubleLoop,
369                                Quantize, Duplicate, Browse, PageRight, PageLeft, OctaveUp, OctaveDown, Layout, Scale
370         };
371
372         for (size_t n = 0; n < sizeof (buttons) / sizeof (buttons[0]); ++n) {
373                 Button* b = id_button_map[buttons[n]];
374
375                 if (startup) {
376                         b->set_color (LED::White);
377                 } else {
378                         b->set_color (LED::Black);
379                 }
380                 b->set_state (LED::OneShot24th);
381                 write (b->state_msg());
382         }
383
384         if (startup) {
385
386                 /* all other buttons are off (black) */
387
388                 ButtonID off_buttons[] = { TapTempo, Setup, User, Stop, Convert, New, FixedLength,
389                                            Fwd32ndT, Fwd32nd, Fwd16thT, Fwd16th, Fwd8thT, Fwd8th, Fwd4trT, Fwd4tr,
390                                            Accent, Note, Session,  };
391
392                 for (size_t n = 0; n < sizeof (off_buttons) / sizeof (off_buttons[0]); ++n) {
393                         Button* b = id_button_map[off_buttons[n]];
394
395                         b->set_color (LED::Black);
396                         b->set_state (LED::OneShot24th);
397                         write (b->state_msg());
398                 }
399         }
400
401         if (!startup) {
402                 for (NNPadMap::iterator pi = nn_pad_map.begin(); pi != nn_pad_map.end(); ++pi) {
403                         Pad* pad = pi->second;
404
405                         pad->set_color (LED::Black);
406                         pad->set_state (LED::OneShot24th);
407                         write (pad->state_msg());
408                 }
409         }
410 }
411
412 bool
413 Push2::probe ()
414 {
415         libusb_device_handle *h;
416         libusb_init (NULL);
417
418         if ((h = libusb_open_device_with_vid_pid (NULL, ABLETON, PUSH2)) == 0) {
419                 DEBUG_TRACE (DEBUG::Push2, "no Push2 device found\n");
420                 return false;
421         }
422
423         libusb_close (h);
424         DEBUG_TRACE (DEBUG::Push2, "Push2 device located\n");
425         return true;
426 }
427
428 void*
429 Push2::request_factory (uint32_t num_requests)
430 {
431         /* AbstractUI<T>::request_buffer_factory() is a template method only
432            instantiated in this source module. To provide something visible for
433            use in the interface/descriptor, we have this static method that is
434            template-free.
435         */
436         return request_buffer_factory (num_requests);
437 }
438
439 void
440 Push2::do_request (Push2Request * req)
441 {
442         if (req->type == CallSlot) {
443
444                 call_slot (MISSING_INVALIDATOR, req->the_slot);
445
446         } else if (req->type == Quit) {
447
448                 stop ();
449         }
450 }
451
452 int
453 Push2::stop ()
454 {
455         BaseUI::quit ();
456         close ();
457         return 0;
458 }
459
460
461 void
462 Push2::splash ()
463 {
464         set_current_layout (splash_layout);
465         splash_start = get_microseconds ();
466 }
467
468 bool
469 Push2::vblank ()
470 {
471         if (splash_start) {
472
473                 /* display splash for 2 seconds */
474
475                 if (get_microseconds() - splash_start > 2000000) {
476                         splash_start = 0;
477                         DEBUG_TRACE (DEBUG::Push2, "splash interval ended, switch to mix layout\n");
478                         set_current_layout (mix_layout);
479                 }
480         }
481
482         _canvas->vblank();
483
484         return true;
485 }
486
487 int
488 Push2::set_active (bool yn)
489 {
490         DEBUG_TRACE (DEBUG::Push2, string_compose("Push2Protocol::set_active init with yn: '%1'\n", yn));
491
492         if (yn == active()) {
493                 return 0;
494         }
495
496         if (yn) {
497
498                 /* start event loop */
499
500                 BaseUI::run ();
501
502                 if (open ()) {
503                         DEBUG_TRACE (DEBUG::Push2, "device open failed\n");
504                         close ();
505                         return -1;
506                 }
507
508                 /* Connect input port to event loop */
509
510                 AsyncMIDIPort* asp;
511
512                 asp = dynamic_cast<AsyncMIDIPort*> (_input_port);
513                 asp->xthread().set_receive_handler (sigc::bind (sigc::mem_fun (this, &Push2::midi_input_handler), _input_port));
514                 asp->xthread().attach (main_loop()->get_context());
515
516                 connect_session_signals ();
517
518                 /* set up periodic task used to push a frame buffer to the
519                  * device (25fps). The device can handle 60fps, but we don't
520                  * need that frame rate.
521                  */
522
523                 Glib::RefPtr<Glib::TimeoutSource> vblank_timeout = Glib::TimeoutSource::create (40); // milliseconds
524                 vblank_connection = vblank_timeout->connect (sigc::mem_fun (*this, &Push2::vblank));
525                 vblank_timeout->attach (main_loop()->get_context());
526
527
528                 Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (1000); // milliseconds
529                 periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &Push2::periodic));
530                 periodic_timeout->attach (main_loop()->get_context());
531
532                 init_buttons (true);
533                 init_touch_strip ();
534                 set_pad_scale (_scale_root, _root_octave, _mode, _in_key);
535                 splash ();
536
537         } else {
538
539                 stop ();
540
541         }
542
543         ControlProtocol::set_active (yn);
544
545         DEBUG_TRACE (DEBUG::Push2, string_compose("Push2Protocol::set_active done with yn: '%1'\n", yn));
546
547         return 0;
548 }
549
550 void
551 Push2::init_touch_strip ()
552 {
553         MidiByteArray msg (9, 0xf0, 0x00, 0x21, 0x1d, 0x01, 0x01, 0x17, 0x00, 0xf7);
554         /* flags are the final byte (ignore end-of-sysex */
555
556         /* show bar, not point
557            autoreturn to center
558            bar starts at center
559         */
560         msg[7] = (1<<4) | (1<<5) | (1<<6);
561         write (msg);
562 }
563
564 void
565 Push2::write (const MidiByteArray& data)
566 {
567         /* immediate delivery */
568         _output_port->write (&data[0], data.size(), 0);
569 }
570
571 bool
572 Push2::midi_input_handler (IOCondition ioc, MIDI::Port* port)
573 {
574         if (ioc & ~IO_IN) {
575                 DEBUG_TRACE (DEBUG::Push2, "MIDI port closed\n");
576                 return false;
577         }
578
579         if (ioc & IO_IN) {
580
581                 // DEBUG_TRACE (DEBUG::Push2, string_compose ("something happend on  %1\n", port->name()));
582
583                 AsyncMIDIPort* asp = dynamic_cast<AsyncMIDIPort*>(port);
584                 if (asp) {
585                         asp->clear ();
586                 }
587
588                 //DEBUG_TRACE (DEBUG::Push2, string_compose ("data available on %1\n", port->name()));
589                 framepos_t now = AudioEngine::instance()->sample_time();
590                 port->parse (now);
591         }
592
593         return true;
594 }
595
596 bool
597 Push2::periodic ()
598 {
599         return true;
600 }
601
602 void
603 Push2::connect_to_parser ()
604 {
605         DEBUG_TRACE (DEBUG::Push2, string_compose ("Connecting to signals on port %2\n", _input_port->name()));
606
607         MIDI::Parser* p = _input_port->parser();
608
609         /* Incoming sysex */
610         p->sysex.connect_same_thread (*this, boost::bind (&Push2::handle_midi_sysex, this, _1, _2, _3));
611         /* V-Pot messages are Controller */
612         p->controller.connect_same_thread (*this, boost::bind (&Push2::handle_midi_controller_message, this, _1, _2));
613         /* Button messages are NoteOn */
614         p->note_on.connect_same_thread (*this, boost::bind (&Push2::handle_midi_note_on_message, this, _1, _2));
615         /* Button messages are NoteOn but libmidi++ sends note-on w/velocity = 0 as note-off so catch them too */
616         p->note_off.connect_same_thread (*this, boost::bind (&Push2::handle_midi_note_on_message, this, _1, _2));
617         /* Fader messages are Pitchbend */
618         p->channel_pitchbend[0].connect_same_thread (*this, boost::bind (&Push2::handle_midi_pitchbend_message, this, _1, _2));
619 }
620
621 void
622 Push2::handle_midi_sysex (MIDI::Parser&, MIDI::byte* raw_bytes, size_t sz)
623 {
624         DEBUG_TRACE (DEBUG::Push2, string_compose ("Sysex, %1 bytes\n", sz));
625
626         if (sz < 8) {
627                 return;
628         }
629
630         MidiByteArray msg (sz, raw_bytes);
631         MidiByteArray push2_sysex_header (6, 0xF0, 0x00, 0x21, 0x1D, 0x01, 0x01);
632
633         if (!push2_sysex_header.compare_n (msg, 6)) {
634                 return;
635         }
636
637         switch (msg[6]) {
638         case 0x1f: /* pressure mode */
639                 if (msg[7] == 0x0) {
640                         _pressure_mode = AfterTouch;
641                         PressureModeChange (AfterTouch);
642                         cerr << "Pressure mode is after\n";
643                 } else {
644                         _pressure_mode = PolyPressure;
645                         PressureModeChange (PolyPressure);
646                         cerr << "Pressure mode is poly\n";
647                 }
648                 break;
649         }
650 }
651
652 void
653 Push2::handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes* ev)
654 {
655         DEBUG_TRACE (DEBUG::Push2, string_compose ("CC %1 (value %2)\n", (int) ev->controller_number, (int) ev->value));
656
657         CCButtonMap::iterator b = cc_button_map.find (ev->controller_number);
658
659         if (ev->value) {
660                 /* any press cancels any pending long press timeouts */
661                 for (set<ButtonID>::iterator x = buttons_down.begin(); x != buttons_down.end(); ++x) {
662                         Button* bb = id_button_map[*x];
663                         bb->timeout_connection.disconnect ();
664                 }
665         }
666
667         if (b != cc_button_map.end()) {
668
669                 Button* button = b->second;
670
671                 if (ev->value) {
672                         buttons_down.insert (button->id);
673                         start_press_timeout (*button, button->id);
674                 } else {
675                         buttons_down.erase (button->id);
676                         button->timeout_connection.disconnect ();
677                 }
678
679
680                 set<ButtonID>::iterator c = consumed.find (button->id);
681
682                 if (c == consumed.end()) {
683                         if (ev->value == 0) {
684                                 (this->*button->release_method)();
685                         } else {
686                                 (this->*button->press_method)();
687                         }
688                 } else {
689                         DEBUG_TRACE (DEBUG::Push2, "button was consumed, ignored\n");
690                         consumed.erase (c);
691                 }
692
693         } else {
694
695                 /* encoder/vpot */
696
697                 int delta = ev->value;
698
699                 if (delta > 63) {
700                         delta = -(128 - delta);
701                 }
702
703                 switch (ev->controller_number) {
704                 case 71:
705                         _current_layout->strip_vpot (0, delta);
706                         break;
707                 case 72:
708                         _current_layout->strip_vpot (1, delta);
709                         break;
710                 case 73:
711                         _current_layout->strip_vpot (2, delta);
712                         break;
713                 case 74:
714                         _current_layout->strip_vpot (3, delta);
715                         break;
716                 case 75:
717                         _current_layout->strip_vpot (4, delta);
718                         break;
719                 case 76:
720                         _current_layout->strip_vpot (5, delta);
721                         break;
722                 case 77:
723                         _current_layout->strip_vpot (6, delta);
724                         break;
725                 case 78:
726                         _current_layout->strip_vpot (7, delta);
727                         break;
728
729                         /* left side pair */
730                 case 14:
731                         other_vpot (8, delta);
732                         break;
733                 case 15:
734                         other_vpot (1, delta);
735                         break;
736
737                         /* right side */
738                 case 79:
739                         other_vpot (2, delta);
740                         break;
741                 }
742         }
743 }
744
745 void
746 Push2::handle_midi_note_on_message (MIDI::Parser& parser, MIDI::EventTwoBytes* ev)
747 {
748         // DEBUG_TRACE (DEBUG::Push2, string_compose ("Note On %1 (velocity %2)\n", (int) ev->note_number, (int) ev->velocity));
749
750         if (ev->velocity == 0) {
751                 handle_midi_note_off_message (parser, ev);
752                 return;
753         }
754
755         switch (ev->note_number) {
756         case 0:
757                 _current_layout->strip_vpot_touch (0, ev->velocity > 64);
758                 break;
759         case 1:
760                 _current_layout->strip_vpot_touch (1, ev->velocity > 64);
761                 break;
762         case 2:
763                 _current_layout->strip_vpot_touch (2, ev->velocity > 64);
764                 break;
765         case 3:
766                 _current_layout->strip_vpot_touch (3, ev->velocity > 64);
767                 break;
768         case 4:
769                 _current_layout->strip_vpot_touch (4, ev->velocity > 64);
770                 break;
771         case 5:
772                 _current_layout->strip_vpot_touch (5, ev->velocity > 64);
773                 break;
774         case 6:
775                 _current_layout->strip_vpot_touch (6, ev->velocity > 64);
776                 break;
777         case 7:
778                 _current_layout->strip_vpot_touch (7, ev->velocity > 64);
779                 break;
780
781                 /* left side */
782         case 10:
783                 other_vpot_touch (0, ev->velocity > 64);
784                 break;
785         case 9:
786                 other_vpot_touch (1, ev->velocity > 64);
787                 break;
788
789                 /* right side */
790         case 8:
791                 other_vpot_touch (3, ev->velocity > 64);
792                 break;
793
794                 /* touch strip */
795         case 12:
796                 if (ev->velocity < 64) {
797                         transport_stop ();
798                 }
799                 break;
800         }
801
802         if (ev->note_number < 11) {
803                 return;
804         }
805
806         /* Pad illuminations */
807
808         NNPadMap::const_iterator pm = nn_pad_map.find (ev->note_number);
809
810         if (pm == nn_pad_map.end()) {
811                 return;
812         }
813
814         const Pad * const pad_pressed = pm->second;
815
816         pair<FNPadMap::iterator,FNPadMap::iterator> pads_with_note = fn_pad_map.equal_range (pad_pressed->filtered);
817
818         if (pads_with_note.first == fn_pad_map.end()) {
819                 return;
820         }
821
822         for (FNPadMap::iterator pi = pads_with_note.first; pi != pads_with_note.second; ++pi) {
823                 Pad* pad = pi->second;
824
825                 pad->set_color (contrast_color);
826                 pad->set_state (LED::OneShot24th);
827                 write (pad->state_msg());
828         }
829 }
830
831 void
832 Push2::handle_midi_note_off_message (MIDI::Parser&, MIDI::EventTwoBytes* ev)
833 {
834         // DEBUG_TRACE (DEBUG::Push2, string_compose ("Note Off %1 (velocity %2)\n", (int) ev->note_number, (int) ev->velocity));
835
836         if (ev->note_number < 11) {
837                 /* theoretically related to encoder touch start/end, but
838                  * actually they send note on with two different velocity
839                  * values (127 & 64).
840                  */
841                 return;
842         }
843
844         /* Pad illuminations */
845
846         NNPadMap::const_iterator pm = nn_pad_map.find (ev->note_number);
847
848         if (pm == nn_pad_map.end()) {
849                 return;
850         }
851
852         const Pad * const pad_pressed = pm->second;
853
854         pair<FNPadMap::iterator,FNPadMap::iterator> pads_with_note = fn_pad_map.equal_range (pad_pressed->filtered);
855
856         if (pads_with_note.first == fn_pad_map.end()) {
857                 return;
858         }
859
860         for (FNPadMap::iterator pi = pads_with_note.first; pi != pads_with_note.second; ++pi) {
861                 Pad* pad = pi->second;
862
863                 if (pad->do_when_pressed == Pad::FlashOn) {
864                         pad->set_color (LED::Black);
865                         pad->set_state (LED::OneShot24th);
866                         write (pad->state_msg());
867                 } else if (pad->do_when_pressed == Pad::FlashOff) {
868                         pad->set_color (pad->perma_color);
869                         pad->set_state (LED::OneShot24th);
870                         write (pad->state_msg());
871                 }
872         }
873 }
874
875 void
876 Push2::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb)
877 {
878 }
879
880 void
881 Push2::thread_init ()
882 {
883         struct sched_param rtparam;
884
885         pthread_set_name (event_loop_name().c_str());
886
887         PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
888         ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
889
890         memset (&rtparam, 0, sizeof (rtparam));
891         rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
892
893         if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
894                 // do we care? not particularly.
895         }
896 }
897
898 void
899 Push2::connect_session_signals()
900 {
901         // receive routes added
902         //session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_routes_added, this, _1), this);
903         // receive VCAs added
904         //session->vca_manager().VCAAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_vca_added, this, _1), this);
905
906         // receive record state toggled
907         session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_record_state_changed, this), this);
908         // receive transport state changed
909         session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_transport_state_changed, this), this);
910         session->TransportLooped.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_loop_state_changed, this), this);
911         // receive punch-in and punch-out
912         Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_parameter_changed, this, _1), this);
913         session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_parameter_changed, this, _1), this);
914         // receive rude solo changed
915         session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_solo_active_changed, this, _1), this);
916 }
917
918 void
919 Push2::notify_record_state_changed ()
920 {
921         IDButtonMap::iterator b = id_button_map.find (RecordEnable);
922
923         if (b == id_button_map.end()) {
924                 return;
925         }
926
927         switch (session->record_status ()) {
928         case Session::Disabled:
929                 b->second->set_color (LED::White);
930                 b->second->set_state (LED::NoTransition);
931                 break;
932         case Session::Enabled:
933                 b->second->set_color (LED::Red);
934                 b->second->set_state (LED::Blinking4th);
935                 break;
936         case Session::Recording:
937                 b->second->set_color (LED::Red);
938                 b->second->set_state (LED::OneShot24th);
939                 break;
940         }
941
942         write (b->second->state_msg());
943 }
944
945 void
946 Push2::notify_transport_state_changed ()
947 {
948         Button* b = id_button_map[Play];
949
950         if (session->transport_rolling()) {
951                 b->set_state (LED::OneShot24th);
952                 b->set_color (LED::Green);
953         } else {
954
955                 /* disable any blink on FixedLength from pending edit range op */
956                 Button* fl = id_button_map[FixedLength];
957
958                 fl->set_color (LED::Black);
959                 fl->set_state (LED::NoTransition);
960                 write (fl->state_msg());
961
962                 b->set_color (LED::White);
963                 b->set_state (LED::NoTransition);
964         }
965
966         write (b->state_msg());
967 }
968
969 void
970 Push2::notify_loop_state_changed ()
971 {
972 }
973
974 void
975 Push2::notify_parameter_changed (std::string param)
976 {
977         IDButtonMap::iterator b;
978
979         if (param == "clicking") {
980                 if ((b = id_button_map.find (Metronome)) == id_button_map.end()) {
981                         return;
982                 }
983                 if (Config->get_clicking()) {
984                         b->second->set_state (LED::Blinking4th);
985                         b->second->set_color (LED::White);
986                 } else {
987                         b->second->set_color (LED::White);
988                         b->second->set_state (LED::NoTransition);
989                 }
990                 write (b->second->state_msg ());
991         }
992 }
993
994 void
995 Push2::notify_solo_active_changed (bool yn)
996 {
997         IDButtonMap::iterator b = id_button_map.find (Solo);
998
999         if (b == id_button_map.end()) {
1000                 return;
1001         }
1002
1003         if (yn) {
1004                 b->second->set_state (LED::Blinking4th);
1005                 b->second->set_color (LED::Red);
1006         } else {
1007                 b->second->set_state (LED::NoTransition);
1008                 b->second->set_color (LED::White);
1009         }
1010
1011         write (b->second->state_msg());
1012 }
1013
1014 XMLNode&
1015 Push2::get_state()
1016 {
1017         XMLNode& node (ControlProtocol::get_state());
1018         XMLNode* child;
1019
1020         child = new XMLNode (X_("Input"));
1021         child->add_child_nocopy (_async_in->get_state());
1022         node.add_child_nocopy (*child);
1023         child = new XMLNode (X_("Output"));
1024         child->add_child_nocopy (_async_out->get_state());
1025         node.add_child_nocopy (*child);
1026
1027         node.add_property (X_("root"), to_string (_scale_root, std::dec));
1028         node.add_property (X_("root_octave"), to_string (_root_octave, std::dec));
1029         node.add_property (X_("in_key"), _in_key ? X_("yes") : X_("no"));
1030         node.add_property (X_("mode"), enum_2_string (_mode));
1031
1032         return node;
1033 }
1034
1035 int
1036 Push2::set_state (const XMLNode & node, int version)
1037 {
1038         DEBUG_TRACE (DEBUG::Push2, string_compose ("Push2::set_state: active %1\n", active()));
1039
1040         int retval = 0;
1041
1042         if (ControlProtocol::set_state (node, version)) {
1043                 return -1;
1044         }
1045
1046         XMLNode* child;
1047
1048         if ((child = node.child (X_("Input"))) != 0) {
1049                 XMLNode* portnode = child->child (Port::state_node_name.c_str());
1050                 if (portnode) {
1051                         _async_in->set_state (*portnode, version);
1052                 }
1053         }
1054
1055         if ((child = node.child (X_("Output"))) != 0) {
1056                 XMLNode* portnode = child->child (Port::state_node_name.c_str());
1057                 if (portnode) {
1058                         _async_out->set_state (*portnode, version);
1059                 }
1060         }
1061
1062         XMLProperty const* prop;
1063
1064         if ((prop = node.property (X_("root"))) != 0) {
1065                 _scale_root = atoi (prop->value());
1066         }
1067
1068         if ((prop = node.property (X_("root_octave"))) != 0) {
1069                 _root_octave = atoi (prop->value());
1070         }
1071
1072         if ((prop = node.property (X_("in_key"))) != 0) {
1073                 _in_key = string_is_affirmative (prop->value());
1074         }
1075
1076         if ((prop = node.property (X_("mode"))) != 0) {
1077                 _mode = (MusicalMode::Type) string_2_enum (prop->value(), _mode);
1078         }
1079
1080         return retval;
1081 }
1082
1083 void
1084 Push2::other_vpot (int n, int delta)
1085 {
1086         switch (n) {
1087         case 0:
1088                 break;
1089         case 1:
1090                 break;
1091         case 2:
1092                 /* master gain control */
1093                 if (master) {
1094                         boost::shared_ptr<AutomationControl> ac = master->gain_control();
1095                         if (ac) {
1096                                 ac->set_value (ac->get_value() + ((2.0/64.0) * delta), PBD::Controllable::UseGroup);
1097                         }
1098                 }
1099                 break;
1100         }
1101 }
1102
1103 void
1104 Push2::other_vpot_touch (int n, bool touching)
1105 {
1106         switch (n) {
1107         case 0:
1108                 break;
1109         case 1:
1110                 break;
1111         case 2:
1112                 if (master) {
1113                         boost::shared_ptr<AutomationControl> ac = master->gain_control();
1114                         if (ac) {
1115                                 if (touching) {
1116                                         ac->start_touch (session->audible_frame());
1117                                 } else {
1118                                         ac->stop_touch (true, session->audible_frame());
1119                                 }
1120                         }
1121                 }
1122         }
1123 }
1124
1125 void
1126 Push2::start_shift ()
1127 {
1128         cerr << "start shift\n";
1129         _modifier_state = ModifierState (_modifier_state | ModShift);
1130         Button* b = id_button_map[Shift];
1131         b->set_color (LED::White);
1132         b->set_state (LED::Blinking16th);
1133         write (b->state_msg());
1134 }
1135
1136 void
1137 Push2::end_shift ()
1138 {
1139         if (_modifier_state & ModShift) {
1140                 cerr << "end shift\n";
1141                 _modifier_state = ModifierState (_modifier_state & ~(ModShift));
1142                 Button* b = id_button_map[Shift];
1143                 b->timeout_connection.disconnect ();
1144                 b->set_color (LED::White);
1145                 b->set_state (LED::OneShot24th);
1146                 write (b->state_msg());
1147         }
1148 }
1149
1150 bool
1151 Push2::pad_filter (MidiBuffer& in, MidiBuffer& out) const
1152 {
1153         /* This filter is called asynchronously from a realtime process
1154            context. It must use atomics to check state, and must not block.
1155         */
1156
1157         bool matched = false;
1158
1159         for (MidiBuffer::iterator ev = in.begin(); ev != in.end(); ++ev) {
1160                 if ((*ev).is_note_on() || (*ev).is_note_off()) {
1161
1162                         /* encoder touch start/touch end use note
1163                          * 0-10. touchstrip uses note 12
1164                          */
1165
1166                         if ((*ev).note() > 10 && (*ev).note() != 12) {
1167
1168                                 const int n = (*ev).note ();
1169                                 NNPadMap::const_iterator nni = nn_pad_map.find (n);
1170
1171                                 if (nni != nn_pad_map.end()) {
1172                                         Pad const * pad = nni->second;
1173                                         /* shift for output to the shadow port */
1174                                         if (pad->filtered >= 0) {
1175                                                 (*ev).set_note (pad->filtered + (octave_shift*12));
1176                                                 out.push_back (*ev);
1177                                                 /* shift back so that the pads light correctly  */
1178                                                 (*ev).set_note (n);
1179                                         } else {
1180                                                 /* no mapping, don't send event */
1181                                         }
1182                                 } else {
1183                                         out.push_back (*ev);
1184                                 }
1185
1186                                 matched = true;
1187                         }
1188                 } else if ((*ev).is_pitch_bender() || (*ev).is_poly_pressure() || (*ev).is_channel_pressure()) {
1189                         out.push_back (*ev);
1190                 }
1191         }
1192
1193         return matched;
1194 }
1195
1196 bool
1197 Push2::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
1198 {
1199         DEBUG_TRACE (DEBUG::FaderPort, "FaderPort::connection_handler  start\n");
1200         if (!_input_port || !_output_port) {
1201                 return false;
1202         }
1203
1204         string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_async_in)->name());
1205         string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_async_out)->name());
1206
1207         if (ni == name1 || ni == name2) {
1208                 if (yn) {
1209                         connection_state |= InputConnected;
1210                 } else {
1211                         connection_state &= ~InputConnected;
1212                 }
1213         } else if (no == name1 || no == name2) {
1214                 if (yn) {
1215                         connection_state |= OutputConnected;
1216                 } else {
1217                         connection_state &= ~OutputConnected;
1218                 }
1219         } else {
1220                 DEBUG_TRACE (DEBUG::FaderPort, string_compose ("Connections between %1 and %2 changed, but I ignored it\n", name1, name2));
1221                 /* not our ports */
1222                 return false;
1223         }
1224
1225         if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
1226
1227                 /* XXX this is a horrible hack. Without a short sleep here,
1228                    something prevents the device wakeup messages from being
1229                    sent and/or the responses from being received.
1230                 */
1231
1232                 g_usleep (100000);
1233                 DEBUG_TRACE (DEBUG::FaderPort, "device now connected for both input and output\n");
1234                 connected ();
1235
1236         } else {
1237                 DEBUG_TRACE (DEBUG::FaderPort, "Device disconnected (input or output or both) or not yet fully connected\n");
1238         }
1239
1240         ConnectionChange (); /* emit signal for our GUI */
1241
1242         DEBUG_TRACE (DEBUG::FaderPort, "FaderPort::connection_handler  end\n");
1243
1244         return true; /* connection status changed */
1245 }
1246
1247 void
1248 Push2::connected ()
1249 {
1250         request_pressure_mode ();
1251 }
1252
1253 boost::shared_ptr<Port>
1254 Push2::output_port()
1255 {
1256         return _async_out;
1257 }
1258
1259 boost::shared_ptr<Port>
1260 Push2::input_port()
1261 {
1262         return _async_in;
1263 }
1264
1265 int
1266 Push2::pad_note (int row, int col) const
1267 {
1268         NNPadMap::const_iterator nni = nn_pad_map.find (36+(row*8)+col);
1269
1270         if (nni != nn_pad_map.end()) {
1271                 return nni->second->filtered;
1272         }
1273
1274         return 0;
1275 }
1276
1277 void
1278 Push2::update_selection_color ()
1279 {
1280         boost::shared_ptr<MidiTrack> current_midi_track = current_pad_target.lock();
1281
1282         if (!current_midi_track) {
1283                 return;
1284         }
1285
1286         selection_color = get_color_index (current_midi_track->presentation_info().color());
1287         contrast_color = get_color_index (ArdourCanvas::HSV (current_midi_track->presentation_info().color()).opposite().color());
1288
1289         reset_pad_colors ();
1290 }
1291
1292 void
1293 Push2::reset_pad_colors ()
1294 {
1295         set_pad_scale (_scale_root, _root_octave, _mode, _in_key);
1296 }
1297
1298 void
1299 Push2::set_pad_scale (int root, int octave, MusicalMode::Type mode, bool inkey)
1300 {
1301         MusicalMode m (mode);
1302         vector<float>::iterator interval;
1303         int note;
1304         const int original_root = root;
1305
1306         interval = m.steps.begin();
1307         root += (octave*12);
1308         note = root;
1309
1310         const int root_start = root;
1311
1312         set<int> mode_map; /* contains only notes in mode, O(logN) lookup */
1313         vector<int> mode_vector; /* sorted in note order */
1314
1315         mode_map.insert (note);
1316         mode_vector.push_back (note);
1317
1318         /* build a map of all notes in the mode, from the root to 127 */
1319
1320         while (note < 128) {
1321
1322                 if (interval == m.steps.end()) {
1323
1324                         /* last distance was the end of the scale,
1325                            so wrap, adding the next note at one
1326                            octave above the last root.
1327                         */
1328
1329                         interval = m.steps.begin();
1330                         root += 12;
1331                         mode_map.insert (root);
1332                         mode_vector.push_back (root);
1333
1334                 } else {
1335                         note = (int) floor (root + (2.0 * (*interval)));
1336                         interval++;
1337                         mode_map.insert (note);
1338                         mode_vector.push_back (note);
1339                 }
1340         }
1341
1342         fn_pad_map.clear ();
1343
1344         if (inkey) {
1345
1346                 vector<int>::iterator notei;
1347                 int row_offset = 0;
1348
1349                 for (int row = 0; row < 8; ++row) {
1350
1351                         /* Ableton's grid layout wraps the available notes in the scale
1352                          * by offsetting 3 notes per row (from the bottom)
1353                          */
1354
1355                         notei = mode_vector.begin();
1356                         notei += row_offset;
1357                         row_offset += 3;
1358
1359                         for (int col = 0; col < 8; ++col) {
1360                                 int index = 36 + (row*8) + col;
1361                                 Pad* pad = nn_pad_map[index];
1362                                 int notenum;
1363                                 if (notei != mode_vector.end()) {
1364
1365                                         notenum = *notei;
1366                                         pad->filtered = notenum;
1367
1368                                         fn_pad_map.insert (make_pair (notenum, pad));
1369
1370                                         if ((notenum % 12) == original_root) {
1371                                                 pad->set_color (selection_color);
1372                                                 pad->perma_color = selection_color;
1373                                         } else {
1374                                                 pad->set_color (LED::White);
1375                                                 pad->perma_color = LED::White;
1376                                         }
1377
1378                                         pad->do_when_pressed = Pad::FlashOff;
1379                                         notei++;
1380
1381                                 } else {
1382
1383                                         pad->set_color (LED::Black);
1384                                         pad->do_when_pressed = Pad::Nothing;
1385                                         pad->filtered = -1;
1386                                 }
1387
1388                                 pad->set_state (LED::OneShot24th);
1389                                 write (pad->state_msg());
1390                         }
1391                 }
1392
1393         } else {
1394
1395                 /* chromatic: all notes available, but highlight those in the scale */
1396
1397                 for (note = 36; note < 100; ++note) {
1398
1399                         Pad* pad = nn_pad_map[note];
1400
1401                         /* Chromatic: all pads play, half-tone steps. Light
1402                          * those in the scale, and highlight root notes
1403                          */
1404
1405                         pad->filtered = root_start + (note - 36);
1406
1407                         fn_pad_map.insert (make_pair (pad->filtered, pad));
1408
1409                         if (mode_map.find (note) != mode_map.end()) {
1410
1411                                 if ((note % 12) == original_root) {
1412                                         pad->set_color (selection_color);
1413                                         pad->perma_color = selection_color;
1414                                 } else {
1415                                         pad->set_color (LED::White);
1416                                         pad->perma_color = LED::White;
1417                                 }
1418
1419                                 pad->do_when_pressed = Pad::FlashOff;
1420
1421                         } else {
1422
1423                                 /* note is not in mode, turn it off */
1424
1425                                 pad->do_when_pressed = Pad::FlashOn;
1426                                 pad->set_color (LED::Black);
1427
1428                         }
1429
1430                         pad->set_state (LED::OneShot24th);
1431                         write (pad->state_msg());
1432                 }
1433         }
1434
1435         /* store state */
1436
1437         bool changed = false;
1438
1439         if (_scale_root != original_root) {
1440                 _scale_root = original_root;
1441                 changed = true;
1442         }
1443         if (_root_octave != octave) {
1444                 _root_octave = octave;
1445                 changed = true;
1446         }
1447         if (_in_key != inkey) {
1448                 _in_key = inkey;
1449                 changed = true;
1450         }
1451         if (_mode != mode) {
1452                 _mode = mode;
1453                 changed = true;
1454         }
1455
1456         if (changed) {
1457                 ScaleChange (); /* EMIT SIGNAL */
1458         }
1459 }
1460
1461 void
1462 Push2::set_percussive_mode (bool yn)
1463 {
1464         if (!yn) {
1465                 cerr << "back to scale\n";
1466                 set_pad_scale (_scale_root, _root_octave, _mode, _in_key);
1467                 percussion = false;
1468                 return;
1469         }
1470
1471         int drum_note = 36;
1472
1473         for (int row = 0; row < 8; ++row) {
1474
1475                 for (int col = 0; col < 4; ++col) {
1476
1477                         int index = 36 + (row*8) + col;
1478                         Pad* pad = nn_pad_map[index];
1479
1480                         pad->filtered = drum_note;
1481                         drum_note++;
1482                 }
1483         }
1484
1485         for (int row = 0; row < 8; ++row) {
1486
1487                 for (int col = 4; col < 8; ++col) {
1488
1489                         int index = 36 + (row*8) + col;
1490                         Pad* pad = nn_pad_map[index];
1491
1492                         pad->filtered = drum_note;
1493                         drum_note++;
1494                 }
1495         }
1496
1497         percussion = true;
1498 }
1499
1500 Push2Layout*
1501 Push2::current_layout () const
1502 {
1503         Glib::Threads::Mutex::Lock lm (layout_lock);
1504         return _current_layout;
1505 }
1506
1507 void
1508 Push2::stripable_selection_change (StripableNotificationListPtr selected)
1509 {
1510         boost::shared_ptr<MidiPort> pad_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in)->shadow_port();
1511         boost::shared_ptr<MidiTrack> current_midi_track = current_pad_target.lock();
1512         boost::shared_ptr<MidiTrack> new_pad_target;
1513
1514         /* See if there's a MIDI track selected */
1515
1516         for (StripableNotificationList::iterator si = selected->begin(); si != selected->end(); ++si) {
1517
1518                 new_pad_target = boost::dynamic_pointer_cast<MidiTrack> ((*si).lock());
1519
1520                 if (new_pad_target) {
1521                         break;
1522                 }
1523         }
1524
1525         if (current_midi_track == new_pad_target) {
1526                 /* nothing to do */
1527                 return;
1528         }
1529
1530         if (!new_pad_target) {
1531                 /* leave existing connection alone */
1532                 return;
1533         }
1534
1535         /* disconnect from pad port, if appropriate */
1536
1537         if (current_midi_track && pad_port) {
1538                 current_midi_track->input()->disconnect (current_midi_track->input()->nth(0), pad_port->name(), this);
1539         }
1540
1541         /* now connect the pad port to this (newly) selected midi
1542          * track, if indeed there is one.
1543          */
1544
1545         if (new_pad_target && pad_port) {
1546                 new_pad_target->input()->connect (new_pad_target->input()->nth (0), pad_port->name(), this);
1547                 current_pad_target = new_pad_target;
1548                 selection_color = get_color_index (new_pad_target->presentation_info().color());
1549                 contrast_color = get_color_index (ArdourCanvas::HSV (new_pad_target->presentation_info().color()).opposite().color());
1550         } else {
1551                 current_pad_target.reset ();
1552                 selection_color = LED::Green;
1553                 contrast_color = LED::Green;
1554         }
1555
1556         reset_pad_colors ();
1557 }
1558
1559 Push2::Button*
1560 Push2::button_by_id (ButtonID bid)
1561 {
1562         return id_button_map[bid];
1563 }
1564
1565 uint8_t
1566 Push2::get_color_index (ArdourCanvas::Color rgba)
1567 {
1568         ColorMap::iterator i = color_map.find (rgba);
1569
1570         if (i != color_map.end()) {
1571                 return i->second;
1572         }
1573
1574         double dr, dg, db, da;
1575         int r, g, b;
1576         ArdourCanvas::color_to_rgba (rgba, dr, dg, db, da);
1577         int w = 126; /* not sure where/when we should get this value */
1578
1579
1580         r = (int) floor (255.0 * dr);
1581         g = (int) floor (255.0 * dg);
1582         b = (int) floor (255.0 * db);
1583
1584         /* get a free index */
1585
1586         uint8_t index;
1587
1588         if (color_map_free_list.empty()) {
1589                 /* random replacement of any entry above zero and below 122 (where the
1590                  * Ableton standard colors live)
1591                  */
1592                 index = 1 + (random() % 121);
1593         } else {
1594                 index = color_map_free_list.top();
1595                 color_map_free_list.pop();
1596         }
1597
1598         MidiByteArray palette_msg (17,
1599                                    0xf0,
1600                                    0x00 , 0x21, 0x1d, 0x01, 0x01, 0x03, /* reset palette header */
1601                                    0x00, /* index = 7 */
1602                                    0x00, 0x00, /* r = 8 & 9 */
1603                                    0x00, 0x00, /* g = 10 & 11 */
1604                                    0x00, 0x00, /* b = 12 & 13 */
1605                                    0x00, 0x00, /* w (a?) = 14 & 15*/
1606                                    0xf7);
1607         palette_msg[7] = index;
1608         palette_msg[8] = r & 0x7f;
1609         palette_msg[9] = (r & 0x80) >> 7;
1610         palette_msg[10] = g & 0x7f;
1611         palette_msg[11] = (g & 0x80) >> 7;
1612         palette_msg[12] = b & 0x7f;
1613         palette_msg[13] = (b & 0x80) >> 7;
1614         palette_msg[14] = w & 0x7f;
1615         palette_msg[15] = w & 0x80;
1616
1617         write (palette_msg);
1618
1619         MidiByteArray update_pallette_msg (8, 0xf0, 0x00, 0x21, 0x1d, 0x01, 0x01, 0x05, 0xF7);
1620         write (update_pallette_msg);
1621
1622         color_map[rgba] = index;
1623
1624         return index;
1625 }
1626
1627 void
1628 Push2::build_color_map ()
1629 {
1630         /* These are "standard" colors that Ableton docs suggest will always be
1631            there. Put them in our color map so that when we look up these
1632            colors, we will use the Ableton indices for them.
1633         */
1634
1635         color_map.insert (make_pair (RGB_TO_UINT (0,0,0), 0));
1636         color_map.insert (make_pair (RGB_TO_UINT (204,204,204), 122));
1637         color_map.insert (make_pair (RGB_TO_UINT (64,64,64), 123));
1638         color_map.insert (make_pair (RGB_TO_UINT (20,20,20), 124));
1639         color_map.insert (make_pair (RGB_TO_UINT (0,0,255), 125));
1640         color_map.insert (make_pair (RGB_TO_UINT (0,255,0), 126));
1641         color_map.insert (make_pair (RGB_TO_UINT (255,0,0), 127));
1642
1643         for (uint8_t n = 1; n < 122; ++n) {
1644                 color_map_free_list.push (n);
1645         }
1646 }
1647
1648 void
1649 Push2::fill_color_table ()
1650 {
1651         colors.insert (make_pair (DarkBackground, ArdourCanvas::rgba_to_color (0, 0, 0, 1)));
1652         colors.insert (make_pair (LightBackground, ArdourCanvas::rgba_to_color (0.98, 0.98, 0.98, 1)));
1653
1654         colors.insert (make_pair (ParameterName, ArdourCanvas::rgba_to_color (0.98, 0.98, 0.98, 1)));
1655
1656         colors.insert (make_pair (KnobArcBackground, ArdourCanvas::rgba_to_color (0.3, 0.3, 0.3, 1.0)));
1657         colors.insert (make_pair (KnobArcStart, ArdourCanvas::rgba_to_color (1.0, 0.0, 0.0, 1.0)));
1658         colors.insert (make_pair (KnobArcEnd, ArdourCanvas::rgba_to_color (0.0, 1.0, 0.0, 1.0)));
1659
1660         colors.insert (make_pair (KnobLineShadow, ArdourCanvas::rgba_to_color  (0, 0, 0, 0.3)));
1661         colors.insert (make_pair (KnobLine, ArdourCanvas::rgba_to_color (1, 1, 1, 1)));
1662
1663         colors.insert (make_pair (KnobForeground, ArdourCanvas::rgba_to_color (0.2, 0.2, 0.2, 1)));
1664         colors.insert (make_pair (KnobBackground, ArdourCanvas::rgba_to_color (0.2, 0.2, 0.2, 1)));
1665         colors.insert (make_pair (KnobShadow, ArdourCanvas::rgba_to_color (0, 0, 0, 0.1)));
1666         colors.insert (make_pair (KnobBorder, ArdourCanvas::rgba_to_color (0, 0, 0, 1)));
1667
1668 }
1669
1670 ArdourCanvas::Color
1671 Push2::get_color (ColorName name)
1672 {
1673         Colors::iterator c = colors.find (name);
1674         if (c != colors.end()) {
1675                 return c->second;
1676         }
1677
1678         return random();
1679 }
1680
1681 void
1682 Push2::set_current_layout (Push2Layout* layout)
1683 {
1684         if (_current_layout) {
1685                 _current_layout->hide ();
1686                 _canvas->root()->remove (_current_layout);
1687                 _previous_layout = _current_layout;
1688         }
1689
1690         _current_layout = layout;
1691
1692         if (_current_layout) {
1693                 _canvas->root()->add (_current_layout);
1694                 _current_layout->show ();
1695         }
1696
1697         _canvas->request_redraw ();
1698 }
1699
1700 void
1701 Push2::use_previous_layout ()
1702 {
1703         if (_previous_layout) {
1704                 set_current_layout (_previous_layout);
1705         }
1706 }
1707
1708 void
1709 Push2::request_pressure_mode ()
1710 {
1711         MidiByteArray msg (8, 0xF0, 0x00, 0x21, 0x1D, 0x01, 0x01, 0x1F, 0xF7);
1712         write (msg);
1713 }
1714
1715 void
1716 Push2::set_pressure_mode (PressureMode pm)
1717 {
1718         MidiByteArray msg (9, 0xF0, 0x00, 0x21, 0x1D, 0x01, 0x01, 0x1E, 0x0, 0xF7);
1719
1720         switch (pm) {
1721         case AfterTouch:
1722                 /* nothing to do, message is correct */
1723                 break;
1724         case PolyPressure:
1725                 msg[7] = 0x1;
1726                 break;
1727         default:
1728                 return;
1729         }
1730
1731         write (msg);
1732         cerr << "Sent PM message " << msg << endl;
1733 }