diff options
Diffstat (limited to 'libs/ardour/tranzport_control_protocol.cc')
-rw-r--r-- | libs/ardour/tranzport_control_protocol.cc | 718 |
1 files changed, 718 insertions, 0 deletions
diff --git a/libs/ardour/tranzport_control_protocol.cc b/libs/ardour/tranzport_control_protocol.cc new file mode 100644 index 0000000000..9640ea4a75 --- /dev/null +++ b/libs/ardour/tranzport_control_protocol.cc @@ -0,0 +1,718 @@ +#include <iostream> + +#include <pbd/pthread_utils.h> + +#include <ardour/tranzport_control_protocol.h> +#include <ardour/route.h> +#include <ardour/session.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; +} + +TranzportControlProtocol::~TranzportControlProtocol () +{ + if (udev) { + pthread_cancel_one (thread); + close (); + } +} + +int +TranzportControlProtocol::init () +{ + if (open ()) { + return -1; + } + + pthread_create_and_store (X_("Tranzport"), &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 () +{ + jack_nframes_t where = session.transport_frame(); + + if (where != last_where) { + + char clock_label[16]; + SMPTE_Time smpte; + char* ptr = clock_label; + + session.smpte_time (where, smpte); + memset (clock_label, ' ', sizeof (clock_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; + + lcd_write (7, &clock_label[0]); + lcd_write (8, &clock_label[4]); + lcd_write (9, &clock_label[8]); + + last_where = where; + } +} + +void* +TranzportControlProtocol::_thread_work (void* arg) +{ + return static_cast<TranzportControlProtocol*>(arg)->thread_work (); +} + +void* +TranzportControlProtocol::thread_work () +{ + cerr << "tranzport thread here, sending message to LCD\n"; + + 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 ()) { + cerr << "Tranzport command received\n"; + break; + } + } + + return 0; +} + +int +TranzportControlProtocol::open () +{ + struct usb_bus *bus; + struct usb_device *dev; + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + cerr << "checking busses\n"; + + for (bus = usb_busses; bus; bus = bus->next) { + + cerr << "checking devices\n"; + + for(dev = bus->devices; dev; dev = dev->next) { + cerr << "Checking " << dev->descriptor.idVendor << '/' << dev->descriptor.idProduct << endl; + if (dev->descriptor.idVendor != VENDORID) + continue; + if (dev->descriptor.idProduct != PRODUCTID) + continue; + cerr << "Open this one" << endl; + 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) +{ + int val; + val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout); + if (val < 0) + return val; + if (val != 8) + return -1; + 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; + + return write (cmd); +} + +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); +} + +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); +} + +int +TranzportControlProtocol::read () +{ + uint8_t buf[8]; + int val; + + memset(buf, 0, 8); + val = usb_interrupt_read(udev, READ_ENDPOINT, (char*) buf, 8, timeout); + if (val < 0) { + cerr << "Tranzport read error, val = " << val << endl; + return val; + } + if (val != 8) { + cerr << "Tranzport short read, val = " << val << endl; + 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) +{ +} |