$Id$
*/
+#include <fcntl.h>
#include <map>
-#include <pbd/error.h>
-#include <midi++/mmc.h>
-#include <midi++/port.h>
-#include <midi++/parser.h>
+#include "timecode/time.h"
+#include "pbd/error.h"
+#include "midi++/mmc.h"
+#include "midi++/port.h"
+#include "midi++/jack_midi_port.h"
+#include "midi++/parser.h"
+#include "midi++/manager.h"
using namespace std;
using namespace MIDI;
+using namespace PBD;
static std::map<int,string> mmc_cmd_map;
static void build_mmc_cmd_map ()
}
-MachineControl::MachineControl (Port &p, float version,
- CommandSignature &csig,
- ResponseSignature &rsig)
-
- : _port (p)
+MachineControl::MachineControl (Manager* m, jack_client_t* jack)
{
- Parser *parser;
-
build_mmc_cmd_map ();
- _device_id = 1;
-
- if ((parser = _port.input()) != 0) {
- parser->mmc.connect
- (mem_fun (*this, &MachineControl::process_mmc_message));
- } else {
- warning << "MMC connected to a non-input port: useless!"
- << endmsg;
- }
+ _receive_device_id = 0x7f;
+ _send_device_id = 0x7f;
+
+ _input_port = m->add_port (new JackMIDIPort ("MMC in", Port::IsInput, jack));
+ _output_port = m->add_port (new JackMIDIPort ("MMC out", Port::IsOutput, jack));
+
+ _input_port->parser()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3));
+ _input_port->parser()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this));
+ _input_port->parser()->contineu.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_continue, this));
+ _input_port->parser()->stop.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_stop, this));
}
void
-MachineControl::set_device_id (byte id)
+MachineControl::set_receive_device_id (byte id)
+{
+ _receive_device_id = id & 0x7f;
+}
+void
+MachineControl::set_send_device_id (byte id)
{
- _device_id = id & 0x7f;
+ _send_device_id = id & 0x7f;
}
bool
MachineControl::is_mmc (byte *sysex_buf, size_t len)
-
{
if (len < 4 || len > 48) {
return false;
}
void
-MachineControl::process_mmc_message (Parser &p, byte *msg, size_t len)
-
+MachineControl::process_mmc_message (Parser &, byte *msg, size_t len)
{
size_t skiplen;
byte *mmc_msg;
*/
#if 0
- cerr << "*** MMC message: len = " << len << "\n\t";
+ cerr << "*** me = " << (int) _receive_device_id << " MMC message: len = " << len << "\n\t";
for (size_t i = 0; i < len; i++) {
cerr << hex << (int) msg[i] << dec << ' ';
}
cerr << endl;
#endif
- if (msg[1] != 0x7f && msg[1] != _device_id) {
+ if (msg[1] != 0x7f && msg[1] != _receive_device_id) {
return;
}
int
MachineControl::do_masked_write (byte *msg, size_t len)
-
{
/* return the number of bytes "consumed" */
switch (msg[2]) {
case 0x4f: /* Track Record Ready Status */
- write_track_record_ready (&msg[3], len - 3);
+ write_track_status (&msg[3], len - 3, msg[2]);
+ break;
+
+ case 0x62: /* track mute */
+ write_track_status (&msg[3], len - 3, msg[2]);
break;
default:
}
void
-MachineControl::write_track_record_ready (byte *msg, size_t len)
-
+MachineControl::write_track_status (byte *msg, size_t /*len*/, byte reg)
{
size_t n;
- size_t base_track;
+ ssize_t base_track;
/* Bits 0-4 of the first byte are for special tracks:
change track 3: msg[0] = 1; << second byte of track bitmap
msg[1] = 0000001; << binary: bit 0 set
- the (msg[0] * 7) - 5 computation is an attempt to
+ the (msg[0] * 8) - 6 computation is an attempt to
extract the value of the first track: ie. the one
that would be indicated by bit 0 being set.
supported number of tracks.
*/
- base_track = (msg[0] * 7) - 5;
+ if (msg[0] == 0) {
+ base_track = -5;
+ } else {
+ base_track = (msg[0] * 8) - 6;
+ }
for (n = 0; n < 7; n++) {
if (msg[1] & (1<<n)) {
bit set.
*/
- if (msg[2] & (1<<n)) {
- trackRecordStatus[base_track+n] = true;
- TrackRecordStatusChange (*this, base_track+n,
- true);
- } else {
- trackRecordStatus[base_track+n] = false;
- TrackRecordStatusChange (*this, base_track+n,
- false);
+ bool val = (msg[2] & (1<<n));
+
+ switch (reg) {
+ case 0x4f:
+ trackRecordStatus[base_track+n] = val;
+ TrackRecordStatusChange (*this, base_track+n, val);
+ break;
+
+ case 0x62:
+ trackMute[base_track+n] = val;
+ TrackMuteChange (*this, base_track+n, val);
+ break;
}
}
}
int
-MachineControl::do_locate (byte *msg, size_t msglen)
-
+MachineControl::do_locate (byte *msg, size_t /*msglen*/)
{
if (msg[2] == 0) {
warning << "MIDI::MMC: locate [I/F] command not supported"
}
int
-MachineControl::do_step (byte *msg, size_t msglen)
+MachineControl::do_step (byte *msg, size_t /*msglen*/)
{
int steps = msg[2] & 0x3f;
}
int
-MachineControl::do_shuttle (byte *msg, size_t msglen)
-
+MachineControl::do_shuttle (byte *msg, size_t /*msglen*/)
{
size_t forward;
byte sh = msg[2];
return 0;
}
+void
+MachineControl::enable_send (bool yn)
+{
+ _enable_send = yn;
+}
+
+/** Send a MMC command to a the MMC port.
+ * @param c command.
+ */
+void
+MachineControl::send (MachineControlCommand const & c)
+{
+ if (_output_port == 0 || !_enable_send) {
+ // cerr << "Not delivering MMC " << _mmc->port() << " - " << session_send_mmc << endl;
+ return;
+ }
+
+ MIDI::byte buffer[32];
+ MIDI::byte* b = c.fill_buffer (this, buffer);
+
+ if (_output_port->midimsg (buffer, b - buffer, 0)) {
+ error << "MMC: cannot send command" << endmsg;
+ }
+}
+
+void
+MachineControl::spp_start ()
+{
+ SPPStart (); /* EMIT SIGNAL */
+}
+
+void
+MachineControl::spp_continue ()
+{
+ SPPContinue (); /* EMIT SIGNAL */
+}
+
+void
+MachineControl::spp_stop ()
+{
+ SPPStop (); /* EMIT SIGNAL */
+}
+
+MachineControlCommand::MachineControlCommand (MachineControl::Command c)
+ : _command (c)
+{
+
+}
+
+MachineControlCommand::MachineControlCommand (Timecode::Time t)
+ : _command (MachineControl::cmdLocate)
+ , _time (t)
+{
+
+}
+
+MIDI::byte *
+MachineControlCommand::fill_buffer (MachineControl* mmc, MIDI::byte* b) const
+{
+ *b++ = 0xf0; // SysEx
+ *b++ = 0x7f; // Real-time SysEx ID for MMC
+ *b++ = mmc->send_device_id();
+ *b++ = 0x6; // MMC command
+
+ *b++ = _command;
+
+ if (_command == MachineControl::cmdLocate) {
+ *b++ = 0x6; // byte count
+ *b++ = 0x1; // "TARGET" subcommand
+ *b++ = _time.hours;
+ *b++ = _time.minutes;
+ *b++ = _time.seconds;
+ *b++ = _time.frames;
+ *b++ = _time.subframes;
+ }
+
+ *b++ = 0xf7;
+
+ return b;
+}
+