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