Commit 10159143 authored by Ryan Lortie's avatar Ryan Lortie

clock applet: port to GDBus

no more dbus-glib in gnome-panel
parent b8449144
......@@ -17,8 +17,6 @@
#include <gio/gio.h>
#ifdef HAVE_NETWORK_MANAGER
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <NetworkManager/NetworkManager.h>
#endif
......@@ -502,9 +500,14 @@ typedef struct {
} MakeCurrentData;
static void
make_current_cb (gpointer data, GError *error)
make_current_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
MakeCurrentData *mcdata = data;
MakeCurrentData *mcdata = user_data;
GError *error = NULL;
set_system_timezone_finish (result, &error);
if (error == NULL) {
if (current_location)
......@@ -521,13 +524,7 @@ make_current_cb (gpointer data, GError *error)
mcdata->callback (mcdata->data, error);
else
g_error_free (error);
}
static void
free_make_current_data (gpointer data)
{
MakeCurrentData *mcdata = data;
if (mcdata->destroy)
mcdata->destroy (mcdata->data);
......@@ -576,9 +573,8 @@ clock_location_make_current (ClockLocation *loc,
filename = g_build_filename (SYSTEM_ZONEINFODIR, priv->timezone, NULL);
set_system_timezone_async (filename,
(GFunc)make_current_cb,
mcdata,
free_make_current_data);
make_current_cb,
mcdata);
g_free (filename);
}
......@@ -722,94 +718,45 @@ update_weather_infos (void)
}
static void
state_notify (DBusPendingCall *pending, gpointer data)
network_monitor_signal (GDBusProxy *proxy,
const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
DBusMessage *msg = dbus_pending_call_steal_reply (pending);
if (!msg)
return;
if (g_str_equal (signal_name, "StateChanged")) {
if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(u)"))) {
guint32 state;
if (dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_RETURN) {
dbus_uint32_t result;
g_variant_get (parameters, "(u)", &state);
if (dbus_message_get_args (msg, NULL,
DBUS_TYPE_UINT32, &result,
DBUS_TYPE_INVALID)) {
if (result == NM_STATE_CONNECTED) {
if (state == NM_STATE_CONNECTED) {
update_weather_infos ();
}
}
}
dbus_message_unref (msg);
}
static void
check_network (DBusConnection *connection)
{
DBusMessage *message;
DBusPendingCall *reply;
message = dbus_message_new_method_call (NM_DBUS_SERVICE,
NM_DBUS_PATH,
NM_DBUS_INTERFACE,
"state");
if (dbus_connection_send_with_reply (connection, message, &reply, -1)) {
dbus_pending_call_set_notify (reply, state_notify, NULL, NULL);
dbus_pending_call_unref (reply);
}
dbus_message_unref (message);
}
static DBusHandlerResult
filter_func (DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
if (dbus_message_is_signal (message,
NM_DBUS_INTERFACE,
"StateChanged")) {
check_network (connection);
return DBUS_HANDLER_RESULT_HANDLED;
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
static void
setup_network_monitor (void)
{
GError *error;
DBusError derror;
static DBusGConnection *bus = NULL;
DBusConnection *dbus;
GError *error = NULL;
GDBusProxy *proxy;
if (bus == NULL) {
error = NULL;
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
g_warning ("Couldn't connect to system bus: %s",
error->message);
g_error_free (error);
proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL, NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE,
NULL, &error);
return;
}
if (proxy == NULL) {
g_warning ("Couldn't create NetworkManager proxy: %s",
error->message);
g_error_free (error);
return;
}
dbus_error_init (&derror);
dbus = dbus_g_connection_get_connection (bus);
dbus_connection_add_filter (dbus, filter_func, NULL, NULL);
dbus_bus_add_match (dbus,
"type='signal',"
"interface='" NM_DBUS_INTERFACE "'",
&derror);
if (dbus_error_is_set (&derror)) {
g_warning ("Couldn't register signal handler: %s: %s",
derror.name, derror.message);
dbus_error_free (&derror);
}
}
g_signal_connect (proxy, "g-signal", G_CALLBACK (network_monitor_signal), NULL);
/* leak the proxy */
}
#endif
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 David Zeuthen <david@fubar.dk>
/*
* Copyright (C) 2011 Codethink Limited
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -16,12 +15,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gio/gio.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
......@@ -29,263 +30,154 @@
#include <string.h>
#include <sys/wait.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include "set-timezone.h"
#define CACHE_VALIDITY_SEC 2
static DBusGConnection *
get_system_bus (void)
{
GError *error;
static DBusGConnection *bus = NULL;
if (bus == NULL) {
error = NULL;
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
if (bus == NULL) {
g_warning ("Couldn't connect to system bus: %s",
error->message);
g_error_free (error);
}
}
#define MECHANISM_BUS_NAME "org.gnome.SettingsDaemon.DateTimeMechanism"
#define MECHANISM_OBJECT_PATH "/"
#define MECHANISM_INTERFACE "org.gnome.SettingsDaemon.DateTimeMechanism"
return bus;
}
#define CACHE_VALIDITY_SEC 2
typedef struct {
gboolean in_progress;
gint value;
guint64 stamp;
} Cache;
typedef void (*CanDoFunc) (gint value);
static Cache can_set_time_cache;
static Cache can_set_timezone_cache;
static void
notify_can_do (DBusGProxy *proxy,
DBusGProxyCall *call,
void *user_data)
static GDBusConnection *
get_system_bus (GError **error)
{
CanDoFunc callback = user_data;
GError *error = NULL;
gint value;
if (dbus_g_proxy_end_call (proxy, call,
&error,
G_TYPE_INT, &value,
G_TYPE_INVALID)) {
callback (value);
}
static GDBusConnection *system;
static gboolean initialised;
static GError *saved_error;
if (!initialised)
{
system = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &saved_error);
initialised = TRUE;
}
if (system == NULL && error)
*error = g_error_copy (saved_error);
return system;
}
static void
refresh_can_do (const gchar *action, CanDoFunc callback)
can_set_call_finished (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
DBusGConnection *bus;
DBusGProxy *proxy;
bus = get_system_bus ();
if (bus == NULL)
return;
proxy = dbus_g_proxy_new_for_name (bus,
"org.gnome.SettingsDaemon.DateTimeMechanism",
"/",
"org.gnome.SettingsDaemon.DateTimeMechanism");
dbus_g_proxy_begin_call_with_timeout (proxy,
action,
notify_can_do,
callback, NULL,
INT_MAX,
G_TYPE_INVALID);
}
Cache *cache = user_data;
GVariant *reply;
static gint settimezone_cache = 0;
static time_t settimezone_stamp = 0;
reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source),
result, NULL);
static void
update_can_settimezone (gint res)
{
settimezone_cache = res;
time (&settimezone_stamp);
if (reply != NULL)
{
g_variant_get (reply, "(u)", cache->value);
g_variant_unref (reply);
}
cache->stamp = g_get_monotonic_time ();
cache->in_progress = FALSE;
}
gint
can_set_system_timezone (void)
static int
can_set (Cache *cache, const gchar *method_name)
{
time_t now;
time (&now);
if (ABS (now - settimezone_stamp) > CACHE_VALIDITY_SEC) {
refresh_can_do ("CanSetTimezone", update_can_settimezone);
settimezone_stamp = now;
}
guint64 now = g_get_monotonic_time ();
if (now - cache->stamp > (CACHE_VALIDITY_SEC * 1000000))
{
if (!cache->in_progress)
{
GDBusConnection *system_bus = get_system_bus (NULL);
if (system_bus != NULL)
g_dbus_connection_call (system_bus, MECHANISM_BUS_NAME,
MECHANISM_OBJECT_PATH, MECHANISM_INTERFACE,
method_name, NULL, G_VARIANT_TYPE ("(i)"),
G_DBUS_CALL_FLAGS_NONE, -1, NULL,
can_set_call_finished, cache);
/* Even if the system bus was NULL, we want to set this in
* order to effectively wedge ourselves from ever trying
* again.
*/
cache->in_progress = TRUE;
}
}
return settimezone_cache;
return cache->value;
}
static gint settime_cache = 0;
static time_t settime_stamp = 0;
static void
update_can_settime (gint res)
gint
can_set_system_timezone (void)
{
settime_cache = res;
time (&settime_stamp);
return can_set (&can_set_timezone_cache, "CanSetTimeZone");
}
gint
can_set_system_time (void)
{
time_t now;
time (&now);
if (ABS (now - settime_stamp) > CACHE_VALIDITY_SEC) {
refresh_can_do ("CanSetTime", update_can_settime);
settime_stamp = now;
}
return settime_cache;
return can_set (&can_set_time_cache, "CanSetTime");
}
typedef struct {
gint ref_count;
gchar *call;
gint64 time;
gchar *filename;
GFunc callback;
gpointer data;
GDestroyNotify notify;
} SetTimeCallbackData;
static void
free_data (gpointer d)
gboolean
set_system_timezone_finish (GAsyncResult *result,
GError **error)
{
SetTimeCallbackData *data = d;
data->ref_count--;
if (data->ref_count == 0) {
if (data->notify)
data->notify (data->data);
g_free (data->filename);
g_free (data);
}
}
GDBusConnection *system_bus = get_system_bus (NULL);
GVariant *reply;
static void
set_time_notify (DBusGProxy *proxy,
DBusGProxyCall *call,
void *user_data)
{
SetTimeCallbackData *data = user_data;
GError *error = NULL;
if (dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) {
if (data->callback)
data->callback (data->data, NULL);
}
else {
if (error->domain == DBUS_GERROR &&
error->code == DBUS_GERROR_NO_REPLY) {
/* these errors happen because dbus doesn't
* use monotonic clocks
*/
g_warning ("ignoring no-reply error when setting time");
g_error_free (error);
if (data->callback)
data->callback (data->data, NULL);
}
else {
if (data->callback)
data->callback (data->data, error);
else
g_error_free (error);
}
}
}
/* detect if we set an error due to being unable to get the system bus */
if (g_simple_async_result_is_valid (result, NULL, set_system_timezone_async))
{
g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
error);
return FALSE;
}
static void
set_time_async (SetTimeCallbackData *data)
{
DBusGConnection *bus;
DBusGProxy *proxy;
bus = get_system_bus ();
if (bus == NULL)
return;
proxy = dbus_g_proxy_new_for_name (bus,
"org.gnome.SettingsDaemon.DateTimeMechanism",
"/",
"org.gnome.SettingsDaemon.DateTimeMechanism");
data->ref_count++;
if (strcmp (data->call, "SetTime") == 0)
dbus_g_proxy_begin_call_with_timeout (proxy,
"SetTime",
set_time_notify,
data, free_data,
INT_MAX,
/* parameters: */
G_TYPE_INT64, data->time,
G_TYPE_INVALID,
/* return values: */
G_TYPE_INVALID);
else
dbus_g_proxy_begin_call_with_timeout (proxy,
"SetTimezone",
set_time_notify,
data, free_data,
INT_MAX,
/* parameters: */
G_TYPE_STRING, data->filename,
G_TYPE_INVALID,
/* return values: */
G_TYPE_INVALID);
}
g_assert (system_bus != NULL);
void
set_system_time_async (gint64 time,
GFunc callback,
gpointer d,
GDestroyNotify notify)
{
SetTimeCallbackData *data;
if (time == -1)
return;
data = g_new0 (SetTimeCallbackData, 1);
data->ref_count = 1;
data->call = "SetTime";
data->time = time;
data->filename = NULL;
data->callback = callback;
data->data = d;
data->notify = notify;
set_time_async (data);
free_data (data);
reply = g_dbus_connection_call_finish (system_bus, result, error);
if (reply != NULL)
g_variant_unref (reply);
return reply != NULL;
}
void
set_system_timezone_async (const gchar *filename,
GFunc callback,
gpointer d,
GDestroyNotify notify)
set_system_timezone_async (const gchar *filename,
GAsyncReadyCallback callback,
gpointer user_data)
{
SetTimeCallbackData *data;
if (filename == NULL)
return;
data = g_new0 (SetTimeCallbackData, 1);
data->ref_count = 1;
data->call = "SetTimezone";
data->time = -1;
data->filename = g_strdup (filename);
data->callback = callback;
data->data = d;
data->notify = notify;
set_time_async (data);
free_data (data);
GDBusConnection *system_bus;
GError *error = NULL;
system_bus = get_system_bus (&error);
if (system_bus == NULL)
{
GSimpleAsyncResult *simple;
simple = g_simple_async_result_new (NULL, callback, user_data,
set_system_timezone_async);
g_simple_async_result_set_from_error (simple, error);
g_simple_async_result_complete_in_idle (simple);
g_object_unref (simple);
g_error_free (error);
}
g_dbus_connection_call (system_bus, MECHANISM_BUS_NAME,
MECHANISM_OBJECT_PATH, MECHANISM_INTERFACE,
"SetTimeZone", g_variant_new ("(s)", filename),
NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL,
callback, user_data);
}
......@@ -27,14 +27,11 @@ gint can_set_system_timezone (void);
gint can_set_system_time (void);
void set_system_time_async (gint64 time,
GFunc callback,
gpointer data,
GDestroyNotify notify);
void set_system_timezone_async (const gchar *filename,
GAsyncReadyCallback callback,
gpointer user_data);
void set_system_timezone_async (const gchar *filename,
GFunc callback,
gpointer data,
GDestroyNotify notify);
gboolean set_system_timezone_finish (GAsyncResult *result,
GError **error);
#endif
......@@ -137,7 +137,7 @@ PKG_CHECK_MODULES(TZ, gio-2.0 >= $GLIB_REQUIRED)
AC_SUBST(TZ_CFLAGS)
AC_SUBST(TZ_LIBS)
PKG_CHECK_MODULES(CLOCK, pango >= $PANGO_REQUIRED gtk+-3.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED gio-2.0 >= $GLIB_REQUIRED $LIBECAL_REQUIREMENT librsvg-2.0 dbus-glib-1 gweather-3.0 >= $GWEATHER_REQUIRED gnome-desktop-3.0 >= $LIBGNOME_DESKTOP_REQUIRED)
PKG_CHECK_MODULES(CLOCK, pango >= $PANGO_REQUIRED gtk+-3.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED gio-2.0 >= $GLIB_REQUIRED $LIBECAL_REQUIREMENT librsvg-2.0 gweather-3.0 >= $GWEATHER_REQUIRED gnome-desktop-3.0 >= $LIBGNOME_DESKTOP_REQUIRED)
AC_SUBST(CLOCK_CFLAGS)
AC_SUBST(CLOCK_LIBS)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment