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