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