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