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