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