aboutsummaryrefslogtreecommitdiff
path: root/libindicate/listener.c
diff options
context:
space:
mode:
Diffstat (limited to 'libindicate/listener.c')
-rw-r--r--libindicate/listener.c1084
1 files changed, 0 insertions, 1084 deletions
diff --git a/libindicate/listener.c b/libindicate/listener.c
deleted file mode 100644
index 48ad616..0000000
--- a/libindicate/listener.c
+++ /dev/null
@@ -1,1084 +0,0 @@
-/*
-A library to allow applictions to provide simple indications of
-information to be displayed to users of the application through the
-interface shell.
-
-Copyright 2009 Canonical Ltd.
-
-Authors:
- Ted Gould <ted@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of either or both of the following licenses:
-
-1) the GNU Lesser General Public License version 3, as published by the
-Free Software Foundation; and/or
-2) the GNU Lesser General Public License version 2.1, as published by
-the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
-PURPOSE. See the applicable version of the GNU Lesser General Public
-License for more details.
-
-You should have received a copy of both the GNU Lesser General Public
-License version 3 and version 2.1 along with this program. If not, see
-<http://www.gnu.org/licenses/>
-*/
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-
-#include "listener.h"
-#include "listener-marshal.h"
-#include <dbus/dbus-glib-bindings.h>
-#include "dbus-indicate-client.h"
-#include "dbus-listener-client.h"
-#include "interests-priv.h"
-
-/* Errors */
-enum {
- LAST_ERROR
-};
-
-/* Signals */
-enum {
- INDICATOR_ADDED,
- INDICATOR_REMOVED,
- INDICATOR_MODIFIED,
- SERVER_ADDED,
- SERVER_REMOVED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-#include "listener-private.h"
-
-typedef struct {
- DBusGProxy * proxy;
- DBusGProxy * property_proxy;
- DBusGConnection * connection;
- gchar * name;
- gchar * type;
- IndicateListener * listener;
- GHashTable * indicators;
- guint introspect_level;
-
- IndicateListenerServer server;
-} proxy_t;
-
-static gint
-proxy_t_equal (gconstpointer pa, gconstpointer pb)
-{
- proxy_t * a = (proxy_t *)pa; proxy_t * b = (proxy_t *)pb;
-
- if (a->connection == b->connection) {
- return g_strcmp0(a->name, b->name);
- } else {
- /* we're only using this for equal, not sorting */
- return 1;
- }
-}
-
-typedef struct {
- DBusGConnection * bus;
- gchar * name;
- gboolean startup;
-} proxy_todo_t;
-
-G_DEFINE_TYPE (IndicateListener, indicate_listener, G_TYPE_OBJECT);
-
-/* Prototypes */
-static void indicate_listener_finalize (GObject * obj);
-static void dbus_owner_change (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, IndicateListener * listener);
-static void proxy_struct_destroy (gpointer data);
-static void build_todo_list_cb (DBusGProxy * proxy, char ** names, GError * error, void * data);
-static void todo_list_add (const gchar * name, DBusGProxy * proxy, IndicateListener * listener, gboolean startup);
-static gboolean todo_idle (gpointer data);
-static void get_type_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data);
-static void proxy_server_added (DBusGProxy * proxy, const gchar * type, proxy_t * proxyt);
-static void proxy_indicator_added (DBusGProxy * proxy, guint id, const gchar * type, proxy_t * proxyt);
-static void proxy_indicator_removed (DBusGProxy * proxy, guint id, const gchar * type, proxy_t * proxyt);
-static void proxy_indicator_modified (DBusGProxy * proxy, guint id, const gchar * type, proxy_t * proxyt);
-static void proxy_get_indicator_list (DBusGProxy * proxy, GArray * indicators, GError * error, gpointer data);
-static void proxy_get_indicator_type (DBusGProxy * proxy, gchar * type, GError * error, gpointer data);
-static void proxy_indicators_free (gpointer data);
-static void introspect_this (DBusGProxy * proxy, char * OUT_data, GError * error, gpointer data);
-
-/* DBus interface */
-gboolean _indicate_listener_get_indicator_servers (IndicateListener * listener, GList * servers);
-
-/* Need the above prototypes */
-#include "dbus-listener-server.h"
-
-/* Code */
-static void
-indicate_listener_class_init (IndicateListenerClass * class)
-{
- /* g_debug("Listener Class Initialized"); */
- GObjectClass * gobj;
- gobj = G_OBJECT_CLASS(class);
-
- g_type_class_add_private (class, sizeof (IndicateListenerPrivate));
-
- gobj->finalize = indicate_listener_finalize;
-
- signals[INDICATOR_ADDED] = g_signal_new(INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED,
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (IndicateListenerClass, indicator_added),
- NULL, NULL,
- _indicate_listener_marshal_VOID__POINTER_POINTER_STRING,
- G_TYPE_NONE, 3, INDICATE_TYPE_LISTENER_SERVER, INDICATE_TYPE_LISTENER_INDICATOR, G_TYPE_STRING);
- signals[INDICATOR_REMOVED] = g_signal_new(INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED,
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (IndicateListenerClass, indicator_removed),
- NULL, NULL,
- _indicate_listener_marshal_VOID__POINTER_POINTER_STRING,
- G_TYPE_NONE, 3, INDICATE_TYPE_LISTENER_SERVER, INDICATE_TYPE_LISTENER_INDICATOR, G_TYPE_STRING);
- signals[INDICATOR_MODIFIED] = g_signal_new(INDICATE_LISTENER_SIGNAL_INDICATOR_MODIFIED,
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (IndicateListenerClass, indicator_modified),
- NULL, NULL,
- _indicate_listener_marshal_VOID__POINTER_POINTER_STRING_STRING,
- G_TYPE_NONE, 4, INDICATE_TYPE_LISTENER_SERVER, INDICATE_TYPE_LISTENER_INDICATOR, G_TYPE_STRING, G_TYPE_STRING);
- signals[SERVER_ADDED] = g_signal_new(INDICATE_LISTENER_SIGNAL_SERVER_ADDED,
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (IndicateListenerClass, server_added),
- NULL, NULL,
- _indicate_listener_marshal_VOID__POINTER_STRING,
- G_TYPE_NONE, 2, INDICATE_TYPE_LISTENER_SERVER, G_TYPE_STRING);
- signals[SERVER_REMOVED] = g_signal_new(INDICATE_LISTENER_SIGNAL_SERVER_REMOVED,
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (IndicateListenerClass, server_removed),
- NULL, NULL,
- _indicate_listener_marshal_VOID__POINTER_STRING,
- G_TYPE_NONE, 2, INDICATE_TYPE_LISTENER_SERVER, G_TYPE_STRING);
-
- dbus_g_object_register_marshaller(_indicate_listener_marshal_VOID__UINT_STRING,
- G_TYPE_NONE,
- G_TYPE_UINT,
- G_TYPE_STRING,
- G_TYPE_INVALID);
-
- return;
-}
-
-static void
-indicate_listener_init (IndicateListener * listener)
-{
- /* g_debug("Listener Object Initialized"); */
- IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
- GError *error = NULL;
-
- /* Get the buses */
- priv->session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
- if (error != NULL) {
- g_error("Unable to get session bus: %s", error->message);
- g_error_free(error);
- return;
- }
-
- priv->system_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
- if (error != NULL) {
- g_error("Unable to get system bus: %s", error->message);
- g_error_free(error);
- return;
- }
-
- /* Set up the DBUS service proxies */
- priv->dbus_proxy_session = dbus_g_proxy_new_for_name_owner (priv->session_bus,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- &error);
- if (error != NULL) {
- g_error("Unable to get dbus proxy on session bus: %s", error->message);
- g_error_free(error);
- return;
- }
-
- priv->dbus_proxy_system = dbus_g_proxy_new_for_name_owner (priv->system_bus,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- &error);
- if (error != NULL) {
- g_error("Unable to get dbus proxy on system bus: %s", error->message);
- g_error_free(error);
- return;
- }
-
- /* Set up name change signals */
- dbus_g_proxy_add_signal(priv->dbus_proxy_session, "NameOwnerChanged",
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(priv->dbus_proxy_session, "NameOwnerChanged",
- G_CALLBACK(dbus_owner_change), listener, NULL);
- dbus_g_proxy_add_signal(priv->dbus_proxy_system, "NameOwnerChanged",
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(priv->dbus_proxy_system, "NameOwnerChanged",
- G_CALLBACK(dbus_owner_change), listener, NULL);
-
- /* Initialize Data structures */
- priv->proxies_working = NULL;
- priv->proxies_possible = NULL;
-
- /* TODO: Look at some common scenarios and find out how to make this sized */
- priv->proxy_todo = g_array_new(FALSE, TRUE, sizeof(proxy_todo_t));
- priv->todo_idle = 0;
-
- /* WARNING */
- /* Starting massive asynchronisity */
- /* */
-
- /* Build todo list */
- org_freedesktop_DBus_list_names_async (priv->dbus_proxy_session, build_todo_list_cb, listener);
- org_freedesktop_DBus_list_names_async (priv->dbus_proxy_system, build_todo_list_cb, listener);
-
- return;
-}
-
-static void
-indicate_listener_finalize (GObject * obj)
-{
- IndicateListener * listener = INDICATE_LISTENER(obj);
- IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
-
- if (priv->todo_idle != 0) {
- g_idle_remove_by_data(obj);
- }
- /* Hack: proxy_struct_destroy() lacks a user_data parameter, but since the
- * caller is responsible for handling params on the stack, it works
- */
- g_list_foreach(priv->proxies_possible, (GFunc)proxy_struct_destroy, NULL);
- g_list_free(priv->proxies_possible);
- g_list_foreach(priv->proxies_working, (GFunc)proxy_struct_destroy, NULL);
- g_list_free(priv->proxies_working);
- G_OBJECT_CLASS (indicate_listener_parent_class)->finalize (obj);
- return;
-}
-
-IndicateListener *
-indicate_listener_new (void)
-{
- IndicateListener * listener;
- listener = g_object_new(INDICATE_TYPE_LISTENER, NULL);
- return listener;
-}
-
-static IndicateListener * default_indicate_listener = NULL;
-
-IndicateListener *
-indicate_listener_ref_default (void)
-{
- if (default_indicate_listener != NULL) {
- g_object_ref(default_indicate_listener);
- } else {
- default_indicate_listener = g_object_new(INDICATE_TYPE_LISTENER, NULL);
- g_object_add_weak_pointer(G_OBJECT(default_indicate_listener),
- (gpointer *)&default_indicate_listener);
- }
-
- return default_indicate_listener;
-}
-
-static void
-dbus_owner_change (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, IndicateListener * listener)
-{
- IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
-
- DBusGConnection * bus;
- gchar * bus_name;
- if (proxy == priv->dbus_proxy_system) {
- bus = priv->system_bus;
- bus_name = "system";
- } else {
- bus = priv->session_bus;
- bus_name = "session";
- }
-
- /* g_debug("Name change on %s bus: '%s' from '%s' to '%s'", bus_name, name, prev, new); */
-
- if (prev != NULL && prev[0] == '\0') {
- todo_list_add(name, proxy, listener, FALSE);
- }
- if (new != NULL && new[0] == '\0') {
- proxy_t searchitem;
- searchitem.connection = bus;
- searchitem.name = (gchar *)name; /* Droping const, not that it isn't, but to remove the warning */
-
- GList * proxyt_item;
- proxyt_item = g_list_find_custom(priv->proxies_working, &searchitem, proxy_t_equal);
- if (proxyt_item != NULL) {
- proxy_struct_destroy((proxy_t *)proxyt_item->data);
- priv->proxies_working = g_list_remove(priv->proxies_working, proxyt_item->data);
- }
- proxyt_item = g_list_find_custom(priv->proxies_possible, &searchitem, proxy_t_equal);
- if (proxyt_item != NULL) {
- proxy_struct_destroy((proxy_t *)proxyt_item->data);
- priv->proxies_possible = g_list_remove(priv->proxies_possible, proxyt_item->data);
- }
- }
-
- return;
-}
-
-static void
-proxy_struct_destroy_indicators (gpointer key, gpointer value, gpointer data)
-{
- gchar * type = (gchar *)key;
- GHashTable * indicators = (GHashTable *)value;
- proxy_t * proxy_data = data;
-
- GList * keys = g_hash_table_get_keys(indicators);
- GList * indicator;
- for (indicator = keys; indicator != NULL; indicator = indicator->next) {
- guint id = (guint)indicator->data;
- g_signal_emit(proxy_data->listener, signals[INDICATOR_REMOVED], 0, &proxy_data->server, GUINT_TO_POINTER(id), type, TRUE);
- }
- g_list_free(keys);
-
- g_hash_table_remove_all(indicators);
- return;
-}
-
-static void
-proxy_struct_destroy (gpointer data)
-{
- proxy_t * proxy_data = data;
-
- /* TODO: Clear the indicators by signaling */
- if (proxy_data->indicators != NULL) {
- g_hash_table_foreach(proxy_data->indicators,
- proxy_struct_destroy_indicators,
- proxy_data);
- g_hash_table_remove_all(proxy_data->indicators);
-
- g_signal_emit(proxy_data->listener, signals[SERVER_REMOVED], 0, &proxy_data->server, proxy_data->type, TRUE);
- proxy_data->indicators = NULL;
- }
-
- if (DBUS_IS_G_PROXY(proxy_data->property_proxy)) {
- g_object_unref(G_OBJECT(proxy_data->property_proxy));
- }
-
- if (DBUS_IS_G_PROXY(proxy_data->proxy)) {
- g_object_unref(G_OBJECT(proxy_data->proxy));
- }
-
- g_free(proxy_data->name);
- if (proxy_data->type != NULL) {
- g_free(proxy_data->type);
- }
- g_free(proxy_data);
-
- return;
-}
-
-static void
-build_todo_list_cb (DBusGProxy * proxy, char ** names, GError * error, void * data)
-{
- IndicateListener * listener = INDICATE_LISTENER(data);
-
- if (error != NULL) {
- g_warning("Unable to get names: %s", error->message);
- return;
- }
-
- guint i = 0;
- for (i = 0; names[i] != NULL; i++) {
- todo_list_add(names[i], proxy, listener, TRUE);
- }
-
- return;
-}
-
-static void
-todo_list_add (const gchar * name, DBusGProxy * proxy, IndicateListener * listener, gboolean startup)
-{
- if (name == NULL || name[0] != ':') {
- return;
- }
-
- IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
-
- DBusGConnection * bus;
- gchar * bus_name;
- if (proxy == priv->dbus_proxy_system) {
- bus = priv->system_bus;
- bus_name = "system";
- } else {
- bus = priv->session_bus;
- bus_name = "session";
- }
- /* g_debug ("Adding on %s bus: %s", bus_name, name); */
-
- proxy_todo_t todo;
- todo.name = g_strdup(name);
- todo.bus = bus;
- todo.startup = startup;
-
- g_array_append_val(priv->proxy_todo, todo);
-
- if (priv->todo_idle == 0) {
- priv->todo_idle = g_idle_add(todo_idle, listener);
- }
-
- return;
-}
-
-gboolean
-todo_idle (gpointer data)
-{
- IndicateListener * listener = INDICATE_LISTENER(data);
- if (listener == NULL) {
- g_error("Listener got lost in todo_idle");
- return FALSE;
- }
-
- IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
-
- if (priv->proxy_todo->len == 0) {
- /* Basically if we have no todo, we need to stop running. This
- * is done this way to make the function error handling simpler
- * and results in an extra run */
- priv->todo_idle = 0;
- return FALSE;
- }
-
- proxy_todo_t * todo = &g_array_index(priv->proxy_todo, proxy_todo_t, priv->proxy_todo->len - 1);
-
- proxy_t * proxyt = g_new0(proxy_t, 1);
- proxyt->name = todo->name;
- proxyt->type = NULL;
- proxyt->proxy = dbus_g_proxy_new_for_name(todo->bus,
- proxyt->name,
- "/org/freedesktop/indicate",
- "org.freedesktop.indicator");
- proxyt->property_proxy = NULL;
- proxyt->listener = listener;
- proxyt->indicators = NULL;
- proxyt->connection = todo->bus;
- proxyt->server.name = todo->name;
- proxyt->server.proxy = proxyt->proxy;
- proxyt->server.connection = proxyt->connection;
-
- priv->proxy_todo = g_array_remove_index(priv->proxy_todo, priv->proxy_todo->len - 1);
-
- if (proxyt->proxy == NULL) {
- g_warning("Unable to create proxy for %s", proxyt->name);
- return TRUE;
- }
-
- dbus_g_proxy_add_signal(proxyt->proxy, "ServerShow",
- G_TYPE_STRING, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(proxyt->proxy, "ServerShow",
- G_CALLBACK(proxy_server_added), proxyt, NULL);
-
- priv->proxies_possible = g_list_prepend(priv->proxies_possible, proxyt);
-
- /* Look through the introspection data to see if this
- is already a server */
- introspect_this (NULL, NULL, NULL, proxyt);
-
- return TRUE;
-}
-
-static void
-get_type_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
-{
- if (type == NULL) {
- /* This is usually caused by an error getting the type,
- * which would mean that this isn't an indicator server */
- return;
- }
-
- proxy_t * proxyt = (proxy_t *)data;
-
- proxy_server_added (proxyt->proxy, type, proxyt);
- org_freedesktop_indicator_get_indicator_list_async(proxyt->proxy, proxy_get_indicator_list, proxyt);
-
- return;
-}
-
-typedef struct {
- guint id;
- proxy_t * proxyt;
-} indicator_type_t;
-
-static void
-proxy_get_indicator_list (DBusGProxy * proxy, GArray * indicators, GError * error, gpointer data)
-{
- if (error != NULL) {
- return;
- }
-
- proxy_t * proxyt = (proxy_t *)data;
-
- int i;
- for (i = 0; i < indicators->len; i++) {
- indicator_type_t * itt = g_new(indicator_type_t, 1);
- itt->id = g_array_index(indicators, guint, i);
- itt->proxyt = proxyt;
-
- org_freedesktop_indicator_get_indicator_property_async(proxyt->proxy, itt->id, "type", proxy_get_indicator_type, itt);
- }
-
- return;
-}
-
-static void
-proxy_get_indicator_type (DBusGProxy * proxy, gchar * type, GError * error, gpointer data)
-{
- if (error != NULL) {
- g_warning("Get Indicator Type returned error: %s", error->message);
- return;
- }
-
- indicator_type_t * itt = (indicator_type_t *)data;
- guint id = itt->id;
- proxy_t * proxyt = itt->proxyt;
-
- g_free(itt);
-
- return proxy_indicator_added(proxy, id, type, proxyt);
-}
-
-static void
-proxy_server_added (DBusGProxy * proxy, const gchar * type, proxy_t * proxyt)
-{
- if (proxyt->indicators == NULL) {
- proxyt->indicators = g_hash_table_new_full(g_str_hash, g_str_equal,
- g_free, proxy_indicators_free);
- /* Elevate to working */
- IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(proxyt->listener);
-
- GList * proxyt_item;
- proxyt_item = g_list_find_custom(priv->proxies_possible, proxyt, proxy_t_equal);
- if (proxyt_item != NULL) {
- priv->proxies_possible = g_list_remove(priv->proxies_possible, proxyt_item->data);
- }
- priv->proxies_working = g_list_prepend(priv->proxies_working, proxyt);
-
- dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorAdded",
- G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorAdded",
- G_CALLBACK(proxy_indicator_added), proxyt, NULL);
- dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorRemoved",
- G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorRemoved",
- G_CALLBACK(proxy_indicator_removed), proxyt, NULL);
- dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorModified",
- G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(proxyt->proxy, "IndicatorModified",
- G_CALLBACK(proxy_indicator_modified), proxyt, NULL);
-
- if (type != NULL) {
- if (proxyt->type != NULL) {
- g_free(proxyt->type);
- }
- proxyt->type = g_strdup(type);
- }
-
- g_signal_emit(proxyt->listener, signals[SERVER_ADDED], 0, &proxyt->server, proxyt->type, TRUE);
- }
-
- return;
-}
-
-static void
-proxy_indicator_added (DBusGProxy * proxy, guint id, const gchar * type, proxy_t * proxyt)
-{
- if (proxyt->indicators == NULL) {
- proxy_server_added (proxy, NULL, proxyt);
- }
-
- GHashTable * indicators = g_hash_table_lookup(proxyt->indicators, type);
-
- if (indicators == NULL) {
- indicators = g_hash_table_new(g_direct_hash, g_direct_equal);
- g_hash_table_insert(proxyt->indicators, g_strdup(type), indicators);
- }
-
- if (!g_hash_table_lookup(indicators, (gpointer)id)) {
- g_hash_table_insert(indicators, (gpointer)id, (gpointer)TRUE);
- g_signal_emit(proxyt->listener, signals[INDICATOR_ADDED], 0, &proxyt->server, GUINT_TO_POINTER(id), type, TRUE);
- }
-
- return;
-}
-
-static void
-proxy_indicator_removed (DBusGProxy * proxy, guint id, const gchar * type, proxy_t * proxyt)
-{
- if (proxyt->indicators == NULL) {
- g_warning("Oddly we had an indicator removed from an interface that we didn't think had indicators.");
- return;
- }
-
- GHashTable * indicators = g_hash_table_lookup(proxyt->indicators, type);
- if (indicators == NULL) {
- g_warning("Can not remove indicator %d of type '%s' as there are no indicators of that type on %s.", id, type, proxyt->name);
- return;
- }
-
- if (!g_hash_table_lookup(indicators, (gpointer)id)) {
- g_warning("No indicator %d of type '%s' on '%s'.", id, type, proxyt->name);
- return;
- }
-
- g_hash_table_remove(indicators, (gpointer)id);
- g_signal_emit(proxyt->listener, signals[INDICATOR_REMOVED], 0, &proxyt->server, GUINT_TO_POINTER(id), type, TRUE);
-
- return;
-}
-
-static void
-proxy_indicator_modified (DBusGProxy * proxy, guint id, const gchar * property, proxy_t * proxyt)
-{
- if (proxyt->indicators == NULL) {
- g_warning("Oddly we had an indicator modified from an interface that we didn't think had indicators.");
- return;
- }
-
- GList * keys = g_hash_table_get_keys(proxyt->indicators);
- GList * inc = NULL;
- gchar * type;
-
- for (inc = g_list_first(keys); inc != NULL; inc = g_list_next(inc)) {
- type = (gchar *)inc->data;
-
- GHashTable * indicators = g_hash_table_lookup(proxyt->indicators, type);
- if (indicators == NULL) continue; /* no indicators for this type? Odd, but not an error */
-
- if (g_hash_table_lookup(indicators, (gpointer)id)) {
- break;
- }
- }
-
- if (inc == NULL) {
- g_warning("Can not modify indicator %d with property '%s' as there are no indicators with that id on %s.", id, property, proxyt->name);
- return;
- }
-
- g_signal_emit(proxyt->listener, signals[INDICATOR_MODIFIED], 0, &proxyt->server, GUINT_TO_POINTER(id), type, property, TRUE);
-
- return;
-}
-
-static void
-proxy_indicators_free (gpointer data)
-{
- GHashTable * table = (GHashTable *)data;
-
- if (g_hash_table_size(table) != 0) {
- g_warning("Clearning a set of indicators that wasn't signaled!");
- }
-
- g_hash_table_unref(table);
- return;
-}
-
-typedef enum _get_property_type get_property_type;
-enum _get_property_type {
- PROPERTY_TYPE_STRING,
- PROPERTY_TYPE_TIME
-};
-
-typedef struct _get_property_t get_property_t;
-struct _get_property_t {
- GCallback cb;
- gpointer data;
- IndicateListener * listener;
- IndicateListenerServer * server;
- IndicateListenerIndicator * indicator;
- gchar * property;
- get_property_type type;
-};
-
-static void
-get_property_cb (DBusGProxy *proxy, char * OUT_value, GError *error, gpointer userdata)
-{
- get_property_t * get_property_data = (get_property_t *)userdata;
-
- if (error != NULL) {
- g_warning("Unable to get property data: %s", error->message);
- g_error_free(error);
- return;
- }
-
- switch (get_property_data->type) {
- case PROPERTY_TYPE_STRING: {
- indicate_listener_get_property_cb cb = (indicate_listener_get_property_cb)get_property_data->cb;
- cb(get_property_data->listener, get_property_data->server, get_property_data->indicator, get_property_data->property, OUT_value, get_property_data->data);
- break;
- }
- case PROPERTY_TYPE_TIME: {
- indicate_listener_get_property_time_cb cb = (indicate_listener_get_property_time_cb)get_property_data->cb;
- GTimeVal time;
- if (g_time_val_from_iso8601(OUT_value, &time)) {
- cb(get_property_data->listener, get_property_data->server, get_property_data->indicator, get_property_data->property, &time, get_property_data->data);
- }
- break;
- }
- }
-
- g_free(get_property_data->property);
- g_free(get_property_data);
-
- return;
-};
-
-static void
-get_property_helper (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, GCallback callback, gpointer data, get_property_type prop_type)
-{
- /* g_debug("get_property_helper: %s %d", property, prop_type); */
- /* TODO: Do we need to somehow refcount the server/indicator while we're waiting on this? */
- get_property_t * get_property_data = g_new(get_property_t, 1);
- get_property_data->cb = callback;
- get_property_data->data = data;
- get_property_data->listener = listener;
- get_property_data->server = server;
- get_property_data->indicator = indicator;
- get_property_data->property = g_strdup(property);
- get_property_data->type = prop_type;
-
- org_freedesktop_indicator_get_indicator_property_async (server->proxy , INDICATE_LISTENER_INDICATOR_ID(indicator), property, get_property_cb, get_property_data);
- return;
-}
-
-void
-indicate_listener_get_property (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, indicate_listener_get_property_cb callback, gpointer data)
-{
- return get_property_helper(listener, server, indicator, property, G_CALLBACK(callback), data, PROPERTY_TYPE_STRING);
-}
-
-void
-indicate_listener_get_property_time (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gchar * property, indicate_listener_get_property_time_cb callback, gpointer data)
-{
- return get_property_helper(listener, server, indicator, property, G_CALLBACK(callback), data, PROPERTY_TYPE_TIME);
-}
-
-gboolean
-_indicate_listener_get_indicator_servers (IndicateListener * listener, GList * servers)
-{
-
- return TRUE;
-}
-
-static void
-listener_display_cb (DBusGProxy *proxy, GError *error, gpointer userdata)
-{
- if (error != NULL) {
- g_warning("Listener display caused an error: %s", error->message);
- }
- return;
-}
-
-void
-indicate_listener_display (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator)
-{
- org_freedesktop_indicator_show_indicator_to_user_async (server->proxy, INDICATE_LISTENER_INDICATOR_ID(indicator), listener_display_cb, NULL);
-
- return;
-}
-
-typedef struct {
- IndicateListener * listener;
- IndicateListenerServer * server;
- indicate_listener_get_server_property_cb cb;
- gpointer data;
-} property_cb_t;
-
-static void
-property_cb (DBusGProxy * proxy, DBusGProxyCall * call, void * data)
-{
- /* g_debug("Callback for property %s %s %s", dbus_g_proxy_get_bus_name(proxy), dbus_g_proxy_get_path(proxy), dbus_g_proxy_get_interface(proxy)); */
- property_cb_t * propertyt = data;
- GError * error = NULL;
-
- GValue property = {0};
-
- dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &property, G_TYPE_INVALID);
- if (error != NULL) {
- /* g_warning("Unable to get property: %s", error->message); */
- g_error_free(error);
- g_free(propertyt);
- return;
- }
-
- if (!G_VALUE_HOLDS_STRING(&property)) {
- g_warning("Property returned is not a string!");
- g_free(propertyt);
- return;
- }
-
- IndicateListener * listener = propertyt->listener;
- IndicateListenerServer * server = propertyt->server;
- indicate_listener_get_server_property_cb cb = propertyt->cb;
- gpointer cb_data = propertyt->data;
-
- g_free(propertyt);
-
- gchar * propstr = g_value_dup_string(&property);
-
- /* g_debug("\tProperty value: %s", propstr); */
-
- return cb(listener, server, propstr, cb_data);
-}
-
-static void
-get_server_property (IndicateListener * listener, IndicateListenerServer * server, indicate_listener_get_server_property_cb callback, const gchar * property_name, gpointer data)
-{
- /* g_debug("Setting up callback for property %s on %s", property_name, INDICATE_LISTENER_SERVER_DBUS_NAME(server)); */
- IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
-
- proxy_t searchitem;
- searchitem.name = server->name;
- searchitem.connection = server->connection;
-
- GList * proxyitem = g_list_find_custom(priv->proxies_possible, &searchitem, proxy_t_equal);
- if (proxyitem == NULL) {
- proxyitem = g_list_find_custom(priv->proxies_working, &searchitem, proxy_t_equal);
- }
-
- if (proxyitem == NULL) {
- g_warning("Can not find a proxy for the server at all.");
- return;
- }
-
- proxy_t * proxyt = (proxy_t *)proxyitem->data;
-
- if (proxyt->property_proxy == NULL) {
- proxyt->property_proxy = dbus_g_proxy_new_for_name(proxyt->connection,
- proxyt->name,
- "/org/freedesktop/indicate",
- DBUS_INTERFACE_PROPERTIES);
- }
-
- property_cb_t * localdata = g_new(property_cb_t, 1);
- localdata->listener = listener;
- localdata->server = server;
- localdata->cb = callback;
- localdata->data = data;
-
- dbus_g_proxy_begin_call (proxyt->property_proxy,
- "Get",
- property_cb,
- localdata,
- NULL,
- G_TYPE_STRING, "org.freedesktop.indicator",
- G_TYPE_STRING, property_name,
- G_TYPE_INVALID, G_TYPE_VALUE, G_TYPE_INVALID);
-
- return;
-}
-
-void
-indicate_listener_server_get_type (IndicateListener * listener, IndicateListenerServer * server, indicate_listener_get_server_property_cb callback, gpointer data)
-{
- return get_server_property(listener, server, callback, "type", data);
-}
-
-void
-indicate_listener_server_get_desktop (IndicateListener * listener, IndicateListenerServer * server, indicate_listener_get_server_property_cb callback, gpointer data)
-{
- return get_server_property(listener, server, callback, "desktop", data);
-}
-
-const gchar *
-indicate_listener_server_get_dbusname (IndicateListenerServer * server)
-{
- if (server == NULL) return NULL;
- return server->name;
-}
-
-guint
-indicate_listener_indicator_get_id (IndicateListenerIndicator * indicator)
-{
- return GPOINTER_TO_UINT(indicator);
-}
-
-static const gchar *
-interest_to_string (IndicateInterests interest)
-{
- switch (interest) {
- case INDICATE_INTEREST_SERVER_DISPLAY:
- return INDICATE_INTEREST_STRING_SERVER_DISPLAY;
- case INDICATE_INTEREST_SERVER_SIGNAL:
- return INDICATE_INTEREST_STRING_SERVER_SIGNAL;
- case INDICATE_INTEREST_INDICATOR_DISPLAY:
- return INDICATE_INTEREST_STRING_INDICATOR_DISPLAY;
- case INDICATE_INTEREST_INDICATOR_SIGNAL:
- return INDICATE_INTEREST_STRING_INDICATOR_SIGNAL;
- case INDICATE_INTEREST_INDICATOR_COUNT:
- return INDICATE_INTEREST_STRING_INDICATOR_COUNT;
- default:
- return "";
- }
-}
-
-static void
-interest_cb (DBusGProxy *proxy, GError *error, gpointer userdata)
-{
- if (error != NULL) {
- g_warning("Unable to configure interest.");
- }
-
- return;
-}
-
-void
-indicate_listener_server_show_interest (IndicateListener * listener, IndicateListenerServer * server, IndicateInterests interest)
-{
- if (!(interest > INDICATE_INTEREST_NONE && interest < INDICATE_INTEREST_LAST)) {
- return;
- }
-
- if (!server->interests[interest]) {
- org_freedesktop_indicator_show_interest_async (server->proxy, interest_to_string(interest), interest_cb, server);
- server->interests[interest] = TRUE;
- }
- return;
-}
-
-void
-indicate_listener_server_remove_interest (IndicateListener * listener, IndicateListenerServer * server, IndicateInterests interest)
-{
- if (server->interests[interest]) {
- org_freedesktop_indicator_remove_interest_async (server->proxy, interest_to_string(interest), interest_cb, server);
- server->interests[interest] = FALSE;
- }
- return;
-}
-
-gboolean
-indicate_listener_server_check_interest (IndicateListener * listener, IndicateListenerServer * server, IndicateInterests interest)
-{
- return server->interests[interest];
-}
-
-GType
-indicate_listener_server_get_gtype (void)
-{
- static GType our_type = 0;
-
- if (our_type == 0)
- our_type = g_pointer_type_register_static ("IndicateListenerServer");
-
- return our_type;
-}
-
-GType
-indicate_listener_indicator_get_gtype (void)
-{
- static GType our_type = 0;
-
- if (our_type == 0)
- our_type = g_pointer_type_register_static ("IndicateListenerIndicator");
-
- return our_type;
-}
-
-static const gchar * _introspector_path[] = {"", "org", "freedesktop", "indicate", NULL};
-static const gchar * _introspector_fullpath[] = {"/", "/org", "/org/freedesktop", "/org/freedesktop/indicate", NULL};
-static const gchar * _introspector_interface = "org.freedesktop.indicator";
-
-static void
-introspect_this (DBusGProxy * proxy, char * OUT_data, GError * error, gpointer data)
-{
- /* g_debug("Introspect this:\n%s", OUT_data); */
- proxy_t * server = (proxy_t *)data;
- if (proxy != NULL) {
- g_object_unref(proxy);
- }
- if (error != NULL) {
- /* We probably couldn't introspect that far up. That's
- life, it happens. Or there's a timeout, that happens
- too, I guess some apps are too busy for us. */
- /* g_debug("Introspection error on %s object %s: %s", server->name, _introspector_fullpath[server->introspect_level], error->message); */
- return;
- }
-
- if (OUT_data != NULL) {
- xmlDocPtr xmldoc;
- /* Parse the XML */
- xmldoc = xmlReadMemory(OUT_data, g_utf8_strlen(OUT_data, 16*1024), "introspection.xml", NULL, 0);
-
- /* Check for root being "node" */
- xmlNodePtr root = xmlDocGetRootElement(xmldoc);
- if (g_strcmp0(root->name, "node") != 0) {
- xmlFreeDoc(xmldoc);
- g_warning("Introspection data from %s is not valid: %s", server->name, OUT_data);
- return;
- }
-
- server->introspect_level += 1;
- const gchar * nodename = NULL;
- const gchar * nameval = NULL;
- if (_introspector_path[server->introspect_level] == NULL) {
- /* We're looking for our interface */
- nodename = "interface";
- nameval = _introspector_interface;
- } else {
- /* We're looking for our next node */
- nodename = "node";
- nameval = _introspector_path[server->introspect_level];
- }
-
- gboolean found = FALSE;
- xmlNodePtr children;
- for (children = root->children; children != NULL; children = children->next) {
- gchar * xmlnameval = NULL;
- if (g_strcmp0(children->name, nodename) == 0) {
- xmlAttrPtr attrib;
- for (attrib = children->properties; attrib != NULL; attrib = attrib->next) {
- if (g_strcmp0(attrib->name, "name") == 0) {
- if (attrib->children != NULL) {
- xmlnameval = attrib->children->content;
- }
- break;
- }
- }
-
- if (!g_strcmp0(nameval, xmlnameval)) {
- found = TRUE;
- break;
- }
- }
- }
-
- xmlFreeDoc(xmldoc);
-
- if (!found) {
- /* Ah, nothing we're interested in */
- return;
- }
-
- if (_introspector_path[server->introspect_level] == NULL) {
- /* If we've found the interface at the end of the tree, whoo! hoo! */
- /* Now we know it's safe to get the type on it */
- indicate_listener_server_get_type(server->listener, &server->server, get_type_cb, server);
- return;
- }
- } else {
- server->introspect_level = 0;
- }
-
- DBusGProxy * newproxy = dbus_g_proxy_new_for_name(server->connection,
- server->name,
- _introspector_fullpath[server->introspect_level],
- DBUS_INTERFACE_INTROSPECTABLE);
-
- org_freedesktop_DBus_Introspectable_introspect_async(newproxy, introspect_this, server);
-
- return;
-}