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