diff --git a/src/gst/gstpipewiredeviceprovider.c b/src/gst/gstpipewiredeviceprovider.c index 4ba265a66..4a52bbdde 100644 --- a/src/gst/gstpipewiredeviceprovider.c +++ b/src/gst/gstpipewiredeviceprovider.c @@ -729,8 +729,16 @@ static void registry_event_global(void *data, uint32_t id, uint32_t permissions, if (!spa_streq(name, "default")) return; + /* PipeWire re-emits the global event for the same id when the client's + * permissions change. Only bind and add the listener once, otherwise we + * would re-append the already-linked metadata_listener hook and corrupt + * the proxy's listener list. */ + if (self->metadata != NULL) + return; + self->metadata = pw_registry_bind(self->registry, id, type, PW_VERSION_METADATA, 0); + self->metadata_id = id; pw_metadata_add_listener(self->metadata, &self->metadata_listener, &metadata_events, self); } @@ -744,6 +752,13 @@ no_mem: static void registry_event_global_remove(void *data, uint32_t id) { + GstPipeWireDeviceProvider *self = data; + + if (self->metadata != NULL && self->metadata_id == id) { + spa_hook_remove(&self->metadata_listener); + pw_proxy_destroy((struct pw_proxy *)self->metadata); + self->metadata = NULL; + } } static const struct pw_registry_events registry_events = { diff --git a/src/gst/gstpipewiredeviceprovider.h b/src/gst/gstpipewiredeviceprovider.h index 82b2a8a11..c74ada091 100644 --- a/src/gst/gstpipewiredeviceprovider.h +++ b/src/gst/gstpipewiredeviceprovider.h @@ -52,6 +52,7 @@ struct _GstPipeWireDeviceProvider { struct spa_hook registry_listener; struct pw_metadata *metadata; + uint32_t metadata_id; struct spa_hook metadata_listener; gchar *default_audio_source_name;