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