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