+/*
+ Copyright (C) 2006 Paul Davis
+ Copyright (C) 2007 Mike Taht
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+
#ifndef ardour_tranzport_control_protocol_h
#define ardour_tranzport_control_protocol_h
-#include <vector>
+#include "tranzport_base.h"
+#include <vector>
+#include <bitset>
+#include <sys/time.h>
#include <pthread.h>
+
+#if !HAVE_TRANZPORT_KERNEL_DRIVER
#include <usb.h>
-#include <ardour/control_protocol.h>
+#endif
+
+#include <glibmm/thread.h>
#include <ardour/types.h>
-namespace ARDOUR {
+#include <control_protocol/control_protocol.h>
-class TranzportControlProtocol : public ControlProtocol {
- public:
- TranzportControlProtocol (Session&);
+class TranzportControlProtocol : public ARDOUR::ControlProtocol
+{
+public:
+ TranzportControlProtocol (ARDOUR::Session&);
virtual ~TranzportControlProtocol();
- int init ();
- bool active() const;
+ int set_active (bool yn);
+
+ static bool probe ();
- void send_route_feedback (std::list<Route*>&);
- void send_global_feedback ();
+ XMLNode& get_state ();
+ int set_state (const XMLNode&);
- private:
+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;
+ const static int STATUS_OK = 0x00;
+
+ const static int LIGHTS = 7;
+ const static int ROWS = 2;
+ const static int COLUMNS = 20;
+ const static uint8_t WheelDirectionThreshold = 0x7f;
enum LightID {
LightRecord = 0,
ButtonStop = 0x00010000,
ButtonPlay = 0x00100000,
ButtonRecord = 0x00000100,
- ButtonShift = 0x08000000
+ ButtonShift = 0x08000000,
+ ButtonFootswitch = 0x00001000
+ };
+
+ enum WheelShiftMode {
+ WheelShiftGain,
+ WheelShiftPan,
+ WheelShiftMaster,
+ WheelShiftMarker
};
+ enum WheelMode {
+ WheelTimeline,
+ WheelScrub,
+ WheelShuttle
+ };
+
+ // FIXME - look at gtk2_ardour for snap settings
+
+ enum WheelIncrement {
+ WheelIncrSlave,
+ WheelIncrScreen,
+ WheelIncrSample,
+ WheelIncrBeat,
+ WheelIncrBar,
+ WheelIncrSecond,
+ WheelIncrMinute
+ };
+
+ enum DisplayMode {
+ DisplayNormal,
+ DisplayRecording,
+ DisplayRecordingMeter,
+ DisplayBigMeter,
+ DisplayConfig,
+ DisplayBling,
+ DisplayBlingMeter
+ };
+
+ enum BlingMode {
+ BlingOff,
+ BlingKit,
+ BlingRotating,
+ BlingPairs,
+ BlingRows,
+ BlingFlashAll,
+ BlingEnter,
+ BlingExit
+ };
+
pthread_t thread;
+#if HAVE_TRANZPORT_KERNEL_DRIVER
+ int udev;
+#else
+ usb_dev_handle* udev;
+#endif
+
+#if TRANZPORT_THREADS
+ pthread_t thread_read;
+#endif
+ int last_read_error;
+
uint32_t buttonmask;
uint32_t timeout;
+ uint32_t inflight;
+ uint32_t current_track_id;
+#if TRANZPORT_THREADS
+ pthread_t thread_write;
+#endif
+ int last_write_error;
uint8_t _datawheel;
uint8_t _device_status;
- usb_dev_handle* udev;
- Route* current_route;
- uint32_t current_track_id;
- char current_screen[2][20];
- char next_screen[2][20];
- bool lights[7];
+ WheelMode wheel_mode;
+ WheelShiftMode wheel_shift_mode;
+ DisplayMode display_mode;
+ BlingMode bling_mode;
+ WheelIncrement wheel_increment;
+
+ ARDOUR::gain_t gain_fraction;
+
+ Glib::Mutex update_lock;
+
+ std::bitset<ROWS*COLUMNS> screen_invalid;
+ char screen_current[ROWS][COLUMNS];
+ char screen_pending[ROWS][COLUMNS];
+ char screen_flash[ROWS][COLUMNS];
+
+ std::bitset<LIGHTS> lights_invalid;
+ std::bitset<LIGHTS> lights_current;
+ std::bitset<LIGHTS> lights_pending;
+ std::bitset<LIGHTS> lights_flash;
- std::vector<sigc::connection> track_connections;
+ int32_t last_notify;
+ char last_notify_msg[COLUMNS+1];
+ uint32_t last_bars;
+ uint32_t last_beats;
+ uint32_t last_ticks;
- bool last_negative;
- uint32_t last_hrs;
- uint32_t last_mins;
- uint32_t last_secs;
- uint32_t last_frames;
- jack_nframes_t last_where;
+ bool last_negative;
+ uint32_t last_hrs;
+ uint32_t last_mins;
+ uint32_t last_secs;
+ uint32_t last_frames;
+ nframes_t last_where;
+ ARDOUR::gain_t last_track_gain;
+ uint32_t last_meter_fill;
+ struct timeval last_wheel_motion;
+ int last_wheel_dir;
+
+ Glib::Mutex io_lock;
int open ();
- int read (uint32_t timeout_override = 0);
+ int read (uint8_t *buf,uint32_t timeout_override = 0);
int write (uint8_t* cmd, uint32_t timeout_override = 0);
+ int write_noretry (uint8_t* cmd, uint32_t timeout_override = 0);
int close ();
+ int save_config(char *name = "default");
+ int load_config(char *name = "default");
+ int save(char *name);
+ int load(char *name);
+ void print (int row, int col, const char* text);
+ void print_noretry (int row, int col, const char* text);
+ void notify(const char *msg);
+
+#if HAVE_TRANZPORT_KERNEL_DRIVER
+ int rtpriority_set(int priority = 3); // we don't need serious rt privs anymore
+#else
+ int rtpriority_set(int priority = 52);
+#endif
+ int rtpriority_unset(int priority = 0);
+ // I hate changing the api to do either but until I have clean io class what can you do?
+#if !HAVE_TRANZPORT_KERNEL_DRIVER
int open_core (struct usb_device*);
+#endif
+ static void* _monitor_work (void* arg);
+ void* monitor_work ();
+
+ int process (uint8_t *);
+ int update_state();
+ void invalidate();
+ int flush();
+ // bool isuptodate(); // think on this. It seems futile to update more than 30/sec
+
+ // A screen is a cache of what should be on the lcd
+
+ void screen_init();
+ void screen_validate();
+ void screen_invalidate();
+ int screen_flush();
+ void screen_clear();
+ // bool screen_isuptodate(); // think on this -
+ int screen_show_bling();
+
+ // Commands to write to the lcd
+ int lcd_init();
+ bool lcd_damage();
+ bool lcd_isdamaged();
+
+ bool lcd_damage(int row, int col = 0, int length = COLUMNS);
+ bool lcd_isdamaged(int row, int col = 0, int length = COLUMNS);
+
+ int lcd_flush();
+ int lcd_write(uint8_t* cmd, uint32_t timeout_override = 0); // pedantic alias for write
+ void lcd_fill (uint8_t fill_char);
void lcd_clear ();
- int lcd_write (uint8_t cell, const char *text);
+ void lcd_print (int row, int col, const char* text);
+ void lcd_print_noretry (int row, int col, const char* text);
+
+ // Commands to write to the lights
+ // FIXME - on some devices lights can have intensity and colors
+ void lights_init();
+ void lights_validate();
+ void lights_invalidate();
+ void light_validate(LightID light);
+ void light_invalidate(LightID light);
+ int lights_flush();
+ int lights_write(uint8_t* cmd,uint32_t timeout_override = 0); // pedantic alias to write
+
+ // a cache of what should be lit
+
+ void lights_off ();
+ void lights_on ();
+ int light_set(LightID, bool offon = true);
int light_on (LightID);
int light_off (LightID);
- void flush_lcd ();
- void write_clock (const uint8_t* label);
+ // some modes for the lights, should probably be renamed
+
+ int lights_show_normal();
+ int lights_show_recording();
+ int lights_show_tempo();
+ int lights_show_bling();
+
+ void enter_big_meter_mode ();
+ void enter_normal_display_mode ();
+ void enter_config_mode();
+ void enter_recording_mode();
+ void enter_bling_mode();
+
+ void next_marker (); // basicui doesn't give me enough info
+ void prev_marker ();
+
+ void next_display_mode ();
+ void normal_update ();
void show_current_track ();
+ void show_track_gain ();
void show_transport_time ();
+ void show_bbt (nframes_t where);
+ void show_smpte (nframes_t where);
+ void show_wheel_mode ();
+ void show_gain ();
+ void show_pan ();
+ void show_meter ();
+ void show_mini_meter ();
+ void show_bling();
+ void show_notify();
- void track_solo_changed (void*);
- void track_rec_changed (void*);
- void track_mute_changed (void*);
+ void datawheel ();
+ void scrub ();
+ void scroll ();
+ void shuttle ();
+ void config ();
+
+ void next_wheel_mode ();
+ void next_wheel_shift_mode ();
+
+ void set_current_track (ARDOUR::Route*);
+ void next_track ();
+ void prev_track ();
+ void step_gain_up ();
+ void step_gain_down ();
+ void step_pan_right ();
+ void step_pan_left ();
- 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_play_release (bool shifted);
void button_event_record_press (bool shifted);
void button_event_record_release (bool shifted);
+ void button_event_footswitch_press(bool shifted);
+ void button_event_footswitch_release (bool shifted);
+
+ // new api - still thinking about it
+ void button_event_mute (bool pressed, bool shifted);
};
-} // namespace
#endif // ardour_tranzport_control_protocol_h