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