elocation: Add elocation libraray to EFL.

Elocation is meant as a convenience library to ease application developers
the usage of geo information in their apps. Adding a geo tag to a picture or
translating an address to a GPS position and show it on a map widget are just
some of the use cases.

This has been developed a while ago and was living in my private dev space.
It is about time to move this into EFL and bring it forward.

So far it has only support for GeoClue1 while I already work on GeoClue2
support. The API is not considered stable yet and it will change for sure when
the GeoClue2 support gets merged. We will likely start if a reduced API when
1.13 gets released and extend if over time.
This commit is contained in:
Stefan Schmidt 2014-11-11 13:36:10 +01:00
commit 513d6f397e
14 changed files with 2566 additions and 1 deletions

View File

@ -4374,6 +4374,42 @@ EFL_EVAL_PKGS([ELUA])
EFL_LIB_END_OPTIONAL([Elua])
#### End of Elua
#### Elocation
EFL_LIB_START([Elocation])
### Default values
### Additional options to configure
### Checks for programs
### Checks for libraries
EFL_PLATFORM_DEPEND([ELOCATION], [evil])
EFL_INTERNAL_DEPEND_PKG([ELOCATION], [eina])
EFL_INTERNAL_DEPEND_PKG([ELOCATION], [eo])
EFL_INTERNAL_DEPEND_PKG([ELOCATION], [ecore])
EFL_INTERNAL_DEPEND_PKG([ELOCATION], [eldbus])
EFL_ADD_LIBS([ELOCATION], [-lm])
### Checks for header files
### Checks for types
### Checks for structures
### Checks for compiler characteristics
### Checks for linker characteristics
### Checks for library functions
### Check availability
EFL_LIB_END([Elocation])
#### End of Elocation
### Add Wayland server library if test is enabled
if test "x${want_tests}" = "xyes" -a "x${want_wayland}" = "xyes"; then
EFL_DEPEND_PKG([ECORE_WAYLAND_SRV], [WAYLAND], [wayland-server >= 1.3.0])
@ -4431,6 +4467,7 @@ src/examples/emotion/Makefile
src/examples/ethumb_client/Makefile
src/examples/elua/Makefile
src/examples/eolian_cxx/Makefile
src/examples/elocation/Makefile
src/lib/eina/eina_config.h
src/lib/ecore_x/ecore_x_version.h
src/lib/efl/Efl_Config.h
@ -4496,6 +4533,7 @@ pc/edje-cxx.pc
pc/emotion.pc
pc/ethumb.pc
pc/ethumb_client.pc
pc/elocation.pc
dbus-services/org.enlightenment.Efreet.service
dbus-services/org.enlightenment.Ethumb.service
systemd-services/efreet.service

View File

@ -24,6 +24,7 @@
* @li @ref evil_main microsoft windows portability layer.
* @li @ref eolian_main an EO file parser and code generator.
* @li @ref eina_cxx_main Eina C++ bindings.
* @li @ref Location awareness library.
*
*/

1
pc/.gitignore vendored
View File

@ -28,6 +28,7 @@
/eet-cxx.pc
/eio.pc
/eldbus.pc
/elocation.pc
/embryo.pc
/emotion.pc
/eo.pc

12
pc/elocation.pc.in Normal file
View File

@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: elocation
Description: Enlightenment location library
@pkgconfig_requires_private@: @requirements_elocation@
Version: @VERSION@
Libs: -L${libdir} -lelocation
Libs.private: -lm
Cflags: -I${includedir}/elocation-@VMAJ@

View File

@ -78,8 +78,8 @@ include Makefile_Eolian_Cxx.am
include Makefile_Eet_Cxx.am
include Makefile_Eo_Cxx.am
include Makefile_Efl_Cxx.am
include Makefile_Elua.am
include Makefile_Elocation.am
.PHONY: benchmark examples
@ -107,6 +107,7 @@ examples/eldbus \
examples/ephysics \
examples/edje \
examples/emotion \
examples/elocation \
examples/ethumb_client
if HAVE_ELUA

37
src/Makefile_Elocation.am Normal file
View File

