~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to libs/surfaces/mackie/surface.cc

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
ImportĀ upstreamĀ versionĀ 3.4~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "midi++/port.h"
 
27
#include "midi++/manager.h"
 
28
 
 
29
#include "ardour/automation_control.h"
 
30
#include "ardour/debug.h"
 
31
#include "ardour/route.h"
 
32
#include "ardour/panner.h"
 
33
#include "ardour/panner_shell.h"
 
34
#include "ardour/rc_configuration.h"
 
35
#include "ardour/session.h"
 
36
#include "ardour/utils.h"
 
37
 
 
38
#include "control_group.h"
 
39
#include "surface_port.h"
 
40
#include "surface.h"
 
41
#include "strip.h"
 
42
#include "mackie_control_protocol.h"
 
43
#include "jog_wheel.h"
 
44
 
 
45
#include "strip.h"
 
46
#include "button.h"
 
47
#include "led.h"
 
48
#include "pot.h"
 
49
#include "fader.h"
 
50
#include "jog.h"
 
51
#include "meter.h"
 
52
 
 
53
#include "i18n.h"
 
54
 
 
55
using namespace std;
 
56
using namespace PBD;
 
57
using namespace Mackie;
 
58
using ARDOUR::Route;
 
59
using ARDOUR::Panner;
 
60
using ARDOUR::Pannable;
 
61
using ARDOUR::AutomationControl;
 
62
 
 
63
#define ui_context() MackieControlProtocol::instance() /* a UICallback-derived object that specifies the event loop for signal handling */
 
64
 
 
65
// The MCU sysex header.4th byte Will be overwritten
 
66
// when we get an incoming sysex that identifies
 
67
// the device type
 
68
static MidiByteArray mackie_sysex_hdr  (5, MIDI::sysex, 0x0, 0x0, 0x66, 0x14);
 
69
 
 
70
// The MCU extender sysex header.4th byte Will be overwritten
 
71
// when we get an incoming sysex that identifies
 
72
// the device type
 
73
static MidiByteArray mackie_sysex_hdr_xt  (5, MIDI::sysex, 0x0, 0x0, 0x66, 0x15);
 
74
 
 
75
static MidiByteArray empty_midi_byte_array;
 
76
 
 
77
Surface::Surface (MackieControlProtocol& mcp, const std::string& device_name, uint32_t number, surface_type_t stype)
 
78
        : _mcp (mcp)
 
79
        , _stype (stype)
 
80
        , _number (number)
 
81
        , _name (device_name)
 
82
        , _active (false)
 
83
        , _connected (false)
 
84
        , _jog_wheel (0)
 
85
        , _master_fader (0)
 
86
        , _last_master_gain_written (-0.0f)
 
87
{
 
88
        DEBUG_TRACE (DEBUG::MackieControl, "Surface::Surface init\n");
 
89
        
 
90
        _port = new SurfacePort (*this);
 
91
 
 
92
        /* only the first Surface object has global controls */
 
93
 
 
94
        if (_number == 0) {
 
95
                DEBUG_TRACE (DEBUG::MackieControl, "Surface is first. Might have global controls.\n");
 
96
                if (_mcp.device_info().has_global_controls()) {
 
97
                        init_controls ();
 
98
                        DEBUG_TRACE (DEBUG::MackieControl, "init_controls done\n");
 
99
                }
 
100
 
 
101
                if (_mcp.device_info().has_master_fader()) {
 
102
                        setup_master ();
 
103
                        DEBUG_TRACE (DEBUG::MackieControl, "setup_master done\n");
 
104
                }
 
105
        }
 
106
 
 
107
        uint32_t n = _mcp.device_info().strip_cnt();
 
108
        
 
109
        if (n) {
 
110
                init_strips (n);
 
111
                DEBUG_TRACE (DEBUG::MackieControl, "init_strips done\n");
 
112
        }
 
113
        
 
114
        connect_to_signals ();
 
115
 
 
116
        DEBUG_TRACE (DEBUG::MackieControl, "Surface::Surface done\n");
 
117
}
 
118
 
 
119
Surface::~Surface ()
 
120
{
 
121
        DEBUG_TRACE (DEBUG::MackieControl, "Surface::~Surface init\n");
 
122
 
 
123
        zero_all ();
 
124
 
 
125
        // delete groups
 
126
        for (Groups::iterator it = groups.begin(); it != groups.end(); ++it) {
 
127
                delete it->second;
 
128
        }
 
129
        
 
130
        // delete controls
 
131
        for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
 
132
                delete *it;
 
133
        }
 
