From 43f655d32a7a4aadac9566b2aba42b2b906cceda Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Fri, 30 Sep 2011 12:51:59 -0400 Subject: [PATCH] UDisksClient: add a rate-limited ::change signal Signed-off-by: David Zeuthen --- udisks/udisksclient.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/udisks/udisksclient.c b/udisks/udisksclient.c index 9eee721..7b467ca 100644 --- a/udisks/udisksclient.c +++ b/udisks/udisksclient.c @@ -53,6 +53,8 @@ struct _UDisksClient GDBusObjectManager *object_manager; GMainContext *context; + + GSource *changed_timeout_source; }; typedef struct @@ -67,9 +69,42 @@ enum PROP_MANAGER }; +enum +{ + CHANGED_SIGNAL, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + static void initable_iface_init (GInitableIface *initable_iface); static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface); +static void on_object_added (GDBusObjectManager *manager, + GDBusObject *object, + gpointer user_data); + +static void on_object_removed (GDBusObjectManager *manager, + GDBusObject *object, + gpointer user_data); + +static void on_interface_added (GDBusObjectManager *manager, + GDBusObject *object, + GDBusInterface *interface, + gpointer user_data); + +static void on_interface_removed (GDBusObjectManager *manager, + GDBusObject *object, + GDBusInterface *interface, + gpointer user_data); + +static void on_interface_proxy_properties_changed (GDBusObjectManagerClient *manager, + GDBusObjectProxy *object_proxy, + GDBusProxy *interface_proxy, + GVariant *changed_properties, + const gchar *const *invalidated_properties, + gpointer user_data); + G_DEFINE_TYPE_WITH_CODE (UDisksClient, udisks_client, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init) G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init) @@ -80,9 +115,27 @@ udisks_client_finalize (GObject *object) { UDisksClient *client = UDISKS_CLIENT (object); + if (client->changed_timeout_source != NULL) + g_source_destroy (client->changed_timeout_source); + if (client->initialization_error != NULL) g_error_free (client->initialization_error); + g_signal_handlers_disconnect_by_func (client->object_manager, + G_CALLBACK (on_object_added), + client); + g_signal_handlers_disconnect_by_func (client->object_manager, + G_CALLBACK (on_object_removed), + client); + g_signal_handlers_disconnect_by_func (client->object_manager, + G_CALLBACK (on_interface_added), + client); + g_signal_handlers_disconnect_by_func (client->object_manager, + G_CALLBACK (on_interface_removed), + client); + g_signal_handlers_disconnect_by_func (client->object_manager, + G_CALLBACK (on_interface_proxy_properties_changed), + client); g_object_unref (client->object_manager); if (client->context != NULL) @@ -163,6 +216,34 @@ udisks_client_class_init (UDisksClientClass *klass) UDISKS_TYPE_MANAGER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * UDisksClient::changed: + * @client: A #UDisksClient. + * + * This signal is emitted either when an object or interface is + * added or removed a when property has changed. Additionally, + * multiple received signals are coalesced into a single signal that + * is rate-limited to fire at most every 100ms. + * + * For greater detail, connect to the + * #GDBusObjectManager::object-added, + * #GDBusObjectManager::object-removed, + * #GDBusObjectManager::interface-added, + * #GDBusObjectManager::interface-removed, + * #GDBusObjectManagerClient::interface-proxy-properties-changed and + * signals on the #UDisksClient:object-manager object. + */ + signals[CHANGED_SIGNAL] = g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + 0, /* G_STRUCT_OFFSET */ + NULL, /* accu */ + NULL, /* accu data */ + g_cclosure_marshal_generic, + G_TYPE_NONE, + 0); + } /** @@ -279,6 +360,27 @@ initable_init (GInitable *initable, if (client->object_manager == NULL) goto out; + g_signal_connect (client->object_manager, + "object-added", + G_CALLBACK (on_object_added), + client); + g_signal_connect (client->object_manager, + "object-removed", + G_CALLBACK (on_object_removed), + client); + g_signal_connect (client->object_manager, + "interface-added", + G_CALLBACK (on_interface_added), + client); + g_signal_connect (client->object_manager, + "interface-removed", + G_CALLBACK (on_interface_removed), + client); + g_signal_connect (client->object_manager, + "interface-proxy-properties-changed", + G_CALLBACK (on_interface_proxy_properties_changed), + client); + ret = TRUE; out: @@ -998,3 +1100,82 @@ udisks_client_get_cleartext_block (UDisksClient *client, g_list_free (objects); return ret; } + +/* ---------------------------------------------------------------------------------------------------- */ + +static gboolean +on_changed_timeout (gpointer user_data) +{ + UDisksClient *client = UDISKS_CLIENT (user_data); + client->changed_timeout_source = NULL; + g_signal_emit (client, signals[CHANGED_SIGNAL], 0); + return FALSE; /* remove source */ +} + +static void +queue_changed (UDisksClient *client) +{ + if (client->changed_timeout_source != NULL) + goto out; + + client->changed_timeout_source = g_timeout_source_new (100); + g_source_set_callback (client->changed_timeout_source, + (GSourceFunc) on_changed_timeout, + client, + NULL); /* destroy notify */ + g_source_attach (client->changed_timeout_source, client->context); + g_source_unref (client->changed_timeout_source); + + out: + ; +} + +static void +on_object_added (GDBusObjectManager *manager, + GDBusObject *object, + gpointer user_data) +{ + UDisksClient *client = UDISKS_CLIENT (user_data); + queue_changed (client); +} + +static void +on_object_removed (GDBusObjectManager *manager, + GDBusObject *object, + gpointer user_data) +{ + UDisksClient *client = UDISKS_CLIENT (user_data); + queue_changed (client); +} + +static void +on_interface_added (GDBusObjectManager *manager, + GDBusObject *object, + GDBusInterface *interface, + gpointer user_data) +{ + UDisksClient *client = UDISKS_CLIENT (user_data); + queue_changed (client); +} + +static void +on_interface_removed (GDBusObjectManager *manager, + GDBusObject *object, + GDBusInterface *interface, + gpointer user_data) +{ + UDisksClient *client = UDISKS_CLIENT (user_data); + queue_changed (client); +} + +static void +on_interface_proxy_properties_changed (GDBusObjectManagerClient *manager, + GDBusObjectProxy *object_proxy, + GDBusProxy *interface_proxy, + GVariant *changed_properties, + const gchar *const *invalidated_properties, + gpointer user_data) +{ + UDisksClient *client = UDISKS_CLIENT (user_data); + queue_changed (client); +} -- 2.7.4