@ -0,0 +1,37 @@
### Library
lib_LTLIBRARIES += lib/elocation/libelocation.la
installed_elocationsmainheadersdir = $(includedir)/elocation-@VMAJ@
dist_installed_elocationsmainheaders_DATA = \
lib/elocation/Elocation.h \
lib/elocation/elocation_private.h
lib_elocation_libelocation_la_SOURCES = \
lib/elocation/elocation.c
lib_elocation_libelocation_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ELOCATION_CFLAGS@
lib_elocation_libelocation_la_LIBADD = @ELOCATION_LIBS@
lib_elocation_libelocation_la_DEPENDENCIES = @ELOCATION_INTERNAL_LIBS@
lib_elocation_libelocation_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
### Unit tests
if EFL_ENABLE_TESTS
check_PROGRAMS += tests/elocation/elocation_suite
TESTS += tests/elocation/elocation_suite
tests_elocation_elocation_suite_SOURCES = \
tests/elocation/elocation_suite.c
tests_elocation_elocation_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-DTESTS_WD=\"`pwd`\" \
-DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/elocation\" \
-DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/elocation\" \
@CHECK_CFLAGS@ \
@ELOCATION_CFLAGS@
tests_elocation_elocation_suite_LDADD = @CHECK_LIBS@ @USE_ELOCATION_LIBS@
tests_elocation_elocation_suite_DEPENDENCIES = @USE_ELOCATION_INTERNAL_LIBS@
endif

1
src/examples/elocation/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/elocation

View File

@ -0,0 +1,51 @@
MAINTAINERCLEANFILES = Makefile.in
AM_CPPFLAGS = \
-I$(top_builddir)/src/lib/efl \
-I$(top_srcdir)/src/lib/eina \
-I$(top_srcdir)/src/lib/eo \
-I$(top_srcdir)/src/lib/ecore \
-I$(top_srcdir)/src/lib/eldbus \
-I$(top_srcdir)/src/lib/elocation \
-I$(top_builddir)/src/lib/eina \
-I$(top_builddir)/src/lib/eo \
-I$(top_builddir)/src/lib/ecore \
-I$(top_builddir)/src/lib/eldbus \
-I$(top_builddir)/src/lib/elocation
EXTRA_PROGRAMS = \
elocation
elocation_SOURCES = elocation.c
elocation_LDADD = \
$(top_builddir)/src/lib/elocation/libelocation.la \
$(top_builddir)/src/lib/eo/libeo.la \
$(top_builddir)/src/lib/ecore/libecore.la \
$(top_builddir)/src/lib/eldbus/libeldbus.la \
$(top_builddir)/src/lib/eina/libeina.la \
@ELOCATION_LDFLAGS@
SRCS = \
elocation.c
DATA_FILES = Makefile.examples
EXTRA_DIST = $(DATA_FILES)
examples: $(EXTRA_PROGRAMS)
clean-local:
rm -f $(EXTRA_PROGRAMS)
install-examples:
mkdir -p $(datadir)/elocation/examples
cd $(srcdir) && $(install_sh_DATA) -c $(SRCS) $(DATA_FILES) $(datadir)/elocation/examples
uninstall-local:
for f in $(SRCS) $(DATA_FILES); do \
rm -f $(datadir)/elocation/examples/$$f ; \
done
if ALWAYS_BUILD_EXAMPLES
noinst_PROGRAMS = $(EXTRA_PROGRAMS)
endif

View File

@ -0,0 +1,14 @@
CC=gcc
COMMON_FLAGS=`pkg-config --libs --cflags eina,ecore,eldbus,elocation`
EXAMPLES= elocation
all: examples
examples: $(EXAMPLES)
$(EXAMPLES):
$(CC) -o $@ $@.c $(COMMON_FLAGS)
clean:
@echo "Cleaning up built objects..."
@rm -Rf $(EXAMPLES)

View File

