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