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