c8ea3ceb4fa0e26fb8ecf8f57c588bf2ab6e6944
[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
30 #include "midi++/parser.h"
31 #include "timecode/time.h"
32 #include "timecode/bbt_time.h"
33
34 #include "ardour/async_midi_port.h"
35 #include "ardour/audioengine.h"
36 #include "ardour/debug.h"
37 #include "ardour/filesystem_paths.h"
38 #include "ardour/midiport_manager.h"
39 #include "ardour/session.h"
40 #include "ardour/tempo.h"
41
42 #include "push2.h"
43
44 using namespace ARDOUR;
45 using namespace std;
46 using namespace PBD;
47 using namespace Glib;
48 using namespace ArdourSurface;
49
50 #include "i18n.h"
51
52 #include "pbd/abstract_ui.cc" // instantiate template
53
54 const int Push2::cols = 960;
55 const int Push2::rows = 160;
56 const int Push2::pixels_per_row = 1024;
57
58 #define ABLETON 0x2982
59 #define PUSH2   0x1967
60
61 Push2::Push2 (ARDOUR::Session& s)
62         : ControlProtocol (s, string (X_("Ableton Push 2")))
63         , AbstractUI<Push2Request> (name())
64         , handle (0)
65         , device_buffer (0)
66         , frame_buffer (Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, cols, rows))
67         , modifier_state (None)
68         , splash_start (0)
69         , bank_start (0)
70 {
71         context = Cairo::Context::create (frame_buffer);
72         tc_clock_layout = Pango::Layout::create (context);
73         bbt_clock_layout = Pango::Layout::create (context);
74
75         Pango::FontDescription fd ("Sans Bold 24");
76         tc_clock_layout->set_font_description (fd);
77         bbt_clock_layout->set_font_description (fd);
78
79         Pango::FontDescription fd2 ("Sans 10");
80         for (int n = 0; n < 8; ++n) {
81                 upper_layout[n] = Pango::Layout::create (context);
82                 upper_layout[n]->set_font_description (fd2);
83                 upper_layout[n]->set_text ("solo");
84                 lower_layout[n] = Pango::Layout::create (context);
85                 lower_layout[n]->set_font_description (fd2);
86                 lower_layout[n]->set_text ("mute");
87         }
88
89         Pango::FontDescription fd3 ("Sans Bold 10");
90         for (int n = 0; n < 8; ++n) {
91                 mid_layout[n] = Pango::Layout::create (context);
92                 mid_layout[n]->set_font_description (fd3);
93         }
94
95         build_maps ();
96
97         if (open ()) {
98                 throw failed_constructor ();
99         }
100
101 }
102
103 Push2::~Push2 ()
104 {
105         stop ();
106 }
107
108 int
109 Push2::open ()
110 {
111         int err;
112
113         if (handle) {
114                 /* already open */
115                 return 0;
116         }
117
118         if ((handle = libusb_open_device_with_vid_pid (NULL, ABLETON, PUSH2)) == 0) {
119                 return -1;
120         }
121
122         if ((err = libusb_claim_interface (handle, 0x00))) {
123                 return -1;
124         }
125
126         device_frame_buffer = new uint16_t[rows*pixels_per_row];
127
128         memset (device_frame_buffer, 0, sizeof (uint16_t) * rows * pixels_per_row);
129
130         frame_header[0] = 0xef;
131         frame_header[1] = 0xcd;
132         frame_header[2] = 0xab;
133         frame_header[3] = 0x89;
134         memset (&frame_header[4], 0, 12);
135
136         /* setup ports */
137
138         _async_in  = AudioEngine::instance()->register_input_port (DataType::MIDI, X_("push2 in"), true);
139         _async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, X_("push2 out"), true);
140
141         if (_async_in == 0 || _async_out == 0) {
142                 return -1;
143         }
144
145         _input_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_in).get();
146         _output_port = boost::dynamic_pointer_cast<AsyncMIDIPort>(_async_out).get();
147
148         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));
149
150         connect_to_parser ();
151
152         return 0;
153 }
154
155 int
156 Push2::close ()
157 {
158         init_buttons (false);
159
160         /* wait for button data to be flushed */
161         AsyncMIDIPort* asp;
162         asp = dynamic_cast<AsyncMIDIPort*> (_output_port);
163         asp->drain (10000, 500000);
164
165         AudioEngine::instance()->unregister_port (_async_in);
166         AudioEngine::instance()->unregister_port (_async_out);
167
168         _async_in.reset ((ARDOUR::Port*) 0);
169         _async_out.reset ((ARDOUR::Port*) 0);
170         _input_port = 0;
171         _output_port = 0;
172
173         vblank_connection.disconnect ();
174         periodic_connection.disconnect ();
175         session_connections.drop_connections ();
176         stripable_connections.drop_connections ();
177
178         if (handle) {
179                 libusb_release_interface (handle, 0x00);
180                 libusb_close (handle);
181                 handle = 0;
182         }
183
184         for (int n = 0; n < 8; ++n) {
185                 stripable[n].reset ();
186         }
187
188         delete [] device_frame_buffer;
189         device_frame_buffer = 0;
190
191         return 0;
192 }
193
194 void
195 Push2::init_buttons (bool startup)
196 {
197         /* This is a list of buttons that we want lit because they do something
198            in ardour related (loosely, sometimes) to their illuminated label.
199         */
200
201         ButtonID buttons[] = { Mute, Solo, Master, Up, Right, Left, Down, Note, Session, Mix, AddTrack, Delete, Undo,
202                                Metronome, Shift, Select, Play, RecordEnable, Automate, Repeat, Note, Session, DoubleLoop,
203                                Quantize, Duplicate, Browse, PageRight, PageLeft,
204         };
205
206         for (size_t n = 0; n < sizeof (buttons) / sizeof (buttons[0]); ++n) {
207                 Button* b = id_button_map[buttons[n]];
208
209                 if (startup) {
210                         b->set_color (LED::White);
211                 } else {
212                         b->set_color (LED::Black);
213                 }
214                 b->set_state (LED::OneShot24th);
215                 write (b->state_msg());
216         }
217
218         /* Strip buttons should all be off (black) by default. They will change
219          * color to reflect various conditions
220          */
221
222         ButtonID strip_buttons[] = { Upper1, Upper2, Upper3, Upper4, Upper5, Upper6, Upper7, Upper8,
223                                      Lower1, Lower2, Lower3, Lower4, Lower5, Lower6, Lower7, Lower8, };
224
225         for (size_t n = 0; n < sizeof (strip_buttons) / sizeof (strip_buttons[0]); ++n) {
226                 Button* b = id_button_map[strip_buttons[n]];
227
228                 b->set_color (LED::Black);
229                 b->set_state (LED::OneShot24th);
230                 write (b->state_msg());
231         }
232
233         if (startup) {
234
235                 /* all other buttons are off (black) */
236
237                 ButtonID off_buttons[] = { TapTempo, Setup, User, Stop, Convert, New, FixedLength,
238                                            Fwd32ndT, Fwd32nd, Fwd16thT, Fwd16th, Fwd8thT, Fwd8th, Fwd4trT, Fwd4tr,
239                                            Accent, Scale, Layout, Note, Session,  OctaveUp, OctaveDown, };
240
241                 for (size_t n = 0; n < sizeof (off_buttons) / sizeof (off_buttons[0]); ++n) {
242                         Button* b = id_button_map[off_buttons[n]];
243
244                         b->set_color (LED::Black);
245                         b->set_state (LED::OneShot24th);
246                         write (b->state_msg());
247                 }
248         }
249
250         for (NNPadMap::iterator pi = nn_pad_map.begin(); pi != nn_pad_map.end(); ++pi) {
251                 Pad* pad = pi->second;
252
253                 pad->set_color (LED::Black);
254                 pad->set_state (LED::OneShot24th);
255                 write (pad->state_msg());
256         }
257 }
258
259 bool
260 Push2::probe ()
261 {
262         libusb_device_handle *h;
263         libusb_init (NULL);
264
265         if ((h = libusb_open_device_with_vid_pid (NULL, ABLETON, PUSH2)) == 0) {
266                 DEBUG_TRACE (DEBUG::Push2, "no Push2 device found\n");
267                 return false;
268         }
269
270         libusb_close (h);
271         DEBUG_TRACE (DEBUG::Push2, "Push2 device located\n");
272         return true;
273 }
274
275 void*
276 Push2::request_factory (uint32_t num_requests)
277 {
278         /* AbstractUI<T>::request_buffer_factory() is a template method only
279            instantiated in this source module. To provide something visible for
280            use in the interface/descriptor, we have this static method that is
281            template-free.
282         */
283         return request_buffer_factory (num_requests);
284 }
285
286 void
287 Push2::do_request (Push2Request * req)
288 {
289         DEBUG_TRACE (DEBUG::Push2, string_compose ("doing request type %1\n", req->type));
290         if (req->type == CallSlot) {
291
292                 call_slot (MISSING_INVALIDATOR, req->the_slot);
293
294         } else if (req->type == Quit) {
295
296                 stop ();
297         }
298 }
299
300 int
301 Push2::stop ()
302 {
303         BaseUI::quit ();
304         close ();
305         return 0;
306 }
307
308 /** render host-side frame buffer (a Cairo ImageSurface) to the current
309  * device-side frame buffer. The device frame buffer will be pushed to the
310  * device on the next call to vblank()
311  */
312
313 int
314 Push2::blit_to_device_frame_buffer ()
315 {
316         /* ensure that all drawing has been done before we fetch pixel data */
317
318         frame_buffer->flush ();
319
320         const int stride = 3840; /* bytes per row for Cairo::FORMAT_ARGB32 */
321         const uint8_t* data = frame_buffer->get_data ();
322
323         /* fill frame buffer (320kB) */
324
325         uint16_t* fb = (uint16_t*) device_frame_buffer;
326
327         for (int row = 0; row < rows; ++row) {
328
329                 const uint8_t* dp = data + row * stride;
330
331                 for (int col = 0; col < cols; ++col) {
332
333                         /* fetch r, g, b (range 0..255). Ignore alpha */
334
335                         const int r = (*((const uint32_t*)dp) >> 16) & 0xff;
336                         const int g = (*((const uint32_t*)dp) >> 8) & 0xff;
337                         const int b = *((const uint32_t*)dp) & 0xff;
338
339                         /* convert to 5 bits, 6 bits, 5 bits, respectively */
340                         /* generate 16 bit BGB565 value */
341
342                         *fb++ = (r >> 3) | ((g & 0xfc) << 3) | ((b & 0xf8) << 8);
343
344                         /* the push2 docs state that we should xor the pixel
345                          * data. Doing so doesn't work correctly, and not doing
346                          * so seems to work fine (colors roughly match intended
347                          * values).
348                          */
349
350                         dp += 4;
351                 }
352
353                 /* skip 128 bytes to next line. This is filler, used to avoid line borders occuring in the middle of 512
354                    byte USB buffers
355                 */
356
357                 fb += 64; /* 128 bytes = 64 int16_t */
358         }
359
360         return 0;
361 }
362
363 bool
364 Push2::redraw ()
365 {
366         string tc_clock_text;
367         string bbt_clock_text;
368
369         if (splash_start) {
370                 if (get_microseconds() - splash_start > 4000000) {
371                         splash_start = 0;
372                 } else {
373                         return false;
374                 }
375         }
376
377         if (session) {
378                 framepos_t audible = session->audible_frame();
379                 Timecode::Time TC;
380                 bool negative = false;
381
382                 if (audible < 0) {
383                         audible = -audible;
384                         negative = true;
385                 }
386
387                 session->timecode_time (audible, TC);
388
389                 TC.negative = TC.negative || negative;
390
391                 tc_clock_text = Timecode::timecode_format_time(TC);
392
393                 Timecode::BBT_Time bbt = session->tempo_map().bbt_at_frame (audible);
394                 char buf[16];
395
396 #define BBT_BAR_CHAR "|"
397
398                 if (negative) {
399                         snprintf (buf, sizeof (buf), "-%03" PRIu32 BBT_BAR_CHAR "%02" PRIu32 BBT_BAR_CHAR "%04" PRIu32,
400                                   bbt.bars, bbt.beats, bbt.ticks);
401                 } else {
402                         snprintf (buf, sizeof (buf), " %03" PRIu32 BBT_BAR_CHAR "%02" PRIu32 BBT_BAR_CHAR "%04" PRIu32,
403                                   bbt.bars, bbt.beats, bbt.ticks);
404                 }
405
406                 bbt_clock_text = buf;
407         }
408
409         bool dirty = false;
410
411         if (tc_clock_text != tc_clock_layout->get_text()) {
412                 dirty = true;
413                 tc_clock_layout->set_text (tc_clock_text);
414         }
415
416         if (bbt_clock_text != tc_clock_layout->get_text()) {
417                 dirty = true;
418                 bbt_clock_layout->set_text (bbt_clock_text);
419         }
420
421         string mid_text;
422
423         for (int n = 0; n < 8; ++n) {
424                 if (stripable[n]) {
425                         mid_text = short_version (stripable[n]->name(), 10);
426                         if (mid_text != mid_layout[n]->get_text()) {
427                                 mid_layout[n]->set_text (mid_text);
428                                 dirty = true;
429                         }
430                 }
431         }
432
433         if (!dirty) {
434                 return false;
435         }
436
437         context->set_source_rgb (0.764, 0.882, 0.882);
438         context->rectangle (0, 0, 960, 160);
439         context->fill ();
440         context->set_source_rgb (0.23, 0.0, 0.349);
441         context->move_to (650, 25);
442         tc_clock_layout->update_from_cairo_context (context);
443         tc_clock_layout->show_in_cairo_context (context);
444         context->move_to (650, 60);
445         bbt_clock_layout->update_from_cairo_context (context);
446         bbt_clock_layout->show_in_cairo_context (context);
447
448         for (int n = 0; n < 8; ++n) {
449                 context->move_to (10 + (n*120), 2);
450                 upper_layout[n]->update_from_cairo_context (context);
451                 upper_layout[n]->show_in_cairo_context (context);
452         }
453
454         for (int n = 0; n < 8; ++n) {
455                 context->move_to (10 + (n*120), 140);
456                 lower_layout[n]->update_from_cairo_context (context);
457                 lower_layout[n]->show_in_cairo_context (context);
458         }
459
460         for (int n = 0; n < 8; ++n) {
461                 if (stripable[n] && stripable[n]->presentation_info().selected()) {
462                         context->rectangle (10 + (n*120) - 5, 115, 120, 22);
463                         context->set_source_rgb (1.0, 0.737, 0.172);
464                         context->fill();
465                 }
466                 context->set_source_rgb (0.0, 0.0, 0.0);
467                 context->move_to (10 + (n*120), 120);
468                 mid_layout[n]->update_from_cairo_context (context);
469                 mid_layout[n]->show_in_cairo_context (context);
470         }
471
472         /* render clock */
473         /* render foo */
474         /* render bar */
475
476         return true;
477 }
478
479 bool
480 Push2::vblank ()
481 {
482         int transferred = 0;
483         const int timeout_msecs = 1000;
484         int err;
485
486         if ((err = libusb_bulk_transfer (handle, 0x01, frame_header, sizeof (frame_header), &transferred, timeout_msecs))) {
487                 return false;
488         }
489
490         if (redraw()) {
491                 /* things changed */
492                 blit_to_device_frame_buffer ();
493         }
494
495         if ((err = libusb_bulk_transfer (handle, 0x01, (uint8_t*) device_frame_buffer , 2 * rows * pixels_per_row, &transferred, timeout_msecs))) {
496                 return false;
497         }
498
499         return true;
500 }
501
502 int
503 Push2::set_active (bool yn)
504 {
505         DEBUG_TRACE (DEBUG::Push2, string_compose("Push2Protocol::set_active init with yn: '%1'\n", yn));
506
507         if (yn == active()) {
508                 return 0;
509         }
510
511         if (yn) {
512
513                 /* start event loop */
514
515                 BaseUI::run ();
516
517                 if (open ()) {
518                         DEBUG_TRACE (DEBUG::Push2, "device open failed\n");
519                         close ();
520                         return -1;
521                 }
522
523                 /* Connect input port to event loop */
524
525                 AsyncMIDIPort* asp;
526
527                 asp = dynamic_cast<AsyncMIDIPort*> (_input_port);
528                 asp->xthread().set_receive_handler (sigc::bind (sigc::mem_fun (this, &Push2::midi_input_handler), _input_port));
529                 asp->xthread().attach (main_loop()->get_context());
530
531                 connect_session_signals ();
532
533                 /* set up periodic task used to push a frame buffer to the
534                  * device (25fps). The device can handle 60fps, but we don't
535                  * need that frame rate.
536                  */
537
538                 Glib::RefPtr<Glib::TimeoutSource> vblank_timeout = Glib::TimeoutSource::create (40); // milliseconds
539                 vblank_connection = vblank_timeout->connect (sigc::mem_fun (*this, &Push2::vblank));
540                 vblank_timeout->attach (main_loop()->get_context());
541
542
543                 Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (1000); // milliseconds
544                 periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &Push2::periodic));
545                 periodic_timeout->attach (main_loop()->get_context());
546
547                 init_buttons (true);
548                 init_touch_strip ();
549                 switch_bank (0);
550                 splash ();
551
552         } else {
553
554                 stop ();
555
556         }
557
558         ControlProtocol::set_active (yn);
559
560         DEBUG_TRACE (DEBUG::Push2, string_compose("Push2Protocol::set_active done with yn: '%1'\n", yn));
561
562         return 0;
563 }
564
565 void
566 Push2::init_touch_strip ()
567 {
568         MidiByteArray msg (9, 0xf0, 0x00, 0x21, 0x1d, 0x01, 0x01, 0x17, 0x00, 0xf7);
569         /* flags are the final byte (ignore end-of-sysex */
570
571         /* show bar, not point
572            autoreturn to center
573            bar starts at center
574         */
575         msg[7] = (1<<4) | (1<<5) | (1<<6);
576         write (msg);
577 }
578
579 void
580 Push2::write (const MidiByteArray& data)
581 {
582         /* immediate delivery */
583         _output_port->write (&data[0], data.size(), 0);
584 }
585
586 bool
587 Push2::midi_input_handler (IOCondition ioc, MIDI::Port* port)
588 {
589         if (ioc & ~IO_IN) {
590                 DEBUG_TRACE (DEBUG::Push2, "MIDI port closed\n");
591                 return false;
592         }
593
594         if (ioc & IO_IN) {
595
596                 // DEBUG_TRACE (DEBUG::Push2, string_compose ("something happend on  %1\n", port->name()));
597
598                 AsyncMIDIPort* asp = dynamic_cast<AsyncMIDIPort*>(port);
599                 if (asp) {
600                         asp->clear ();
601                 }
602
603                 //DEBUG_TRACE (DEBUG::Push2, string_compose ("data available on %1\n", port->name()));
604                 framepos_t now = AudioEngine::instance()->sample_time();
605                 port->parse (now);
606         }
607
608         return true;
609 }
610
611 bool
612 Push2::periodic ()
613 {
614         return true;
615 }
616
617 void
618 Push2::connect_to_parser ()
619 {
620         DEBUG_TRACE (DEBUG::Push2, string_compose ("Connecting to signals on port %2\n", _input_port->name()));
621
622         MIDI::Parser* p = _input_port->parser();
623
624         /* Incoming sysex */
625         p->sysex.connect_same_thread (*this, boost::bind (&Push2::handle_midi_sysex, this, _1, _2, _3));
626         /* V-Pot messages are Controller */
627         p->controller.connect_same_thread (*this, boost::bind (&Push2::handle_midi_controller_message, this, _1, _2));
628         /* Button messages are NoteOn */
629         p->note_on.connect_same_thread (*this, boost::bind (&Push2::handle_midi_note_on_message, this, _1, _2));
630         /* Button messages are NoteOn but libmidi++ sends note-on w/velocity = 0 as note-off so catch them too */
631         p->note_off.connect_same_thread (*this, boost::bind (&Push2::handle_midi_note_on_message, this, _1, _2));
632         /* Fader messages are Pitchbend */
633         p->channel_pitchbend[0].connect_same_thread (*this, boost::bind (&Push2::handle_midi_pitchbend_message, this, _1, _2));
634 }
635
636 void
637 Push2::handle_midi_sysex (MIDI::Parser&, MIDI::byte* raw_bytes, size_t sz)
638 {
639         DEBUG_TRACE (DEBUG::Push2, string_compose ("Sysex, %1 bytes\n", sz));
640 }
641
642 void
643 Push2::handle_midi_controller_message (MIDI::Parser&, MIDI::EventTwoBytes* ev)
644 {
645         DEBUG_TRACE (DEBUG::Push2, string_compose ("CC %1 (value %2)\n", (int) ev->controller_number, (int) ev->value));
646
647         CCButtonMap::iterator b = cc_button_map.find (ev->controller_number);
648
649         if (ev->value) {
650                 /* any press cancels any pending long press timeouts */
651                 for (set<ButtonID>::iterator x = buttons_down.begin(); x != buttons_down.end(); ++x) {
652                         Button* bb = id_button_map[*x];
653                         bb->timeout_connection.disconnect ();
654                 }
655         }
656
657         if (b != cc_button_map.end()) {
658
659                 Button* button = b->second;
660
661                 if (ev->value) {
662                         buttons_down.insert (button->id);
663                         start_press_timeout (*button, button->id);
664                 } else {
665                         buttons_down.erase (button->id);
666                         button->timeout_connection.disconnect ();
667                 }
668
669
670                 set<ButtonID>::iterator c = consumed.find (button->id);
671
672                 if (c == consumed.end()) {
673                         if (ev->value == 0) {
674                                 (this->*button->release_method)();
675                         } else {
676                                 (this->*button->press_method)();
677                         }
678                 } else {
679                         DEBUG_TRACE (DEBUG::Push2, "button was consumed, ignored\n");
680                         consumed.erase (c);
681                 }
682
683         } else {
684
685                 /* encoder/vpot */
686
687                 int delta = ev->value;
688
689                 if (delta > 63) {
690                         delta = -(128 - delta);
691                 }
692
693                 switch (ev->controller_number) {
694                 case 71:
695                         strip_vpot (0, delta);
696                         break;
697                 case 72:
698                         strip_vpot (1, delta);
699                         break;
700                 case 73:
701                         strip_vpot (2, delta);
702                         break;
703                 case 74:
704                         strip_vpot (3, delta);
705                         break;
706                 case 75:
707                         strip_vpot (4, delta);
708                         break;
709                 case 76:
710                         strip_vpot (5, delta);
711                         break;
712                 case 77:
713                         strip_vpot (6, delta);
714                         break;
715                 case 78:
716                         strip_vpot (7, delta);
717                         break;
718
719                         /* left side pair */
720                 case 14:
721                         strip_vpot (8, delta);
722                         break;
723                 case 15:
724                         other_vpot (1, delta);
725                         break;
726
727                         /* right side */
728                 case 79:
729                         other_vpot (2, delta);
730                         break;
731                 }
732         }
733 }
734
735 void
736 Push2::handle_midi_note_on_message (MIDI::Parser& parser, MIDI::EventTwoBytes* ev)
737 {
738         DEBUG_TRACE (DEBUG::Push2, string_compose ("Note On %1 (velocity %2)\n", (int) ev->note_number, (int) ev->velocity));
739
740         if (ev->velocity == 0) {
741                 handle_midi_note_off_message (parser, ev);
742                 return;
743         }
744
745         switch (ev->note_number) {
746         case 0:
747                 strip_vpot_touch (0, ev->velocity > 64);
748                 break;
749         case 1:
750                 strip_vpot_touch (1, ev->velocity > 64);
751                 break;
752         case 2:
753                 strip_vpot_touch (2, ev->velocity > 64);
754                 break;
755         case 3:
756                 strip_vpot_touch (3, ev->velocity > 64);
757                 break;
758         case 4:
759                 strip_vpot_touch (4, ev->velocity > 64);
760                 break;
761         case 5:
762                 strip_vpot_touch (5, ev->velocity > 64);
763                 break;
764         case 6:
765                 strip_vpot_touch (6, ev->velocity > 64);
766                 break;
767         case 7:
768                 strip_vpot_touch (7, ev->velocity > 64);
769                 break;
770
771                 /* left side */
772         case 10:
773                 other_vpot_touch (0, ev->velocity > 64);
774                 break;
775         case 9:
776                 other_vpot_touch (1, ev->velocity > 64);
777                 break;
778
779                 /* right side */
780         case 8:
781                 other_vpot_touch (3, ev->velocity > 64);
782                 break;
783
784                 /* touch strip */
785         case 12:
786                 if (ev->velocity < 64) {
787                         transport_stop ();
788                 }
789                 break;
790         }
791
792         if (ev->note_number < 11) {
793                 return;
794         }
795
796         /* Pad */
797
798         NNPadMap::iterator pi = nn_pad_map.find (ev->note_number);
799
800         if (pi == nn_pad_map.end()) {
801                 return;
802         }
803
804         Pad* pad = pi->second;
805
806         pad->set_color (LED::White);
807         pad->set_state (LED::OneShot24th);
808         write (pad->state_msg());
809 }
810
811 void
812 Push2::handle_midi_note_off_message (MIDI::Parser&, MIDI::EventTwoBytes* ev)
813 {
814         DEBUG_TRACE (DEBUG::Push2, string_compose ("Note Off %1 (velocity %2)\n", (int) ev->note_number, (int) ev->velocity));
815
816         if (ev->note_number < 11) {
817                 /* theoretically related to encoder touch start/end, but
818                  * actually they send note on with two different velocity
819                  * values (127 & 64).
820                  */
821                 return;
822         }
823
824         NNPadMap::iterator pi = nn_pad_map.find (ev->note_number);
825
826         if (pi == nn_pad_map.end()) {
827                 return;
828         }
829
830         Pad* pad = pi->second;
831
832         pad->set_color (LED::Black);
833         pad->set_state (LED::OneShot24th);
834         write (pad->state_msg());
835
836 }
837
838 void
839 Push2::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb)
840 {
841         if (!session) {
842                 return;
843         }
844
845         float speed;
846
847         /* range of +1 .. -1 */
848         speed = ((int32_t) pb - 8192) / 8192.0;
849         /* convert to range of +3 .. -3 */
850         session->request_transport_speed (speed * 3.0);
851 }
852
853 void
854 Push2::thread_init ()
855 {
856         struct sched_param rtparam;
857
858         pthread_set_name (event_loop_name().c_str());
859
860         PBD::notify_event_loops_about_thread_creation (pthread_self(), event_loop_name(), 2048);
861         ARDOUR::SessionEvent::create_per_thread_pool (event_loop_name(), 128);
862
863         memset (&rtparam, 0, sizeof (rtparam));
864         rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
865
866         if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
867                 // do we care? not particularly.
868         }
869 }
870
871 void
872 Push2::connect_session_signals()
873 {
874         // receive routes added
875         //session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_routes_added, this, _1), this);
876         // receive VCAs added
877         //session->vca_manager().VCAAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_vca_added, this, _1), this);
878
879         // receive record state toggled
880         session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_record_state_changed, this), this);
881         // receive transport state changed
882         session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_transport_state_changed, this), this);
883         session->TransportLooped.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_loop_state_changed, this), this);
884         // receive punch-in and punch-out
885         Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_parameter_changed, this, _1), this);
886         session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_parameter_changed, this, _1), this);
887         // receive rude solo changed
888         session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&Push2::notify_solo_active_changed, this, _1), this);
889 }
890
891 void
892 Push2::notify_record_state_changed ()
893 {
894         IDButtonMap::iterator b = id_button_map.find (RecordEnable);
895
896         if (b == id_button_map.end()) {
897                 return;
898         }
899
900         switch (session->record_status ()) {
901         case Session::Disabled:
902                 b->second->set_color (LED::White);
903                 b->second->set_state (LED::NoTransition);
904                 break;
905         case Session::Enabled:
906                 b->second->set_color (LED::Red);
907                 b->second->set_state (LED::Blinking4th);
908                 break;
909         case Session::Recording:
910                 b->second->set_color (LED::Red);
911                 b->second->set_state (LED::OneShot24th);
912                 break;
913         }
914
915         write (b->second->state_msg());
916 }
917
918 void
919 Push2::notify_transport_state_changed ()
920 {
921         Button* b = id_button_map[Play];
922
923         if (session->transport_rolling()) {
924                 b->set_state (LED::OneShot24th);
925                 b->set_color (LED::Green);
926         } else {
927
928                 /* disable any blink on FixedLength from pending edit range op */
929                 Button* fl = id_button_map[FixedLength];
930
931                 fl->set_color (LED::Black);
932                 fl->set_state (LED::NoTransition);
933                 write (fl->state_msg());
934
935                 b->set_color (LED::White);
936                 b->set_state (LED::NoTransition);
937         }
938
939         write (b->state_msg());
940 }
941
942 void
943 Push2::notify_loop_state_changed ()
944 {
945 }
946
947 void
948 Push2::notify_parameter_changed (std::string param)
949 {
950         IDButtonMap::iterator b;
951
952         if (param == "clicking") {
953                 if ((b = id_button_map.find (Metronome)) == id_button_map.end()) {
954                         return;
955                 }
956                 if (Config->get_clicking()) {
957                         b->second->set_state (LED::Blinking4th);
958                         b->second->set_color (LED::White);
959                 } else {
960                         b->second->set_color (LED::White);
961                         b->second->set_state (LED::NoTransition);
962                 }
963                 write (b->second->state_msg ());
964         }
965 }
966
967 void
968 Push2::notify_solo_active_changed (bool yn)
969 {
970         IDButtonMap::iterator b = id_button_map.find (Solo);
971
972         if (b == id_button_map.end()) {
973                 return;
974         }
975
976         if (yn) {
977                 b->second->set_state (LED::Blinking4th);
978                 b->second->set_color (LED::Red);
979         } else {
980                 b->second->set_state (LED::NoTransition);
981                 b->second->set_color (LED::White);
982         }
983
984         write (b->second->state_msg());
985 }
986
987 XMLNode&
988 Push2::get_state()
989 {
990         XMLNode& node (ControlProtocol::get_state());
991         XMLNode* child;
992
993         child = new XMLNode (X_("Input"));
994         child->add_child_nocopy (_async_in->get_state());
995         node.add_child_nocopy (*child);
996         child = new XMLNode (X_("Output"));
997         child->add_child_nocopy (_async_out->get_state());
998         node.add_child_nocopy (*child);
999
1000         return node;
1001 }
1002
1003 int
1004 Push2::set_state (const XMLNode & node, int version)
1005 {
1006         DEBUG_TRACE (DEBUG::Push2, string_compose ("Push2::set_state: active %1\n", active()));
1007
1008         int retval = 0;
1009
1010         if (ControlProtocol::set_state (node, version)) {
1011                 return -1;
1012         }
1013
1014         XMLNode* child;
1015
1016         if ((child = node.child (X_("Input"))) != 0) {
1017                 XMLNode* portnode = child->child (Port::state_node_name.c_str());
1018                 if (portnode) {
1019                         _async_in->set_state (*portnode, version);
1020                 }
1021         }
1022
1023         if ((child = node.child (X_("Output"))) != 0) {
1024                 XMLNode* portnode = child->child (Port::state_node_name.c_str());
1025                 if (portnode) {
1026                         _async_out->set_state (*portnode, version);
1027                 }
1028         }
1029
1030         return retval;
1031 }
1032
1033 void
1034 Push2::switch_bank (uint32_t base)
1035 {
1036         if (!session) {
1037                 return;
1038         }
1039
1040         stripable_connections.drop_connections ();
1041
1042         /* try to get the first stripable for the requested bank */
1043
1044         stripable[0] = session->get_remote_nth_stripable (base, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
1045
1046         if (!stripable[0]) {
1047                 return;
1048         }
1049
1050         /* at least one stripable in this bank */
1051         bank_start = base;
1052
1053         stripable[1] = session->get_remote_nth_stripable (base+1, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
1054         stripable[2] = session->get_remote_nth_stripable (base+2, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
1055         stripable[3] = session->get_remote_nth_stripable (base+3, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
1056         stripable[4] = session->get_remote_nth_stripable (base+4, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
1057         stripable[5] = session->get_remote_nth_stripable (base+5, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
1058         stripable[6] = session->get_remote_nth_stripable (base+6, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
1059         stripable[7] = session->get_remote_nth_stripable (base+7, PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::VCA));
1060
1061
1062         for (int n = 0; n < 8; ++n) {
1063                 if (!stripable[n]) {
1064                         continue;
1065                 }
1066
1067                 /* stripable goes away? refill the bank, starting at the same point */
1068
1069                 stripable[n]->DropReferences.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Push2::switch_bank, this, bank_start), this);
1070                 boost::shared_ptr<AutomationControl> sc = stripable[n]->solo_control();
1071                 if (sc) {
1072                         sc->Changed.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Push2::solo_change, this, n), this);
1073                 }
1074
1075                 boost::shared_ptr<AutomationControl> mc = stripable[n]->mute_control();
1076                 if (mc) {
1077                         mc->Changed.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Push2::mute_change, this, n), this);
1078                 }
1079
1080                 stripable[n]->presentation_info().PropertyChanged.connect (stripable_connections, MISSING_INVALIDATOR, boost::bind (&Push2::stripable_property_change, this, _1, n), this);
1081
1082                 solo_change (n);
1083                 mute_change (n);
1084
1085         }
1086
1087         /* master cannot be removed, so no need to connect to going-away signal */
1088         master = session->master_out ();
1089 }
1090
1091 void
1092 Push2::stripable_property_change (PropertyChange const& what_changed, int which)
1093 {
1094         if (what_changed.contains (Properties::selected)) {
1095                 /* cancel string, which will cause a redraw on the next update
1096                  * cycle. The redraw will reflect selected status
1097                  */
1098                 mid_layout[which]->set_text (string());
1099         }
1100 }
1101
1102 void
1103 Push2::solo_change (int n)
1104 {
1105         ButtonID bid;
1106
1107         switch (n) {
1108         case 0:
1109                 bid = Upper1;
1110                 break;
1111         case 1:
1112                 bid = Upper2;
1113                 break;
1114         case 2:
1115                 bid = Upper3;
1116                 break;
1117         case 3:
1118                 bid = Upper4;
1119                 break;
1120         case 4:
1121                 bid = Upper5;
1122                 break;
1123         case 5:
1124                 bid = Upper6;
1125                 break;
1126         case 6:
1127                 bid = Upper7;
1128                 break;
1129         case 7:
1130                 bid = Upper8;
1131                 break;
1132         default:
1133                 return;
1134         }
1135
1136         boost::shared_ptr<SoloControl> ac = stripable[n]->solo_control ();
1137         if (!ac) {
1138                 return;
1139         }
1140
1141         Button* b = id_button_map[bid];
1142
1143         if (ac->soloed()) {
1144                 b->set_color (LED::Green);
1145         } else {
1146                 b->set_color (LED::Black);
1147         }
1148
1149         if (ac->soloed_by_others_upstream() || ac->soloed_by_others_downstream()) {
1150                 b->set_state (LED::Blinking4th);
1151         } else {
1152                 b->set_state (LED::OneShot24th);
1153         }
1154
1155         write (b->state_msg());
1156 }
1157
1158 void
1159 Push2::mute_change (int n)
1160 {
1161         ButtonID bid;
1162
1163         if (!stripable[n]) {
1164                 return;
1165         }
1166
1167         cerr << "Mute changed on " << n << ' ' << stripable[n]->name() << endl;
1168
1169         switch (n) {
1170         case 0:
1171                 bid = Lower1;
1172                 break;
1173         case 1:
1174                 bid = Lower2;
1175                 break;
1176         case 2:
1177                 bid = Lower3;
1178                 break;
1179         case 3:
1180                 bid = Lower4;
1181                 break;
1182         case 4:
1183                 bid = Lower5;
1184                 break;
1185         case 5:
1186                 bid = Lower6;
1187                 break;
1188         case 6:
1189                 bid = Lower7;
1190                 break;
1191         case 7:
1192                 bid = Lower8;
1193                 break;
1194         default:
1195                 return;
1196         }
1197
1198         boost::shared_ptr<MuteControl> mc = stripable[n]->mute_control ();
1199
1200         if (!mc) {
1201                 return;
1202         }
1203
1204         Button* b = id_button_map[bid];
1205
1206         if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1207
1208                 if (mc->muted_by_self ()) {
1209                         /* full mute */
1210                         b->set_color (LED::Blue);
1211                         b->set_state (LED::OneShot24th);
1212                         cerr << "FULL MUTE1\n";
1213                 } else if (mc->muted_by_others_soloing () || mc->muted_by_masters ()) {
1214                         /* this will reflect both solo mutes AND master mutes */
1215                         b->set_color (LED::Blue);
1216                         b->set_state (LED::Blinking4th);
1217                         cerr << "OTHER MUTE1\n";
1218                 } else {
1219                         /* no mute at all */
1220                         b->set_color (LED::Black);
1221                         b->set_state (LED::OneShot24th);
1222                         cerr << "NO MUTE1\n";
1223                 }
1224
1225         } else {
1226
1227                 if (mc->muted_by_self()) {
1228                         /* full mute */
1229                         b->set_color (LED::Blue);
1230                         b->set_state (LED::OneShot24th);
1231                         cerr << "FULL MUTE2\n";
1232                 } else if (mc->muted_by_masters ()) {
1233                         /* this shows only master mutes, not mute-by-others-soloing */
1234                         b->set_color (LED::Blue);
1235                         b->set_state (LED::Blinking4th);
1236                         cerr << "OTHER MUTE1\n";
1237                 } else {
1238                         /* no mute at all */
1239                         b->set_color (LED::Black);
1240                         b->set_state (LED::OneShot24th);
1241                         cerr << "NO MUTE2\n";
1242                 }
1243         }
1244
1245         write (b->state_msg());
1246 }
1247
1248 void
1249 Push2::strip_vpot (int n, int delta)
1250 {
1251         if (stripable[n]) {
1252                 boost::shared_ptr<AutomationControl> ac = stripable[n]->gain_control();
1253                 if (ac) {
1254                         ac->set_value (ac->get_value() + ((2.0/64.0) * delta), PBD::Controllable::UseGroup);
1255                 }
1256         }
1257 }
1258
1259 void
1260 Push2::strip_vpot_touch (int n, bool touching)
1261 {
1262         if (stripable[n]) {
1263                 boost::shared_ptr<AutomationControl> ac = stripable[n]->gain_control();
1264                 if (ac) {
1265                         if (touching) {
1266                                 ac->start_touch (session->audible_frame());
1267                         } else {
1268                                 ac->stop_touch (true, session->audible_frame());
1269                         }
1270                 }
1271         }
1272 }
1273
1274 void
1275 Push2::other_vpot (int n, int delta)
1276 {
1277         switch (n) {
1278         case 0:
1279                 break;
1280         case 1:
1281                 break;
1282         case 2:
1283                 /* master gain control */
1284                 if (master) {
1285                         boost::shared_ptr<AutomationControl> ac = master->gain_control();
1286                         if (ac) {
1287                                 ac->set_value (ac->get_value() + ((2.0/64.0) * delta), PBD::Controllable::UseGroup);
1288                         }
1289                 }
1290                 break;
1291         }
1292 }
1293
1294 void
1295 Push2::other_vpot_touch (int n, bool touching)
1296 {
1297         switch (n) {
1298         case 0:
1299                 break;
1300         case 1:
1301                 break;
1302         case 2:
1303                 if (master) {
1304                         boost::shared_ptr<AutomationControl> ac = master->gain_control();
1305                         if (ac) {
1306                                 if (touching) {
1307                                         ac->start_touch (session->audible_frame());
1308                                 } else {
1309                                         ac->stop_touch (true, session->audible_frame());
1310                                 }
1311                         }
1312                 }
1313         }
1314 }
1315
1316 void
1317 Push2::start_shift ()
1318 {
1319         cerr << "start shift\n";
1320         modifier_state = ModifierState (modifier_state | ModShift);
1321         Button* b = id_button_map[Shift];
1322         b->set_color (LED::White);
1323         b->set_state (LED::Blinking16th);
1324         write (b->state_msg());
1325 }
1326
1327 void
1328 Push2::end_shift ()
1329 {
1330         if (modifier_state & ModShift) {
1331                 cerr << "end shift\n";
1332                 modifier_state = ModifierState (modifier_state & ~(ModShift));
1333                 Button* b = id_button_map[Shift];
1334                 b->timeout_connection.disconnect ();
1335                 b->set_color (LED::White);
1336                 b->set_state (LED::OneShot24th);
1337                 write (b->state_msg());
1338         }
1339 }
1340
1341 void
1342 Push2::start_select ()
1343 {
1344         cerr << "start select\n";
1345         modifier_state = ModifierState (modifier_state | ModSelect);
1346         Button* b = id_button_map[Select];
1347         b->set_color (LED::White);
1348         b->set_state (LED::Blinking16th);
1349         write (b->state_msg());
1350 }
1351
1352 void
1353 Push2::end_select ()
1354 {
1355         if (modifier_state & ModSelect) {
1356                 cerr << "end select\n";
1357                 modifier_state = ModifierState (modifier_state & ~(ModSelect));
1358                 Button* b = id_button_map[Select];
1359                 b->timeout_connection.disconnect ();
1360                 b->set_color (LED::White);
1361                 b->set_state (LED::OneShot24th);
1362                 write (b->state_msg());
1363         }
1364 }
1365
1366 void
1367 Push2::splash ()
1368 {
1369         std::string splash_file;
1370
1371         Searchpath rc (ARDOUR::ardour_data_search_path());
1372         rc.add_subdirectory_to_paths ("resources");
1373
1374         if (!find_file (rc, PROGRAM_NAME "-splash.png", splash_file)) {
1375                 cerr << "Cannot find splash screen image file\n";
1376                 throw failed_constructor();
1377         }
1378
1379         Cairo::RefPtr<Cairo::ImageSurface> img = Cairo::ImageSurface::create_from_png (splash_file);
1380
1381         double x_ratio = (double) img->get_width() / (cols - 20);
1382         double y_ratio = (double) img->get_height() / (rows - 20);
1383         double scale = min (x_ratio, y_ratio);
1384
1385         /* background */
1386
1387         context->set_source_rgb (0.764, 0.882, 0.882);
1388         context->paint ();
1389
1390         /* image */
1391
1392         context->save ();
1393         context->translate (5, 5);
1394         context->scale (scale, scale);
1395         context->set_source (img, 0, 0);
1396         context->paint ();
1397         context->restore ();
1398
1399         /* text */
1400
1401         Glib::RefPtr<Pango::Layout> some_text = Pango::Layout::create (context);
1402
1403         Pango::FontDescription fd ("Sans 38");
1404         some_text->set_font_description (fd);
1405         some_text->set_text (string_compose ("%1 %2", PROGRAM_NAME, VERSIONSTRING));
1406
1407         context->move_to (200, 10);
1408         context->set_source_rgb (0, 0, 0);
1409         some_text->update_from_cairo_context (context);
1410         some_text->show_in_cairo_context (context);
1411
1412         Pango::FontDescription fd2 ("Sans Italic 18");
1413         some_text->set_font_description (fd2);
1414         some_text->set_text (_("Ableton Push 2 Support"));
1415
1416         context->move_to (200, 80);
1417         context->set_source_rgb (0, 0, 0);
1418         some_text->update_from_cairo_context (context);
1419         some_text->show_in_cairo_context (context);
1420
1421         splash_start = get_microseconds ();
1422         blit_to_device_frame_buffer ();
1423 }
1424
1425 bool
1426 Push2::pad_filter (MidiBuffer& in, MidiBuffer& out) const
1427 {
1428         /* This filter is called asynchronously from a realtime process
1429            context. It must use atomics to check state, and must not block.
1430         */
1431
1432         bool matched = false;
1433
1434         for (MidiBuffer::iterator ev = in.begin(); ev != in.end(); ++ev) {
1435                 if ((*ev).is_note_on() || (*ev).is_note_off()) {
1436                         /* encoder touch start/touch end use note 0-10 */
1437                         if ((*ev).note() > 10) {
1438                                 out.push_back (*ev);
1439                                 matched = true;
1440                         }
1441                 }
1442         }
1443
1444         return matched;
1445 }