134
        
 
135
        delete _jog_wheel;
 
136
        delete _port;
 
137
 
 
138
        DEBUG_TRACE (DEBUG::MackieControl, "Surface::~Surface done\n");
 
139
}
 
140
 
 
141
const MidiByteArray& 
 
142
Surface::sysex_hdr() const
 
143
{
 
144
        switch  (_stype) {
 
145
        case mcu: return mackie_sysex_hdr;
 
146
        case ext: return mackie_sysex_hdr_xt;
 
147
        }
 
148
        cout << "SurfacePort::sysex_hdr _port_type not known" << endl;
 
149
        return mackie_sysex_hdr;
 
150
}
 
151
 
 
152
static GlobalControlDefinition mackie_global_controls[] = {
 
153
        { "external", Pot::External, Pot::factory, "none" },
 
154
        { "fader_touch", Led::FaderTouch, Led::factory, "master" },
 
155
        { "timecode", Led::Timecode, Led::factory, "none" },
 
156
        { "beats", Led::Beats, Led::factory, "none" },
 
157
        { "solo", Led::RudeSolo, Led::factory, "none" },
 
158
        { "relay_click", Led::RelayClick, Led::factory, "none" },
 
159
        { "", 0, Led::factory, "" }
 
160
};
 
161
 
 
162
void 
 
163
Surface::init_controls()
 
164
{
 
165
        Group* group;
 
166
        
 
167
        DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating groups\n");
 
168
        groups["assignment"] = new Group  ("assignment");
 
169
        groups["automation"] = new Group  ("automation");
 
170
        groups["bank"] = new Group  ("bank");
 
171
        groups["cursor"] = new Group  ("cursor");
 
172
        groups["display"] = new Group  ("display");
 
173
        groups["function select"] = new Group  ("function select");
 
174
        groups["global view"] = new Group ("global view");
 
175
        groups["master"] = new Group ("master");
 
176
        groups["modifiers"] = new Group  ("modifiers");
 
177
        groups["none"] = new Group  ("none");
 
178
        groups["transport"] = new Group  ("transport");
 
179
        groups["user"] = new Group  ("user");
 
180
        groups["utilities"] = new Group  ("utilities");
 
181
                
 
182
        DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating jog wheel\n");
 
183
        if (_mcp.device_info().has_jog_wheel()) {
 
184
                _jog_wheel = new Mackie::JogWheel (_mcp);
 
185
        }
 
186
 
 
187
        DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: creating global controls\n");
 
188
        for (uint32_t n = 0; mackie_global_controls[n].name[0]; ++n) {
 
189
                group = groups[mackie_global_controls[n].group_name];
 
190
                Control* control = mackie_global_controls[n].factory (*this, mackie_global_controls[n].id, mackie_global_controls[n].name, *group);
 
191
                controls_by_device_independent_id[mackie_global_controls[n].id] = control;
 
192
        }
 
193
 
 
194
        /* add global buttons */
 
195
        DEBUG_TRACE (DEBUG::MackieControl, "Surface::init_controls: adding global buttons\n");
 
196
        const map<Button::ID,GlobalButtonInfo>& global_buttons (_mcp.device_info().global_buttons());
 
197
 
 
198
        for (map<Button::ID,GlobalButtonInfo>::const_iterator b = global_buttons.begin(); b != global_buttons.end(); ++b){
 
199
                group = groups[b->second.group];
 
200
                controls_by_device_independent_id[b->first] = Button::factory (*this, b->first, b->second.id, b->second.label, *group);
 
201
        }
 
202
}
 
203
 
 
204
void 
 
205
Surface::init_strips (uint32_t n)
 
206
{
 
207
        const map<Button::ID,StripButtonInfo>& strip_buttons (_mcp.device_info().strip_buttons());
 
208
 
 
209
        for (uint32_t i = 0; i < n; ++i) {
 
210
 
 
211
                char name[32];
 
212
                
 
213
                snprintf (name, sizeof (name), "strip_%d", (8* _number) + i);
 
214
 
 
215
                Strip* strip = new Strip (*this, name, i, strip_buttons);
 
216
                
 
217
                groups[name] = strip;
 
218
                strips.push_back (strip);
 
219
        }
 
220
}
 
221
 
 
222
void
 
223
Surface::setup_master ()
 
