4 #include <sigc++/bind.h>
7 #include "ardour/session.h"
12 using namespace ARDOUR
;
15 void wiimote_control_protocol_cwiid_callback(cwiid_wiimote_t
*wiimote
, int mesg_count
, union cwiid_mesg mesg
[], struct timespec
*t
);
17 uint16_t WiimoteControlProtocol::button_state
= 0;
19 WiimoteControlProtocol::WiimoteControlProtocol ( Session
& session
)
20 : ControlProtocol ( session
, "Wiimote"),
21 main_thread_quit (false),
22 restart_discovery (false),
23 callback_thread_registered_for_ardour (false),
26 main_thread
= Glib::Thread::create( sigc::mem_fun(*this, &WiimoteControlProtocol::wiimote_main
), true);
29 WiimoteControlProtocol::~WiimoteControlProtocol()
31 main_thread_quit
= true;
36 cwiid_close(wiimote_handle
);
39 std::cerr
<< "Wiimote: closed" << std::endl
;
43 WiimoteControlProtocol::probe()
49 WiimoteControlProtocol::wiimote_callback(cwiid_wiimote_t
*wiimote
, int mesg_count
, union cwiid_mesg mesg
[], struct timespec
*t
)
54 if (!callback_thread_registered_for_ardour
) {
55 register_thread("Wiimote Control Protocol");
56 callback_thread_registered_for_ardour
= true;
59 for (i
=0; i
< mesg_count
; i
++)
61 if (mesg
[i
].type
== CWIID_MESG_ERROR
) {
62 std::cerr
<< "Wiimote: disconnect" << std::endl
;
63 restart_discovery
= true;
68 if (mesg
[i
].type
!= CWIID_MESG_BTN
) continue;
70 // what buttons are pressed down which weren't pressed down last time
71 b
= (mesg
[i
].btn_mesg
.buttons
^ button_state
) & mesg
[i
].btn_mesg
.buttons
;
73 button_state
= mesg
[i
].btn_mesg
.buttons
;
75 // if B is pressed down
76 if (button_state
& CWIID_BTN_B
) {
77 if (b
& CWIID_BTN_A
) { // B is down and A is pressed
78 access_action("Transport/ToggleRollForgetCapture");
81 if (b
& CWIID_BTN_LEFT
) {
82 access_action("Editor/playhead-to-previous-region-boundary");
84 if (b
& CWIID_BTN_RIGHT
) {
85 access_action("Editor/playhead-to-next-region-boundary");
87 if (b
& CWIID_BTN_UP
) {
90 if (b
& CWIID_BTN_DOWN
) {
94 if (b
& CWIID_BTN_HOME
) {
95 access_action("Editor/add-location-from-playhead");
98 if (b
& CWIID_BTN_MINUS
) {
99 access_action("Transport/GotoStart");
102 if (b
& CWIID_BTN_PLUS
) {
103 access_action("Transport/GotoEnd");
110 if (b
& CWIID_BTN_A
) {
111 access_action("Transport/ToggleRoll");
114 if (b
& CWIID_BTN_1
) { // 1
115 access_action("Editor/track-record-enable-toggle");
117 if (b
& CWIID_BTN_2
) { // 2
122 if (b
& CWIID_BTN_LEFT
) { // left
123 access_action("Editor/nudge-playhead-backward");
125 if (b
& CWIID_BTN_RIGHT
) { // right
126 access_action("Editor/nudge-playhead-forward");
128 if (b
& CWIID_BTN_DOWN
) { // down
129 access_action("Editor/select-next-route");
131 if (b
& CWIID_BTN_UP
) { // up
132 access_action("Editor/select-prev-route");
136 if (b
& CWIID_BTN_PLUS
) { // +
137 access_action("Editor/temporal-zoom-in");
139 if (b
& CWIID_BTN_MINUS
) { // -
140 access_action("Editor/temporal-zoom-out");
142 if (b
& CWIID_BTN_HOME
) { // "home"
143 // no op, yet. any suggestions?
144 access_action("Editor/playhead-to-edit");
151 WiimoteControlProtocol::update_led_state()
153 ENSURE_WIIMOTE_THREAD(sigc::mem_fun(*this, &WiimoteControlProtocol::update_led_state
));
157 if (session
->transport_rolling()) {
158 state
|= CWIID_LED1_ON
;
161 if (session
->actively_recording()) {
162 state
|= CWIID_LED4_ON
;
165 cwiid_set_led(wiimote_handle
, state
);
169 WiimoteControlProtocol::_wiimote_main ()
172 unsigned char rpt_mode
= 0;
174 register_thread ("Wiimote");
178 std::cerr
<< "Wiimote: discovering, press 1+2" << std::endl
;
180 while (!wiimote_handle
&& !main_thread_quit
) {
181 bdaddr
= (bdaddr_t
) {{0, 0, 0, 0, 0, 0}};
182 callback_thread_registered_for_ardour
= false;
183 wiimote_handle
= cwiid_open(&bdaddr
, 0);
185 if (!wiimote_handle
&& !main_thread_quit
) {
187 // We don't know whether the issue was a timeout or a configuration
192 if (main_thread_quit
) {
193 // The corner case where the wiimote is bound at the same time as
194 // the control protocol is destroyed
195 if (wiimote_handle
) {
196 cwiid_close(wiimote_handle
);
200 std::cerr
<< "Wiimote Control Protocol stopped before connected to a wiimote" << std::endl
;
204 std::cerr
<< "Wiimote: connected" << std::endl
;
205 WiimoteControlProtocol::button_state
= 0;
207 if (cwiid_enable(wiimote_handle
, CWIID_FLAG_REPEAT_BTN
)) {
208 std::cerr
<< "cwiid_enable(), error" << std::endl
;
209 cwiid_close(wiimote_handle
);
213 if (cwiid_set_mesg_callback(wiimote_handle
, wiimote_control_protocol_cwiid_callback
)) {
214 std::cerr
<< "cwiid_set_mesg_callback(), couldn't connect callback" << std::endl
;
215 cwiid_close(wiimote_handle
);
219 if (cwiid_command(wiimote_handle
, CWIID_CMD_RPT_MODE
, CWIID_RPT_BTN
)) {
220 std::cerr
<< "cwiid_command(), RPT_MODE error" << std::endl
;
221 cwiid_close(wiimote_handle
);
226 rpt_mode
|= CWIID_RPT_BTN
;
227 cwiid_enable(wiimote_handle
, CWIID_FLAG_MESG_IFC
);
228 cwiid_set_rpt_mode(wiimote_handle
, rpt_mode
);
230 transport_state_conn
= session
->TransportStateChange
.connect(sigc::mem_fun(*this, &WiimoteControlProtocol::update_led_state
));
231 record_state_conn
= session
->RecordStateChanged
.connect(sigc::mem_fun(*this, &WiimoteControlProtocol::update_led_state
));
233 std::cerr
<< "Wiimote: initialization done, waiting for callbacks / quit" << std::endl
;
235 while (!main_thread_quit
) {
237 while (slot_list
.empty() && !main_thread_quit
&& !restart_discovery
)
238 slot_cond
.wait(slot_mutex
);
240 if (main_thread_quit
) {
245 if (restart_discovery
) {
246 std::cerr
<< "Wiimote: closing wiimote and restarting discovery" << std::endl
;
247 if (wiimote_handle
) {
248 cwiid_close(wiimote_handle
);
252 restart_discovery
= false;
253 goto wiimote_discovery
;
256 sigc::slot
<void> call_me
= *slot_list
.begin();
257 slot_list
.pop_front();
264 std::cerr
<< "Wiimote: main thread stopped" << std::endl
;
270 WiimoteControlProtocol::set_active (bool yn
)
272 // Let's not care about this just yet
278 WiimoteControlProtocol::get_state()
280 XMLNode
*node
= new XMLNode ("Protocol");
281 node
->add_property (X_("name"), _name
);
282 node
->add_property (X_("feedback"), "0");
288 WiimoteControlProtocol::set_state(const XMLNode
& node
)