From 556956c8517b1c6593245b2cd10580035d4e7c98 Mon Sep 17 00:00:00 2001 From: Evgeny Bobkin Date: Mon, 19 Aug 2013 16:11:08 +0200 Subject: [PATCH] Vala support and common improvements -Introduce Api versioning for consisntency. -Minor enhancements in the configure.ac. -Add vala support: A metadata and custom.vala files were required to work around the async constructor issue and the order of arguments in -finish functions. -An optional demo written in vala is added. -Libs and Cflags were added to the pc file. -EXTRA_DIST were moved out of the "if introspection" condition. -Introspection support were rewritten in a more automake friendly way. --- configure.ac | 36 +++++++++++++---- demo/Makefile.am | 20 ++++++++- demo/find-location.vala | 99 +++++++++++++++++++++++++++++++++++++++++++++ src/Geoclue-2.0-custom.vala | 31 ++++++++++++++ src/Geoclue-2.0.metadata | 28 +++++++++++++ src/Makefile.am | 97 +++++++++++++++++++++++++++----------------- src/geoclue-2.0.pc.in | 4 +- 7 files changed, 267 insertions(+), 48 deletions(-) create mode 100644 demo/find-location.vala create mode 100644 src/Geoclue-2.0-custom.vala create mode 100644 src/Geoclue-2.0.metadata diff --git a/configure.ac b/configure.ac index a98d92f..871c023 100644 --- a/configure.ac +++ b/configure.ac @@ -10,6 +10,16 @@ AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_AUX_DIR([build-aux]) +# API versioning +GCLUE_API_VERSION=2.0 +GCLUE_API_MAJOR_VERSION=2 +GCLUE_API_MINOR_VERSION=0 + +AC_SUBST([GCLUE_API_VERSION]) +AC_SUBST([GCLUE_API_MAJOR_VERSION]) +AC_SUBST([GCLUE_API_MINOR_VERSION]) +AC_SUBST([GCLUE_API_VERSION_U],[AS_TR_SH([$GCLUE_API_VERSION])]) + AM_INIT_AUTOMAKE([1.11 dist-xz no-dist-gzip tar-ustar foreign -Wall -Werror]) AM_MAINTAINER_MODE([enable]) @@ -29,7 +39,7 @@ LT_INIT([disable-static]) # Pkg-config PKG_PROG_PKG_CONFIG([0.22]) -# i18 support +# I18n support IT_PROG_INTLTOOL(0.40.0) GETTEXT_PACKAGE=AC_PACKAGE_NAME @@ -39,6 +49,15 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[The name of the gettext d # GObject-introspection support GOBJECT_INTROSPECTION_REQUIRE([0.9.6]) +# Vala bindings +AM_PROG_VALAC +VAPIGEN_CHECK([0.18],,,[no]) + +if test "$enable_vala" != "no"; then + AC_PATH_PROG([VALAC], [valac], []) +fi +AM_CONDITIONAL(HAVE_VALAC, test "x$VALAC" != "x") + # Mallard help YELP_HELP_INIT @@ -101,14 +120,14 @@ else fi AM_CONDITIONAL([BUILD_GEOIP_SERVER], [test "x$build_geoip_server" = "xyes"]) -dnl Strict compiler +# Strict compiler AC_ARG_ENABLE([strict-cc], AS_HELP_STRING([--enable-strict-cc],[Enable strict C compiler])) AS_IF([test "x$enable_strict_cc" = "xyes"], [CFLAGS="$CFLAGS -Wall -Werror"], [CFLAGS="$CFLAGS -w"]) -dnl Debugging +# Debugging AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[enable debugging]),, enable_debug=no) @@ -130,8 +149,8 @@ GOBJECT_INTROSPECTION_CHECK([0.6.2]) AC_CONFIG_FILES([ Makefile src/Makefile - src/geoclue-2.0.pc src/geoip-server/Makefile + src/geoclue-${GCLUE_API_VERSION}.pc po/Makefile.in data/Makefile demo/Makefile @@ -139,12 +158,15 @@ AC_CONFIG_FILES([ AC_OUTPUT -dnl ========================================================================== +# ========================================================================== AC_MSG_NOTICE([ GeoClue $VERSION ================= - prefix: ${prefix} - c compiler: ${CC} ${CFLAGS} + prefix: ${prefix} + c compiler: ${CC} ${CFLAGS} + + Build introspectable bindings: ${found_introspection} + Build Vala bindings: ${enable_vala} ]) diff --git a/demo/Makefile.am b/demo/Makefile.am index acb6b15..83084c5 100644 --- a/demo/Makefile.am +++ b/demo/Makefile.am @@ -4,6 +4,22 @@ where_am_i_SOURCES = where-am-i.c where_am_i_CFLAGS = -I$(top_srcdir)/src \ -I$(top_builddir)/src \ $(GEOCLUE_CFLAGS) \ - -DLOCALEDIR="\"$(datadir)/locale\"" -where_am_i_LDADD = $(top_builddir)/src/libgeoclue-1.0.la \ + -DLOCALEDIR="\"$(localedir)\"" +where_am_i_LDADD = $(top_builddir)/src/libgeoclue-@GCLUE_API_MAJOR_VERSION@.la \ $(GEOCLUE_LIBS) + + +if ENABLE_VAPIGEN +if HAVE_VALAC +noinst_PROGRAMS += find-location +find_location_VALAFLAGS = --vapidir $(top_builddir)/src \ + --pkg geoclue-@GCLUE_API_VERSION@ \ + --pkg gio-2.0 +find_location_CFLAGS = $(GEOCLUE_CFLAGS) \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src +find_location_LDADD = $(top_builddir)/src/libgeoclue-@GCLUE_API_MAJOR_VERSION@.la \ + $(GEOCLUE_LIBS) +find_location_SOURCES = find-location.vala +endif +endif diff --git a/demo/find-location.vala b/demo/find-location.vala new file mode 100644 index 0000000..2e5cb5f --- /dev/null +++ b/demo/find-location.vala @@ -0,0 +1,99 @@ +class FindLocation : Object { + public static MainLoop main_loop = new MainLoop (); + + private GClue.Manager manager; + private GClue.Client client; + private string? client_path; + + public FindLocation () { + client_path = null; + + Environment.set_application_name ("Find Location"); + } + + public void search () { + GClue.ManagerProxy.create_for_bus.begin (GLib.BusType.SYSTEM, + GLib.DBusProxyFlags.NONE, + "org.freedesktop.GeoClue2", + "/org/freedesktop/GeoClue2/Manager", + null, on_manager_proxy); + } + + public void on_manager_proxy (Object? obj, AsyncResult res) { + try { + manager = GClue.ManagerProxy.create_for_bus.end (res); + manager.call_get_client.begin (null, on_client_path); + } catch (Error e) { + error ("Failed to connect to GeoClue2 Manager service: %s", e.message); + } + } + + public void on_client_path (Object? obj, AsyncResult res) { + try { + manager.call_get_client.end (res, out client_path); + } catch (Error e) { + error ("Failed to get client path: %s", e.message); + } + + if (client_path != null) { + stdout.printf ("Client object: %s\n", client_path); + + GClue.ClientProxy.create_for_bus.begin (GLib.BusType.SYSTEM, + GLib.DBusProxyFlags.NONE, + "org.freedesktop.GeoClue2", + client_path, + null, on_client_proxy); + } else + error ("The client path is not set"); + } + + public void on_client_proxy (Object? obj, AsyncResult res) { + try { + client = GClue.ClientProxy.create_for_bus.end (res); + + client.location_updated.connect ((old_path, new_path) => { + GClue.LocationProxy.create_for_bus.begin (GLib.BusType.SYSTEM, + GLib.DBusProxyFlags.NONE, + "org.freedesktop.GeoClue2", + new_path, + null, + on_location_proxy); + }); + + client.call_start.begin (null, (obj, res) => { + try { + client.call_start.end (res); + } catch (Error e) { + error ("Failed to start client: %s", e.message); + } + }); + } catch (Error e) { + error ("Failed to connect to GeoClue2 Client service: %s", e.message); + } + } + + public void on_location_proxy (Object? obj, AsyncResult res) { + try { + GClue.Location location = GClue.LocationProxy.create_for_bus.end (res); + stdout.printf ("Latitude: %f\nLongitude: %f\nAccuracy (in meters): %f\n", + location.latitude, + location.longitude, + location.accuracy); + + string desc = location.description; + if (desc != null) + stdout.printf ("Description: %s\n", desc); + + main_loop.quit (); + } catch (Error e) { + error ("Failed to connect to GeoClue2 Location service: %s", e.message); + } + } + + public static void main () { + var fl = new FindLocation (); + fl.search (); + + main_loop.run (); + } +} diff --git a/src/Geoclue-2.0-custom.vala b/src/Geoclue-2.0-custom.vala new file mode 100644 index 0000000..e48b024 --- /dev/null +++ b/src/Geoclue-2.0-custom.vala @@ -0,0 +1,31 @@ +namespace GClue { + [CCode (cheader_filename = "geoclue.h", type_id = "gclue_manager_proxy_get_type ()")] + public class ManagerProxy : GLib.DBusProxy, GClue.Manager, GLib.AsyncInitable, GLib.DBusInterface, GLib.Initable { + [CCode (cname = "gclue_manager_proxy_new", finish_function = "gclue_manager_proxy_new_finish")] + public static async GClue.Manager @new (GLib.DBusConnection connection, GLib.DBusProxyFlags flags , string? name , string object_path, GLib.Cancellable? cancellable = null) throws GLib.Error; + [CCode (cname = "gclue_manager_proxy_new_for_bus", finish_function = "gclue_manager_proxy_new_for_bus_finish")] + public static async GClue.Manager create_for_bus (GLib.BusType bus_type, GLib.DBusProxyFlags flags, string? name, string object_path, GLib.Cancellable? cancellable = null) throws GLib.Error; + } + + [CCode (cheader_filename = "geoclue.h", type_id = "gclue_location_proxy_get_type ()")] + public class LocationProxy : GLib.DBusProxy, GClue.Location, GLib.AsyncInitable, GLib.DBusInterface, GLib.Initable { + [CCode (cname = "gclue_location_proxy_new", finish_function = "gclue_location_proxy_new_finish")] + public static async GClue.Location @new (GLib.DBusConnection connection, GLib.DBusProxyFlags flags, string? name, string object_path, GLib.Cancellable? cancellable = null) throws GLib.Error; + [CCode (cname = "gclue_location_proxy_new_for_bus", finish_function = "gclue_location_proxy_new_for_bus_finish")] + public static async GClue.Location create_for_bus (GLib.BusType bus_type, GLib.DBusProxyFlags flags, string name, string object_path, GLib.Cancellable? cancellable = null) throws GLib.Error; + } + + [CCode (cheader_filename = "geoclue.h", type_id = "gclue_client_proxy_get_type ()")] + public class ClientProxy : GLib.DBusProxy, GClue.Client, GLib.AsyncInitable, GLib.DBusInterface, GLib.Initable { + [CCode (cname = "gclue_client_proxy_new", finish_function = "gclue_client_proxy_new_finish")] + public static async GClue.Client @new (GLib.DBusConnection connection, GLib.DBusProxyFlags flags, string? name, string object_path, GLib.Cancellable? cancellable = null) throws GLib.IOError; + [CCode (cname = "gclue_client_proxy_new_for_bus", finish_function = "gclue_client_proxy_new_for_bus_finish")] + public static async GClue.Client create_for_bus (GLib.BusType bus_type, GLib.DBusProxyFlags flags, string name, string object_path, GLib.Cancellable? cancellable = null) throws GLib.IOError; + } + + [CCode (cheader_filename = "geoclue.h", type_id = "gclue_manager_get_type ()")] + public interface Manager : GLib.Object { + public async bool call_get_client ([CCode (pos = 0.01)] out string out_client, GLib.Cancellable? cancellable = null) throws GLib.Error; + } + +} diff --git a/src/Geoclue-2.0.metadata b/src/Geoclue-2.0.metadata new file mode 100644 index 0000000..b87bf3f --- /dev/null +++ b/src/Geoclue-2.0.metadata @@ -0,0 +1,28 @@ +* cheader_filename="geoclue.h" +*.*.cancellable#parameter nullable default=null + +// Bug #659886: Async constructors don't work +ManagerProxy + .new skip + .new_finish skip + .new_for_bus skip + .new_for_bus_finish skip + +ClientProxy + .new skip + .new_finish skip + .new_for_bus skip + .new_for_bus_finish skip + +LocationProxy + .new skip + .new_finish skip + .new_for_bus skip + .new_for_bus_finish skip + +// Due to wrong order of arguments +Manager + .call_get_client skip + .call_get_client_finish skip + + diff --git a/src/Makefile.am b/src/Makefile.am index 2caab68..96c0e9c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -40,59 +40,80 @@ geoclue_SOURCES = \ gclue-service-location.c \ $(NULL) -geoclue_CFLAGS = $(GEOCLUE_CFLAGS) \ - -DLOCALEDIR="\"$(datadir)/locale\"" +geoclue_CFLAGS = \ + $(GEOCLUE_CFLAGS) \ + -DLOCALEDIR="\"$(localedir)\"" \ + $(NULL) + geoclue_LDADD = $(GEOCLUE_LIBS) $(LIBS) -lib_LTLIBRARIES = libgeoclue-1.0.la -libgeoclue_1_0_ladir = $(includedir)/geoclue-1.0 +lib_LTLIBRARIES = libgeoclue-@GCLUE_API_MAJOR_VERSION@.la +libgeoclue_@GCLUE_API_MAJOR_VERSION@_ladir = $(includedir)/geoclue-@GCLUE_API_VERSION@ -libgeoclue_1_0_la_HEADERS = geoclue.h geoclue-interface.h -libgeoclue_1_0_la_SOURCES = geoclue-interface.c -libgeoclue_1_0_la_CFLAGS = $(GEOCLUE_CFLAGS) -libgeoclue_1_0_la_LIBADD = $(GEOCLUE_LIBS) +libgeoclue_@GCLUE_API_MAJOR_VERSION@_la_HEADERS = geoclue.h geoclue-interface.h +libgeoclue_@GCLUE_API_MAJOR_VERSION@_la_SOURCES = geoclue-interface.c +libgeoclue_@GCLUE_API_MAJOR_VERSION@_la_CFLAGS = $(GEOCLUE_CFLAGS) +libgeoclue_@GCLUE_API_MAJOR_VERSION@_la_LIBADD = $(GEOCLUE_LIBS) CLEANFILES = $(BUILT_SOURCES) pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = geoclue-2.0.pc +pkgconfig_DATA = geoclue-@GCLUE_API_VERSION@.pc if HAVE_INTROSPECTION +-include $(INTROSPECTION_MAKEFILE) +INTROSPECTION_GIRS = +INTROSPECTION_SCANNER_ARGS = --warn-all --add-include-path=$(srcdir) +INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir) + +introspection_sources = $(libgeoclue_@GCLUE_API_MAJOR_VERSION@_la_SOURCES) $(libgeoclue_@GCLUE_API_MAJOR_VERSION@_la_HEADERS) + +Geoclue-@GCLUE_API_VERSION@.gir: libgeoclue-@GCLUE_API_MAJOR_VERSION@.la +Geoclue_@GCLUE_API_VERSION_U@_gir_INCLUDES = Gio-2.0 +Geoclue_@GCLUE_API_VERSION_U@_gir_FILES = $(introspection_sources) +Geoclue_@GCLUE_API_VERSION_U@_gir_EXPORT_PACKAGES = geoclue-@GCLUE_API_VERSION@ +Geoclue_@GCLUE_API_VERSION_U@_gir_NAMESPACE = Geoclue +Geoclue_@GCLUE_API_VERSION_U@_gir_PACKAGES = glib-2.0 gobject-2.0 gio-2.0 +Geoclue_@GCLUE_API_VERSION_U@_gir_LIBS = libgeoclue-@GCLUE_API_MAJOR_VERSION@.la +Geoclue_@GCLUE_API_VERSION_U@_gir_SCANNERFLAGS = \ + --identifier-prefix=GClue \ + --c-include='geoclue.h' \ + --symbol-prefix=gclue \ + $(NULL) + +INTROSPECTION_GIRS += Geoclue-@GCLUE_API_VERSION@.gir + girdir = $(datadir)/gir-1.0 -gir_DATA = Geoclue-1.0.gir +gir_DATA = Geoclue-@GCLUE_API_VERSION@.gir typelibsdir = $(libdir)/girepository-1.0 -typelibs_DATA = Geoclue-1.0.typelib - -Geoclue-1.0.gir: $(libgeoclue_1_0_la_SOURCES) $(libgeoclue_1_0_la_HEADERS) - $(INTROSPECTION_SCANNER) -v \ - --warn-all \ - --namespace Geoclue \ - --identifier-prefix=GClue \ - --symbol-prefix=gclue \ - --nsversion=1.0 \ - --include=Gio-2.0 \ - --library=geoclue-1.0 \ - --output $@ \ - --pkg=glib-2.0 \ - --pkg=gobject-2.0 \ - --pkg=gio-2.0 \ - --pkg-export=geoclue-1.0 \ - --libtool=$(top_builddir)/libtool \ - --c-include='geoclue.h' \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - $^ \ - $(NULL) - -Geoclue-1.0.gir: libgeoclue-1.0.la $(INTROSPECTION_SCANNER) Makefile.am -Geoclue-1.0.typelib: Geoclue-1.0.gir $(INTROSPECTION_COMPILER) - $(INTROSPECTION_COMPILER) $< -o $@ +typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib) CLEANFILES += $(gir_DATA) $(typelibs_DATA) -EXTRA_DIST = geoclue-interface.xml \ - test-data/freegeoip-results.json + +if ENABLE_VAPIGEN +-include $(VAPIGEN_MAKEFILE) + +geoclue-@GCLUE_API_VERSION@.vapi: Geoclue-@GCLUE_API_VERSION@.gir + +VAPIGEN_VAPIS = geoclue-@GCLUE_API_VERSION@.vapi + +geoclue_@GCLUE_API_VERSION_U@_vapi_DEPS = gio-2.0 cairo +geoclue_@GCLUE_API_VERSION_U@_vapi_METADATADIRS = $(srcdir) +geoclue_@GCLUE_API_VERSION_U@_vapi_FILES = Geoclue-@GCLUE_API_VERSION@.gir Geoclue-@GCLUE_API_VERSION@-custom.vala + +vapidir = $(datadir)/vala/vapi +vapi_DATA = $(VAPIGEN_VAPIS) + +CLEANFILES += $(VAPIGEN_VAPIS) + +endif # ENABLE_VAPIGEN endif # HAVE_INTROSPECTION +EXTRA_DIST = geoclue-interface.xml \ + test-data/freegeoip-results.json \ + Geoclue-@GCLUE_API_VERSION@-custom.vala \ + Geoclue-@GCLUE_API_VERSION@.metadata + -include $(top_srcdir)/git.mk diff --git a/src/geoclue-2.0.pc.in b/src/geoclue-2.0.pc.in index 5b8bd5f..919c657 100644 --- a/src/geoclue-2.0.pc.in +++ b/src/geoclue-2.0.pc.in @@ -6,4 +6,6 @@ includedir=@includedir@ Name: Geoclue Description: The Geoinformation Service Version: @VERSION@ -Requires: gio-unix-2.0 libsoup json-glib-1.0 +Requires: gio-unix-2.0 libsoup-2.4 json-glib-1.0 +Libs: -L${libdir} -lgeoclue-@GCLUE_API_MAJOR_VERSION@ +Cflags: -I${includedir}/geoclue-@GCLUE_API_VERSION@ -- 1.8.1.5