diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2006-04-05 00:21:43 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2006-04-05 00:21:43 +0000 |
commit | 9ae0f6cbeec4702b50bcd2360ea4d5dc1aeebd47 (patch) | |
tree | 4879aebc558936ab87857749656b66a208b9ee99 /libs/surfaces | |
parent | f7c82c69113419a8db083f0095044af5ad4c872c (diff) |
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
Diffstat (limited to 'libs/surfaces')
-rw-r--r-- | libs/surfaces/generic_midi/SConscript | 51 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.cc | 55 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/generic_midi_control_protocol.h | 31 | ||||
-rw-r--r-- | libs/surfaces/generic_midi/interface.cc | 34 | ||||
-rw-r--r-- | libs/surfaces/tranzport/SConscript | 52 | ||||
-rw-r--r-- | libs/surfaces/tranzport/interface.cc | 34 | ||||
-rw-r--r-- | libs/surfaces/tranzport/tranzport_control_protocol.cc | 789 | ||||
-rw-r--r-- | libs/surfaces/tranzport/tranzport_control_protocol.h | 147 |
8 files changed, 1193 insertions, 0 deletions
diff --git a/libs/surfaces/generic_midi/SConscript b/libs/surfaces/generic_midi/SConscript new file mode 100644 index 0000000000..abede3f4d7 --- /dev/null +++ b/libs/surfaces/generic_midi/SConscript @@ -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'))) diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc new file mode 100644 index 0000000000..4d64c6ce23 --- /dev/null +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -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(); +} + diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h new file mode 100644 index 0000000000..75b514f016 --- /dev/null +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -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 diff --git a/libs/surfaces/generic_midi/interface.cc b/libs/surfaces/generic_midi/interface.cc new file mode 100644 index 0000000000..8283b92e6f --- /dev/null +++ b/libs/surfaces/generic_midi/interface.cc @@ -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; +} +} + diff --git a/libs/surfaces/tranzport/SConscript b/libs/surfaces/tranzport/SConscript new file mode 100644 index 0000000000..e43f0bc77c --- /dev/null +++ b/libs/surfaces/tranzport/SConscript @@ -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'))) diff --git a/libs/surfaces/tranzport/interface.cc b/libs/surfaces/tranzport/interface.cc new file mode 100644 index 0000000000..a731be2ddf --- /dev/null +++ b/libs/surfaces/tranzport/interface.cc @@ -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; +} +} + diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.cc b/libs/surfaces/tranzport/tranzport_control_protocol.cc new file mode 100644 index 0000000000..518a4387d1 --- /dev/null +++ b/libs/surfaces/tranzport/tranzport_control_protocol.cc @@ -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) +{ +} diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.h b/libs/surfaces/tranzport/tranzport_control_protocol.h new file mode 100644 index 0000000000..5880f3807a --- /dev/null +++ b/libs/surfaces/tranzport/tranzport_control_protocol.h @@ -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 |