summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2013-01-07 18:28:09 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2013-01-07 18:28:09 +0000
commit02092679808718c993e741f7328a33888ddc294c (patch)
tree79548571062cfcb555886b42860321e2bad45636 /libs
parent6e0fc35806a99a91a09980e26a4d53b9d5331657 (diff)
reinstate wiimote support, thanks to work by jannis pohlmann
git-svn-id: svn://localhost/ardour2/branches/3.0@13796 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/debug.h1
-rw-r--r--libs/ardour/debug.cc1
-rw-r--r--libs/surfaces/wiimote/interface.cc68
-rw-r--r--libs/surfaces/wiimote/wiimote.cc569
-rw-r--r--libs/surfaces/wiimote/wiimote.h117
-rw-r--r--libs/surfaces/wiimote/wscript9
-rw-r--r--libs/surfaces/wscript20
7 files changed, 482 insertions, 303 deletions
diff --git a/libs/ardour/ardour/debug.h b/libs/ardour/ardour/debug.h
index dd76f14603..202d0cc424 100644
--- a/libs/ardour/ardour/debug.h
+++ b/libs/ardour/ardour/debug.h
@@ -62,6 +62,7 @@ namespace PBD {
extern uint64_t TempoMap;
extern uint64_t OrderKeys;
extern uint64_t Automation;
+ extern uint64_t WiimoteControl;
}
}
diff --git a/libs/ardour/debug.cc b/libs/ardour/debug.cc
index 36c9b6adb0..afd5da2169 100644
--- a/libs/ardour/debug.cc
+++ b/libs/ardour/debug.cc
@@ -59,5 +59,6 @@ uint64_t PBD::DEBUG::TempoMath = PBD::new_debug_bit ("tempomath");
uint64_t PBD::DEBUG::TempoMap = PBD::new_debug_bit ("tempomap");
uint64_t PBD::DEBUG::OrderKeys = PBD::new_debug_bit ("orderkeys");
uint64_t PBD::DEBUG::Automation = PBD::new_debug_bit ("automation");
+uint64_t PBD::DEBUG::WiimoteControl = PBD::new_debug_bit ("wiimotecontrol");
diff --git a/libs/surfaces/wiimote/interface.cc b/libs/surfaces/wiimote/interface.cc
index 5f622d5c09..318bc40adf 100644
--- a/libs/surfaces/wiimote/interface.cc
+++ b/libs/surfaces/wiimote/interface.cc
@@ -1,52 +1,50 @@
-#include <pbd/failed_constructor.h>
+/*
+ Copyright (C) 2009-2013 Paul Davis
+ Authors: Sampo Savolainen, Jannis Pohlmann
-#include "control_protocol/control_protocol.h"
-#include "wiimote.h"
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "pbd/failed_constructor.h"
+#include "pbd/error.h"
#include "ardour/session.h"
+#include "control_protocol/control_protocol.h"
-using namespace ARDOUR;
+#include "wiimote.h"
-static WiimoteControlProtocol *foo;
+using namespace ARDOUR;
+using namespace PBD;
ControlProtocol*
-new_wiimote_protocol (ControlProtocolDescriptor* descriptor, Session* s)
+new_wiimote_protocol (ControlProtocolDescriptor*, Session* s)
{
- WiimoteControlProtocol* wmcp;
-
- try {
- wmcp = new WiimoteControlProtocol (*s);
- } catch (failed_constructor& err) {
- return 0;
- }
-
- if (wmcp-> set_active (true)) {
- delete wmcp;
- return 0;
- }
-
- foo = wmcp;
-
+ WiimoteControlProtocol* wmcp = new WiimoteControlProtocol (*s);
+ wmcp->set_active (true);
return wmcp;
}
void
-wiimote_control_protocol_cwiid_callback(cwiid_wiimote_t *wiimote, int mesg_count, union cwiid_mesg mesg[], struct timespec *t)
+delete_wiimote_protocol (ControlProtocolDescriptor* /*descriptor*/, ControlProtocol* cp)
{
- assert(foo != 0);
-
- foo->wiimote_callback(wiimote,mesg_count,mesg,t);
-}
-
-void
-delete_wiimote_protocol (ControlProtocolDescriptor* descriptor, ControlProtocol* cp)
-{
- foo = 0;
delete cp;
}
bool
-probe_wiimote_protocol (ControlProtocolDescriptor* descriptor)
+probe_wiimote_protocol (ControlProtocolDescriptor*)
{
return WiimoteControlProtocol::probe ();
}
@@ -62,12 +60,14 @@ static ControlProtocolDescriptor wiimote_descriptor = {
initialize : new_wiimote_protocol,
destroy : delete_wiimote_protocol
};
-
+
extern "C" {
-ControlProtocolDescriptor*
+
+ControlProtocolDescriptor*
protocol_descriptor () {
return &wiimote_descriptor;
}
+
}
diff --git a/libs/surfaces/wiimote/wiimote.cc b/libs/surfaces/wiimote/wiimote.cc
index 26f7e1810f..68f2125dcb 100644
--- a/libs/surfaces/wiimote/wiimote.cc
+++ b/libs/surfaces/wiimote/wiimote.cc
@@ -1,291 +1,460 @@
-#include "wiimote.h"
+/*
+ Copyright (C) 2009-2013 Paul Davis
+ Authors: Sampo Savolainen, Jannis Pohlmann
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
#include <iostream>
-#include <sigc++/bind.h>
-#include "pbd/xml++.h"
+#include "pbd/compose.h"
+#include "pbd/error.h"
+#include "ardour/debug.h"
#include "ardour/session.h"
-
#include "i18n.h"
+#include "wiimote.h"
using namespace ARDOUR;
using namespace PBD;
+using namespace std;
+
+#include "pbd/abstract_ui.cc" // instantiate template
-void wiimote_control_protocol_cwiid_callback(cwiid_wiimote_t *wiimote, int mesg_count, union cwiid_mesg mesg[], struct timespec *t);
+void wiimote_control_protocol_mesg_callback (cwiid_wiimote_t *wiimote, int mesg_count, union cwiid_mesg mesg[], timespec *t);
-uint16_t WiimoteControlProtocol::button_state = 0;
+WiimoteControlProtocol::WiimoteControlProtocol (Session& session)
+ : ControlProtocol (session, X_("Wiimote"))
+ , AbstractUI<WiimoteControlUIRequest> ("wiimote")
+ , wiimote (0)
+ , idle_source (0)
+ , button_state (0)
+ , callback_thread_registered (false)
+{
+}
-WiimoteControlProtocol::WiimoteControlProtocol ( Session & session)
- : ControlProtocol ( session, "Wiimote"),
- main_thread_quit (false),
- restart_discovery (false),
- callback_thread_registered_for_ardour (false),
- wiimote_handle (0)
+WiimoteControlProtocol::~WiimoteControlProtocol ()
{
- main_thread = Glib::Thread::create( sigc::mem_fun(*this, &WiimoteControlProtocol::wiimote_main), true);
+ stop ();
}
-WiimoteControlProtocol::~WiimoteControlProtocol()
+bool
+WiimoteControlProtocol::probe ()
{
- main_thread_quit = true;
- slot_cond.signal();
- main_thread->join();
+ return true;
+}
- if (wiimote_handle) {
- cwiid_close(wiimote_handle);
+int
+WiimoteControlProtocol::set_active (bool yn)
+{
+ int result;
+
+ DEBUG_TRACE (DEBUG::WiimoteControl, string_compose ("WiimoteControlProtocol::set_active init with yn: '%1'\n", yn));
+
+ /* do nothing if the active state is not changing */
+ if (yn == _active) {
+ return 0;
}
- std::cerr << "Wiimote: closed" << std::endl;
+ if (yn) {
+ /* activate Wiimote control surface */
+ result = start ();
+ } else {
+ /* deactivate Wiimote control surface */
+ result = stop ();
+ }
+
+ /* remember new active state */
+ _active = yn;
+
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::set_active done\n");
+
+ return result;
}
-bool
-WiimoteControlProtocol::probe()
+XMLNode&
+WiimoteControlProtocol::get_state ()
{
- return true;
+ XMLNode *node = new XMLNode ("Protocol");
+ node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
+ node->add_property (X_("feedback"), "0");
+ return *node;
+}
+
+int
+WiimoteControlProtocol::set_state (const XMLNode&, int)
+{
+ return 0;
}
void
-WiimoteControlProtocol::wiimote_callback(cwiid_wiimote_t *wiimote, int mesg_count, union cwiid_mesg mesg[], struct timespec *t)
+WiimoteControlProtocol::do_request (WiimoteControlUIRequest* req)
{
- int i;
- uint16_t b;
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::do_request init\n");
- if (!callback_thread_registered_for_ardour) {
- register_thread("Wiimote Control Protocol");
- callback_thread_registered_for_ardour = true;
+ if (req->type == CallSlot) {
+ call_slot (MISSING_INVALIDATOR, req->the_slot);
+ } else if (req->type == Quit) {
+ stop ();
}
- for (i=0; i < mesg_count; i++)
- {
- if (mesg[i].type == CWIID_MESG_ERROR) {
- std::cerr << "Wiimote: disconnect" << std::endl;
- restart_discovery = true;
- slot_cond.signal();
- return;
- }
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::do_request done\n");
+}
- if (mesg[i].type != CWIID_MESG_BTN) continue;
+int
+WiimoteControlProtocol::start ()
+{
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::start init\n");
- // what buttons are pressed down which weren't pressed down last time
- b = (mesg[i].btn_mesg.buttons ^ button_state) & mesg[i].btn_mesg.buttons;
+ // update LEDs whenever the transport or recording state changes
+ session->TransportStateChange.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&WiimoteControlProtocol::update_led_state, this), this);
+ session->RecordStateChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&WiimoteControlProtocol::update_led_state, this), this);
- button_state = mesg[i].btn_mesg.buttons;
-
- // if B is pressed down
- if (button_state & CWIID_BTN_B) {
- if (b & CWIID_BTN_A) { // B is down and A is pressed
- access_action("Transport/ToggleRollForgetCapture");
- }
+ // start the Wiimote control UI; it will run in its own thread context
+ BaseUI::run ();
- if (b & CWIID_BTN_LEFT) {
- access_action("Editor/playhead-to-previous-region-boundary");
- }
- if (b & CWIID_BTN_RIGHT) {
- access_action("Editor/playhead-to-next-region-boundary");
- }
- if (b & CWIID_BTN_UP) {
- next_marker();
- }
- if (b & CWIID_BTN_DOWN) {
- prev_marker();
- }
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::start done\n");
- if (b & CWIID_BTN_HOME) {
- access_action("Editor/add-location-from-playhead");
- }
+ return 0;
+}
- if (b & CWIID_BTN_MINUS) {
- access_action("Transport/GotoStart");
- }
-
- if (b & CWIID_BTN_PLUS) {
- access_action("Transport/GotoEnd");
- }
+int
+WiimoteControlProtocol::stop ()
+{
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::stop init\n");
- continue;
- }
+ // stop wiimote discovery, just in case
+ stop_wiimote_discovery ();
+ // close and reset the wiimote handle
+ if (wiimote) {
+ cwiid_close (wiimote);
+ wiimote = 0;
+ callback_thread_registered = false;
+ }
- if (b & CWIID_BTN_A) {
- access_action("Transport/ToggleRoll");
- }
+ // stop the Wiimote control UI
+ BaseUI::quit ();
- if (b & CWIID_BTN_1) { // 1
- access_action("Editor/track-record-enable-toggle");
- }
- if (b & CWIID_BTN_2) { // 2
- rec_enable_toggle();
- }
+ // no longer update the LEDs
+ session_connections.drop_connections ();
- // d-pad
- if (b & CWIID_BTN_LEFT) { // left
- access_action("Editor/nudge-playhead-backward");
- }
- if (b & CWIID_BTN_RIGHT) { // right
- access_action("Editor/nudge-playhead-forward");
- }
- if (b & CWIID_BTN_DOWN) { // down
- access_action("Editor/select-next-route");
- }
- if (b & CWIID_BTN_UP) { // up
- access_action("Editor/select-prev-route");
- }
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::stop done\n");
+ return 0;
+}
- if (b & CWIID_BTN_PLUS) { // +
- access_action("Editor/temporal-zoom-in");
- }
- if (b & CWIID_BTN_MINUS) { // -
- access_action("Editor/temporal-zoom-out");
- }
- if (b & CWIID_BTN_HOME) { // "home"
- // no op, yet. any suggestions?
- access_action("Editor/playhead-to-edit");
- }
+void
+WiimoteControlProtocol::thread_init ()
+{
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::thread_init init\n");
- }
+ pthread_set_name (X_("wiimote"));
+
+ // allow to make requests to the GUI and RT thread(s)
+ PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self (), X_("wiimote"), 2048);
+ BasicUI::register_thread ("wiimote");
+
+ // connect a Wiimote
+ start_wiimote_discovery ();
+
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::thread_init done\n");
}
void
-WiimoteControlProtocol::update_led_state()
+WiimoteControlProtocol::start_wiimote_discovery ()
{
- ENSURE_WIIMOTE_THREAD(sigc::mem_fun(*this, &WiimoteControlProtocol::update_led_state));
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::start_wiimote_discovery init\n");
- uint8_t state = 0;
+ // connect to the Wiimote using an idle source
+ Glib::RefPtr<Glib::IdleSource> source = Glib::IdleSource::create ();
+ source->connect (sigc::mem_fun (*this, &WiimoteControlProtocol::connect_idle));
+ source->attach (_main_loop->get_context ());
- if (session->transport_rolling()) {
- state |= CWIID_LED1_ON;
- }
+ // grab a reference on the underlying idle source to keep it around
+ idle_source = source->gobj ();
+ g_source_ref (idle_source);
- if (session->actively_recording()) {
- state |= CWIID_LED4_ON;
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::start_wiimote_discovery done\n");
+}
+
+void
+WiimoteControlProtocol::stop_wiimote_discovery ()
+{
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::stop_wiimote_discovery init\n");
+
+ if (idle_source) {
+ g_source_unref (idle_source);
+ idle_source = 0;
}
- cwiid_set_led(wiimote_handle, state);
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::stop_wiimote_discovery done\n");
}
-void
-WiimoteControlProtocol::_wiimote_main ()
+bool
+WiimoteControlProtocol::connect_idle ()
{
- bdaddr_t bdaddr;
- unsigned char rpt_mode = 0;
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::connect_idle init\n");
- register_thread ("Wiimote");
+ bool retry = true;
-wiimote_discovery:
+ if (connect_wiimote ()) {
+ stop_wiimote_discovery ();
+ retry = false;
+ }
- std::cerr << "Wiimote: discovering, press 1+2" << std::endl;
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::connect_idle done\n");
- while (!wiimote_handle && !main_thread_quit) {
- bdaddr = (bdaddr_t) {{0, 0, 0, 0, 0, 0}};
- callback_thread_registered_for_ardour = false;
- wiimote_handle = cwiid_open(&bdaddr, 0);
+ return retry;
+}
- if (!wiimote_handle && !main_thread_quit) {
- sleep(1);
- // We don't know whether the issue was a timeout or a configuration
- // issue
- }
+bool
+WiimoteControlProtocol::connect_wiimote ()
+{
+ // abort the discovery and do nothing else if we already have a Wiimote
+ if (wiimote) {
+ return true;
}
- if (main_thread_quit) {
- // The corner case where the wiimote is bound at the same time as
- // the control protocol is destroyed
- if (wiimote_handle) {
- cwiid_close(wiimote_handle);
+ bool success = true;
+
+ // if we don't have a Wiimote yet, try to discover it; if that
+ // fails, wait for a short period of time and try again
+ if (!wiimote) {
+ cerr << "Wiimote: Not discovered yet, press 1+2 to connect" << endl;
+
+ bdaddr_t bdaddr = {{ 0, 0, 0, 0, 0, 0 }};
+ wiimote = cwiid_open (&bdaddr, 0);
+ callback_thread_registered = false;
+ if (!wiimote) {
+ success = false;
+ } else {
+ // a Wiimote was discovered
+ cerr << "Wiimote: Connected successfully" << endl;
+
+ // attach the WiimoteControlProtocol object to the Wiimote handle
+ if (cwiid_set_data (wiimote, this)) {
+ cerr << "Wiimote: Failed to attach control protocol" << endl;
+ success = false;
+ }
+
+ // clear the last button state to start processing events cleanly
+ button_state = 0;
}
- wiimote_handle = 0;
+ }
- std::cerr << "Wiimote Control Protocol stopped before connected to a wiimote" << std::endl;
- return;
+ // enable message based communication with the Wiimote
+ if (success && cwiid_enable (wiimote, CWIID_FLAG_MESG_IFC)) {
+ cerr << "Wiimote: Failed to enable message based communication" << endl;
+ success = false;
}
- std::cerr << "Wiimote: connected" << std::endl;
- WiimoteControlProtocol::button_state = 0;
+ // enable button events to be received from the Wiimote
+ if (success && cwiid_command (wiimote, CWIID_CMD_RPT_MODE, CWIID_RPT_BTN)) {
+ cerr << "Wiimote: Failed to enable button events" << endl;
+ success = false;
+ }
- if (cwiid_enable(wiimote_handle, CWIID_FLAG_REPEAT_BTN)) {
- std::cerr << "cwiid_enable(), error" << std::endl;
- cwiid_close(wiimote_handle);
- wiimote_handle = 0;
- return;
+ // receive an event for every single button pressed, not just when
+ // a different button was pressed than before
+ if (success && cwiid_enable (wiimote, CWIID_FLAG_REPEAT_BTN)) {
+ cerr << "Wiimote: Failed to enable repeated button events" << endl;
+ success = false;
}
- if (cwiid_set_mesg_callback(wiimote_handle, wiimote_control_protocol_cwiid_callback)) {
- std::cerr << "cwiid_set_mesg_callback(), couldn't connect callback" << std::endl;
- cwiid_close(wiimote_handle);
- wiimote_handle = 0;
- return;
- }
- if (cwiid_command(wiimote_handle, CWIID_CMD_RPT_MODE, CWIID_RPT_BTN)) {
- std::cerr << "cwiid_command(), RPT_MODE error" << std::endl;
- cwiid_close(wiimote_handle);
- wiimote_handle = 0;
+
+ // be notified of new input events
+ if (success && cwiid_set_mesg_callback (wiimote, wiimote_control_protocol_mesg_callback)) {
+ }
+
+ // reset Wiimote handle if the configuration failed
+ if (!success && wiimote) {
+ cwiid_close (wiimote);
+ wiimote = 0;
+ callback_thread_registered = false;
+ }
+
+ return success;
+}
+
+void
+WiimoteControlProtocol::update_led_state ()
+{
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::update_led_state init\n");
+
+ uint8_t state = 0;
+
+ // do nothing if we do not have a Wiimote
+ if (!wiimote) {
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::update_led_state no wiimote connected\n");
return;
}
- rpt_mode |= CWIID_RPT_BTN;
- cwiid_enable(wiimote_handle, CWIID_FLAG_MESG_IFC);
- cwiid_set_rpt_mode(wiimote_handle, rpt_mode);
+ // enable LED1 if Ardour is playing
+ if (session->transport_rolling ()) {
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::update_led_state playing, activate LED1\n");
+ state |= CWIID_LED1_ON;
+ }
- transport_state_conn = session->TransportStateChange.connect(sigc::mem_fun(*this, &WiimoteControlProtocol::update_led_state));
- record_state_conn = session->RecordStateChanged.connect(sigc::mem_fun(*this, &WiimoteControlProtocol::update_led_state));
+ // enable LED4 if Ardour is recording
+ if (session->actively_recording ()) {
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::update_led_state recording, activate LED4\n");
+ state |= CWIID_LED4_ON;
+ }
- std::cerr << "Wiimote: initialization done, waiting for callbacks / quit" << std::endl;
+ // apply the LED state
+ cwiid_set_led (wiimote, state);
+
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::update_led_state done\n");
+}
- while (!main_thread_quit) {
- slot_mutex.lock();
- while (slot_list.empty() && !main_thread_quit && !restart_discovery)
- slot_cond.wait(slot_mutex);
+void
+WiimoteControlProtocol::wiimote_callback (int mesg_count, union cwiid_mesg mesg[])
+{
+ // register the cwiid callback thread if that hasn't happened yet
+ if (!callback_thread_registered) {
+ BasicUI::register_thread ("wiimote callback");
+ callback_thread_registered = true;
+ }
- if (main_thread_quit) {
- slot_mutex.unlock();
- break;
+ for (int i = 0; i < mesg_count; i++) {
+ // restart Wiimote discovery when receiving errors
+ if (mesg[i].type == CWIID_MESG_ERROR) {
+ cerr << "Wiimote: disconnected" << endl;
+ cwiid_close (wiimote);
+ wiimote = 0;
+ callback_thread_registered = false;
+ start_wiimote_discovery ();
+ return;
}
- if (restart_discovery) {
- std::cerr << "Wiimote: closing wiimote and restarting discovery" << std::endl;
- if (wiimote_handle) {
- cwiid_close(wiimote_handle);
- wiimote_handle = 0;
- }
- slot_mutex.unlock();
- restart_discovery = false;
- goto wiimote_discovery;
+ // skip non-button events
+ if (mesg[i].type != CWIID_MESG_BTN) {
+ continue;
}
- sigc::slot<void> call_me = *slot_list.begin();
- slot_list.pop_front();
- slot_mutex.unlock();
+ // drop buttons from the event that were already pressed before
+ uint16_t b = mesg[i].btn_mesg.buttons & ~button_state;
- call_me();
- }
+ // remember new button state
+ button_state = mesg[i].btn_mesg.buttons;
+ if (button_state & CWIID_BTN_B) {
+ // B + A = abort recording and jump back
+ if (b & CWIID_BTN_A) {
+ access_action ("Transport/ToggleRollForgetCapture");
+ }
- std::cerr << "Wiimote: main thread stopped" << std::endl;
- return 0;
-}
+ // B + left = move playhead to previous region boundary
+ if (b & CWIID_BTN_LEFT) {
+ access_action ("Editor/playhead-to-previous-region-boundary");
+ }
+ // B + right = move playhead to next region boundary
+ if (b & CWIID_BTN_RIGHT) {
+ access_action ("Editor/playhead-to-next-region-boundary");
+ }
-int
-WiimoteControlProtocol::set_active (bool yn)
-{
- // Let's not care about this just yet
- return 0;
+ // B + up = move playhead to next marker
+ if (b & CWIID_BTN_UP) {
+ next_marker ();
+ }
-}
+ // B + down = move playhead to prev marker
+ if (b & CWIID_BTN_DOWN) {
+ prev_marker ();
+ }
-XMLNode&
-WiimoteControlProtocol::get_state()
-{
- XMLNode *node = new XMLNode ("Protocol");
- node->add_property (X_("name"), _name);
- node->add_property (X_("feedback"), "0");
+ // B + Home = add marker at playhead
+ if (b & CWIID_BTN_HOME) {
+ access_action ("Editor/add-location-from-playhead");
+ }
- return *node;
+ // B + minus = move playhead to the start
+ if (b & CWIID_BTN_MINUS) {
+ access_action ("Transport/GotoStart");
+ }
+
+ // B + plus = move playhead to the end
+ if (b & CWIID_BTN_PLUS) {
+ access_action ("Transport/GotoEnd");
+ }
+ } else {
+ // A = toggle playback
+ if (b & CWIID_BTN_A) {
+ access_action ("Transport/ToggleRoll");
+ }
+
+ // 1 = toggle recording on the current track
+ if (b & CWIID_BTN_1) {
+ access_action ("Editor/track-record-enable-toggle");
+ }
+
+ // 2 = enable recording in general
+ if (b & CWIID_BTN_2) {
+ rec_enable_toggle ();
+ }
+
+ // left = move playhead back a bit
+ if (b & CWIID_BTN_LEFT) {
+ access_action ("Editor/nudge-playhead-backward");
+ }
+
+ // right = move playhead forward a bit
+ if (b & CWIID_BTN_RIGHT) {
+ access_action ("Editor/nudge-playhead-forward");
+ }
+
+ // up = select previous track
+ if (b & CWIID_BTN_UP) {
+ access_action ("Editor/select-prev-route");
+ }
+
+ // down = select next track
+ if (b & CWIID_BTN_DOWN) {
+ access_action ("Editor/select-next-route");
+ }
+
+ // + = zoom in
+ if (b & CWIID_BTN_PLUS) {
+ access_action ("Editor/temporal-zoom-in");
+ }
+
+ // - = zoom out
+ if (b & CWIID_BTN_MINUS) {
+ access_action ("Editor/temporal-zoom-out");
+ }
+
+ // home = no-op
+ if (b & CWIID_BTN_HOME) {
+ access_action ("Editor/playhead-to-edit");
+ }
+ }
+ }
}
-int
-WiimoteControlProtocol::set_state(const XMLNode& node)
+void
+wiimote_control_protocol_mesg_callback (cwiid_wiimote_t *wiimote, int mesg_count, union cwiid_mesg mesg[], timespec *)
{
- return 0;
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::mesg_callback init\n");
+
+ WiimoteControlProtocol *protocol = (WiimoteControlProtocol *)cwiid_get_data (wiimote);
+
+ if (protocol) {
+ protocol->wiimote_callback (mesg_count, mesg);
+ }
+
+ DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::mesg_callback done\n");
}
diff --git a/libs/surfaces/wiimote/wiimote.h b/libs/surfaces/wiimote/wiimote.h
index 4ab19749e5..f6ac8edc41 100644
--- a/libs/surfaces/wiimote/wiimote.h
+++ b/libs/surfaces/wiimote/wiimote.h
@@ -1,69 +1,76 @@
+/*
+ Copyright (C) 2009-2013 Paul Davis
+ Authors: Sampo Savolainen, Jannis Pohlmann
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
#ifndef ardour_wiimote_control_protocol_h
#define ardour_wiimote_control_protocol_h
+#include <cwiid.h>
+
+#include "pbd/abstract_ui.h"
#include "ardour/types.h"
#include "control_protocol/control_protocol.h"
-#include <glibmm/threads.h>
+struct WiimoteControlUIRequest : public BaseUI::BaseRequestObject {
+public:
+ WiimoteControlUIRequest () {}
+ ~WiimoteControlUIRequest () {}
+};
+
+class WiimoteControlProtocol
+ : public ARDOUR::ControlProtocol
+ , public AbstractUI<WiimoteControlUIRequest>
+{
+public:
+ WiimoteControlProtocol (ARDOUR::Session &);
+ virtual ~WiimoteControlProtocol ();
-#include "pbd/abstract_ui.h"
+ static bool probe ();
+ int set_active (bool yn);
-#include <cwiid.h>
+ XMLNode& get_state ();
+ int set_state (const XMLNode&, int version);
+ void start_wiimote_discovery ();
+ void stop_wiimote_discovery ();
-namespace ARDOUR {
- class Session;
-}
-
-#define ENSURE_WIIMOTE_THREAD(slot) \
- if (Glib::Threads::Thread::self() != main_thread) { \
- slot_mutex.lock();\
- slot_list.push_back(slot);\
- slot_cond.signal();\
- slot_mutex.unlock();\
- return;\
- }
-
-
-class WiimoteControlProtocol : public ARDOUR::ControlProtocol {
- public:
- WiimoteControlProtocol (ARDOUR::Session &);
- virtual ~WiimoteControlProtocol ();
-
- static bool probe();
-
- int set_active (bool yn);
- XMLNode& get_state();
- int set_state(const XMLNode&);
-
- void wiimote_callback(cwiid_wiimote_t *, int, union cwiid_mesg [],
- struct timespec *);
-
- private:
-
- void wiimote_main();
- volatile bool main_thread_quit;
- volatile bool restart_discovery;
-
- Glib::Threads::Thread *main_thread;
-
- void update_led_state();
-
- bool callback_thread_registered_for_ardour;
-
- static uint16_t button_state;
-
- cwiid_wiimote_t *wiimote_handle;
-
- Glib::Threads::Cond slot_cond;
- Glib::Threads::Mutex slot_mutex;
-
- std::list< sigc::slot<void> > slot_list;
-
- sigc::connection transport_state_conn;
- sigc::connection record_state_conn;
-};
+ void wiimote_callback (int mesg_count, union cwiid_mesg mesg[]);
+
+protected:
+ void do_request (WiimoteControlUIRequest*);
+ int start ();
+ int stop ();
+ void thread_init ();
+
+ bool connect_idle ();
+ bool connect_wiimote ();
+
+ void update_led_state ();
+
+protected:
+ PBD::ScopedConnectionList session_connections;
+ cwiid_wiimote_t* wiimote;
+ GSource *idle_source;
+ uint16_t button_state;
+ bool callback_thread_registered;
+};
#endif /* ardour_wiimote_control_protocol_h */
diff --git a/libs/surfaces/wiimote/wscript b/libs/surfaces/wiimote/wscript
index 3fbea7e248..3a4bd109c2 100644
--- a/libs/surfaces/wiimote/wscript
+++ b/libs/surfaces/wiimote/wscript
@@ -26,10 +26,11 @@ def build(bld):
'''
obj.export_includes = ['./wiimote']
obj.cxxflags = '-DPACKAGE="ardour_wiimote"'
- obj.includes = ['.', './wiimote']
- obj.name = 'libwiimote'
- obj.target = 'wiimote'
- obj.use = 'libardour libardour_cp'
+ obj.includes = ['.', '../libs']
+ obj.name = 'libardour_wiimote'
+ obj.target = 'ardour_wiimote'
+ obj.uselib = 'GTKMM CWIID'
+ obj.use = 'libardour libardour_cp libgtkmm2ext'
obj.vnum = LIBARDOUR_WIIMOTE_LIB_VERSION
obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3', 'surfaces')
diff --git a/libs/surfaces/wscript b/libs/surfaces/wscript
index 57770340b8..20ad07d60f 100644
--- a/libs/surfaces/wscript
+++ b/libs/surfaces/wscript
@@ -51,16 +51,16 @@ def configure(conf):
conf.check_cc (header_name='linux/input.h', define_name='BUILD_POWERMATE',mandatory=False)
autowaf.check_pkg (conf, 'liblo', mandatory=False, uselib_store="LO", atleast_version="0.24")
- if Options.options.wiimote:
- conf.check_cc (header_name='cwiid.h', define_name='HAVE_CWIID_H')
- if not conf.is_defined('HAVE_CWIID_H'):
- print('WIIMOTE configured but you are missing libcwiid!')
- sys.exit(1)
- conf.check_cc (header_name='bluetooth/bluetooth.h', define_name='HAVE_BLUETOOTH_H')
- if not conf.is_defined('HAVE_BLUETOOTH_H'):
- print('WIIMOTE configured but you are missing the libbluetooth headers needed to compile wiimote support!')
- sys.exit(1)
- conf.define ('BUILD_WIIMOTE', 1)
+ conf.check_cc (header_name='cwiid.h', define_name='HAVE_CWIID_H',mandatory=False)
+ if conf.is_defined('HAVE_CWIID_H'):
+ conf.check_cc (header_name='bluetooth/bluetooth.h', define_name='HAVE_BLUETOOTH_H',mandatory=False)
+ if conf.is_defined('HAVE_BLUETOOTH_H'):
+ autowaf.check_pkg(conf, 'cwiid', uselib_store='CWIID', atleast_version='0.6.00')
+ conf.define ('BUILD_WIIMOTE', 1)
+ else:
+ print('You are missing the libbluetooth headers needed to compile wiimote support')
+ else:
+ print('You are missing the cwiid headers needed to compile wiimote support')
def build(bld):
bld.recurse('control_protocol')