13
0
livetrax/libs/surfaces/tranzport/tranzport_control_protocol.cc
Paul Davis 9ae0f6cbee 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
2006-04-05 00:21:43 +00:00

790 lines
16 KiB
C++

#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], &current_screen[0][0], 4)) {
lcd_write (0, &next_screen[0][0]);
}
if (memcmp (&next_screen[0][4], &current_screen[0][4], 4)) {
lcd_write (1, &next_screen[0][0]);
}
if (memcmp (&next_screen[0][8], &current_screen[0][8], 4)) {
lcd_write (2, &next_screen[0][0]);
}
if (memcmp (&next_screen[0][12], &current_screen[0][12], 4)) {
lcd_write (3, &next_screen[0][0]);
}
if (memcmp (&next_screen[0][16], &current_screen[0][16], 4)) {
lcd_write (4, &next_screen[0][0]);
}
if (memcmp (&next_screen[1][0], &current_screen[1][0], 4)) {
lcd_write (5, &next_screen[0][0]);
}
if (memcmp (&next_screen[1][4], &current_screen[1][4], 4)) {
lcd_write (6, &next_screen[0][0]);
}
if (memcmp (&next_screen[1][8], &current_screen[1][8], 4)) {
lcd_write (7, &next_screen[0][0]);
}
if (memcmp (&next_screen[1][12], &current_screen[1][12], 4)) {
lcd_write (8, &next_screen[0][0]);
}
if (memcmp (&next_screen[1][16], &current_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)
{
}