Ticket #53 (closed defect: fixed)

Opened 5 years ago

Last modified 4 years ago

Need some way to discover and connect to remotes with shorter timeouts, or asynchronously

Reported by: josh Owned by: dsmith
Priority: major Milestone:
Component: libcwiid Version: 0.6.00
Keywords: Cc:

Description

wiimote_open takes a long time to find and connect to a new Wiimote, which involves some very long delays (particularly when using 1+2 rather than the sync button). However, I want to connect several Wiimotes without knowing the number of Wiimotes or their bluetooth addresses in advance; I will use something like "Press A on any remote to stop looking for more remotes". I don't see any way with the current cwiid interfaces to do this elegantly.

First, even if I had the bluetooth addresses (such as from the cwiid bluetooth discovery functions), cwiid_open still takes a long time to connect. While connecting, I cannot watch for the A button on other remotes and abort. I also cannot discover and connect to new wiimotes in parallel, so the long timeouts run sequentially rather than concurrently.

Second, the bluetooth discovery functions themselves appear to have some long timeouts.

(If I have missed some other way to do this, my apologies; please let me know.)

Change History

Changed 5 years ago by josh

  • version 0.5.02 deleted
  • component changed from build system to libcwiid

Changed 5 years ago by dsmith

  • status changed from new to assigned
  • version set to 0.6.00

All valid complaints, partially due to my laziness, partially due to the crappy BlueZ interface, partially due to parts of the BlueZ interface that aren't crappy, but that the BlueZ guys can't be bothered to document (hey, I've only been distracted for a semester - they've had years). I'll take a look at reworking the interface with minimal impact to existing code.

Changed 5 years ago by yabbas

I've found using DBus methods to be more effective. Perhaps integrate this with CWiid?

/* Build with: */ /* glib-genmarshal --prefix=marshal marshal.list --header > marshal.h */ /* glib-genmarshal --prefix=marshal marshal.list --body > marshal.c */ /* gcc pkg-config --libs --cflags glib-2.0 dbus-1 dbus-glib-1 lswm.c marshal.c -o lswm */

#include <stdlib.h> #include <getopt.h> #include <dbus/dbus.h> #include <dbus/dbus-glib.h> #include <glib-object.h>

#include "marshal.h"

int verbose = 0, retwiimote = 1;

static GMainLoop *loop = NULL;

void print_usage(void) {

printf("lswm is a program that lists Wiimote bluetooth addresses\n"); printf("Usage: lswm [OPTIONS]...\n\n"); printf("Options:\n"); printf("\t-h, --help\t\tPrints this output.\n"); printf("\t-v, --version\t\tOutput version information and exit.\n"); printf("\t-l, --verbose\t\tVerbose output\n");

}

static void remote_device_found(DBusGProxy *object, const char *address, const unsigned int class, const int rssi, gpointer user_data) {

g_print("Signal: RemoteDeviceFound?(%s, %d, %d)\n", address, class, rssi);

}

static void discovery_started(DBusGProxy *object, gpointer user_data) {

g_print("Signal: DiscoveryStarted?()\n");

}

static void remote_name_updated(DBusGProxy *object, const char *address, const char *name, gpointer user_data) {

if (verbose) g_print("Signal: RemoteNameUpdated?(%s, %s)\n", address, name);

if(!strcmp(name, "Nintendo RVL-CNT-01") && retwiimote) {

printf("Found Wiimote at: "); setenv("WIIMOTE_BDADDR", address, 1); printf("%s\n", getenv("WIIMOTE_BDADDR"));

}

}

static void discovery_completed(DBusGProxy *object, gpointer user_data) {

if(verbose)

g_print("Signal: DiscoveryCompleted?()\n");

g_main_loop_quit (loop);

}

static void run_mainloop (void) {

GMainContext *ctx;

ctx = g_main_loop_get_context (loop);

while (g_main_context_pending (ctx))

g_main_context_iteration (ctx, FALSE);

}

int main(int argc, char* argv[]) {

int c;

/* Parse Options */ while (1) {

int option_index = 0;

static struct option long_options[] = {

{"help", 0, 0, 'h'}, {"version", 0, 0, 'v'}, {"verbose", 0, 0, 'l'}, {0, 0, 0, 0}

};

c = getopt_long (argc, argv, "hvc:dqr::w", long_options, &option_index);

if (c == -1) {

break;

}

switch (c) { case 'h':

print_usage(); return 0; break;

case 'v':

printf("lswm version %s\n", "1.0.0"); return 0; break;

case 'l':

verbose = 1; retwiimote = 0; break;

case '?':

printf("Try lswm --help for more information\n"); return 1; break;

default:

return -1; break;

}

}

GError *error = NULL; DBusGConnection * bus = NULL; DBusGProxy * obj = NULL;

g_type_init(); g_log_set_always_fatal (G_LOG_LEVEL_WARNING); loop = g_main_loop_new (NULL, FALSE);

bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); if (error != NULL) {

g_printerr("Connecting to system bus failed: %s\n", error->message); g_error_free(error); exit(EXIT_FAILURE);

}

obj = dbus_g_proxy_new_for_name(bus, "org.bluez", "/org/bluez/hci0", "org.bluez.Adapter");

dbus_g_object_register_marshaller(marshal_VOIDSTRING_UINT_INT, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INT, G_TYPE_INVALID); dbus_g_proxy_add_signal(obj, "RemoteDeviceFound?", G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INT, G_TYPE_INVALID); if (verbose) dbus_g_proxy_connect_signal(obj, "RemoteDeviceFound?", G_CALLBACK(remote_device_found), bus, NULL);

dbus_g_proxy_add_signal(obj, "DiscoveryStarted?", G_TYPE_INVALID); if (verbose) dbus_g_proxy_connect_signal(obj, "DiscoveryStarted?", G_CALLBACK(discovery_started), bus, NULL);

dbus_g_proxy_add_signal(obj, "DiscoveryCompleted?", G_TYPE_INVALID); if (verbose) dbus_g_proxy_connect_signal(obj, "DiscoveryCompleted?", G_CALLBACK(discovery_completed), bus, NULL);

dbus_g_object_register_marshaller(marshal_VOIDSTRING_STRING, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_add_signal(obj, "RemoteNameUpdated?", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID); dbus_g_proxy_connect_signal(obj, "RemoteNameUpdated?", G_CALLBACK(remote_name_updated), NULL, NULL);

dbus_g_proxy_call(obj, "DiscoverDevices?", &error, G_TYPE_INVALID, G_TYPE_INVALID); if (error != NULL) {

g_printerr("Failed to discover devices: %s\n", error->message); g_error_free(error); exit(EXIT_FAILURE);

}

run_mainloop (); dbus_g_connection_flush (bus); g_main_loop_run (loop); dbus_g_connection_unref(bus);

return 0;

}

Changed 4 years ago by dsmith

  • status changed from assigned to closed
  • resolution set to fixed

So, a few comments.

  1. I don't understand the need for DBUS, but I'm admittedly ignorant to what DBUS is for. I'll be glad to entertain arguments as to why it's all that.
  2. Passing the address to cwiid_open is almost immediate. I don't see a problem there.
  3. You're right - not passing an address to cwiid_open sucks. I've added a cwiid_open_timeout function with a timeout argument for finding wiimotes. r185
Note: See TracTickets for help on using tickets.