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