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