224
{
 
225
        boost::shared_ptr<Route> m;
 
226
        
 
227
        if ((m = _mcp.get_session().monitor_out()) == 0) {
 
228
                m = _mcp.get_session().master_out();
 
229
        } 
 
230
        
 
231
        if (!m) {
 
232
                return;
 
233
        }
 
234
 
 
235
        _master_fader = dynamic_cast<Fader*> (Fader::factory (*this, _mcp.device_info().strip_cnt(), "master", *groups["master"]));
 
236
        
 
237
        _master_fader->set_control (m->gain_control());
 
238
        m->gain_control()->Changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&Surface::master_gain_changed, this), ui_context());
 
239
 
 
240
        Groups::iterator group_it;
 
241
        group_it = groups.find("master");
 
242
 
 
243
        DeviceInfo device_info = _mcp.device_info();
 
244
        GlobalButtonInfo master_button = device_info.get_global_button(Button::MasterFaderTouch);
 
245
        Button* bb = dynamic_cast<Button*> (Button::factory (
 
246
                *this,
 
247
                Button::MasterFaderTouch,
 
248
                master_button.id,
 
249
                master_button.label,
 
250
                *(group_it->second)
 
251
));
 
252
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 Master Fader new button BID %2 id %3\n",
 
253
                number(), Button::MasterFaderTouch, bb->id()));
 
254
}
 
255
 
 
256
void
 
257
Surface::master_gain_changed ()
 
258
{
 
259
        if (!_master_fader) {
 
260
                return;
 
261
        }
 
262
 
 
263
        boost::shared_ptr<AutomationControl> ac = _master_fader->control();
 
264
        if (!ac) {
 
265
                return;
 
266
        }
 
267
 
 
268
        float normalized_position = ac->internal_to_interface (ac->get_value());
 
269
        if (normalized_position == _last_master_gain_written) {
 
270
                return;
 
271
        }
 
272
 
 
273
        DEBUG_TRACE (DEBUG::MackieControl, "Surface::master_gain_changed: updating surface master fader\n");
 
274
 
 
275
        _port->write (_master_fader->set_position (normalized_position));
 
276
        _last_master_gain_written = normalized_position;
 
277
}
 
278
 
 
279
float 
 
280
Surface::scaled_delta (float delta, float current_speed)
 
281
{
 
282
        /* XXX needs work before use */
 
283
        const float sign = delta < 0.0 ? -1.0 : 1.0;
 
284
 
 
285
        return ((sign * std::pow (delta + 1.0, 2.0)) + current_speed) / 100.0;
 
286
}
 
287
 
 
288
void 
 
289
Surface::display_bank_start (uint32_t current_bank)
 
290
{
 
291
        if  (current_bank == 0) {
 
292
                // send Ar. to 2-char display on the master
 
293
                show_two_char_display ("Ar", "..");
 
294
        } else {
 
295
                // write the current first remote_id to the 2-char display
 
296
                show_two_char_display (current_bank);
 
297
        }
 
298
}
 
299
 
 
300
void 
 
301
Surface::blank_jog_ring ()
 
302
{
 
303
        Control* control = controls_by_device_independent_id[Jog::ID];
 
304
 
 
305
        if (control) {
 
306
                Pot* pot = dynamic_cast<Pot*> (control);
 
307
                if (pot) {
 
308
                        _port->write (pot->set (0.0, false, Pot::spread));
 
309
                }
 
310
        }
 
311
}
 
312
 
 
313
float
 
314
Surface::scrub_scaling_factor () const
 
315
{
 
316
        return 100.0;
 
317
}
 
318
 
 
319
void 
 
320
Surface::connect_to_signals ()
 
321
{
 
322
        if (!_connected) {
 
323
 
 
324
 
 
325
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface %1 connecting to signals on port %2\n", 
 
326
                                                                   number(), _port->input_port().name()));
 
327
 
 
328
                MIDI::Parser* p = _port->input_port().parser();
 
329
 
 
330
                /* Incoming sysex */
 
331
                p->sysex.connect_same_thread (*this, boost::bind (&Surface::handle_midi_sysex, this, _1, _2, _3));
 
332
                /* V-Pot messages are Controller */
 
333
                p->controller.connect_same_thread (*this, boost::bind (&Surface::handle_midi_controller_message, this, _1, _2));
 
334
                /* Button messages are NoteOn */
 
335
                p->note_on.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
 
336
                /* Button messages are NoteOn. libmidi++ sends note-on w/velocity = 0 as note-off so catch them too */
 
337
                p->note_off.connect_same_thread (*this, boost::bind (&Surface::handle_midi_note_on_message, this, _1, _2));
 
