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