Merge branch 'geoclue2-provider'

Add GeoClue2 location provider
This commit is contained in:
Jon Lund Steffensen
2014-12-15 01:53:59 -05:00
8 changed files with 377 additions and 4 deletions
+2 -1
View File
@@ -8,5 +8,6 @@ install:
- sudo apt-get install -qq libxcb1-dev libxcb-randr0-dev
- sudo apt-get install -qq libx11-dev libxxf86vm-dev
- sudo apt-get install -qq libgeoclue-dev
- sudo apt-get install -qq libglib2.0-dev
- sudo apt-get install -qq python3
script: ./bootstrap && ./configure --enable-drm --enable-vidmode --enable-randr --enable-geoclue --enable-gui && make -j2 distcheck
script: ./bootstrap && ./configure --enable-drm --enable-vidmode --enable-randr --enable-geoclue --enable-geoclue2 --enable-gui && make -j2 distcheck
+26
View File
@@ -32,6 +32,7 @@ PKG_CHECK_MODULES([XCB_RANDR], [xcb-randr],
PKG_CHECK_MODULES([GLIB], [glib-2.0 gobject-2.0], [have_glib=yes], [have_glib=no])
PKG_CHECK_MODULES([GEOCLUE], [geoclue], [have_geoclue=yes], [have_geoclue=no])
PKG_CHECK_MODULES([GEOCLUE2], [glib-2.0 gio-2.0 >= 2.26], [have_geoclue2=yes], [have_geoclue2=no])
AC_CHECK_HEADER([windows.h], [have_windows_h=yes], [have_windows_h=no])
@@ -159,6 +160,30 @@ AS_IF([test "x$enable_geoclue" != xno], [
])
AM_CONDITIONAL([ENABLE_GEOCLUE], [test "x$enable_geoclue" = xyes])
# Check Geoclue2 location provider
AC_MSG_CHECKING([whether to enable Geoclue2 location provider])
AC_ARG_ENABLE([geoclue2], [AC_HELP_STRING([--enable-geoclue2],
[enable Geoclue2 location provider])],
[enable_geoclue2=$enableval],[enable_geoclue2=maybe])
AS_IF([test "x$enable_geoclue2" != xno], [
AS_IF([test "x$have_geoclue2" = xyes], [
AC_DEFINE([ENABLE_GEOCLUE2], 1,
[Define to 1 to enable Geoclue2 location provider])
AC_MSG_RESULT([yes])
enable_geoclue2=yes
], [
AC_MSG_RESULT([missing dependencies])
AS_IF([test "x$enable_geoclue2" = xyes], [
AC_MSG_ERROR([missing dependencies for Geoclue2 location provider])
])
enable_geoclue2=no
])
], [
AC_MSG_RESULT([no])
enable_geoclue2=no
])
AM_CONDITIONAL([ENABLE_GEOCLUE2], [test "x$enable_geoclue2" = xyes])
# Check for GUI status icon
AC_MSG_CHECKING([whether to enable GUI status icon])
@@ -249,6 +274,7 @@ echo "
Location providers:
Geoclue: ${enable_geoclue}
Geoclue2: ${enable_geoclue2}
GUI: ${enable_gui}
Ubuntu icons: ${enable_ubuntu}
+2 -2
View File
@@ -10,7 +10,7 @@ BuildRequires: gettext-devel
BuildRequires: libX11-devel
BuildRequires: libXxf86vm-devel
BuildRequires: libxcb-devel
BuildRequires: geoclue-devel
BuildRequires: glib2-devel
BuildRequires: systemd
%description
@@ -44,7 +44,7 @@ temperature adjustment program.
%setup -q
%build
%configure --enable-gui --enable-geoclue --enable-randr --enable-vidmode --with-systemduserunitdir=%{_userunitdir}
%configure --enable-gui --disable-geoclue --enable-geoclue2 --enable-randr --enable-vidmode --with-systemduserunitdir=%{_userunitdir}
make %{?_smp_mflags} V=1
%install
+1
View File
@@ -13,6 +13,7 @@ src/gamma-w32gdi.c
src/gamma-dummy.c
src/location-geoclue.c
src/location-geoclue2.c
src/location-manual.c
src/redshift-gtk/statusicon.py
+8
View File
@@ -66,3 +66,11 @@ redshift_LDADD += \
$(GEOCLUE_LIBS) $(GEOCLUE_CFLAGS)
$(GLIB_LIBS) $(GLIB_CFLAGS)
endif
if ENABLE_GEOCLUE2
redshift_SOURCES += location-geoclue2.c location-geoclue2.h
AM_CFLAGS += \
$(GEOCLUE2_CFLAGS)
redshift_LDADD += \
$(GEOCLUE2_LIBS) $(GEOCLUE2_CFLAGS)
endif
+281
View File
@@ -0,0 +1,281 @@
/* location-geoclue2.c -- GeoClue2 location provider source
This file is part of Redshift.
Redshift is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Redshift is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Redshift. If not, see <http://www.gnu.org/licenses/>.
Copyright (c) 2014 Jon Lund Steffensen <jonlst@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <glib/gprintf.h>
#include <gio/gio.h>
#include "location-geoclue2.h"
#ifdef ENABLE_NLS
# include <libintl.h>
# define _(s) gettext(s)
#else
# define _(s) s
#endif
typedef struct {
GMainLoop *loop;
int available;
float latitude;
float longitude;
} get_location_data_t;
int
location_geoclue2_init(void *state)
{
#if !GLIB_CHECK_VERSION(2, 35, 0)
g_type_init();
#endif
return 0;
}
int
location_geoclue2_start(void *state)
{
return 0;
}
void
location_geoclue2_free(void *state)
{
}
void
location_geoclue2_print_help(FILE *f)
{
fputs(_("Use the location as discovered by a GeoClue2 provider.\n"), f);
fputs("\n", f);
fputs(_("NOTE: currently redshift doesn't recheck GeoClue2 once started,\n"
"which means it has to be restarted to take notice after travel.\n"),
f);
fputs("\n", f);
}
int
location_geoclue2_set_option(void *state,
const char *key, const char *value)
{
fprintf(stderr, _("Unknown method parameter: `%s'.\n"), key);
return -1;
}
/* Handle position change callbacks */
static void
geoclue_client_signal_cb(GDBusProxy *client, gchar *sender_name,
gchar *signal_name, GVariant *parameters,
gpointer *user_data)
{
get_location_data_t *data = (get_location_data_t *)user_data;
/* Only handle LocationUpdated signals */
if (g_strcmp0(signal_name, "LocationUpdated") != 0) {
return;
}
/* Obtain location path */
const gchar *location_path;
g_variant_get_child(parameters, 1, "&o", &location_path);
/* Obtain location */
GError *error = NULL;
GDBusProxy *location =
g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.freedesktop.GeoClue2",
location_path,
"org.freedesktop.GeoClue2.Location",
NULL, &error);
if (location == NULL) {
g_printerr(_("Unable to obtain location: %s.\n"),
error->message);
g_error_free(error);
return;
}
/* Read location properties */
GVariant *lat_v = g_dbus_proxy_get_cached_property(location,
"Latitude");
data->latitude = g_variant_get_double(lat_v);
GVariant *lon_v = g_dbus_proxy_get_cached_property(location,
"Longitude");
data->longitude = g_variant_get_double(lon_v);
data->available = 1;
/* Return from main loop */
g_main_loop_quit(data->loop);
}
/* Callback when GeoClue name appears on the bus */
static void
on_name_appeared(GDBusConnection *conn, const gchar *name,
const gchar *name_owner, gpointer user_data)
{
get_location_data_t *data = (get_location_data_t *)user_data;
/* Obtain GeoClue Manager */
GError *error = NULL;
GDBusProxy *geoclue_manager =
g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.freedesktop.GeoClue2",
"/org/freedesktop/GeoClue2/Manager",
"org.freedesktop.GeoClue2.Manager",
NULL, &error);
if (geoclue_manager == NULL) {
g_printerr(_("Unable to obtain GeoClue Manager: %s.\n"),
error->message);
g_error_free(error);
return;
}
/* Obtain GeoClue Client path */
error = NULL;
GVariant *client_path_v =
g_dbus_proxy_call_sync(geoclue_manager,
"GetClient",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (client_path_v == NULL) {
g_printerr(_("Unable to obtain GeoClue client path: %s.\n"),
error->message);
g_error_free(error);
g_object_unref(geoclue_manager);
return;
}
const gchar *client_path;
g_variant_get(client_path_v, "(&o)", &client_path);
/* Obtain GeoClue client */
error = NULL;
GDBusProxy *geoclue_client =
g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
"org.freedesktop.GeoClue2",
client_path,
"org.freedesktop.GeoClue2.Client",
NULL, &error);
if (geoclue_client == NULL) {
g_printerr(_("Unable to obtain GeoClue Client: %s.\n"),
error->message);
g_error_free(error);
g_variant_unref(client_path_v);
g_object_unref(geoclue_manager);
return;
}
g_variant_unref(client_path_v);
/* Set distance threshold */
error = NULL;
GVariant *ret_v =
g_dbus_proxy_call_sync(geoclue_client,
"org.freedesktop.DBus.Properties.Set",
g_variant_new("(ssv)",
"org.freedesktop.GeoClue2.Client",
"DistanceThreshold",
g_variant_new("u", 50000)),
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (ret_v == NULL) {
g_printerr(_("Unable to set distance threshold: %s.\n"),
error->message);
g_error_free(error);
g_object_unref(geoclue_client);
g_object_unref(geoclue_manager);
return;
}
g_variant_unref(ret_v);
/* Attach signal callback to client */
g_signal_connect(geoclue_client, "g-signal",
G_CALLBACK(geoclue_client_signal_cb),
data);
/* Start GeoClue client */
error = NULL;
ret_v = g_dbus_proxy_call_sync(geoclue_client,
"Start",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (ret_v == NULL) {
g_printerr(_("Unable to start GeoClue client: %s.\n"),
error->message);
g_error_free(error);
g_object_unref(geoclue_client);
g_object_unref(geoclue_manager);
return;
}
g_variant_unref(ret_v);
}
/* Callback when GeoClue disappears from the bus */
static void
on_name_vanished(GDBusConnection *connection, const gchar *name,
gpointer user_data)
{
get_location_data_t *data = (get_location_data_t *)user_data;
g_fprintf(stderr, _("Unable to connect to GeoClue.\n"));
g_main_loop_quit(data->loop);
}
int
location_geoclue2_get_location(void *state,
float *lat, float *lon)
{
get_location_data_t data;
data.available = 0;
guint watcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
"org.freedesktop.GeoClue2",
G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
on_name_appeared,
on_name_vanished,
&data, NULL);
data.loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(data.loop);
g_bus_unwatch_name(watcher_id);
if (!data.available) return -1;
*lat = data.latitude;
*lon = data.longitude;
return 0;
}
+38
View File
@@ -0,0 +1,38 @@
/* location-geoclue2.h -- Geoclue2 location provider header
This file is part of Redshift.
Redshift is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Redshift is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Redshift. If not, see <http://www.gnu.org/licenses/>.
Copyright (c) 2014 Jon Lund Steffensen <jonlst@gmail.com>
*/
#ifndef REDSHIFT_LOCATION_GEOCLUE2_H
#define REDSHIFT_LOCATION_GEOCLUE2_H
#include <stdio.h>
int location_geoclue2_init(void *state);
int location_geoclue2_start(void *state);
void location_geoclue2_free(void *state);
void location_geoclue2_print_help(FILE *f);
int location_geoclue2_set_option(void *state,
const char *key, const char *value);
int location_geoclue2_get_location(void *state,
float *lat, float *lon);
#endif /* ! REDSHIFT_LOCATION_GEOCLUE2_H */
+19 -1
View File
@@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with Redshift. If not, see <http://www.gnu.org/licenses/>.
Copyright (c) 2013 Jon Lund Steffensen <jonlst@gmail.com>
Copyright (c) 2009-2014 Jon Lund Steffensen <jonlst@gmail.com>
*/
#ifdef HAVE_CONFIG_H
@@ -76,6 +76,10 @@
# include "location-geoclue.h"
#endif
#ifdef ENABLE_GEOCLUE2
# include "location-geoclue2.h"
#endif
/* Union of state data for gamma adjustment methods */
typedef union {
@@ -182,6 +186,20 @@ static const location_provider_t location_providers[] = {
(location_provider_get_location_func *)
location_geoclue_get_location
},
#endif
#ifdef ENABLE_GEOCLUE2
{
"geoclue2",
(location_provider_init_func *)location_geoclue2_init,
(location_provider_start_func *)location_geoclue2_start,
(location_provider_free_func *)location_geoclue2_free,
(location_provider_print_help_func *)
location_geoclue2_print_help,
(location_provider_set_option_func *)
location_geoclue2_set_option,
(location_provider_get_location_func *)
location_geoclue2_get_location
},
#endif
{
"manual",