dsp: add support for convert mode
This commit is contained in:
@@ -155,7 +155,7 @@ on_audio_dsp_converter_created(GObject *initable, GAsyncResult *res,
|
|||||||
g_variant_iter_init (&iter, self->streams);
|
g_variant_iter_init (&iter, self->streams);
|
||||||
for (i = 0; g_variant_iter_next (&iter, "&s", &stream); i++) {
|
for (i = 0; g_variant_iter_next (&iter, "&s", &stream); i++) {
|
||||||
wp_pw_audio_dsp_new (WP_ENDPOINT(self), i, stream, self->direction,
|
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 */
|
/* Register the stream */
|
||||||
g_variant_dict_init (&d, NULL);
|
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
|
/* TODO: For now we create convert as a stream because convert mode does not
|
||||||
* generate any ports, not sure why */
|
* generate any ports, not sure why */
|
||||||
wp_pw_audio_dsp_new (WP_ENDPOINT(self), WP_STREAM_ID_NONE, "master",
|
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
|
static void
|
||||||
|
@@ -22,6 +22,7 @@ enum {
|
|||||||
PROP_ID,
|
PROP_ID,
|
||||||
PROP_NAME,
|
PROP_NAME,
|
||||||
PROP_DIRECTION,
|
PROP_DIRECTION,
|
||||||
|
PROP_CONVERT,
|
||||||
PROP_TARGET,
|
PROP_TARGET,
|
||||||
PROP_FORMAT,
|
PROP_FORMAT,
|
||||||
};
|
};
|
||||||
@@ -42,17 +43,18 @@ struct _WpPwAudioDsp
|
|||||||
/* The remote pipewire */
|
/* The remote pipewire */
|
||||||
WpRemotePipewire *remote_pipewire;
|
WpRemotePipewire *remote_pipewire;
|
||||||
|
|
||||||
/* Handler */
|
|
||||||
gulong proxy_done_handler_id;
|
|
||||||
|
|
||||||
/* Props */
|
/* Props */
|
||||||
GWeakRef endpoint;
|
GWeakRef endpoint;
|
||||||
guint id;
|
guint id;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
enum pw_direction direction;
|
enum pw_direction direction;
|
||||||
|
gboolean convert;
|
||||||
const struct pw_node_info *target;
|
const struct pw_node_info *target;
|
||||||
const struct spa_audio_info_raw *format;
|
const struct spa_audio_info_raw *format;
|
||||||
|
|
||||||
|
/* All ports handled by the port added callback */
|
||||||
|
GHashTable *handled_ports;
|
||||||
|
|
||||||
/* Proxies */
|
/* Proxies */
|
||||||
WpProxyNode *proxy;
|
WpProxyNode *proxy;
|
||||||
GPtrArray *port_proxies;
|
GPtrArray *port_proxies;
|
||||||
@@ -137,23 +139,6 @@ register_controls (WpPwAudioDsp * self)
|
|||||||
wp_endpoint_register_control (ep, g_variant_dict_end (&d));
|
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
|
static void
|
||||||
on_audio_dsp_port_created(GObject *initable, GAsyncResult *res,
|
on_audio_dsp_port_created(GObject *initable, GAsyncResult *res,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
@@ -168,28 +153,24 @@ on_audio_dsp_port_created(GObject *initable, GAsyncResult *res,
|
|||||||
/* Add the proxy port to the array */
|
/* Add the proxy port to the array */
|
||||||
g_return_if_fail (self->port_proxies);
|
g_return_if_fail (self->port_proxies);
|
||||||
g_ptr_array_add(self->port_proxies, port_proxy);
|
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
|
static void
|
||||||
on_audio_dsp_port_added(WpRemotePipewire *rp, guint id, guint parent_id,
|
handled_ports_foreach_func (gpointer key, gpointer value, gpointer data)
|
||||||
gconstpointer p, gpointer d)
|
|
||||||
{
|
{
|
||||||
WpPwAudioDsp *self = d;
|
WpPwAudioDsp *self = data;
|
||||||
const struct pw_node_info *dsp_info = NULL;
|
const struct pw_node_info *dsp_info = NULL;
|
||||||
struct pw_port_proxy *port_proxy = 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 */
|
/* Get the dsp info */
|
||||||
if (!self->proxy)
|
g_return_if_fail (self->proxy);
|
||||||
return;
|
dsp_info = wp_proxy_node_get_info(self->proxy);
|
||||||
dsp_info = wp_proxy_node_get_info (self->proxy);
|
g_return_if_fail (dsp_info);
|
||||||
if (!dsp_info || dsp_info->id != parent_id)
|
|
||||||
|
/* Skip ports that are not owned by this DSP */
|
||||||
|
if (dsp_info->id != parent_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Create the audio dsp port async */
|
/* 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);
|
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
|
static void
|
||||||
on_audio_dsp_running(WpPwAudioDsp *self)
|
on_audio_dsp_running(WpPwAudioDsp *self)
|
||||||
{
|
{
|
||||||
@@ -348,6 +367,7 @@ on_audio_dsp_proxy_created(GObject *initable, GAsyncResult *res,
|
|||||||
/* Emit the props param */
|
/* Emit the props param */
|
||||||
pw_node_proxy_enum_params (pw_proxy, 0, SPA_PARAM_Props, 0, -1, NULL);
|
pw_node_proxy_enum_params (pw_proxy, 0, SPA_PARAM_Props, 0, -1, NULL);
|
||||||
|
|
||||||
|
if (!self->convert) {
|
||||||
/* Get the port format */
|
/* Get the port format */
|
||||||
g_return_if_fail (self->format);
|
g_return_if_fail (self->format);
|
||||||
format = *self->format;
|
format = *self->format;
|
||||||
@@ -360,6 +380,12 @@ on_audio_dsp_proxy_created(GObject *initable, GAsyncResult *res,
|
|||||||
SPA_PARAM_PROFILE_direction, SPA_POD_Id(pw_direction_reverse(self->direction)),
|
SPA_PARAM_PROFILE_direction, SPA_POD_Id(pw_direction_reverse(self->direction)),
|
||||||
SPA_PARAM_PROFILE_format, SPA_POD_Pod(param));
|
SPA_PARAM_PROFILE_format, SPA_POD_Pod(param));
|
||||||
pw_node_proxy_set_param(pw_proxy, SPA_PARAM_Profile, 0, 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
|
static void
|
||||||
@@ -374,6 +400,10 @@ wp_pw_audio_dsp_finalize (GObject * object)
|
|||||||
/* Destroy the init task */
|
/* Destroy the init task */
|
||||||
g_clear_object(&self->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 */
|
/* Destroy the proxy dsp */
|
||||||
g_clear_object(&self->proxy);
|
g_clear_object(&self->proxy);
|
||||||
|
|
||||||
@@ -405,6 +435,9 @@ wp_pw_audio_dsp_set_property (GObject * object, guint property_id,
|
|||||||
case PROP_DIRECTION:
|
case PROP_DIRECTION:
|
||||||
self->direction = g_value_get_uint(value);
|
self->direction = g_value_get_uint(value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CONVERT:
|
||||||
|
self->convert = g_value_get_boolean(value);
|
||||||
|
break;
|
||||||
case PROP_TARGET:
|
case PROP_TARGET:
|
||||||
self->target = g_value_get_pointer(value);
|
self->target = g_value_get_pointer(value);
|
||||||
break;
|
break;
|
||||||
@@ -436,6 +469,9 @@ wp_pw_audio_dsp_get_property (GObject * object, guint property_id,
|
|||||||
case PROP_DIRECTION:
|
case PROP_DIRECTION:
|
||||||
g_value_set_uint (value, self->direction);
|
g_value_set_uint (value, self->direction);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CONVERT:
|
||||||
|
g_value_set_boolean (value, self->convert);
|
||||||
|
break;
|
||||||
case PROP_TARGET:
|
case PROP_TARGET:
|
||||||
g_value_set_pointer (value, (gpointer)self->target);
|
g_value_set_pointer (value, (gpointer)self->target);
|
||||||
break;
|
break;
|
||||||
@@ -468,6 +504,9 @@ wp_pw_audio_dsp_init_async (GAsyncInitable *initable, int io_priority,
|
|||||||
/* Create the async task */
|
/* Create the async task */
|
||||||
self->init_task = g_task_new (initable, cancellable, callback, data);
|
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 */
|
/* Init the list of port proxies */
|
||||||
self->port_proxies = g_ptr_array_new_full(4, (GDestroyNotify)g_object_unref);
|
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 */
|
/* Set the properties */
|
||||||
pw_properties_set(props, "audio-dsp.name",
|
pw_properties_set(props, "audio-dsp.name",
|
||||||
self->name ? self->name : "Audio-DSP");
|
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.direction", "%d", self->direction);
|
||||||
pw_properties_setf(props, "audio-dsp.maxbuffer", "%ld",
|
pw_properties_setf(props, "audio-dsp.maxbuffer", "%ld",
|
||||||
MAX_QUANTUM_SIZE * sizeof(float));
|
MAX_QUANTUM_SIZE * sizeof(float));
|
||||||
@@ -547,6 +587,10 @@ wp_pw_audio_dsp_class_init (WpPwAudioDspClass * klass)
|
|||||||
g_param_spec_uint ("direction", "direction",
|
g_param_spec_uint ("direction", "direction",
|
||||||
"The direction of the audio DSP", 0, 1, 0,
|
"The direction of the audio DSP", 0, 1, 0,
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
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_object_class_install_property (object_class, PROP_TARGET,
|
||||||
g_param_spec_pointer ("target", "target",
|
g_param_spec_pointer ("target", "target",
|
||||||
"The target node info of the audio DSP",
|
"The target node info of the audio DSP",
|
||||||
@@ -559,8 +603,9 @@ wp_pw_audio_dsp_class_init (WpPwAudioDspClass * klass)
|
|||||||
|
|
||||||
void
|
void
|
||||||
wp_pw_audio_dsp_new (WpEndpoint *endpoint, guint id, const char *name,
|
wp_pw_audio_dsp_new (WpEndpoint *endpoint, guint id, const char *name,
|
||||||
enum pw_direction direction, const struct pw_node_info *target,
|
enum pw_direction direction, gboolean convert,
|
||||||
const struct spa_audio_info_raw *format, GAsyncReadyCallback callback,
|
const struct pw_node_info *target, const struct spa_audio_info_raw *format,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_async_initable_new_async (
|
g_async_initable_new_async (
|
||||||
@@ -570,6 +615,7 @@ wp_pw_audio_dsp_new (WpEndpoint *endpoint, guint id, const char *name,
|
|||||||
"id", id,
|
"id", id,
|
||||||
"name", name,
|
"name", name,
|
||||||
"direction", direction,
|
"direction", direction,
|
||||||
|
"convert", convert,
|
||||||
"target", target,
|
"target", target,
|
||||||
"format", format,
|
"format", format,
|
||||||
NULL);
|
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_id_decode (guint id, guint *stream_id, guint *control_id);
|
||||||
|
|
||||||
void wp_pw_audio_dsp_new (WpEndpoint *endpoint, guint id, const char *name,
|
void wp_pw_audio_dsp_new (WpEndpoint *endpoint, guint id, const char *name,
|
||||||
enum pw_direction direction, const struct pw_node_info *target,
|
enum pw_direction direction, gboolean convert,
|
||||||
const struct spa_audio_info_raw *format, GAsyncReadyCallback callback,
|
const struct pw_node_info *target, const struct spa_audio_info_raw *format,
|
||||||
gpointer user_data);
|
GAsyncReadyCallback callback, gpointer user_data);
|
||||||
WpPwAudioDsp * wp_pw_audio_dsp_new_finish (GObject *initable, GAsyncResult *res,
|
WpPwAudioDsp * wp_pw_audio_dsp_new_finish (GObject *initable, GAsyncResult *res,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user