338
                /* Fader messages are Pitchbend */
 
339
                uint32_t i;
 
340
                for (i = 0; i < _mcp.device_info().strip_cnt(); i++) {
 
341
                        p->channel_pitchbend[i].connect_same_thread (*this, boost::bind (&Surface::handle_midi_pitchbend_message, this, _1, _2, i));
 
342
                }
 
343
                // Master fader
 
344
                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()));
 
345
                
 
346
                _connected = true;
 
347
        }
 
348
}
 
349
 
 
350
void
 
351
Surface::handle_midi_pitchbend_message (MIDI::Parser&, MIDI::pitchbend_t pb, uint32_t fader_id)
 
352
{
 
353
        /* Pitchbend messages are fader messages. Nothing in the data we get
 
354
         * from the MIDI::Parser conveys the fader ID, which was given by the
 
355
         * channel ID in the status byte.
 
356
         *
 
357
         * Instead, we have used bind() to supply the fader-within-strip ID 
 
358
         * when we connected to the per-channel pitchbend events.
 
359
         */
 
360
 
 
361
 
 
362
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface::handle_midi_pitchbend_message on port %3, fader = %1 value = %2\n",
 
363
                                                           fader_id, pb, _number));
 
364
        
 
365
        if (_mcp.device_info().no_handshake()) {
 
366
                turn_it_on ();
 
367
        }
 
368
 
 
369
        Fader* fader = faders[fader_id];
 
370
 
 
371
        if (fader) {
 
372
                Strip* strip = dynamic_cast<Strip*> (&fader->group());
 
373
                float pos = (pb >> 4)/1023.0; // only the top 10 bytes are used
 
374
                if (strip) {
 
375
                        strip->handle_fader (*fader, pos);
 
376
                } else {
 
377
                        DEBUG_TRACE (DEBUG::MackieControl, "Handling master fader\n");
 
378
                        /* master fader */
 
379
                        fader->set_value (pos); // alter master gain
 
380
                        _port->write (fader->set_position (pos)); // write back value (required for servo)
 
381
                }
 
382
        } else {
 
383
                DEBUG_TRACE (DEBUG::MackieControl, "fader not found\n");
 
384
        }
 
385
}
 
386
 
 
387
void 
 
388
Surface::handle_midi_note_on_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
 
389
{
 
390
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Surface::handle_midi_note_on_message %1 = %2\n", (int) ev->note_number, (int) ev->velocity));
 
391
        
 
392
        if (_mcp.device_info().no_handshake()) {
 
393
                turn_it_on ();
 
394
        }
 
395
 
 
396
        Button* button = buttons[ev->note_number];
 
397
 
 
398
        if (button) {
 
399
                Strip* strip = dynamic_cast<Strip*> (&button->group());
 
400
 
 
401
                if (strip) {
 
402
                        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("strip %1 button %2 pressed ? %3\n",
 
403
                                                                           strip->index(), button->name(), (ev->velocity > 64)));
 
404
                        strip->handle_button (*button, ev->velocity > 64 ? press : release);
 
405
                } else {
 
406
                        /* global button */
 
407
                        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("global button %1\n", button->id()));
 
408
                        _mcp.handle_button_event (*this, *button, ev->velocity > 64 ? press : release);
 
409
                }
 
410
        } else {
 
411
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("no button found for %1\n", (int) ev->note_number));
 
412
        }
 
413
}
 
414
 
 
415
void 
 
416
Surface::handle_midi_controller_message (MIDI::Parser &, MIDI::EventTwoBytes* ev)
 
417
{
 
418
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("SurfacePort::handle_midi_controller %1 = %2\n", (int) ev->controller_number, (int) ev->value));
 
419
 
 
420
        if (_mcp.device_info().no_handshake()) {
 
421
                turn_it_on ();
 
422
        }
 
423
 
 
424
        Pot* pot = pots[ev->controller_number];
 
425
 
 
426
        // bit 6 gives the sign
 
427
        float sign = (ev->value & 0x40) == 0 ? 1.0 : -1.0; 
 
428
        // bits 0..5 give the velocity. we interpret this as "ticks
 
429
        // moved before this message was sent"
 
430
        float ticks = (ev->value & 0x3f);
 
431
        if (ticks == 0) {
 
432
                /* euphonix and perhaps other devices send zero
 
433
                   when they mean 1, we think.
 
434
                */
 
435
                ticks = 1;
 
436
        }
 
