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);
38 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;
173 register_thread("Wiimote Discovery and Callback Thread");
177 std::cerr << "Wiimote: discovering, press 1+2" << std::endl;
179 while (!wiimote_handle && !main_thread_quit) {
180 bdaddr = *BDADDR_ANY;
181 callback_thread_registered_for_ardour = false;
182 wiimote_handle = cwiid_open(&bdaddr, 0);
184 if (!wiimote_handle && !main_thread_quit) {
186 // We don't know whether the issue was a timeout or a configuration
191 if (main_thread_quit) {
192 // The corner case where the wiimote is bound at the same time as
193 // the control protocol is destroyed
194 if (wiimote_handle) {
195 cwiid_close(wiimote_handle);
199 std::cerr << "Wiimote Control Protocol stopped before connected to a wiimote" << std::endl;
203 std::cerr << "Wiimote: connected" << std::endl;
204 WiimoteControlProtocol::button_state = 0;
206 if (cwiid_enable(wiimote_handle, CWIID_FLAG_REPEAT_BTN)) {
207 std::cerr << "cwiid_enable(), error" << std::endl;
208 cwiid_close(wiimote_handle);
212 if (cwiid_set_mesg_callback(wiimote_handle, wiimote_control_protocol_cwiid_callback)) {
213 std::cerr << "cwiid_set_mesg_callback(), couldn't connect callback" << std::endl;
214 cwiid_close(wiimote_handle);
218 if (cwiid_command(wiimote_handle, CWIID_CMD_RPT_MODE, CWIID_RPT_BTN)) {
219 std::cerr << "cwiid_command(), RPT_MODE error" << std::endl;
220 cwiid_close(wiimote_handle);
225 rpt_mode |= CWIID_RPT_BTN;
226 cwiid_enable(wiimote_handle, CWIID_FLAG_MESG_IFC);
227 cwiid_set_rpt_mode(wiimote_handle, rpt_mode);
229 transport_state_conn = session->TransportStateChange.connect(sigc::mem_fun(*this, &WiimoteControlProtocol::update_led_state));
230 record_state_conn = session->RecordStateChanged.connect(sigc::mem_fun(*this, &WiimoteControlProtocol::update_led_state));
232 std::cerr << "Wiimote: initialization done, waiting for callbacks / quit" << std::endl;
234 while (!main_thread_quit) {
236 while (slot_list.empty() && !main_thread_quit && !restart_discovery)
237 slot_cond.wait(slot_mutex);
239 if (main_thread_quit) {
244 if (restart_discovery) {
245 std::cerr << "Wiimote: closing wiimote and restarting discovery" << std::endl;
246 if (wiimote_handle) {
247 cwiid_close(wiimote_handle);
251 restart_discovery = false;
252 goto wiimote_discovery;
255 sigc::slot<void> call_me = *slot_list.begin();
256 slot_list.pop_front();
263 std::cerr << "Wiimote: main thread stopped" << std::endl;
268 WiimoteControlProtocol::set_active (bool yn)
270 // Let's not care about this just yet
276 WiimoteControlProtocol::get_state()
278 XMLNode *node = new XMLNode ("Protocol");
279 node->add_property (X_("name"), _name);
280 node->add_property (X_("feedback"), "0");
286 WiimoteControlProtocol::set_state(const XMLNode& node)