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