diff --git a/modules/module-pw-audio-softdsp-endpoint.c b/modules/module-pw-audio-softdsp-endpoint.c index e7dc32ee972d851d13634e0a1d9212e73b91f28c..496e130029673dcdf7c291393cc65e4098e57d6e 100644 --- a/modules/module-pw-audio-softdsp-endpoint.c +++ b/modules/module-pw-audio-softdsp-endpoint.c @@ -155,7 +155,7 @@ on_audio_dsp_converter_created(GObject *initable, GAsyncResult *res, g_variant_iter_init (&iter, self->streams); for (i = 0; g_variant_iter_next (&iter, "&s", &stream); i++) { wp_pw_audio_dsp_new (WP_ENDPOINT(self), i, stream, self->direction, - target, format, on_audio_dsp_stream_created, self); + FALSE, target, format, on_audio_dsp_stream_created, self); /* Register the stream */ g_variant_dict_init (&d, NULL); @@ -197,7 +197,8 @@ on_proxy_node_created(GObject *initable, GAsyncResult *res, gpointer data) /* TODO: For now we create convert as a stream because convert mode does not * generate any ports, not sure why */ wp_pw_audio_dsp_new (WP_ENDPOINT(self), WP_STREAM_ID_NONE, "master", - self->direction, target, format, on_audio_dsp_converter_created, self); + self->direction, TRUE, target, format, on_audio_dsp_converter_created, + self); } static void diff --git a/modules/module-pw-audio-softdsp-endpoint/dsp.c b/modules/module-pw-audio-softdsp-endpoint/dsp.c index 3dc6f4efb6b9b238f49c23c792afc8a3823b2e4a..0c0f6b18915a270e699d29f3ba9027f1b9dda812 100644 --- a/modules/module-pw-audio-softdsp-endpoint/dsp.c +++ b/modules/module-pw-audio-softdsp-endpoint/dsp.c @@ -22,6 +22,7 @@ enum { PROP_ID, PROP_NAME, PROP_DIRECTION, + PROP_CONVERT, PROP_TARGET, PROP_FORMAT, }; @@ -42,17 +43,18 @@ struct _WpPwAudioDsp /* The remote pipewire */ WpRemotePipewire *remote_pipewire; - /* Handler */ - gulong proxy_done_handler_id; - /* Props */ GWeakRef endpoint; guint id; gchar *name; enum pw_direction direction; + gboolean convert; const struct pw_node_info *target; const struct spa_audio_info_raw *format; + /* All ports handled by the port added callback */ + GHashTable *handled_ports; + /* Proxies */ WpProxyNode *proxy; GPtrArray *port_proxies; @@ -137,23 +139,6 @@ register_controls (WpPwAudioDsp * self) wp_endpoint_register_control (ep, g_variant_dict_end (&d)); } -static void -on_audio_dsp_done(WpProxy *proxy, gpointer data) -{ - WpPwAudioDsp *self = data; - - /* Don't do anything if the endpoint has already been initialized */ - if (!self->init_task) - return; - - /* Register the controls */ - register_controls (self); - - /* Finish the creation of the audio dsp */ - g_task_return_boolean (self->init_task, TRUE); - g_clear_object(&self->init_task); -} - static void on_audio_dsp_port_created(GObject *initable, GAsyncResult *res, gpointer data) @@ -168,28 +153,24 @@ on_audio_dsp_port_created(GObject *initable, GAsyncResult *res, /* Add the proxy port to the array */ g_return_if_fail (self->port_proxies); g_ptr_array_add(self->port_proxies, port_proxy); - - /* Register a callback to know when all the dsp ports have been emitted */ - if (!self->proxy_done_handler_id) { - self->proxy_done_handler_id = g_signal_connect_object(self->proxy, - "done", (GCallback)on_audio_dsp_done, self, 0); - wp_proxy_sync (WP_PROXY(self->proxy)); - } } static void -on_audio_dsp_port_added(WpRemotePipewire *rp, guint id, guint parent_id, - gconstpointer p, gpointer d) +handled_ports_foreach_func (gpointer key, gpointer value, gpointer data) { - WpPwAudioDsp *self = d; + WpPwAudioDsp *self = data; const struct pw_node_info *dsp_info = NULL; struct pw_port_proxy *port_proxy = NULL; + const guint id = GPOINTER_TO_INT (key); + const guint parent_id = GPOINTER_TO_INT (value); - /* Make sure the port belongs to this audio dsp */ - if (!self->proxy) - return; - dsp_info = wp_proxy_node_get_info (self->proxy); - if (!dsp_info || dsp_info->id != parent_id) + /* Get the dsp info */ + g_return_if_fail (self->proxy); + dsp_info = wp_proxy_node_get_info(self->proxy); + g_return_if_fail (dsp_info); + + /* Skip ports that are not owned by this DSP */ + if (dsp_info->id != parent_id) return; /* Create the audio dsp port async */ @@ -199,6 +180,44 @@ on_audio_dsp_port_added(WpRemotePipewire *rp, guint id, guint parent_id, wp_proxy_port_new(id, port_proxy, on_audio_dsp_port_created, self); } +static void +on_audio_dsp_done(WpProxy *proxy, gpointer data) +{ + WpPwAudioDsp *self = data; + + g_return_if_fail (self->proxy); + + /* Don't do anything if the endpoint has already been initialized */ + if (!self->init_task) + return; + + /* Create the proxis and sync to trigger this function again */ + if (self->port_proxies->len == 0) { + g_hash_table_foreach (self->handled_ports, handled_ports_foreach_func, self); + wp_proxy_sync (WP_PROXY(self->proxy)); + return; + } + + /* Register the controls */ + register_controls (self); + + /* Finish the creation of the audio dsp */ + g_task_return_boolean (self->init_task, TRUE); + g_clear_object(&self->init_task); +} + +static void +on_audio_dsp_port_added(WpRemotePipewire *rp, guint id, guint parent_id, + gconstpointer p, gpointer d) +{ + WpPwAudioDsp *self = d; + + /* Add the port to the map if it is not already there */ + if (!g_hash_table_contains (self->handled_ports, GUINT_TO_POINTER (id))) + g_hash_table_insert (self->handled_ports, GUINT_TO_POINTER(id), + GUINT_TO_POINTER(parent_id)); +} + static void on_audio_dsp_running(WpPwAudioDsp *self) { @@ -348,18 +367,25 @@ on_audio_dsp_proxy_created(GObject *initable, GAsyncResult *res, /* Emit the props param */ pw_node_proxy_enum_params (pw_proxy, 0, SPA_PARAM_Props, 0, -1, NULL); - /* Get the port format */ - g_return_if_fail (self->format); - format = *self->format; - - /* Emit the ports */ - spa_pod_builder_init(&pod_builder, buf, sizeof(buf)); - param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &format); - param = spa_pod_builder_add_object(&pod_builder, - SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile, - SPA_PARAM_PROFILE_direction, SPA_POD_Id(pw_direction_reverse(self->direction)), - SPA_PARAM_PROFILE_format, SPA_POD_Pod(param)); - pw_node_proxy_set_param(pw_proxy, SPA_PARAM_Profile, 0, param); + if (!self->convert) { + /* Get the port format */ + g_return_if_fail (self->format); + format = *self->format; + + /* Emit the ports */ + spa_pod_builder_init(&pod_builder, buf, sizeof(buf)); + param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &format); + param = spa_pod_builder_add_object(&pod_builder, + SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile, + SPA_PARAM_PROFILE_direction, SPA_POD_Id(pw_direction_reverse(self->direction)), + SPA_PARAM_PROFILE_format, SPA_POD_Pod(param)); + pw_node_proxy_set_param(pw_proxy, SPA_PARAM_Profile, 0, param); + } + + /* Register a callback to know when all the dsp ports have been emitted */ + g_signal_connect_object(self->proxy, "done", (GCallback)on_audio_dsp_done, + self, 0); + wp_proxy_sync (WP_PROXY(self->proxy)); } static void @@ -374,6 +400,10 @@ wp_pw_audio_dsp_finalize (GObject * object) /* Destroy the init task */ g_clear_object(&self->init_task); + /* Destroy the handled ports map */ + g_hash_table_unref(self->handled_ports); + self->handled_ports = NULL; + /* Destroy the proxy dsp */ g_clear_object(&self->proxy); @@ -405,6 +435,9 @@ wp_pw_audio_dsp_set_property (GObject * object, guint property_id, case PROP_DIRECTION: self->direction = g_value_get_uint(value); break; + case PROP_CONVERT: + self->convert = g_value_get_boolean(value); + break; case PROP_TARGET: self->target = g_value_get_pointer(value); break; @@ -436,6 +469,9 @@ wp_pw_audio_dsp_get_property (GObject * object, guint property_id, case PROP_DIRECTION: g_value_set_uint (value, self->direction); break; + case PROP_CONVERT: + g_value_set_boolean (value, self->convert); + break; case PROP_TARGET: g_value_set_pointer (value, (gpointer)self->target); break; @@ -468,6 +504,9 @@ wp_pw_audio_dsp_init_async (GAsyncInitable *initable, int io_priority, /* Create the async task */ self->init_task = g_task_new (initable, cancellable, callback, data); + /* Init the handled ports map */ + self->handled_ports = g_hash_table_new (g_direct_hash, g_direct_equal); + /* Init the list of port proxies */ self->port_proxies = g_ptr_array_new_full(4, (GDestroyNotify)g_object_unref); @@ -482,6 +521,7 @@ wp_pw_audio_dsp_init_async (GAsyncInitable *initable, int io_priority, /* Set the properties */ pw_properties_set(props, "audio-dsp.name", self->name ? self->name : "Audio-DSP"); + pw_properties_set(props, "audio-dsp.mode", self->convert ? "convert" : NULL); pw_properties_setf(props, "audio-dsp.direction", "%d", self->direction); pw_properties_setf(props, "audio-dsp.maxbuffer", "%ld", MAX_QUANTUM_SIZE * sizeof(float)); @@ -547,6 +587,10 @@ wp_pw_audio_dsp_class_init (WpPwAudioDspClass * klass) g_param_spec_uint ("direction", "direction", "The direction of the audio DSP", 0, 1, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_CONVERT, + g_param_spec_boolean ("convert", "convert", + "Whether the DSP is only in convert mode or not", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_TARGET, g_param_spec_pointer ("target", "target", "The target node info of the audio DSP", @@ -559,8 +603,9 @@ wp_pw_audio_dsp_class_init (WpPwAudioDspClass * klass) void wp_pw_audio_dsp_new (WpEndpoint *endpoint, guint id, const char *name, - enum pw_direction direction, const struct pw_node_info *target, - const struct spa_audio_info_raw *format, GAsyncReadyCallback callback, + enum pw_direction direction, gboolean convert, + const struct pw_node_info *target, const struct spa_audio_info_raw *format, + GAsyncReadyCallback callback, gpointer user_data) { g_async_initable_new_async ( @@ -570,6 +615,7 @@ wp_pw_audio_dsp_new (WpEndpoint *endpoint, guint id, const char *name, "id", id, "name", name, "direction", direction, + "convert", convert, "target", target, "format", format, NULL); diff --git a/modules/module-pw-audio-softdsp-endpoint/dsp.h b/modules/module-pw-audio-softdsp-endpoint/dsp.h index 484158448b67f98bc3b8e05defcb1a375a060478..5d7c6f44cebfb5ee318058983a24f5d0b452f12d 100644 --- a/modules/module-pw-audio-softdsp-endpoint/dsp.h +++ b/modules/module-pw-audio-softdsp-endpoint/dsp.h @@ -19,9 +19,9 @@ guint wp_pw_audio_dsp_id_encode (guint stream_id, guint control_id); void wp_pw_audio_dsp_id_decode (guint id, guint *stream_id, guint *control_id); void wp_pw_audio_dsp_new (WpEndpoint *endpoint, guint id, const char *name, - enum pw_direction direction, const struct pw_node_info *target, - const struct spa_audio_info_raw *format, GAsyncReadyCallback callback, - gpointer user_data); + enum pw_direction direction, gboolean convert, + const struct pw_node_info *target, const struct spa_audio_info_raw *format, + GAsyncReadyCallback callback, gpointer user_data); WpPwAudioDsp * wp_pw_audio_dsp_new_finish (GObject *initable, GAsyncResult *res, GError **error);