@ -0,0 +1,169 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <Ecore.h>
#include <Elocation.h>
/* A set of callbacks to react on incoming elocation events. They are standard
* ecore events and we register callbacks based on these events in the main
* function.
*/
static Eina_Bool
status_changed(void *data, int ev_type, void *event)
{
int *status = event;
printf("Status changed to: %i\n", *status);
printf("\n");
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
rgeocode_arrived(void *data, int ev_type, void *event)
{
Elocation_Address *address;
address = event;
printf("Geocode reply:\n");
printf("Country: %s\n", address->country);
printf("Countrycode: %s\n", address->countrycode);
printf("Locality: %s\n", address->locality);
printf("Postalcode: %s\n", address->postalcode);
printf("Region: %s\n", address->region);
printf("Timezone: %s\n", address->timezone);
printf("Accuracy level: %i\n", address->accur->level);
printf("Accuracy horizontal: %f\n", address->accur->horizontal);
printf("Accuracy vertical: %f\n", address->accur->vertical);
printf("\n");
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
geocode_arrived(void *data, int ev_type, void *event)
{
Elocation_Position *position;
position = event;
printf("Reverse geocode reply:\n");
printf("Latitude:\t %f\n", position->latitude);
printf("Longitude:\t %f\n", position->longitude);
printf("Altitude:\t %f\n", position->altitude);
printf("Accuracy level: %i\n", position->accur->level);
printf("Accuracy horizontal: %f\n", position->accur->horizontal);
printf("Accuracy vertical: %f\n", position->accur->vertical);
printf("\n");
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
address_changed(void *data, int ev_type, void *event)
{
Elocation_Address *address;
address = event;
printf("Address update with data from timestamp: %i\n", address->timestamp);
printf("Country: %s\n", address->country);
printf("Countrycode: %s\n", address->countrycode);
printf("Locality: %s\n", address->locality);
printf("Postalcode: %s\n", address->postalcode);
printf("Region: %s\n", address->region);
printf("Timezone: %s\n", address->timezone);
printf("Accuracy level: %i\n", address->accur->level);
printf("Accuracy horizontal: %f\n", address->accur->horizontal);
printf("Accuracy vertical: %f\n", address->accur->vertical);
printf("\n");
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
position_changed(void *data, int ev_type, void *event)
{
Elocation_Position *position;
position = event;
printf("GeoClue position reply with data from timestamp %i\n", position->timestamp);
printf("Latitude:\t %f\n", position->latitude);
printf("Longitude:\t %f\n", position->longitude);
printf("Altitude:\t %f\n", position->altitude);
printf("Accuracy level: %i\n", position->accur->level);
printf("Accuracy horizontal: %f\n", position->accur->horizontal);
printf("Accuracy vertical: %f\n", position->accur->vertical);
printf("\n");
return ECORE_CALLBACK_DONE;
}
int
main(void)
{
Elocation_Address *address, *addr_geocode;
Elocation_Position *position, *pos_geocode;
int status;
/* Init the needed efl subsystems so we can safely use them */
ecore_init();
eldbus_init();
elocation_init();
/* Create an address and positon object that we use for all our operations.
* Needs to be freed manually with elocation_*_free when we now longer use
* them */
address = elocation_address_new();
position = elocation_position_new();
/* Register callback so we get updates later on */
ecore_event_handler_add(ELOCATION_EVENT_STATUS, status_changed, NULL);
ecore_event_handler_add(ELOCATION_EVENT_POSITION, position_changed, NULL);
ecore_event_handler_add(ELOCATION_EVENT_ADDRESS, address_changed, NULL);
ecore_event_handler_add(ELOCATION_EVENT_GEOCODE, geocode_arrived, NULL);
ecore_event_handler_add(ELOCATION_EVENT_REVERSEGEOCODE, rgeocode_arrived, NULL);
/* To the initial request for status address and position. This fills in the
* objects with the data from GeoClue */
elocation_status_get(&status);
elocation_position_get(position);
elocation_address_get(address);
/* Another set of address and position object. This time for demonstrating
* the GeoCode functionalities */
addr_geocode = elocation_address_new();
pos_geocode = elocation_position_new();
/* The Freeform API could use any string to transform it into position
* coordinates. How good that works depends on the used GeoClue provider */
elocation_freeform_address_to_position("London", pos_geocode);
/* Some demo values to show the position to address conversion */
pos_geocode->latitude = 51.7522;
pos_geocode->longitude = -1.25596;
pos_geocode->accur->level = 3;
elocation_position_to_address(pos_geocode, addr_geocode);
/* And now from address to position */
addr_geocode->locality = "Cambridge";
addr_geocode->countrycode = "UK";
elocation_address_to_position(addr_geocode, pos_geocode);
/* Enter the mainloop now that we are setup with initial data and waiting for
* events. */
ecore_main_loop_begin();
/* Cleanup allocated memory now that we shut down */
elocation_address_free(addr_geocode);
elocation_position_free(pos_geocode);
elocation_address_free(address);
elocation_position_free(position);
/* Make sure we also shut down the initialized subsystems */
elocation_shutdown();
eldbus_shutdown();
ecore_shutdown();
return 0;
}

View File

@ -0,0 +1,413 @@
/**
* @file Elocation.h
* @brief Elocation Library
*
* @defgroup Location Location
*/
/**
*
* @section intro Elocation Use Cases
*
* Elocation is meant as a convenience library to ease application developers
* the usage of geo information in their apps. Adding a geo tag to a picture or
* translating an address to a GPS position and show it on a map widget are just
* some of the use cases.
*
* In the beginning elocation will rely on the GeoClue DBus service. Its has
* providers for various techniques to get hold off the current position.
* Ranging from GeoIP over wifi and GSM cell location to GPS. As well as
* provider to translates between location in a textual form to coordinates
* (GeoCode).
*
* Elocation covers all of these interfaces but in the end it depends on your
* system and the installed GeoClue providers what can be used.
*
* Currently it offer the following functionality:
* @li Request current address in textual form
* @li Request current position in GPS format
* @li Translate a position into and address or an address in a position
*
* You can find the API documentation at @ref Location
*/
#ifndef _ELOCATION_H
#define _ELOCATION_H
#ifdef EAPI
# undef EAPI
#endif
#ifdef _WIN32
# ifdef EFL_ECORE_BUILD
# ifdef DLL_EXPORT
# define EAPI __declspec(dllexport)
# else
# define EAPI
# endif /* ! DLL_EXPORT */
# else
# define EAPI __declspec(dllimport)
# endif /* ! EFL_ECORE_BUILD */
#else
# ifdef __GNUC__
# if __GNUC__ >= 4
# define EAPI __attribute__ ((visibility("default")))
# else
# define EAPI
# endif
# else
# define EAPI
# endif
#endif /* ! _WIN32 */
#include <stdio.h>
#include <Ecore.h>
#include <Eldbus.h>
/**
* @ingroup Location
* @brief Available location events that are emitted from the library
* @since 1.13
*
* Ecore events emitted by the library. Applications can register ecore event
* handlers to react on such events. After the initial query this can be used
* to keep track of changes and update your UI or data accordingly.
* @{
*/
EAPI extern int ELOCATION_EVENT_STATUS; /**< Status changed */
EAPI extern int ELOCATION_EVENT_POSITION; /**< Position changed */
EAPI extern int ELOCATION_EVENT_ADDRESS; /**< Address changed */
EAPI extern int ELOCATION_EVENT_VELOCITY; /**< Velocity changed */
EAPI extern int ELOCATION_EVENT_GEOCODE; /**< Reply for geocode translation arrived */
EAPI extern int ELOCATION_EVENT_REVERSEGEOCODE; /**< Reply for geocode translation arrived */
EAPI extern int ELOCATION_EVENT_NMEA; /**< NMEA update */
EAPI extern int ELOCATION_EVENT_SATELLITE; /**< Satellite info changed */
EAPI extern int ELOCATION_EVENT_POI; /**< POI reply */
EAPI extern int ELOCATION_EVENT_META_READY; /**< Meta provider is ready to be used */
/**@}*/
/**
* @ingroup Location
* @typedef Elocation_Accuracy_Level
* @since 1.13
*
* Different location accuracy levels from country level up to detailed,
* e.g. GPS, information.
* @{
*/
typedef enum {
ELOCATION_ACCURACY_LEVEL_NONE = 0,
ELOCATION_ACCURACY_LEVEL_COUNTRY,
ELOCATION_ACCURACY_LEVEL_REGION,
ELOCATION_ACCURACY_LEVEL_LOCALITY,
ELOCATION_ACCURACY_LEVEL_POSTALCODE,
ELOCATION_ACCURACY_LEVEL_STREET,
ELOCATION_ACCURACY_LEVEL_DETAILED,
} Elocation_Accuracy_Level;
/**@}*/
/**
* @ingroup Location
* @typedef Elocation_Resource_Flags
* @since 1.13
*
* Flags for available system resources to be used for locating. So far they
* cover physical resources like network connection, cellular network
* connection and GPS.
* @{
*/
typedef enum {
ELOCATION_RESOURCE_NONE = 0,
ELOCATION_RESOURCE_NETWORK = 1 << 0, /**< Internet connection is available */
ELOCATION_RESOURCE_CELL = 1 << 1, /**< Cell network information, e.g. GSM, is available */
ELOCATION_RESOURCE_GPS = 1 << 2, /**< GPS information is available */
ELOCATION_RESOURCE_ALL = (1 << 10) - 1 /**< All resources are available */
} Elocation_Resource_Flags;
/**@}*/
/**
* @ingroup Location
* @typedef Elocation_Accuracy
* @since 1.13
*
* Information about the accuracy of the reported location. For details about
* the level of accuracy see #Elocation_Accuracy_Level. It also covers
* horizontal and vertical accuracy. The values depend on the used provider
* and may very in quality.
*/
typedef struct _Elocation_Accuracy
{
Elocation_Accuracy_Level level;
double horizontal;
double vertical;
} Elocation_Accuracy;
/**
* @ingroup Location
* @typedef Elocation_Address
* @since 1.13
*
* Location information in textual form. Depending on the used provider this
* can cover only the country or a detailed address with postcode and street.
* The level of detail varies depending on the used provider.
* A timestamp is available to calculate the age of the address data.
*/
typedef struct _Elocation_Address
{
unsigned int timestamp; /**< Timestamp of data read out in seconds since epoch */
char *country;
char *countrycode;
char *locality;
char *postalcode;
char *region;
char *timezone;
Elocation_Accuracy *accur;
} Elocation_Address;
/**
* @ingroup Location
* @typedef Elocation_Position
* @since 1.13
*
* Location information based on the GPS grid. Latitude, longitude and altitude.
* A timestamp is available to calculate the age of the address data.
*/
typedef struct _Elocation_Postion
{
unsigned int timestamp; /**< Timestamp of data read out in seconds since epoch */
double latitude;
double longitude;
double altitude;
Elocation_Accuracy *accur;
} Elocation_Position;
/**
* @ingroup Location
* @typedef Elocation_Velocity
* @since 1.13
*
* Velocity information. So far this interface is only offered with GPS based
* providers. It offers information about speed, direction and climb.
* A timestamp is available to calculate the age of the address data.
*
* FIXME: check units and formats of this values coming in from GeoClue
*/
typedef struct _Elocation_Velocity
{
unsigned int timestamp; /**< Timestamp of data read out in seconds since epoch */
double speed;
double direction;
double climb;
} Elocation_Velocity;
/**
* @ingroup Location
* @typedef Elocation_Requirements
* @since 1.13
*
* Requirement settings for the location provider. Requirements can be a level
* of accuracy or allowed resources like network access or GPS. See
* #Elocation_Resource_Flags for all available resource flags.
*
* Based on this setting the best provider is chosen between the available
* providers of GeoClue.
*/
typedef struct _Elocation_Requirements
{
Elocation_Accuracy_Level accurancy_level;
int min_time; /**< Minimal time between updates. Not implemented upstream */
Eina_Bool require_update;
Elocation_Resource_Flags allowed_resources;
} Elocation_Requirements;
/**
* @brief Create a new address object to operate on.
* @return Address object.
*
* The returned address object is safe to be operated on. It can be used for
* all other elocation functions. Once finished with it it need to be destroyed
* with a call to #elocation_address_free.
*
* @ingroup Location
* @since 1.13
*/
EAPI Elocation_Address *elocation_address_new(void);
/**
* @brief Free an address object
* @param address Address object to be freed.
*
* Destroys an address object created with #elocation_address_new. Should be
* used during the cleanup of the application or whenever the address object is
* no longer needed.
*
* @ingroup Location
* @since 1.13
*/
EAPI void elocation_address_free(Elocation_Address *address);
/**
* @brief Create a new position object to operate on.
* @return Position object.
*
* The returned address object is safe to be operated on. It can be used for
* all other elocation functions. Once finished with it it need to be destroyed
* with a call to #elocation_address_free.
*
* @ingroup Location
* @since 1.13
*/
EAPI Elocation_Position *elocation_position_new(void);
/**
* @brief Free an position object
* @param position Position object to be freed.
*
* Destroys a position object created with #elocation_address_new. Should be
* used during the cleanup of the application or whenever the location object is
* no longer needed.
*
* @ingroup Location
* @since 1.13
*/
EAPI void elocation_position_free(Elocation_Position *position);
/**
* @brief Get the current address information.
* @param address Address struct to be filled with information.
* @return EINA_TRUE for success and EINA_FALSE for failure.
*
* Request the latest address. The requested to the underling components might
* be asynchronous so better check the timestamp if the data has changed. To get
* events when the address changes one can also subscribe to the
* #ELOCATION_EVENT_ADDRESS ecore event which will have the address object as
* event.
*
* @ingroup Location
* @since 1.13
*/
EAPI Eina_Bool elocation_address_get(Elocation_Address *address);
/**
* @brief Get the current position information.
* @param position Position struct to be filled with information.
* @return EINA_TRUE for success and EINA_FALSE for failure.
*
* Request the latest position. The requested to the underling components might
* be asynchronous so better check the timestamp if the data has changed. To get
* events when the position changes one can also subscribe to the
* #ELOCATION_EVENT_POSITION ecore event which will have the position object as
* event.
*
* @ingroup Location
* @since 1.13
*/
EAPI Eina_Bool elocation_position_get(Elocation_Position *position);
/**
* @brief Get the current status.
* @param status Status
* @return EINA_TRUE for success and EINA_FALSE for failure.
*
* @ingroup Location
* @since 1.13
*/
EAPI Eina_Bool elocation_status_get(int *status);
/**
* @brief Set the requirements.
* @param requirements Requirements
* @return EINA_TRUE for success and EINA_FALSE for failure.
*
* Set the requirements for selecting a provider.
*
* @ingroup Location
* @since 1.13
*/
EAPI Eina_Bool elocation_requirements_set(Elocation_Requirements *requirements);
/**
* @brief Convert position to address
* @param position_shadow Position input
* @param address_shadow Address output
* @return EINA_TRUE for success and EINA_FALSE for failure.
*
* Use a GeoCode provider to translate from a given GPS coordinate
* representation of a location to a representation in textual form.
*
* @ingroup Location
* @since 1.13
*/
EAPI Eina_Bool elocation_position_to_address(Elocation_Position *position_shadow, Elocation_Address *address_shadow);
/**
* @brief Convert address to position
* @param address_shadow Address input
* @param position_shadow Position output
* @return EINA_TRUE for success and EINA_FALSE for failure.
*
* Use a GeoCode provider to translate from a given textual form
* representation of a location to a representation as GPS coordinates.
*
* @ingroup Location
* @since 1.13
*/
EAPI Eina_Bool elocation_address_to_position(Elocation_Address *address_shadow, Elocation_Position *position_shadow);
/**
* @brief Convert free form address tring to position
* @param freeform_address Address string in free form
* @param position_shadow Position output
* @return EINA_TRUE for success and EINA_FALSE for failure.
*
* Similar GeoCode translation from textual form to GPS coordinates as
* #elocation_address_to_position but in this case the address is a simple
* string which hopefully contains enough information for the provider to
* understand and translate.
*
* Useful for an easy search interface in an application but also more error
* prone regarding correct results.
*
* @ingroup Location
* @since 1.13
*/
EAPI Eina_Bool elocation_freeform_address_to_position(const char *freeform_address, Elocation_Position *position_shadow);
/**
* @brief Request a landmark position
* @param position_shadow Position ouput
* @param address_shadow Address input
* @return EINA_TRUE for success and EINA_FALSE for failure.
*
* Request a landmark position also known as Point Of Interest (POI) from
* GeoClue.
*
* @ingroup Location
* @since 1.13
*/
EAPI Eina_Bool elocation_landmarks_get(Elocation_Position *position_shadow, Elocation_Address *address_shadow);
/**
* @brief Initialize the elocation subsystem.
* @return EINA_TRUE for success and EINA_FALSE for failure.
*
* This function must be called before using any of the Elocation functionality
* in your application to make sure it it setup correctly for usage.
*
* @ingroup Location
* @since 1.13
*/
EAPI Eina_Bool elocation_init(void);
/**
* @brief Cleanup and shutdown the elocation subsystem.
*
* This function must be called when the application is no longer using any of
* the Elocation functionality to allow the subsystem to shutdown cleanly.
*
* @ingroup Location
* @since 1.13
*/
EAPI void elocation_shutdown(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,181 @@
#ifndef _ELOCATION_PRIVATE_H
#define _ELOCATION_PRIVATE_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <Eina.h>
#include <Ecore.h>
#include <Eldbus.h>
#ifndef ELOCATION_COLOR_DEFAULT
#define ELOCATION_COLOR_DEFAULT EINA_COLOR_BLUE
#endif
extern int _elocation_log_dom;
#ifdef CRI
#undef CRI
#endif
#ifdef ERR
#undef ERR
#endif
#ifdef INF
#undef INF
#endif
#ifdef WARN
#undef WARN
#endif
#ifdef DBG
#undef DBG
#endif
#define CRI(...) EINA_LOG_DOM_CRIT(_elocation_log_dom, __VA_ARGS__)
#define DBG(...) EINA_LOG_DOM_DBG(_elocation_log_dom, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_elocation_log_dom, __VA_ARGS__)
#define WARN(...) EINA_LOG_DOM_WARN(_elocation_log_dom, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(_elocation_log_dom, __VA_ARGS__)
/* Provider bus names and object paths. Master is the generic one which should
* pick up the best one internally based on given requirements. It is also still
* possible to use providers directly */
#define GEOCLUE_DBUS_NAME "org.freedesktop.Geoclue.Master"
#define GEOCLUE_OBJECT_PATH "/org/freedesktop/Geoclue/Master"
#define GSMLOC_DBUS_NAME "org.freedesktop.Geoclue.Providers.Gsmloc"
#define GSMLOC_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Gsmloc"
#define HOSTIP_DBUS_NAME "org.freedesktop.Geoclue.Providers.Hostip"
#define HOSTIP_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Hostip"
#define SKYHOOK_DBUS_NAME "org.freedesktop.Geoclue.Providers.Skyhook"
#define SKYHOOK_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Skyhook"
#define UBUNTU_DBUS_NAME "org.freedesktop.Geoclue.Providers.UbuntuGeoIP"
#define UBUNTU_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/UbuntuGeoIP"
#define GEONAMES_DBUS_NAME "org.freedesktop.Geoclue.Providers.Geonames"
#define GEONAMES_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Geonames"
#define PLAZES_DBUS_NAME "org.freedesktop.Geoclue.Providers.Plazes"
#define PLAZES_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Plazes"
#define YAHOO_DBUS_NAME "org.freedesktop.Geoclue.Providers.Yahoo"
#define YAHOO_OBJECT_PATH "/org/freedesktop/Geoclue/Providers/Yahoo"
/* Master interfaces to control geoclue */
#define GEOCLUE_MASTER_IFACE "org.freedesktop.Geoclue.Master"
#define GEOCLUE_MASTERCLIENT_IFACE "org.freedesktop.Geoclue.MasterClient"
/* Provider interfaces to access location data */
#define GEOCLUE_GEOCLUE_IFACE "org.freedesktop.Geoclue"
#define GEOCLUE_POSITION_IFACE "org.freedesktop.Geoclue.Position"
#define GEOCLUE_ADDRESS_IFACE "org.freedesktop.Geoclue.Address"
#define GEOCLUE_VELOCITY_IFACE "org.freedesktop.Geoclue.Velocity"
#define GEOCLUE_GEOCODE_IFACE "org.freedesktop.Geoclue.Geocode"
#define GEOCLUE_REVERSEGEOCODE_IFACE "org.freedesktop.Geoclue.ReverseGeocode"
/* More provider interfaces. These three are not in upstream geoclue but only
* in the Tizen version. Lets hope they get upstream at some point. Right now
* we will test at runtime if they are offered and ignore them if not */
#define GEOCLUE_NMEA_IFACE "org.freedesktop.Geoclue.Nmea"
#define GEOCLUE_SATELLITE_IFACE "org.freedesktop.Geoclue.Satellite"
#define GEOCLUE_POI_IFACE "org.freedesktop.Geoclue.Poi"
#define GEOCLUE_ADDRESS_KEY_AREA "area"
#define GEOCLUE_ADDRESS_KEY_COUNTRY "country"
#define GEOCLUE_ADDRESS_KEY_COUNTRYCODE "countrycode"
#define GEOCLUE_ADDRESS_KEY_LOCALITY "locality"
#define GEOCLUE_ADDRESS_KEY_POSTALCODE "postalcode"
#define GEOCLUE_ADDRESS_KEY_REGION "region"
#define GEOCLUE_ADDRESS_KEY_STREET "street"
extern int ELOCATION_EVENT_IN;
extern int ELOCATION_EVENT_OUT;
/* Some ENUMs that we mimic from GeoClue code as we only access it over the DBus
* interface and share no header file for such defines.
*/
/**
* @ingroup Location
* @typedef GeocluePositionFields
* @since 1.13
*
* Bitmask to indicate which of the supplied positions fields are valid.
*
* @{
*/
typedef enum {
GEOCLUE_POSITION_FIELDS_NONE = 0,
GEOCLUE_POSITION_FIELDS_LATITUDE = 1 << 0,
GEOCLUE_POSITION_FIELDS_LONGITUDE = 1 << 1,
GEOCLUE_POSITION_FIELDS_ALTITUDE = 1 << 2
} GeocluePositionFields;
/**@}*/
/**
* @ingroup Location
* @typedef GeoclueNetworkStatus
* @since 1.13
*
* Status of the network connectivity for GeoClue. Needed for all providers that
* access external data to determine the location. For example GeoIP or GeoCode
* providers.
*
* @{
*/
typedef enum {
GEOCLUE_CONNECTIVITY_UNKNOWN,
GEOCLUE_CONNECTIVITY_OFFLINE,
GEOCLUE_CONNECTIVITY_ACQUIRING,
GEOCLUE_CONNECTIVITY_ONLINE,
} GeoclueNetworkStatus;
/**@}*/
/**
* @ingroup Location
* @typedef GeoclueStatus
* @since 1.13
*
* Status of a GeoClue provider.
*
* @{
*/
typedef enum {
GEOCLUE_STATUS_ERROR,
GEOCLUE_STATUS_UNAVAILABLE,
GEOCLUE_STATUS_ACQUIRING,
GEOCLUE_STATUS_AVAILABLE
} GeoclueStatus;
/**@}*/
/**
* @ingroup Location
* @typedef GeoclueVelocityFields
* @since 1.13
*
* Bitmask to indicate which of the supplied velocity fields are valid.
*
* @{
*/
typedef enum {
GEOCLUE_VELOCITY_FIELDS_NONE = 0,
GEOCLUE_VELOCITY_FIELDS_SPEED = 1 << 0,
GEOCLUE_VELOCITY_FIELDS_DIRECTION = 1 << 1,
GEOCLUE_VELOCITY_FIELDS_CLIMB = 1 << 2
} GeoclueVelocityFields;
/**@}*/
/**
* @ingroup Location
* @typedef Elocation_Provider
* @since 1.13
*
* Data structure to hold information about a GeoClue provider.
*
*/
typedef struct _Elocation_Provider
{
char *name;
char *description;
char *service;
char *path;
GeoclueStatus status;
} Elocation_Provider;
#endif

View File

@ -0,0 +1,233 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* ifdef HAVE_CONFIG_H */
#include <stdlib.h>
#include <stdio.h>
#include <check.h>
#include <Elocation.h>
/* Test the init and shutdown pathes only. Good to do that as we don't set up
* other things and already triggered problems with this.
*/
START_TEST(elocation_test_init)
{
Eina_Bool ret;
ret = elocation_init();
fail_if(ret != EINA_TRUE);
elocation_shutdown();
}
END_TEST
/* Basic address object testing. Creating and freeing the object */
START_TEST(elocation_test_address_object)
{
Eina_Bool ret;
Elocation_Address *address = NULL;
ret = elocation_init();
fail_if(ret != EINA_TRUE);
address = elocation_address_new();
fail_if(address == NULL);
elocation_address_free(address);
elocation_shutdown();
}
END_TEST
/* Basic position object testing. Creating and freeing the object */
START_TEST(elocation_test_position_object)
{
Eina_Bool ret;
Elocation_Position *position = NULL;
ret = elocation_init();
fail_if(ret != EINA_TRUE);
position = elocation_position_new();
fail_if(position == NULL);
elocation_position_free(position);
elocation_shutdown();
}
END_TEST
/* Basic testing for the various functions of the GeoCode API */
static int cb_count = 0;
static Eina_Bool
event_cb(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event)
{
fail_if(event == NULL);
/* We expect 3 callbacks right now */
if (++cb_count == 3)
ecore_main_loop_quit();
return ECORE_CALLBACK_DONE;
}
START_TEST(elocation_test_api_geocode)
{
Eina_Bool ret;
Elocation_Position *position = NULL;
Elocation_Address *address = NULL;
Ecore_Event_Handler *handler;
ret = elocation_init();
fail_if(ret != EINA_TRUE);
handler = ecore_event_handler_add(ELOCATION_EVENT_GEOCODE, event_cb, NULL);
fail_if(handler == NULL);
handler = ecore_event_handler_add(ELOCATION_EVENT_REVERSEGEOCODE, event_cb, NULL);
fail_if(handler == NULL);
position = elocation_position_new();
fail_if(position == NULL);
address = elocation_address_new();
fail_if(address == NULL);
ret = elocation_freeform_address_to_position("London", position);
fail_if(ret != EINA_TRUE);
position->latitude = 51.7522;
position->longitude = -1.25596;
position->accur->level = 3;
ret = elocation_position_to_address(position, address);
fail_if(ret != EINA_TRUE);
address->locality = strdup("Cambridge");
address->countrycode = strdup("UK");
ret = elocation_address_to_position(address, position);
fail_if(ret != EINA_TRUE);
ecore_main_loop_begin();
elocation_position_free(position);
elocation_address_free(address);
elocation_shutdown();
}
END_TEST
/* Basic testing for position API */
START_TEST(elocation_test_api_position)
{
Eina_Bool ret;
Elocation_Position *position = NULL;
ret = elocation_init();
fail_if(ret != EINA_TRUE);
position = elocation_position_new();
fail_if(position == NULL);
ret = elocation_position_get(position);
fail_if(ret != EINA_TRUE);
elocation_position_free(position);
elocation_shutdown();
}
END_TEST
/* Basic testing for address API */
START_TEST(elocation_test_api_address)
{
Eina_Bool ret;
Elocation_Address *address = NULL;
ret = elocation_init();
fail_if(ret != EINA_TRUE);
address = elocation_address_new();
fail_if(address == NULL);
ret = elocation_address_get(address);
fail_if(ret != EINA_TRUE);
elocation_address_free(address);
elocation_shutdown();
}
END_TEST
/* Basic testing for status API */
START_TEST(elocation_test_api_status)
{
Eina_Bool ret;
int status = 0;
ret = elocation_init();
fail_if(ret != EINA_TRUE);
ret = elocation_status_get(&status);
fail_if(ret != EINA_TRUE);
elocation_shutdown();
}
END_TEST
Suite *
elocation_suite(void)
{
Suite *s;
TCase *tc;
s = suite_create("Elocation");
tc = tcase_create("Elocation_Init");
tcase_add_test(tc, elocation_test_init);
suite_add_tcase(s, tc);
tc = tcase_create("Elocation_Objects");
tcase_add_test(tc, elocation_test_address_object);
tcase_add_test(tc, elocation_test_position_object);
suite_add_tcase(s, tc);
tc = tcase_create("Elocation_API_Geocode");
tcase_add_test(tc, elocation_test_api_geocode);
suite_add_tcase(s, tc);
tc = tcase_create("Elocation_API_Position");
tcase_add_test(tc, elocation_test_api_position);
suite_add_tcase(s, tc);
tc = tcase_create("Elocation_API_Address");
tcase_add_test(tc, elocation_test_api_address);
suite_add_tcase(s, tc);
/*
tc = tcase_create("Elocation_API_Status");
tcase_add_test(tc, elocation_test_api_status);
suite_add_tcase(s, tc);
*/
return s;
}
int
main(void)
{
Suite *s;
SRunner *sr;
int failed_count;
putenv("EFL_RUN_IN_TREE=1");
s = elocation_suite();
sr = srunner_create(s);
srunner_set_xml(sr, TESTS_BUILD_DIR "/check-results.xml");
srunner_run_all(sr, CK_ENV);
failed_count = srunner_ntests_failed(sr);
srunner_free(sr);
return (failed_count == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}