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