437
        float delta = sign * (ticks / (float) 0x3f);
 
438
        
 
439
        if (!pot) {
 
440
                if (ev->controller_number == Jog::ID && _jog_wheel) {
 
441
 
 
442
                        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Jog wheel moved %1\n", ticks));
 
443
                        _jog_wheel->jog_event (delta);
 
444
                        return;
 
445
                }
 
446
 
 
447
                return;
 
448
        }
 
449
 
 
450
        Strip* strip = dynamic_cast<Strip*> (&pot->group());
 
451
        if (strip) {
 
452
                strip->handle_pot (*pot, delta);
 
453
        } 
 
454
}
 
455
 
 
456
void 
 
457
Surface::handle_midi_sysex (MIDI::Parser &, MIDI::byte * raw_bytes, size_t count)
 
458
{
 
459
        MidiByteArray bytes (count, raw_bytes);
 
460
 
 
461
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("handle_midi_sysex: %1\n", bytes));
 
462
 
 
463
        if (_mcp.device_info().no_handshake()) {
 
464
                turn_it_on ();
 
465
        }
 
466
 
 
467
        /* always save the device type ID so that our outgoing sysex messages
 
468
         * are correct 
 
469
         */
 
470
 
 
471
        if (_stype == mcu) {
 
472
                mackie_sysex_hdr[4] = bytes[4];
 
473
        } else {
 
474
                mackie_sysex_hdr_xt[4] = bytes[4];
 
475
        }
 
476
 
 
477
        switch (bytes[5]) {
 
478
        case 0x01:
 
479
                /* MCP: Device Ready 
 
480
                   LCP: Connection Challenge 
 
481
                */
 
482
                if (bytes[4] == 0x10 || bytes[4] == 0x11) {
 
483
                        write_sysex (host_connection_query (bytes));
 
484
                } else {
 
485
                        if (!_active) {
 
486
                                turn_it_on ();
 
487
                        }
 
488
                }
 
489
                break;
 
490
 
 
491
        case 0x03: /* LCP Connection Confirmation */
 
492
                if (bytes[4] == 0x10 || bytes[4] == 0x11) {
 
493
                        write_sysex (host_connection_confirmation (bytes));
 
494
                        _active = true;
 
495
                }
 
496
                break;
 
497
 
 
498
        case 0x04: /* LCP: Confirmation Denied */
 
499
                _active = false;
 
500
                break;
 
501
        default:
 
502
                error << "MCP: unknown sysex: " << bytes << endmsg;
 
503
        }
 
504
}
 
505
 
 
506
static MidiByteArray 
 
507
calculate_challenge_response (MidiByteArray::iterator begin, MidiByteArray::iterator end)
 
508
{
 
509
        MidiByteArray l;
 
510
        back_insert_iterator<MidiByteArray> back  (l);
 
511
        copy (begin, end, back);
 
512
        
 
513
        MidiByteArray retval;
 
514
        
 
515
        // this is how to calculate the response to the challenge.
 
516
        // from the Logic docs.
 
517
        retval <<  (0x7f &  (l[0] +  (l[1] ^ 0xa) - l[3]));
 
518
        retval <<  (0x7f &  ( (l[2] >> l[3]) ^  (l[0] + l[3])));
 
519
        retval <<  (0x7f &  ((l[3] -  (l[2] << 2)) ^  (l[0] | l[1])));
 
520
        retval <<  (0x7f &  (l[1] - l[2] +  (0xf0 ^  (l[3] << 4))));
 
521
        
 
522
        return retval;
 
523
}
 
524
 
 
525
// not used right now
 
526
MidiByteArray 
 
527
Surface::host_connection_query (MidiByteArray & bytes)
 
528
{
 
529
        MidiByteArray response;
 
530
        
 
531
        if (bytes[4] != 0x10 && bytes[4] != 0x11) {
 
532
                /* not a Logic Control device - no response required */
 
533
                return response;
 
534
        }
 
535
 
 
536
        // handle host connection query
 
537
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host connection query: %1\n", bytes));
 
538
        
 
539
        if  (bytes.size() != 18) {
 
540
                cerr << "expecting 18 bytes, read " << bytes << " from " << _port->input_port().name() << endl;
 
541
                return response;
 
542
        }
 
543
 
 
544
        // build and send host connection reply
 
545
        response << 0x02;
 
546
        copy (bytes.begin() + 6, bytes.begin() + 6 + 7, back_inserter (response));
 
547
        response << calculate_challenge_response (bytes.begin() + 6 + 7, bytes.begin() + 6 + 7 + 4);
 
548
        return response;
 
549
}
 
