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