diff --git a/modules/module-standard-event-source.c b/modules/module-standard-event-source.c index e23696bc..e0f5d34b 100644 --- a/modules/module-standard-event-source.c +++ b/modules/module-standard-event-source.c @@ -31,6 +31,7 @@ typedef enum { OBJECT_TYPE_CLIENT, OBJECT_TYPE_DEVICE, OBJECT_TYPE_METADATA, + OBJECT_TYPE_COLLECTION, N_OBJECT_TYPES, OBJECT_TYPE_INVALID = N_OBJECT_TYPES } ObjectType; @@ -65,6 +66,7 @@ rescan_context_get_type (void) struct _WpStandardEventSource { WpPlugin parent; + WpObjectManager *globals_om; WpObjectManager *oms[N_OBJECT_TYPES]; WpEventHook *rescan_done_hook; gboolean rescan_scheduled[N_RESCAN_CONTEXTS]; @@ -93,6 +95,7 @@ object_type_to_gtype (ObjectType type) case OBJECT_TYPE_CLIENT: return WP_TYPE_CLIENT; case OBJECT_TYPE_DEVICE: return WP_TYPE_DEVICE; case OBJECT_TYPE_METADATA: return WP_TYPE_METADATA; + case OBJECT_TYPE_COLLECTION: return WP_TYPE_COLLECTION; default: g_assert_not_reached (); } @@ -115,6 +118,8 @@ type_str_to_object_type (const gchar * type_str) return OBJECT_TYPE_DEVICE; else if (!g_strcmp0 (type_str, "metadata")) return OBJECT_TYPE_METADATA; + else if (!g_strcmp0 (type_str, "collection")) + return OBJECT_TYPE_COLLECTION; else return OBJECT_TYPE_INVALID; } @@ -148,6 +153,8 @@ get_object_type (gpointer obj, WpProperties **properties) return "device"; else if (WP_IS_METADATA (obj)) return "metadata"; + else if (WP_IS_COLLECTION (obj)) + return "collection"; wp_debug_object (obj, "Unknown global proxy type"); return G_OBJECT_TYPE_NAME (obj); @@ -324,6 +331,50 @@ on_metadata_changed (WpMetadata *obj, guint32 subject, wp_standard_event_source_push_event (self, "changed", obj, properties); } +static void +on_global_collected (WpCollection *obj, guint32 global_id, + WpStandardEventSource *self) +{ + g_autoptr (WpGlobalProxy) global = NULL; + const gchar *collection_name = NULL; + g_autoptr (WpProperties) properties = NULL; + + global = wp_object_manager_lookup (self->globals_om, WP_TYPE_GLOBAL_PROXY, + WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", global_id, NULL); + if (!global) { + wp_info_object (self, "could not find collected global %u", global_id); + return; + } + + collection_name = wp_collection_get_name (obj); + + properties = wp_properties_new_empty (); + wp_properties_set (properties, "event.subject.collection", collection_name); + wp_standard_event_source_push_event (self, "collected", global, properties); +} + +static void +on_global_dropped (WpCollection *obj, guint32 global_id, + WpStandardEventSource *self) +{ + g_autoptr (WpGlobalProxy) global = NULL; + const gchar *collection_name = NULL; + g_autoptr (WpProperties) properties = NULL; + + global = wp_object_manager_lookup (self->globals_om, WP_TYPE_GLOBAL_PROXY, + WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", global_id, NULL); + if (!global) { + wp_info_object (self, "could not find dropped global %u", global_id); + return; + } + + collection_name = wp_collection_get_name (obj); + + properties = wp_properties_new_empty (); + wp_properties_set (properties, "event.subject.collection", collection_name); + wp_standard_event_source_push_event (self, "dropped", global, properties); +} + static void on_params_changed (WpPipewireObject *obj, const gchar *id, WpStandardEventSource *self) @@ -368,6 +419,12 @@ on_object_added (WpObjectManager *om, WpObject *obj, WpStandardEventSource *self g_signal_connect_object (obj, "changed", G_CALLBACK (on_metadata_changed), self, 0); } + else if (WP_IS_COLLECTION (obj)) { + g_signal_connect_object (obj, "global-collected", + G_CALLBACK (on_global_collected), self, 0); + g_signal_connect_object (obj, "global-dropped", + G_CALLBACK (on_global_dropped), self, 0); + } } static void @@ -383,6 +440,29 @@ on_om_installed (WpObjectManager * om, WpStandardEventSource * self) wp_object_update_features (WP_OBJECT (self), WP_PLUGIN_FEATURE_ENABLED, 0); } +static void +on_global_om_installed (WpObjectManager * om, WpStandardEventSource * self) +{ + g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self)); + + /* install object specific object managers */ + self->n_oms_installed = 0; + for (gint i = 0; i < N_OBJECT_TYPES; i++) { + GType gtype = object_type_to_gtype (i); + self->oms[i] = wp_object_manager_new (); + wp_object_manager_add_interest (self->oms[i], gtype, NULL); + wp_object_manager_request_object_features (self->oms[i], + gtype, WP_OBJECT_FEATURES_ALL); + g_signal_connect_object (self->oms[i], "object-added", + G_CALLBACK (on_object_added), self, 0); + g_signal_connect_object (self->oms[i], "object-removed", + G_CALLBACK (on_object_removed), self, 0); + g_signal_connect_object (self->oms[i], "installed", + G_CALLBACK (on_om_installed), self, 0); + wp_core_install_object_manager (core, self->oms[i]); + } +} + static void on_rescan_done (WpEvent * event, WpStandardEventSource * self) { @@ -408,22 +488,14 @@ wp_standard_event_source_enable (WpPlugin * plugin, WpTransition * transition) wp_event_dispatcher_get_instance (core); g_return_if_fail (dispatcher); - /* install object managers */ - self->n_oms_installed = 0; - for (gint i = 0; i < N_OBJECT_TYPES; i++) { - GType gtype = object_type_to_gtype (i); - self->oms[i] = wp_object_manager_new (); - wp_object_manager_add_interest (self->oms[i], gtype, NULL); - wp_object_manager_request_object_features (self->oms[i], - gtype, WP_OBJECT_FEATURES_ALL); - g_signal_connect_object (self->oms[i], "object-added", - G_CALLBACK (on_object_added), self, 0); - g_signal_connect_object (self->oms[i], "object-removed", - G_CALLBACK (on_object_removed), self, 0); - g_signal_connect_object (self->oms[i], "installed", - G_CALLBACK (on_om_installed), self, 0); - wp_core_install_object_manager (core, self->oms[i]); - } + /* Install global object manager */ + self->globals_om = wp_object_manager_new (); + wp_object_manager_add_interest (self->globals_om, WP_TYPE_GLOBAL_PROXY, NULL); + wp_object_manager_request_object_features (self->globals_om, + WP_TYPE_GLOBAL_PROXY, WP_PIPEWIRE_OBJECT_FEATURES_MINIMAL); + g_signal_connect_object (self->globals_om, "installed", + G_CALLBACK (on_global_om_installed), self, 0); + wp_core_install_object_manager (core, self->globals_om); /* install hook to restore the rescan_scheduled state just before rescanning */ self->rescan_done_hook = wp_simple_event_hook_new ( @@ -446,6 +518,7 @@ wp_standard_event_source_disable (WpPlugin * plugin) for (gint i = 0; i < N_OBJECT_TYPES; i++) g_clear_object (&self->oms[i]); + g_clear_object (&self->globals_om); if (dispatcher) wp_event_dispatcher_unregister_hook (dispatcher, self->rescan_done_hook);