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