Heya,
First patch changes the SetOptions API to pass a{sv} instead of a{ss}
and modifies the GConf to actually use those integers.
The second patch fixes an object leak (we were leaking the GypsyDevice
object if we changed between devices whilst running), and adds support
for the BaudRate options.
Tested locally with gypsy master, and my crummy ND-100 USB GPS.
Cheers
>From d0bca5c1ae4befd200209da2864a457d0df784f2 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <[email protected]>
Date: Fri, 23 Apr 2010 17:12:53 +0100
Subject: [PATCH 1/2] Make the SetOptions call take an a{sv}
Instead of a{ss}, so that we can pass integers properly now.
---
interfaces/gc-iface-geoclue-full.xml | 2 +-
providers/example/geoclue-example.c | 5 +-
providers/gpsd/geoclue-gpsd.c | 17 +++--
providers/gypsy/geoclue-gypsy.c | 11 ++--
src/main.c | 104 +++++++++++++++++++++++++++-------
5 files changed, 104 insertions(+), 35 deletions(-)
diff --git a/interfaces/gc-iface-geoclue-full.xml b/interfaces/gc-iface-geoclue-full.xml
index 7543955..e2bded1 100644
--- a/interfaces/gc-iface-geoclue-full.xml
+++ b/interfaces/gc-iface-geoclue-full.xml
@@ -39,7 +39,7 @@
</signal>
<method name="SetOptions">
- <arg type="a{ss}" name="options" direction="in" />
+ <arg type="a{sv}" name="options" direction="in" />
</method>
<method name="AddReference">
diff --git a/providers/example/geoclue-example.c b/providers/example/geoclue-example.c
index 49d4ae3..a7ef6f7 100644
--- a/providers/example/geoclue-example.c
+++ b/providers/example/geoclue-example.c
@@ -62,7 +62,10 @@ print_option (gpointer key,
gpointer value,
gpointer data)
{
- g_print (" %s - %s\n", key, value);
+ if (G_VALUE_TYPE (value) == G_TYPE_STRING)
+ g_print (" %s - %s\n", key, g_value_get_string (value));
+ else
+ g_print (" %s - %d\n", key, g_value_get_int (value));
}
static gboolean
diff --git a/providers/gpsd/geoclue-gpsd.c b/providers/gpsd/geoclue-gpsd.c
index 6e141a6..dba91be 100644
--- a/providers/gpsd/geoclue-gpsd.c
+++ b/providers/gpsd/geoclue-gpsd.c
@@ -140,14 +140,17 @@ set_options (GcIfaceGeoclue *gc,
GError **error)
{
GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc);
- char *port, *host;
+ GValue *port_value, *host_value;
+ const char *port, *host;
gboolean changed = FALSE;
-
- host = g_hash_table_lookup (options,
- "org.freedesktop.Geoclue.GPSHost");
- port = g_hash_table_lookup (options,
- "org.freedesktop.Geoclue.GPSPort");
-
+
+ host_value = g_hash_table_lookup (options,
+ "org.freedesktop.Geoclue.GPSHost");
+ host = host_value ? g_value_get_string (host_value) : NULL;
+ port_value = g_hash_table_lookup (options,
+ "org.freedesktop.Geoclue.GPSPort");
+ port = port_value ? g_value_get_string (port_value) : NULL;
+
if (port == NULL) {
port = DEFAULT_GPSD_PORT;
}
diff --git a/providers/gypsy/geoclue-gypsy.c b/providers/gypsy/geoclue-gypsy.c
index 7d43450..2b67a1c 100644
--- a/providers/gypsy/geoclue-gypsy.c
+++ b/providers/gypsy/geoclue-gypsy.c
@@ -378,15 +378,16 @@ set_options (GcIfaceGeoclue *gc,
GError **error)
{
GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc);
+ GValue *device_value;
const char *device_name;
char *path;
- device_name = g_hash_table_lookup (options,
- "org.freedesktop.Geoclue.GPSDevice");
+ device_value = g_hash_table_lookup (options,
+ "org.freedesktop.Geoclue.GPSDevice");
+ device_name = device_value ? g_value_get_string (device_value) : NULL;
- if (g_strcmp0 (gypsy->device_name, device_name) == 0) {
- return TRUE;
- }
+ if (g_strcmp0 (gypsy->device_name, device_name) == 0)
+ return TRUE;
g_free (gypsy->device_name);
gypsy->device_name = NULL;
diff --git a/src/main.c b/src/main.c
index 0f436af..adbe8a8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -44,33 +44,96 @@ static GcMaster *master;
#define GEOCLUE_GCONF_TOP "/apps/geoclue/master"
#define GEOCLUE_MASTER_NAME "org.freedesktop.Geoclue.Master"
+static GValue *
+gconf_value_to_value (GConfValue *value)
+{
+ GValue *gvalue;
+
+ g_return_val_if_fail (value != NULL, NULL);
+ g_return_val_if_fail (value->type == GCONF_VALUE_STRING ||
+ value->type == GCONF_VALUE_INT, NULL);
+
+ if (value->type == GCONF_VALUE_STRING) {
+ const char *str;
+
+ gvalue = g_new0 (GValue, 1);
+ str = gconf_value_get_string (value);
+
+ /* Don't add empty strings in the hashtable */
+ if (str != NULL && str[0] == '\0')
+ str = NULL;
+
+ g_value_init (gvalue, G_TYPE_STRING);
+ g_value_set_string (gvalue, str);
+ } else if (value->type == GCONF_VALUE_INT) {
+ int i;
+
+ gvalue = g_new0 (GValue, 1);
+ i = gconf_value_get_int (value);
+ g_value_init (gvalue, G_TYPE_INT);
+ g_value_set_int (gvalue, i);
+ }
+
+ return gvalue;
+}
+
+static void
+debug_print_key (gboolean init,
+ const char *key,
+ GValue *gvalue)
+{
+ const char *message;
+ char *string;
+
+ if (init)
+ message = "GConf key '%s' initialised to '%s'";
+ else
+ message = "GConf key '%s' changed to '%s'";
+
+ if (G_VALUE_TYPE (gvalue) == G_TYPE_STRING) {
+ string = g_value_dup_string (gvalue);
+ } else if (G_VALUE_TYPE (gvalue) == G_TYPE_INT) {
+ string = g_strdup_printf ("%d", g_value_get_int (gvalue));
+ } else {
+ return;
+ }
+
+ g_message (message, key, string);
+ g_free (string);
+}
+
static void
gconf_key_changed (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
gpointer user_data)
{
- const char *key, *value;
+ const char *key;
GConfValue *v;
+ GValue *gvalue;
key = gconf_entry_get_key (entry);
v = gconf_entry_get_value (entry);
- if (v->type != GCONF_VALUE_STRING)
+ gvalue = gconf_value_to_value (v);
+ if (gvalue == NULL)
return;
- value = gconf_value_get_string (v);
- g_message ("gconf key changed %s", key);
+ debug_print_key (FALSE, key, gvalue);
- /* Don't add empty strings in the hashtable */
- if (value != NULL && value[0] == '\0')
- value = NULL;
-
- g_hash_table_insert (options, g_path_get_basename (key),
- g_strdup (value));
+ g_hash_table_insert (options, g_path_get_basename (key), gvalue);
g_signal_emit_by_name (G_OBJECT (master), "options-changed", options);
}
+static void
+free_gvalue (GValue *value)
+{
+ if (value == NULL)
+ return;
+ g_value_unset (value);
+ g_free (value);
+}
+
static GHashTable *
load_options (void)
{
@@ -94,26 +157,25 @@ load_options (void)
(GConfClientNotifyFunc) gconf_key_changed,
NULL, NULL, NULL);
- ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ ht = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) free_gvalue);
g_print ("Master options:\n");
for (e = entries; e; e = e->next) {
GConfEntry *entry = e->data;
- const char *key, *value;
+ const char *key;
GConfValue *v;
+ GValue *gvalue;
key = gconf_entry_get_key (entry);
v = gconf_entry_get_value (entry);
- if (v->type != GCONF_VALUE_STRING)
- continue;
- value = gconf_value_get_string (v);
+ gvalue = gconf_value_to_value (v);
+ if (gvalue == NULL)
+ continue;
- if (value != NULL && value[0] == '\0')
- value = NULL;
+ debug_print_key (TRUE, key, gvalue);
- g_print (" %s = %s\n", key, value);
- g_hash_table_insert (ht, g_path_get_basename (key),
- g_strdup (value));
- gconf_entry_free (entry);
+ g_hash_table_insert (ht, g_path_get_basename (key), gvalue);
+ gconf_entry_free (entry);
}
g_slist_free (entries);
--
1.7.0.1
>From b598ab73614bc43060d365e492689d8d1614c83c Mon Sep 17 00:00:00 2001
From: Bastien Nocera <[email protected]>
Date: Wed, 28 Apr 2010 17:43:00 +0100
Subject: [PATCH 2/2] Add support for baud rates setting in Gypsy
Which allows crummy GPSes like mine to function properly.
---
configure.ac | 3 ++-
providers/gypsy/geoclue-gypsy.c | 39 +++++++++++++++++++++++++++++++++++----
2 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/configure.ac b/configure.ac
index 5d2d192..999f7d9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -149,6 +149,7 @@ PROVIDER_SUBDIRS="example hostip geonames nominatim manual plazes localnet yahoo
# gypsy / gpsd / skyhook
# -----------------------------------------------------------
+GYPSY_REQUIRED=0.7.1
AC_ARG_ENABLE(gypsy,
AS_HELP_STRING([--enable-gypsy=@<:@no/yes/auto@:>@],
[build with gypsy support]), ,
@@ -157,7 +158,7 @@ AC_ARG_ENABLE(gypsy,
if test "x$enable_gypsy" != "xno"; then
PKG_CHECK_MODULES(GYPSY,
[
- gypsy
+ gypsy >= $GYPSY_REQUIRED
], have_gypsy="yes", have_gypsy="no")
if test "x$have_gypsy" = "xyes"; then
diff --git a/providers/gypsy/geoclue-gypsy.c b/providers/gypsy/geoclue-gypsy.c
index 2b67a1c..bc390ce 100644
--- a/providers/gypsy/geoclue-gypsy.c
+++ b/providers/gypsy/geoclue-gypsy.c
@@ -38,7 +38,8 @@ typedef struct {
GcProvider parent;
char *device_name;
-
+ guint baud_rate;
+
GypsyControl *control;
GypsyDevice *device;
GypsyPosition *position;
@@ -378,17 +379,28 @@ set_options (GcIfaceGeoclue *gc,
GError **error)
{
GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc);
- GValue *device_value;
+ GValue *device_value, *baud_rate_value;
const char *device_name;
char *path;
+ int baud_rate;
device_value = g_hash_table_lookup (options,
"org.freedesktop.Geoclue.GPSDevice");
device_name = device_value ? g_value_get_string (device_value) : NULL;
+ baud_rate_value = g_hash_table_lookup (options,
+ "org.freedesktop.Geoclue.GPSBaudRate");
+ baud_rate = baud_rate_value ? g_value_get_int (baud_rate_value) : 0;
- if (g_strcmp0 (gypsy->device_name, device_name) == 0)
+ if (g_strcmp0 (gypsy->device_name, device_name) == 0 &&
+ gypsy->baud_rate == baud_rate)
return TRUE;
+ /* Disconnect from the old device, if any */
+ if (gypsy->device != NULL) {
+ g_object_unref (gypsy->device);
+ gypsy->device = NULL;
+ }
+
g_free (gypsy->device_name);
gypsy->device_name = NULL;
@@ -397,7 +409,8 @@ set_options (GcIfaceGeoclue *gc,
}
gypsy->device_name = g_strdup (device_name);
- g_print ("Gypsy provider using '%s'\n", gypsy->device_name);
+ gypsy->baud_rate = baud_rate;
+ g_print ("Gypsy provider using '%s' at %d bps\n", gypsy->device_name, gypsy->baud_rate);
path = gypsy_control_create (gypsy->control, gypsy->device_name,
error);
if (*error != NULL) {
@@ -426,6 +439,24 @@ set_options (GcIfaceGeoclue *gc,
G_CALLBACK (accuracy_changed), gypsy);
g_debug ("starting device");
+ if (gypsy->baud_rate != 0) {
+ GHashTable *goptions;
+ GValue speed_val = { 0, };
+ GError *err = NULL;
+
+ g_value_init (&speed_val, G_TYPE_UINT);
+ g_value_set_uint (&speed_val, gypsy->baud_rate);
+ goptions = g_hash_table_new (g_str_hash,
+ g_str_equal);
+ g_hash_table_insert (goptions, "BaudRate", &speed_val);
+ if (!gypsy_device_set_start_options (gypsy->device,
+ goptions,
+ &err)) {
+ g_warning ("Error: %s", err->message);
+ g_error_free (err);
+ }
+ g_hash_table_destroy (goptions);
+ }
gypsy_device_start (gypsy->device, error);
if (*error != NULL) {
g_print ("Error - %s?\n", (*error)->message);
--
1.7.0.1
_______________________________________________
GeoClue mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/geoclue