Skip to content
Snippets Groups Projects
Commit 184b293b authored by Julian Bouzas's avatar Julian Bouzas
Browse files

dsp: add support for convert mode

parent ebe22c34
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
......@@ -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);
......
......@@ -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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment