1 /*
2 * Copyright (C) 2000-2017 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2009-2010 David Robillard <d@drobilla.net>
4 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
5 * Copyright (C) 2014-2015 Robin Gareus <robin@gareus.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include <fcntl.h>
23 #include <map>
24
25 #include "temporal/time.h"
26 #include "temporal/bbt_time.h"
27
28 #include "pbd/error.h"
29
30 #include "midi++/mmc.h"
31 #include "midi++/port.h"
32 #include "midi++/parser.h"
33
34 #ifndef __INT_MAX__ // 'ssize_t' won't be defined yet
35 // (except in later versions of MSVC)
36 #if !defined (_MSC_VER) || (_MSC_VER < 1800)
37 typedef long ssize_t;
38 #endif
39 #endif
40
41 using namespace std;
42 using namespace MIDI;
43 using namespace PBD;
44
45 /**
46 * As libtimecode is linked statically to libmidi++ this
47 * is necessary to pull in all the symbols from libtimecode
48 * so they are exported for other users of libtimecode.
49 */
50 double tmp = Timecode::BBT_Time::ticks_per_beat;
51
52 static std::map<int,string> mmc_cmd_map;
build_mmc_cmd_map()53 static void build_mmc_cmd_map ()
54 {
55 pair<int,string> newpair;
56
57 newpair.first = 0x1;
58 newpair.second = "Stop";
59 mmc_cmd_map.insert (newpair);
60
61 newpair.first = 0x2;
62 newpair.second = "Play";
63 mmc_cmd_map.insert (newpair);
64
65 newpair.first = 0x3;
66 newpair.second = "DeferredPlay";
67 mmc_cmd_map.insert (newpair);
68
69 newpair.first = 0x4;
70 newpair.second = "FastForward";
71 mmc_cmd_map.insert (newpair);
72
73 newpair.first = 0x5;
74 newpair.second = "Rewind";
75 mmc_cmd_map.insert (newpair);
76
77 newpair.first = 0x6;
78 newpair.second = "RecordStrobe";
79 mmc_cmd_map.insert (newpair);
80
81 newpair.first = 0x7;
82 newpair.second = "RecordExit";
83 mmc_cmd_map.insert (newpair);
84
85 newpair.first = 0x8;
86 newpair.second = "RecordPause";
87 mmc_cmd_map.insert (newpair);
88
89 newpair.first = 0x9;
90 newpair.second = "Pause";
91 mmc_cmd_map.insert (newpair);
92
93 newpair.first = 0xA;
94 newpair.second = "Eject";
95 mmc_cmd_map.insert (newpair);
96
97 newpair.first = 0xB;
98 newpair.second = "Chase";
99 mmc_cmd_map.insert (newpair);
100
101 newpair.first = 0xC;
102 newpair.second = "CommandErrorReset";
103 mmc_cmd_map.insert (newpair);
104
105 newpair.first = 0xD;
106 newpair.second = "MmcReset";
107 mmc_cmd_map.insert (newpair);
108
109 newpair.first = 0x20;
110 newpair.second = "Illegal Mackie Jog Start";
111 mmc_cmd_map.insert (newpair);
112
113 newpair.first = 0x21;
114 newpair.second = "Illegal Mackie Jog Stop";
115 mmc_cmd_map.insert (newpair);
116
117 newpair.first = 0x40;
118 newpair.second = "Write";
119 mmc_cmd_map.insert (newpair);
120
121 newpair.first = 0x41;
122 newpair.second = "MaskedWrite";
123 mmc_cmd_map.insert (newpair);
124
125 newpair.first = 0x42;
126 newpair.second = "Read";
127 mmc_cmd_map.insert (newpair);
128
129 newpair.first = 0x43;
130 newpair.second = "Update";
131 mmc_cmd_map.insert (newpair);
132
133 newpair.first = 0x44;
134 newpair.second = "Locate";
135 mmc_cmd_map.insert (newpair);
136
137 newpair.first = 0x45;
138 newpair.second = "VariablePlay";
139 mmc_cmd_map.insert (newpair);
140
141 newpair.first = 0x46;
142 newpair.second = "Search";
143 mmc_cmd_map.insert (newpair);
144
145 newpair.first = 0x47;
146 newpair.second = "Shuttle";
147 mmc_cmd_map.insert (newpair);
148
149 newpair.first = 0x48;
150 newpair.second = "Step";
151 mmc_cmd_map.insert (newpair);
152
153 newpair.first = 0x49;
154 newpair.second = "AssignSystemMaster";
155 mmc_cmd_map.insert (newpair);
156
157 newpair.first = 0x4A;
158 newpair.second = "GeneratorCommand";
159 mmc_cmd_map.insert (newpair);
160
161 newpair.first = 0x4B;
162 newpair.second = "MtcCommand";
163 mmc_cmd_map.insert (newpair);
164
165 newpair.first = 0x4C;
166 newpair.second = "Move";
167 mmc_cmd_map.insert (newpair);
168
169 newpair.first = 0x4D;
170 newpair.second = "Add";
171 mmc_cmd_map.insert (newpair);
172
173 newpair.first = 0x4E;
174 newpair.second = "Subtract";
175 mmc_cmd_map.insert (newpair);
176
177 newpair.first = 0x4F;
178 newpair.second = "DropFrameAdjust";
179 mmc_cmd_map.insert (newpair);
180
181 newpair.first = 0x50;
182 newpair.second = "Procedure";
183 mmc_cmd_map.insert (newpair);
184
185 newpair.first = 0x51;
186 newpair.second = "Event";
187 mmc_cmd_map.insert (newpair);
188
189 newpair.first = 0x52;
190 newpair.second = "Group";
191 mmc_cmd_map.insert (newpair);
192
193 newpair.first = 0x53;
194 newpair.second = "CommandSegment";
195 mmc_cmd_map.insert (newpair);
196
197 newpair.first = 0x54;
198 newpair.second = "DeferredVariablePlay";
199 mmc_cmd_map.insert (newpair);
200
201 newpair.first = 0x55;
202 newpair.second = "RecordStrobeVariable";
203 mmc_cmd_map.insert (newpair);
204
205 newpair.first = 0x7C;
206 newpair.second = "Wait";
207 mmc_cmd_map.insert (newpair);
208
209 newpair.first = 0x7F;
210 newpair.second = "Resume";
211 mmc_cmd_map.insert (newpair);
212 }
213
MachineControl()214 MachineControl::MachineControl ()
215 {
216 build_mmc_cmd_map ();
217
218 _receive_device_id = 0x7f;
219 _send_device_id = 0x7f;
220 }
221
222 void
set_ports(MIDI::Port * ip,MIDI::Port * op)223 MachineControl::set_ports (MIDI::Port* ip, MIDI::Port* op)
224 {
225 port_connections.drop_connections ();
226
227 _input_port = ip;
228 _output_port = op;
229
230 _input_port->parser()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3));
231 _input_port->parser()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this));
232 _input_port->parser()->contineu.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_continue, this));
233 _input_port->parser()->stop.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_stop, this));
234 }
235
236 void
set_receive_device_id(MIDI::byte id)237 MachineControl::set_receive_device_id (MIDI::byte id)
238 {
239 _receive_device_id = id & 0x7f;
240 }
241
242 void
set_send_device_id(MIDI::byte id)243 MachineControl::set_send_device_id (MIDI::byte id)
244 {
245 _send_device_id = id & 0x7f;
246 }
247
248 bool
is_mmc(MIDI::byte * sysex_buf,size_t len)249 MachineControl::is_mmc (MIDI::byte *sysex_buf, size_t len)
250 {
251 if (len < 4 || len > 48) {
252 return false;
253 }
254
255 if (sysex_buf[1] != 0x7f) {
256 return false;
257 }
258
259 if (sysex_buf[3] != 0x6 && /* MMC Command */
260 sysex_buf[3] != 0x7) { /* MMC Response */
261 return false;
262 }
263
264 return true;
265 }
266
267 void
process_mmc_message(Parser &,MIDI::byte * msg,size_t len)268 MachineControl::process_mmc_message (Parser &, MIDI::byte *msg, size_t len)
269 {
270 size_t skiplen;
271 byte *mmc_msg;
272 bool single_byte;
273
274 /* Reject if its not for us. 0x7f is the "all-call" device ID */
275
276 /* msg[0] = 0x7f (MMC sysex ID(
277 msg[1] = device ID
278 msg[2] = 0x6 (MMC command) or 0x7 (MMC response)
279 msg[3] = MMC command code
280 msg[4] = (typically) byte count for following part of command
281 */
282
283 #if 0
284 cerr << "*** me = " << (int) _receive_device_id << " MMC message: len = " << len << "\n\t";
285 for (size_t i = 0; i < len; i++) {
286 cerr << hex << (int) msg[i] << dec << ' ';
287 }
288 cerr << endl;
289 #endif
290
291 if (_receive_device_id != 0x7f && msg[1] != 0x7f && msg[1] != _receive_device_id) {
292 return;
293 }
294
295 mmc_msg = &msg[3];
296 len -= 3;
297
298 do {
299
300 single_byte = false;
301
302 /* this works for all non-single-byte "counted"
303 commands. we set it to 1 for the exceptions.
304 */
305
306 std::map<int,string>::iterator x = mmc_cmd_map.find ((int)mmc_msg[0]);
307 string cmdname = "unknown";
308
309 if (x != mmc_cmd_map.end()) {
310 cmdname = (*x).second;
311 }
312
313 #if 0
314 cerr << "+++ MMC type "
315 << hex
316 << ((int) *mmc_msg)
317 << dec
318 << " \"" << cmdname << "\" "
319 << " len = " << len
320 << endl;
321 #endif
322
323 switch (*mmc_msg) {
324
325 /* SINGLE-BYTE, UNCOUNTED COMMANDS */
326
327 case cmdStop:
328 Stop (*this);
329 single_byte = true;
330 break;
331
332 case cmdPlay:
333 Play (*this);
334 single_byte = true;
335 break;
336
337 case cmdDeferredPlay:
338 DeferredPlay (*this);
339 single_byte = true;
340 break;
341
342 case cmdFastForward:
343 FastForward (*this);
344 single_byte = true;
345 break;
346
347 case cmdRewind:
348 Rewind (*this);
349 single_byte = true;
350 break;
351
352 case cmdRecordStrobe:
353 RecordStrobe (*this);
354 single_byte = true;
355 break;
356
357 case cmdRecordExit:
358 RecordExit (*this);
359 single_byte = true;
360 break;
361
362 case cmdRecordPause:
363 RecordPause (*this);
364 single_byte = true;
365 break;
366
367 case cmdPause:
368 Pause (*this);
369 single_byte = true;
370 break;
371
372 case cmdEject:
373 Eject (*this);
374 single_byte = true;
375 break;
376
377 case cmdChase:
378 Chase (*this);
379 single_byte = true;
380 break;
381
382 case cmdCommandErrorReset:
383 CommandErrorReset (*this);
384 single_byte = true;
385 break;
386
387 case cmdMmcReset:
388 MmcReset (*this);
389 single_byte = true;
390 break;
391
392 case cmdIllegalMackieJogStart:
393 JogStart (*this);
394 single_byte = true;
395 break;
396
397 case cmdIllegalMackieJogStop:
398 JogStop (*this);
399 single_byte = true;
400 break;
401
402 /* END OF SINGLE-BYTE, UNCOUNTED COMMANDS */
403
404 case cmdMaskedWrite:
405 do_masked_write (mmc_msg, len);
406 break;
407
408 case cmdLocate:
409 do_locate (mmc_msg, len);
410 break;
411
412 case cmdShuttle:
413 do_shuttle (mmc_msg, len);
414 break;
415
416 case cmdStep:
417 do_step (mmc_msg, len);
418 break;
419
420 case cmdWrite:
421 case cmdRead:
422 case cmdUpdate:
423 case cmdVariablePlay:
424 case cmdSearch:
425 case cmdAssignSystemMaster:
426 case cmdGeneratorCommand:
427 case cmdMtcCommand:
428 case cmdMove:
429 case cmdAdd:
430 case cmdSubtract:
431 case cmdDropFrameAdjust:
432 case cmdProcedure:
433 case cmdEvent:
434 case cmdGroup:
435 case cmdCommandSegment:
436 case cmdDeferredVariablePlay:
437 case cmdRecordStrobeVariable:
438 case cmdWait:
439 case cmdResume:
440 error << "MIDI::MachineControl: unimplemented MMC command "
441 << hex << (int) *mmc_msg << dec
442 << endmsg;
443
444 break;
445
446 default:
447 error << "MIDI::MachineControl: unknown MMC command "
448 << hex << (int) *mmc_msg << dec
449 << endmsg;
450
451 break;
452 }
453
454 /* increase skiplen to cover the command byte and
455 count byte (if it existed).
456 */
457
458 if (!single_byte) {
459 skiplen = mmc_msg[1] + 2;
460 } else {
461 skiplen = 1;
462 }
463
464 if (len <= skiplen) {
465 break;
466 }
467
468 mmc_msg += skiplen;
469 len -= skiplen;
470
471 } while (len > 1); /* skip terminating EOX byte */
472 }
473
474 int
do_masked_write(MIDI::byte * msg,size_t len)475 MachineControl::do_masked_write (MIDI::byte *msg, size_t len)
476 {
477 /* return the number of bytes "consumed" */
478
479 int retval = msg[1] + 2; /* bytes following + 2 */
480
481 switch (msg[2]) {
482 case 0x4f: /* Track Record Ready Status */
483 write_track_status (&msg[3], len - 3, msg[2]);
484 break;
485
486 case 0x62: /* track mute */
487 write_track_status (&msg[3], len - 3, msg[2]);
488 break;
489
490 default:
491 warning << "MIDI::MachineControl: masked write to "
492 << hex << (int) msg[2] << dec
493 << " not implemented"
494 << endmsg;
495 }
496
497 return retval;
498 }
499
500 void
write_track_status(MIDI::byte * msg,size_t,MIDI::byte reg)501 MachineControl::write_track_status (MIDI::byte *msg, size_t /*len*/, MIDI::byte reg)
502 {
503 size_t n;
504 ssize_t base_track;
505
506 /* Bits 0-4 of the first byte are for special tracks:
507
508 bit 0: video
509 bit 1: reserved
510 bit 2: time code
511 bit 3: aux track a
512 bit 4: aux track b
513
514 the format of the message (its an MMC Masked Write) is:
515
516 0x41 Command Code
517 <count> byte count of following data
518 <name> byte value of the field being written
519 <byte #> byte number of target byte in the
520 bitmap being written to
521 <mask> ones in the mask indicate which bits will be changed
522 <data> new data for the byte being written
523
524 by the time this code is executing, msg[0] is the
525 byte number of the target byte. if its zero, we
526 are writing to a special byte in the standard
527 track bitmap, in which the first 5 bits are
528 special. hence the bits for tracks 1 + 2 are bits
529 5 and 6 of the first byte of the track
530 bitmap. so:
531
532 change track 1: msg[0] = 0; << first byte of track bitmap
533 msg[1] = 0100000; << binary: bit 5 set
534
535 change track 2: msg[0] = 0; << first byte of track bitmap
536 msg[1] = 1000000; << binary: bit 6 set
537
538 change track 3: msg[0] = 1; << second byte of track bitmap
539 msg[1] = 0000001; << binary: bit 0 set
540
541 the (msg[0] * 8) - 6 computation is an attempt to
542 extract the value of the first track: ie. the one
543 that would be indicated by bit 0 being set.
544
545 so, if msg[0] = 0, msg[1] = 0100000 (binary),
546 what happens is that base_track = -5, but by the
547 time we check the correct bit, n = 5, and so the
548 computed track for the status change is 0 (first
549 track).
550
551 if msg[0] = 1, then the base track for any change is 2 (the third track), and so on.
552 */
553
554 /* XXX check needed to make sure we don't go outside the
555 supported number of tracks.
556 */
557
558 if (msg[0] == 0) {
559 base_track = -5;
560 } else {
561 base_track = (msg[0] * 8) - 6;
562 }
563
564 for (n = 0; n < 7; n++) {
565 if (msg[1] & (1<<n)) {
566
567 /* Only touch tracks that have the "mask"
568 bit set.
569 */
570
571 bool val = (msg[2] & (1<<n));
572
573 switch (reg) {
574 case 0x4f:
575 trackRecordStatus[base_track+n] = val;
576 TrackRecordStatusChange (*this, base_track+n, val);
577 break;
578
579 case 0x62:
580 trackMute[base_track+n] = val;
581 TrackMuteChange (*this, base_track+n, val);
582 break;
583 }
584 }
585
586 }
587 }
588
589 int
do_locate(MIDI::byte * msg,size_t)590 MachineControl::do_locate (MIDI::byte *msg, size_t /*msglen*/)
591 {
592 if (msg[2] == 0) {
593 warning << "MIDI::MMC: locate [I/F] command not supported"
594 << endmsg;
595 return 0;
596 }
597
598 /* regular "target" locate command */
599
600 Locate (*this, &msg[3]);
601 return 0;
602 }
603
604 int
do_step(MIDI::byte * msg,size_t)605 MachineControl::do_step (MIDI::byte *msg, size_t /*msglen*/)
606 {
607 int steps = msg[2] & 0x3f;
608
609 if (msg[2] & 0x40) {
610 steps = -steps;
611 }
612
613 Step (*this, steps);
614 return 0;
615 }
616
617 int
do_shuttle(MIDI::byte * msg,size_t)618 MachineControl::do_shuttle (MIDI::byte *msg, size_t /*msglen*/)
619 {
620 size_t forward;
621 byte sh = msg[2];
622 byte sm = msg[3];
623 byte sl = msg[4];
624 size_t left_shift;
625 size_t integral;
626 size_t fractional;
627 float shuttle_speed;
628
629 if (sh & (1<<6)) {
630 forward = false;
631 } else {
632 forward = true;
633 }
634
635 left_shift = (sh & 0x38);
636
637 integral = ((sh & 0x7) << left_shift) | (sm >> (7 - left_shift));
638 fractional = ((sm << left_shift) << 7) | sl;
639
640 shuttle_speed = integral +
641 ((float)fractional / (1 << (14 - left_shift)));
642
643 Shuttle (*this, shuttle_speed, forward);
644
645 return 0;
646 }
647
648 void
enable_send(bool yn)649 MachineControl::enable_send (bool yn)
650 {
651 _enable_send = yn;
652 }
653
654 /** Send a MMC command to a the MMC port.
655 * @param c command.
656 */
657 void
send(MachineControlCommand const & c,timestamp_t when)658 MachineControl::send (MachineControlCommand const & c, timestamp_t when)
659 {
660 if (_output_port == 0 || !_enable_send) {
661 // cerr << "Not delivering MMC " << _mmc->port() << " - " << session_send_mmc << endl;
662 return;
663 }
664
665 MIDI::byte buffer[32];
666 MIDI::byte* b = c.fill_buffer (this, buffer);
667
668 if (_output_port->midimsg (buffer, b - buffer, when)) {
669 error << "MMC: cannot send command" << endmsg;
670 }
671 }
672
673 void
spp_start()674 MachineControl::spp_start ()
675 {
676 SPPStart (); /* EMIT SIGNAL */
677 }
678
679 void
spp_continue()680 MachineControl::spp_continue ()
681 {
682 SPPContinue (); /* EMIT SIGNAL */
683 }
684
685 void
spp_stop()686 MachineControl::spp_stop ()
687 {
688 SPPStop (); /* EMIT SIGNAL */
689 }
690
MachineControlCommand(MachineControl::Command c)691 MachineControlCommand::MachineControlCommand (MachineControl::Command c)
692 : _command (c)
693 {
694
695 }
696
MachineControlCommand(Timecode::Time t)697 MachineControlCommand::MachineControlCommand (Timecode::Time t)
698 : _command (MachineControl::cmdLocate)
699 , _time (t)
700 {
701
702 }
703
704 MIDI::byte *
fill_buffer(MachineControl * mmc,MIDI::byte * b) const705 MachineControlCommand::fill_buffer (MachineControl* mmc, MIDI::byte* b) const
706 {
707 *b++ = 0xf0; // SysEx
708 *b++ = 0x7f; // Real-time SysEx ID for MMC
709 *b++ = mmc->send_device_id();
710 *b++ = 0x6; // MMC command
711
712 *b++ = _command;
713
714 if (_command == MachineControl::cmdLocate) {
715 *b++ = 0x6; // byte count
716 *b++ = 0x1; // "TARGET" subcommand
717 *b++ = _time.hours % 24;
718 *b++ = _time.minutes;
719 *b++ = _time.seconds;
720 *b++ = _time.frames;
721 *b++ = _time.subframes;
722 }
723
724 *b++ = 0xf7;
725
726 return b;
727 }
728
729