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