550
 
 
551
// not used right now
 
552
MidiByteArray 
 
553
Surface::host_connection_confirmation (const MidiByteArray & bytes)
 
554
{
 
555
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("host_connection_confirmation: %1\n", bytes));
 
556
        
 
557
        // decode host connection confirmation
 
558
        if  (bytes.size() != 14) {
 
559
                ostringstream os;
 
560
                os << "expecting 14 bytes, read " << bytes << " from " << _port->input_port().name();
 
561
                throw MackieControlException (os.str());
 
562
        }
 
563
        
 
564
        // send version request
 
565
        return MidiByteArray (2, 0x13, 0x00);
 
566
}
 
567
 
 
568
void
 
569
Surface::turn_it_on ()
 
570
{
 
571
        if (_active) {
 
572
                return;
 
573
        }
 
574
 
 
575
        _active = true;
 
576
 
 
577
        for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
 
578
                (*s)->notify_all ();
 
579
        }
 
580
 
 
581
        update_view_mode_display ();
 
582
 
 
583
        if (_mcp.device_info ().has_global_controls ()) {
 
584
                _mcp.update_global_button (Button::Read, _mcp.metering_active ());
 
585
        }
 
586
}
 
587
 
 
588
void 
 
589
Surface::handle_port_inactive (SurfacePort*)
 
590
{
 
591
        _active = false;
 
592
}
 
593
 
 
594
void 
 
595
Surface::write_sysex (const MidiByteArray & mba)
 
596
{
 
597
        if (mba.empty()) {
 
598
                return;
 
599
        }
 
600
 
 
601
        MidiByteArray buf;
 
602
        buf << sysex_hdr() << mba << MIDI::eox;
 
603
        _port->write (buf);
 
604
}
 
605
 
 
606
void 
 
607
Surface::write_sysex (MIDI::byte msg)
 
608
{
 
609
        MidiByteArray buf;
 
610
        buf << sysex_hdr() << msg << MIDI::eox;
 
611
        _port->write (buf);
 
612
}
 
613
 
 
614
uint32_t
 
615
Surface::n_strips (bool with_locked_strips) const
 
616
{
 
617
        if (with_locked_strips) {
 
618
                return strips.size();
 
619
        } 
 
620
 
 
621
        uint32_t n = 0;
 
622
 
 
623
        for (Strips::const_iterator it = strips.begin(); it != strips.end(); ++it) {
 
624
                if (!(*it)->locked()) {
 
625
                        ++n;
 
626
                }
 
627
        }
 
628
        return n;
 
629
}
 
630
 
 
631
Strip*
 
632
Surface::nth_strip (uint32_t n) const
 
633
{
 
634
        if (n > n_strips()) {
 
635
                return 0;
 
636
        }
 
637
        return strips[n];
 
638
}
 
639
 
 
640
void
 
641
Surface::zero_all ()
 
642
{
 
643
        if (_mcp.device_info().has_timecode_display ()) {
 
644
                display_timecode (string (10, '0'), string (10, ' '));
 
645
        }
 
646
        
 
647
        if (_mcp.device_info().has_two_character_display()) {
 
648
                show_two_char_display (string (2, '0'), string (2, ' '));
 
649
        }
 
650
 
 
651
        if (_mcp.device_info().has_master_fader () && _master_fader) {
 
652
                _port->write (_master_fader->zero ());
 
653
        }
 
654
 
 
655
        // zero all strips
 
656
        for (Strips::iterator it = strips.begin(); it != strips.end(); ++it) {
 
657
                (*it)->zero();
 
658
        }
 
659
 
 
660
        zero_controls ();
 
661
}
 
662
 
 
663
void
 
664
Surface::zero_controls ()
 
665
{
 
666
        if (!_mcp.device_info().has_global_controls()) {
 
667
                return;
 
668
        }
 
669
 
 
670
        // turn off global buttons and leds
 
671
        // global buttons are only ever on mcu_port, so we don't have
 
672
        // to figure out which port.
 
673
 
 
674
        for (Controls::iterator it = controls.begin(); it != controls.end(); ++it) {
 
675
                Control & control = **it;
 
676
                if (!control.group().is_strip()) {
 
677
                        _port->write (control.zero());
 
678
                }
 
679
        }
 
680
 
 
681
        // and the led ring for the master strip
 
682
        blank_jog_ring ();
 
683
 
 
684
        _last_master_gain_written = 0.0f;
 
685
}
 
