1 /*
2   Copyright (C) 2006 Paul Davis
3   Copyright (C) 2007 Mike Taht
4 
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9 
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14 
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 
19 */
20 
21 
22 #ifndef ardour_tranzport_control_protocol_h
23 #define ardour_tranzport_control_protocol_h
24 
25 #include "tranzport_base.h"
26 
27 #include <vector>
28 #include <bitset>
29 #include <sys/time.h>
30 #include <pthread.h>
31 
32 #if !HAVE_TRANZPORT_KERNEL_DRIVER
33 #include <usb.h>
34 #endif
35 
36 #include <glibmm/threads.h>
37 #include "ardour/types.h"
38 
39 #include "control_protocol/control_protocol.h"
40 
41 class TranzportControlProtocol : public ARDOUR::ControlProtocol
42 {
43 public:
44 	TranzportControlProtocol (ARDOUR::Session&);
45 	virtual ~TranzportControlProtocol();
46 
47 	int set_active (bool yn);
48 
49 	static bool probe ();
50 
51 	XMLNode& get_state ();
52 	int set_state (const XMLNode&);
53 
54 private:
55 	static const int VENDORID = 0x165b;
56 	static const int PRODUCTID = 0x8101;
57 	static const int READ_ENDPOINT  = 0x81;
58 	static const int WRITE_ENDPOINT = 0x02;
59 	const static int STATUS_OFFLINE  = 0xff;
60 	const static int STATUS_ONLINE = 0x01;
61 	const static int STATUS_OK = 0x00;
62 
63 	const static int LIGHTS = 7;
64 	const static int ROWS = 2;
65 	const static int COLUMNS = 20;
66 	const static uint8_t WheelDirectionThreshold = 0x7f;
67 
68 	enum LightID {
69 		LightRecord = 0,
70 		LightTrackrec,
71 		LightTrackmute,
72 		LightTracksolo,
73 		LightAnysolo,
74 		LightLoop,
75 		LightPunch
76 	};
77 
78 	enum ButtonID {
79 		ButtonBattery = 0x00004000,
80 		ButtonBacklight = 0x00008000,
81 		ButtonTrackLeft = 0x04000000,
82 		ButtonTrackRight = 0x40000000,
83 		ButtonTrackRec = 0x00040000,
84 		ButtonTrackMute = 0x00400000,
85 		ButtonTrackSolo = 0x00000400,
86 		ButtonUndo = 0x80000000,
87 		ButtonIn = 0x02000000,
88 		ButtonOut = 0x20000000,
89 		ButtonPunch = 0x00800000,
90 		ButtonLoop = 0x00080000,
91 		ButtonPrev = 0x00020000,
92 		ButtonAdd = 0x00200000,
93 		ButtonNext = 0x00000200,
94 		ButtonRewind = 0x01000000,
95 		ButtonFastForward = 0x10000000,
96 		ButtonStop = 0x00010000,
97 		ButtonPlay = 0x00100000,
98 		ButtonRecord = 0x00000100,
99 		ButtonShift = 0x08000000,
100 		ButtonFootswitch = 0x00001000
101 	};
102 
103 	enum WheelShiftMode {
104 		WheelShiftGain,
105 		WheelShiftPan,
106 		WheelShiftMaster,
107 		WheelShiftMarker
108 	};
109 
110 	enum WheelMode {
111 		WheelTimeline,
112 		WheelScrub,
113 		WheelShuttle
114 	};
115 
116 	// FIXME - look at gtk2_ardour for snap settings
117 
118 	enum WheelIncrement {
119 		WheelIncrSlave,
120 		WheelIncrScreen,
121 		WheelIncrSample,
122 		WheelIncrBeat,
123 		WheelIncrBar,
124 		WheelIncrSecond,
125 		WheelIncrMinute
126 	};
127 
128 	enum DisplayMode {
129 		DisplayNormal,
130 		DisplayRecording,
131 		DisplayRecordingMeter,
132 		DisplayBigMeter,
133 		DisplayConfig,
134 		DisplayBling,
135 		DisplayBlingMeter
136 	};
137 
138 	enum BlingMode {
139 		BlingOff,
140 		BlingKit,
141 		BlingRotating,
142 		BlingPairs,
143 		BlingRows,
144 		BlingFlashAll,
145 		BlingEnter,
146 		BlingExit
147 	};
148 
149 	pthread_t       thread;
150 #if HAVE_TRANZPORT_KERNEL_DRIVER
151 	int udev;
152 #else
153 	usb_dev_handle* udev;
154 #endif
155 
156 	int             last_read_error;
157 
158 	uint32_t        buttonmask;
159 	uint32_t        timeout;
160 	uint32_t        inflight;
161 	uint32_t        current_track_id;
162 	int             last_write_error;
163 	uint8_t        _datawheel;
164 	uint8_t        _device_status;
165 	WheelMode       wheel_mode;
166 	WheelShiftMode  wheel_shift_mode;
167 	DisplayMode     display_mode;
168 	BlingMode       bling_mode;
169 	WheelIncrement  wheel_increment;
170 
171 	ARDOUR::gain_t  gain_fraction;
172 
173 	Glib::Threads::Mutex update_lock;
174 
175 	std::bitset<ROWS*COLUMNS> screen_invalid;
176 	char screen_current[ROWS][COLUMNS];
177 	char screen_pending[ROWS][COLUMNS];
178 	char screen_flash[ROWS][COLUMNS];
179 
180 	std::bitset<LIGHTS> lights_invalid;
181 	std::bitset<LIGHTS> lights_current;
182 	std::bitset<LIGHTS> lights_pending;
183 	std::bitset<LIGHTS> lights_flash;
184 
185 	int32_t       last_notify;
186 	char           last_notify_msg[COLUMNS+1];
187 	uint32_t       last_bars;
188 	uint32_t       last_beats;
189 	uint32_t       last_ticks;
190 
191 	bool           last_negative;
192 	uint32_t       last_hrs;
193 	uint32_t       last_mins;
194 	uint32_t       last_secs;
195 	uint32_t       last_samples;
196 	samplepos_t    last_where;
197 	ARDOUR::gain_t last_track_gain;
198 	uint32_t       last_meter_fill;
199 	struct timeval last_wheel_motion;
200 	int            last_wheel_dir;
201 
202 	Glib::Mutex io_lock;
203 
204 	int open ();
205 	int read (uint8_t *buf,uint32_t timeout_override = 0);
206 	int write (uint8_t* cmd, uint32_t timeout_override = 0);
207 	int write_noretry (uint8_t* cmd, uint32_t timeout_override = 0);
208 	int close ();
209 	int save_config(char *name = "default");
210 	int load_config(char *name = "default");
211 	int save(char *name);
212 	int load(char *name);
213 	void print (int row, int col, const char* text);
214 	void print_noretry (int row, int col, const char* text);
215 	void notify(const char *msg);
216 
217 #if HAVE_TRANZPORT_KERNEL_DRIVER
218 	int rtpriority_set(int priority = 3); // we don't need serious rt privs anymore
219 #else
220 	int rtpriority_set(int priority = 52);
221 #endif
222 	int rtpriority_unset(int priority = 0);
223 
224 	// I hate changing the api to do either but until I have clean io class what can you do?
225 #if !HAVE_TRANZPORT_KERNEL_DRIVER
226 	int open_core (struct usb_device*);
227 #endif
228 	static void* _monitor_work (void* arg);
229 	void* monitor_work ();
230 
231 	int process (uint8_t *);
232 	int update_state();
233 	void invalidate();
234 	int flush();
235 	// bool isuptodate(); // think on this. It seems futile to update more than 30/sec
236 
237 	// A screen is a cache of what should be on the lcd
238 
239 	void screen_init();
240 	void screen_validate();
241 	void screen_invalidate();
242 	int  screen_flush();
243 	void screen_clear();
244 	// bool screen_isuptodate(); // think on this -
245 	int  screen_show_bling();
246 
247 	// Commands to write to the lcd
248 
249 	int  lcd_init();
250 	bool lcd_damage();
251 	bool lcd_isdamaged();
252 
253 	bool lcd_damage(int row, int col = 0, int length = COLUMNS);
254 	bool lcd_isdamaged(int row, int col = 0, int length = COLUMNS);
255 
256 	int  lcd_flush();
257 	int  lcd_write(uint8_t* cmd, uint32_t timeout_override = 0); // pedantic alias for write
258 	void lcd_fill (uint8_t fill_char);
259 	void lcd_clear ();
260 	void lcd_print (int row, int col, const char* text);
261 	void lcd_print_noretry (int row, int col, const char* text);
262 
263 	// Commands to write to the lights
264 	// FIXME - on some devices lights can have intensity and colors
265 
266 	void lights_init();
267 	void lights_validate();
268 	void lights_invalidate();
269 	void light_validate(LightID light);
270 	void light_invalidate(LightID light);
271 	int  lights_flush();
272 	int  lights_write(uint8_t* cmd,uint32_t timeout_override = 0); // pedantic alias to write
273 
274 	// a cache of what should be lit
275 
276 	void lights_off ();
277 	void lights_on ();
278 	int  light_set(LightID, bool offon = true);
279 	int  light_on (LightID);
280 	int  light_off (LightID);
281 
282 	// some modes for the lights, should probably be renamed
283 
284 	int  lights_show_normal();
285 	int  lights_show_recording();
286 	int  lights_show_tempo();
287 	int  lights_show_bling();
288 
289 	void enter_big_meter_mode ();
290 	void enter_normal_display_mode ();
291 	void enter_config_mode();
292 	void enter_recording_mode();
293 	void enter_bling_mode();
294 
295 	void next_marker (); // basicui doesn't give me enough info
296 	void prev_marker ();
297 
298 	void next_display_mode ();
299 	void normal_update ();
300 
301 	void show_current_track ();
302 	void show_track_gain ();
303 	void show_transport_time ();
304 	void show_bbt (samplepos_t where);
305 	void show_timecode (samplepos_t where);
306 	void show_wheel_mode ();
307 	void show_gain ();
308 	void show_pan ();
309 	void show_meter ();
310 	void show_mini_meter ();
311 	void show_bling();
312 	void show_notify();
313 
314 	void datawheel ();
315 	void scrub ();
316 	void scroll ();
317 	void shuttle ();
318 	void config ();
319 
320 	void next_wheel_mode ();
321 	void next_wheel_shift_mode ();
322 
323 	void set_current_track (ARDOUR::Route*);
324 	void next_track ();
325 	void prev_track ();
326 	void step_gain_up ();
327 	void step_gain_down ();
328 	void step_pan_right ();
329 	void step_pan_left ();
330 
331 
332 	void button_event_battery_press (bool shifted);
333 	void button_event_battery_release (bool shifted);
334 	void button_event_backlight_press (bool shifted);
335 	void button_event_backlight_release (bool shifted);
336 	void button_event_trackleft_press (bool shifted);
337 	void button_event_trackleft_release (bool shifted);
338 	void button_event_trackright_press (bool shifted);
339 	void button_event_trackright_release (bool shifted);
340 	void button_event_trackrec_press (bool shifted);
341 	void button_event_trackrec_release (bool shifted);
342 	void button_event_trackmute_press (bool shifted);
343 	void button_event_trackmute_release (bool shifted);
344 	void button_event_tracksolo_press (bool shifted);
345 	void button_event_tracksolo_release (bool shifted);
346 	void button_event_undo_press (bool shifted);
347 	void button_event_undo_release (bool shifted);
348 	void button_event_in_press (bool shifted);
349 	void button_event_in_release (bool shifted);
350 	void button_event_out_press (bool shifted);
351 	void button_event_out_release (bool shifted);
352 	void button_event_punch_press (bool shifted);
353 	void button_event_punch_release (bool shifted);
354 	void button_event_loop_press (bool shifted);
355 	void button_event_loop_release (bool shifted);
356 	void button_event_prev_press (bool shifted);
357 	void button_event_prev_release (bool shifted);
358 	void button_event_add_press (bool shifted);
359 	void button_event_add_release (bool shifted);
360 	void button_event_next_press (bool shifted);
361 	void button_event_next_release (bool shifted);
362 	void button_event_rewind_press (bool shifted);
363 	void button_event_rewind_release (bool shifted);
364 	void button_event_fastforward_press (bool shifted);
365 	void button_event_fastforward_release (bool shifted);
366 	void button_event_stop_press (bool shifted);
367 	void button_event_stop_release (bool shifted);
368 	void button_event_play_press (bool shifted);
369 	void button_event_play_release (bool shifted);
370 	void button_event_record_press (bool shifted);
371 	void button_event_record_release (bool shifted);
372 	void button_event_footswitch_press(bool shifted);
373 	void button_event_footswitch_release (bool shifted);
374 
375 	// new api - still thinking about it
376 	void button_event_mute (bool pressed, bool shifted);
377 };
378 
379 
380 #endif // ardour_tranzport_control_protocol_h
381