2014-10-28 03:22:55 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <Eina.h>
|
|
|
|
#include <Ecore.h>
|
|
|
|
#include <Eldbus.h>
|
|
|
|
#include <Elocation.h>
|
|
|
|
#include <elocation_private.h>
|
|
|
|
|
|
|
|
/* FIXME: These globals really need to get reduced before leaving the PROTO
|
|
|
|
* area.
|
|
|
|
*/
|
|
|
|
static char *unique_name = NULL;
|
|
|
|
static Eldbus_Connection *conn = NULL;
|
|
|
|
static Elocation_Provider *address_provider = NULL;
|
|
|
|
static Elocation_Provider *position_provider = NULL;
|
|
|
|
static Eldbus_Object *obj_meta = NULL;
|
|
|
|
static Eldbus_Proxy *manager_master = NULL;
|
|
|
|
static Eldbus_Proxy *meta_geoclue = NULL;
|
|
|
|
static Eldbus_Proxy *meta_address = NULL;
|
|
|
|
static Eldbus_Proxy *meta_position = NULL;
|
|
|
|
static Eldbus_Proxy *meta_masterclient = NULL;
|
|
|
|
static Eldbus_Proxy *meta_velocity = NULL;
|
|
|
|
static Eldbus_Proxy *meta_nmea = NULL;
|
|
|
|
static Eldbus_Proxy *meta_satellite = NULL;
|
|
|
|
static Eldbus_Proxy *geonames_geocode = NULL;
|
|
|
|
static Eldbus_Proxy *geonames_rgeocode = NULL;
|
|
|
|
static Eldbus_Proxy *master_poi = NULL;
|
|
|
|
static Elocation_Address *address = NULL;
|
|
|
|
static Elocation_Position *position = NULL;
|
|
|
|
static Elocation_Address *addr_geocode = NULL;
|
|
|
|
static Elocation_Position *pos_geocode = NULL;
|
|
|
|
static Elocation_Velocity *velocity = NULL;
|
2014-11-11 02:46:14 -08:00
|
|
|
static int status = -1; /* 0 is a valid status code */
|
2014-10-28 03:22:55 -07:00
|
|
|
static char nmea_sentence[256];
|
|
|
|
|
|
|
|
int _elocation_log_dom = -1;
|
|
|
|
|
|
|
|
/* Elocation ecore event types we provide to the application. */
|
2017-03-09 16:17:24 -08:00
|
|
|
EAPI int ELOCATION_EVENT_STATUS = 0;
|
|
|
|
EAPI int ELOCATION_EVENT_POSITION = 0;
|
|
|
|
EAPI int ELOCATION_EVENT_ADDRESS = 0;
|
|
|
|
EAPI int ELOCATION_EVENT_VELOCITY = 0;
|
|
|
|
EAPI int ELOCATION_EVENT_GEOCODE = 0;
|
|
|
|
EAPI int ELOCATION_EVENT_REVERSEGEOCODE = 0;
|
|
|
|
EAPI int ELOCATION_EVENT_NMEA = 0;
|
|
|
|
EAPI int ELOCATION_EVENT_SATELLITE = 0;
|
|
|
|
EAPI int ELOCATION_EVENT_POI = 0;
|
|
|
|
EAPI int ELOCATION_EVENT_META_READY = 0;
|
2014-10-28 03:22:55 -07:00
|
|
|
|
2014-11-12 00:54:58 -08:00
|
|
|
/* Internal events */
|
2017-03-09 16:17:24 -08:00
|
|
|
int ELOCATION_EVENT_IN = 0;
|
|
|
|
int ELOCATION_EVENT_OUT = 0;
|
2014-11-12 00:54:58 -08:00
|
|
|
|
2014-10-28 03:22:55 -07:00
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
_dummy_free(void *user_data EINA_UNUSED, void *func_data EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
/* Don't free the event data after dispatching the event. We keep track of
|
|
|
|
* it on our own
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Generic provider message unmarshaller. Used from all different provider
|
|
|
|
* calbacks that receive such a message
|
|
|
|
*/
|
|
|
|
static Eina_Bool
|
|
|
|
unmarshall_provider(const Eldbus_Message *reply, Elocation_Provider *provider)
|
|
|
|
{
|
|
|
|
char *name = NULL, *desc = NULL, *service = NULL, *path = NULL;
|
|
|
|
|
|
|
|
if (!eldbus_message_arguments_get(reply, "ssss", &name, &desc, &service, &path))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
provider->name = strdup(name);
|
|
|
|
provider->description = strdup(desc);
|
|
|
|
provider->service = strdup(service);
|
|
|
|
provider->path = strdup(path);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
meta_address_provider_info_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
Elocation_Provider *addr_provider;
|
|
|
|
|
|
|
|
addr_provider = data;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_provider(reply, addr_provider))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall address provider");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Meta address provider name: %s, %s, %s, %s", addr_provider->name,
|
|
|
|
addr_provider->description,
|
|
|
|
addr_provider->service,
|
|
|
|
addr_provider->path);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
meta_position_provider_info_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
Elocation_Provider *pos_provider;
|
|
|
|
|
|
|
|
pos_provider = data;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_provider(reply, pos_provider))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall position provider");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Meta position provider name: %s, %s, %s, %s", pos_provider->name,
|
|
|
|
pos_provider->description,
|
|
|
|
pos_provider->service,
|
|
|
|
pos_provider->path);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_address_provider_info_signal_cb(void *data, const Eldbus_Message *reply)
|
|
|
|
{
|
|
|
|
Elocation_Provider *addr_provider;
|
|
|
|
addr_provider = data;
|
|
|
|
|
|
|
|
if (!unmarshall_provider(reply, addr_provider))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall address provider");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Meta address provider name changed: %s, %s, %s, %s", addr_provider->name,
|
|
|
|
addr_provider->description,
|
|
|
|
addr_provider->service,
|
|
|
|
addr_provider->path);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_position_provider_info_signal_cb(void *data, const Eldbus_Message *reply)
|
|
|
|
{
|
|
|
|
Elocation_Provider *pos_provider;
|
|
|
|
pos_provider = data;
|
|
|
|
|
|
|
|
if (!unmarshall_provider(reply, pos_provider))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall position provider");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Meta position provider name changed: %s, %s, %s, %s", pos_provider->name,
|
|
|
|
pos_provider->description,
|
|
|
|
pos_provider->service,
|
|
|
|
pos_provider->path);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* A address is quite flexible what kind of key value pairs it contains in the
|
|
|
|
* dict. Similar to a reverse GeoCode message as both return an address object.
|
|
|
|
*/
|
|
|
|
static Eina_Bool
|
|
|
|
unmarshall_address(const Eldbus_Message *reply, Elocation_Address *addr)
|
|
|
|
{
|
|
|
|
int32_t level, timestamp;
|
|
|
|
Eldbus_Message_Iter *sub, *dict, *entry;
|
|
|
|
double horizontal;
|
|
|
|
double vertical;
|
|
|
|
const char *key, *signature;
|
|
|
|
char *value;
|
|
|
|
|
|
|
|
signature = eldbus_message_signature_get(reply);
|
|
|
|
|
|
|
|
if (!strcmp(signature, "ia{ss}(idd)"))
|
|
|
|
{
|
|
|
|
if (!eldbus_message_arguments_get(reply, "ia{ss}(idd)", ×tamp, &dict, &sub))
|
|
|
|
return EINA_FALSE;
|
|
|
|
addr->timestamp = timestamp;
|
|
|
|
}
|
|
|
|
else if (!strcmp(signature, "a{ss}(idd)"))
|
|
|
|
{
|
|
|
|
if (!eldbus_message_arguments_get(reply, "a{ss}(idd)", &dict, &sub))
|
|
|
|
return EINA_FALSE;
|
|
|
|
addr->timestamp = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
/* Cleanup potential old entries before re-using */
|
|
|
|
addr->country = NULL;
|
|
|
|
addr->countrycode = NULL;
|
|
|
|
addr->locality = NULL;
|
|
|
|
addr->postalcode = NULL;
|
|
|
|
addr->region = NULL;
|
|
|
|
addr->timezone = NULL;
|
|
|
|
|
|
|
|
while (eldbus_message_iter_get_and_next(dict, 'e', &entry))
|
|
|
|
{
|
2014-11-14 01:51:56 -08:00
|
|
|
if (!eldbus_message_iter_arguments_get(entry, "ss", &key, &value))
|
|
|
|
continue;
|
2014-10-28 03:22:55 -07:00
|
|
|
|
|
|
|
if (!strcmp(key, "country"))
|
|
|
|
{
|
|
|
|
free(addr->country);
|
|
|
|
addr->country = strdup(value);
|
|
|
|
}
|
|
|
|
else if (!strcmp(key, "countrycode"))
|
|
|
|
{
|
|
|
|
free(addr->countrycode);
|
|
|
|
addr->countrycode = strdup(value);
|
|
|
|
}
|
|
|
|
else if (!strcmp(key, "locality"))
|
|
|
|
{
|
|
|
|
free(addr->locality);
|
|
|
|
addr->locality = strdup(value);
|
|
|
|
}
|
|
|
|
else if (!strcmp(key, "postalcode"))
|
|
|
|
{
|
|
|
|
free(addr->postalcode);
|
|
|
|
addr->postalcode = strdup(value);
|
|
|
|
}
|
|
|
|
else if (!strcmp(key, "region"))
|
|
|
|
{
|
|
|
|
free(addr->region);
|
|
|
|
addr->region = strdup(value);
|
|
|
|
}
|
|
|
|
else if (!strcmp(key, "timezone"))
|
|
|
|
{
|
|
|
|
free(addr->timezone);
|
|
|
|
addr->timezone = strdup(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-12 01:18:58 -08:00
|
|
|
if (!eldbus_message_iter_arguments_get(sub, "idd", &level, &horizontal, &vertical))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
2014-10-28 03:22:55 -07:00
|
|
|
addr->accur->level = level;
|
|
|
|
addr->accur->horizontal = horizontal;
|
|
|
|
addr->accur->vertical = vertical;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Receive and unmarshall a reverse GeoCode message. The dict can contain a
|
|
|
|
* variable set of key value pairs so we need to handle this with care
|
|
|
|
*/
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
rgeocode_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_address(reply, addr_geocode))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall address");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_REVERSEGEOCODE, addr_geocode, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Point of Interest (POI) aka landmark message unmarshalling. Thsi interface is
|
|
|
|
* not in standard GeoClue but currently a Tizen extension.
|
|
|
|
*/
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
poi_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
int32_t count, id, rank;
|
|
|
|
double lat, lon, bound_left, bound_top, bound_right, bound_bottom;
|
|
|
|
const char *name, *icon, *house, *road, *village, *suburb, *postcode;
|
|
|
|
const char *city, *county, *country, *country_code;
|
|
|
|
Eldbus_Message_Iter *array, *struct_landmark;
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Yeah, its quite a horrible message. The POI interface could use a better design */
|
|
|
|
if (!eldbus_message_arguments_get(reply, "ia(iiddddddsssssssssss", &count ,&array))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* TODO re-check that the parameter ordering is what we expect */
|
|
|
|
while (eldbus_message_iter_get_and_next(array, 'r', &struct_landmark))
|
|
|
|
{
|
2014-11-12 01:18:58 -08:00
|
|
|
if (!eldbus_message_iter_arguments_get(struct_landmark, "iiddddddsssssssssss", &id, &rank,
|
2014-10-28 03:22:55 -07:00
|
|
|
&lat, &lon, &bound_left, &bound_top, &bound_right,
|
|
|
|
&bound_bottom, &name, &icon, &house, &road,
|
|
|
|
&village, &suburb, &postcode, &city, &county,
|
2014-11-12 01:18:58 -08:00
|
|
|
&country, &country_code))
|
|
|
|
return;
|
|
|
|
|
2014-10-28 03:22:55 -07:00
|
|
|
DBG("Landmark received: %i, %i, %f, %f, %f, %f, %f, %f, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,",
|
|
|
|
id, rank, lat, lon, bound_left, bound_top, bound_right,
|
|
|
|
bound_bottom, name, icon, house, road, village,
|
|
|
|
suburb, postcode, city, county, country, country_code);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_POI, NULL, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unmarshall a GeoCode message */
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
geocode_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
GeocluePositionFields fields;
|
|
|
|
int32_t level;
|
|
|
|
double horizontal = 0.0;
|
|
|
|
double vertical = 0.0;
|
|
|
|
double latitude = 0.0;
|
|
|
|
double longitude = 0.0;
|
|
|
|
double altitude = 0.0;
|
|
|
|
Eldbus_Message_Iter *sub;
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_message_arguments_get(reply, "iddd(idd)", &fields,&latitude,
|
|
|
|
&longitude, &altitude, &sub))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* GeoClue uses some flags to mark position fields as valid. We set invalid
|
|
|
|
* fields to 0.0 */
|
|
|
|
if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE)
|
|
|
|
pos_geocode->latitude = latitude;
|
|
|
|
else
|
|
|
|
pos_geocode->latitude = 0.0;
|
|
|
|
|
|
|
|
if (fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)
|
|
|
|
pos_geocode->longitude = longitude;
|
|
|
|
else
|
|
|
|
pos_geocode->longitude = 0.0;
|
|
|
|
|
|
|
|
if (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE)
|
|
|
|
pos_geocode->altitude = altitude;
|
|
|
|
else
|
|
|
|
pos_geocode->altitude = 0.0;
|
|
|
|
|
2014-11-12 01:18:58 -08:00
|
|
|
if (!eldbus_message_iter_arguments_get(sub, "idd", &level, &horizontal, &vertical))
|
|
|
|
return;
|
|
|
|
|
2014-10-28 03:22:55 -07:00
|
|
|
pos_geocode->accur->level = level;
|
|
|
|
pos_geocode->accur->horizontal = horizontal;
|
|
|
|
pos_geocode->accur->vertical = vertical;
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_GEOCODE, pos_geocode, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
address_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_address(reply, address))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall address");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_ADDRESS, address, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
address_signal_cb(void *data EINA_UNUSED, const Eldbus_Message *reply)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_address(reply, address))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall address");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_ADDRESS, address, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unmarshall a velocity message. This is only available if we use a GPS
|
|
|
|
* provider from GeoClue. None of the other providers offer this currently.
|
|
|
|
*/
|
|
|
|
static Eina_Bool
|
|
|
|
unmarshall_velocity(const Eldbus_Message *reply)
|
|
|
|
{
|
|
|
|
GeoclueVelocityFields fields;
|
|
|
|
int32_t timestamp = 0;
|
|
|
|
double speed = 0.0;
|
|
|
|
double direction = 0.0;
|
|
|
|
double climb = 0.0;
|
|
|
|
|
|
|
|
if (!eldbus_message_arguments_get(reply, "iiddd", &fields, ×tamp,
|
|
|
|
&speed, &direction, &climb))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
velocity->timestamp = timestamp;
|
|
|
|
|
|
|
|
/* GeoClue uses some flags to mark velocity fields as valid. We set invalid
|
|
|
|
* fields to 0.0 */
|
|
|
|
if (fields & GEOCLUE_VELOCITY_FIELDS_SPEED)
|
|
|
|
velocity->speed = speed;
|
|
|
|
else
|
|
|
|
velocity->speed = 0.0;
|
|
|
|
|
|
|
|
if (fields & GEOCLUE_VELOCITY_FIELDS_DIRECTION)
|
|
|
|
velocity->direction = direction;
|
|
|
|
else
|
|
|
|
velocity->direction = 0.0;
|
|
|
|
|
|
|
|
if (fields & GEOCLUE_VELOCITY_FIELDS_CLIMB)
|
|
|
|
velocity->climb = climb;
|
|
|
|
else
|
|
|
|
velocity->climb = 0.0;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
velocity_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
WARN("Warning: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_velocity(reply))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall velocity");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_VELOCITY, velocity, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
velocity_signal_cb(void *data EINA_UNUSED, const Eldbus_Message *reply)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
if (!unmarshall_velocity(reply))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall velocity");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_VELOCITY, velocity, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unmarshall an raw NMEA message. It conatins a raw NMEA sentence which we can
|
|
|
|
* pass on to applications that want to use their own NMEA parser. This is not
|
|
|
|
* reommended. Better use the other interfaces to access the needed data.
|
|
|
|
*
|
|
|
|
* This is currently a Tizen only interface and not in GeoClue upstream.
|
|
|
|
*/
|
|
|
|
static Eina_Bool
|
|
|
|
unmarshall_nmea(const Eldbus_Message *reply)
|
|
|
|
{
|
|
|
|
int32_t timestamp = 0;
|
|
|
|
|
|
|
|
if (!eldbus_message_arguments_get(reply, "is", ×tamp, &nmea_sentence))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
nmea_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
WARN("Warning: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_nmea(reply))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall nmea");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_NMEA, nmea_sentence, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
nmea_signal_cb(void *data EINA_UNUSED, const Eldbus_Message *reply)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
if (!unmarshall_nmea(reply))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall nmea");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ecore_event_add(ELOCATION_EVENT_NMEA, nmea_sentence, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unmarshall a satellite information message. This offers GPS specific
|
|
|
|
* information about the used satellites and its properties. It can be used for
|
|
|
|
* applications that rely on GPS and want to show more information like a 3D fix
|
|
|
|
* or used satellites.
|
|
|
|
*
|
|
|
|
* This is currently a Tizen only interface and not available in GeoClue upstream.
|
|
|
|
*/
|
|
|
|
static Eina_Bool
|
|
|
|
unmarshall_satellite(const Eldbus_Message *reply)
|
|
|
|
{
|
|
|
|
int32_t timestamp = 0, satellite_used = 0, satellite_visible = 0;
|
|
|
|
int32_t snr = 0, elevation = 0, azimuth = 0, prn = 0, used_prn = 0;
|
|
|
|
Eldbus_Message_Iter *sub_prn, *sub_info, *struct_info;
|
|
|
|
|
|
|
|
if (!eldbus_message_arguments_get(reply, "iiiaia(iiii)", ×tamp, &satellite_used,
|
|
|
|
&satellite_visible, &sub_prn, &sub_info))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
while (eldbus_message_iter_get_and_next(sub_prn, 'i', &used_prn))
|
|
|
|
{
|
|
|
|
DBG("Satellite used PRN %i", used_prn);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO re-check that the parameter ordering is what we expect */
|
|
|
|
while (eldbus_message_iter_get_and_next(sub_info, 'r', &struct_info))
|
|
|
|
{
|
2014-11-12 01:18:58 -08:00
|
|
|
if (!eldbus_message_iter_arguments_get(struct_info, "iiii", &prn, &elevation, &azimuth, &snr))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
2014-10-28 03:22:55 -07:00
|
|
|
DBG("Satellite info %i, %i, %i, %i", prn, elevation, azimuth, snr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
satellite_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
WARN("Warning: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_satellite(reply))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall satellite");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_SATELLITE, NULL, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
last_satellite_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
WARN("Warning: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_satellite(reply))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall last satellite");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_SATELLITE, NULL, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
satellite_signal_cb(void *data EINA_UNUSED, const Eldbus_Message *reply)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
if (!unmarshall_satellite(reply))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall satellite");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_SATELLITE, NULL, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unmarshall position coordination message */
|
|
|
|
static Eina_Bool
|
|
|
|
unmarshall_position(const Eldbus_Message *reply)
|
|
|
|
{
|
|
|
|
GeocluePositionFields fields;
|
|
|
|
int32_t level, timestamp;
|
|
|
|
double horizontal = 0.0;
|
|
|
|
double vertical = 0.0;
|
|
|
|
double latitude = 0.0;
|
|
|
|
double longitude = 0.0;
|
|
|
|
double altitude = 0.0;
|
|
|
|
Eldbus_Message_Iter *sub;
|
|
|
|
|
|
|
|
if (!eldbus_message_arguments_get(reply, "iiddd(idd)", &fields, ×tamp,
|
|
|
|
&latitude, &longitude, &altitude, &sub))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
if (!eldbus_message_iter_arguments_get(sub, "idd", &level, &horizontal, &vertical))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
position->timestamp = timestamp;
|
|
|
|
|
|
|
|
/* GeoClue uses some flags to mark position fields as valid. We set invalid
|
|
|
|
* fields to 0.0 */
|
|
|
|
if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE)
|
|
|
|
position->latitude = latitude;
|
|
|
|
else
|
|
|
|
position->latitude = 0.0;
|
|
|
|
|
|
|
|
if (fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)
|
|
|
|
position->longitude = longitude;
|
|
|
|
else
|
|
|
|
position->longitude = 0.0;
|
|
|
|
|
|
|
|
if (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE)
|
|
|
|
position->altitude = altitude;
|
|
|
|
else
|
|
|
|
position->altitude = 0.0;
|
|
|
|
|
|
|
|
position->accur->level = level;
|
|
|
|
position->accur->horizontal = horizontal;
|
|
|
|
position->accur->vertical = vertical;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
position_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!unmarshall_position(reply))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall position");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_POSITION, position, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
position_signal_cb(void *data EINA_UNUSED, const Eldbus_Message *reply)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
if (!unmarshall_position(reply))
|
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall position");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send out an event to all interested parties that we have an update */
|
|
|
|
ecore_event_add(ELOCATION_EVENT_POSITION, position, _dummy_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2014-10-28 09:01:07 -07:00
|
|
|
geoclue_start(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
DBG("GeoClue start event at %s", unique_name);
|
|
|
|
return ECORE_CALLBACK_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2014-10-28 09:01:07 -07:00
|
|
|
geoclue_stop(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
DBG("GeoClue stop event");
|
|
|
|
return ECORE_CALLBACK_DONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
_reference_add_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG("Reference added");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
_reference_del_cb(void *data EINA_UNUSED, const Eldbus_Message *reply EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
/* Dummy callback. We are not waiting for any reply here on shutdown */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
status_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-11-11 02:46:14 -08:00
|
|
|
if (!eldbus_message_arguments_get(reply,"i", &status))
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall status");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-11-11 02:46:14 -08:00
|
|
|
address_provider->status = position_provider->status = status;
|
2014-10-28 03:22:55 -07:00
|
|
|
/* Send out an event to all interested parties that we have an update */
|
2014-11-11 02:46:14 -08:00
|
|
|
ecore_event_add(ELOCATION_EVENT_STATUS, &status, _dummy_free, NULL);
|
2014-10-28 03:22:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
status_signal_cb(void *data EINA_UNUSED, const Eldbus_Message *reply)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
2014-11-11 02:46:14 -08:00
|
|
|
if (!eldbus_message_arguments_get(reply,"i", &status))
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
ERR("Error: Unable to unmarshall status");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-11-11 02:46:14 -08:00
|
|
|
address_provider->status = position_provider->status = status;
|
2014-10-28 03:22:55 -07:00
|
|
|
/* Send out an event to all interested parties that we have an update */
|
2014-11-11 02:46:14 -08:00
|
|
|
ecore_event_add(ELOCATION_EVENT_STATUS, &status, _dummy_free, NULL);
|
2014-10-28 03:22:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
_dummy_cb(void *data EINA_UNUSED, const Eldbus_Message *msg EINA_UNUSED, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We got notified from GeoClue that the meta-provider we asked for is now
|
|
|
|
* ready. That means we can finish up our initialization and set up all
|
|
|
|
* callbacks and handling for the interfaces we use on the meta-provider.
|
|
|
|
*
|
|
|
|
* We also call the interfaces to get an initial set of data that we can provide
|
|
|
|
* to eager aplications.
|
|
|
|
*/
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
create_cb(void *data EINA_UNUSED, const Eldbus_Message *reply, Eldbus_Pending *pending EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
const char *object_path;
|
|
|
|
Eina_Bool updates;
|
|
|
|
int accur_level, min_time, resources;
|
|
|
|
const char *err, *errmsg;
|
|
|
|
|
|
|
|
if (eldbus_message_error_get(reply, &err, &errmsg))
|
|
|
|
{
|
|
|
|
ERR("Error: %s %s", err, errmsg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_message_arguments_get(reply, "o", &object_path)) return;
|
|
|
|
|
|
|
|
DBG("Object path for client: %s", object_path);
|
|
|
|
|
|
|
|
/* With the created object path we now have a meta provider we can operate on.
|
|
|
|
* Geoclue handles the selection of the best provider internally for the meta
|
|
|
|
* provider */
|
|
|
|
obj_meta = eldbus_object_get(conn, GEOCLUE_DBUS_NAME, object_path);
|
|
|
|
if (!obj_meta)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get object for client");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_geoclue = eldbus_proxy_get(obj_meta, GEOCLUE_GEOCLUE_IFACE);
|
|
|
|
if (!meta_geoclue)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy for geoclue");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_address = eldbus_proxy_get(obj_meta, GEOCLUE_ADDRESS_IFACE);
|
|
|
|
if (!meta_address)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy address");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_position = eldbus_proxy_get(obj_meta, GEOCLUE_POSITION_IFACE);
|
|
|
|
if (!meta_position)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy for position");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_masterclient = eldbus_proxy_get(obj_meta, GEOCLUE_MASTERCLIENT_IFACE);
|
|
|
|
if (!meta_masterclient)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy for master client");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_velocity = eldbus_proxy_get(obj_meta, GEOCLUE_VELOCITY_IFACE);
|
|
|
|
if (!meta_velocity)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy for velocity");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_nmea = eldbus_proxy_get(obj_meta, GEOCLUE_NMEA_IFACE);
|
|
|
|
if (!meta_nmea)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy for nmea");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_satellite = eldbus_proxy_get(obj_meta, GEOCLUE_SATELLITE_IFACE);
|
|
|
|
if (!meta_satellite)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy for satellite");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send Geoclue a set of requirements we have for the provider and start the address and position
|
|
|
|
* meta provider afterwards. After this we should be ready for operation. */
|
|
|
|
updates = EINA_FALSE; /* Especially the web providers do not offer updates */
|
|
|
|
accur_level = ELOCATION_ACCURACY_LEVEL_COUNTRY;
|
|
|
|
min_time = 0; /* Minimal times between updates (no implemented yet) */
|
|
|
|
resources = ELOCATION_RESOURCE_ALL;
|
|
|
|
|
|
|
|
eldbus_proxy_signal_handler_add(meta_masterclient, "AddressProviderChanged",
|
|
|
|
meta_address_provider_info_signal_cb, address_provider);
|
|
|
|
eldbus_proxy_signal_handler_add(meta_masterclient, "PositionProviderChanged",
|
|
|
|
meta_position_provider_info_signal_cb, position_provider);
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_masterclient, "SetRequirements", _dummy_cb, NULL, -1, "iibi",
|
|
|
|
accur_level, min_time, updates, resources))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call SetRequirements");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_masterclient, "AddressStart", _dummy_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call AddressStart");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_masterclient, "PositionStart", _dummy_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call PositionStart");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_geoclue, "AddReference", _reference_add_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call AddReference");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_address, "GetAddress", address_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call GetAddress");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_position, "GetPosition", position_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call GetPosition");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_geoclue, "GetStatus", status_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call GetStatus");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_velocity, "GetVelocity", velocity_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call GetVelocity");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_nmea, "GetNmea", nmea_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call GetNmea");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_satellite, "GetSatellite", satellite_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call GetSatellite");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_satellite, "GetLastSatellite", last_satellite_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call GetLastSatellite");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_masterclient, "GetAddressProvider", meta_address_provider_info_cb,
|
|
|
|
address_provider, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call GetAddressProvider");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!eldbus_proxy_call(meta_masterclient, "GetPositionProvider", meta_position_provider_info_cb,
|
|
|
|
position_provider, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call GetPositionProvider");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
eldbus_proxy_signal_handler_add(meta_address, "AddressChanged", address_signal_cb, NULL);
|
|
|
|
eldbus_proxy_signal_handler_add(meta_position, "PositionChanged", position_signal_cb, NULL);
|
|
|
|
eldbus_proxy_signal_handler_add(meta_geoclue, "StatusChanged", status_signal_cb, NULL);
|
|
|
|
eldbus_proxy_signal_handler_add(meta_velocity, "VelocityChanged", velocity_signal_cb, NULL);
|
|
|
|
eldbus_proxy_signal_handler_add(meta_nmea, "NmeaChanged", nmea_signal_cb, NULL);
|
|
|
|
eldbus_proxy_signal_handler_add(meta_satellite, "SatelliteChanged", satellite_signal_cb, NULL);
|
|
|
|
|
|
|
|
ecore_event_add(ELOCATION_EVENT_META_READY, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-10-28 09:01:07 -07:00
|
|
|
_name_owner_changed(void *data EINA_UNUSED, const char *bus EINA_UNUSED, const char *old, const char *new)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
if (old[0] == '\0' && new[0] != '\0')
|
|
|
|
{
|
|
|
|
ecore_event_add(ELOCATION_EVENT_IN, NULL, NULL, NULL);
|
|
|
|
unique_name = strdup(new);
|
|
|
|
}
|
|
|
|
else if (old[0] != '\0' && new[0] == '\0')
|
|
|
|
{
|
|
|
|
if (strcmp(unique_name, old) != 0)
|
|
|
|
WARN("%s was not the known name %s, ignored.", old, unique_name);
|
|
|
|
else
|
|
|
|
ecore_event_add(ELOCATION_EVENT_OUT, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-12-13 09:53:33 -08:00
|
|
|
DBG("unknown change from %s to %s", old, new);
|
2014-10-28 03:22:55 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to request a landmarks position based on an address object */
|
|
|
|
EAPI Eina_Bool
|
2014-10-28 09:01:07 -07:00
|
|
|
elocation_landmarks_get(Elocation_Position *position_shadow EINA_UNUSED, Elocation_Address *address_shadow EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
Eldbus_Message *msg;
|
|
|
|
Eldbus_Message_Iter *iter;
|
|
|
|
const char *keyword = NULL, *lang = NULL, *country_code = NULL;
|
|
|
|
int limit = 0;
|
|
|
|
double left= 0.0, top = 0.0, right = 0.0, bottom = 0.0;
|
|
|
|
|
|
|
|
msg = eldbus_proxy_method_call_new(master_poi, "SearchByPosition");
|
|
|
|
iter = eldbus_message_iter_get(msg);
|
|
|
|
eldbus_message_iter_basic_append(iter, 's', keyword);
|
|
|
|
eldbus_message_iter_basic_append(iter, 's', lang);
|
|
|
|
eldbus_message_iter_basic_append(iter, 's', country_code);
|
|
|
|
eldbus_message_iter_basic_append(iter, 'i', limit);
|
|
|
|
eldbus_message_iter_basic_append(iter, 'd', left);
|
|
|
|
eldbus_message_iter_basic_append(iter, 'd', top);
|
|
|
|
eldbus_message_iter_basic_append(iter, 'd', right);
|
|
|
|
eldbus_message_iter_basic_append(iter, 'd', bottom);
|
|
|
|
if (!eldbus_proxy_send(master_poi, msg, poi_cb, NULL, -1))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call SearchByPosition");
|
|
|
|
eldbus_message_unref(msg);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to get an address from a position */
|
|
|
|
EAPI Eina_Bool
|
2014-10-28 09:01:07 -07:00
|
|
|
elocation_position_to_address(Elocation_Position *position_shadow, Elocation_Address *address_shadow EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
Eldbus_Message *msg;
|
|
|
|
Eldbus_Message_Iter *iter, *structure;
|
|
|
|
|
|
|
|
msg = eldbus_proxy_method_call_new(geonames_rgeocode, "PositionToAddress");
|
|
|
|
iter = eldbus_message_iter_get(msg);
|
|
|
|
eldbus_message_iter_basic_append(iter, 'd', position_shadow->latitude);
|
|
|
|
eldbus_message_iter_basic_append(iter, 'd', position_shadow->longitude);
|
|
|
|
structure = eldbus_message_iter_container_new(iter, 'r', NULL);
|
|
|
|
eldbus_message_iter_basic_append(structure, 'i', position_shadow->accur->level);
|
|
|
|
eldbus_message_iter_basic_append(structure, 'd', position_shadow->accur->horizontal);
|
|
|
|
eldbus_message_iter_basic_append(structure, 'd', position_shadow->accur->vertical);
|
|
|
|
eldbus_message_iter_container_close(iter, structure);
|
|
|
|
if (!eldbus_proxy_send(geonames_rgeocode, msg, rgeocode_cb, NULL, -1))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call PositionToAddress");
|
|
|
|
eldbus_message_unref(msg);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to get a position from and address */
|
|
|
|
EAPI Eina_Bool
|
2014-10-28 09:01:07 -07:00
|
|
|
elocation_address_to_position(Elocation_Address *address_shadow, Elocation_Position *position_shadow EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
Eldbus_Message *msg;
|
|
|
|
Eldbus_Message_Iter *iter, *array;
|
|
|
|
|
|
|
|
/* In function macro to generate a key value pair structure for the dict */
|
|
|
|
#define ENTRY(key) { #key, address_shadow->key }
|
|
|
|
struct keyval {
|
|
|
|
const char *key;
|
|
|
|
const char *val;
|
|
|
|
} keyval[] = {
|
|
|
|
ENTRY(country),
|
|
|
|
ENTRY(countrycode),
|
|
|
|
ENTRY(locality),
|
|
|
|
ENTRY(postalcode),
|
|
|
|
ENTRY(region),
|
|
|
|
ENTRY(timezone),
|
|
|
|
{ NULL, NULL }
|
|
|
|
};
|
|
|
|
#undef ENTRY
|
|
|
|
|
|
|
|
struct keyval *k;
|
|
|
|
|
|
|
|
msg = eldbus_proxy_method_call_new(geonames_geocode, "AddressToPosition");
|
|
|
|
iter = eldbus_message_iter_get(msg);
|
|
|
|
|
|
|
|
array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
|
|
|
|
|
|
|
|
for (k = keyval; k && k->key; k++)
|
|
|
|
{
|
|
|
|
Eldbus_Message_Iter *entry;
|
|
|
|
|
|
|
|
if (!k->val) continue;
|
|
|
|
|
|
|
|
entry = eldbus_message_iter_container_new(array, 'e', NULL);
|
|
|
|
eldbus_message_iter_arguments_append(entry, "ss", k->key, k->val);
|
|
|
|
eldbus_message_iter_container_close(array, entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
eldbus_message_iter_container_close(iter, array);
|
|
|
|
|
|
|
|
if (!eldbus_proxy_send(geonames_geocode, msg, geocode_cb, NULL, -1))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call AddressToPosition");
|
|
|
|
eldbus_message_unref(msg);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to get the position from a freeform text input style
|
|
|
|
* address
|
|
|
|
*/
|
|
|
|
EAPI Eina_Bool
|
2014-10-28 09:01:07 -07:00
|
|
|
elocation_freeform_address_to_position(const char *freeform_address, Elocation_Position *position_shadow EINA_UNUSED)
|
2014-10-28 03:22:55 -07:00
|
|
|
{
|
|
|
|
if (!eldbus_proxy_call(geonames_geocode, "FreeformAddressToPosition", geocode_cb, NULL, -1, "s", freeform_address))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call FreeformAddressToPosition");
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to request the current address */
|
|
|
|
EAPI Eina_Bool
|
|
|
|
elocation_address_get(Elocation_Address *address_shadow)
|
|
|
|
{
|
|
|
|
if (!address) return EINA_FALSE;
|
2014-11-11 03:02:10 -08:00
|
|
|
if (address == address_shadow) return EINA_TRUE;
|
2014-10-28 03:22:55 -07:00
|
|
|
|
2017-07-30 20:18:00 -07:00
|
|
|
*address_shadow = *address;
|
2014-10-28 03:22:55 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to request the current position */
|
|
|
|
EAPI Eina_Bool
|
|
|
|
elocation_position_get(Elocation_Position *position_shadow)
|
|
|
|
{
|
|
|
|
if (!position) return EINA_FALSE;
|
2014-11-11 03:02:10 -08:00
|
|
|
if (position == position_shadow) return EINA_TRUE;
|
2014-10-28 03:22:55 -07:00
|
|
|
|
2017-07-30 20:18:00 -07:00
|
|
|
*position_shadow = *position;
|
2014-10-28 03:22:55 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to request the status */
|
|
|
|
EAPI Eina_Bool
|
|
|
|
elocation_status_get(int *status_shadow)
|
|
|
|
{
|
|
|
|
if (status < 0) return EINA_FALSE;
|
2014-11-11 03:02:10 -08:00
|
|
|
if (&status == status_shadow) return EINA_TRUE;
|
2014-10-28 03:22:55 -07:00
|
|
|
|
2017-07-30 20:18:00 -07:00
|
|
|
*status_shadow = status;
|
2014-10-28 03:22:55 -07:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to create a new position object */
|
|
|
|
EAPI Elocation_Position *
|
|
|
|
elocation_position_new(void)
|
|
|
|
{
|
|
|
|
/* Malloc the global struct we operate on here in this lib. This shadows the
|
|
|
|
* updated data we are giving to the application */
|
|
|
|
position = calloc(1, sizeof(Elocation_Position));
|
|
|
|
if (!position) return NULL;
|
|
|
|
|
|
|
|
position->accur = calloc(1, sizeof(Elocation_Accuracy));
|
|
|
|
if (!position->accur) return NULL;
|
|
|
|
|
|
|
|
return position;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to create an new address object */
|
|
|
|
EAPI Elocation_Address *
|
|
|
|
elocation_address_new(void)
|
|
|
|
{
|
|
|
|
/* Malloc the global struct we operate on here in this lib. This shadows the
|
|
|
|
* updated data we are giving to the application */
|
|
|
|
address = calloc(1, sizeof(Elocation_Address));
|
|
|
|
if (!address) return NULL;
|
|
|
|
|
|
|
|
address->accur = calloc(1, sizeof(Elocation_Accuracy));
|
|
|
|
if (!address->accur) return NULL;
|
|
|
|
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to free an position object */
|
|
|
|
EAPI void
|
|
|
|
elocation_position_free(Elocation_Position *position_shadow)
|
|
|
|
{
|
|
|
|
if (position != position_shadow)
|
|
|
|
{
|
|
|
|
ERR("Corrupted position object");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(position->accur);
|
|
|
|
free(position);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to free an address object */
|
|
|
|
EAPI void
|
|
|
|
elocation_address_free(Elocation_Address *address_shadow)
|
|
|
|
{
|
|
|
|
if (address != address_shadow)
|
|
|
|
{
|
|
|
|
ERR("Corrupted address object");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (address)
|
|
|
|
{
|
|
|
|
free(address->country);
|
|
|
|
free(address->countrycode);
|
|
|
|
free(address->locality);
|
|
|
|
free(address->postalcode);
|
|
|
|
free(address->region);
|
|
|
|
free(address->timezone);
|
|
|
|
free(address->accur);
|
|
|
|
free(address);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-31 01:45:31 -07:00
|
|
|
/* Public API function to initialize the elocation library */
|
2014-10-28 03:22:55 -07:00
|
|
|
EAPI Eina_Bool
|
|
|
|
elocation_init(void)
|
|
|
|
{
|
|
|
|
Eldbus_Object *obj_master = NULL;
|
|
|
|
Eldbus_Object *obj_geonames = NULL;
|
|
|
|
|
|
|
|
if (!eina_init()) return EINA_FALSE;
|
|
|
|
if (!ecore_init()) return EINA_FALSE;
|
|
|
|
if (!eldbus_init()) return EINA_FALSE;
|
|
|
|
|
|
|
|
_elocation_log_dom = eina_log_domain_register("elocation", EINA_COLOR_BLUE);
|
|
|
|
if (_elocation_log_dom < 0)
|
|
|
|
{
|
|
|
|
EINA_LOG_ERR("Could not register 'elocation' log domain.");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create objects, one for each kind, we operate on internally */
|
|
|
|
address_provider = calloc(1, sizeof(Elocation_Provider));
|
|
|
|
position_provider = calloc(1, sizeof(Elocation_Provider));
|
|
|
|
|
|
|
|
addr_geocode = calloc(1, sizeof(Elocation_Address));
|
|
|
|
if (!addr_geocode) return EINA_FALSE;
|
|
|
|
|
|
|
|
addr_geocode->accur = calloc(1, sizeof(Elocation_Accuracy));
|
|
|
|
if (!addr_geocode->accur) return EINA_FALSE;
|
|
|
|
|
|
|
|
pos_geocode = calloc(1, sizeof(Elocation_Position));
|
|
|
|
if (!pos_geocode) return EINA_FALSE;
|
|
|
|
|
|
|
|
pos_geocode->accur = calloc(1, sizeof(Elocation_Accuracy));
|
|
|
|
if (!pos_geocode->accur) return EINA_FALSE;
|
|
|
|
|
|
|
|
conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
|
|
|
|
if (!conn)
|
|
|
|
{
|
|
|
|
ERR("Error: could not connect to session bus.");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create all ecore event types we send out to interested applications */
|
2017-12-18 18:14:37 -08:00
|
|
|
ELOCATION_EVENT_IN = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_OUT = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_STATUS = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_POSITION = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_ADDRESS = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_VELOCITY = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_GEOCODE = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_REVERSEGEOCODE = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_NMEA = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_SATELLITE = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_POI = ecore_event_type_new();
|
|
|
|
ELOCATION_EVENT_META_READY = ecore_event_type_new();
|
2014-10-28 03:22:55 -07:00
|
|
|
|
|
|
|
obj_master= eldbus_object_get(conn, GEOCLUE_DBUS_NAME, GEOCLUE_OBJECT_PATH);
|
|
|
|
if (!obj_master)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get object");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
manager_master = eldbus_proxy_get(obj_master, GEOCLUE_MASTER_IFACE);
|
|
|
|
if (!manager_master)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a meta provider for all normal use cases. This will allow GeoClue
|
|
|
|
* to decide which provider is the best for us internally.
|
|
|
|
* Right now we don't have the functionality in place to specifically request
|
|
|
|
* a provider but we maybe need this in the future. We will try without it
|
|
|
|
* for now.
|
|
|
|
*/
|
|
|
|
if (!eldbus_proxy_call(manager_master, "Create", create_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call Create");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
master_poi = eldbus_proxy_get(obj_master, GEOCLUE_POI_IFACE);
|
|
|
|
if (!master_poi)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Geocode and reverse geocode never show up as meta provider. Still we want
|
|
|
|
* to be able to convert so we keep them around directly here. */
|
|
|
|
obj_geonames= eldbus_object_get(conn, GEONAMES_DBUS_NAME, GEONAMES_OBJECT_PATH);
|
|
|
|
if (!obj_geonames)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get object for geonames");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
geonames_geocode = eldbus_proxy_get(obj_geonames, GEOCLUE_GEOCODE_IFACE);
|
|
|
|
if (!geonames_geocode)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
geonames_rgeocode = eldbus_proxy_get(obj_geonames, GEOCLUE_REVERSEGEOCODE_IFACE);
|
|
|
|
if (!geonames_rgeocode)
|
|
|
|
{
|
|
|
|
ERR("Error: could not get proxy");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
eldbus_name_owner_changed_callback_add(conn, GEOCLUE_DBUS_NAME, _name_owner_changed,
|
|
|
|
NULL, EINA_TRUE);
|
|
|
|
|
|
|
|
ecore_event_handler_add(ELOCATION_EVENT_IN, geoclue_start, NULL);
|
|
|
|
ecore_event_handler_add(ELOCATION_EVENT_OUT, geoclue_stop, NULL);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public API function to shutdown the elocation library form the application */
|
|
|
|
EAPI void
|
|
|
|
elocation_shutdown(void)
|
|
|
|
{
|
|
|
|
/* Depending on if the create_cb was successfully received meta_geoclue is
|
|
|
|
* setup or not. So we * need to check here if this is not the case
|
|
|
|
*/
|
|
|
|
if (meta_geoclue)
|
|
|
|
{
|
|
|
|
/* To allow geoclue freeing unused providers we free our reference on it here */
|
|
|
|
if (!eldbus_proxy_call(meta_geoclue, "RemoveReference", _reference_del_cb, NULL, -1, ""))
|
|
|
|
{
|
|
|
|
ERR("Error: could not call RemoveReference");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-09 16:17:24 -08:00
|
|
|
ecore_event_type_flush(ELOCATION_EVENT_IN,
|
|
|
|
ELOCATION_EVENT_OUT,
|
|
|
|
ELOCATION_EVENT_STATUS,
|
|
|
|
ELOCATION_EVENT_POSITION,
|
|
|
|
ELOCATION_EVENT_ADDRESS,
|
|
|
|
ELOCATION_EVENT_VELOCITY,
|
|
|
|
ELOCATION_EVENT_GEOCODE,
|
|
|
|
ELOCATION_EVENT_REVERSEGEOCODE,
|
|
|
|
ELOCATION_EVENT_NMEA,
|
|
|
|
ELOCATION_EVENT_SATELLITE,
|
|
|
|
ELOCATION_EVENT_POI,
|
|
|
|
ELOCATION_EVENT_META_READY);
|
|
|
|
|
2014-10-28 03:22:55 -07:00
|
|
|
/* Quite a bit of allocated string and generic memory cleanup. This should be
|
|
|
|
*less when we went away from all this global var business.
|
|
|
|
*/
|
|
|
|
if (address_provider)
|
|
|
|
{
|
|
|
|
free(address_provider->name);
|
|
|
|
free(address_provider->description);
|
|
|
|
free(address_provider->service);
|
|
|
|
free(address_provider->path);
|
|
|
|
free(address_provider);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (position_provider)
|
|
|
|
{
|
|
|
|
free(position_provider->name);
|
|
|
|
free(position_provider->description);
|
|
|
|
free(position_provider->service);
|
|
|
|
free(position_provider->path);
|
|
|
|
free(position_provider);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pos_geocode)
|
|
|
|
{
|
|
|
|
free(pos_geocode->accur);
|
|
|
|
free(pos_geocode);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addr_geocode)
|
|
|
|
{
|
|
|
|
free(addr_geocode->country);
|
|
|
|
free(addr_geocode->countrycode);
|
|
|
|
free(addr_geocode->locality);
|
|
|
|
free(addr_geocode->postalcode);
|
|
|
|
free(addr_geocode->region);
|
|
|
|
free(addr_geocode->timezone);
|
|
|
|
free(addr_geocode->accur);
|
|
|
|
free(addr_geocode);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Unreference some eldbus strcutures we now longer use. To allow eldbus to
|
|
|
|
* free them internally.
|
|
|
|
*/
|
|
|
|
if (manager_master)
|
|
|
|
eldbus_proxy_unref(manager_master);
|
|
|
|
|
|
|
|
eldbus_name_owner_changed_callback_del(conn, GEOCLUE_DBUS_NAME, _name_owner_changed, NULL);
|
|
|
|
eldbus_connection_unref(conn);
|
|
|
|
eldbus_shutdown();
|
|
|
|
ecore_shutdown();
|
|
|
|
eina_log_domain_unregister(_elocation_log_dom);
|
|
|
|
eina_shutdown();
|
|
|
|
}
|