a) dynamically loadable control surface support
b) move tranzport and generic midi into separate dirs under "surfaces" git-svn-id: svn://localhost/trunk/ardour2@442 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
51
libs/surfaces/generic_midi/SConscript
Normal file
51
libs/surfaces/generic_midi/SConscript
Normal file
@@ -0,0 +1,51 @@
|
||||
# -*- python -*-
|
||||
|
||||
import os
|
||||
import glob
|
||||
|
||||
Import('env final_prefix install_prefix final_config_prefix libraries i18n')
|
||||
|
||||
genericmidi = env.Copy()
|
||||
|
||||
#
|
||||
# this defines the version number of libardour_genericmidi
|
||||
#
|
||||
|
||||
domain = 'ardour_genericmidi'
|
||||
|
||||
genericmidi.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
|
||||
genericmidi.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
|
||||
genericmidi.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
|
||||
genericmidi.Append(PACKAGE = domain)
|
||||
genericmidi.Append(POTFILE = domain + '.pot')
|
||||
|
||||
genericmidi_files=Split("""
|
||||
interface.cc
|
||||
generic_midi_control_protocol.cc
|
||||
""")
|
||||
|
||||
genericmidi.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
|
||||
genericmidi.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
|
||||
genericmidi.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
|
||||
genericmidi.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
|
||||
|
||||
genericmidi.Merge ([
|
||||
libraries['usb'],
|
||||
libraries['ardour'],
|
||||
libraries['sigc2'],
|
||||
libraries['pbd3'],
|
||||
libraries['midi++2'],
|
||||
libraries['xml']
|
||||
])
|
||||
|
||||
libardour_genericmidi = genericmidi.SharedLibrary('ardour_genericmidi', genericmidi_files)
|
||||
|
||||
Default(libardour_genericmidi)
|
||||
|
||||
if env['NLS']:
|
||||
i18n (genericmidi, genericmidi_files, env)
|
||||
|
||||
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||
[ 'SConscript', 'i18n.h', 'gettext.h' ] +
|
||||
genericmidi_files +
|
||||
glob.glob('po/*.po') + glob.glob('*.h')))
|
||||
55
libs/surfaces/generic_midi/generic_midi_control_protocol.cc
Normal file
55
libs/surfaces/generic_midi/generic_midi_control_protocol.cc
Normal file
@@ -0,0 +1,55 @@
|
||||
#include <ardour/route.h>
|
||||
#include <ardour/session.h>
|
||||
|
||||
#include "generic_midi_control_protocol.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
|
||||
: ControlProtocol (s, _("GenericMIDI"))
|
||||
{
|
||||
_port = 0;
|
||||
}
|
||||
|
||||
GenericMidiControlProtocol::~GenericMidiControlProtocol ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
GenericMidiControlProtocol::set_port (MIDI::Port* p)
|
||||
{
|
||||
_port = p;
|
||||
}
|
||||
|
||||
void
|
||||
GenericMidiControlProtocol::send_route_feedback (list<Route*>& routes)
|
||||
{
|
||||
if (_port != 0) {
|
||||
|
||||
const int32_t bufsize = 16 * 1024;
|
||||
int32_t bsize = bufsize;
|
||||
MIDI::byte* buf = new MIDI::byte[bufsize];
|
||||
MIDI::byte* end = buf;
|
||||
|
||||
for (list<Route*>::iterator r = routes.begin(); r != routes.end(); ++r) {
|
||||
end = (*r)->write_midi_feedback (end, bsize);
|
||||
}
|
||||
|
||||
if (end == buf) {
|
||||
delete [] buf;
|
||||
return;
|
||||
}
|
||||
|
||||
session.deliver_midi (_port, buf, (int32_t) (end - buf));
|
||||
//cerr << "MIDI feedback: wrote " << (int32_t) (end - buf) << " to midi port\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GenericMidiControlProtocol::active() const
|
||||
{
|
||||
return _port && send();
|
||||
}
|
||||
|
||||
31
libs/surfaces/generic_midi/generic_midi_control_protocol.h
Normal file
31
libs/surfaces/generic_midi/generic_midi_control_protocol.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef ardour_generic_midi_control_protocol_h
|
||||
#define ardour_generic_midi_control_protocol_h
|
||||
|
||||
#include <ardour/control_protocol.h>
|
||||
|
||||
namespace MIDI {
|
||||
class Port;
|
||||
}
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class GenericMidiControlProtocol : public ControlProtocol {
|
||||
public:
|
||||
GenericMidiControlProtocol (Session&);
|
||||
virtual ~GenericMidiControlProtocol();
|
||||
|
||||
bool active() const;
|
||||
|
||||
void set_port (MIDI::Port*);
|
||||
MIDI::Port* port () const { return _port; }
|
||||
|
||||
void send_route_feedback (std::list<Route*>&);
|
||||
|
||||
private:
|
||||
void route_feedback (ARDOUR::Route&, bool);
|
||||
MIDI::Port* _port;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // ardour_generic_midi_control_protocol_h
|
||||
34
libs/surfaces/generic_midi/interface.cc
Normal file
34
libs/surfaces/generic_midi/interface.cc
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <ardour/control_protocol.h>
|
||||
|
||||
#include "generic_midi_control_protocol.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
ControlProtocol*
|
||||
new_generic_midi_protocol (ControlProtocolDescriptor* descriptor, Session* s)
|
||||
{
|
||||
return new GenericMidiControlProtocol (*s);
|
||||
}
|
||||
|
||||
void
|
||||
delete_generic_midi_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
|
||||
{
|
||||
delete cp;
|
||||
}
|
||||
|
||||
static ControlProtocolDescriptor generic_midi_descriptor = {
|
||||
name : "Generic MIDI",
|
||||
ptr : 0,
|
||||
module : 0,
|
||||
initialize : new_generic_midi_protocol,
|
||||
destroy : delete_generic_midi_protocol
|
||||
};
|
||||
|
||||
|
||||
extern "C" {
|
||||
ControlProtocolDescriptor*
|
||||
protocol_descriptor () {
|
||||
return &generic_midi_descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
52
libs/surfaces/tranzport/SConscript
Normal file
52
libs/surfaces/tranzport/SConscript
Normal file
@@ -0,0 +1,52 @@
|
||||
# -*- python -*-
|
||||
|
||||
import os
|
||||
import glob
|
||||
|
||||
Import('env final_prefix install_prefix final_config_prefix libraries i18n')
|
||||
|
||||
tranzport = env.Copy()
|
||||
|
||||
#
|
||||
# this defines the version number of libardour_tranzport
|
||||
#
|
||||
|
||||
domain = 'ardour_tranzport'
|
||||
|
||||
tranzport.Append(DOMAIN = domain, MAJOR = 1, MINOR = 0, MICRO = 0)
|
||||
tranzport.Append(CXXFLAGS = "-DPACKAGE=\\\"" + domain + "\\\"")
|
||||
tranzport.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
|
||||
tranzport.Append(PACKAGE = domain)
|
||||
tranzport.Append(POTFILE = domain + '.pot')
|
||||
|
||||
tranzport_files=Split("""
|
||||
interface.cc
|
||||
tranzport_control_protocol.cc
|
||||
""")
|
||||
|
||||
tranzport.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE")
|
||||
tranzport.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"")
|
||||
tranzport.Append(CXXFLAGS="-DCONFIG_DIR=\\\""+final_config_prefix+"\\\"")
|
||||
tranzport.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"")
|
||||
|
||||
tranzport.Append(CPPPATH=libraries['ardour'].get ('CPPPATH', []))
|
||||
tranzport.Append(CPPPATH=libraries['sigc2'].get ('CPPPATH', []))
|
||||
tranzport.Append(CPPPATH=libraries['pbd3'].get ('CPPPATH', []))
|
||||
tranzport.Append(CPPPATH=libraries['midi++2'].get ('CPPPATH', []))
|
||||
|
||||
tranzport.Merge ([
|
||||
libraries['xml'],
|
||||
libraries['usb']
|
||||
])
|
||||
|
||||
libardour_tranzport = tranzport.SharedLibrary('ardour_tranzport', tranzport_files)
|
||||
|
||||
Default(libardour_tranzport)
|
||||
|
||||
if env['NLS']:
|
||||
i18n (tranzport, tranzport_files, env)
|
||||
|
||||
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||
[ 'SConscript', 'i18n.h', 'gettext.h' ] +
|
||||
tranzport_files +
|
||||
glob.glob('po/*.po') + glob.glob('*.h')))
|
||||
34
libs/surfaces/tranzport/interface.cc
Normal file
34
libs/surfaces/tranzport/interface.cc
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <ardour/control_protocol.h>
|
||||
|
||||
#include "tranzport_control_protocol.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
|
||||
ControlProtocol*
|
||||
new_tranzport_protocol (ControlProtocolDescriptor* descriptor, Session* s)
|
||||
{
|
||||
return new TranzportControlProtocol (*s);
|
||||
}
|
||||
|
||||
void
|
||||
delete_tranzport_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
|
||||
{
|
||||
delete cp;
|
||||
}
|
||||
|
||||
static ControlProtocolDescriptor tranzport_descriptor = {
|
||||
name : "Tranzport",
|
||||
ptr : 0,
|
||||
module : 0,
|
||||
initialize : new_tranzport_protocol,
|
||||
destroy : delete_tranzport_protocol
|
||||
};
|
||||
|
||||
|
||||
extern "C" {
|
||||
ControlProtocolDescriptor*
|
||||
protocol_descriptor () {
|
||||
return &tranzport_descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
789
libs/surfaces/tranzport/tranzport_control_protocol.cc
Normal file
789
libs/surfaces/tranzport/tranzport_control_protocol.cc
Normal file
@@ -0,0 +1,789 @@
|
||||
#include <iostream>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <pbd/pthread_utils.h>
|
||||
|
||||
#include <ardour/route.h>
|
||||
#include <ardour/session.h>
|
||||
|
||||
#include "tranzport_control_protocol.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace std;
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
TranzportControlProtocol::TranzportControlProtocol (Session& s)
|
||||
: ControlProtocol (s, _("Tranzport"))
|
||||
{
|
||||
timeout = 60000;
|
||||
buttonmask = 0;
|
||||
_datawheel = 0;
|
||||
_device_status = STATUS_OFFLINE;
|
||||
udev = 0;
|
||||
current_route = 0;
|
||||
current_track_id = 0;
|
||||
last_where = max_frames;
|
||||
memset (next_screen, ' ', sizeof (next_screen));
|
||||
memset (current_screen, ' ', sizeof (current_screen));
|
||||
}
|
||||
|
||||
TranzportControlProtocol::~TranzportControlProtocol ()
|
||||
{
|
||||
if (udev) {
|
||||
lcd_clear ();
|
||||
pthread_cancel_one (thread);
|
||||
close ();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
TranzportControlProtocol::init ()
|
||||
{
|
||||
if (open ()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* outbound thread */
|
||||
|
||||
init_thread ();
|
||||
|
||||
/* inbound thread */
|
||||
|
||||
pthread_create_and_store (X_("tranzport monitor"), &thread, 0, _thread_work, this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
TranzportControlProtocol::active() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::send_route_feedback (list<Route*>& routes)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::send_global_feedback ()
|
||||
{
|
||||
show_transport_time ();
|
||||
|
||||
flush_lcd ();
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::show_transport_time ()
|
||||
{
|
||||
jack_nframes_t where = session.transport_frame();
|
||||
|
||||
if (where != last_where) {
|
||||
|
||||
uint8_t label[12];
|
||||
SMPTE_Time smpte;
|
||||
char* ptr = (char *) label;
|
||||
|
||||
session.smpte_time (where, smpte);
|
||||
memset (label, ' ', sizeof (label));
|
||||
|
||||
if (smpte.negative) {
|
||||
sprintf (ptr, "-%02ld:", smpte.hours);
|
||||
} else {
|
||||
sprintf (ptr, " %02ld:", smpte.hours);
|
||||
}
|
||||
ptr += 4;
|
||||
|
||||
sprintf (ptr, "%02ld:", smpte.minutes);
|
||||
ptr += 3;
|
||||
|
||||
sprintf (ptr, "%02ld:", smpte.seconds);
|
||||
ptr += 3;
|
||||
|
||||
sprintf (ptr, "%02ld", smpte.frames);
|
||||
ptr += 2;
|
||||
|
||||
write_clock (label);
|
||||
|
||||
last_where = where;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::write_clock (const uint8_t* label)
|
||||
{
|
||||
memcpy (&next_screen[1][8], &label[0]);
|
||||
memcpy (&next_screen[1][12], &label[4]);
|
||||
memcpy (&next_screen[1][16], &label[8]);
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::flush_lcd ()
|
||||
{
|
||||
if (memcmp (&next_screen[0][0], ¤t_screen[0][0], 4)) {
|
||||
lcd_write (0, &next_screen[0][0]);
|
||||
}
|
||||
if (memcmp (&next_screen[0][4], ¤t_screen[0][4], 4)) {
|
||||
lcd_write (1, &next_screen[0][0]);
|
||||
}
|
||||
if (memcmp (&next_screen[0][8], ¤t_screen[0][8], 4)) {
|
||||
lcd_write (2, &next_screen[0][0]);
|
||||
}
|
||||
if (memcmp (&next_screen[0][12], ¤t_screen[0][12], 4)) {
|
||||
lcd_write (3, &next_screen[0][0]);
|
||||
}
|
||||
if (memcmp (&next_screen[0][16], ¤t_screen[0][16], 4)) {
|
||||
lcd_write (4, &next_screen[0][0]);
|
||||
}
|
||||
if (memcmp (&next_screen[1][0], ¤t_screen[1][0], 4)) {
|
||||
lcd_write (5, &next_screen[0][0]);
|
||||
}
|
||||
if (memcmp (&next_screen[1][4], ¤t_screen[1][4], 4)) {
|
||||
lcd_write (6, &next_screen[0][0]);
|
||||
}
|
||||
if (memcmp (&next_screen[1][8], ¤t_screen[1][8], 4)) {
|
||||
lcd_write (7, &next_screen[0][0]);
|
||||
}
|
||||
if (memcmp (&next_screen[1][12], ¤t_screen[1][12], 4)) {
|
||||
lcd_write (8, &next_screen[0][0]);
|
||||
}
|
||||
if (memcmp (&next_screen[1][16], ¤t_screen[1][16], 4)) {
|
||||
lcd_write (9, &next_screen[0][0]);
|
||||
}
|
||||
|
||||
memcpy (current_screen, next_screen, sizeof (current_screen));
|
||||
}
|
||||
|
||||
void*
|
||||
TranzportControlProtocol::_thread_work (void* arg)
|
||||
{
|
||||
return static_cast<TranzportControlProtocol*>(arg)->thread_work ();
|
||||
}
|
||||
|
||||
void*
|
||||
TranzportControlProtocol::thread_work ()
|
||||
{
|
||||
PBD::ThreadCreated (pthread_self(), X_("tranzport monitor"));
|
||||
|
||||
while (true) {
|
||||
if (read()) {
|
||||
return 0;
|
||||
}
|
||||
switch (_device_status) {
|
||||
case STATUS_OFFLINE:
|
||||
cerr << "offline\n";
|
||||
break;
|
||||
case STATUS_ONLINE:
|
||||
cerr << "online\n";
|
||||
break;
|
||||
default:
|
||||
cerr << "unknown status\n";
|
||||
break;
|
||||
}
|
||||
|
||||
if (_device_status == STATUS_ONLINE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lcd_write (0, " ");
|
||||
lcd_write (1, "WELC");
|
||||
lcd_write (2, "OME ");
|
||||
lcd_write (3, "TO ");
|
||||
lcd_write (4, " ");
|
||||
lcd_write (5, " ");
|
||||
lcd_write (6, " ");
|
||||
lcd_write (7, "ARDO");
|
||||
lcd_write (8, "UR ");
|
||||
lcd_write (9, " ");
|
||||
|
||||
while (true) {
|
||||
if (read ()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
TranzportControlProtocol::open ()
|
||||
{
|
||||
struct usb_bus *bus;
|
||||
struct usb_device *dev;
|
||||
|
||||
usb_init();
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
for (bus = usb_busses; bus; bus = bus->next) {
|
||||
|
||||
for(dev = bus->devices; dev; dev = dev->next) {
|
||||
if (dev->descriptor.idVendor != VENDORID)
|
||||
continue;
|
||||
if (dev->descriptor.idProduct != PRODUCTID)
|
||||
continue;
|
||||
return open_core (dev);
|
||||
}
|
||||
}
|
||||
|
||||
error << _("Tranzport: no device detected") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
TranzportControlProtocol::open_core (struct usb_device* dev)
|
||||
{
|
||||
if (!(udev = usb_open (dev))) {
|
||||
error << _("Tranzport: cannot open USB transport") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (usb_claim_interface (udev, 0) < 0) {
|
||||
error << _("Tranzport: cannot claim USB interface") << endmsg;
|
||||
usb_close (udev);
|
||||
udev = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
TranzportControlProtocol::close ()
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (udev == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (usb_release_interface (udev, 0) < 0) {
|
||||
error << _("Tranzport: cannot release interface") << endmsg;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (usb_close (udev)) {
|
||||
error << _("Tranzport: cannot close device") << endmsg;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
TranzportControlProtocol::write (uint8_t* cmd, uint32_t timeout_override)
|
||||
{
|
||||
int val;
|
||||
struct timeval tv1, tv2, tv_diff;
|
||||
|
||||
gettimeofday (&tv1, 0);
|
||||
val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
|
||||
gettimeofday (&tv2, 0);
|
||||
if (val < 0)
|
||||
return val;
|
||||
if (val != 8)
|
||||
return -1;
|
||||
timersub (&tv2, &tv1, &tv_diff);
|
||||
cerr << "time to write command = " << tv_diff.tv_sec << '.' << tv_diff.tv_usec << endl;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::lcd_clear ()
|
||||
{
|
||||
lcd_write (0, " ");
|
||||
lcd_write (1, " ");
|
||||
lcd_write (2, " ");
|
||||
lcd_write (3, " ");
|
||||
lcd_write (4, " ");
|
||||
lcd_write (5, " ");
|
||||
lcd_write (6, " ");
|
||||
lcd_write (7, " ");
|
||||
lcd_write (8, " ");
|
||||
lcd_write (9, " ");
|
||||
}
|
||||
|
||||
int
|
||||
TranzportControlProtocol::lcd_write (uint8_t cell, const char* text)
|
||||
{
|
||||
uint8_t cmd[8];
|
||||
|
||||
if (cell > 9) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x01;
|
||||
cmd[2] = cell;
|
||||
cmd[3] = text[0];
|
||||
cmd[4] = text[1];
|
||||
cmd[5] = text[2];
|
||||
cmd[6] = text[3];
|
||||
cmd[7] = 0x00;
|
||||
|
||||
int index = cell%4;
|
||||
cell /= 4;
|
||||
|
||||
current_screen[cell][index] = text[0];
|
||||
current_screen[cell][index+1] = text[1];
|
||||
current_screen[cell][index+2] = text[2];
|
||||
current_screen[cell][index+3] = text[3];
|
||||
|
||||
return write (cmd, 500);
|
||||
}
|
||||
|
||||
int
|
||||
TranzportControlProtocol::light_on (LightID light)
|
||||
{
|
||||
uint8_t cmd[8];
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x00;
|
||||
cmd[2] = light;
|
||||
cmd[3] = 0x01;
|
||||
cmd[4] = 0x00;
|
||||
cmd[5] = 0x00;
|
||||
cmd[6] = 0x00;
|
||||
cmd[7] = 0x00;
|
||||
|
||||
return write (cmd, 500);
|
||||
}
|
||||
|
||||
int
|
||||
TranzportControlProtocol::light_off (LightID light)
|
||||
{
|
||||
uint8_t cmd[8];
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x00;
|
||||
cmd[2] = light;
|
||||
cmd[3] = 0x00;
|
||||
cmd[4] = 0x00;
|
||||
cmd[5] = 0x00;
|
||||
cmd[6] = 0x00;
|
||||
cmd[7] = 0x00;
|
||||
|
||||
return write (cmd, 500);
|
||||
}
|
||||
|
||||
int
|
||||
TranzportControlProtocol::read (uint32_t timeout_override)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
int val;
|
||||
|
||||
memset(buf, 0, 8);
|
||||
again:
|
||||
val = usb_interrupt_read(udev, READ_ENDPOINT, (char*) buf, 8, timeout_override ? timeout_override : timeout);
|
||||
if (val < 0) {
|
||||
return val;
|
||||
}
|
||||
if (val != 8) {
|
||||
if (val == 0) {
|
||||
goto again;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* printf("read: %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);*/
|
||||
|
||||
uint32_t this_button_mask;
|
||||
uint32_t button_changes;
|
||||
|
||||
_device_status = buf[1];
|
||||
this_button_mask = 0;
|
||||
this_button_mask |= buf[2] << 24;
|
||||
this_button_mask |= buf[3] << 16;
|
||||
this_button_mask |= buf[4] << 8;
|
||||
this_button_mask |= buf[5];
|
||||
_datawheel = buf[6];
|
||||
|
||||
button_changes = (this_button_mask ^ buttonmask);
|
||||
buttonmask = this_button_mask;
|
||||
|
||||
if (button_changes & ButtonBattery) {
|
||||
if (buttonmask & ButtonBattery) {
|
||||
button_event_battery_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_battery_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonBacklight) {
|
||||
if (buttonmask & ButtonBacklight) {
|
||||
button_event_backlight_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_backlight_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonTrackLeft) {
|
||||
if (buttonmask & ButtonTrackLeft) {
|
||||
button_event_trackleft_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_trackleft_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonTrackRight) {
|
||||
if (buttonmask & ButtonTrackRight) {
|
||||
button_event_trackright_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_trackright_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonTrackRec) {
|
||||
if (buttonmask & ButtonTrackRec) {
|
||||
button_event_trackrec_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_trackrec_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonTrackMute) {
|
||||
if (buttonmask & ButtonTrackMute) {
|
||||
button_event_trackmute_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_trackmute_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonTrackSolo) {
|
||||
if (buttonmask & ButtonTrackSolo) {
|
||||
button_event_tracksolo_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_tracksolo_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonUndo) {
|
||||
if (buttonmask & ButtonUndo) {
|
||||
button_event_undo_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_undo_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonIn) {
|
||||
if (buttonmask & ButtonIn) {
|
||||
button_event_in_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_in_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonOut) {
|
||||
if (buttonmask & ButtonOut) {
|
||||
button_event_out_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_out_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonPunch) {
|
||||
if (buttonmask & ButtonPunch) {
|
||||
button_event_punch_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_punch_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonLoop) {
|
||||
if (buttonmask & ButtonLoop) {
|
||||
button_event_loop_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_loop_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonPrev) {
|
||||
if (buttonmask & ButtonPrev) {
|
||||
button_event_prev_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_prev_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonAdd) {
|
||||
if (buttonmask & ButtonAdd) {
|
||||
button_event_add_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_add_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonNext) {
|
||||
if (buttonmask & ButtonNext) {
|
||||
button_event_next_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_next_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonRewind) {
|
||||
if (buttonmask & ButtonRewind) {
|
||||
button_event_rewind_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_rewind_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonFastForward) {
|
||||
if (buttonmask & ButtonFastForward) {
|
||||
button_event_fastforward_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_fastforward_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonStop) {
|
||||
if (buttonmask & ButtonStop) {
|
||||
button_event_stop_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_stop_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonPlay) {
|
||||
if (buttonmask & ButtonPlay) {
|
||||
button_event_play_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_play_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
if (button_changes & ButtonRecord) {
|
||||
if (buttonmask & ButtonRecord) {
|
||||
button_event_record_press (buttonmask&ButtonShift);
|
||||
} else {
|
||||
button_event_record_release (buttonmask&ButtonShift);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::show_current_track ()
|
||||
{
|
||||
current_route = session.route_by_remote_id (current_track_id);
|
||||
|
||||
if (current_route == 0) {
|
||||
char buf[5];
|
||||
lcd_clear ();
|
||||
lcd_write (0, "NO T");
|
||||
lcd_write (1, "RACK");
|
||||
lcd_write (2, " ID ");
|
||||
snprintf (buf, sizeof (buf), "%4d", current_track_id);
|
||||
lcd_write (3, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
string name = current_route->name();
|
||||
|
||||
lcd_write (0, name.substr (0, 4).c_str());
|
||||
lcd_write (1, name.substr (4, 4).c_str());
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_battery_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_battery_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_backlight_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_backlight_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_trackleft_press (bool shifted)
|
||||
{
|
||||
if (current_track_id == 0) {
|
||||
current_track_id = session.nroutes() - 1;
|
||||
} else {
|
||||
current_track_id--;
|
||||
}
|
||||
|
||||
show_current_track ();
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_trackleft_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_trackright_press (bool shifted)
|
||||
{
|
||||
if (current_track_id == session.nroutes()) {
|
||||
current_track_id = 0;
|
||||
} else {
|
||||
current_track_id++;
|
||||
}
|
||||
|
||||
show_current_track ();
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_trackright_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_trackrec_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_trackrec_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_trackmute_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_trackmute_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_tracksolo_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_tracksolo_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_undo_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_undo_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_in_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_in_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_out_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_out_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_punch_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_punch_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_loop_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_loop_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_prev_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_prev_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_add_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_add_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_next_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_next_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_rewind_press (bool shifted)
|
||||
{
|
||||
session.request_transport_speed (-2.0f);
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_rewind_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_fastforward_press (bool shifted)
|
||||
{
|
||||
session.request_transport_speed (2.0f);
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_fastforward_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_stop_press (bool shifted)
|
||||
{
|
||||
session.request_transport_speed (0.0);
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_stop_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_play_press (bool shifted)
|
||||
{
|
||||
session.request_transport_speed (1.0);
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_play_release (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_record_press (bool shifted)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TranzportControlProtocol::button_event_record_release (bool shifted)
|
||||
{
|
||||
}
|
||||
147
libs/surfaces/tranzport/tranzport_control_protocol.h
Normal file
147
libs/surfaces/tranzport/tranzport_control_protocol.h
Normal file
@@ -0,0 +1,147 @@
|
||||
#ifndef ardour_tranzport_control_protocol_h
|
||||
#define ardour_tranzport_control_protocol_h
|
||||
|
||||
#include <pthread.h>
|
||||
#include <usb.h>
|
||||
#include <ardour/control_protocol.h>
|
||||
#include <ardour/types.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class TranzportControlProtocol : public ControlProtocol {
|
||||
public:
|
||||
TranzportControlProtocol (Session&);
|
||||
virtual ~TranzportControlProtocol();
|
||||
|
||||
int init ();
|
||||
bool active() const;
|
||||
|
||||
void send_route_feedback (std::list<Route*>&);
|
||||
void send_global_feedback ();
|
||||
|
||||
private:
|
||||
static const int VENDORID = 0x165b;
|
||||
static const int PRODUCTID = 0x8101;
|
||||
static const int READ_ENDPOINT = 0x81;
|
||||
static const int WRITE_ENDPOINT = 0x02;
|
||||
const static int STATUS_OFFLINE = 0xff;
|
||||
const static int STATUS_ONLINE = 0x01;
|
||||
|
||||
enum LightID {
|
||||
LightRecord = 0,
|
||||
LightTrackrec,
|
||||
LightTrackmute,
|
||||
LightTracksolo,
|
||||
LightAnysolo,
|
||||
LightLoop,
|
||||
LightPunch
|
||||
};
|
||||
|
||||
enum ButtonID {
|
||||
ButtonBattery = 0x00004000,
|
||||
ButtonBacklight = 0x00008000,
|
||||
ButtonTrackLeft = 0x04000000,
|
||||
ButtonTrackRight = 0x40000000,
|
||||
ButtonTrackRec = 0x00040000,
|
||||
ButtonTrackMute = 0x00400000,
|
||||
ButtonTrackSolo = 0x00000400,
|
||||
ButtonUndo = 0x80000000,
|
||||
ButtonIn = 0x02000000,
|
||||
ButtonOut = 0x20000000,
|
||||
ButtonPunch = 0x00800000,
|
||||
ButtonLoop = 0x00080000,
|
||||
ButtonPrev = 0x00020000,
|
||||
ButtonAdd = 0x00200000,
|
||||
ButtonNext = 0x00000200,
|
||||
ButtonRewind = 0x01000000,
|
||||
ButtonFastForward = 0x10000000,
|
||||
ButtonStop = 0x00010000,
|
||||
ButtonPlay = 0x00100000,
|
||||
ButtonRecord = 0x00000100,
|
||||
ButtonShift = 0x08000000
|
||||
};
|
||||
|
||||
pthread_t thread;
|
||||
uint32_t buttonmask;
|
||||
uint32_t timeout;
|
||||
uint8_t _datawheel;
|
||||
uint8_t _device_status;
|
||||
usb_dev_handle* udev;
|
||||
Route* current_route;
|
||||
uint32_t current_track_id;
|
||||
uint8_t lcd_screen[2][20];
|
||||
|
||||
bool last_negative;
|
||||
uint32_t last_hrs;
|
||||
uint32_t last_mins;
|
||||
uint32_t last_secs;
|
||||
uint32_t last_frames;
|
||||
jack_nframes_t last_where;
|
||||
|
||||
int open ();
|
||||
int read (uint32_t timeout_override = 0);
|
||||
int write (uint8_t* cmd, uint32_t timeout_override = 0);
|
||||
int close ();
|
||||
|
||||
int open_core (struct usb_device*);
|
||||
|
||||
void lcd_clear ();
|
||||
int lcd_write (uint8_t cell, const char *text);
|
||||
|
||||
int light_on (LightID);
|
||||
int light_off (LightID);
|
||||
|
||||
void flush_lcd ();
|
||||
void write_clock (const uint8_t* label);
|
||||
|
||||
void show_current_track ();
|
||||
void show_transport_time ();
|
||||
|
||||
static void* _thread_work (void* arg);
|
||||
void* thread_work ();
|
||||
|
||||
void button_event_battery_press (bool shifted);
|
||||
void button_event_battery_release (bool shifted);
|
||||
void button_event_backlight_press (bool shifted);
|
||||
void button_event_backlight_release (bool shifted);
|
||||
void button_event_trackleft_press (bool shifted);
|
||||
void button_event_trackleft_release (bool shifted);
|
||||
void button_event_trackright_press (bool shifted);
|
||||
void button_event_trackright_release (bool shifted);
|
||||
void button_event_trackrec_press (bool shifted);
|
||||
void button_event_trackrec_release (bool shifted);
|
||||
void button_event_trackmute_press (bool shifted);
|
||||
void button_event_trackmute_release (bool shifted);
|
||||
void button_event_tracksolo_press (bool shifted);
|
||||
void button_event_tracksolo_release (bool shifted);
|
||||
void button_event_undo_press (bool shifted);
|
||||
void button_event_undo_release (bool shifted);
|
||||
void button_event_in_press (bool shifted);
|
||||
void button_event_in_release (bool shifted);
|
||||
void button_event_out_press (bool shifted);
|
||||
void button_event_out_release (bool shifted);
|
||||
void button_event_punch_press (bool shifted);
|
||||
void button_event_punch_release (bool shifted);
|
||||
void button_event_loop_press (bool shifted);
|
||||
void button_event_loop_release (bool shifted);
|
||||
void button_event_prev_press (bool shifted);
|
||||
void button_event_prev_release (bool shifted);
|
||||
void button_event_add_press (bool shifted);
|
||||
void button_event_add_release (bool shifted);
|
||||
void button_event_next_press (bool shifted);
|
||||
void button_event_next_release (bool shifted);
|
||||
void button_event_rewind_press (bool shifted);
|
||||
void button_event_rewind_release (bool shifted);
|
||||
void button_event_fastforward_press (bool shifted);
|
||||
void button_event_fastforward_release (bool shifted);
|
||||
void button_event_stop_press (bool shifted);
|
||||
void button_event_stop_release (bool shifted);
|
||||
void button_event_play_press (bool shifted);
|
||||
void button_event_play_release (bool shifted);
|
||||
void button_event_record_press (bool shifted);
|
||||
void button_event_record_release (bool shifted);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // ardour_tranzport_control_protocol_h
|
||||
Reference in New Issue
Block a user