enough with umpteen "i18n.h" files. Consolidate on pbd/i18n.h
[ardour.git] / libs / surfaces / faderport / faderport.h
1 /*
2     Copyright (C) 2006 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef ardour_surface_faderport_h
21 #define ardour_surface_faderport_h
22
23 #include <list>
24 #include <map>
25 #include <set>
26 #include <glibmm/threads.h>
27
28 #define ABSTRACT_UI_EXPORTS
29 #include "pbd/abstract_ui.h"
30
31 #include "ardour/types.h"
32
33 #include "control_protocol/control_protocol.h"
34
35 namespace PBD {
36         class Controllable;
37         class ControllableDescriptor;
38 }
39
40 #include <midi++/types.h>
41
42 //#include "pbd/signals.h"
43
44
45 //#include "midi_byte_array.h"
46 #include "types.h"
47
48 #include "glibmm/main.h"
49
50 namespace MIDI {
51         class Parser;
52         class Port;
53 }
54
55
56 namespace ARDOUR {
57         class AsyncMIDIPort;
58         class Bundle;
59         class Port;
60         class Session;
61         class MidiPort;
62 }
63
64
65 class MIDIControllable;
66 class MIDIFunction;
67 class MIDIAction;
68
69 namespace ArdourSurface {
70
71 struct FaderPortRequest : public BaseUI::BaseRequestObject {
72 public:
73         FaderPortRequest () {}
74         ~FaderPortRequest () {}
75 };
76
77 class FaderPort : public ARDOUR::ControlProtocol, public AbstractUI<FaderPortRequest> {
78   public:
79         FaderPort (ARDOUR::Session&);
80         virtual ~FaderPort();
81
82         int set_active (bool yn);
83
84         /* we probe for a device when our ports are connected. Before that,
85            there's no way to know if the device exists or not.
86          */
87         static bool probe() { return true; }
88         static void* request_factory (uint32_t);
89
90         XMLNode& get_state ();
91         int set_state (const XMLNode&, int version);
92
93         bool has_editor () const { return true; }
94         void* get_gui () const;
95         void  tear_down_gui ();
96
97         /* Note: because the FaderPort speaks an inherently duplex protocol,
98            we do not implement get/set_feedback() since this aspect of
99            support for the protocol is not optional.
100         */
101
102         void do_request (FaderPortRequest*);
103         int stop ();
104
105         void thread_init ();
106
107         PBD::Signal0<void> ConnectionChange;
108
109         boost::shared_ptr<ARDOUR::Port> input_port();
110         boost::shared_ptr<ARDOUR::Port> output_port();
111
112         /* In a feat of engineering brilliance, the Presonus Faderport sends
113          * one button identifier when the button is pressed/released, but
114          * responds to another button identifier as a command to light the LED
115          * corresponding to the button. These ID's define what is sent
116          * for press/release; a separate data structure contains information
117          * on what to send to turn the LED on/off.
118          *
119          * One can only conclude that Presonus just didn't want to fix this
120          * issue because it contradicts their own documentation and is more or
121          * less the first thing you discover when programming the device.
122          */
123
124         enum ButtonID {
125                 Mute = 18,
126                 Solo = 17,
127                 Rec = 16,
128                 Left = 19,
129                 Bank = 20,
130                 Right = 21,
131                 Output = 22,
132                 FP_Read = 10,
133                 FP_Write = 9,
134                 FP_Touch = 8,
135                 FP_Off = 23,
136                 Mix = 11,
137                 Proj = 12,
138                 Trns = 13,
139                 Undo = 14,
140                 Shift = 2,
141                 Punch = 1,
142                 User = 0,
143                 Loop = 15,
144                 Rewind = 3,
145                 Ffwd = 4,
146                 Stop = 5,
147                 Play = 6,
148                 RecEnable = 7,
149                 Footswitch = 126,
150                 FaderTouch = 127,
151         };
152
153         enum ButtonState {
154                 ShiftDown = 0x1,
155                 RewindDown = 0x2,
156                 StopDown = 0x4,
157                 UserDown = 0x8,
158                 LongPress = 0x10
159         };
160
161         void set_action (ButtonID, std::string const& action_name, bool on_press, FaderPort::ButtonState = ButtonState (0));
162         std::string get_action (ButtonID, bool on_press, FaderPort::ButtonState = ButtonState (0));
163
164         std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
165
166   private:
167         boost::shared_ptr<ARDOUR::Stripable> _current_stripable;
168         boost::weak_ptr<ARDOUR::Stripable> pre_master_stripable;
169         boost::weak_ptr<ARDOUR::Stripable> pre_monitor_stripable;
170
171         boost::shared_ptr<ARDOUR::AsyncMIDIPort> _input_port;
172         boost::shared_ptr<ARDOUR::AsyncMIDIPort> _output_port;
173
174         // Bundle to represent our input ports
175         boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
176         // Bundle to represent our output ports
177         boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
178
179         PBD::ScopedConnectionList midi_connections;
180
181         bool midi_input_handler (Glib::IOCondition ioc, boost::shared_ptr<ARDOUR::AsyncMIDIPort> port);
182
183         mutable void *gui;
184         void build_gui ();
185
186         bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
187         PBD::ScopedConnection port_connection;
188
189         enum ConnectionState {
190                 InputConnected = 0x1,
191                 OutputConnected = 0x2
192         };
193
194         int connection_state;
195         void connected ();
196         bool _device_active;
197         int fader_msb;
198         int fader_lsb;
199         bool fader_is_touched;
200
201         ARDOUR::microseconds_t last_encoder_time;
202         int last_good_encoder_delta;
203         int last_encoder_delta, last_last_encoder_delta;
204
205         void sysex_handler (MIDI::Parser &p, MIDI::byte *, size_t);
206         void button_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
207         void encoder_handler (MIDI::Parser &, MIDI::pitchbend_t pb);
208         void fader_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
209
210         ButtonState button_state;
211
212         friend class Button;
213
214         class Button {
215           public:
216
217                 enum ActionType {
218                         NamedAction,
219                         InternalFunction,
220                 };
221
222                 Button (FaderPort& f, std::string const& str, ButtonID i, int o)
223                         : fp (f)
224                         , name (str)
225                         , id (i)
226                         , out (o)
227                         , flash (false)
228                 {}
229
230                 void set_action (std::string const& action_name, bool on_press, FaderPort::ButtonState = ButtonState (0));
231                 void set_action (boost::function<void()> function, bool on_press, FaderPort::ButtonState = ButtonState (0));
232                 std::string get_action (bool press, FaderPort::ButtonState bs = ButtonState (0));
233
234                 void set_led_state (boost::shared_ptr<MIDI::Port>, bool onoff);
235                 void invoke (ButtonState bs, bool press);
236                 bool uses_flash () const { return flash; }
237                 void set_flash (bool yn) { flash = yn; }
238
239                 XMLNode& get_state () const;
240                 int set_state (XMLNode const&);
241
242                 sigc::connection timeout_connection;
243
244           private:
245                 FaderPort& fp;
246                 std::string name;
247                 ButtonID id;
248                 int out;
249                 bool flash;
250
251                 struct ToDo {
252                         ActionType type;
253                         /* could be a union if boost::function didn't require a
254                          * constructor
255                          */
256                         std::string action_name;
257                         boost::function<void()> function;
258                 };
259
260                 typedef std::map<FaderPort::ButtonState,ToDo> ToDoMap;
261                 ToDoMap on_press;
262                 ToDoMap on_release;
263         };
264
265         typedef std::map<ButtonID,Button> ButtonMap;
266
267         ButtonMap buttons;
268         Button& get_button (ButtonID) const;
269
270         std::set<ButtonID> buttons_down;
271         std::set<ButtonID> consumed;
272
273         bool button_long_press_timeout (ButtonID id);
274         void start_press_timeout (Button&, ButtonID);
275
276         void all_lights_out ();
277         void close ();
278         void start_midi_handling ();
279         void stop_midi_handling ();
280
281         PBD::ScopedConnectionList session_connections;
282         void connect_session_signals ();
283         void map_recenable_state ();
284         void map_transport_state ();
285
286         sigc::connection periodic_connection;
287         bool periodic ();
288
289         sigc::connection blink_connection;
290         typedef std::list<ButtonID> Blinkers;
291         Blinkers blinkers;
292         bool blink_state;
293         bool blink ();
294         void start_blinking (ButtonID);
295         void stop_blinking (ButtonID);
296
297         void set_current_stripable (boost::shared_ptr<ARDOUR::Stripable>);
298         void drop_current_stripable ();
299         void use_master ();
300         void use_monitor ();
301         void gui_track_selection_changed (ARDOUR::StripableNotificationListPtr);
302         PBD::ScopedConnection selection_connection;
303         PBD::ScopedConnectionList stripable_connections;
304
305         void map_stripable_state ();
306         void map_solo ();
307         void map_mute ();
308         bool rec_enable_state;
309         void map_recenable ();
310         void map_gain ();
311         void map_cut ();
312         void map_auto ();
313         void parameter_changed (std::string);
314
315         /* operations (defined in operations.cc) */
316
317         void read ();
318         void write ();
319
320         void left ();
321         void right ();
322
323         void touch ();
324         void off ();
325
326         void undo ();
327         void redo ();
328         void solo ();
329         void mute ();
330         void rec_enable ();
331
332         void ardour_pan_azimuth (int);
333         void ardour_pan_width (int);
334         void mixbus_pan (int);
335
336         void punch ();
337 };
338
339 }
340
341 #endif /* ardour_surface_faderport_h */