/*
- Copyright (C) 2000 Paul Barton-Davis
+ Copyright (C) 2000 Paul Barton-Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id$
*/
#ifndef __midipp_mmc_h_h__
#define __midipp_mmc_h_h__
-#include <sigc++/sigc++.h>
-#include <midi++/types.h>
+#include "timecode/time.h"
+
+#include "pbd/signals.h"
+#include "pbd/ringbuffer.h"
+
+#include "midi++/libmidi_visibility.h"
+#include "midi++/types.h"
+#include "midi++/parser.h"
+
+namespace ARDOUR {
+ class PortEngine;
+}
namespace MIDI {
class Port;
class Parser;
+class MachineControlCommand;
-class MachineControl : public sigc::trackable
-
+/** Class to handle incoming and outgoing MIDI machine control messages */
+class LIBMIDIPP_API MachineControl
{
public:
- typedef byte CommandSignature[60];
- typedef byte ResponseSignature[60];
+ typedef PBD::Signal1<void,MachineControl&> MMCSignal;
enum Command {
cmdStop = 0x1,
cmdChase = 0xB,
cmdCommandErrorReset = 0xC,
cmdMmcReset = 0xD,
-
+
cmdIllegalMackieJogStart = 0x20,
cmdIllegalMackieJogStop = 0x21,
-
+
cmdWrite = 0x40,
cmdMaskedWrite = 0x41,
cmdRead = 0x42,
cmdWait = 0x7C,
cmdResume = 0x7F
};
-
- MachineControl (Port &port,
- float MMCVersion,
- CommandSignature &cs,
- ResponseSignature &rs);
- Port &port() { return _port; }
-
- void set_device_id (byte id);
- byte device_id () const { return _device_id; }
+ MachineControl ();
+
+ void set_ports (MIDI::Port* input, MIDI::Port* output);
+
+ Port* input_port() { return _input_port; }
+ Port* output_port() { return _output_port; }
+
+ void set_receive_device_id (byte id);
+ void set_send_device_id (byte id);
+ byte receive_device_id () const { return _receive_device_id; }
+ byte send_device_id () const { return _send_device_id; }
+ void enable_send (bool);
+ bool send_enabled () const { return _enable_send; }
+ void send (MachineControlCommand const &, timestamp_t when);
static bool is_mmc (byte *sysex_buf, size_t len);
/* Signals to connect to if you want to run "callbacks"
when certain MMC commands are received.
*/
-
- sigc::signal<void,MachineControl &> Stop;
- sigc::signal<void,MachineControl &> Play;
- sigc::signal<void,MachineControl &> DeferredPlay;
- sigc::signal<void,MachineControl &> FastForward;
- sigc::signal<void,MachineControl &> Rewind;
- sigc::signal<void,MachineControl &> RecordStrobe;
- sigc::signal<void,MachineControl &> RecordExit;
- sigc::signal<void,MachineControl &> RecordPause;
- sigc::signal<void,MachineControl &> Pause;
- sigc::signal<void,MachineControl &> Eject;
- sigc::signal<void,MachineControl &> Chase;
- sigc::signal<void,MachineControl &> CommandErrorReset;
- sigc::signal<void,MachineControl &> MmcReset;
-
- sigc::signal<void,MachineControl &> JogStart;
- sigc::signal<void,MachineControl &> JogStop;
-
- sigc::signal<void,MachineControl &> Write;
- sigc::signal<void,MachineControl &> MaskedWrite;
- sigc::signal<void,MachineControl &> Read;
- sigc::signal<void,MachineControl &> Update;
- sigc::signal<void,MachineControl &> VariablePlay;
- sigc::signal<void,MachineControl &> Search;
- sigc::signal<void,MachineControl &> AssignSystemMaster;
- sigc::signal<void,MachineControl &> GeneratorCommand;
- sigc::signal<void,MachineControl &> MidiTimeCodeCommand;
- sigc::signal<void,MachineControl &> Move;
- sigc::signal<void,MachineControl &> Add;
- sigc::signal<void,MachineControl &> Subtract;
- sigc::signal<void,MachineControl &> DropFrameAdjust;
- sigc::signal<void,MachineControl &> Procedure;
- sigc::signal<void,MachineControl &> Event;
- sigc::signal<void,MachineControl &> Group;
- sigc::signal<void,MachineControl &> CommandSegment;
- sigc::signal<void,MachineControl &> DeferredVariablePlay;
- sigc::signal<void,MachineControl &> RecordStrobeVariable;
- sigc::signal<void,MachineControl &> Wait;
- sigc::signal<void,MachineControl &> Resume;
+
+ MMCSignal Stop;
+ MMCSignal Play;
+ MMCSignal DeferredPlay;
+ MMCSignal FastForward;
+ MMCSignal Rewind;
+ MMCSignal RecordStrobe;
+ MMCSignal RecordExit;
+ MMCSignal RecordPause;
+ MMCSignal Pause;
+ MMCSignal Eject;
+ MMCSignal Chase;
+ MMCSignal CommandErrorReset;
+ MMCSignal MmcReset;
+ MMCSignal JogStart;
+ MMCSignal JogStop;
+ MMCSignal Write;
+ MMCSignal MaskedWrite;
+ MMCSignal Read;
+ MMCSignal Update;
+ MMCSignal VariablePlay;
+ MMCSignal Search;
+ MMCSignal AssignSystemMaster;
+ MMCSignal GeneratorCommand;
+ MMCSignal MidiTimeCodeCommand;
+ MMCSignal Move;
+ MMCSignal Add;
+ MMCSignal Subtract;
+ MMCSignal DropFrameAdjust;
+ MMCSignal Procedure;
+ MMCSignal Event;
+ MMCSignal Group;
+ MMCSignal CommandSegment;
+ MMCSignal DeferredVariablePlay;
+ MMCSignal RecordStrobeVariable;
+ MMCSignal Wait;
+ MMCSignal Resume;
+
+ PBD::Signal0<void> SPPStart;
+ PBD::Signal0<void> SPPContinue;
+ PBD::Signal0<void> SPPStop;
/* The second argument is the shuttle speed, the third is
true if the direction is "forwards", false for "reverse"
*/
-
- sigc::signal<void,MachineControl &,float,bool> Shuttle;
+
+ PBD::Signal3<void,MachineControl&,float,bool> Shuttle;
/* The second argument specifies the desired track record enabled
status.
*/
- sigc::signal<void,MachineControl &,size_t,bool>
+ PBD::Signal3<void,MachineControl &,size_t,bool>
TrackRecordStatusChange;
-
+
+ /* The second argument specifies the desired track record enabled
+ status.
+ */
+
+ PBD::Signal3<void,MachineControl &,size_t,bool>
+ TrackMuteChange;
+
/* The second argument points to a byte array containing
the locate target value in MMC Standard Time Code
format (5 bytes, roughly: hrs/mins/secs/frames/subframes)
*/
- sigc::signal<void,MachineControl &, const byte *> Locate;
+ PBD::Signal2<void,MachineControl &, const byte *> Locate;
/* The second argument is the number of steps to jump */
-
- sigc::signal<void,MachineControl &, int> Step;
-
- protected:
-#define MMC_NTRACKS 48
+ PBD::Signal2<void,MachineControl &, int> Step;
- /* MMC Information fields (think "registers") */
+#define MMC_NTRACKS 48
- CommandSignature commandSignature;
- ResponseSignature responseSignature;
+ /* note: these are not currently in use */
byte updateRate;
byte responseError;
byte commandError;
byte commandErrorLevel;
-
+
byte motionControlTally;
byte velocityTally;
byte stopMode;
byte fixedSpeed;
byte lifterDefeat;
byte controlDisable;
- byte trackMute;
+ byte trackMute[MMC_NTRACKS];
byte failure;
byte selectedTimeCode;
byte shortSelectedTimeCode;
byte resume;
private:
- byte _device_id;
- MIDI::Port &_port;
+ byte _receive_device_id;
+ byte _send_device_id;
+ Port* _input_port;
+ Port* _output_port;
+ bool _enable_send; ///< true if MMC sending is enabled
void process_mmc_message (Parser &p, byte *, size_t len);
-
+ PBD::ScopedConnectionList port_connections; ///< connections to our parser for incoming data
+
int do_masked_write (byte *, size_t len);
int do_locate (byte *, size_t len);
int do_step (byte *, size_t len);
int do_shuttle (byte *, size_t len);
- void write_track_record_ready (byte *, size_t len);
+ void write_track_status (byte *, size_t len, byte reg);
+ void spp_start ();
+ void spp_continue ();
+ void spp_stop ();
+};
+
+/** Class to describe a MIDI machine control command to be sent.
+ * In an ideal world we might use a class hierarchy for this, but objects of this type
+ * have to be allocated off the stack for RT safety.
+ */
+class LIBMIDIPP_API MachineControlCommand
+{
+public:
+ MachineControlCommand () : _command (MachineControl::Command (0)) {}
+ MachineControlCommand (MachineControl::Command);
+ MachineControlCommand (Timecode::Time);
+
+ MIDI::byte* fill_buffer (MachineControl *mmc, MIDI::byte *) const;
+
+private:
+ MachineControl::Command _command;
+ Timecode::Time _time;
};
} // namespace MIDI