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