Commit 18bfa888 authored by Jussi Kukkonen's avatar Jussi Kukkonen

working GcMasterClient

Client can now select the best provider based on
 * given requirements
 * provider status
 * provider theoretical accuracy
 * provider observed accuracy

Testing is _very_ difficult so bugs should still be expected. code is
still also a bit rough, especially in client.c.

So, Works For Me but needs refactoring and testing.
parent 24ddc287
......@@ -15,7 +15,7 @@
* defines the provider status
**/
typedef enum {
GEOCLUE_STATUS_ERROR,
GEOCLUE_STATUS_ERROR,
GEOCLUE_STATUS_UNAVAILABLE,
GEOCLUE_STATUS_ACQUIRING,
GEOCLUE_STATUS_AVAILABLE
......
......@@ -292,7 +292,6 @@ geoclue_gpsd_update_status (GeoclueGpsd *gpsd, NmeaTag nmea_tag)
gpsd->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE;
}
g_debug ("new status: %d", gpsd->last_status);
gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (gpsd),
gpsd->last_status);
}
......@@ -334,6 +333,7 @@ geoclue_gpsd_init (GeoclueGpsd *self)
/* init gpsd (localhost, default port) */
self->gpsdata = gps_open (NULL, DEFAULT_GPSD_PORT);
if (self->gpsdata) {
/* FIXME: This will block for a long time (10-80 seconds) if device is not available */
gps_set_callback (self->gpsdata, gpsd_callback, &gps_thread);
} else {
g_printerr("Cannot find gpsd!\n");
......
This diff is collapsed.
......@@ -26,13 +26,12 @@ typedef struct {
gboolean require_updates;
GeoclueResourceFlags allowed_resources;
guint32 update_id;
GcMasterProvider *position_provider;
GList *position_providers;
GcMasterProvider *address_provider;
GList *position_providers;
GList *address_providers;
} GcMasterClient;
typedef struct {
......
/*
* Geoclue
* master-provider.c - Provider object for master and master client
*
* Author: Jussi Kukkonen <jku@o-hand.com>
*
* Copyright 2007-2008 by Garmin Ltd. or its subsidiaries
*/
/**
* Provider object for GcMaster. Takes care of cacheing
* queried data.
......@@ -10,13 +19,6 @@
* have a "allowOldData" setting)
*
* TODO:
* fix status especially for network providers
*
* save accuracy level estimate in .provider: could be used to
* select suitable providers and to sort them...
*
* fix address marshaller problems
*
* implement velocity (maybe this should be somehow related to position)
*
* implement other (non-updating) ifaces
......@@ -57,7 +59,7 @@ typedef struct _GcMasterProviderPrivate {
char *name;
char *service;
char *path;
GeoclueAccuracyLevel accuracy_level;
GeoclueAccuracyLevel promised_accuracy;
GeoclueResourceFlags required_resources;
GeoclueProvideFlags provides;
......@@ -79,6 +81,7 @@ typedef struct _GcMasterProviderPrivate {
enum {
STATUS_CHANGED,
ACCURACY_CHANGED,
POSITION_CHANGED,
ADDRESS_CHANGED,
LAST_SIGNAL
......@@ -89,6 +92,28 @@ static guint32 signals[LAST_SIGNAL] = {0, };
G_DEFINE_TYPE (GcMasterProvider, gc_master_provider, G_TYPE_OBJECT)
static void
gc_master_provider_handle_new_accuracy (GcMasterProvider *provider,
GeoclueAccuracy *accuracy)
{
GeoclueAccuracyLevel old_level, new_level;
GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
if (priv->position_cache.accuracy) {
geoclue_accuracy_get_details (priv->position_cache.accuracy,
&old_level, NULL, NULL);
} else {
old_level = priv->promised_accuracy;
}
geoclue_accuracy_get_details (accuracy,
&new_level, NULL, NULL);
if (old_level != new_level) {
g_signal_emit (provider, signals[ACCURACY_CHANGED], 0,
new_level);
}
}
static void
gc_master_provider_set_position (GcMasterProvider *provider,
GeocluePositionFields fields,
......@@ -100,6 +125,8 @@ gc_master_provider_set_position (GcMasterProvider *provider,
{
GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
gc_master_provider_handle_new_accuracy (provider, accuracy);
priv->position_cache.timestamp = timestamp;
priv->position_cache.fields = fields;
priv->position_cache.latitude = latitude;
......@@ -153,6 +180,9 @@ gc_master_provider_set_address (GcMasterProvider *provider,
{
GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
gc_master_provider_handle_new_accuracy (provider, accuracy);
priv->address_cache.timestamp = timestamp;
free_address_details (priv->address_cache.details);
......@@ -213,7 +243,7 @@ gc_master_provider_update_cache (GcMasterProvider *provider)
return;
}
g_debug ("master-provider: Updating %s cache ", priv->name);
g_debug ("%s: Updating cache ", priv->name);
if (priv->position) {
int timestamp;
......@@ -319,7 +349,6 @@ gc_master_provider_handle_status_change (GcMasterProvider *provider)
priv->master_status = new_master_status;
if (!startup) {
g_debug ("master-provider: %s emitting new status: %d", priv->name, new_master_status);
g_signal_emit (provider, signals[STATUS_CHANGED], 0, new_master_status);
gc_master_provider_update_cache (provider);
}
......@@ -436,6 +465,15 @@ gc_master_provider_class_init (GcMasterProviderClass *klass)
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE, 1,
G_TYPE_INT);
signals[ACCURACY_CHANGED] = g_signal_new ("accuracy-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST |
G_SIGNAL_NO_RECURSE,
G_STRUCT_OFFSET (GcMasterProviderClass, accuracy_changed),
NULL, NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE, 1,
G_TYPE_INT);
signals[POSITION_CHANGED] = g_signal_new ("position-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST |
......@@ -576,7 +614,7 @@ gc_master_provider_dump_provider_details (GcMasterProvider *provider)
g_print ("\n Name - %s\n", priv->name);
g_print (" Service - %s\n", priv->service);
g_print (" Path - %s\n", priv->path);
g_print (" Accuracy level - %d\n", priv->accuracy_level);
g_print (" Accuracy level - %d\n", priv->promised_accuracy);
gc_master_provider_dump_required_resources (provider);
gc_master_provider_dump_provides (provider);
......@@ -714,7 +752,7 @@ gc_master_provider_new (const char *filename,
priv->path = g_key_file_get_value (keyfile, "Geoclue Provider",
"Path", NULL);
priv->accuracy_level =
priv->promised_accuracy =
g_key_file_get_integer (keyfile, "Geoclue Provider",
"Accuracy", NULL);
......@@ -885,7 +923,7 @@ gc_master_provider_is_good (GcMasterProvider *provider,
return (((supported_ifaces & iface_type) == iface_type) &&
((priv->provides & required_flags) == required_flags) &&
(priv->accuracy_level >= min_accuracy) &&
(priv->promised_accuracy >= min_accuracy) &&
((priv->required_resources & (~allowed_resources)) == 0));
}
......@@ -897,13 +935,50 @@ gc_master_provider_get_status (GcMasterProvider *provider)
return priv->master_status;
}
/* GCompareFunc for sorting providers by accuracy */
/*returns a reference, but is not meant for editing...*/
char *
gc_master_provider_get_name (GcMasterProvider *provider)
{
GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
return priv->name;
}
GeoclueAccuracyLevel
gc_master_provider_get_accuracy_level (GcMasterProvider *provider)
{
GcMasterProviderPrivate *priv = GET_PRIVATE (provider);
return priv->promised_accuracy;
}
/* GCompareFunc for sorting providers by accuracy and required resources */
gint
gc_master_provider_compare_by_accuracy (GcMasterProvider *a,
GcMasterProvider *b)
gc_master_provider_compare (GcMasterProvider *a,
GcMasterProvider *b)
{
int diff;
GeoclueAccuracyLevel level_a, level_b;
GcMasterProviderPrivate *priv_a = GET_PRIVATE (a);
GcMasterProviderPrivate *priv_b = GET_PRIVATE (b);
return priv_b->accuracy_level - priv_a->accuracy_level;
if (priv_a->position_cache.accuracy) {
geoclue_accuracy_get_details (priv_a->position_cache.accuracy,
&level_a, NULL, NULL);
} else {
level_a = priv_a->promised_accuracy;
}
if (priv_b->position_cache.accuracy) {
geoclue_accuracy_get_details (priv_b->position_cache.accuracy,
&level_b, NULL, NULL);
} else {
level_b = priv_b->promised_accuracy;
}
diff = level_b - level_a;
if (diff != 0) {
return diff;
}
return priv_a->required_resources - priv_b->required_resources;
}
......@@ -30,6 +30,8 @@ typedef struct _GcMasterProviderClass {
void (* status_changed) (GcMasterProvider *master_provider,
GeoclueStatus status);
void (* accuracy_changed) (GcMasterProvider *master_provider,
GeoclueAccuracyLevel status);
void (* position_changed) (GcMasterProvider *master_provider,
GeocluePositionFields fields,
int timestamp,
......@@ -48,7 +50,7 @@ GType gc_master_provider_get_type (void);
GcMasterProvider *gc_master_provider_new (const char *filename,
GeoclueConnectivity *connectivity);
gint gc_master_provider_compare_by_accuracy (GcMasterProvider *a, GcMasterProvider *b);
gint gc_master_provider_compare (GcMasterProvider *a, GcMasterProvider *b);
gboolean gc_master_provider_is_good (GcMasterProvider *provider,
GcInterfaceFlags iface_types,
......@@ -59,6 +61,9 @@ gboolean gc_master_provider_is_good (GcMasterProvider *provider,
void gc_master_provider_network_status_changed (GcMasterProvider *provider,
GeoclueNetworkStatus status);
char* gc_master_provider_get_name (GcMasterProvider *provider);
GeoclueAccuracyLevel gc_master_provider_get_accuracy_level (GcMasterProvider *provider);
GeoclueNetworkStatus gc_master_provider_get_status (GcMasterProvider *provider);
GeocluePositionFields gc_master_provider_get_position (GcMasterProvider *master_provider,
......
......@@ -3,6 +3,7 @@
* master.c - Master process
*
* Authors: Iain Holmes <iain@openedhand.com>
* Jussi Kukkonen <jku@o-hand.com>
* Copyright 2007-2008 by Garmin Ltd. or its subsidiaries
*/
......@@ -98,7 +99,15 @@ gc_master_class_init (GcMasterClass *klass)
&dbus_glib_gc_iface_master_object_info);
}
static void
accuracy_changed (GcMasterProvider *provider,
GeoclueAccuracyLevel level,
GcMaster *master)
{
g_debug ("master: provider accuracy changed, sorting list");
providers = g_list_sort (providers,
(GCompareFunc)gc_master_provider_compare);
}
/* Load the provider details out of a keyfile */
static void
......@@ -117,7 +126,12 @@ gc_master_add_new_provider (GcMaster *master,
providers = g_list_insert_sorted
(providers, provider,
(GCompareFunc)gc_master_provider_compare_by_accuracy);
(GCompareFunc)gc_master_provider_compare);
g_signal_connect (G_OBJECT (provider),
"accuracy-changed",
G_CALLBACK (accuracy_changed),
master);
}
/* Scan a directory for .provider files */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment