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