aboutsummaryrefslogtreecommitdiff
path: root/libindicate/listener.c
diff options
context:
space:
mode:
Diffstat (limited to 'libindicate/listener.c')
-rw-r--r--libindicate/listener.c208
1 files changed, 156 insertions, 52 deletions
diff --git a/libindicate/listener.c b/libindicate/listener.c
index b786552..0796bf1 100644
--- a/libindicate/listener.c
+++ b/libindicate/listener.c
@@ -32,7 +32,6 @@ License version 3 and version 2.1 along with this program. If not, see
#include <dbus/dbus-glib-bindings.h>
#include "dbus-indicate-client.h"
#include "dbus-listener-client.h"
-#include "dbus-listener-server.h"
/* Errors */
enum {
@@ -51,6 +50,17 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
+struct _IndicateListenerServer {
+ gchar * name;
+ DBusGProxy * proxy;
+ DBusGConnection * connection;
+ gboolean interests[INDICATE_INTEREST_LAST];
+};
+
+struct _IndicateListenerIndicator {
+ guint id;
+};
+
typedef struct _IndicateListenerPrivate IndicateListenerPrivate;
struct _IndicateListenerPrivate
{
@@ -60,8 +70,8 @@ struct _IndicateListenerPrivate
DBusGProxy * dbus_proxy_session;
DBusGProxy * dbus_proxy_system;
- GHashTable * proxies_working;
- GHashTable * proxies_possible;
+ GList * proxies_working;
+ GList * proxies_possible;
GArray * proxy_todo;
guint todo_idle;
@@ -78,8 +88,23 @@ typedef struct {
gchar * type;
IndicateListener * listener;
GHashTable * indicators;
+
+ 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;
@@ -95,7 +120,7 @@ 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);
-void get_type_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * type, 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);
@@ -104,6 +129,12 @@ static void proxy_get_indicator_list (DBusGProxy * proxy, GArray * indicators, G
static void proxy_get_indicator_type (DBusGProxy * proxy, gchar * type, GError * error, gpointer data);
static void proxy_indicators_free (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)
@@ -121,38 +152,38 @@ indicate_listener_class_init (IndicateListenerClass * class)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (IndicateListenerClass, indicator_added),
NULL, NULL,
- indicate_listener_marshal_VOID__POINTER_POINTER_STRING,
+ _indicate_listener_marshal_VOID__POINTER_POINTER_STRING,
G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_POINTER, 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,
+ _indicate_listener_marshal_VOID__POINTER_POINTER_STRING,
G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_POINTER, 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,
+ _indicate_listener_marshal_VOID__POINTER_POINTER_STRING_STRING,
G_TYPE_NONE, 4, G_TYPE_POINTER, G_TYPE_POINTER, 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,
+ _indicate_listener_marshal_VOID__POINTER_STRING,
G_TYPE_NONE, 2, G_TYPE_POINTER, 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,
+ _indicate_listener_marshal_VOID__POINTER_STRING,
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_STRING);
- dbus_g_object_register_marshaller(indicate_listener_marshal_VOID__UINT_STRING,
+ dbus_g_object_register_marshaller(_indicate_listener_marshal_VOID__UINT_STRING,
G_TYPE_NONE,
G_TYPE_UINT,
G_TYPE_STRING,
@@ -219,8 +250,8 @@ indicate_listener_init (IndicateListener * listener)
G_CALLBACK(dbus_owner_change), listener, NULL);
/* Initialize Data structures */
- priv->proxies_working = g_hash_table_new(g_str_hash, g_str_equal);
- priv->proxies_possible = g_hash_table_new(g_str_hash, g_str_equal);
+ 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));
@@ -292,16 +323,20 @@ dbus_owner_change (DBusGProxy * proxy, const gchar * name, const gchar * prev, c
todo_list_add(name, proxy, listener, FALSE);
}
if (new != NULL && new[0] == '\0') {
- proxy_t * proxyt;
- proxyt = g_hash_table_lookup(priv->proxies_working, name);
- if (proxyt != NULL) {
- g_hash_table_remove(priv->proxies_working, name);
- proxy_struct_destroy(proxyt);
+ 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);
}
- proxyt = g_hash_table_lookup(priv->proxies_possible, name);
- if (proxyt != NULL) {
- g_hash_table_remove(priv->proxies_possible, name);
- proxy_struct_destroy(proxyt);
+ 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);
}
}
@@ -319,7 +354,7 @@ proxy_struct_destroy_indicators (gpointer key, gpointer value, gpointer data)
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->name, id, type, TRUE);
+ g_signal_emit(proxy_data->listener, signals[INDICATOR_REMOVED], 0, &proxy_data->server, GUINT_TO_POINTER(id), type, TRUE);
}
g_list_free(keys);
@@ -339,7 +374,7 @@ proxy_struct_destroy (gpointer data)
proxy_data);
g_hash_table_remove_all(proxy_data->indicators);
- g_signal_emit(proxy_data->listener, signals[SERVER_REMOVED], 0, proxy_data->name, proxy_data->type, TRUE);
+ g_signal_emit(proxy_data->listener, signals[SERVER_REMOVED], 0, &proxy_data->server, proxy_data->type, TRUE);
proxy_data->indicators = NULL;
}
@@ -433,7 +468,7 @@ todo_idle (gpointer data)
proxy_todo_t * todo = &g_array_index(priv->proxy_todo, proxy_todo_t, priv->proxy_todo->len - 1);
- proxy_t * proxyt = g_new(proxy_t, 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,
@@ -444,6 +479,9 @@ todo_idle (gpointer data)
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);
@@ -457,7 +495,7 @@ todo_idle (gpointer data)
dbus_g_proxy_connect_signal(proxyt->proxy, "ServerShow",
G_CALLBACK(proxy_server_added), proxyt, NULL);
- g_hash_table_insert(priv->proxies_possible, proxyt->name, proxyt);
+ priv->proxies_possible = g_list_append(priv->proxies_possible, proxyt);
/* I think that we need to have this as there is a race
* condition here. If someone comes on the bus and we get
@@ -465,12 +503,12 @@ todo_idle (gpointer data)
* signal it gets sent, we wouldn't get it. So then we would
* miss an indicator server coming on the bus. I'd like to not
* generate a warning in every app with DBus though. */
- indicate_listener_server_get_type(listener, (IndicateListenerServer *)proxyt->name, get_type_cb, proxyt);
+ indicate_listener_server_get_type(listener, &proxyt->server, get_type_cb, proxyt);
return TRUE;
}
-void
+static void
get_type_cb (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data)
{
if (type == NULL) {
@@ -538,8 +576,13 @@ proxy_server_added (DBusGProxy * proxy, const gchar * type, proxy_t * proxyt)
g_free, proxy_indicators_free);
/* Elevate to working */
IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(proxyt->listener);
- g_hash_table_remove(priv->proxies_possible, proxyt->name);
- g_hash_table_insert(priv->proxies_working, proxyt->name, proxyt);
+
+ 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);
+ }
+ priv->proxies_working = g_list_append(priv->proxies_working, proxyt);
dbus_g_proxy_add_signal(proxyt->proxy, "IndicatorAdded",
G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID);
@@ -561,7 +604,7 @@ proxy_server_added (DBusGProxy * proxy, const gchar * type, proxy_t * proxyt)
proxyt->type = g_strdup(type);
}
- g_signal_emit(proxyt->listener, signals[SERVER_ADDED], 0, proxyt->name, proxyt->type, TRUE);
+ g_signal_emit(proxyt->listener, signals[SERVER_ADDED], 0, &proxyt->server, proxyt->type, TRUE);
}
return;
@@ -583,7 +626,7 @@ proxy_indicator_added (DBusGProxy * proxy, guint id, const gchar * type, proxy_t
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->name, id, type, TRUE);
+ g_signal_emit(proxyt->listener, signals[INDICATOR_ADDED], 0, &proxyt->server, GUINT_TO_POINTER(id), type, TRUE);
}
return;
@@ -609,7 +652,7 @@ proxy_indicator_removed (DBusGProxy * proxy, guint id, const gchar * type, proxy
}
g_hash_table_remove(indicators, (gpointer)id);
- g_signal_emit(proxyt->listener, signals[INDICATOR_REMOVED], 0, proxyt->name, id, type, TRUE);
+ g_signal_emit(proxyt->listener, signals[INDICATOR_REMOVED], 0, &proxyt->server, GUINT_TO_POINTER(id), type, TRUE);
return;
}
@@ -642,7 +685,7 @@ proxy_indicator_modified (DBusGProxy * proxy, guint id, const gchar * property,
return;
}
- g_signal_emit(proxyt->listener, signals[INDICATOR_MODIFIED], 0, proxyt->name, id, type, property, TRUE);
+ g_signal_emit(proxyt->listener, signals[INDICATOR_MODIFIED], 0, &proxyt->server, GUINT_TO_POINTER(id), type, property, TRUE);
return;
}
@@ -754,14 +797,6 @@ get_property_helper (IndicateListener * listener, IndicateListenerServer * serve
{
/* 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? */
- IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
-
- proxy_t * proxyt = g_hash_table_lookup(priv->proxies_working, server);
- if (proxyt == NULL) {
- g_error("Trying to get property '%s' on server '%s' that currently isn't set to working.", property, (gchar *)server);
- return;
- }
-
get_property_t * get_property_data = g_new(get_property_t, 1);
get_property_data->cb = callback;
get_property_data->data = data;
@@ -771,7 +806,7 @@ get_property_helper (IndicateListener * listener, IndicateListenerServer * serve
get_property_data->property = g_strdup(property);
get_property_data->type = prop_type;
- org_freedesktop_indicator_get_indicator_property_async (proxyt->proxy , INDICATE_LISTENER_INDICATOR_ID(indicator), property, get_property_cb, get_property_data);
+ org_freedesktop_indicator_get_indicator_property_async (server->proxy , INDICATE_LISTENER_INDICATOR_ID(indicator), property, get_property_cb, get_property_data);
return;
}
@@ -794,7 +829,7 @@ indicate_listener_get_property_icon (IndicateListener * listener, IndicateListen
}
gboolean
-indicate_listener_get_indicator_servers (IndicateListener * listener, GList * servers)
+_indicate_listener_get_indicator_servers (IndicateListener * listener, GList * servers)
{
@@ -812,11 +847,7 @@ listener_display_cb (DBusGProxy *proxy, GError *error, gpointer userdata)
void
indicate_listener_display (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator)
{
- IndicateListenerPrivate * priv = INDICATE_LISTENER_GET_PRIVATE(listener);
-
- proxy_t * proxyt = g_hash_table_lookup(priv->proxies_working, server);
-
- org_freedesktop_indicator_show_indicator_to_user_async (proxyt->proxy, INDICATE_LISTENER_INDICATOR_ID(indicator), listener_display_cb, NULL);
+ org_freedesktop_indicator_show_indicator_to_user_async (server->proxy, INDICATE_LISTENER_INDICATOR_ID(indicator), listener_display_cb, NULL);
return;
}
@@ -871,16 +902,22 @@ get_server_property (IndicateListener * listener, IndicateListenerServer * serve
/* 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 * proxyt = g_hash_table_lookup(priv->proxies_possible, server);
- if (proxyt == NULL) {
- proxyt = g_hash_table_lookup(priv->proxies_working, server);
+ 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 (proxyt == NULL) {
+ 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,
@@ -918,3 +955,70 @@ indicate_listener_server_get_desktop (IndicateListener * listener, IndicateListe
return get_server_property(listener, server, callback, "desktop", data);
}
+const gchar *
+indicate_listener_server_get_dbusname (IndicateListenerServer * server)
+{
+ 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 on server %s because: %s", ((IndicateListenerServer *)userdata)->name, error->message);
+ }
+
+ return;
+}
+
+void
+indicate_listener_server_show_interest (IndicateListener * listener, IndicateListenerServer * server, IndicateInterests interest)
+{
+ 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];
+}
+