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