m-standard-event-source: Emit '*-collected' and '*-dropped' events

These events are emitted when a global was collected into a collection or
dropped from a collection respectively.
This commit is contained in:
Julian Bouzas 2026-04-24 09:09:01 -04:00
parent bfdec9e653
commit 35cd7b5c5f

View file

@ -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);