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