ardour/libs/midi++2/midi++/mmc.h

310 lines
7.5 KiB
C++

/*
* Copyright (C) 2000-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2005-2006 Taybin Rutkin <taybin@taybin.com>
* Copyright (C) 2009-2010 David Robillard <d@drobilla.net>
* Copyright (C) 2010-2012 Carl Hetherington <carl@carlh.net>
* Copyright (C) 2015-2019 Robin Gareus <robin@gareus.org>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __midipp_mmc_h_h__
#define __midipp_mmc_h_h__
#include "temporal/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 to handle incoming and outgoing MIDI machine control messages */
class LIBMIDIPP_API MachineControl
{
public:
typedef PBD::Signal1<void,MachineControl&> MMCSignal;
enum Command {
cmdStop = 0x1,
cmdPlay = 0x2,
cmdDeferredPlay = 0x3,
cmdFastForward = 0x4,
cmdRewind = 0x5,
cmdRecordStrobe = 0x6,
cmdRecordExit = 0x7,
cmdRecordPause = 0x8,
cmdPause = 0x9,
cmdEject = 0xA,
cmdChase = 0xB,
cmdCommandErrorReset = 0xC,
cmdMmcReset = 0xD,
cmdIllegalMackieJogStart = 0x20,
cmdIllegalMackieJogStop = 0x21,
cmdWrite = 0x40,
cmdMaskedWrite = 0x41,
cmdRead = 0x42,
cmdUpdate = 0x43,
cmdLocate = 0x44,
cmdVariablePlay = 0x45,
cmdSearch = 0x46,
cmdShuttle = 0x47,
cmdStep = 0x48,
cmdAssignSystemMaster = 0x49,
cmdGeneratorCommand = 0x4A,
cmdMtcCommand = 0x4B,
cmdMove = 0x4C,
cmdAdd = 0x4D,
cmdSubtract = 0x4E,
cmdDropFrameAdjust = 0x4F,
cmdProcedure = 0x50,
cmdEvent = 0x51,
cmdGroup = 0x52,
cmdCommandSegment = 0x53,
cmdDeferredVariablePlay = 0x54,
cmdRecordStrobeVariable = 0x55,
cmdWait = 0x7C,
cmdResume = 0x7F
};
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.
*/
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"
*/
PBD::Signal3<void,MachineControl&,float,bool> Shuttle;
/* The second argument specifies the desired track record enabled
status.
*/
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)
*/
PBD::Signal2<void,MachineControl &, const byte *> Locate;
/* The second argument is the number of steps to jump */
PBD::Signal2<void,MachineControl &, int> Step;
#define MMC_NTRACKS 48
/* note: these are not currently in use */
byte updateRate;
byte responseError;
byte commandError;
byte commandErrorLevel;
byte motionControlTally;
byte velocityTally;
byte stopMode;
byte fastMode;
byte recordMode;
byte recordStatus;
bool trackRecordStatus[MMC_NTRACKS];
bool trackRecordReady[MMC_NTRACKS];
byte globalMonitor;
byte recordMonitor;
byte trackSyncMonitor;
byte trackInputMonitor;
byte stepLength;
byte playSpeedReference;
byte fixedSpeed;
byte lifterDefeat;
byte controlDisable;
byte trackMute[MMC_NTRACKS];
byte failure;
byte selectedTimeCode;
byte shortSelectedTimeCode;
byte timeStandard;
byte selectedTimeCodeSource;
byte selectedTimeCodeUserbits;
byte selectedMasterCode;
byte requestedOffset;
byte actualOffset;
byte lockDeviation;
byte shortSelectedMasterCode;
byte shortRequestedOffset;
byte shortActualOffset;
byte shortLockDeviation;
byte resolvedPlayMode;
byte chaseMode;
byte generatorTimeCode;
byte shortGeneratorTimeCode;
byte generatorCommandTally;
byte generatorSetUp;
byte generatorUserbits;
byte vitcInsertEnable;
byte midiTimeCodeInput;
byte shortMidiTimeCodeInput;
byte midiTimeCodeCommandTally;
byte midiTimeCodeSetUp;
byte gp0;
byte gp1;
byte gp2;
byte gp3;
byte gp4;
byte gp5;
byte gp6;
byte gp7;
byte shortGp0;
byte shortGp1;
byte shortGp2;
byte shortGp3;
byte shortGp4;
byte shortGp5;
byte shortGp6;
byte shortGp7;
byte procedureResponse;
byte eventResponse;
byte responseSegment;
byte wait;
byte resume;
private:
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_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
#endif /* __midipp_mmc_h_h__ */