/*
- 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
- 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- $Id$
-*/
+ * Copyright (C) 2000-2017 Paul Davis <paul@linuxaudiosystems.com>
+ * Copyright (C) 2009-2010 David Robillard <d@drobilla.net>
+ * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
+ * Copyright (C) 2014-2015 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.
+ */
#include <fcntl.h>
#include <map>
-#include "timecode/time.h"
+#include "temporal/time.h"
+#include "temporal/bbt_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"
#ifndef __INT_MAX__ // 'ssize_t' won't be defined yet
typedef long ssize_t;
using namespace MIDI;
using namespace PBD;
+/**
+ * As libtimecode is linked statically to libmidi++ this
+ * is necessary to pull in all the symbols from libtimecode
+ * so they are exported for other users of libtimecode.
+ */
+double tmp = Timecode::BBT_Time::ticks_per_beat;
+
static std::map<int,string> mmc_cmd_map;
static void build_mmc_cmd_map ()
{
mmc_cmd_map.insert (newpair);
}
-
-MachineControl::MachineControl (Manager* m, jack_client_t* jack)
+MachineControl::MachineControl ()
{
build_mmc_cmd_map ();
_receive_device_id = 0x7f;
_send_device_id = 0x7f;
+}
+
+void
+MachineControl::set_ports (MIDI::Port* ip, MIDI::Port* op)
+{
+ port_connections.drop_connections ();
- _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 = ip;
+ _output_port = op;
_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));
sysex_buf[3] != 0x7) { /* MMC Response */
return false;
}
-
+
return true;
}
cerr << endl;
#endif
- if (msg[1] != 0x7f && msg[1] != _receive_device_id) {
+ if (_receive_device_id != 0x7f && msg[1] != 0x7f && msg[1] != _receive_device_id) {
return;
}
}
#if 0
- cerr << "+++ MMC type "
+ cerr << "+++ MMC type "
<< hex
<< ((int) *mmc_msg)
<< dec
break;
}
- /* increase skiplen to cover the command byte and
+ /* increase skiplen to cover the command byte and
count byte (if it existed).
*/
len -= skiplen;
} while (len > 1); /* skip terminating EOX byte */
-}
+}
int
MachineControl::do_masked_write (MIDI::byte *msg, size_t len)
/* return the number of bytes "consumed" */
int retval = msg[1] + 2; /* bytes following + 2 */
-
+
switch (msg[2]) {
case 0x4f: /* Track Record Ready Status */
write_track_status (&msg[3], len - 3, msg[2]);
bit 4: aux track b
the format of the message (its an MMC Masked Write) is:
-
+
0x41 Command Code
<count> byte count of following data
<name> byte value of the field being written
- <byte #> byte number of target byte in the
+ <byte #> byte number of target byte in the
bitmap being written to
<mask> ones in the mask indicate which bits will be changed
<data> new data for the byte being written
-
+
by the time this code is executing, msg[0] is the
byte number of the target byte. if its zero, we
are writing to a special byte in the standard
special. hence the bits for tracks 1 + 2 are bits
5 and 6 of the first byte of the track
bitmap. so:
-
- change track 1: msg[0] = 0; << first byte of track bitmap
+
+ change track 1: msg[0] = 0; << first byte of track bitmap
msg[1] = 0100000; << binary: bit 5 set
-
+
change track 2: msg[0] = 0; << first byte of track bitmap
msg[1] = 1000000; << binary: bit 6 set
-
+
change track 3: msg[0] = 1; << second byte of track bitmap
msg[1] = 0000001; << binary: bit 0 set
-
+
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.
-
+
so, if msg[0] = 0, msg[1] = 0100000 (binary),
what happens is that base_track = -5, but by the
time we check the correct bit, n = 5, and so the
*/
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;
}
- }
+ }
}
}
} else {
forward = true;
}
-
+
left_shift = (sh & 0x38);
integral = ((sh & 0x7) << left_shift) | (sm >> (7 - left_shift));
fractional = ((sm << left_shift) << 7) | sl;
- shuttle_speed = integral +
+ shuttle_speed = integral +
((float)fractional / (1 << (14 - left_shift)));
Shuttle (*this, shuttle_speed, forward);
* @param c command.
*/
void
-MachineControl::send (MachineControlCommand const & c)
+MachineControl::send (MachineControlCommand const & c, timestamp_t when)
{
if (_output_port == 0 || !_enable_send) {
// cerr << "Not delivering MMC " << _mmc->port() << " - " << session_send_mmc << endl;
MIDI::byte buffer[32];
MIDI::byte* b = c.fill_buffer (this, buffer);
- if (_output_port->midimsg (buffer, b - buffer, 0)) {
+ if (_output_port->midimsg (buffer, b - buffer, when)) {
error << "MMC: cannot send command" << endmsg;
}
}
}
-MIDI::byte *
+MIDI::byte *
MachineControlCommand::fill_buffer (MachineControl* mmc, MIDI::byte* b) const
{
*b++ = 0xf0; // SysEx
if (_command == MachineControl::cmdLocate) {
*b++ = 0x6; // byte count
*b++ = 0x1; // "TARGET" subcommand
- *b++ = _time.hours;
+ *b++ = _time.hours % 24;
*b++ = _time.minutes;
*b++ = _time.seconds;
*b++ = _time.frames;