enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / surfaces / mackie / surface.cc
1 /*
2     Copyright (C) 2012 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
20 #include <sstream>
21 #include <iomanip>
22 #include <iostream>
23 #include <cstdio>
24 #include <cmath>
25
26 #include <glibmm/convert.h>
27
28 #include "pbd/stacktrace.h"
29
30 #include "midi++/port.h"
31
32 #include "ardour/audioengine.h"
33 #include "ardour/automation_control.h"
34 #include "ardour/debug.h"
35 #include "ardour/route.h"
36 #include "ardour/panner.h"
37 #include "ardour/panner_shell.h"
38 #include "ardour/profile.h"
39 #include "ardour/rc_configuration.h"
40 #include "ardour/session.h"
41 #include "ardour/utils.h"
42
43 #include <gtkmm2ext/gui_thread.h>
44
45 #include "control_group.h"
46 #include "surface_port.h"
47 #include "surface.h"
48 #include "strip.h"
49 #include "mackie_control_protocol.h"
50 #include "jog_wheel.h"
51
52 #include "strip.h"
53 #include "button.h"
54 #include "led.h"
55 #include "pot.h"
56 #include "fader.h"
57 #include "jog.h"
58 #include "meter.h"
59
60 #include "pbd/i18n.h"
61
62 #ifdef PLATFORM_WINDOWS
63 #define random() rand()
64 #endif
65
66 using namespace std;
67 using namespace PBD;
68 using ARDOUR::Stripable;
69 using ARDOUR::Panner;
70 using ARDOUR::Profile;
71 using ARDOUR::AutomationControl;
72 using namespace ArdourSurface;
73 using namespace Mackie;
74
75 #define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
76
77 // The MCU sysex header.4th byte Will be overwritten
78 // when we get an incoming sysex that identifies
79 // the device type
80 static MidiByteArray mackie_sysex_hdr  (5, MIDI::sysex, 0x0, 0x0, 0x66, 0x14);
81
82 // The MCU extender sysex header.4th byte Will be overwritten
83 // when we get an incoming sysex that identifies
84 // the device type
85 static MidiByteArray mackie_sysex_hdr_xt  (5, MIDI::sysex, 0x0, 0x0, 0x66, 0x15);
86
87 static MidiByteArray empty_midi_byte_array;
88
89 Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, uint32_t number, surface_type_t stype)
90         : _mcp (mcp)
91         , _stype (stype)
92         , _number (number)
93         , _name (device_name)
94         , _active (false)
95         , _connected (false)
96         , _jog_wheel (0)
97         , _master_fader (0)
98         , _last_master_gain_written (-0.0f)
99         , connection_state (0)
100         , input_source (0)
101 {
102         DEBUG_TRACE (DEBUG::MackieControl, "Surface::Surface init\n");
103
104         try {
105                 _port = new SurfacePort (*this);
106         } catch (...) {
107                 throw failed_constructor ();
108         }
109
110         /* only the first Surface object has global controls */
111         /* lets use master_position instead */
112         uint32_t mp = _mcp.device_info().master_position();
113         if (_number == mp) {
114                 DEBUG_TRACE (DEBUG::MackieControl, "Surface matches MasterPosition. Might have global controls.\n");
115                 if (_mcp.device_info().has_global_controls()) {
116                         init_controls ();
117                         DEBUG_TRACE (DEBUG::MackieControl, "init_controls done\n");
118                 }
119
120                 if (_mcp.device_info().has_master_fader()) {
121                         setup_master ();
122                         DEBUG_TRACE (DEBUG::MackieControl, "setup_master done\n");
123                 }
124         }
125
126         uint32_t n = _mcp.device_info().strip_cnt();
127
128         if (n) {
129                 init_strips (n);
130                 DEBUG_TRACE (DEBUG::MackieControl, "init_strips done\n");
131         }
132
133         if (_mcp.device_info().uses_ipmidi()) {
134                 /* ipMIDI port already exists, we can just assume that we're
135                  * connected.
136                  *
137                  * If the user still hasn't connected the ipMIDI surface and/or
138                  * turned it on, then they have to press "Discover Mackie
139                  * Devices" in the GUI at the right time.
140                  */
141
142                 connection_state |= (InputConnected|OutputConnected);
143                 connected ();
144         }
145
146         connect_to_signals ();
147
148         DEBUG_TRACE (DEBUG::MackieControl, "Surface::Surface done\n");
149 }
150
151 Surface::~Surface ()
152 {
153         DEBUG_TRACE (DEBUG::MackieControl, "Surface::~Surface init\n");
154
155         if (input_source) {
156                 g_source_destroy (input_source);
157                 input_source = 0;
158         }
159
160         // delete groups (strips)
161         for (Groups::iterator it = groups.begin(); it != groups.end(); ++it) {
162                 delete it->second;
163         }
164
165         // delete controls (global buttons, master fader etc)
166         for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
167                 delete *it;
168         }
169
170         delete _jog_wheel;
171         delete _port;
172         // the ports take time to release and we may be rebuilding right away
173         // in the case of changing devices.
174         g_usleep (10000);
175         DEBUG_TRACE (DEBUG::MackieControl, "Surface::~Surface done\n");
176 }
177
178 bool
179 Surface::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
180 {
181         if (!_port) {
182                 return false;
183         }
184
185         string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (_port->input_name());
186         string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (_port->output_name());
187
188         if (ni == name1 || ni == name2) {
189                 if (yn) {
190                         connection_state |= InputConnected;
191                 } else {
192                         connection_state &= ~InputConnected;
193                 }
194         } else if (no == name1 || no == name2) {
195                 if (yn) {
196                         connection_state |= OutputConnected;
197                 } else {
198                         connection_state &= ~OutputConnected;
199                 }
200         } else {
201                 /* not our ports */
202                 return false;
203         }
204
205         if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
206
207                 /* this will send a device query message, which should
208                    result in a response that will kick off device type
209                    discovery and activation of the surface(s).
210
211                    The intended order of events is:
212
213                    - each surface sends a device query message
214                    - devices respond with either MCP or LCP response (sysex in both
215                    cases)
216                    - sysex message causes Surface::turn_it_on() which tells the
217                    MCP object that the surface is ready, and sets up strip
218                    displays and binds faders and buttons for that surface
219
220                    In the case of LCP, where this is a handshake process that could
221                    fail, the response process to the initial sysex after a device query
222                    will mark the surface inactive, which won't shut anything down
223                    but will stop any writes to the device.
224
225                    Note: there are no known cases of the handshake process failing.
226
227                    We actually can't initiate this in this callback, so we have
228                    to queue it with the MCP event loop.
229                 */
230
231                 /* XXX this is a horrible hack. Without a short sleep here,
232                    something prevents the device wakeup messages from being
233                    sent and/or the responses from being received.
234                 */
235
236                 g_usleep (100000);
237                 connected ();
238
239         } else {
240                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 disconnected (input or output or both)\n", _name));
241                 _active = false;
242         }
243
244         return true; /* connection status changed */
245 }
246
247 XMLNode&
248 Surface::get_state()
249 {
250         XMLNode* node = new XMLNode (X_("Surface"));
251         node->add_property (X_("name"), _name);
252         node->add_child_nocopy (_port->get_state());
253         return *node;
254 }
255
256 int
257 Surface::set_state (const XMLNode& node, int version)
258 {
259         /* Look for a node named after the device we're part of */
260
261         XMLNodeList const& children = node.children();
262         XMLNode* mynode = 0;
263
264         for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
265                 XMLProperty const* prop = (*c)->property (X_("name"));
266                 if (prop) {
267                         if (prop->value() == _name) {
268                                 mynode = *c;
269                                 break;
270                         }
271                 }
272         }
273
274         if (!mynode) {
275                 return 0;
276         }
277
278         XMLNode* portnode = mynode->child (X_("Port"));
279         if (portnode) {
280                 if (_port->set_state (*portnode, version)) {
281                         return -1;
282                 }
283         }
284
285         return 0;
286 }
287
288 const MidiByteArray&
289 Surface::sysex_hdr() const
290 {
291         switch  (_stype) {
292         case mcu: return mackie_sysex_hdr;
293         case ext: return mackie_sysex_hdr_xt;
294         }
295         cout << "SurfacePort::sysex_hdr _port_type not known" << endl;
296         return mackie_sysex_hdr;
297 }
298
299 static GlobalControlDefinition mackie_global_controls[] = {
300         { "external", Pot::External, Pot::factory, "none" },
301         { "fader_touch", Led::FaderTouch, Led::factory, "master" },
302         { "timecode", Led::Timecode, Led::factory, "none" },
303         { "beats", Led::Beats, Led::factory, "none" },
304         { "solo", Led::RudeSolo, Led::factory, "none" },
305         { "relay_click", Led::RelayClick, Led::factory, "none" },
306         { "", 0, Led::factory, "" }
307 };
308
309 void
310 Surface::init_controls()
311 {
312         Group* group;
313
314         DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating groups\n");
315         groups["assignment"] = new Group  ("assignment");
316         groups["automation"] = new Group  ("automation");
317         groups["bank"] = new Group  ("bank");
318         groups["cursor"] = new Group  ("cursor");
319         groups["display"] = new Group  ("display");
320         groups["function select"] = new Group  ("function select");
321         groups["global view"] = new Group ("global view");
322         groups["master"] = new Group ("master");
323         groups["modifiers"] = new Group  ("modifiers");
324         groups["none"] = new Group  ("none");
325         groups["transport"] = new Group  ("transport");
326         groups["user"] = new Group  ("user");
327         groups["utilities"] = new Group  ("utilities");
328
329         DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating jog wheel\n");
330         if (_mcp.device_info().has_jog_wheel()) {
331                 _jog_wheel = new Mackie::JogWheel (_mcp);
332         }
333
334         DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating global controls\n");
335         for (uint32_t n = 0; mackie_global_controls[n].name[0]; ++n) {
336                 group = groups[mackie_global_controls[n].group_name];
337                 Control* control = mackie_global_controls[n].factory (*this, mackie_global_controls[n].id, mackie_global_controls[n].name, *group);
338                 controls_by_device_independent_id[mackie_global_controls[n].id] = control;
339         }
340
341         /* add global buttons */
342         DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: adding global buttons\n");
343         const map<Button::ID,GlobalButtonInfo>& global_buttons (_mcp.device_info().global_buttons());
344
345         for (map<Button::ID,GlobalButtonInfo>::const_iterator b = global_buttons.begin(); b != global_buttons.end(); ++b){
346                 group = groups[b->second.group];
347                 controls_by_device_independent_id[b->first] = Button::factory (*this, b->first, b->second.id, b->second.label, *group);
348         }
349 }
350
351 void
352 Surface::init_strips (uint32_t n)
353 {
354         const map<Button::ID,StripButtonInfo>& strip_buttons (_mcp.device_info().strip_buttons());
355
356         for (uint32_t i = 0; i < n; ++i) {
357
358                 char name[32];
359
360                 snprintf (name, sizeof (name), "strip_%d", (8* _number) + i);
361
362                 Strip* strip = new Strip (*this, name, i, strip_buttons);
363
364                 groups[name] = strip;
365                 strips.push_back (strip);
366         }
367 }
368
369 void
370 Surface::master_monitor_may_have_changed ()
371 {
372         if (_number == _mcp.device_info().master_position()) {
373                 setup_master ();
374         }
375 }
376
377 void
378 Surface::setup_master ()
379 {
380         boost::shared_ptr<Stripable> m;
381
382         if ((m = _mcp.get_session().monitor_out()) == 0) {
383                 m = _mcp.get_session().master_out();
384         }
385
386         if (!m) {
387                 if (_master_fader) {
388                         _master_fader->set_control (boost::shared_ptr<AutomationControl>());
389                 }
390                 master_connection.disconnect ();
391                 return;
392         }
393
394         if (!_master_fader) {
395                 Groups::iterator group_it;
396                 Group* master_group;
397                 group_it = groups.find("master");
398
399                 if (group_it == groups.end()) {
400                         groups["master"] = master_group = new Group ("master");
401                 } else {
402                         master_group = group_it->second;
403                 }
404
405                 _master_fader = dynamic_cast<Fader*> (Fader::factory (*this, _mcp.device_info().strip_cnt(), "master", *master_group));
406
407                 DeviceInfo device_info = _mcp.device_info();
408                 GlobalButtonInfo master_button = device_info.get_global_button(Button::MasterFaderTouch);
409                 Button* bb = dynamic_cast<Button*> (Button::factory (
410                                                             *this,
411                                                             Button::MasterFaderTouch,
412                                                             master_button.id,
413                                                             master_button.label,
414                                                             *(group_it->second)
415                                                             ));
416
417                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 Master Fader new button BID %2 id %3\n",
418                                                                    number(), Button::MasterFaderTouch, bb->id()));
419         } else {
420                 master_connection.disconnect ();
421         }
422
423         _master_fader->set_control (m->gain_control());
424         m->gain_control()->Changed.connect (master_connection, MISSING_INVALIDATOR, boost::bind (&Surface::master_gain_changed, this), ui_context());
425         _last_master_gain_written = FLT_MAX; /* some essentially impossible value */
426         master_gain_changed ();
427 }
428
429 void
430 Surface::master_gain_changed ()
431 {
432         if (!_master_fader) {
433                 return;
434         }
435
436         boost::shared_ptr<AutomationControl> ac = _master_fader->control();
437         if (!ac) {
438                 return;
439         }
440
441         float normalized_position = ac->internal_to_interface (ac->get_value());
442         if (normalized_position == _last_master_gain_written) {
443                 return;
444         }
445
446         DEBUG_TRACE (DEBUG::MackieControl, "Surface::master_gain_changed: updating surface master fader\n");
447
448         _port->write (_master_fader->set_position (normalized_position));
449         _last_master_gain_written = normalized_position;
450 }
451
452 float
453 Surface::scaled_delta (float delta, float current_speed)
454 {
455         /* XXX needs work before use */
456         const float sign = delta < 0.0 ? -1.0 : 1.0;
457
458         return ((sign * std::pow (delta + 1.0, 2.0)) + current_speed) / 100.0;
459 }
460
461 void
462 Surface::display_bank_start (uint32_t current_bank)
463 {
464         if  (current_bank == 0) {
465                 // send Ar. to 2-char display on the master
466                 show_two_char_display ("Ar", "..");
467         } else {
468                 // write the current first remote_id to the 2-char display
469                 show_two_char_display (current_bank);
470         }
471 }
472
473 void
474 Surface::blank_jog_ring ()
475 {
476         Control* control = controls_by_device_independent_id[Jog::ID];
477
478         if (control) {
479                 Pot* pot = dynamic_cast<Pot*> (control);
480                 if (pot) {
481                         _port->write (pot->set (0.0, false, Pot::spread));
482                 }
483         }
484 }
485
486 float
487 Surface::scrub_scaling_factor () const
488 {
489         return 100.0;
490 }
491
492 void
493 Surface::connect_to_signals ()
494 {
495         if (!_connected) {
496
497
498                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 connecting to signals on port %2\n",
499                                                                    number(), _port->input_port().name()));
500
501                 MIDI::Parser* p = _port->input_port().parser();
502
503                 /* Incoming sysex */
504                 p->sysex.connect_same_thread (*this, boost::bind (&Surface::handle_midi_sysex, this, _1, _2, _3));
505                 /* V-Pot messages are Controller */
506                 p->controller.connect_same_thread (*this, boost::bind (&Surface::handle_midi_controller_message, this, _1, _2));
507                 /* Button messages are NoteOn */
508                 p->note_on.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
509                 /* Button messages are NoteOn but libmidi++ sends note-on w/velocity = 0 as note-off so catch them too */
510                 p->note_off.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
511                 /* Fader messages are Pitchbend */
512                 uint32_t i;
513                 for (i = 0; i < _mcp.device_info().strip_cnt(); i++) {
514                         p->channel_pitchbend[i].connect_same_thread (*this, boost::bind (&Surface::handle_midi_pitchbend_message, this, _1, _2, i));
515                 }
516                 // Master fader
517                 p->channel_pitchbend[_mcp.device_info().strip_cnt()].connect_same_thread (*this, boost::bind (&Surface::handle_midi_pitchbend_message, this, _1, _2, _mcp.device_info().strip_cnt()));
518
519                 _connected = true;
520         }
521 }
522
523 void
524 Surface::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb, uint32_t fader_id)
525 {
526         /* Pitchbend messages are fader position messages. Nothing in the data we get
527          * from the MIDI::Parser conveys the fader ID, which was given by the
528          * channel ID in the status byte.
529          *
530          * Instead, we have used bind() to supply the fader-within-strip ID
531          * when we connected to the per-channel pitchbend events.
532          */
533
534         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface::handle_midi_pitchbend_message on port %3, fader = %1 value = %2 (%4)\n",
535                                                            fader_id, pb, _number, pb/16384.0));
536
537         if (_mcp.device_info().no_handshake()) {
538                 turn_it_on ();
539         }
540
541         Fader* fader = faders[fader_id];
542
543         if (fader) {
544                 Strip* strip = dynamic_cast<Strip*> (&fader->group());
545                 float pos = pb / 16384.0;
546                 if (strip) {
547                         strip->handle_fader (*fader, pos);
548                 } else {
549                         DEBUG_TRACE (DEBUG::MackieControl, "Handling master fader\n");
550                         /* master fader */
551                         fader->set_value (pos); // alter master gain
552                         _port->write (fader->set_position (pos)); // write back value (required for servo)
553                 }
554         } else {
555                 DEBUG_TRACE (DEBUG::MackieControl, "fader not found\n");
556         }
557 }
558
559 void
560 Surface::handle_midi_note_on_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
561 {
562         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface::handle_midi_note_on_message %1 = %2\n", (int) ev->note_number, (int) ev->velocity));
563
564         if (_mcp.device_info().no_handshake()) {
565                 turn_it_on ();
566         }
567
568         if (_mcp.device_info().device_type() == DeviceInfo::HUI && ev->note_number == 0 && ev->velocity == 127) {
569                 turn_it_on ();
570         }
571
572         /* fader touch sense is given by "buttons" 0xe..0xe7 and 0xe8 for the
573          * master.
574          */
575
576         if (ev->note_number >= 0xE0 && ev->note_number <= 0xE8) {
577                 Fader* fader = faders[ev->note_number];
578
579                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface: fader touch message, fader = %1\n", fader));
580
581                 if (fader) {
582
583                         Strip* strip = dynamic_cast<Strip*> (&fader->group());
584
585                         if (ev->velocity > 64) {
586                                 strip->handle_fader_touch (*fader, true);
587                         } else {
588                                 strip->handle_fader_touch (*fader, false);
589                         }
590                 }
591                 return;
592         }
593
594         Button* button = buttons[ev->note_number];
595
596         if (button) {
597
598                 if (ev->velocity > 64) {
599                         button->pressed ();
600                 }
601
602                 Strip* strip = dynamic_cast<Strip*> (&button->group());
603
604                 if (strip) {
605                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 button %2 pressed ? %3\n",
606                                                                            strip->index(), button->name(), (ev->velocity > 64)));
607                         strip->handle_button (*button, ev->velocity > 64 ? press : release);
608                 } else {
609                         /* global button */
610                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("global button %1\n", button->id()));
611                         _mcp.handle_button_event (*this, *button, ev->velocity > 64 ? press : release);
612                 }
613
614                 if (ev->velocity <= 64) {
615                         button->released ();
616                 }
617
618         } else {
619                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("no button found for %1\n", (int) ev->note_number));
620         }
621
622         /* button release should reset timer AFTER handler(s) have run */
623 }
624
625 void
626 Surface::handle_midi_controller_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
627 {
628         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("SurfacePort::handle_midi_controller %1 = %2\n", (int) ev->controller_number, (int) ev->value));
629
630         if (_mcp.device_info().no_handshake()) {
631                 turn_it_on ();
632         }
633
634         Pot* pot = pots[ev->controller_number];
635
636         // bit 6 gives the sign
637         float sign = (ev->value & 0x40) == 0 ? 1.0 : -1.0;
638         // bits 0..5 give the velocity. we interpret this as "ticks
639         // moved before this message was sent"
640         float ticks = (ev->value & 0x3f);
641         if (ticks == 0) {
642                 /* euphonix and perhaps other devices send zero
643                    when they mean 1, we think.
644                 */
645                 ticks = 1;
646         }
647
648         float delta = 0;
649         if (mcp().main_modifier_state() == MackieControlProtocol::MODIFIER_SHIFT) {
650                 delta = sign * (ticks / (float) 0xff);
651         } else {
652                 delta = sign * (ticks / (float) 0x3f);
653         }
654
655         if (!pot) {
656                 if (ev->controller_number == Jog::ID && _jog_wheel) {
657
658                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Jog wheel moved %1\n", ticks));
659                         _jog_wheel->jog_event (delta);
660                         return;
661                 }
662                 // add external (pedal?) control here
663
664                 return;
665         }
666
667         Strip* strip = dynamic_cast<Strip*> (&pot->group());
668         if (strip) {
669                 strip->handle_pot (*pot, delta);
670         }
671 }
672
673 void
674 Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count)
675 {
676         MidiByteArray bytes (count, raw_bytes);
677
678         if (_mcp.device_info().no_handshake()) {
679                 turn_it_on ();
680         }
681
682         /* always save the device type ID so that our outgoing sysex messages
683          * are correct
684          */
685
686         if (_stype == mcu) {
687                 mackie_sysex_hdr[4] = bytes[4];
688         } else {
689                 mackie_sysex_hdr_xt[4] = bytes[4];
690         }
691
692         switch (bytes[5]) {
693         case 0x01:
694                 if (!_active) {
695                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", bytes));
696                 }
697                 /* MCP: Device Ready
698                    LCP: Connection Challenge
699                 */
700                 if (bytes[4] == 0x10 || bytes[4] == 0x11) {
701                         DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device connection challenge\n");
702                         write_sysex (host_connection_query (bytes));
703                 } else {
704                         if (!_active) {
705                                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Mackie Control Device ready, current status = %1\n", _active));
706                         }
707                         turn_it_on ();
708                 }
709                 break;
710
711         case 0x06:
712                 if (!_active) {
713                         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", bytes));
714                 }
715                 /* Behringer X-Touch Compact: Device Ready
716                 */
717                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Behringer X-Touch Compact ready, current status = %1\n", _active));
718                 turn_it_on ();
719                 break;
720
721         case 0x03: /* LCP Connection Confirmation */
722                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", bytes));
723                 DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device confirms connection, ardour replies\n");
724                 if (bytes[4] == 0x10 || bytes[4] == 0x11) {
725                         write_sysex (host_connection_confirmation (bytes));
726                         turn_it_on ();
727                 }
728                 break;
729
730         case 0x04: /* LCP: Confirmation Denied */
731                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", bytes));
732                 DEBUG_TRACE (DEBUG::MackieControl, "Logic Control Device denies connection\n");
733                 _active = false;
734                 break;
735
736         default:
737                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", bytes));
738                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("unknown device ID byte %1", (int) bytes[5]));
739                 error << "MCP: unknown sysex: " << bytes << endmsg;
740         }
741 }
742
743 static MidiByteArray
744 calculate_challenge_response (MidiByteArray::iterator begin, MidiByteArray::iterator end)
745 {
746         MidiByteArray l;
747         back_insert_iterator<MidiByteArray> back  (l);
748         copy (begin, end, back);
749
750         MidiByteArray retval;
751
752         // this is how to calculate the response to the challenge.
753         // from the Logic docs.
754         retval <<  (0x7f &  (l[0] +  (l[1] ^ 0xa) - l[3]));
755         retval <<  (0x7f &  ( (l[2] >> l[3]) ^  (l[0] + l[3])));
756         retval <<  (0x7f &  ((l[3] -  (l[2] << 2)) ^  (l[0] | l[1])));
757         retval <<  (0x7f &  (l[1] - l[2] +  (0xf0 ^  (l[3] << 4))));
758
759         return retval;
760 }
761
762 MidiByteArray
763 Surface::host_connection_query (MidiByteArray & bytes)
764 {
765         MidiByteArray response;
766
767         if (bytes[4] != 0x10 && bytes[4] != 0x11) {
768                 /* not a Logic Control device - no response required */
769                 return response;
770         }
771
772         // handle host connection query
773         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host connection query: %1\n", bytes));
774
775         if  (bytes.size() != 18) {
776                 cerr << "expecting 18 bytes, read " << bytes << " from " << _port->input_port().name() << endl;
777                 return response;
778         }
779
780         // build and send host connection reply
781         response << 0x02;
782         copy (bytes.begin() + 6, bytes.begin() + 6 + 7, back_inserter (response));
783         response << calculate_challenge_response (bytes.begin() + 6 + 7, bytes.begin() + 6 + 7 + 4);
784         return response;
785 }
786
787 MidiByteArray
788 Surface::host_connection_confirmation (const MidiByteArray & bytes)
789 {
790         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host_connection_confirmation: %1\n", bytes));
791
792         // decode host connection confirmation
793         if  (bytes.size() != 14) {
794                 ostringstream os;
795                 os << "expecting 14 bytes, read " << bytes << " from " << _port->input_port().name();
796                 throw MackieControlException (os.str());
797         }
798
799         // send version request
800         return MidiByteArray (2, 0x13, 0x00);
801 }
802
803 void
804 Surface::turn_it_on ()
805 {
806         if (_active) {
807                 return;
808         }
809
810         _active = true;
811
812         _mcp.device_ready ();
813
814         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
815                 (*s)->notify_all ();
816         }
817
818         update_view_mode_display (false);
819
820 //      if (_mcp.device_info ().has_global_controls ()) {
821 //              _mcp.update_global_button (Button::Read, _mcp.metering_active ());
822 //      }
823 }
824
825 void
826 Surface::write_sysex (const MidiByteArray & mba)
827 {
828         if (mba.empty()) {
829                 return;
830         }
831
832         MidiByteArray buf;
833         buf << sysex_hdr() << mba << MIDI::eox;
834         _port->write (buf);
835 }
836
837 void
838 Surface::write_sysex (MIDI::byte msg)
839 {
840         MidiByteArray buf;
841         buf << sysex_hdr() << msg << MIDI::eox;
842         _port->write (buf);
843 }
844
845 uint32_t
846 Surface::n_strips (bool with_locked_strips) const
847 {
848         if (with_locked_strips) {
849                 return strips.size();
850         }
851
852         uint32_t n = 0;
853
854         for (Strips::const_iterator it = strips.begin(); it != strips.end(); ++it) {
855                 if (!(*it)->locked()) {
856                         ++n;
857                 }
858         }
859         return n;
860 }
861
862 Strip*
863 Surface::nth_strip (uint32_t n) const
864 {
865         if (n > n_strips()) {
866                 return 0;
867         }
868         return strips[n];
869 }
870
871 void
872 Surface::zero_all ()
873 {
874         if (_mcp.device_info().has_timecode_display ()) {
875                 display_timecode (string (10, '0'), string (10, ' '));
876         }
877
878         if (_mcp.device_info().has_two_character_display()) {
879                 show_two_char_display (string (2, '0'), string (2, ' '));
880         }
881
882         if (_mcp.device_info().has_master_fader () && _master_fader) {
883                 _port->write (_master_fader->zero ());
884         }
885
886         // zero all strips
887         for (Strips::iterator it = strips.begin(); it != strips.end(); ++it) {
888                 (*it)->zero();
889         }
890
891         zero_controls ();
892 }
893
894 void
895 Surface::zero_controls ()
896 {
897         if (!_mcp.device_info().has_global_controls()) {
898                 return;
899         }
900
901         // turn off global buttons and leds
902
903         for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
904                 Control & control = **it;
905                 if (!control.group().is_strip()) {
906                         _port->write (control.zero());
907                 }
908         }
909
910         // and the led ring for the master strip
911         blank_jog_ring ();
912
913         _last_master_gain_written = 0.0f;
914 }
915
916 void
917 Surface::periodic (uint64_t now_usecs)
918 {
919         master_gain_changed();
920         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
921                 (*s)->periodic (now_usecs);
922         }
923 }
924
925 void
926 Surface::redisplay (ARDOUR::microseconds_t now, bool force)
927 {
928         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
929                 (*s)->redisplay (now, force);
930         }
931 }
932
933 void
934 Surface::write (const MidiByteArray& data)
935 {
936         if (_active) {
937                 _port->write (data);
938         } else {
939                 DEBUG_TRACE (DEBUG::MackieControl, "surface not active, write ignored\n");
940         }
941 }
942
943 void
944 Surface::map_stripables (const vector<boost::shared_ptr<Stripable> >& stripables)
945 {
946         vector<boost::shared_ptr<Stripable> >::const_iterator r;
947         Strips::iterator s = strips.begin();
948
949         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Mapping %1 stripables to %2 strips\n", stripables.size(), strips.size()));
950
951         for (r = stripables.begin(); r != stripables.end() && s != strips.end(); ++s) {
952
953                 /* don't try to assign stripables to a locked strip. it won't
954                    use it anyway, but if we do, then we get out of sync
955                    with the proposed mapping.
956                 */
957
958                 if (!(*s)->locked()) {
959                         (*s)->set_stripable (*r);
960                         ++r;
961                 }
962         }
963
964         for (; s != strips.end(); ++s) {
965                 DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 being set to null stripable\n", (*s)->index()));
966                 (*s)->set_stripable (boost::shared_ptr<Stripable>());
967         }
968 }
969
970 static char
971 translate_seven_segment (char achar)
972 {
973         achar = toupper (achar);
974
975         if  (achar >= 0x40 && achar <= 0x60) {
976                 return achar - 0x40;
977         } else if  (achar >= 0x21 && achar <= 0x3f) {
978                 return achar;
979         } else {
980                 return 0x00;
981         }
982 }
983
984 void
985 Surface::show_two_char_display (const std::string & msg, const std::string & dots)
986 {
987         if (_stype != mcu || !_mcp.device_info().has_two_character_display() || msg.length() != 2 || dots.length() != 2) {
988                 return;
989         }
990
991         MidiByteArray right (3, 0xb0, 0x4b, 0x00);
992         MidiByteArray left (3, 0xb0, 0x4a, 0x00);
993
994         right[2] = translate_seven_segment (msg[0]) +  (dots[0] == '.' ? 0x40 : 0x00);
995         left[2] = translate_seven_segment (msg[1]) +  (dots[1] == '.' ? 0x40 : 0x00);
996
997         _port->write (right);
998         _port->write (left);
999 }
1000
1001 void
1002 Surface::show_two_char_display (unsigned int value, const std::string & /*dots*/)
1003 {
1004         ostringstream os;
1005         os << setfill('0') << setw(2) << value % 100;
1006         show_two_char_display (os.str());
1007 }
1008
1009 void
1010 Surface::display_timecode (const std::string & timecode, const std::string & last_timecode)
1011 {
1012         if (!_active || !_mcp.device_info().has_timecode_display()) {
1013                 return;
1014         }
1015         // if there's no change, send nothing, not even sysex header
1016         if  (timecode == last_timecode) return;
1017
1018         // length sanity checking
1019         string local_timecode = timecode;
1020
1021         // truncate to 10 characters
1022         if  (local_timecode.length() > 10) {
1023                 local_timecode = local_timecode.substr (0, 10);
1024         }
1025
1026         // pad to 10 characters
1027         while  (local_timecode.length() < 10) {
1028                 local_timecode += " ";
1029         }
1030
1031         // translate characters.
1032         // Only the characters that actually changed are sent.
1033         int position = 0x3f;
1034         int i;
1035         for (i = local_timecode.length () - 1; i >= 0; i--) {
1036                 position++;
1037                 if (local_timecode[i] == last_timecode[i]) {
1038                         continue;
1039                 }
1040                 MidiByteArray retval (2, 0xb0, position);
1041                 retval << translate_seven_segment (local_timecode[i]);
1042                 _port->write (retval);
1043         }
1044 }
1045
1046 void
1047 Surface::update_flip_mode_display ()
1048 {
1049         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
1050                 (*s)->flip_mode_changed ();
1051         }
1052 }
1053
1054 void
1055 Surface::subview_mode_changed ()
1056 {
1057         for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
1058                 (*s)->subview_mode_changed ();
1059         }
1060 }
1061
1062 void
1063 Surface::update_view_mode_display (bool with_helpful_text)
1064 {
1065         string text;
1066         int id = -1;
1067
1068         if (!_active) {
1069                 return;
1070         }
1071
1072         switch (_mcp.view_mode()) {
1073         case MackieControlProtocol::Mixer:
1074                 show_two_char_display ("Mx");
1075                 id = Button::View;
1076                 text = _("Mixer View");
1077                 break;
1078         case MackieControlProtocol::AudioTracks:
1079                 show_two_char_display ("AT");
1080                 id = Button::AudioTracks;
1081                 text = _("Audio Tracks");
1082                 break;
1083         case MackieControlProtocol::MidiTracks:
1084                 show_two_char_display ("MT");
1085                 id = Button::MidiTracks;
1086                 text = _("MIDI Tracks");
1087                 break;
1088         case MackieControlProtocol::Plugins:
1089                 show_two_char_display ("PL");
1090                 id = Button::Plugin;
1091                 text = _("Plugins");
1092                 break;
1093         case MackieControlProtocol::Busses:
1094                 show_two_char_display ("BS");
1095                 id = Button::Busses;
1096                 if (Profile->get_mixbus()) {
1097                         text = _("Mixbusses");
1098                 } else {
1099                         text = _("Busses");
1100                 }
1101                 break;
1102         case MackieControlProtocol::Auxes:
1103                 show_two_char_display ("Au");
1104                 id = Button::Aux;
1105                 text = _("Auxes");
1106                 break;
1107         case MackieControlProtocol::Hidden:
1108                 show_two_char_display ("HI");
1109                 id = Button::Outputs;
1110                 text = _("Hidden Tracks");
1111                 break;
1112         case MackieControlProtocol::Selected:
1113                 show_two_char_display ("SE");
1114                 id = Button::User;
1115                 text = _("Selected Tracks");
1116                 break;
1117         default:
1118                 break;
1119         }
1120
1121         vector<int> view_mode_buttons;
1122         view_mode_buttons.push_back (Button::View);
1123         view_mode_buttons.push_back (Button::Busses);
1124         view_mode_buttons.push_back (Button::Plugin);
1125         view_mode_buttons.push_back (Button::AudioTracks);
1126         view_mode_buttons.push_back (Button::MidiTracks);
1127         view_mode_buttons.push_back (Button::Aux);
1128         view_mode_buttons.push_back (Button::Outputs);
1129         view_mode_buttons.push_back (Button::User);
1130
1131         if (id >= 0) {
1132
1133                 for (vector<int>::iterator i = view_mode_buttons.begin(); i != view_mode_buttons.end(); ++i) {
1134                         map<int,Control*>::iterator x = controls_by_device_independent_id.find (id);
1135
1136                         if (x != controls_by_device_independent_id.end()) {
1137                                 Button* button = dynamic_cast<Button*> (x->second);
1138                                 if (button) {
1139                                         bool onoff;
1140                                         onoff = (*i) == id;
1141
1142                                         _port->write (button->set_state (onoff));
1143                                 }
1144                         }
1145                 }
1146         }
1147
1148         if (with_helpful_text && !text.empty()) {
1149                 display_message_for (text, 1000);
1150         }
1151 }
1152
1153 void
1154 Surface::say_hello ()
1155 {
1156         /* wakeup for Mackie Control */
1157         MidiByteArray wakeup (7, MIDI::sysex, 0x00, 0x00, 0x66, 0x14, 0x00, MIDI::eox);
1158         _port->write (wakeup);
1159         wakeup[4] = 0x15; /* wakup Mackie XT */
1160         _port->write (wakeup);
1161         wakeup[4] = 0x10; /* wakeup Logic Control */
1162         _port->write (wakeup);
1163         wakeup[4] = 0x11; /* wakeup Logic Control XT */
1164         _port->write (wakeup);
1165 }
1166
1167 void
1168 Surface::next_jog_mode ()
1169 {
1170 }
1171
1172 void
1173 Surface::set_jog_mode (JogWheel::Mode)
1174 {
1175 }
1176
1177 bool
1178 Surface::stripable_is_locked_to_strip (boost::shared_ptr<Stripable> stripable) const
1179 {
1180         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1181                 if ((*s)->stripable() == stripable && (*s)->locked()) {
1182                         return true;
1183                 }
1184         }
1185         return false;
1186 }
1187
1188 bool
1189 Surface::stripable_is_mapped (boost::shared_ptr<Stripable> stripable) const
1190 {
1191         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1192                 if ((*s)->stripable() == stripable) {
1193                         return true;
1194                 }
1195         }
1196
1197         return false;
1198 }
1199
1200 void
1201 Surface::notify_metering_state_changed()
1202 {
1203         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1204                 (*s)->notify_metering_state_changed ();
1205         }
1206 }
1207
1208 void
1209 Surface::reset ()
1210 {
1211         if (_port) {
1212                 /* reset msg for Mackie Control */
1213                 MidiByteArray msg;
1214                 msg << sysex_hdr();
1215                 msg << 0x08;
1216                 msg << 0x00;
1217                 msg << MIDI::eox;
1218                 _port->write (msg);
1219         }
1220 }
1221
1222 void
1223 Surface::toggle_backlight ()
1224 {
1225         if (_port) {
1226                 int onoff = random() %2;
1227                 MidiByteArray msg;
1228                 msg << sysex_hdr ();
1229                 msg << 0xa;
1230                 msg << (onoff ? 0x1 : 0x0);
1231                 msg << MIDI::eox;
1232                 _port->write (msg);
1233         }
1234 }
1235
1236 void
1237 Surface::recalibrate_faders ()
1238 {
1239         if (_port) {
1240                 MidiByteArray msg;
1241                 msg << sysex_hdr ();
1242                 msg << 0x09;
1243                 msg << 0x00;
1244                 msg << MIDI::eox;
1245                 _port->write (msg);
1246         }
1247 }
1248
1249 void
1250 Surface::set_touch_sensitivity (int sensitivity)
1251 {
1252         /* NOTE: assumed called from GUI code, hence sleep() */
1253
1254         /* sensitivity already clamped by caller */
1255
1256         if (_port) {
1257                 MidiByteArray msg;
1258
1259                 msg << sysex_hdr ();
1260                 msg << 0x0e;
1261                 msg << 0xff; /* overwritten for each fader below */
1262                 msg << (sensitivity & 0x7f);
1263                 msg << MIDI::eox;
1264
1265                 for (int fader = 0; fader < 9; ++fader) {
1266                         msg[6] = fader;
1267                         _port->write (msg);
1268                 }
1269         }
1270 }
1271
1272 void
1273 Surface::hui_heartbeat ()
1274 {
1275         if (!_port) {
1276                 return;
1277         }
1278
1279         MidiByteArray msg (3, MIDI::on, 0x0, 0x0);
1280         _port->write (msg);
1281 }
1282
1283 void
1284 Surface::connected ()
1285 {
1286         DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 now connected, trying to ping device...\n", _name));
1287
1288         say_hello ();
1289
1290         if (_mcp.device_info().no_handshake()) {
1291                 turn_it_on ();
1292         }
1293 }
1294
1295 MidiByteArray
1296 Surface::display_line (string const& msg, int line_num)
1297 {
1298         MidiByteArray midi_msg;
1299         midi_msg << sysex_hdr ();
1300         midi_msg << 0x12;
1301         midi_msg << (line_num ? 0x38 : 0x0); /* offsets into char array
1302                                               * on device that
1303                                               * correspond to line
1304                                               * starts
1305                                               */
1306         if (msg.empty()) {
1307
1308                 midi_msg.insert (midi_msg.end(), 55, ' ');
1309
1310         } else {
1311
1312                 /* ascii data to display. @param msg is UTF-8 which is not legal. */
1313                 string ascii = Glib::convert_with_fallback (msg, "UTF-8", "ISO-8859-1", "_");
1314                 string::size_type len = ascii.length();
1315
1316                 if (len > 55) {
1317                         midi_msg << ascii.substr (0, 55);
1318                 } else {
1319                         midi_msg << ascii;
1320
1321                         for (string::size_type i = len; i < 55; ++i) {
1322                                 midi_msg << ' ';
1323                         }
1324                 }
1325         }
1326
1327         midi_msg << MIDI::eox;
1328
1329         return midi_msg;
1330 }
1331
1332 /** display @param msg on the 55x2 screen for @param msecs milliseconds
1333  *
1334  *  @param msg is assumed to be UTF-8 encoded, and will be converted
1335  *  to ASCII with an underscore as fallback character before being
1336  *  sent to the device.
1337  */
1338 void
1339 Surface::display_message_for (string const& msg, uint64_t msecs)
1340 {
1341         string::size_type newline;
1342
1343         if ((newline = msg.find ('\n')) == string::npos) {
1344
1345                 _port->write (display_line (msg, 0));
1346                 _port->write (display_line (string(), 1));
1347
1348         } else if (newline == 0) {
1349
1350                 _port->write (display_line (string(), 0));
1351                 _port->write (display_line (msg.substr (1), 1));
1352
1353         } else {
1354
1355                 string first_line = msg.substr (0, newline-1);
1356                 string second_line = msg.substr (newline+1);
1357
1358                 _port->write (display_line (first_line, 0));
1359                 _port->write (display_line (second_line.substr (0, second_line.find_first_of ('\n')), 1));
1360         }
1361
1362         for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
1363                 (*s)->block_screen_display_for (msecs);
1364         }
1365 }