Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Send D-Bus signal on configuration value change
When a MCE configuration value changes, a dbus signal with
property name and property value variant is sent.

[mce] A D-Bus signal is sent on configuration value change
  • Loading branch information
spiiroin committed Sep 4, 2013
1 parent e8ab782 commit 3ea0b2f
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 13 deletions.
49 changes: 49 additions & 0 deletions builtin-gconf.c
Expand Up @@ -18,6 +18,9 @@
* - value types can't be changed
* ------------------------------------------------------------------------- */

/** Flag for: do not include real gconf headers */
#define BUILTIN_GCONF

#include <glib.h>

#include <stdio.h>
Expand Down Expand Up @@ -169,6 +172,8 @@ typedef struct GConfClientNotify

} GConfClientNotify;

#include "mce-dbus.h"

/* ========================================================================= *
*
* FUNCTION PROTOTYPES
Expand Down Expand Up @@ -1931,6 +1936,46 @@ gconf_client_notify_new(const gchar *namespace_section,
return self;
}

/** Broadcast value change on D-Bus */
static
void
gconf_signal_value_change(GConfEntry *entry)
{
static GHashTable *sent = 0;

const char *prev = 0;
char *curr = 0;

/* HACK: The builtin-gconf does not care if the value actually changes
* or not. To avoid sending "no change" signals we keep track
* of the string representation of the last change that was
* broadcast ... */
if( !sent )
{
sent = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
}

if( !(curr = gconf_value_str(entry->value)) )
{
goto EXIT;
}

prev = g_hash_table_lookup(sent, entry->key);

if( prev && !strcmp(prev, curr) )
{
goto EXIT;
}

g_hash_table_insert(sent, strdup(entry->key), curr), curr = 0;
mce_dbus_send_config_notification(entry);

EXIT:
free(curr);
return;
}


/** Dispatch change notifications via installed callbacks */
static
void
Expand All @@ -1942,6 +1987,7 @@ gconf_client_notify_change(GConfClient *client,

if( entry )
{
/* handle internal notifications */
for( GSList *item = client->notify_list; item; item = item->next )
{
GConfClientNotify *notify = item->data;
Expand All @@ -1957,6 +2003,9 @@ gconf_client_notify_change(GConfClient *client,
notify->func(client, notify->id, entry, notify->user_data);
}
}

/* broadcast change also on dbus */
gconf_signal_value_change(entry);
}

g_clear_error(&err);
Expand Down
90 changes: 77 additions & 13 deletions mce-dbus.c
Expand Up @@ -768,6 +768,13 @@ static gboolean append_gconf_value_to_dbus_message(DBusMessage *reply, GConfValu
return FALSE;
}

/* FIXME: Once the constants are in mce-dev these can be removed */
#ifndef MCE_CONFIG_GET
# define MCE_CONFIG_GET "get_config"
# define MCE_CONFIG_SET "set_config"
# define MCE_CONFIG_CHANGE_SIG "config_change_ind"
#endif

/**
* D-Bus callback for the config get method call
*
Expand All @@ -783,15 +790,24 @@ static gboolean config_get_dbus_cb(DBusMessage *const msg)
GError *err = NULL;
GConfValue *conf = 0;

DBusError error = DBUS_ERROR_INIT;
DBusMessageIter body;

mce_log(LL_DEBUG, "Received configuration query request");

if( !dbus_message_get_args(msg, &error,
DBUS_TYPE_OBJECT_PATH, &key,
DBUS_TYPE_INVALID) ) {
mce_log(LL_ERR, "%s: %s", error.name, error.message);
reply = dbus_message_new_error(msg, error.name, error.message);
dbus_message_iter_init(msg, &body);

/* HACK: The key used to be object path, not string.
* Allow clients to use either one. */
switch( dbus_message_iter_get_arg_type(&body) ) {
case DBUS_TYPE_OBJECT_PATH:
case DBUS_TYPE_STRING:
dbus_message_iter_get_basic(&body, &key);
dbus_message_iter_next(&body);
break;

default:
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS,
"expected string/object path");
goto EXIT;
}

