summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac37
-rw-r--r--pc/elocation.pc.in12
-rw-r--r--src/Makefile.am2
-rw-r--r--src/Makefile_Elocation.am16
-rw-r--r--src/lib/elocation/Elocation.h418
-rw-r--r--src/lib/elocation/elocation.c1416
-rw-r--r--src/lib/elocation/elocation_private.h181
7 files changed, 2081 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index c9cacb795a..8b030241ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4374,6 +4374,42 @@ EFL_EVAL_PKGS([ELUA])
4374EFL_LIB_END_OPTIONAL([Elua]) 4374EFL_LIB_END_OPTIONAL([Elua])
4375#### End of Elua 4375#### End of Elua
4376 4376
4377#### Elocation
4378
4379EFL_LIB_START([Elocation])
4380
4381### Default values
4382
4383### Additional options to configure
4384
4385### Checks for programs
4386
4387### Checks for libraries
4388EFL_PLATFORM_DEPEND([ELOCATION], [evil])
4389EFL_INTERNAL_DEPEND_PKG([ELOCATION], [eina])
4390EFL_INTERNAL_DEPEND_PKG([ELOCATION], [eo])
4391EFL_INTERNAL_DEPEND_PKG([ELOCATION], [ecore])
4392EFL_INTERNAL_DEPEND_PKG([ELOCATION], [eldbus])
4393
4394EFL_ADD_LIBS([ELOCATION], [-lm])
4395
4396### Checks for header files
4397
4398### Checks for types
4399
4400### Checks for structures
4401
4402### Checks for compiler characteristics
4403
4404### Checks for linker characteristics
4405
4406### Checks for library functions
4407
4408### Check availability
4409
4410EFL_LIB_END([Elocation])
4411#### End of Elocation
4412
4377### Add Wayland server library if test is enabled 4413### Add Wayland server library if test is enabled
4378if test "x${want_tests}" = "xyes" -a "x${want_wayland}" = "xyes"; then 4414if test "x${want_tests}" = "xyes" -a "x${want_wayland}" = "xyes"; then
4379 EFL_DEPEND_PKG([ECORE_WAYLAND_SRV], [WAYLAND], [wayland-server >= 1.3.0]) 4415 EFL_DEPEND_PKG([ECORE_WAYLAND_SRV], [WAYLAND], [wayland-server >= 1.3.0])
@@ -4496,6 +4532,7 @@ pc/edje-cxx.pc
4496pc/emotion.pc 4532pc/emotion.pc
4497pc/ethumb.pc 4533pc/ethumb.pc
4498pc/ethumb_client.pc 4534pc/ethumb_client.pc
4535pc/elocation.pc
4499dbus-services/org.enlightenment.Efreet.service 4536dbus-services/org.enlightenment.Efreet.service
4500dbus-services/org.enlightenment.Ethumb.service 4537dbus-services/org.enlightenment.Ethumb.service
4501systemd-services/efreet.service 4538systemd-services/efreet.service
diff --git a/pc/elocation.pc.in b/pc/elocation.pc.in
new file mode 100644
index 0000000000..5b6e52bb3d
--- /dev/null
+++ b/pc/elocation.pc.in
@@ -0,0 +1,12 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: elocation
7Description: Enlightenment location library
8@pkgconfig_requires_private@: @requirements_elocation@
9Version: @VERSION@
10Libs: -L${libdir} -lelocation
11Libs.private: -lm
12Cflags: -I${includedir}/elocation-@VMAJ@
diff --git a/src/Makefile.am b/src/Makefile.am
index fdb13a2976..72830d52ac 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -78,8 +78,8 @@ include Makefile_Eolian_Cxx.am
78include Makefile_Eet_Cxx.am 78include Makefile_Eet_Cxx.am
79include Makefile_Eo_Cxx.am 79include Makefile_Eo_Cxx.am
80include Makefile_Efl_Cxx.am 80include Makefile_Efl_Cxx.am
81
82include Makefile_Elua.am 81include Makefile_Elua.am
82include Makefile_Elocation.am
83 83
84.PHONY: benchmark examples 84.PHONY: benchmark examples
85 85
diff --git a/src/Makefile_Elocation.am b/src/Makefile_Elocation.am
new file mode 100644
index 0000000000..0fc5b696ed
--- /dev/null
+++ b/src/Makefile_Elocation.am
@@ -0,0 +1,16 @@
1### Library
2
3lib_LTLIBRARIES += lib/elocation/libelocation.la
4
5installed_elocationsmainheadersdir = $(includedir)/elocation-@VMAJ@
6dist_installed_elocationsmainheaders_DATA = \
7lib/elocation/Elocation.h \
8lib/elocation/elocation_private.h
9
10lib_elocation_libelocation_la_SOURCES = \
11lib/elocation/elocation.c
12
13lib_elocation_libelocation_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ELOCATION_CFLAGS@
14lib_elocation_libelocation_la_LIBADD = @ELOCATION_LIBS@
15lib_elocation_libelocation_la_DEPENDENCIES = @ELOCATION_INTERNAL_LIBS@
16lib_elocation_libelocation_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
diff --git a/src/lib/elocation/Elocation.h b/src/lib/elocation/Elocation.h
new file mode 100644
index 0000000000..851b679172
--- /dev/null
+++ b/src/lib/elocation/Elocation.h
@@ -0,0 +1,418 @@
1/**
2 * @brief Elocation Library
3 *
4 * @mainpage Elocation
5 * @version 0.0.0
6 * @author Stefan Schmidt <stefan@datenfreihafen.org>
7 * @date 2012
8 *
9 * @section intro Elocation Use Cases
10 *
11 * Elocation is meant as a convenience library to ease application developers
12 * the usage of geo information in their apps. Adding a geo tag to a picture or
13 * translating an address to a GPS position and show it on a map widget are just
14 * some of the use cases.
15 *
16 * In the beginning elocation will rely on the GeoClue DBus service. Its has
17 * providers for various techniques to get hold off the current position.
18 * Ranging from GeoIP over wifi and GSM cell location to GPS. As well as
19 * provider to translates between location in a textual form to coordinates
20 * (GeoCode).
21 *
22 * Elocation covers all of these interfaces but in the end it depends on your
23 * system and the installed GeoClue providers what can be used.
24 *
25 * Currently it offer the following functionality:
26 * @li Request current address in textual form
27 * @li Request current position in GPS format
28 * @li Translate a position into and address or an address in a position
29 *
30 * You can find the API documentation at @ref Location
31*/
32#ifndef _ELOCATION_H
33#define _ELOCATION_H
34
35#ifdef EAPI
36# undef EAPI
37#endif
38
39#ifdef _WIN32
40# ifdef EFL_ECORE_BUILD
41# ifdef DLL_EXPORT
42# define EAPI __declspec(dllexport)
43# else
44# define EAPI
45# endif /* ! DLL_EXPORT */
46# else
47# define EAPI __declspec(dllimport)
48# endif /* ! EFL_ECORE_BUILD */
49#else
50# ifdef __GNUC__
51# if __GNUC__ >= 4
52# define EAPI __attribute__ ((visibility("default")))
53# else
54# define EAPI
55# endif
56# else
57# define EAPI
58# endif
59#endif /* ! _WIN32 */
60
61#include <stdio.h>
62
63#include <Ecore.h>
64#include <Eldbus.h>
65
66/**
67 * @file Elocation.h
68 *
69 * @defgroup Location Location
70 */
71
72/**
73 * @ingroup Location
74 * @brief Available location events that are emitted from the library
75 * @since 1.8
76 *
77 * Ecore events emitted by the library. Applications can register ecore event
78 * handlers to react on such events. After the initial query this can be used
79 * to keep track of changes and update your UI or data accordingly.
80 * @{
81 */
82EAPI extern int ELOCATION_EVENT_STATUS; /**< Status changed */
83EAPI extern int ELOCATION_EVENT_POSITION; /**< Position changed */
84EAPI extern int ELOCATION_EVENT_ADDRESS; /**< Address changed */
85EAPI extern int ELOCATION_EVENT_VELOCITY; /**< Velocity changed */
86EAPI extern int ELOCATION_EVENT_GEOCODE; /**< Reply for geocode translation arrived */
87EAPI extern int ELOCATION_EVENT_REVERSEGEOCODE; /**< Reply for geocode translation arrived */
88EAPI extern int ELOCATION_EVENT_NMEA; /**< NMEA update */
89EAPI extern int ELOCATION_EVENT_SATELLITE; /**< Satellite info changed */
90EAPI extern int ELOCATION_EVENT_POI; /**< POI reply */
91EAPI extern int ELOCATION_EVENT_META_READY; /**< Meta provider is ready to be used */
92/**@}*/
93
94/**
95 * @ingroup Location
96 * @typedef Elocation_Accuracy_Level
97 * @since 1.8
98 *
99 * Different location accuracy levels from country level up to detailed,
100 * e.g. GPS, information.
101 * @{
102 */
103typedef enum {
104 ELOCATION_ACCURACY_LEVEL_NONE = 0,
105 ELOCATION_ACCURACY_LEVEL_COUNTRY,
106 ELOCATION_ACCURACY_LEVEL_REGION,
107 ELOCATION_ACCURACY_LEVEL_LOCALITY,
108 ELOCATION_ACCURACY_LEVEL_POSTALCODE,
109 ELOCATION_ACCURACY_LEVEL_STREET,
110 ELOCATION_ACCURACY_LEVEL_DETAILED,
111} Elocation_Accuracy_Level;
112/**@}*/
113
114/**
115 * @ingroup Location
116 * @typedef Elocation_Resource_Flags
117 * @since 1.8
118 *
119 * Flags for available system resources to be used for locating. So far they
120 * cover physical resources like network connection, cellular network
121 * connection and GPS.
122 * @{
123 */
124typedef enum {
125 ELOCATION_RESOURCE_NONE = 0,
126 ELOCATION_RESOURCE_NETWORK = 1 << 0, /**< Internet connection is available */
127 ELOCATION_RESOURCE_CELL = 1 << 1, /**< Cell network information, e.g. GSM, is available */
128 ELOCATION_RESOURCE_GPS = 1 << 2, /**< GPS information is available */
129
130 ELOCATION_RESOURCE_ALL = (1 << 10) - 1 /**< All resources are available */
131} Elocation_Resource_Flags;
132/**@}*/
133
134/**
135 * @ingroup Location
136 * @typedef Elocation_Accuracy
137 * @since 1.8
138 *
139 * Information about the accuracy of the reported location. For details about
140 * the level of accuracy see #Elocation_Accuracy_Level. It also covers
141 * horizontal and vertical accuracy. The values depend on the used provider
142 * and may very in quality.
143 */
144typedef struct _Elocation_Accuracy
145{
146 Elocation_Accuracy_Level level;
147 double horizontal;
148 double vertical;
149} Elocation_Accuracy;
150
151/**
152 * @ingroup Location
153 * @typedef Elocation_Address
154 * @since 1.8
155 *
156 * Location information in textual form. Depending on the used provider this
157 * can cover only the country or a detailed address with postcode and street.
158 * The level of detail varies depending on the used provider.
159 * A timestamp is available to calculate the age of the address data.
160 */
161typedef struct _Elocation_Address
162{
163 unsigned int timestamp; /**< Timestamp of data read out in seconds since epoch */
164 char *country;
165 char *countrycode;
166 char *locality;
167 char *postalcode;
168 char *region;
169 char *timezone;
170 Elocation_Accuracy *accur;
171} Elocation_Address;
172
173/**
174 * @ingroup Location
175 * @typedef Elocation_Position
176 * @since 1.8
177 *
178 * Location information based on the GPS grid. Latitude, longitude and altitude.
179 * A timestamp is available to calculate the age of the address data.
180 */
181typedef struct _Elocation_Postion
182{
183 unsigned int timestamp; /**< Timestamp of data read out in seconds since epoch */
184 double latitude;
185 double longitude;
186 double altitude;
187 Elocation_Accuracy *accur;
188} Elocation_Position;
189
190/**
191 * @ingroup Location
192 * @typedef Elocation_Velocity
193 * @since 1.8
194 *
195 * Velocity information. So far this interface is only offered with GPS based
196 * providers. It offers information about speed, direction and climb.
197 * A timestamp is available to calculate the age of the address data.
198 *
199 * FIXME: check units and formats of this values coming in from GeoClue
200 */
201typedef struct _Elocation_Velocity
202{
203 unsigned int timestamp; /**< Timestamp of data read out in seconds since epoch */
204 double speed;
205 double direction;
206 double climb;
207} Elocation_Velocity;
208
209/**
210 * @ingroup Location
211 * @typedef Elocation_Requirements
212 * @since 1.8
213 *
214 * Requirement settings for the location provider. Requirements can be a level
215 * of accuracy or allowed resources like network access or GPS. See
216 * #Elocation_Resource_Flags for all available resource flags.
217 *
218 * Based on this setting the best provider is chosen between the available
219 * providers of GeoClue.
220 */
221typedef struct _Elocation_Requirements
222{
223 Elocation_Accuracy_Level accurancy_level;
224 int min_time; /**< Minimal time between updates. Not implemented upstream */
225 Eina_Bool require_update;
226 Elocation_Resource_Flags allowed_resources;
227} Elocation_Requirements;
228
229/**
230 * @brief Create a new address object to operate on.
231 * @return Address object.
232 *
233 * The returned address object is safe to be operated on. It can be used for
234 * all other elocation functions. Once finished with it it need to be destroyed
235 * with a call to #elocation_address_free.
236 *
237 * @ingroup Location
238 * @since 1.8
239 */
240EAPI Elocation_Address *elocation_address_new(void);
241
242/**
243 * @brief Free an address object
244 * @param address Address object to be freed.
245 *
246 * Destroys an address object created with #elocation_address_new. Should be
247 * used during the cleanup of the application or whenever the address object is
248 * no longer needed.
249 *
250 * @ingroup Location
251 * @since 1.8
252 */
253EAPI void elocation_address_free(Elocation_Address *address);
254
255/**
256 * @brief Create a new position object to operate on.
257 * @return Position object.
258 *
259 * The returned address object is safe to be operated on. It can be used for
260 * all other elocation functions. Once finished with it it need to be destroyed
261 * with a call to #elocation_address_free.
262 *
263 * @ingroup Location
264 * @since 1.8
265 */
266EAPI Elocation_Position *elocation_position_new(void);
267
268/**
269 * @brief Free an position object
270 * @param position Position object to be freed.
271 *
272 * Destroys a position object created with #elocation_address_new. Should be
273 * used during the cleanup of the application or whenever the location object is
274 * no longer needed.
275 *
276 * @ingroup Location
277 * @since 1.8
278 */
279EAPI void elocation_position_free(Elocation_Position *position);
280
281/**
282 * @brief Get the current address information.
283 * @param address Address struct to be filled with information.
284 * @return EINA_TRUE for success and EINA_FALSE for failure.
285 *
286 * Request the latest address. The requested to the underling components might
287 * be asynchronous so better check the timestamp if the data has changed. To get
288 * events when the address changes one can also subscribe to the
289 * #ELOCATION_EVENT_ADDRESS ecore event which will have the address object as
290 * event.
291 *
292 * @ingroup Location
293 * @since 1.8
294 */
295EAPI Eina_Bool elocation_address_get(Elocation_Address *address);
296
297/**
298 * @brief Get the current position information.
299 * @param position Position struct to be filled with information.
300 * @return EINA_TRUE for success and EINA_FALSE for failure.
301 *
302 * Request the latest position. The requested to the underling components might
303 * be asynchronous so better check the timestamp if the data has changed. To get
304 * events when the position changes one can also subscribe to the
305 * #ELOCATION_EVENT_POSITION ecore event which will have the position object as
306 * event.
307 *
308 * @ingroup Location
309 * @since 1.8
310 */
311EAPI Eina_Bool elocation_position_get(Elocation_Position *position);
312
313/**
314 * @brief Get the current status.
315 * @param status Status
316 * @return EINA_TRUE for success and EINA_FALSE for failure.
317 *
318 * @ingroup Location
319 * @since 1.8
320 */
321EAPI Eina_Bool elocation_status_get(int *status);
322
323/**
324 * @brief Set the requirements.
325 * @param requirements Requirements
326 * @return EINA_TRUE for success and EINA_FALSE for failure.
327 *
328 * Set the requirements for selecting a provider.
329 *
330 * @ingroup Location
331 * @since 1.8
332 */
333EAPI Eina_Bool elocation_requirements_set(Elocation_Requirements *requirements);
334
335/**
336 * @brief Convert position to address
337 * @param position_shadow Position input
338 * @param address_shadow Address output
339 * @return EINA_TRUE for success and EINA_FALSE for failure.
340 *
341 * Use a GeoCode provider to translate from a given GPS coordinate
342 * representation of a location to a representation in textual form.
343 *
344 * @ingroup Location
345 * @since 1.8
346 */
347EAPI Eina_Bool elocation_position_to_address(Elocation_Position *position_shadow, Elocation_Address *address_shadow);
348
349/**
350 * @brief Convert address to position
351 * @param address_shadow Address input
352 * @param position_shadow Position output
353 * @return EINA_TRUE for success and EINA_FALSE for failure.
354 *
355 * Use a GeoCode provider to translate from a given textual form
356 * representation of a location to a representation as GPS coordinates.
357 *
358 * @ingroup Location
359 * @since 1.8
360 */
361EAPI Eina_Bool elocation_address_to_position(Elocation_Address *address_shadow, Elocation_Position *position_shadow);
362
363/**
364 * @brief Convert free form address tring to position
365 * @param freeform_address Address string in free form
366 * @param position_shadow Position output
367 * @return EINA_TRUE for success and EINA_FALSE for failure.
368 *
369 * Similar GeoCode translation from textual form to GPS coordinates as
370 * #elocation_address_to_position but in this case the address is a simple
371 * string which hopefully contains enough information for the provider to
372 * understand and translate.
373 *
374 * Useful for an easy search interface in an application but also more error
375 * prone regarding correct results.
376 *
377 * @ingroup Location
378 * @since 1.8
379 */
380EAPI Eina_Bool elocation_freeform_address_to_position(const char *freeform_address, Elocation_Position *position_shadow);
381
382/**
383 * @brief Request a landmark position
384 * @param position_shadow Position ouput
385 * @param address_shadow Address input
386 * @return EINA_TRUE for success and EINA_FALSE for failure.
387 *
388 * Request a landmark position also known as Point Of Interest (POI) from
389 * GeoClue.
390 *
391 * @ingroup Location
392 * @since 1.8
393 */
394EAPI Eina_Bool elocation_landmarks_get(Elocation_Position *position_shadow, Elocation_Address *address_shadow);
395
396/**
397 * @brief Initialize the elocation subsystem.
398 * @return EINA_TRUE for success and EINA_FALSE for failure.
399 *
400 * This function must be called before using any of the Elocation functionality
401 * in your application to make sure it it setup correctly for usage.
402 *
403 * @ingroup Location
404 * @since 1.8
405 */
406EAPI Eina_Bool elocation_init(void);
407
408/**
409 * @brief Cleanup and shutdown the elocation subsystem.
410 *
411 * This function must be called when the application is no longer using any of
412 * the Elocation functionality to allow the subsystem to shutdown cleanly.
413 *
414 * @ingroup Location
415 * @since 1.8
416 */
417EAPI void elocation_shutdown(void);
418#endif
diff --git a/src/lib/elocation/elocation.c b/src/lib/elocation/elocation.c
new file mode 100644
index 0000000000..a14d19e483
--- /dev/null
+++ b/src/lib/elocation/elocation.c
@@ -0,0 +1,1416 @@
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdio.h>
6
7#include <Eina.h>
8#include <Ecore.h>
9#include <Eldbus.h>
10#include <Elocation.h>
11#include <elocation_private.h>
12
13/* FIXME: These globals really need to get reduced before leaving the PROTO
14 * area.
15 */
16static char *unique_name = NULL;
17static Eldbus_Connection *conn = NULL;
18static Elocation_Provider *address_provider = NULL;
19static Elocation_Provider *position_provider = NULL;
20static Eldbus_Object *obj_meta = NULL;
21static Eldbus_Proxy *manager_master = NULL;
22static Eldbus_Proxy *meta_geoclue = NULL;
23static Eldbus_Proxy *meta_address = NULL;
24static Eldbus_Proxy *meta_position = NULL;
25static Eldbus_Proxy *meta_masterclient = NULL;
26static Eldbus_Proxy *meta_velocity = NULL;
27static Eldbus_Proxy *meta_nmea = NULL;
28static Eldbus_Proxy *meta_satellite = NULL;
29static Eldbus_Proxy *geonames_geocode = NULL;
30static Eldbus_Proxy *geonames_rgeocode = NULL;
31static Eldbus_Proxy *master_poi = NULL;
32static Elocation_Address *address = NULL;
33static Elocation_Position *position = NULL;
34static Elocation_Address *addr_geocode = NULL;
35static Elocation_Position *pos_geocode = NULL;
36static Elocation_Velocity *velocity = NULL;
37static int *status = -1; /* 0 is a valid status code */
38static char nmea_sentence[256];
39
40int _elocation_log_dom = -1;
41
42/* Elocation ecore event types we provide to the application. */
43EAPI int ELOCATION_EVENT_IN;
44EAPI int ELOCATION_EVENT_OUT;
45EAPI int ELOCATION_EVENT_STATUS;
46EAPI int ELOCATION_EVENT_POSITION;
47EAPI int ELOCATION_EVENT_ADDRESS;
48EAPI int ELOCATION_EVENT_VELOCITY;
49EAPI int ELOCATION_EVENT_GEOCODE;
50EAPI int ELOCATION_EVENT_REVERSEGEOCODE;
51EAPI int ELOCATION_EVENT_NMEA;
52EAPI int ELOCATION_EVENT_SATELLITE;
53EAPI int ELOCATION_EVENT_POI;
54EAPI int ELOCATION_EVENT_META_READY;
55
56static void
57_dummy_free(void *user_data, void *func_data)
58{
59 /* Don't free the event data after dispatching the event. We keep track of
60 * it on our own
61 */
62}
63
64/* Generic provider message unmarshaller. Used from all different provider
65 * calbacks that receive such a message
66 */
67static Eina_Bool
68unmarshall_provider(const Eldbus_Message *reply, Elocation_Provider *provider)
69{
70 char *name = NULL, *desc = NULL, *service = NULL, *path = NULL;
71
72 if (!eldbus_message_arguments_get(reply, "ssss", &name, &desc, &service, &path))
73 return EINA_FALSE;
74
75 provider->name = strdup(name);
76 provider->description = strdup(desc);
77 provider->service = strdup(service);
78 provider->path = strdup(path);
79 return EINA_TRUE;
80}
81
82static void
83meta_address_provider_info_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
84{
85 const char *err, *errmsg;
86 Elocation_Provider *addr_provider;
87
88 addr_provider = data;
89
90 if (eldbus_message_error_get(reply, &err, &errmsg))
91 {
92 ERR("Error: %s %s", err, errmsg);
93 return;
94 }
95
96 if (!unmarshall_provider(reply, addr_provider))
97 {
98 ERR("Error: Unable to unmarshall address provider");
99 return;
100 }
101
102 DBG("Meta address provider name: %s, %s, %s, %s", addr_provider->name,
103 addr_provider->description,
104 addr_provider->service,
105 addr_provider->path);
106}
107
108static void
109meta_position_provider_info_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
110{
111 const char *err, *errmsg;
112 Elocation_Provider *pos_provider;
113
114 pos_provider = data;
115
116 if (eldbus_message_error_get(reply, &err, &errmsg))
117 {
118 ERR("Error: %s %s", err, errmsg);
119 return;
120 }
121
122 if (!unmarshall_provider(reply, pos_provider))
123 {
124 ERR("Error: Unable to unmarshall position provider");
125 return;
126 }
127
128 DBG("Meta position provider name: %s, %s, %s, %s", pos_provider->name,
129 pos_provider->description,
130 pos_provider->service,
131 pos_provider->path);
132}
133
134static void
135meta_address_provider_info_signal_cb(void *data, const Eldbus_Message *reply)
136{
137 Elocation_Provider *addr_provider;
138 addr_provider = data;
139
140 if (!unmarshall_provider(reply, addr_provider))
141 {
142 ERR("Error: Unable to unmarshall address provider");
143 return;
144 }
145
146 DBG("Meta address provider name changed: %s, %s, %s, %s", addr_provider->name,
147 addr_provider->description,
148 addr_provider->service,
149 addr_provider->path);
150}
151
152static void
153meta_position_provider_info_signal_cb(void *data, const Eldbus_Message *reply)
154{
155 Elocation_Provider *pos_provider;
156 pos_provider = data;
157
158 if (!unmarshall_provider(reply, pos_provider))
159 {
160 ERR("Error: Unable to unmarshall position provider");
161 return;
162 }
163
164 DBG("Meta position provider name changed: %s, %s, %s, %s", pos_provider->name,
165 pos_provider->description,
166 pos_provider->service,
167 pos_provider->path);
168}
169
170/* A address is quite flexible what kind of key value pairs it contains in the
171 * dict. Similar to a reverse GeoCode message as both return an address object.
172 */
173static Eina_Bool
174unmarshall_address(const Eldbus_Message *reply, Elocation_Address *addr)
175{
176 int32_t level, timestamp;
177 Eldbus_Message_Iter *sub, *dict, *entry;
178 double horizontal;
179 double vertical;
180 const char *key, *signature;
181 char *value;
182
183 signature = eldbus_message_signature_get(reply);
184
185 if (!strcmp(signature, "ia{ss}(idd)"))
186 {
187 if (!eldbus_message_arguments_get(reply, "ia{ss}(idd)", &timestamp, &dict, &sub))
188 return EINA_FALSE;
189 addr->timestamp = timestamp;
190 }
191 else if (!strcmp(signature, "a{ss}(idd)"))
192 {
193 if (!eldbus_message_arguments_get(reply, "a{ss}(idd)", &dict, &sub))
194 return EINA_FALSE;
195 addr->timestamp = 0;
196 }
197 else
198 return EINA_FALSE;
199
200
201 /* Cleanup potential old entries before re-using */
202 addr->country = NULL;
203 addr->countrycode = NULL;
204 addr->locality = NULL;
205 addr->postalcode = NULL;
206 addr->region = NULL;
207 addr->timezone = NULL;
208
209 while (eldbus_message_iter_get_and_next(dict, 'e', &entry))
210 {
211 eldbus_message_iter_arguments_get(entry, "ss", &key, &value);
212
213 if (!strcmp(key, "country"))
214 {
215 free(addr->country);
216 addr->country = strdup(value);
217 }
218 else if (!strcmp(key, "countrycode"))
219 {
220 free(addr->countrycode);
221 addr->countrycode = strdup(value);
222 }
223 else if (!strcmp(key, "locality"))
224 {
225 free(addr->locality);
226 addr->locality = strdup(value);
227 }
228 else if (!strcmp(key, "postalcode"))
229 {
230 free(addr->postalcode);
231 addr->postalcode = strdup(value);
232 }
233 else if (!strcmp(key, "region"))
234 {
235 free(addr->region);
236 addr->region = strdup(value);
237 }
238 else if (!strcmp(key, "timezone"))
239 {
240 free(addr->timezone);
241 addr->timezone = strdup(value);
242 }
243 }
244
245 eldbus_message_iter_arguments_get(sub, "idd", &level, &horizontal, &vertical);
246 addr->accur->level = level;
247 addr->accur->horizontal = horizontal;
248 addr->accur->vertical = vertical;
249 return EINA_TRUE;
250}
251
252/* Receive and unmarshall a reverse GeoCode message. The dict can contain a
253 * variable set of key value pairs so we need to handle this with care
254 */
255static void
256rgeocode_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
257{
258 const char *err, *errmsg;
259
260 if (eldbus_message_error_get(reply, &err, &errmsg))
261 {
262 ERR("Error: %s %s", err, errmsg);
263 return;
264 }
265
266 if (!unmarshall_address(reply, addr_geocode))
267 {
268 ERR("Error: Unable to unmarshall address");
269 return;
270 }
271
272 /* Send out an event to all interested parties that we have an update */
273 ecore_event_add(ELOCATION_EVENT_REVERSEGEOCODE, addr_geocode, _dummy_free, NULL);
274}
275
276/* Point of Interest (POI) aka landmark message unmarshalling. Thsi interface is
277 * not in standard GeoClue but currently a Tizen extension.
278 */
279static void
280poi_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
281{
282 int32_t count, id, rank;
283 double lat, lon, bound_left, bound_top, bound_right, bound_bottom;
284 const char *name, *icon, *house, *road, *village, *suburb, *postcode;
285 const char *city, *county, *country, *country_code;
286 Eldbus_Message_Iter *array, *struct_landmark;
287 const char *err, *errmsg;
288
289 if (eldbus_message_error_get(reply, &err, &errmsg))
290 {
291 ERR("Error: %s %s", err, errmsg);
292 return;
293 }
294
295 /* Yeah, its quite a horrible message. The POI interface could use a better design */
296 if (!eldbus_message_arguments_get(reply, "ia(iiddddddsssssssssss", &count ,&array))
297 return;
298
299 /* TODO re-check that the parameter ordering is what we expect */
300 while (eldbus_message_iter_get_and_next(array, 'r', &struct_landmark))
301 {
302 eldbus_message_iter_arguments_get(struct_landmark, "iiddddddsssssssssss", &id, &rank,
303 &lat, &lon, &bound_left, &bound_top, &bound_right,
304 &bound_bottom, &name, &icon, &house, &road,
305 &village, &suburb, &postcode, &city, &county,
306 &country, &country_code);
307 DBG("Landmark received: %i, %i, %f, %f, %f, %f, %f, %f, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,",
308 id, rank, lat, lon, bound_left, bound_top, bound_right,
309 bound_bottom, name, icon, house, road, village,
310 suburb, postcode, city, county, country, country_code);
311 }
312
313 /* Send out an event to all interested parties that we have an update */
314 ecore_event_add(ELOCATION_EVENT_POI, NULL, _dummy_free, NULL);
315}
316
317/* Unmarshall a GeoCode message */
318static void
319geocode_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
320{
321 GeocluePositionFields fields;
322 int32_t level;
323 double horizontal = 0.0;
324 double vertical = 0.0;
325 double latitude = 0.0;
326 double longitude = 0.0;
327 double altitude = 0.0;
328 Eldbus_Message_Iter *sub;
329 const char *err, *errmsg;
330
331 if (eldbus_message_error_get(reply, &err, &errmsg))
332 {
333 ERR("Error: %s %s", err, errmsg);
334 return;
335 }
336
337 if (!eldbus_message_arguments_get(reply, "iddd(idd)", &fields,&latitude,
338 &longitude, &altitude, &sub))
339 return;
340
341 /* GeoClue uses some flags to mark position fields as valid. We set invalid
342 * fields to 0.0 */
343 if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE)
344 pos_geocode->latitude = latitude;
345 else
346 pos_geocode->latitude = 0.0;
347
348 if (fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)
349 pos_geocode->longitude = longitude;
350 else
351 pos_geocode->longitude = 0.0;
352
353 if (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE)
354 pos_geocode->altitude = altitude;
355 else
356 pos_geocode->altitude = 0.0;
357
358 eldbus_message_iter_arguments_get(sub, "idd", &level, &horizontal, &vertical);
359 pos_geocode->accur->level = level;
360 pos_geocode->accur->horizontal = horizontal;
361 pos_geocode->accur->vertical = vertical;
362 /* Send out an event to all interested parties that we have an update */
363 ecore_event_add(ELOCATION_EVENT_GEOCODE, pos_geocode, _dummy_free, NULL);
364}
365
366static void
367address_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
368{
369 const char *err, *errmsg;
370
371 if (eldbus_message_error_get(reply, &err, &errmsg))
372 {
373 ERR("Error: %s %s", err, errmsg);
374 return;
375 }
376
377 if (!unmarshall_address(reply, address))
378 {
379 ERR("Error: Unable to unmarshall address");
380 return;
381 }
382
383 /* Send out an event to all interested parties that we have an update */
384 ecore_event_add(ELOCATION_EVENT_ADDRESS, address, _dummy_free, NULL);
385}
386
387static void
388address_signal_cb(void *data, const Eldbus_Message *reply)
389{
390 const char *err, *errmsg;
391
392 if (eldbus_message_error_get(reply, &err, &errmsg))
393 {
394 ERR("Error: %s %s", err, errmsg);
395 return;
396 }
397
398 if (!unmarshall_address(reply, address))
399 {
400 ERR("Error: Unable to unmarshall address");
401 return;
402 }
403
404 /* Send out an event to all interested parties that we have an update */
405 ecore_event_add(ELOCATION_EVENT_ADDRESS, address, _dummy_free, NULL);
406}
407
408/* Unmarshall a velocity message. This is only available if we use a GPS
409 * provider from GeoClue. None of the other providers offer this currently.
410 */
411static Eina_Bool
412unmarshall_velocity(const Eldbus_Message *reply)
413{
414 GeoclueVelocityFields fields;
415 int32_t timestamp = 0;
416 double speed = 0.0;
417 double direction = 0.0;
418 double climb = 0.0;
419
420 if (!eldbus_message_arguments_get(reply, "iiddd", &fields, &timestamp,
421 &speed, &direction, &climb))
422 return EINA_FALSE;
423
424 velocity->timestamp = timestamp;
425
426 /* GeoClue uses some flags to mark velocity fields as valid. We set invalid
427 * fields to 0.0 */
428 if (fields & GEOCLUE_VELOCITY_FIELDS_SPEED)
429 velocity->speed = speed;
430 else
431 velocity->speed = 0.0;
432
433 if (fields & GEOCLUE_VELOCITY_FIELDS_DIRECTION)
434 velocity->direction = direction;
435 else
436 velocity->direction = 0.0;
437
438 if (fields & GEOCLUE_VELOCITY_FIELDS_CLIMB)
439 velocity->climb = climb;
440 else
441 velocity->climb = 0.0;
442
443 return EINA_TRUE;
444}
445
446static void
447velocity_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
448{
449 const char *err, *errmsg;
450
451 if (eldbus_message_error_get(reply, &err, &errmsg))
452 {
453 WARN("Warning: %s %s", err, errmsg);
454 return;
455 }
456
457 if (!unmarshall_velocity(reply))
458 {
459 ERR("Error: Unable to unmarshall velocity");
460 return;
461 }
462
463 /* Send out an event to all interested parties that we have an update */
464 ecore_event_add(ELOCATION_EVENT_VELOCITY, velocity, _dummy_free, NULL);
465}
466
467static void
468velocity_signal_cb(void *data, const Eldbus_Message *reply)
469{
470 if (!unmarshall_velocity(reply))
471 {
472 ERR("Error: Unable to unmarshall velocity");
473 return;
474 }
475
476 /* Send out an event to all interested parties that we have an update */
477 ecore_event_add(ELOCATION_EVENT_VELOCITY, velocity, _dummy_free, NULL);
478}
479
480/* Unmarshall an raw NMEA message. It conatins a raw NMEA sentence which we can
481 * pass on to applications that want to use their own NMEA parser. This is not
482 * reommended. Better use the other interfaces to access the needed data.
483 *
484 * This is currently a Tizen only interface and not in GeoClue upstream.
485 */
486static Eina_Bool
487unmarshall_nmea(const Eldbus_Message *reply)
488{
489 int32_t timestamp = 0;
490
491 if (!eldbus_message_arguments_get(reply, "is", &timestamp, &nmea_sentence))
492 return EINA_FALSE;
493
494 return EINA_TRUE;
495}
496
497static void
498nmea_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
499{
500 const char *err, *errmsg;
501
502 if (eldbus_message_error_get(reply, &err, &errmsg))
503 {
504 WARN("Warning: %s %s", err, errmsg);
505 return;
506 }
507
508 if (!unmarshall_nmea(reply))
509 {
510 ERR("Error: Unable to unmarshall nmea");
511 return;
512 }
513
514 /* Send out an event to all interested parties that we have an update */
515 ecore_event_add(ELOCATION_EVENT_NMEA, nmea_sentence, _dummy_free, NULL);
516}
517
518static void
519nmea_signal_cb(void *data, const Eldbus_Message *reply)
520{
521 if (!unmarshall_nmea(reply))
522 {
523 ERR("Error: Unable to unmarshall nmea");
524 return;
525 }
526
527 ecore_event_add(ELOCATION_EVENT_NMEA, nmea_sentence, _dummy_free, NULL);
528}
529
530/* Unmarshall a satellite information message. This offers GPS specific
531 * information about the used satellites and its properties. It can be used for
532 * applications that rely on GPS and want to show more information like a 3D fix
533 * or used satellites.
534 *
535 * This is currently a Tizen only interface and not available in GeoClue upstream.
536 */
537static Eina_Bool
538unmarshall_satellite(const Eldbus_Message *reply)
539{
540 int32_t timestamp = 0, satellite_used = 0, satellite_visible = 0;
541 int32_t snr = 0, elevation = 0, azimuth = 0, prn = 0, used_prn = 0;
542 Eldbus_Message_Iter *sub_prn, *sub_info, *struct_info;
543
544 if (!eldbus_message_arguments_get(reply, "iiiaia(iiii)", &timestamp, &satellite_used,
545 &satellite_visible, &sub_prn, &sub_info))
546 return EINA_FALSE;
547
548 while (eldbus_message_iter_get_and_next(sub_prn, 'i', &used_prn))
549 {
550 DBG("Satellite used PRN %i", used_prn);
551 }
552
553 /* TODO re-check that the parameter ordering is what we expect */
554 while (eldbus_message_iter_get_and_next(sub_info, 'r', &struct_info))
555 {
556 eldbus_message_iter_arguments_get(struct_info, "iiii", &prn, &elevation, &azimuth, &snr);
557 DBG("Satellite info %i, %i, %i, %i", prn, elevation, azimuth, snr);
558 }
559
560 return EINA_TRUE;
561}
562
563static void
564satellite_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
565{
566 const char *err, *errmsg;
567
568 if (eldbus_message_error_get(reply, &err, &errmsg))
569 {
570 WARN("Warning: %s %s", err, errmsg);
571 return;
572 }
573
574 if (!unmarshall_satellite(reply))
575 {
576 ERR("Error: Unable to unmarshall satellite");
577 return;
578 }
579
580 /* Send out an event to all interested parties that we have an update */
581 ecore_event_add(ELOCATION_EVENT_SATELLITE, NULL, _dummy_free, NULL);
582}
583
584static void
585last_satellite_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
586{
587 const char *err, *errmsg;
588
589 if (eldbus_message_error_get(reply, &err, &errmsg))
590 {
591 WARN("Warning: %s %s", err, errmsg);
592 return;
593 }
594
595 if (!unmarshall_satellite(reply))
596 {
597 ERR("Error: Unable to unmarshall last satellite");
598 return;
599 }
600
601 /* Send out an event to all interested parties that we have an update */
602 ecore_event_add(ELOCATION_EVENT_SATELLITE, NULL, _dummy_free, NULL);
603}
604
605static void
606satellite_signal_cb(void *data, const Eldbus_Message *reply)
607{
608 if (!unmarshall_satellite(reply))
609 {
610 ERR("Error: Unable to unmarshall satellite");
611 return;
612 }
613
614 /* Send out an event to all interested parties that we have an update */
615 ecore_event_add(ELOCATION_EVENT_SATELLITE, NULL, _dummy_free, NULL);
616}
617
618/* Unmarshall position coordination message */
619static Eina_Bool
620unmarshall_position(const Eldbus_Message *reply)
621{
622 GeocluePositionFields fields;
623 int32_t level, timestamp;
624 double horizontal = 0.0;
625 double vertical = 0.0;
626 double latitude = 0.0;
627 double longitude = 0.0;
628 double altitude = 0.0;
629 Eldbus_Message_Iter *sub;
630
631 if (!eldbus_message_arguments_get(reply, "iiddd(idd)", &fields, &timestamp,
632 &latitude, &longitude, &altitude, &sub))
633 return EINA_FALSE;
634
635 if (!eldbus_message_iter_arguments_get(sub, "idd", &level, &horizontal, &vertical))
636 return EINA_FALSE;
637
638 position->timestamp = timestamp;
639
640 /* GeoClue uses some flags to mark position fields as valid. We set invalid
641 * fields to 0.0 */
642 if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE)
643 position->latitude = latitude;
644 else
645 position->latitude = 0.0;
646
647 if (fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)
648 position->longitude = longitude;
649 else
650 position->longitude = 0.0;
651
652 if (fields & GEOCLUE_POSITION_FIELDS_ALTITUDE)
653 position->altitude = altitude;
654 else
655 position->altitude = 0.0;
656
657 position->accur->level = level;
658 position->accur->horizontal = horizontal;
659 position->accur->vertical = vertical;
660
661 return EINA_TRUE;
662}
663
664static void
665position_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
666{
667 const char *err, *errmsg;
668
669 if (eldbus_message_error_get(reply, &err, &errmsg))
670 {
671 ERR("Error: %s %s", err, errmsg);
672 return;
673 }
674
675 if (!unmarshall_position(reply))
676 {
677 ERR("Error: Unable to unmarshall position");
678 return;
679 }
680
681 /* Send out an event to all interested parties that we have an update */
682 ecore_event_add(ELOCATION_EVENT_POSITION, position, _dummy_free, NULL);
683}
684
685static void
686position_signal_cb(void *data, const Eldbus_Message *reply)
687{
688 if (!unmarshall_position(reply))
689 {
690 ERR("Error: Unable to unmarshall position");
691 return;
692 }
693
694 /* Send out an event to all interested parties that we have an update */
695 ecore_event_add(ELOCATION_EVENT_POSITION, position, _dummy_free, NULL);
696}
697
698static Eina_Bool
699geoclue_start(void *data, int ev_type, void *event)
700{
701 DBG("GeoClue start event at %s", unique_name);
702 return ECORE_CALLBACK_DONE;
703}
704
705static Eina_Bool
706geoclue_stop(void *data, int ev_type, void *event)
707{
708 DBG("GeoClue stop event");
709 return ECORE_CALLBACK_DONE;
710}
711
712static void
713_reference_add_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
714{
715 const char *err, *errmsg;
716
717 if (eldbus_message_error_get(reply, &err, &errmsg))
718 {
719 ERR("Error: %s %s", err, errmsg);
720 return;
721 }
722
723 DBG("Reference added");
724}
725
726static void
727_reference_del_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
728{
729 /* Dummy callback. We are not waiting for any reply here on shutdown */
730}
731
732static void
733status_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
734{
735 const char *err, *errmsg;
736
737 if (eldbus_message_error_get(reply, &err, &errmsg))
738 {
739 ERR("Error: %s %s", err, errmsg);
740 return;
741 }
742
743 /* We need this to be malloced to be passed to ecore_event_add. Or provide a dummy free callback. */
744 status = malloc(sizeof(*status));
745
746 if (!eldbus_message_arguments_get(reply,"i", status))
747 {
748 ERR("Error: Unable to unmarshall status");
749 return;
750 }
751
752 address_provider->status = position_provider->status = *status;
753 /* Send out an event to all interested parties that we have an update */
754 ecore_event_add(ELOCATION_EVENT_STATUS, status, NULL, NULL);
755}
756
757static void
758status_signal_cb(void *data, const Eldbus_Message *reply)
759{
760 /* We need this to be malloced to be passed to ecore_event_add. Or provide a dummy free callback. */
761 status = malloc(sizeof(*status));
762
763 if (!eldbus_message_arguments_get(reply,"i", status))
764 {
765 ERR("Error: Unable to unmarshall status");
766 return;
767 }
768
769 address_provider->status = position_provider->status = *status;
770 /* Send out an event to all interested parties that we have an update */
771 ecore_event_add(ELOCATION_EVENT_STATUS, status, NULL, NULL);
772}
773
774static void
775_dummy_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
776{
777}
778
779/* We got notified from GeoClue that the meta-provider we asked for is now
780 * ready. That means we can finish up our initialization and set up all
781 * callbacks and handling for the interfaces we use on the meta-provider.
782 *
783 * We also call the interfaces to get an initial set of data that we can provide
784 * to eager aplications.
785 */
786static void
787create_cb(void *data, const Eldbus_Message *reply, Eldbus_Pending *pending)
788{
789 const char *object_path;
790 Eina_Bool updates;
791 int accur_level, min_time, resources;
792 const char *err, *errmsg;
793
794 if (eldbus_message_error_get(reply, &err, &errmsg))
795 {
796 ERR("Error: %s %s", err, errmsg);
797 return;
798 }
799
800 if (!eldbus_message_arguments_get(reply, "o", &object_path)) return;
801
802 DBG("Object path for client: %s", object_path);
803
804 /* With the created object path we now have a meta provider we can operate on.
805 * Geoclue handles the selection of the best provider internally for the meta
806 * provider */
807 obj_meta = eldbus_object_get(conn, GEOCLUE_DBUS_NAME, object_path);
808 if (!obj_meta)
809 {
810 ERR("Error: could not get object for client");
811 return;
812 }
813
814 meta_geoclue = eldbus_proxy_get(obj_meta, GEOCLUE_GEOCLUE_IFACE);
815 if (!meta_geoclue)
816 {
817 ERR("Error: could not get proxy for geoclue");
818 return;
819 }
820
821 meta_address = eldbus_proxy_get(obj_meta, GEOCLUE_ADDRESS_IFACE);
822 if (!meta_address)
823 {
824 ERR("Error: could not get proxy address");
825 return;
826 }
827
828 meta_position = eldbus_proxy_get(obj_meta, GEOCLUE_POSITION_IFACE);
829 if (!meta_position)
830 {
831 ERR("Error: could not get proxy for position");
832 return;
833 }
834
835 meta_masterclient = eldbus_proxy_get(obj_meta, GEOCLUE_MASTERCLIENT_IFACE);
836 if (!meta_masterclient)
837 {
838 ERR("Error: could not get proxy for master client");
839 return;
840 }
841
842 meta_velocity = eldbus_proxy_get(obj_meta, GEOCLUE_VELOCITY_IFACE);
843 if (!meta_velocity)
844 {
845 ERR("Error: could not get proxy for velocity");
846 return;
847 }
848
849 meta_nmea = eldbus_proxy_get(obj_meta, GEOCLUE_NMEA_IFACE);
850 if (!meta_nmea)
851 {
852 ERR("Error: could not get proxy for nmea");
853 return;
854 }
855
856 meta_satellite = eldbus_proxy_get(obj_meta, GEOCLUE_SATELLITE_IFACE);
857 if (!meta_satellite)
858 {
859 ERR("Error: could not get proxy for satellite");
860 return;
861 }
862
863 /* Send Geoclue a set of requirements we have for the provider and start the address and position
864 * meta provider afterwards. After this we should be ready for operation. */
865 updates = EINA_FALSE; /* Especially the web providers do not offer updates */
866 accur_level = ELOCATION_ACCURACY_LEVEL_COUNTRY;
867 min_time = 0; /* Minimal times between updates (no implemented yet) */
868 resources = ELOCATION_RESOURCE_ALL;
869
870 eldbus_proxy_signal_handler_add(meta_masterclient, "AddressProviderChanged",
871 meta_address_provider_info_signal_cb, address_provider);
872 eldbus_proxy_signal_handler_add(meta_masterclient, "PositionProviderChanged",
873 meta_position_provider_info_signal_cb, position_provider);
874
875 if (!eldbus_proxy_call(meta_masterclient, "SetRequirements", _dummy_cb, NULL, -1, "iibi",
876 accur_level, min_time, updates, resources))
877 {
878 ERR("Error: could not call SetRequirements");
879 return;
880 }
881
882 if (!eldbus_proxy_call(meta_masterclient, "AddressStart", _dummy_cb, NULL, -1, ""))
883 {
884 ERR("Error: could not call AddressStart");
885 return;
886 }
887
888 if (!eldbus_proxy_call(meta_masterclient, "PositionStart", _dummy_cb, NULL, -1, ""))
889 {
890 ERR("Error: could not call PositionStart");
891 return;
892 }
893
894 if (!eldbus_proxy_call(meta_geoclue, "AddReference", _reference_add_cb, NULL, -1, ""))
895 {
896 ERR("Error: could not call AddReference");
897 return;
898 }
899
900 if (!eldbus_proxy_call(meta_address, "GetAddress", address_cb, NULL, -1, ""))
901 {
902 ERR("Error: could not call GetAddress");
903 return;
904 }
905
906 if (!eldbus_proxy_call(meta_position, "GetPosition", position_cb, NULL, -1, ""))
907 {
908 ERR("Error: could not call GetPosition");
909 return;
910 }
911
912 if (!eldbus_proxy_call(meta_geoclue, "GetStatus", status_cb, NULL, -1, ""))
913 {
914 ERR("Error: could not call GetStatus");
915 return;
916 }
917
918 if (!eldbus_proxy_call(meta_velocity, "GetVelocity", velocity_cb, NULL, -1, ""))
919 {
920 ERR("Error: could not call GetVelocity");
921 return;
922 }
923
924 if (!eldbus_proxy_call(meta_nmea, "GetNmea", nmea_cb, NULL, -1, ""))
925 {
926 ERR("Error: could not call GetNmea");
927 return;
928 }
929
930 if (!eldbus_proxy_call(meta_satellite, "GetSatellite", satellite_cb, NULL, -1, ""))
931 {
932 ERR("Error: could not call GetSatellite");
933 return;
934 }
935
936 if (!eldbus_proxy_call(meta_satellite, "GetLastSatellite", last_satellite_cb, NULL, -1, ""))
937 {
938 ERR("Error: could not call GetLastSatellite");
939 return;
940 }
941
942 if (!eldbus_proxy_call(meta_masterclient, "GetAddressProvider", meta_address_provider_info_cb,
943 address_provider, -1, ""))
944 {
945 ERR("Error: could not call GetAddressProvider");
946 return;
947 }
948
949 if (!eldbus_proxy_call(meta_masterclient, "GetPositionProvider", meta_position_provider_info_cb,
950 position_provider, -1, ""))
951 {
952 ERR("Error: could not call GetPositionProvider");
953 return;
954 }
955
956 eldbus_proxy_signal_handler_add(meta_address, "AddressChanged", address_signal_cb, NULL);
957 eldbus_proxy_signal_handler_add(meta_position, "PositionChanged", position_signal_cb, NULL);
958 eldbus_proxy_signal_handler_add(meta_geoclue, "StatusChanged", status_signal_cb, NULL);
959 eldbus_proxy_signal_handler_add(meta_velocity, "VelocityChanged", velocity_signal_cb, NULL);
960 eldbus_proxy_signal_handler_add(meta_nmea, "NmeaChanged", nmea_signal_cb, NULL);
961 eldbus_proxy_signal_handler_add(meta_satellite, "SatelliteChanged", satellite_signal_cb, NULL);
962
963 ecore_event_add(ELOCATION_EVENT_META_READY, NULL, NULL, NULL);
964}
965
966static void
967_name_owner_changed(void *data, const char *bus, const char *old, const char *new)
968{
969 if (old[0] == '\0' && new[0] != '\0')
970 {
971 ecore_event_add(ELOCATION_EVENT_IN, NULL, NULL, NULL);
972 unique_name = strdup(new);
973 }
974 else if (old[0] != '\0' && new[0] == '\0')
975 {
976 if (strcmp(unique_name, old) != 0)
977 WARN("%s was not the known name %s, ignored.", old, unique_name);
978 else
979 ecore_event_add(ELOCATION_EVENT_OUT, NULL, NULL, NULL);
980 }
981 else
982 {
983 DBG("unknow change from %s to %s", old, new);
984 }
985}
986
987/* Public API function to request a landmarks position based on an address object */
988EAPI Eina_Bool
989elocation_landmarks_get(Elocation_Position *position_shadow, Elocation_Address *address_shadow)
990{
991 Eldbus_Message *msg;
992 Eldbus_Message_Iter *iter;
993 const char *keyword = NULL, *lang = NULL, *country_code = NULL;
994 int limit = 0;
995 double left= 0.0, top = 0.0, right = 0.0, bottom = 0.0;
996
997 msg = eldbus_proxy_method_call_new(master_poi, "SearchByPosition");
998 iter = eldbus_message_iter_get(msg);
999 eldbus_message_iter_basic_append(iter, 's', keyword);
1000 eldbus_message_iter_basic_append(iter, 's', lang);
1001 eldbus_message_iter_basic_append(iter, 's', country_code);
1002 eldbus_message_iter_basic_append(iter, 'i', limit);
1003 eldbus_message_iter_basic_append(iter, 'd', left);
1004 eldbus_message_iter_basic_append(iter, 'd', top);
1005 eldbus_message_iter_basic_append(iter, 'd', right);
1006 eldbus_message_iter_basic_append(iter, 'd', bottom);
1007 if (!eldbus_proxy_send(master_poi, msg, poi_cb, NULL, -1))
1008 {
1009 ERR("Error: could not call SearchByPosition");
1010 eldbus_message_unref(msg);
1011 return EINA_FALSE;
1012 }
1013
1014 return EINA_TRUE;
1015}
1016
1017/* Public API function to get an address from a position */
1018EAPI Eina_Bool
1019elocation_position_to_address(Elocation_Position *position_shadow, Elocation_Address *address_shadow)
1020{
1021 Eldbus_Message *msg;
1022 Eldbus_Message_Iter *iter, *structure;
1023
1024 msg = eldbus_proxy_method_call_new(geonames_rgeocode, "PositionToAddress");
1025 iter = eldbus_message_iter_get(msg);
1026 eldbus_message_iter_basic_append(iter, 'd', position_shadow->latitude);
1027 eldbus_message_iter_basic_append(iter, 'd', position_shadow->longitude);
1028 structure = eldbus_message_iter_container_new(iter, 'r', NULL);
1029 eldbus_message_iter_basic_append(structure, 'i', position_shadow->accur->level);
1030 eldbus_message_iter_basic_append(structure, 'd', position_shadow->accur->horizontal);
1031 eldbus_message_iter_basic_append(structure, 'd', position_shadow->accur->vertical);
1032 eldbus_message_iter_container_close(iter, structure);
1033 if (!eldbus_proxy_send(geonames_rgeocode, msg, rgeocode_cb, NULL, -1))
1034 {
1035 ERR("Error: could not call PositionToAddress");
1036 eldbus_message_unref(msg);
1037 return EINA_FALSE;
1038 }
1039
1040 return EINA_TRUE;
1041}
1042
1043/* Public API function to get a position from and address */
1044EAPI Eina_Bool
1045elocation_address_to_position(Elocation_Address *address_shadow, Elocation_Position *position_shadow)
1046{
1047 Eldbus_Message *msg;
1048 Eldbus_Message_Iter *iter, *array;
1049
1050 /* In function macro to generate a key value pair structure for the dict */
1051 #define ENTRY(key) { #key, address_shadow->key }
1052 struct keyval {
1053 const char *key;
1054 const char *val;
1055 } keyval[] = {
1056 ENTRY(country),
1057 ENTRY(countrycode),
1058 ENTRY(locality),
1059 ENTRY(postalcode),
1060 ENTRY(region),
1061 ENTRY(timezone),
1062 { NULL, NULL }
1063 };
1064 #undef ENTRY
1065
1066 struct keyval *k;
1067
1068 msg = eldbus_proxy_method_call_new(geonames_geocode, "AddressToPosition");
1069 iter = eldbus_message_iter_get(msg);
1070
1071 array = eldbus_message_iter_container_new(iter, 'a', "{ss}");
1072
1073 for (k = keyval; k && k->key; k++)
1074 {
1075 Eldbus_Message_Iter *entry;
1076
1077 if (!k->val) continue;
1078
1079 entry = eldbus_message_iter_container_new(array, 'e', NULL);
1080 eldbus_message_iter_arguments_append(entry, "ss", k->key, k->val);
1081 eldbus_message_iter_container_close(array, entry);
1082 }
1083
1084 eldbus_message_iter_container_close(iter, array);
1085
1086 if (!eldbus_proxy_send(geonames_geocode, msg, geocode_cb, NULL, -1))
1087 {
1088 ERR("Error: could not call AddressToPosition");
1089 eldbus_message_unref(msg);
1090 return EINA_FALSE;
1091 }
1092
1093 return EINA_TRUE;
1094}
1095
1096/* Public API function to get the position from a freeform text input style
1097 * address
1098 */
1099EAPI Eina_Bool
1100elocation_freeform_address_to_position(const char *freeform_address, Elocation_Position *position_shadow)
1101{
1102 if (!eldbus_proxy_call(geonames_geocode, "FreeformAddressToPosition", geocode_cb, NULL, -1, "s", freeform_address))
1103 {
1104 ERR("Error: could not call FreeformAddressToPosition");
1105 return EINA_FALSE;
1106 }
1107 return EINA_TRUE;
1108}
1109
1110/* Public API function to request the current address */
1111EAPI Eina_Bool
1112elocation_address_get(Elocation_Address *address_shadow)
1113{
1114 if (!address) return EINA_FALSE;
1115
1116 address_shadow = address;
1117 return EINA_TRUE;
1118}
1119
1120/* Public API function to request the current position */
1121EAPI Eina_Bool
1122elocation_position_get(Elocation_Position *position_shadow)
1123{
1124 if (!position) return EINA_FALSE;
1125
1126 position_shadow = position;
1127 return EINA_TRUE;
1128}
1129
1130/* Public API function to request the status */
1131EAPI Eina_Bool
1132elocation_status_get(int *status_shadow)
1133{
1134 if (status < 0) return EINA_FALSE;
1135
1136 status_shadow = status;
1137 return EINA_TRUE;
1138}
1139
1140/* Public API function to create a new position object */
1141EAPI Elocation_Position *
1142elocation_position_new(void)
1143{
1144 /* Malloc the global struct we operate on here in this lib. This shadows the
1145 * updated data we are giving to the application */
1146 position = calloc(1, sizeof(Elocation_Position));
1147 if (!position) return NULL;
1148
1149 position->accur = calloc(1, sizeof(Elocation_Accuracy));
1150 if (!position->accur) return NULL;
1151
1152 return position;
1153}
1154
1155/* Public API function to create an new address object */
1156EAPI Elocation_Address *
1157elocation_address_new(void)
1158{
1159 /* Malloc the global struct we operate on here in this lib. This shadows the
1160 * updated data we are giving to the application */
1161 address = calloc(1, sizeof(Elocation_Address));
1162 if (!address) return NULL;
1163
1164 address->accur = calloc(1, sizeof(Elocation_Accuracy));
1165 if (!address->accur) return NULL;
1166
1167 return address;
1168}
1169
1170/* Public API function to free an position object */
1171EAPI void
1172elocation_position_free(Elocation_Position *position_shadow)
1173{
1174 if (position != position_shadow)
1175 {
1176 ERR("Corrupted position object");
1177 return;
1178 }
1179
1180 free(position->accur);
1181 free(position);
1182}
1183
1184/* Public API function to free an address object */
1185EAPI void
1186elocation_address_free(Elocation_Address *address_shadow)
1187{
1188 if (address != address_shadow)
1189 {
1190 ERR("Corrupted address object");
1191 return;
1192 }
1193
1194 if (address)
1195 {
1196 free(address->country);
1197 free(address->countrycode);
1198 free(address->locality);
1199 free(address->postalcode);
1200 free(address->region);
1201 free(address->timezone);
1202 free(address->accur);
1203 free(address);
1204 }
1205}
1206
1207/* Public API funtion to initialize the elocation library */
1208EAPI Eina_Bool
1209elocation_init(void)
1210{
1211 Eldbus_Object *obj_master = NULL;
1212 Eldbus_Object *obj_geonames = NULL;
1213
1214 if (!eina_init()) return EINA_FALSE;
1215 if (!ecore_init()) return EINA_FALSE;
1216 if (!eldbus_init()) return EINA_FALSE;
1217
1218 _elocation_log_dom = eina_log_domain_register("elocation", EINA_COLOR_BLUE);
1219 if (_elocation_log_dom < 0)
1220 {
1221 EINA_LOG_ERR("Could not register 'elocation' log domain.");
1222 }
1223
1224 /* Create objects, one for each kind, we operate on internally */
1225 address_provider = calloc(1, sizeof(Elocation_Provider));
1226 position_provider = calloc(1, sizeof(Elocation_Provider));
1227
1228 addr_geocode = calloc(1, sizeof(Elocation_Address));
1229 if (!addr_geocode) return EINA_FALSE;
1230
1231 addr_geocode->accur = calloc(1, sizeof(Elocation_Accuracy));
1232 if (!addr_geocode->accur) return EINA_FALSE;
1233
1234 pos_geocode = calloc(1, sizeof(Elocation_Position));
1235 if (!pos_geocode) return EINA_FALSE;
1236
1237 pos_geocode->accur = calloc(1, sizeof(Elocation_Accuracy));
1238 if (!pos_geocode->accur) return EINA_FALSE;
1239
1240 conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
1241 if (!conn)
1242 {
1243 ERR("Error: could not connect to session bus.");
1244 return EXIT_FAILURE;
1245 }
1246
1247 /* Create all ecore event types we send out to interested applications */
1248 if (ELOCATION_EVENT_IN == 0)
1249 ELOCATION_EVENT_IN = ecore_event_type_new();
1250
1251 if (ELOCATION_EVENT_OUT == 0)
1252 ELOCATION_EVENT_OUT = ecore_event_type_new();
1253
1254 if (ELOCATION_EVENT_STATUS == 0)
1255 ELOCATION_EVENT_STATUS = ecore_event_type_new();
1256
1257 if (ELOCATION_EVENT_POSITION == 0)
1258 ELOCATION_EVENT_POSITION = ecore_event_type_new();
1259
1260 if (ELOCATION_EVENT_ADDRESS == 0)
1261 ELOCATION_EVENT_ADDRESS = ecore_event_type_new();
1262
1263 if (ELOCATION_EVENT_VELOCITY == 0)
1264 ELOCATION_EVENT_VELOCITY = ecore_event_type_new();
1265
1266 if (ELOCATION_EVENT_GEOCODE == 0)
1267 ELOCATION_EVENT_GEOCODE = ecore_event_type_new();
1268
1269 if (ELOCATION_EVENT_REVERSEGEOCODE == 0)
1270 ELOCATION_EVENT_REVERSEGEOCODE = ecore_event_type_new();
1271
1272 if (ELOCATION_EVENT_NMEA == 0)
1273 ELOCATION_EVENT_NMEA = ecore_event_type_new();
1274
1275 if (ELOCATION_EVENT_SATELLITE == 0)
1276 ELOCATION_EVENT_SATELLITE = ecore_event_type_new();
1277
1278 if (ELOCATION_EVENT_POI == 0)
1279 ELOCATION_EVENT_POI = ecore_event_type_new();
1280
1281 if (ELOCATION_EVENT_META_READY == 0)
1282 ELOCATION_EVENT_META_READY = ecore_event_type_new();
1283
1284 obj_master= eldbus_object_get(conn, GEOCLUE_DBUS_NAME, GEOCLUE_OBJECT_PATH);
1285 if (!obj_master)
1286 {
1287 ERR("Error: could not get object");
1288 return EXIT_FAILURE;
1289 }
1290
1291 manager_master = eldbus_proxy_get(obj_master, GEOCLUE_MASTER_IFACE);
1292 if (!manager_master)
1293 {
1294 ERR("Error: could not get proxy");
1295 return EXIT_FAILURE;
1296 }
1297
1298 /* Create a meta provider for all normal use cases. This will allow GeoClue
1299 * to decide which provider is the best for us internally.
1300 * Right now we don't have the functionality in place to specifically request
1301 * a provider but we maybe need this in the future. We will try without it
1302 * for now.
1303 */
1304 if (!eldbus_proxy_call(manager_master, "Create", create_cb, NULL, -1, ""))
1305 {
1306 ERR("Error: could not call Create");
1307 return EXIT_FAILURE;
1308 }
1309
1310 master_poi = eldbus_proxy_get(obj_master, GEOCLUE_POI_IFACE);
1311 if (!master_poi)
1312 {
1313 ERR("Error: could not get proxy");
1314 return EXIT_FAILURE;
1315 }
1316
1317 /* Geocode and reverse geocode never show up as meta provider. Still we want
1318 * to be able to convert so we keep them around directly here. */
1319 obj_geonames= eldbus_object_get(conn, GEONAMES_DBUS_NAME, GEONAMES_OBJECT_PATH);
1320 if (!obj_geonames)
1321 {
1322 ERR("Error: could not get object for geonames");
1323 return EXIT_FAILURE;
1324 }
1325
1326 geonames_geocode = eldbus_proxy_get(obj_geonames, GEOCLUE_GEOCODE_IFACE);
1327 if (!geonames_geocode)
1328 {
1329 ERR("Error: could not get proxy");
1330 return EXIT_FAILURE;
1331 }
1332
1333 geonames_rgeocode = eldbus_proxy_get(obj_geonames, GEOCLUE_REVERSEGEOCODE_IFACE);
1334 if (!geonames_rgeocode)
1335 {
1336 ERR("Error: could not get proxy");
1337 return EXIT_FAILURE;
1338 }
1339
1340 eldbus_name_owner_changed_callback_add(conn, GEOCLUE_DBUS_NAME, _name_owner_changed,
1341 NULL, EINA_TRUE);
1342
1343 ecore_event_handler_add(ELOCATION_EVENT_IN, geoclue_start, NULL);
1344 ecore_event_handler_add(ELOCATION_EVENT_OUT, geoclue_stop, NULL);
1345
1346 return EINA_TRUE;
1347}
1348
1349/* Public API function to shutdown the elocation library form the application */
1350EAPI void
1351elocation_shutdown(void)
1352{
1353 /* Depending on if the create_cb was successfully received meta_geoclue is
1354 * setup or not. So we * need to check here if this is not the case
1355 */
1356 if (meta_geoclue)
1357 {
1358 /* To allow geoclue freeing unused providers we free our reference on it here */
1359 if (!eldbus_proxy_call(meta_geoclue, "RemoveReference", _reference_del_cb, NULL, -1, ""))
1360 {
1361 ERR("Error: could not call RemoveReference");
1362 }
1363 }
1364
1365 /* Quite a bit of allocated string and generic memory cleanup. This should be
1366 *less when we went away from all this global var business.
1367 */
1368 if (address_provider)
1369 {
1370 free(address_provider->name);
1371 free(address_provider->description);
1372 free(address_provider->service);
1373 free(address_provider->path);
1374 free(address_provider);
1375 }
1376
1377 if (position_provider)
1378 {
1379 free(position_provider->name);
1380 free(position_provider->description);
1381 free(position_provider->service);
1382 free(position_provider->path);
1383 free(position_provider);
1384 }
1385
1386 if (pos_geocode)
1387 {
1388 free(pos_geocode->accur);
1389 free(pos_geocode);
1390 }
1391
1392 if (addr_geocode)
1393 {
1394 free(addr_geocode->country);
1395 free(addr_geocode->countrycode);
1396 free(addr_geocode->locality);
1397 free(addr_geocode->postalcode);
1398 free(addr_geocode->region);
1399 free(addr_geocode->timezone);
1400 free(addr_geocode->accur);
1401 free(addr_geocode);
1402 }
1403
1404 /* Unreference some eldbus strcutures we now longer use. To allow eldbus to
1405 * free them internally.
1406 */
1407 if (manager_master)
1408 eldbus_proxy_unref(manager_master);
1409
1410 eldbus_name_owner_changed_callback_del(conn, GEOCLUE_DBUS_NAME, _name_owner_changed, NULL);
1411 eldbus_connection_unref(conn);
1412 eldbus_shutdown();
1413 ecore_shutdown();
1414 eina_log_domain_unregister(_elocation_log_dom);
1415 eina_shutdown();
1416}
diff --git a/src/lib/elocation/elocation_private.h b/src/lib/elocation/elocation_private.h
new file mode 100644
index 0000000000..1203cc35b1
--- /dev/null
+++ b/src/lib/elocation/elocation_private.h
@@ -0,0 +1,181 @@
1#ifndef _ELOCATION_PRIVATE_H
2#define _ELOCATION_PRIVATE_H
3
4#ifdef HAVE_CONFIG_H
5#include "config.h"
6#endif
7
8#include <stdio.h>
9
10#include <Eina.h>
11#include <Ecore.h>
12#include <Eldbus.h>
13
14#ifndef ELOCATION_COLOR_DEFAULT
15#define ELOCATION_COLOR_DEFAULT EINA_COLOR_BLUE
16#endif
17extern int _elocation_log_dom;
18#ifdef CRI
19#undef CRI
20#endif
21
22#ifdef ERR
23#undef ERR
24#endif
25#ifdef INF
26#undef INF
27#endif
28#ifdef WARN
29#undef WARN
30#endif
31#ifdef DBG
32#undef DBG
33#endif
34
35#define CRI(...) EINA_LOG_DOM_CRIT(_elocation_log_dom, __VA_ARGS__)
36#define DBG(...) EINA_LOG_DOM_DBG(_elocation_log_dom, __VA_ARGS__)
37#define INF(...) EINA_LOG_DOM_INFO(_elocation_log_dom, __VA_ARGS__)
38#define WARN(...) EINA_LOG_DOM_WARN(_elocation_log_dom, __VA_ARGS__)
39#define ERR(...) EINA_LOG_DOM_ERR(_elocation_log_dom, __VA_ARGS__)
40
41/* Provider bus names and object paths. Master is the generic one which should
42 * pick up the best one internally based on given requirements. It is also still
43 * possible to use providers directly */
44#define GEOCLUE_DBUS_NAME "org.freedesktop.Geoclue.Master"
45#define GEOCLUE_OBJECT_PATH "/org/freedesktop/Geoclue/Master"
46#define GSMLOC_DBUS_NAME "org.freedesktop.Geoclue.Providers.Gsmloc"
47#define GSMLOC_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Gsmloc"
48#define HOSTIP_DBUS_NAME "org.freedesktop.Geoclue.Providers.Hostip"
49#define HOSTIP_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Hostip"
50#define SKYHOOK_DBUS_NAME "org.freedesktop.Geoclue.Providers.Skyhook"
51#define SKYHOOK_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Skyhook"
52#define UBUNTU_DBUS_NAME "org.freedesktop.Geoclue.Providers.UbuntuGeoIP"
53#define UBUNTU_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/UbuntuGeoIP"
54#define GEONAMES_DBUS_NAME "org.freedesktop.Geoclue.Providers.Geonames"
55#define GEONAMES_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Geonames"
56#define PLAZES_DBUS_NAME "org.freedesktop.Geoclue.Providers.Plazes"
57#define PLAZES_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Plazes"
58#define YAHOO_DBUS_NAME "org.freedesktop.Geoclue.Providers.Yahoo"
59#define YAHOO_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Yahoo"
60
61/* Master interfaces to control geoclue */
62#define GEOCLUE_MASTER_IFACE "org.freedesktop.Geoclue.Master"
63#define GEOCLUE_MASTERCLIENT_IFACE "org.freedesktop.Geoclue.MasterClient"
64
65/* Provider interfaces to access location data */
66#define GEOCLUE_GEOCLUE_IFACE "org.freedesktop.Geoclue"
67#define GEOCLUE_POSITION_IFACE "org.freedesktop.Geoclue.Position"
68#define GEOCLUE_ADDRESS_IFACE "org.freedesktop.Geoclue.Address"
69#define GEOCLUE_VELOCITY_IFACE "org.freedesktop.Geoclue.Velocity"
70#define GEOCLUE_GEOCODE_IFACE "org.freedesktop.Geoclue.Geocode"
71#define GEOCLUE_REVERSEGEOCODE_IFACE "org.freedesktop.Geoclue.ReverseGeocode"
72
73/* More provider interfaces. These three are not in upstream geoclue but only
74 * in the Tizen version. Lets hope they get upstream at some point. Right now
75 * we will test at runtime if they are offered and ignore them if not */
76#define GEOCLUE_NMEA_IFACE "org.freedesktop.Geoclue.Nmea"
77#define GEOCLUE_SATELLITE_IFACE "org.freedesktop.Geoclue.Satellite"
78#define GEOCLUE_POI_IFACE "org.freedesktop.Geoclue.Poi"
79
80#define GEOCLUE_ADDRESS_KEY_AREA "area"
81#define GEOCLUE_ADDRESS_KEY_COUNTRY "country"
82#define GEOCLUE_ADDRESS_KEY_COUNTRYCODE "countrycode"
83#define GEOCLUE_ADDRESS_KEY_LOCALITY "locality"
84#define GEOCLUE_ADDRESS_KEY_POSTALCODE "postalcode"
85#define GEOCLUE_ADDRESS_KEY_REGION "region"
86#define GEOCLUE_ADDRESS_KEY_STREET "street"
87
88extern int ELOCATION_EVENT_IN;
89extern int ELOCATION_EVENT_OUT;
90
91/* Some ENUMs that we mimic from GeoClue code as we only access it over the DBus
92 * interface and share no header file for such defines.
93 */
94
95/**
96 * @ingroup Location
97 * @typedef GeocluePositionFields
98 * @since 1.8
99 *
100 * Bitmask to indicate which of the supplied positions fields are valid.
101 *
102 * @{
103 */
104typedef enum {
105 GEOCLUE_POSITION_FIELDS_NONE = 0,
106 GEOCLUE_POSITION_FIELDS_LATITUDE = 1 << 0,
107 GEOCLUE_POSITION_FIELDS_LONGITUDE = 1 << 1,
108 GEOCLUE_POSITION_FIELDS_ALTITUDE = 1 << 2
109} GeocluePositionFields;
110/**@}*/
111
112/**
113 * @ingroup Location
114 * @typedef GeoclueNetworkStatus
115 * @since 1.8
116 *
117 * Status of the network connectivity for GeoClue. Needed for all providers that
118 * access external data to determine the location. For example GeoIP or GeoCode
119 * providers.
120 *
121 * @{
122 */
123typedef enum {
124 GEOCLUE_CONNECTIVITY_UNKNOWN,
125 GEOCLUE_CONNECTIVITY_OFFLINE,
126 GEOCLUE_CONNECTIVITY_ACQUIRING,
127 GEOCLUE_CONNECTIVITY_ONLINE,
128} GeoclueNetworkStatus;
129/**@}*/
130
131/**
132 * @ingroup Location
133 * @typedef GeoclueStatus
134 * @since 1.8
135 *
136 * Status of a GeoClue provider.
137 *
138 * @{
139 */
140typedef enum {
141 GEOCLUE_STATUS_ERROR,
142 GEOCLUE_STATUS_UNAVAILABLE,
143 GEOCLUE_STATUS_ACQUIRING,
144 GEOCLUE_STATUS_AVAILABLE
145} GeoclueStatus;
146/**@}*/
147
148/**
149 * @ingroup Location
150 * @typedef GeoclueVelocityFields
151 * @since 1.8
152 *
153 * Bitmask to indicate which of the supplied velocity fields are valid.
154 *
155 * @{
156 */
157typedef enum {
158 GEOCLUE_VELOCITY_FIELDS_NONE = 0,
159 GEOCLUE_VELOCITY_FIELDS_SPEED = 1 << 0,
160 GEOCLUE_VELOCITY_FIELDS_DIRECTION = 1 << 1,
161 GEOCLUE_VELOCITY_FIELDS_CLIMB = 1 << 2
162} GeoclueVelocityFields;
163/**@}*/
164
165/**
166 * @ingroup Location
167 * @typedef Elocation_Provider
168 * @since 1.8
169 *
170 * Data structure to hold information about a GeoClue provider.
171 *
172 */
173typedef struct _Elocation_Provider
174{
175 char *name;
176 char *description;
177 char *service;
178 char *path;
179 GeoclueStatus status;
180} Elocation_Provider;
181#endif