686
 
 
687
void
 
688
Surface::periodic (uint64_t now_usecs)
 
689
{
 
690
        master_gain_changed();
 
691
        for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
 
692
                (*s)->periodic (now_usecs);
 
693
        }
 
694
}
 
695
 
 
696
void
 
697
Surface::write (const MidiByteArray& data) 
 
698
{
 
699
        if (_active) {
 
700
                _port->write (data);
 
701
        } else {
 
702
                DEBUG_TRACE (DEBUG::MackieControl, "surface not active, write ignored\n");
 
703
        }
 
704
}
 
705
 
 
706
void
 
707
Surface::map_routes (const vector<boost::shared_ptr<Route> >& routes)
 
708
{
 
709
        vector<boost::shared_ptr<Route> >::const_iterator r;
 
710
        Strips::iterator s = strips.begin();
 
711
 
 
712
        for (r = routes.begin(); r != routes.end() && s != strips.end(); ++s) {
 
713
 
 
714
                /* don't try to assign routes to a locked strip. it won't
 
715
                   use it anyway, but if we do, then we get out of sync
 
716
                   with the proposed mapping.
 
717
                */
 
718
 
 
719
                if (!(*s)->locked()) {
 
720
                        (*s)->set_route (*r);
 
721
                        ++r;
 
722
                }
 
723
        }
 
724
 
 
725
        for (; s != strips.end(); ++s) {
 
726
                (*s)->set_route (boost::shared_ptr<Route>());
 
727
        }
 
728
 
 
729
 
 
730
}
 
731
 
 
732
static char 
 
733
translate_seven_segment (char achar)
 
734
{
 
735
        achar = toupper (achar);
 
736
 
 
737
        if  (achar >= 0x40 && achar <= 0x60) {
 
738
                return achar - 0x40;
 
739
        } else if  (achar >= 0x21 && achar <= 0x3f) {
 
740
                return achar;
 
741
        } else {
 
742
                return 0x00;
 
743
        }
 
744
}
 
745
 
 
746
void
 
747
Surface::show_two_char_display (const std::string & msg, const std::string & dots)
 
748
{
 
749
        if (_stype != mcu || !_mcp.device_info().has_two_character_display() || msg.length() != 2 || dots.length() != 2) {
 
750
                return;
 
751
        }
 
752
        
 
753
        MidiByteArray right (3, 0xb0, 0x4b, 0x00);
 
754
        MidiByteArray left (3, 0xb0, 0x4a, 0x00);
 
755
        
 
756
        right[2] = translate_seven_segment (msg[0]) +  (dots[0] == '.' ? 0x40 : 0x00);
 
757
        left[2] = translate_seven_segment (msg[1]) +  (dots[1] == '.' ? 0x40 : 0x00);
 
758
        
 
759
        _port->write (right);
 
760
        _port->write (left);
 
761
}
 
762
 
 
763
void
 
764
Surface::show_two_char_display (unsigned int value, const std::string & /*dots*/)
 
765
{
 
766
        ostringstream os;
 
767
        os << setfill('0') << setw(2) << value % 100;
 
768
        show_two_char_display (os.str());
 
769
}
 
770
 
 
771
void
 
772
Surface::display_timecode (const std::string & timecode, const std::string & last_timecode)
 
773
{
 
774
        if (!_active || !_mcp.device_info().has_timecode_display()) {
 
775
                return;
 
776
        }
 
777
        // if there's no change, send nothing, not even sysex header
 
778
        if  (timecode == last_timecode) return;
 
779
        
 
780
        // length sanity checking
 
781
        string local_timecode = timecode;
 
782
 
 
783
        // truncate to 10 characters
 
784
        if  (local_timecode.length() > 10) {
 
785
                local_timecode = local_timecode.substr (0, 10);
 
786
        }
 
787
 
 
788
        // pad to 10 characters
 
789
        while  (local_timecode.length() < 10) { 
 
790
                local_timecode += " ";
 
791
        }
 
792
        
 
793
        // translate characters.
 
794
        // Only the characters that actually changed are sent.
 
795
        int position = 0x3f;
 
796
        int i;
 
797
        for (i = local_timecode.length () - 1; i >= 0; i--) {
 
798
                position++;
 
799
                if (local_timecode[i] == last_timecode[i]) {
 
800
                        continue;
 
801
                }
 
802
                MidiByteArray retval (2, 0xb0, position);
 
803
                retval << translate_seven_segment (local_timecode[i]);
 
804
                _port->write (retval);
 
805
        }
 
806
}
 