Expand Down Expand Up @@ -829,11 +845,52 @@ static gboolean config_get_dbus_cb(DBusMessage *const msg)
gconf_value_free(conf);

g_clear_error(&err);
dbus_error_free(&error);

return status;
}

/** Send configuration changed notification signal
*
* @param entry changed setting
*/
void mce_dbus_send_config_notification(GConfEntry *entry)
{
const char *key = 0;
GConfValue *val = 0;
DBusMessage *sig = 0;

if( !entry )
goto EXIT;

if( !(key = gconf_entry_get_key(entry)) )
goto EXIT;

if( !(val = gconf_entry_get_value(entry)) )
goto EXIT;

mce_log(LL_DEBUG, "%s: changed", key);

sig = dbus_message_new_signal(MCE_SIGNAL_PATH,
MCE_SIGNAL_IF,
MCE_CONFIG_CHANGE_SIG);

if( !sig ) goto EXIT;

dbus_message_append_args(sig,
DBUS_TYPE_STRING, &key,
DBUS_TYPE_INVALID);

append_gconf_value_to_dbus_message(sig, val);

dbus_send_message(sig), sig = 0;

EXIT:

if( sig ) dbus_message_unref(sig);

return;
}

/** Release GSList of GConfValue objects
*
* @param list GSList where item->data members are pointers to GConfValue
Expand Down Expand Up @@ -993,13 +1050,20 @@ static gboolean config_set_dbus_cb(DBusMessage *const msg)

dbus_message_iter_init(msg, &body);

if( dbus_message_iter_get_arg_type(&body) != DBUS_TYPE_OBJECT_PATH ) {
/* HACK: The key used to be object path, not string.
* Allow clients to use either one. */
switch( dbus_message_iter_get_arg_type(&body) ) {
case DBUS_TYPE_OBJECT_PATH:
case DBUS_TYPE_STRING:
dbus_message_iter_get_basic(&body, &key);
dbus_message_iter_next(&body);
break;

default:
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS,
"expected object path");
"expected string/object path");
goto EXIT;
}
dbus_message_iter_get_basic(&body, &key);
dbus_message_iter_next(&body);

if( dbus_message_iter_get_arg_type(&body) == DBUS_TYPE_VARIANT ) {
dbus_message_iter_recurse(&body, &iter);
Expand Down Expand Up @@ -1776,15 +1840,15 @@ gboolean mce_dbus_init(const gboolean systembus)

/* get_config */
if (mce_dbus_handler_add(MCE_REQUEST_IF,
"get_config",
MCE_CONFIG_GET,
NULL,
DBUS_MESSAGE_TYPE_METHOD_CALL,
config_get_dbus_cb) == NULL)
goto EXIT;

/* set_config */
if (mce_dbus_handler_add(MCE_REQUEST_IF,
"set_config",
MCE_CONFIG_SET,
NULL,
DBUS_MESSAGE_TYPE_METHOD_CALL,
config_set_dbus_cb) == NULL)
Expand Down
6 changes: 6 additions & 0 deletions mce-dbus.h
Expand Up @@ -26,6 +26,10 @@

#include <mce/dbus-names.h>

#ifndef BUILTIN_GCONF
# include <gconf/gconf-client.h>
#endif

DBusConnection *dbus_connection_get(void);

DBusMessage *dbus_new_signal(const gchar *const path,
Expand Down Expand Up @@ -71,4 +75,6 @@ void mce_dbus_owner_monitor_remove_all(GSList **monitor_list);
gboolean mce_dbus_init(const gboolean systembus);
void mce_dbus_exit(void);

void mce_dbus_send_config_notification(GConfEntry *entry);

#endif /* _MCE_DBUS_H_ */

0 comments on commit 3ea0b2f

Please sign in to comment.