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