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