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