diff --git a/modules/module-pipewire.c b/modules/module-pipewire.c index b7a9ebd882c58f53cb433cfc27f8ca93e4910ffa..2213b899e2ab6a9a33c421dde3e664ecd225e216 100644 --- a/modules/module-pipewire.c +++ b/modules/module-pipewire.c @@ -36,8 +36,79 @@ struct module_data struct pw_registry_proxy *registry_proxy; struct spa_hook registry_listener; + + struct pw_core_proxy *core_proxy; + struct spa_hook core_listener; + GQueue *done_queue; +}; + + +typedef void (*WpDoneCallback)(gpointer, gpointer); + +struct done_data +{ + WpDoneCallback callback; + gpointer data; + GDestroyNotify data_destroy; }; +static void +done_data_destroy(gpointer p) +{ + struct done_data *dd = p; + if (dd->data_destroy) { + dd->data_destroy(dd->data); + dd->data = NULL; + } + g_slice_free (struct done_data, dd); +} + +static void +sync_core_with_callback(struct module_data* impl, WpDoneCallback callback, + gpointer data, GDestroyNotify data_destroy) +{ + struct done_data *dd = g_new0(struct done_data, 1); + + /* Set the data */ + dd->callback = callback; + dd->data = data; + dd->data_destroy = data_destroy; + + /* Add the data to the queue */ + g_queue_push_tail (impl->done_queue, dd); + + /* Sync the core */ + pw_core_proxy_sync(impl->core_proxy, 0, 0); +} + +static void +core_done(void *d, uint32_t id, int seq) +{ + struct module_data * impl = d; + struct done_data * dd = NULL; + + /* Process all the done_data queue */ + while ((dd = g_queue_pop_head(impl->done_queue))) { + if (dd->callback) + dd->callback(impl, dd->data); + done_data_destroy(dd); + } +} + +static const struct pw_core_proxy_events core_events = { + PW_VERSION_CORE_EVENTS, + .done = core_done +}; + +static void +register_endpoint (struct module_data* data, WpEndpoint *ep) +{ + g_autoptr (WpCore) core = NULL; + core = wp_module_get_core (data->module); + g_return_if_fail (core != NULL); + wp_endpoint_register (ep, core); +} + static void registry_global (void * d, uint32_t id, uint32_t parent_id, uint32_t permissions, uint32_t type, uint32_t version, @@ -105,7 +176,8 @@ registry_global (void * d, uint32_t id, uint32_t parent_id, endpoint = wp_factory_make (core, "pipewire-simple-endpoint", WP_TYPE_ENDPOINT, endpoint_props); - wp_endpoint_register (endpoint, core); + sync_core_with_callback (data, (WpDoneCallback) register_endpoint, + g_steal_pointer (&endpoint), g_object_unref); } } @@ -127,7 +199,9 @@ on_remote_state_changed (void *d, enum pw_remote_state old_state, switch (new_state) { case PW_REMOTE_STATE_CONNECTED: - core_proxy = pw_remote_get_core_proxy (data->remote); + core_proxy = data->core_proxy = pw_remote_get_core_proxy (data->remote); + pw_core_proxy_add_listener(data->core_proxy, &data->core_listener, + &core_events, data); data->registry_proxy = pw_core_proxy_get_registry (core_proxy, PW_TYPE_INTERFACE_Registry, PW_VERSION_REGISTRY, 0); pw_registry_proxy_add_listener(data->registry_proxy, @@ -174,6 +248,7 @@ module_destroy (gpointer d) { struct module_data *data = d; + g_queue_free_full(data->done_queue, done_data_destroy); pw_remote_destroy (data->remote); pw_core_destroy (data->core); g_slice_free (struct module_data, data); @@ -189,6 +264,7 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args) data = g_slice_new0 (struct module_data); data->module = module; + data->done_queue = g_queue_new(); wp_module_set_destroy_callback (module, module_destroy, data); source = wp_loop_source_new ();