2 Copyright (C) 2006 Paul Davis
3 Copyright (C) 2016 W.P. van Paassen
5 Thanks to Rolf Meyerhoff for reverse engineering the CC121 protocol.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #ifndef ardour_surface_cc121_h
24 #define ardour_surface_cc121_h
29 #include <glibmm/threads.h>
31 #define ABSTRACT_UI_EXPORTS
32 #include "pbd/abstract_ui.h"
34 #include "ardour/types.h"
36 #include "control_protocol/control_protocol.h"
42 #include <midi++/types.h>
44 //#include "pbd/signals.h"
47 //#include "midi_byte_array.h"
50 #include "glibmm/main.h"
67 class MIDIControllable;
71 namespace ArdourSurface {
73 struct CC121Request : public BaseUI::BaseRequestObject {
79 class CC121 : public ARDOUR::ControlProtocol, public AbstractUI<CC121Request> {
81 CC121 (ARDOUR::Session&);
84 int set_active (bool yn);
86 /* we probe for a device when our ports are connected. Before that,
87 there's no way to know if the device exists or not.
89 static bool probe() { return true; }
90 static void* request_factory (uint32_t);
92 XMLNode& get_state ();
93 int set_state (const XMLNode&, int version);
95 bool has_editor () const { return true; }
96 void* get_gui () const;
97 void tear_down_gui ();
100 /* Note: because the CC121 speaks an inherently duplex protocol,
101 we do not implement get/set_feedback() since this aspect of
102 support for the protocol is not optional.
105 void do_request (CC121Request*);
110 PBD::Signal0<void> ConnectionChange;
112 boost::shared_ptr<ARDOUR::Port> input_port();
113 boost::shared_ptr<ARDOUR::Port> output_port();
160 void set_action (ButtonID, std::string const& action_name, bool on_press, CC121::ButtonState = ButtonState (0));
161 std::string get_action (ButtonID, bool on_press, CC121::ButtonState = ButtonState (0));
163 std::list<boost::shared_ptr<ARDOUR::Bundle> > bundles ();
166 boost::shared_ptr<ARDOUR::Stripable> _current_stripable;
167 boost::weak_ptr<ARDOUR::Stripable> pre_master_stripable;
168 boost::weak_ptr<ARDOUR::Stripable> pre_monitor_stripable;
170 boost::shared_ptr<ARDOUR::AsyncMIDIPort> _input_port;
171 boost::shared_ptr<ARDOUR::AsyncMIDIPort> _output_port;
173 // Bundle to represent our input ports
174 boost::shared_ptr<ARDOUR::Bundle> _input_bundle;
175 // Bundle to represent our output ports
176 boost::shared_ptr<ARDOUR::Bundle> _output_bundle;
178 PBD::ScopedConnectionList midi_connections;
180 bool midi_input_handler (Glib::IOCondition ioc, boost::shared_ptr<ARDOUR::AsyncMIDIPort> port);
185 bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
186 PBD::ScopedConnection port_connection;
188 enum ConnectionState {
189 InputConnected = 0x1,
190 OutputConnected = 0x2
193 int connection_state;
198 bool fader_is_touched;
199 enum JogMode { scroll=1, zoom=2 };
202 ARDOUR::microseconds_t last_encoder_time;
203 int last_good_encoder_delta;
204 int last_encoder_delta, last_last_encoder_delta;
206 void button_press_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
207 void button_release_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
208 void fader_handler (MIDI::Parser &, MIDI::pitchbend_t pb);
209 void encoder_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);
210 /* void fader_handler (MIDI::Parser &, MIDI::EventTwoBytes* tb);*/
212 ButtonState button_state;
224 Button (CC121& f, std::string const& str, ButtonID i)
231 void set_action (std::string const& action_name, bool on_press, CC121::ButtonState = ButtonState (0));
232 void set_action (boost::function<void()> function, bool on_press, CC121::ButtonState = ButtonState (0));
233 std::string get_action (bool press, CC121::ButtonState bs = ButtonState (0));
235 void set_led_state (boost::shared_ptr<MIDI::Port>, bool onoff);
236 void invoke (ButtonState bs, bool press);
237 bool uses_flash () const { return flash; }
238 void set_flash (bool yn) { flash = yn; }
240 XMLNode& get_state () const;
241 int set_state (XMLNode const&);
243 sigc::connection timeout_connection;
253 /* could be a union if boost::function didn't require a
256 std::string action_name;
257 boost::function<void()> function;
260 typedef std::map<CC121::ButtonState,ToDo> ToDoMap;
265 typedef std::map<ButtonID,Button> ButtonMap;
268 Button& get_button (ButtonID) const;
270 std::set<ButtonID> buttons_down;
271 std::set<ButtonID> consumed;
273 void all_lights_out ();
275 void start_midi_handling ();
276 void stop_midi_handling ();
278 PBD::ScopedConnectionList session_connections;
279 void connect_session_signals ();
280 void map_recenable_state ();
281 void map_transport_state ();
283 sigc::connection periodic_connection;
286 sigc::connection heartbeat_connection;
287 sigc::connection blink_connection;
288 typedef std::list<ButtonID> Blinkers;
293 void start_blinking (ButtonID);
294 void stop_blinking (ButtonID);
296 void set_current_stripable (boost::shared_ptr<ARDOUR::Stripable>);
297 void drop_current_stripable ();
300 void stripable_selection_changed ();
301 PBD::ScopedConnection selection_connection;
302 PBD::ScopedConnectionList stripable_connections;
304 void map_stripable_state ();
307 bool rec_enable_state;
308 void map_recenable ();
312 void map_monitoring ();
314 /* operations (defined in operations.cc) */
319 void input_monitor ();
333 void set_controllable (boost::shared_ptr<ARDOUR::AutomationControl>, float);
340 #endif /* ardour_surface_cc121_h */