1 /*
2  * Copyright (C) 2000-2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2009-2010 David Robillard <d@drobilla.net>
5  * Copyright (C) 2010-2012 Carl Hetherington <carl@carlh.net>
6  * Copyright (C) 2015-2019 Robin Gareus <robin@gareus.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 #ifndef __midipp_mmc_h_h__
24 #define __midipp_mmc_h_h__
25 
26 #include "temporal/time.h"
27 
28 #include "pbd/signals.h"
29 #include "pbd/ringbuffer.h"
30 
31 #include "midi++/libmidi_visibility.h"
32 #include "midi++/types.h"
33 #include "midi++/parser.h"
34 
35 namespace ARDOUR {
36 	class PortEngine;
37 }
38 
39 namespace MIDI {
40 
41 class Port;
42 class Parser;
43 class MachineControlCommand;
44 
45 /** Class to handle incoming and outgoing MIDI machine control messages */
46 class LIBMIDIPP_API MachineControl
47 {
48   public:
49 	typedef PBD::Signal1<void,MachineControl&> MMCSignal;
50 
51 	enum Command {
52 		cmdStop = 0x1,
53 		cmdPlay = 0x2,
54 		cmdDeferredPlay = 0x3,
55 		cmdFastForward = 0x4,
56 		cmdRewind = 0x5,
57 		cmdRecordStrobe = 0x6,
58 
59 		cmdRecordExit = 0x7,
60 		cmdRecordPause = 0x8,
61 		cmdPause = 0x9,
62 		cmdEject = 0xA,
63 		cmdChase = 0xB,
64 		cmdCommandErrorReset = 0xC,
65 		cmdMmcReset = 0xD,
66 
67 		cmdIllegalMackieJogStart = 0x20,
68 		cmdIllegalMackieJogStop = 0x21,
69 
70 		cmdWrite = 0x40,
71 		cmdMaskedWrite = 0x41,
72 		cmdRead = 0x42,
73 		cmdUpdate = 0x43,
74 		cmdLocate = 0x44,
75 		cmdVariablePlay = 0x45,
76 		cmdSearch = 0x46,
77 
78 		cmdShuttle = 0x47,
79 		cmdStep = 0x48,
80 		cmdAssignSystemMaster = 0x49,
81 		cmdGeneratorCommand = 0x4A,
82 		cmdMtcCommand = 0x4B,
83 		cmdMove = 0x4C,
84 		cmdAdd = 0x4D,
85 
86 		cmdSubtract = 0x4E,
87 		cmdDropFrameAdjust = 0x4F,
88 		cmdProcedure = 0x50,
89 		cmdEvent = 0x51,
90 		cmdGroup = 0x52,
91 		cmdCommandSegment = 0x53,
92 		cmdDeferredVariablePlay = 0x54,
93 
94 		cmdRecordStrobeVariable = 0x55,
95 
96 		cmdWait = 0x7C,
97 		cmdResume = 0x7F
98 	};
99 
100         MachineControl ();
101 
102         void set_ports (MIDI::Port* input, MIDI::Port* output);
103 
input_port()104 	Port* input_port() { return _input_port; }
output_port()105 	Port* output_port() { return _output_port; }
106 
107 	void set_receive_device_id (byte id);
108 	void set_send_device_id (byte id);
receive_device_id()109 	byte receive_device_id () const { return _receive_device_id; }
send_device_id()110 	byte send_device_id () const { return _send_device_id; }
111 	void enable_send (bool);
send_enabled()112 	bool send_enabled () const { return _enable_send; }
113 	void send (MachineControlCommand const &, timestamp_t when);
114 
115 	static bool is_mmc (byte *sysex_buf, size_t len);
116 
117 	/* Signals to connect to if you want to run "callbacks"
118 	   when certain MMC commands are received.
119 	*/
120 
121 	MMCSignal Stop;
122 	MMCSignal Play;
123 	MMCSignal DeferredPlay;
124 	MMCSignal FastForward;
125 	MMCSignal Rewind;
126 	MMCSignal RecordStrobe;
127 	MMCSignal RecordExit;
128 	MMCSignal RecordPause;
129 	MMCSignal Pause;
130 	MMCSignal Eject;
131 	MMCSignal Chase;
132 	MMCSignal CommandErrorReset;
133 	MMCSignal MmcReset;
134 	MMCSignal JogStart;
135 	MMCSignal JogStop;
136 	MMCSignal Write;
137 	MMCSignal MaskedWrite;
138 	MMCSignal Read;
139 	MMCSignal Update;
140 	MMCSignal VariablePlay;
141 	MMCSignal Search;
142 	MMCSignal AssignSystemMaster;
143 	MMCSignal GeneratorCommand;
144 	MMCSignal MidiTimeCodeCommand;
145 	MMCSignal Move;
146 	MMCSignal Add;
147 	MMCSignal Subtract;
148 	MMCSignal DropFrameAdjust;
149 	MMCSignal Procedure;
150 	MMCSignal Event;
151 	MMCSignal Group;
152 	MMCSignal CommandSegment;
153 	MMCSignal DeferredVariablePlay;
154 	MMCSignal RecordStrobeVariable;
155 	MMCSignal Wait;
156 	MMCSignal Resume;
157 
158 	PBD::Signal0<void> SPPStart;
159 	PBD::Signal0<void> SPPContinue;
160 	PBD::Signal0<void> SPPStop;
161 
162 	/* The second argument is the shuttle speed, the third is
163 	   true if the direction is "forwards", false for "reverse"
164 	*/
165 
166 	PBD::Signal3<void,MachineControl&,float,bool> Shuttle;
167 
168 	/* The second argument specifies the desired track record enabled
169 	   status.
170 	*/
171 
172 	PBD::Signal3<void,MachineControl &,size_t,bool>
173 		                             TrackRecordStatusChange;
174 
175 	/* The second argument specifies the desired track record enabled
176 	   status.
177 	*/
178 
179 	PBD::Signal3<void,MachineControl &,size_t,bool>
180 		                             TrackMuteChange;
181 
182 	/* The second argument points to a byte array containing
183 	   the locate target value in MMC Standard Time Code
184 	   format (5 bytes, roughly: hrs/mins/secs/frames/subframes)
185 	*/
186 
187 	PBD::Signal2<void,MachineControl &, const byte *> Locate;
188 
189 	/* The second argument is the number of steps to jump */
190 
191 	PBD::Signal2<void,MachineControl &, int> Step;
192 
193 #define MMC_NTRACKS 48
194 
195 	/* note: these are not currently in use */
196 
197 	byte updateRate;
198 	byte responseError;
199 	byte commandError;
200 	byte commandErrorLevel;
201 
202 	byte motionControlTally;
203 	byte velocityTally;
204 	byte stopMode;
205 	byte fastMode;
206 	byte recordMode;
207 	byte recordStatus;
208 	bool trackRecordStatus[MMC_NTRACKS];
209 	bool trackRecordReady[MMC_NTRACKS];
210 	byte globalMonitor;
211 	byte recordMonitor;
212 	byte trackSyncMonitor;
213 	byte trackInputMonitor;
214 	byte stepLength;
215 	byte playSpeedReference;
216 	byte fixedSpeed;
217 	byte lifterDefeat;
218 	byte controlDisable;
219 	byte trackMute[MMC_NTRACKS];
220 	byte failure;
221 	byte selectedTimeCode;
222 	byte shortSelectedTimeCode;
223 	byte timeStandard;
224 	byte selectedTimeCodeSource;
225 	byte selectedTimeCodeUserbits;
226 	byte selectedMasterCode;
227 	byte requestedOffset;
228 	byte actualOffset;
229 	byte lockDeviation;
230 	byte shortSelectedMasterCode;
231 	byte shortRequestedOffset;
232 	byte shortActualOffset;
233 	byte shortLockDeviation;
234 	byte resolvedPlayMode;
235 	byte chaseMode;
236 	byte generatorTimeCode;
237 	byte shortGeneratorTimeCode;
238 	byte generatorCommandTally;
239 	byte generatorSetUp;
240 	byte generatorUserbits;
241 	byte vitcInsertEnable;
242 	byte midiTimeCodeInput;
243 	byte shortMidiTimeCodeInput;
244 	byte midiTimeCodeCommandTally;
245 	byte midiTimeCodeSetUp;
246 	byte gp0;
247 	byte gp1;
248 	byte gp2;
249 	byte gp3;
250 	byte gp4;
251 	byte gp5;
252 	byte gp6;
253 	byte gp7;
254 	byte shortGp0;
255 	byte shortGp1;
256 	byte shortGp2;
257 	byte shortGp3;
258 	byte shortGp4;
259 	byte shortGp5;
260 	byte shortGp6;
261 	byte shortGp7;
262 	byte procedureResponse;
263 	byte eventResponse;
264 	byte responseSegment;
265 	byte wait;
266 	byte resume;
267 
268   private:
269 	byte _receive_device_id;
270 	byte _send_device_id;
271 	Port* _input_port;
272 	Port* _output_port;
273 	bool _enable_send; ///< true if MMC sending is enabled
274 
275 	void process_mmc_message (Parser &p, byte *, size_t len);
276 	PBD::ScopedConnectionList port_connections; ///< connections to our parser for incoming data
277 
278 	int  do_masked_write (byte *, size_t len);
279 	int  do_locate (byte *, size_t len);
280 	int  do_step (byte *, size_t len);
281 	int  do_shuttle (byte *, size_t len);
282 
283 	void write_track_status (byte *, size_t len, byte reg);
284 	void spp_start ();
285 	void spp_continue ();
286 	void spp_stop ();
287 };
288 
289 /** Class to describe a MIDI machine control command to be sent.
290  *  In an ideal world we might use a class hierarchy for this, but objects of this type
291  *  have to be allocated off the stack for RT safety.
292  */
293 class LIBMIDIPP_API MachineControlCommand
294 {
295 public:
MachineControlCommand()296 	MachineControlCommand () : _command (MachineControl::Command (0)) {}
297 	MachineControlCommand (MachineControl::Command);
298 	MachineControlCommand (Timecode::Time);
299 
300 	MIDI::byte* fill_buffer (MachineControl *mmc, MIDI::byte *) const;
301 
302 private:
303 	MachineControl::Command _command;
304 	Timecode::Time _time;
305 };
306 
307 } // namespace MIDI
308 
309 #endif /* __midipp_mmc_h_h__ */
310