diff --git a/src/client/context.c b/src/client/context.c index 29532c8d6..faedfedb2 100644 --- a/src/client/context.c +++ b/src/client/context.c @@ -35,7 +35,6 @@ static void subscription_cb (PinosSubscribe *subscribe, PinosSubscriptionEvent event, PinosSubscriptionFlags flags, GDBusProxy *object, - GStrv properties, gpointer user_data); enum @@ -247,8 +246,6 @@ pinos_context_class_init (PinosContextClass * klass) * @event: A #PinosSubscriptionEvent * @flags: #PinosSubscriptionFlags indicating the object * @object: the GDBusProxy object - * @properties: extra properties that changed or %NULL when all properties - * are affected (new and remove) * * Notify about a new object that was added/removed/modified. */ @@ -260,11 +257,10 @@ pinos_context_class_init (PinosContextClass * klass) NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 4, + 3, PINOS_TYPE_SUBSCRIPTION_EVENT, PINOS_TYPE_SUBSCRIPTION_FLAGS, - G_TYPE_DBUS_PROXY, - G_TYPE_STRV); + G_TYPE_DBUS_PROXY); } @@ -415,7 +411,6 @@ subscription_cb (PinosSubscribe *subscribe, PinosSubscriptionEvent event, PinosSubscriptionFlags flags, GDBusProxy *object, - GStrv properties, gpointer user_data) { PinosContext *context = user_data; @@ -460,8 +455,7 @@ subscription_cb (PinosSubscribe *subscribe, 0, event, flags, - object, - properties); + object); } diff --git a/src/client/introspect.c b/src/client/introspect.c index f23548df1..705223d0c 100644 --- a/src/client/introspect.c +++ b/src/client/introspect.c @@ -27,45 +27,71 @@ #include "client/private.h" +#define SET_STRING(name, field, idx) \ +G_STMT_START { \ + GVariant *variant; \ + if (!changed || g_hash_table_contains (changed, name)) \ + info->change_mask |= 1 << idx; \ + if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), name))) { \ + info->field = g_variant_get_string (variant, NULL); \ + g_variant_unref (variant); \ + } else { \ + info->field = "Unknown"; \ + } \ +} G_STMT_END + +#define SET_UINT32(name, field, idx, def) \ +G_STMT_START { \ + GVariant *variant; \ + if (!changed || g_hash_table_contains (changed, name)) \ + info->change_mask |= 1 << idx; \ + if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), name))) { \ + info->field = g_variant_get_uint32 (variant); \ + g_variant_unref (variant); \ + } else { \ + info->field = def; \ + } \ +} G_STMT_END + +#define SET_PROPERTIES(name, field, idx) \ +G_STMT_START { \ + if (!changed || g_hash_table_contains (changed, name)) \ + info->change_mask |= 1 << idx; \ + info->field = pinos_properties_from_variant ( \ + g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), name)); \ +} G_STMT_END + +#define SET_BYTES(name, field, idx) \ +G_STMT_START { \ + GVariant *variant; \ + if (!changed || g_hash_table_contains (changed, name)) \ + info->change_mask |= 1 << idx; \ + if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), name))) { \ + gsize len; \ + gchar *bytes = g_variant_dup_string (variant, &len); \ + info->field = g_bytes_new_take (bytes, len +1); \ + g_variant_unref (variant); \ + } else { \ + info->field = NULL; \ + } \ +} G_STMT_END + static void daemon_fill_info (PinosDaemonInfo *info, GDBusProxy *proxy) { - GVariant *variant; + GHashTable *changed = g_object_get_data (G_OBJECT (proxy), "pinos-changed-properties"); info->id = proxy; + info->change_mask = 0; + SET_STRING ("UserName", user_name, 0); + SET_STRING ("HostName", host_name, 1); + SET_STRING ("Version", version, 2); + SET_STRING ("Name", name, 3); + SET_UINT32 ("Cookie", cookie, 4, 0); + SET_PROPERTIES ("Properties", properties, 5); - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "UserName"))) { - info->user_name = g_variant_get_string (variant, NULL); - g_variant_unref (variant); - } else { - info->user_name = "Unknown"; - } - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "HostName"))) { - info->host_name = g_variant_get_string (variant, NULL); - g_variant_unref (variant); - } else { - info->host_name = "Unknown"; - } - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Version"))) { - info->version = g_variant_get_string (variant, NULL); - g_variant_unref (variant); - } else { - info->version = "Unknown"; - } - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Name"))) { - info->name = g_variant_get_string (variant, NULL); - g_variant_unref (variant); - } else { - info->name = "Unknown"; - } - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Cookie"))) { - info->cookie = g_variant_get_uint32 (variant); - g_variant_unref (variant); - } else { - info->cookie = 0; - } - info->properties = pinos_properties_from_variant ( - g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Properties")); + if (changed) + g_hash_table_remove_all (changed); } static void @@ -106,19 +132,15 @@ pinos_context_get_daemon_info (PinosContext *context, static void client_fill_info (PinosClientInfo *info, GDBusProxy *proxy) { - GVariant *variant; + GHashTable *changed = g_object_get_data (G_OBJECT (proxy), "pinos-changed-properties"); info->id = proxy; + info->change_mask = 0; + SET_STRING ("Name", name, 0); + SET_PROPERTIES ("Properties", properties, 1); - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Name"))) { - info->name = g_variant_get_string (variant, NULL); - g_variant_unref (variant); - } else { - info->name = "Unknown"; - } - - info->properties = pinos_properties_from_variant ( - g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Properties")); + if (changed) + g_hash_table_remove_all (changed); } static void @@ -201,37 +223,19 @@ pinos_context_get_client_info_by_id (PinosContext *context, static void source_fill_info (PinosSourceInfo *info, GDBusProxy *proxy) { - GVariant *variant; + GHashTable *changed = g_object_get_data (G_OBJECT (proxy), "pinos-changed-properties"); info->id = proxy; - info->source_path = g_dbus_proxy_get_object_path (proxy); - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Name"))) { - info->name = g_variant_get_string (variant, NULL); - g_variant_unref (variant); - } else { - info->name = "Unknown"; - } + info->change_mask = 0; + SET_STRING ("Name", name, 0); + SET_PROPERTIES ("Properties", properties, 1); + SET_UINT32 ("State", state, 2, PINOS_SOURCE_STATE_ERROR); + SET_BYTES ("PossibleFormats", possible_formats, 3); - info->properties = pinos_properties_from_variant ( - g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Properties")); - - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "State"))) { - info->state = g_variant_get_uint32 (variant); - g_variant_unref (variant); - } else { - info->state = PINOS_SOURCE_STATE_ERROR; - } - - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "PossibleFormats"))) { - gsize len; - gchar *formats = g_variant_dup_string (variant, &len); - info->possible_formats = g_bytes_new_take (formats, len + 1); - g_variant_unref (variant); - } else { - info->possible_formats = NULL; - } + if (changed) + g_hash_table_remove_all (changed); } static void @@ -315,47 +319,20 @@ pinos_context_get_source_info_by_id (PinosContext *context, static void source_output_fill_info (PinosSourceOutputInfo *info, GDBusProxy *proxy) { - GVariant *variant; + GHashTable *changed = g_object_get_data (G_OBJECT (proxy), "pinos-changed-properties"); info->id = proxy; - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Client"))) { - info->client_path = g_variant_get_string (variant, NULL); - g_variant_unref (variant); - } else { - info->client_path = "Unknown"; - } - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Source"))) { - info->source_path = g_variant_get_string (variant, NULL); - g_variant_unref (variant); - } else { - info->source_path = "Unknown"; - } - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "PossibleFormats"))) { - gsize len; - gchar *formats = g_variant_dup_string (variant, &len); - info->possible_formats = g_bytes_new_take (formats, len + 1); - g_variant_unref (variant); - } else { - info->possible_formats = NULL; - } - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "State"))) { - info->state = g_variant_get_uint32 (variant); - g_variant_unref (variant); - } else { - info->state = PINOS_SOURCE_OUTPUT_STATE_ERROR; - } - if ((variant = g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Format"))) { - gsize len; - gchar *format = g_variant_dup_string (variant, &len); - info->format = g_bytes_new_take (format, len + 1); - g_variant_unref (variant); - } else { - info->format = NULL; - } - info->properties = pinos_properties_from_variant ( - g_dbus_proxy_get_cached_property (G_DBUS_PROXY (proxy), "Properties")); + info->change_mask = 0; + SET_STRING ("Client", client_path, 0); + SET_STRING ("Source", source_path, 1); + SET_BYTES ("PossibleFormats", possible_formats, 2); + SET_UINT32 ("State", state, 3, PINOS_SOURCE_OUTPUT_STATE_ERROR); + SET_BYTES ("Format", format, 4); + SET_PROPERTIES ("Properties", properties, 5); + if (changed) + g_hash_table_remove_all (changed); } static void diff --git a/src/client/introspect.h b/src/client/introspect.h index 768191d0b..fca57a7b7 100644 --- a/src/client/introspect.h +++ b/src/client/introspect.h @@ -31,6 +31,7 @@ G_BEGIN_DECLS /** * PinosDaemonInfo: * @id: generic id of the daemon + * @change_mask: bitfield of changed fields since last call * @user_name: name of the user that started the daemon * @host_name: name of the machine the daemon is running on * @version: version of the daemon @@ -43,6 +44,7 @@ G_BEGIN_DECLS */ typedef struct { gpointer id; + guint64 change_mask; const char *user_name; const char *host_name; const char *version; @@ -66,6 +68,7 @@ void pinos_context_get_daemon_info (PinosContext *context, /** * PinosClientInfo: * @id: generic id of the client + * @change_mask: bitfield of changed fields since last call * @name: name of client * @properties: extra properties * @@ -74,6 +77,7 @@ void pinos_context_get_daemon_info (PinosContext *context, */ typedef struct { gpointer id; + guint64 change_mask; const char *name; PinosProperties *properties; } PinosClientInfo; @@ -121,6 +125,7 @@ typedef enum { * PinosSourceInfo: * @id: generic id of the source * @source_path: the unique path of the source, suitable for connecting + * @change_mask: bitfield of changed fields since last call * @name: name the source, suitable for display * @properties: the properties of the source * @state: the current state of the source @@ -132,6 +137,7 @@ typedef enum { typedef struct { gpointer id; const char *source_path; + guint64 change_mask; const char *name; PinosProperties *properties; PinosSourceState state; @@ -183,6 +189,7 @@ typedef enum { /** * PinosSourceOutputInfo: * @id: generic id of the output + * @change_mask: bitfield of changed fields since last call * @client_path: the owner client * @source_path: the source path * @possible_formats: the possible formats @@ -195,6 +202,7 @@ typedef enum { */ typedef struct { gpointer id; + guint64 change_mask; const char *client_path; const char *source_path; GBytes *possible_formats; diff --git a/src/client/stream.c b/src/client/stream.c index bf9ec7417..331bdc4f1 100644 --- a/src/client/stream.c +++ b/src/client/stream.c @@ -179,7 +179,6 @@ subscription_cb (PinosSubscribe *subscribe, PinosSubscriptionEvent event, PinosSubscriptionFlags flags, GDBusProxy *object, - GStrv properties, gpointer user_data) { PinosStream *stream = PINOS_STREAM (user_data); diff --git a/src/client/subscribe.c b/src/client/subscribe.c index 4404c3f56..21b721ae3 100644 --- a/src/client/subscribe.c +++ b/src/client/subscribe.c @@ -92,8 +92,7 @@ subscription_set_state (PinosSubscribe *subscribe, static void notify_event (PinosSubscribe *subscribe, PinosObjectData *data, - PinosSubscriptionEvent event, - GStrv properties) + PinosSubscriptionEvent event) { const gchar *interface_name; PinosSubscriptionFlags flags = 0; @@ -112,7 +111,7 @@ notify_event (PinosSubscribe *subscribe, flags = PINOS_SUBSCRIPTION_FLAG_SOURCE_OUTPUT; } g_signal_emit (subscribe, signals[SIGNAL_SUBSCRIPTION_EVENT], 0, - event, flags, data->proxy, properties); + event, flags, data->proxy); } static void @@ -122,22 +121,26 @@ on_proxy_properties_changed (GDBusProxy *proxy, gpointer user_data) { PinosObjectData *data = user_data; - GPtrArray *ptr; GVariantIter iter; GVariant *value; gchar *key; + GHashTable *props; + + props = g_object_get_data (G_OBJECT (proxy), "pinos-changed-properties"); + if (props == NULL) { + props = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_object_set_data_full (G_OBJECT (proxy), + "pinos-changed-properties", + props, + (GDestroyNotify) g_hash_table_unref); + } - ptr = g_ptr_array_new_with_free_func (g_free); g_variant_iter_init (&iter, changed_properties); while (g_variant_iter_loop (&iter, "{sv}", &key, &value)) { - g_ptr_array_add (ptr, g_strdup (key)); + if (!g_hash_table_contains (props, key)) + g_hash_table_add (props, g_strdup (key)); } - g_ptr_array_add (ptr, NULL); - - notify_event (data->subscribe, data, PINOS_SUBSCRIPTION_EVENT_CHANGE, - (gchar **) ptr->pdata); - - g_ptr_array_free (ptr, TRUE); + notify_event (data->subscribe, data, PINOS_SUBSCRIPTION_EVENT_CHANGE); } static void @@ -158,7 +161,7 @@ remove_data (PinosSubscribe *subscribe, if (data->pending) { data->removed = TRUE; } else { - notify_event (subscribe, data, PINOS_SUBSCRIPTION_EVENT_REMOVE, NULL); + notify_event (subscribe, data, PINOS_SUBSCRIPTION_EVENT_REMOVE); object_data_free (data); } } @@ -204,7 +207,7 @@ on_proxy_created (GObject *source_object, (GCallback) on_proxy_properties_changed, data); - notify_event (subscribe, data, PINOS_SUBSCRIPTION_EVENT_NEW, NULL); + notify_event (subscribe, data, PINOS_SUBSCRIPTION_EVENT_NEW); for (walk = data->tasks; walk; walk = g_list_next (walk)) { GTask *task = walk->data; @@ -651,8 +654,6 @@ pinos_subscribe_class_init (PinosSubscribeClass * klass) * @event: A #PinosSubscriptionEvent * @flags: #PinosSubscriptionFlags indicating the object * @id: the unique and opaque object id - * @properties: extra properties that changed or %NULL when all properties - * are affected (new or remove) * * Notify about a new object that was added/removed/modified. */ @@ -664,11 +665,10 @@ pinos_subscribe_class_init (PinosSubscribeClass * klass) NULL, g_cclosure_marshal_generic, G_TYPE_NONE, - 4, + 3, PINOS_TYPE_SUBSCRIPTION_EVENT, PINOS_TYPE_SUBSCRIPTION_FLAGS, - G_TYPE_POINTER, - G_TYPE_STRV); + G_TYPE_POINTER); } static void diff --git a/src/gst/gstpinosdeviceprovider.c b/src/gst/gstpinosdeviceprovider.c index 0956164dc..1373a1d0e 100644 --- a/src/gst/gstpinosdeviceprovider.c +++ b/src/gst/gstpinosdeviceprovider.c @@ -273,8 +273,7 @@ context_subscribe_cb (PinosContext *context, PinosSubscriptionEvent type, PinosSubscriptionFlags flags, gpointer id, - gpointer user_data, - GStrv properties) + gpointer user_data) { GstPinosDeviceProvider *self = user_data; GstDeviceProvider *provider = user_data; diff --git a/src/tests/test-subscribe.c b/src/tests/test-subscribe.c index 125060809..6922ff6e6 100644 --- a/src/tests/test-subscribe.c +++ b/src/tests/test-subscribe.c @@ -83,18 +83,21 @@ print_properties (PinosProperties *props) static gboolean dump_daemon_info (PinosContext *c, const PinosDaemonInfo *info, gpointer userdata) { - const gchar * const *props = userdata; - if (info == NULL) return FALSE; g_print ("\tid: %p\n", info->id); - g_print ("\tuser-name: \"%s\"\n", info->user_name); - g_print ("\thost-name: \"%s\"\n", info->host_name); - g_print ("\tversion: \"%s\"\n", info->version); - g_print ("\tname: \"%s\"\n", info->name); - g_print ("\tcookie: %d\n", info->cookie); - if (!props || g_strv_contains (props, "Properties")) + if (info->change_mask & (1 << 0)) + g_print ("\tuser-name: \"%s\"\n", info->user_name); + if (info->change_mask & (1 << 1)) + g_print ("\thost-name: \"%s\"\n", info->host_name); + if (info->change_mask & (1 << 2)) + g_print ("\tversion: \"%s\"\n", info->version); + if (info->change_mask & (1 << 3)) + g_print ("\tname: \"%s\"\n", info->name); + if (info->change_mask & (1 << 4)) + g_print ("\tcookie: %d\n", info->cookie); + if (info->change_mask & (1 << 5)) print_properties (info->properties); return TRUE; @@ -103,15 +106,13 @@ dump_daemon_info (PinosContext *c, const PinosDaemonInfo *info, gpointer userdat static gboolean dump_client_info (PinosContext *c, const PinosClientInfo *info, gpointer userdata) { - const gchar * const *props = userdata; - if (info == NULL) return FALSE; g_print ("\tid: %p\n", info->id); - if (!props || g_strv_contains (props, "Name")) + if (info->change_mask & (1 << 0)) g_print ("\tname: \"%s\"\n", info->name); - if (!props || g_strv_contains (props, "Properties")) + if (info->change_mask & (1 << 1)) print_properties (info->properties); return TRUE; @@ -120,21 +121,19 @@ dump_client_info (PinosContext *c, const PinosClientInfo *info, gpointer userdat static gboolean dump_source_info (PinosContext *c, const PinosSourceInfo *info, gpointer userdata) { - const gchar * const *props = userdata; - if (info == NULL) return FALSE; g_print ("\tid: %p\n", info->id); - if (!props || g_strv_contains (props, "Source")) + if (info->change_mask & (1 << 0)) g_print ("\tsource-path: \"%s\"\n", info->source_path); - if (!props || g_strv_contains (props, "Name")) + if (info->change_mask & (1 << 1)) g_print ("\tname: \"%s\"\n", info->name); - if (!props || g_strv_contains (props, "State")) + if (info->change_mask & (1 << 2)) g_print ("\tstate: %d\n", info->state); - if (!props || g_strv_contains (props, "PossibleFormats")) + if (info->change_mask & (1 << 3)) print_formats ("possible formats", info->possible_formats); - if (!props || g_strv_contains (props, "Properties")) + if (info->change_mask & (1 << 4)) print_properties (info->properties); return TRUE; @@ -143,38 +142,35 @@ dump_source_info (PinosContext *c, const PinosSourceInfo *info, gpointer userdat static gboolean dump_source_output_info (PinosContext *c, const PinosSourceOutputInfo *info, gpointer userdata) { - const gchar * const *props = userdata; - if (info == NULL) return FALSE; g_print ("\tid: %p\n", info->id); - if (!props || g_strv_contains (props, "Client")) + if (info->change_mask & (1 << 0)) g_print ("\tclient-path: \"%s\"\n", info->client_path); - if (!props || g_strv_contains (props, "Source")) + if (info->change_mask & (1 << 1)) g_print ("\tsource-path: \"%s\"\n", info->source_path); - if (!props || g_strv_contains (props, "PossibleFormats")) + if (info->change_mask & (1 << 2)) print_formats ("possible-formats", info->possible_formats); - if (!props || g_strv_contains (props, "State")) + if (info->change_mask & (1 << 3)) g_print ("\tstate: \"%d\"\n", info->state); - if (!props || g_strv_contains (props, "Format")) + if (info->change_mask & (1 << 4)) print_formats ("format", info->format); - if (!props || g_strv_contains (props, "Properties")) + if (info->change_mask & (1 << 5)) print_properties (info->properties); return TRUE; } static void -dump_object (PinosContext *context, GDBusProxy *proxy, PinosSubscriptionFlags flags, - GStrv properties) +dump_object (PinosContext *context, GDBusProxy *proxy, PinosSubscriptionFlags flags) { if (flags & PINOS_SUBSCRIPTION_FLAG_DAEMON) { pinos_context_get_daemon_info (context, PINOS_DAEMON_INFO_FLAGS_NONE, dump_daemon_info, NULL, - properties); + NULL); } else if (flags & PINOS_SUBSCRIPTION_FLAG_CLIENT) { pinos_context_get_client_info_by_id (context, @@ -182,7 +178,7 @@ dump_object (PinosContext *context, GDBusProxy *proxy, PinosSubscriptionFlags fl PINOS_CLIENT_INFO_FLAGS_NONE, dump_client_info, NULL, - properties); + NULL); } else if (flags & PINOS_SUBSCRIPTION_FLAG_SOURCE) { pinos_context_get_source_info_by_id (context, @@ -190,7 +186,7 @@ dump_object (PinosContext *context, GDBusProxy *proxy, PinosSubscriptionFlags fl PINOS_SOURCE_INFO_FLAGS_FORMATS, dump_source_info, NULL, - properties); + NULL); } else if (flags & PINOS_SUBSCRIPTION_FLAG_SOURCE_OUTPUT) { pinos_context_get_source_output_info_by_id (context, @@ -198,7 +194,7 @@ dump_object (PinosContext *context, GDBusProxy *proxy, PinosSubscriptionFlags fl PINOS_SOURCE_OUTPUT_INFO_FLAGS_NONE, dump_source_output_info, NULL, - properties); + NULL); } } @@ -207,18 +203,17 @@ subscription_cb (PinosContext *context, PinosSubscriptionEvent type, PinosSubscriptionFlags flags, gpointer id, - GStrv properties, gpointer user_data) { switch (type) { case PINOS_SUBSCRIPTION_EVENT_NEW: g_print ("added: %s\n", g_dbus_proxy_get_object_path (id)); - dump_object (context, G_DBUS_PROXY (id), flags, properties); + dump_object (context, G_DBUS_PROXY (id), flags); break; case PINOS_SUBSCRIPTION_EVENT_CHANGE: g_print ("changed: %s\n", g_dbus_proxy_get_object_path (id)); - dump_object (context, G_DBUS_PROXY (id), flags, properties); + dump_object (context, G_DBUS_PROXY (id), flags); break; case PINOS_SUBSCRIPTION_EVENT_REMOVE: