#include "server.h"
#include "last_position.h"
+#include "debug_util.h"
#define GEOCLUE_GPSMANAGER_DBUS_SERVICE "org.freedesktop.Geoclue.Providers.GpsManager"
#define GEOCLUE_GPSMANAGER_DBUS_PATH "/org/freedesktop/Geoclue/Providers/GpsManager"
typedef struct {
GcProvider parent;
GMainLoop *loop;
+ GMutex *mutex;
GeoclueStatus status;
pos_data_t position;
pos_data_t last_position;
sv_data_t last_satellite;
- GHashTable *connections;
+ gboolean is_running;
+ gint client_count;
} GeoclueGpsManager;
typedef struct {
G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_SATELLITE, init_satellite)
G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_GEOCLUE, init_geoclue));
-static void constructed(GObject * object)
+static GObject* constructor (GType type, guint n_props, GObjectConstructParam *props)
{
- GeoclueGpsManager *gps_manager = GEOCLUE_GPSMANAGER(object);
+ GObject *object;
- gps_manager->connections = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ object = ((GObjectClass *) geoclue_gpsmanager_parent_class)->constructor(type, n_props, props);
- gps_manager->status = GEOCLUE_STATUS_UNAVAILABLE;
-
- memset(&gps_manager->position, 0x00, sizeof(pos_data_t));
- memset(&gps_manager->satellite, 0x00, sizeof(sv_data_t));
- memset(&gps_manager->nmea, 0x00, sizeof(nmea_data_t));
-
- ((GObjectClass *) geoclue_gpsmanager_parent_class)->constructed(object);
+ return object;
}
static void finalize(GObject * object)
static void dispose(GObject * object)
{
GeoclueGpsManager *gpsmanager = GEOCLUE_GPSMANAGER(object);
-
- g_hash_table_destroy(gpsmanager->connections);
-
+ g_mutex_free(gpsmanager->mutex);
((GObjectClass *) geoclue_gpsmanager_parent_class)->dispose(object);
}
return TRUE;
}
-static void print_option(gpointer key, gpointer value, gpointer data)
+static void start_tracking(GeoclueGpsManager * gpsmanager)
{
- g_print(" %s - %s\n", (char *)key, (char *)value);
+ LOG_GPS(DBG_LOW, "start_tracking");
+ gpsmanager->status = GEOCLUE_STATUS_ACQUIRING;
+ g_mutex_lock(gpsmanager->mutex);
+ if (request_start_session() == TRUE) {
+ gpsmanager->is_running = TRUE;
+ } else {
+ LOG_GPS(DBG_ERR, "Fail to request_start_session");
+ }
+ g_mutex_unlock(gpsmanager->mutex);
}
-static gboolean set_options(GcIfaceGeoclue * gc, GHashTable * options, GError ** error)
+static void stop_tracking(GeoclueGpsManager * gpsmanager)
{
- g_print("Options received---\n");
- g_hash_table_foreach(options, print_option, NULL);
- return TRUE;
+ LOG_GPS(DBG_LOW, "stop_tracking");
+ g_mutex_lock(gpsmanager->mutex);
+ if (request_stop_session() == TRUE) {
+ gpsmanager->is_running = FALSE;
+ }
+ g_mutex_unlock(gpsmanager->mutex);
+ gpsmanager->status = GEOCLUE_STATUS_UNAVAILABLE;
}
-static void shutdown(GcProvider * provider)
+static gboolean set_options(GcIfaceGeoclue * gc, GHashTable * options, GError ** error)
{
- /* No shutdown!! */
+ LOG_GPS(DBG_LOW, "set_options");
+
+ GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(gc));
+ gchar *value = NULL;
+
+ value = g_hash_table_lookup(options, "CMD");
+
+ if (value) {
+ if (!g_strcmp0(value, "START")) {
+ g_mutex_lock(gpsmanager->mutex);
+ gpsmanager->client_count++;
+ g_mutex_unlock(gpsmanager->mutex);
+
+ if (gpsmanager->is_running == TRUE) {
+ LOG_GPS(DBG_LOW, "gps-manager is already running");
+ return TRUE;
+ }
+ start_tracking(gpsmanager);
+ } else if (!g_strcmp0(value, "STOP")) {
+ g_mutex_lock(gpsmanager->mutex);
+ gpsmanager->client_count--;
+ g_mutex_unlock(gpsmanager->mutex);
+
+ if (gpsmanager->is_running == FALSE) {
+ return TRUE;
+ }
+ if (gpsmanager->client_count <= 0 ) {
+ stop_tracking(gpsmanager);
+ }
+ }
+ }
+ return TRUE;
}
-static void start_tracking(GeoclueGpsManager * gpsmanager)
+static gboolean remove_all_clients(GeoclueGpsManager * gpsmanager)
{
- gpsmanager->status = GEOCLUE_STATUS_ACQUIRING;
- request_start_session();
+ if (gpsmanager->client_count <= 0) {
+ return FALSE;
+ }
+
+ gpsmanager->client_count = 0;
+ stop_tracking(gpsmanager);
+
+ return TRUE;
}
-static void stop_tracking(GeoclueGpsManager * gpsmanager)
+static void shutdown(GcProvider * provider)
{
- request_stop_session();
- gpsmanager->status = GEOCLUE_STATUS_UNAVAILABLE;
+ GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(provider));
+
+ if (gpsmanager->is_running) {
+ if (remove_all_clients(gpsmanager)) {
+ LOG_GPS(DBG_ERR, "<<<< Abnormal shutdown >>>>");
+ }
+ }
}
static void update_position_cb(pos_data_t * pos, gps_error_t error, void *user_data)
gpsmanager->status = GEOCLUE_STATUS_AVAILABLE;
- fields = (GEOCLUE_POSITION_FIELDS_LATITUDE | GEOCLUE_POSITION_FIELDS_LONGITUDE | GEOCLUE_POSITION_FIELDS_ALTITUDE);
-
accuracy = geoclue_accuracy_new(GEOCLUE_ACCURACY_LEVEL_DETAILED, pos->hor_accuracy, pos->ver_accuracy);
- gc_iface_position_emit_position_changed(GC_IFACE_POSITION(gpsmanager),
- fields, pos->timestamp, pos->latitude, pos->longitude, pos->altitude, accuracy);
-
fields = (GEOCLUE_VELOCITY_FIELDS_SPEED | GEOCLUE_VELOCITY_FIELDS_DIRECTION);
-
gc_iface_velocity_emit_velocity_changed(GC_IFACE_VELOCITY(gpsmanager),
fields, pos->timestamp, pos->speed, pos->bearing, 0.0);
+ fields = (GEOCLUE_POSITION_FIELDS_LATITUDE | GEOCLUE_POSITION_FIELDS_LONGITUDE | GEOCLUE_POSITION_FIELDS_ALTITUDE);
+ gc_iface_position_emit_position_changed(GC_IFACE_POSITION(gpsmanager),
+ fields, pos->timestamp, pos->latitude, pos->longitude, pos->altitude, accuracy);
+
geoclue_accuracy_free(accuracy);
gc_iface_geoclue_emit_status_changed(GC_IFACE_GEOCLUE(gpsmanager), GEOCLUE_STATUS_AVAILABLE);
g_memmove(gpsmanager->nmea.data, nmea->data, nmea->len);
gpsmanager->nmea.data[nmea->len] = '\0';
+ timestamp = gpsmanager->position.timestamp;
+
gc_iface_nmea_emit_nmea_changed(GC_IFACE_NMEA(gpsmanager), timestamp, gpsmanager->nmea.data);
g_free(gpsmanager->nmea.data);
}
-static void add_reference(GcIfaceGeoclue * gc, DBusGMethodInvocation * context)
-{
- GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(gc));
- char *sender;
- int *pcount;
-
- sender = dbus_g_method_get_sender(context);
- if (g_hash_table_size(gpsmanager->connections) == 0) {
- start_tracking(gpsmanager);
- }
- pcount = g_hash_table_lookup(gpsmanager->connections, sender);
- if (!pcount) {
- pcount = g_malloc0(sizeof(int));
- g_hash_table_insert(gpsmanager->connections, sender, pcount);
- }
- (*pcount)++;
-
- g_debug("add_reference (%s) (%d)", sender, (*pcount));
-
- dbus_g_method_return(context);
-}
-
-static gboolean remove_client(GeoclueGpsManager * gpsmanager, const char *client)
-{
- int *pcount;
-
- pcount = g_hash_table_lookup(gpsmanager->connections, client);
- if (!pcount) {
- return FALSE;
- }
- (*pcount)--;
- if (*pcount == 0) {
- g_hash_table_remove(gpsmanager->connections, client);
- }
- if (g_hash_table_size(gpsmanager->connections) == 0) {
- g_debug("There is no connections!");
- stop_tracking(gpsmanager);
- }
- return TRUE;
-}
-
-static gboolean remove_all_clients(GeoclueGpsManager * gpsmanager, const char *client)
-{
- int *pcount;
-
- pcount = g_hash_table_lookup(gpsmanager->connections, client);
- if (!pcount) {
- return FALSE;
- }
- g_hash_table_remove(gpsmanager->connections, client);
- if (g_hash_table_size(gpsmanager->connections) == 0) {
- g_debug("There is no connections!");
- stop_tracking(gpsmanager);
- }
- return TRUE;
-}
-
-static void remove_reference(GcIfaceGeoclue * gc, DBusGMethodInvocation * context)
-{
- GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(gc));
- char *sender;
-
- sender = dbus_g_method_get_sender(context);
- if (!remove_client(gpsmanager, sender)) {
- g_warning("Unreffed by client taht has not been referenced");
- }
-
- g_free(sender);
-
- dbus_g_method_return(context);
-}
-
-static void name_owner_changed(DBusGProxy * proxy, const char *name, const char *prev_owner, const char *new_owner, void *gc)
-{
- GeoclueGpsManager *gpsmanager = (GEOCLUE_GPSMANAGER(gc));
- g_debug("name_owner_changed, name:%s, prev_owner:%s, new_owner:%s", name, prev_owner, new_owner);
- if (strcmp(new_owner, "") == 0 && strcmp(name, prev_owner) == 0) {
- if (remove_all_clients(gpsmanager, prev_owner)) {
- g_warning("Impolite client %s disconnected without unreferencing\n", prev_owner);
- }
- }
-}
-
static void geoclue_gpsmanager_class_init(GeoclueGpsManagerClass * klass)
{
GObjectClass *o_class = (GObjectClass *) klass;
GcProviderClass *p_class = (GcProviderClass *) klass;
- o_class->constructed = constructed;
+ o_class->constructor = constructor;
o_class->finalize = finalize;
o_class->dispose = dispose;
p_class->get_status = get_status;
static void geoclue_gpsmanager_init(GeoclueGpsManager * gpsmanager)
{
- GError *error = NULL;
- DBusGProxy *driver;
- guint request_ret;
- GcProvider *provider;
- g_debug("geoclue_gpsmanager_init");
-
- g_return_if_fail(GC_IS_PROVIDER(gpsmanager));
- provider = GC_PROVIDER(gpsmanager);
- g_return_if_fail(provider->connection != NULL);
-
- driver = dbus_g_proxy_new_for_name(provider->connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
-
- if (!org_freedesktop_DBus_request_name(driver, GEOCLUE_GPSMANAGER_DBUS_SERVICE, 0, &request_ret, &error)) {
- g_warning("%s was unable to register service %s: %s",
- G_OBJECT_TYPE_NAME(provider), GEOCLUE_GPSMANAGER_DBUS_SERVICE, error->message);
- g_error_free(error);
- return;
- }
+ LOG_GPS(DBG_LOW, "geoclue_gpsmanager_init");
- dbus_g_proxy_add_signal(driver, "NameOwnerChanged", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
-
- dbus_g_proxy_connect_signal(driver, "NameOwnerChanged", G_CALLBACK(name_owner_changed), provider, NULL);
-
- dbus_g_connection_register_g_object(provider->connection, GEOCLUE_GPSMANAGER_DBUS_PATH, G_OBJECT(provider));
+ gpsmanager->status = GEOCLUE_STATUS_UNAVAILABLE;
+ gpsmanager->mutex = g_mutex_new();
+ memset(&gpsmanager->position, 0x00, sizeof(pos_data_t));
+ memset(&gpsmanager->satellite, 0x00, sizeof(sv_data_t));
+ memset(&gpsmanager->nmea, 0x00, sizeof(nmea_data_t));
memset(&gpsmanager->last_position, 0x00, sizeof(pos_data_t));
memset(&gpsmanager->last_satellite, 0x00, sizeof(sv_data_t));
+ gpsmanager->is_running = FALSE;
+ gpsmanager->client_count = 0;
+
+ gc_provider_set_details(GC_PROVIDER(gpsmanager), GEOCLUE_GPSMANAGER_DBUS_SERVICE, GEOCLUE_GPSMANAGER_DBUS_PATH, "gps-manager", "GPS Manager");
+
gps_manager_get_last_position(&gpsmanager->last_position);
}
static void init_geoclue(GcIfaceGeoclueClass * iface)
{
iface->get_provider_info = get_provider_info;
- iface->add_reference = add_reference;
- iface->remove_reference = remove_reference;
}
int main(int argc, char **argv)
cb.sv_cb = update_satellite_cb;
cb.nmea_cb = update_nmea_cb;
+#if !GLIB_CHECK_VERSION (2, 31, 0)
if (!g_thread_supported()) {
g_thread_init(NULL);
}
+#endif
+
dbus_g_thread_init();
g_type_init();