alsa-udev/softdsp-endpoint: make the stream names & count configurable
This commit is contained in:

committed by
Julian Bouzas

parent
4b65593ee1
commit
7618b8b082
@@ -20,6 +20,7 @@ struct impl
|
|||||||
WpModule *module;
|
WpModule *module;
|
||||||
WpRemotePipewire *remote_pipewire;
|
WpRemotePipewire *remote_pipewire;
|
||||||
GHashTable *registered_endpoints;
|
GHashTable *registered_endpoints;
|
||||||
|
GVariant *streams;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -73,6 +74,8 @@ on_node_added(WpRemotePipewire *rp, guint id, guint parent_id, gconstpointer p,
|
|||||||
"media-class", g_variant_new_string (media_class));
|
"media-class", g_variant_new_string (media_class));
|
||||||
g_variant_builder_add (&b, "{sv}",
|
g_variant_builder_add (&b, "{sv}",
|
||||||
"global-id", g_variant_new_uint32 (id));
|
"global-id", g_variant_new_uint32 (id));
|
||||||
|
g_variant_builder_add (&b, "{sv}",
|
||||||
|
"streams", impl->streams);
|
||||||
endpoint_props = g_variant_builder_end (&b);
|
endpoint_props = g_variant_builder_end (&b);
|
||||||
|
|
||||||
/* Create the endpoint async */
|
/* Create the endpoint async */
|
||||||
@@ -110,6 +113,8 @@ module_destroy (gpointer data)
|
|||||||
g_hash_table_unref(impl->registered_endpoints);
|
g_hash_table_unref(impl->registered_endpoints);
|
||||||
impl->registered_endpoints = NULL;
|
impl->registered_endpoints = NULL;
|
||||||
|
|
||||||
|
g_clear_pointer (&impl->streams, g_variant_unref);
|
||||||
|
|
||||||
/* Clean up */
|
/* Clean up */
|
||||||
g_slice_free (struct impl, impl);
|
g_slice_free (struct impl, impl);
|
||||||
}
|
}
|
||||||
@@ -134,6 +139,8 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
|
|||||||
impl->remote_pipewire = rp;
|
impl->remote_pipewire = rp;
|
||||||
impl->registered_endpoints = g_hash_table_new_full (g_direct_hash,
|
impl->registered_endpoints = g_hash_table_new_full (g_direct_hash,
|
||||||
g_direct_equal, NULL, (GDestroyNotify)g_object_unref);
|
g_direct_equal, NULL, (GDestroyNotify)g_object_unref);
|
||||||
|
impl->streams = g_variant_lookup_value (args, "streams",
|
||||||
|
G_VARIANT_TYPE ("as"));
|
||||||
|
|
||||||
/* Set destroy callback for impl */
|
/* Set destroy callback for impl */
|
||||||
wp_module_set_destroy_callback (module, module_destroy, impl);
|
wp_module_set_destroy_callback (module, module_destroy, impl);
|
||||||
|
@@ -25,22 +25,15 @@
|
|||||||
#define MAX_QUANTUM_SIZE 1024
|
#define MAX_QUANTUM_SIZE 1024
|
||||||
#define CONTROL_SELECTED 0
|
#define CONTROL_SELECTED 0
|
||||||
|
|
||||||
static const char * streams[] = {
|
|
||||||
"multimedia",
|
|
||||||
"navigation",
|
|
||||||
"communication",
|
|
||||||
"emergency",
|
|
||||||
};
|
|
||||||
#define N_STREAMS (sizeof (streams) / sizeof (const char *))
|
|
||||||
|
|
||||||
struct _WpPwAudioSoftdspEndpoint
|
struct _WpPwAudioSoftdspEndpoint
|
||||||
{
|
{
|
||||||
WpEndpoint parent;
|
WpEndpoint parent;
|
||||||
|
|
||||||
/* Properties */
|
/* Properties */
|
||||||
guint global_id;
|
guint global_id;
|
||||||
guint stream_count;
|
GVariant *streams;
|
||||||
|
|
||||||
|
guint stream_count;
|
||||||
gboolean selected;
|
gboolean selected;
|
||||||
|
|
||||||
/* The task to signal the endpoint is initialized */
|
/* The task to signal the endpoint is initialized */
|
||||||
@@ -58,12 +51,13 @@ struct _WpPwAudioSoftdspEndpoint
|
|||||||
|
|
||||||
/* Audio Dsp */
|
/* Audio Dsp */
|
||||||
WpPwAudioDsp *converter;
|
WpPwAudioDsp *converter;
|
||||||
WpPwAudioDsp *streams[N_STREAMS];
|
GPtrArray *dsps;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_GLOBAL_ID,
|
PROP_GLOBAL_ID,
|
||||||
|
PROP_STREAMS,
|
||||||
};
|
};
|
||||||
|
|
||||||
static GAsyncInitableIface *wp_endpoint_parent_interface = NULL;
|
static GAsyncInitableIface *wp_endpoint_parent_interface = NULL;
|
||||||
@@ -85,10 +79,10 @@ endpoint_prepare_link (WpEndpoint * ep, guint32 stream_id,
|
|||||||
WpPwAudioDsp *stream = NULL;
|
WpPwAudioDsp *stream = NULL;
|
||||||
|
|
||||||
/* Make sure the stream Id is valid */
|
/* Make sure the stream Id is valid */
|
||||||
g_return_val_if_fail(stream_id < N_STREAMS, FALSE);
|
g_return_val_if_fail(stream_id < self->dsps->len, FALSE);
|
||||||
|
|
||||||
/* Make sure the stream is valid */
|
/* Make sure the stream is valid */
|
||||||
stream = self->streams[stream_id];
|
stream = g_ptr_array_index (self->dsps, stream_id);
|
||||||
g_return_val_if_fail(stream, FALSE);
|
g_return_val_if_fail(stream, FALSE);
|
||||||
|
|
||||||
/* Prepare the link */
|
/* Prepare the link */
|
||||||
@@ -111,24 +105,26 @@ static void
|
|||||||
on_audio_dsp_stream_created(GObject *initable, GAsyncResult *res, gpointer data)
|
on_audio_dsp_stream_created(GObject *initable, GAsyncResult *res, gpointer data)
|
||||||
{
|
{
|
||||||
WpPwAudioSoftdspEndpoint *self = data;
|
WpPwAudioSoftdspEndpoint *self = data;
|
||||||
WpPwAudioDsp *stream = NULL;
|
WpPwAudioDsp *dsp = NULL;
|
||||||
guint stream_id = 0;
|
guint stream_id = 0;
|
||||||
|
g_autofree gchar *name = NULL;
|
||||||
|
|
||||||
/* Get the stream */
|
/* Get the stream */
|
||||||
stream = wp_pw_audio_dsp_new_finish(initable, res, NULL);
|
dsp = wp_pw_audio_dsp_new_finish(initable, res, NULL);
|
||||||
g_return_if_fail (stream);
|
g_return_if_fail (dsp);
|
||||||
|
|
||||||
/* Get the stream id */
|
/* Get the stream id */
|
||||||
g_object_get (stream, "id", &stream_id, NULL);
|
g_object_get (dsp, "id", &stream_id, "name", &name, NULL);
|
||||||
g_return_if_fail (stream_id >= 0);
|
g_return_if_fail (stream_id >= 0);
|
||||||
g_return_if_fail (stream_id < N_STREAMS);
|
|
||||||
|
|
||||||
/* Set the streams */
|
/* Set the streams */
|
||||||
self->streams[stream_id] = stream;
|
g_ptr_array_insert (self->dsps, stream_id, dsp);
|
||||||
|
|
||||||
|
g_debug ("%s:%p Created stream %u %s", G_OBJECT_TYPE_NAME (self), self,
|
||||||
|
stream_id, name);
|
||||||
|
|
||||||
/* Finish the endpoint creation when all the streams are created */
|
/* Finish the endpoint creation when all the streams are created */
|
||||||
self->stream_count++;
|
if (--self->stream_count == 0)
|
||||||
if (self->stream_count == N_STREAMS)
|
|
||||||
finish_endpoint_creation(self);
|
finish_endpoint_creation(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,6 +137,9 @@ on_audio_dsp_converter_created(GObject *initable, GAsyncResult *res,
|
|||||||
const struct pw_node_info *target = NULL;
|
const struct pw_node_info *target = NULL;
|
||||||
const struct spa_audio_info_raw *format = NULL;
|
const struct spa_audio_info_raw *format = NULL;
|
||||||
GVariantDict d;
|
GVariantDict d;
|
||||||
|
GVariantIter iter;
|
||||||
|
const gchar *stream;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Get the proxy dsp converter */
|
/* Get the proxy dsp converter */
|
||||||
self->converter = wp_pw_audio_dsp_new_finish(initable, res, NULL);
|
self->converter = wp_pw_audio_dsp_new_finish(initable, res, NULL);
|
||||||
@@ -153,16 +152,18 @@ on_audio_dsp_converter_created(GObject *initable, GAsyncResult *res,
|
|||||||
g_return_if_fail (format);
|
g_return_if_fail (format);
|
||||||
|
|
||||||
/* Create the audio dsp streams */
|
/* Create the audio dsp streams */
|
||||||
for (int i = 0; i < N_STREAMS; i++) {
|
g_variant_iter_init (&iter, self->streams);
|
||||||
wp_pw_audio_dsp_new (WP_ENDPOINT(self), i, streams[i], self->direction,
|
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);
|
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);
|
||||||
g_variant_dict_insert (&d, "id", "u", i);
|
g_variant_dict_insert (&d, "id", "u", i);
|
||||||
g_variant_dict_insert (&d, "name", "s", streams[i]);
|
g_variant_dict_insert (&d, "name", "s", stream);
|
||||||
wp_endpoint_register_stream (WP_ENDPOINT (self), g_variant_dict_end (&d));
|
wp_endpoint_register_stream (WP_ENDPOINT (self), g_variant_dict_end (&d));
|
||||||
}
|
}
|
||||||
|
self->stream_count = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -243,6 +244,8 @@ endpoint_finalize (GObject * object)
|
|||||||
{
|
{
|
||||||
WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object);
|
WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object);
|
||||||
|
|
||||||
|
g_clear_pointer(&self->streams, g_variant_unref);
|
||||||
|
|
||||||
/* Destroy the proxy node */
|
/* Destroy the proxy node */
|
||||||
g_clear_object(&self->proxy_node);
|
g_clear_object(&self->proxy_node);
|
||||||
|
|
||||||
@@ -253,8 +256,7 @@ endpoint_finalize (GObject * object)
|
|||||||
g_clear_object(&self->converter);
|
g_clear_object(&self->converter);
|
||||||
|
|
||||||
/* Destroy all the proxy dsp streams */
|
/* Destroy all the proxy dsp streams */
|
||||||
for (int i = 0; i < N_STREAMS; i++)
|
g_clear_pointer (&self->dsps, g_ptr_array_unref);
|
||||||
g_clear_object(&self->streams[i]);
|
|
||||||
|
|
||||||
/* Destroy the done task */
|
/* Destroy the done task */
|
||||||
g_clear_object(&self->init_task);
|
g_clear_object(&self->init_task);
|
||||||
@@ -272,6 +274,9 @@ endpoint_set_property (GObject * object, guint property_id,
|
|||||||
case PROP_GLOBAL_ID:
|
case PROP_GLOBAL_ID:
|
||||||
self->global_id = g_value_get_uint(value);
|
self->global_id = g_value_get_uint(value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_STREAMS:
|
||||||
|
self->streams = g_value_dup_variant(value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@@ -288,6 +293,9 @@ endpoint_get_property (GObject * object, guint property_id,
|
|||||||
case PROP_GLOBAL_ID:
|
case PROP_GLOBAL_ID:
|
||||||
g_value_set_uint (value, self->global_id);
|
g_value_set_uint (value, self->global_id);
|
||||||
break;
|
break;
|
||||||
|
case PROP_STREAMS:
|
||||||
|
g_value_set_variant (value, self->streams);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
break;
|
break;
|
||||||
@@ -311,8 +319,8 @@ endpoint_get_control_value (WpEndpoint * ep, guint32 id)
|
|||||||
return wp_pw_audio_dsp_get_control_value (self->converter, control_id);
|
return wp_pw_audio_dsp_get_control_value (self->converter, control_id);
|
||||||
|
|
||||||
/* Otherwise get the stream_id and control_id */
|
/* Otherwise get the stream_id and control_id */
|
||||||
g_return_val_if_fail (stream_id < N_STREAMS, NULL);
|
g_return_val_if_fail (stream_id < self->dsps->len, NULL);
|
||||||
stream = self->streams[stream_id];
|
stream = g_ptr_array_index (self->dsps, stream_id);
|
||||||
g_return_val_if_fail (stream, NULL);
|
g_return_val_if_fail (stream, NULL);
|
||||||
return wp_pw_audio_dsp_get_control_value (stream, control_id);
|
return wp_pw_audio_dsp_get_control_value (stream, control_id);
|
||||||
}
|
}
|
||||||
@@ -337,8 +345,8 @@ endpoint_set_control_value (WpEndpoint * ep, guint32 id, GVariant * value)
|
|||||||
return wp_pw_audio_dsp_set_control_value (self->converter, control_id, value);
|
return wp_pw_audio_dsp_set_control_value (self->converter, control_id, value);
|
||||||
|
|
||||||
/* Otherwise get the stream_id and control_id */
|
/* Otherwise get the stream_id and control_id */
|
||||||
g_return_val_if_fail (stream_id < N_STREAMS, FALSE);
|
g_return_val_if_fail (stream_id < self->dsps->len, FALSE);
|
||||||
stream = self->streams[stream_id];
|
stream = g_ptr_array_index (self->dsps, stream_id);
|
||||||
g_return_val_if_fail (stream, FALSE);
|
g_return_val_if_fail (stream, FALSE);
|
||||||
return wp_pw_audio_dsp_set_control_value (stream, control_id, value);
|
return wp_pw_audio_dsp_set_control_value (stream, control_id, value);
|
||||||
}
|
}
|
||||||
@@ -398,6 +406,7 @@ wp_endpoint_async_initable_init (gpointer iface, gpointer iface_data)
|
|||||||
static void
|
static void
|
||||||
endpoint_init (WpPwAudioSoftdspEndpoint * self)
|
endpoint_init (WpPwAudioSoftdspEndpoint * self)
|
||||||
{
|
{
|
||||||
|
self->dsps = g_ptr_array_new_with_free_func (g_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -419,6 +428,12 @@ endpoint_class_init (WpPwAudioSoftdspEndpointClass * klass)
|
|||||||
g_param_spec_uint ("global-id", "global-id",
|
g_param_spec_uint ("global-id", "global-id",
|
||||||
"The global Id this endpoint refers to", 0, G_MAXUINT, 0,
|
"The global Id this endpoint refers to", 0, G_MAXUINT, 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_STREAMS,
|
||||||
|
g_param_spec_variant ("streams", "streams",
|
||||||
|
"The stream names for the streams to create",
|
||||||
|
G_VARIANT_TYPE ("as"), NULL,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -428,6 +443,7 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties,
|
|||||||
g_autoptr (WpCore) core = NULL;
|
g_autoptr (WpCore) core = NULL;
|
||||||
const gchar *media_class;
|
const gchar *media_class;
|
||||||
guint global_id;
|
guint global_id;
|
||||||
|
g_autoptr (GVariant) streams = NULL;
|
||||||
|
|
||||||
/* Make sure the type is correct */
|
/* Make sure the type is correct */
|
||||||
g_return_if_fail(type == WP_TYPE_ENDPOINT);
|
g_return_if_fail(type == WP_TYPE_ENDPOINT);
|
||||||
@@ -441,6 +457,9 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties,
|
|||||||
return;
|
return;
|
||||||
if (!g_variant_lookup (properties, "global-id", "u", &global_id))
|
if (!g_variant_lookup (properties, "global-id", "u", &global_id))
|
||||||
return;
|
return;
|
||||||
|
if (!(streams = g_variant_lookup_value (properties, "streams",
|
||||||
|
G_VARIANT_TYPE ("as"))))
|
||||||
|
return;
|
||||||
|
|
||||||
/* Create and return the softdsp endpoint object */
|
/* Create and return the softdsp endpoint object */
|
||||||
g_async_initable_new_async (
|
g_async_initable_new_async (
|
||||||
@@ -448,6 +467,7 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties,
|
|||||||
"core", core,
|
"core", core,
|
||||||
"media-class", media_class,
|
"media-class", media_class,
|
||||||
"global-id", global_id,
|
"global-id", global_id,
|
||||||
|
"streams", streams,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,7 +13,9 @@ load-module C libwireplumber-module-mixer
|
|||||||
|
|
||||||
# Monitors the ALSA devices that are discovered via udev
|
# Monitors the ALSA devices that are discovered via udev
|
||||||
# and creates softdsp-endopints for each one of them
|
# and creates softdsp-endopints for each one of them
|
||||||
load-module C libwireplumber-module-pw-alsa-udev
|
load-module C libwireplumber-module-pw-alsa-udev {
|
||||||
|
"streams": <["Multimedia", "Navigation", "Communication", "Emergency"]>
|
||||||
|
}
|
||||||
|
|
||||||
# Implements linking clients to devices and maintains
|
# Implements linking clients to devices and maintains
|
||||||
# information about the devices to be used.
|
# information about the devices to be used.
|
||||||
|
Reference in New Issue
Block a user