807
 
 
808
void
 
809
Surface::update_flip_mode_display ()
 
810
{
 
811
        for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
 
812
                (*s)->flip_mode_changed (true);
 
813
        }
 
814
}
 
815
 
 
816
void
 
817
Surface::update_view_mode_display ()
 
818
{
 
819
        string text;
 
820
        int id = -1;
 
821
 
 
822
        if (!_active) {
 
823
                return;
 
824
        }
 
825
 
 
826
        switch (_mcp.view_mode()) {
 
827
        case MackieControlProtocol::Mixer:
 
828
                show_two_char_display ("Mx");
 
829
                id = Button::Pan;
 
830
                break;
 
831
        case MackieControlProtocol::Dynamics:
 
832
                show_two_char_display ("Dy");
 
833
                id = Button::Dyn;
 
834
                break;
 
835
        case MackieControlProtocol::EQ:
 
836
                show_two_char_display ("EQ");
 
837
                id = Button::Eq;
 
838
                break;
 
839
        case MackieControlProtocol::Loop:
 
840
                show_two_char_display ("LP");
 
841
                id = Button::Loop;
 
842
                break;
 
843
        case MackieControlProtocol::AudioTracks:
 
844
                show_two_char_display ("AT");
 
845
                break;
 
846
        case MackieControlProtocol::MidiTracks:
 
847
                show_two_char_display ("MT");
 
848
                break;
 
849
        case MackieControlProtocol::Sends:
 
850
                show_two_char_display ("Sn");
 
851
                id = Button::Sends;
 
852
                break;
 
853
        case MackieControlProtocol::Plugins:
 
854
                show_two_char_display ("Pl");
 
855
                id = Button::Plugin;
 
856
                break;
 
857
        default:
 
858
                break;
 
859
        }
 
860
 
 
861
        if (id >= 0) {
 
862
                
 
863
                /* we are attempting to turn a global button/LED on */
 
864
 
 
865
                map<int,Control*>::iterator x = controls_by_device_independent_id.find (id);
 
866
 
 
867
                if (x != controls_by_device_independent_id.end()) {
 
868
                        Button* button = dynamic_cast<Button*> (x->second);
 
869
                        if (button) {
 
870
                                _port->write (button->set_state (on));
 
871
                        }
 
872
                }
 
873
        }
 
874
 
 
875
        if (!text.empty()) {
 
876
                for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
 
877
                        _port->write ((*s)->display (1, text));
 
878
                }
 
879
        }
 
880
}
 
881
 
 
882
void
 
883
Surface::gui_selection_changed (const ARDOUR::StrongRouteNotificationList& routes)
 
884
{
 
885
        for (Strips::iterator s = strips.begin(); s != strips.end(); ++s) {
 
886
                (*s)->gui_selection_changed (routes);
 
887
        }
 
888
}
 
889
 
 
890
void
 
891
Surface::say_hello ()
 
892
{
 
893
        /* wakeup for Mackie Control */
 
894
        MidiByteArray wakeup (7, MIDI::sysex, 0x00, 0x00, 0x66, 0x14, 0x00, MIDI::eox);
 
895
        _port->write (wakeup);
 
896
        wakeup[4] = 0x15; /* wakup Mackie XT */
 
897
        _port->write (wakeup);
 
898
        wakeup[4] = 0x10; /* wakupe Logic Control */
 
899
        _port->write (wakeup);
 
900
        wakeup[4] = 0x11; /* wakeup Logic Control XT */
 
901
        _port->write (wakeup);
 
902
}
 
903
 
 
904
void
 
905
Surface::next_jog_mode ()
 
906
{
 
907
}
 
908
 
 
909
void
 
910
Surface::set_jog_mode (JogWheel::Mode)
 
911
{
 
912
}       
 
913
 
 
914
bool
 
915
Surface::route_is_locked_to_strip (boost::shared_ptr<Route> r) const
 
916
{
 
917
        for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
 
918
                if ((*s)->route() == r && (*s)->locked()) {
 
919
                        return true;
 
920
                }
 
921
        }
 
922
        return false;
 
923
}
 
924
 
 
925
void 
 
926
Surface::notify_metering_state_changed()
 
927
{
 
928
        for (Strips::const_iterator s = strips.begin(); s != strips.end(); ++s) {
 
929
                (*s)->notify_metering_state_changed ();
 
930
        }
 
931
}