diff --git a/modules/meson.build b/modules/meson.build index 79448d4db76c978220f6d65b196908982e0d610c..9c96b586c9004c6ab392fc9b9f0ca1b5141aa84f 100644 --- a/modules/meson.build +++ b/modules/meson.build @@ -41,7 +41,6 @@ shared_library( [ 'module-pipewire.c', 'module-pipewire/simple-endpoint-link.c', - 'module-pipewire/simple-endpoint.c', ], c_args : [common_c_args, '-DG_LOG_DOMAIN="m-pipewire"'], install : true, diff --git a/modules/module-pipewire.c b/modules/module-pipewire.c index 9d16f19bafa9a62b7c4be6cfae62d0912d7e09cc..91ae9b9a2a5a372f2ffe83ae487467bfb9390940 100644 --- a/modules/module-pipewire.c +++ b/modules/module-pipewire.c @@ -15,8 +15,6 @@ #include <wp/wp.h> #include <pipewire/pipewire.h> -void simple_endpoint_factory (WpFactory * factory, GType type, - GVariant * properties, GAsyncReadyCallback ready, gpointer user_data); void simple_endpoint_link_factory (WpFactory * factory, GType type, GVariant * properties, GAsyncReadyCallback ready, gpointer user_data); @@ -28,9 +26,7 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args) pw_module_load (pw_core, "libpipewire-module-client-device", NULL, NULL); pw_module_load (pw_core, "libpipewire-module-adapter", NULL, NULL); - /* Register simple-endpoint and simple-endpoint-link */ - wp_factory_new (core, "pipewire-simple-endpoint", - simple_endpoint_factory); + /* Register simple-endpoint-link */ wp_factory_new (core, "pipewire-simple-endpoint-link", simple_endpoint_link_factory); } diff --git a/modules/module-pipewire/simple-endpoint.c b/modules/module-pipewire/simple-endpoint.c deleted file mode 100644 index 9dba4885914f1aaccc2d4631b6d2e3d1e90ad0d7..0000000000000000000000000000000000000000 --- a/modules/module-pipewire/simple-endpoint.c +++ /dev/null @@ -1,544 +0,0 @@ -/* WirePlumber - * - * Copyright © 2019 Collabora Ltd. - * @author George Kiagiadakis <george.kiagiadakis@collabora.com> - * - * SPDX-License-Identifier: MIT - */ - -/** - * The simple endpoint is a WpEndpoint implementation that represents - * all ports of a single direction of a single pipewire node. - * It can be used to create an Endpoint for a client node or for any - * other arbitrary node that does not need any kind of internal management. - */ - -#include <spa/param/audio/format-utils.h> - -#include <wp/wp.h> -#include <pipewire/pipewire.h> -#include <spa/pod/parser.h> -#include <spa/param/props.h> - -struct _WpPipewireSimpleEndpoint -{ - WpEndpoint parent; - - /* properties */ - gchar *role; - guint64 creation_time; - gchar *target; - - /* The task to signal the endpoint is initialized */ - GTask *init_task; - - /* Proxies */ - WpProxyNode *proxy_node; - GPtrArray *proxies_port; - - /* controls cache */ - gfloat volume; - gboolean mute; -}; - -enum { - PROP_0, - PROP_PROXY_NODE, - PROP_ROLE, - PROP_CREATION_TIME, - PROP_TARGET, -}; - -enum { - CONTROL_VOLUME = 0, - CONTROL_MUTE, -}; - -static GAsyncInitableIface *wp_simple_endpoint_parent_interface = NULL; -static void wp_simple_endpoint_async_initable_init (gpointer iface, - gpointer iface_data); - -G_DECLARE_FINAL_TYPE (WpPipewireSimpleEndpoint, - simple_endpoint, WP_PIPEWIRE, SIMPLE_ENDPOINT, WpEndpoint) - -G_DEFINE_TYPE_WITH_CODE (WpPipewireSimpleEndpoint, simple_endpoint, - WP_TYPE_ENDPOINT, - G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, - wp_simple_endpoint_async_initable_init)) - -static gboolean -proxy_safe_augment_finish (WpPipewireSimpleEndpoint * self, WpProxy *proxy, - GAsyncResult *res) -{ - GError *error = NULL; - - /* Return FALSE if we are already aborting */ - if (!self->init_task) - return FALSE; - - wp_proxy_augment_finish (proxy, res, &error); - if (error) { - g_warning ("WpPipewireSimpleEndpoint:%p Aborting construction", self); - g_task_return_error (self->init_task, error); - g_clear_object (&self->init_task); - return FALSE; - } - - return TRUE; -} - -static void -node_proxy_param (WpProxy *proxy, int seq, uint32_t id, - uint32_t index, uint32_t next, const struct spa_pod *param, - WpPipewireSimpleEndpoint *self) -{ - switch (id) { - case SPA_PARAM_Props: - { - struct spa_pod_prop *prop; - struct spa_pod_object *obj = (struct spa_pod_object *) param; - float volume = self->volume; - bool mute = self->mute; - - SPA_POD_OBJECT_FOREACH(obj, prop) { - switch (prop->key) { - case SPA_PROP_volume: - spa_pod_get_float(&prop->value, &volume); - break; - case SPA_PROP_mute: - spa_pod_get_bool(&prop->value, &mute); - break; - default: - break; - } - } - - g_debug ("WpEndpoint:%p param event, vol:(%lf -> %f) mute:(%d -> %d)", - self, self->volume, volume, self->mute, mute); - - if (self->volume != volume) { - self->volume = volume; - wp_endpoint_notify_control_value (WP_ENDPOINT (self), CONTROL_VOLUME); - } - if (self->mute != mute) { - self->mute = mute; - wp_endpoint_notify_control_value (WP_ENDPOINT (self), CONTROL_MUTE); - } - - break; - } - default: - break; - } -} - -static void -on_all_ports_done (WpProxy *proxy, GAsyncResult *res, - WpPipewireSimpleEndpoint *self) -{ - GError *error = NULL; - - /* return if already aborted */ - if (!self->init_task) - return; - - wp_proxy_sync_finish (proxy, res, &error); - - if (error) - g_task_return_error (self->init_task, error); - else - g_task_return_boolean (self->init_task, TRUE); - - g_clear_object(&self->init_task); -} - -static void -on_proxy_port_augmented (WpProxy *proxy, GAsyncResult *res, - WpPipewireSimpleEndpoint *self) -{ - if (!proxy_safe_augment_finish (self, proxy, res)) - return; - - /* Add the proxy port to the array */ - g_ptr_array_add(self->proxies_port, g_object_ref (proxy)); - - /* Sync with the server and use the task data as a flag to know - whether we already called sync or not */ - if (!g_task_get_task_data (self->init_task)) { - wp_proxy_sync (WP_PROXY(self->proxy_node), NULL, - (GAsyncReadyCallback) on_all_ports_done, self); - g_task_set_task_data (self->init_task, GUINT_TO_POINTER (1), NULL); - } -} - -static void -on_port_added (WpCore *core, WpProxy *proxy, gpointer d) -{ - WpPipewireSimpleEndpoint *self = d; - const char *s; - guint node_id = 0; - g_autoptr (WpProperties) props = wp_proxy_get_global_properties (proxy); - - /* Don't do anything if we are aborting */ - if (!self->init_task) - return; - - if ((s = wp_properties_get (props, PW_KEY_NODE_ID))) - node_id = atoi(s); - - /* Only handle ports owned by this endpoint */ - if (node_id != wp_proxy_get_global_id (WP_PROXY (self->proxy_node))) - return; - - /* Augment */ - wp_proxy_augment (proxy, WP_PROXY_FEATURE_PW_PROXY | WP_PROXY_FEATURE_INFO, - NULL, (GAsyncReadyCallback) on_proxy_port_augmented, self); -} - -static void -emit_endpoint_ports(WpPipewireSimpleEndpoint *self) -{ - enum pw_direction direction = wp_endpoint_get_direction (WP_ENDPOINT (self)); - struct spa_audio_info_raw format = { 0, }; - struct spa_pod *param; - char buf[1024]; - struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); - - /* The default format for audio clients */ - format.format = SPA_AUDIO_FORMAT_F32P; - format.flags = 1; - format.rate = 48000; - format.channels = 2; - format.position[0] = SPA_AUDIO_CHANNEL_FL; - format.position[1] = SPA_AUDIO_CHANNEL_FR; - - /* Build the param profile */ - param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &format); - param = spa_pod_builder_add_object(&pod_builder, - SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp), - SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param)); - - /* Set the param profile to emit the ports */ - wp_proxy_node_set_param (self->proxy_node, SPA_PARAM_PortConfig, 0, param); -} - -static void -on_proxy_node_augmented (WpProxy *proxy, GAsyncResult *res, gpointer data) -{ - WpPipewireSimpleEndpoint *self = data; - GVariantDict d; - g_autoptr (WpProperties) props = NULL; - - if (!proxy_safe_augment_finish (self, proxy, res)) - return; - - props = wp_proxy_node_get_properties (self->proxy_node); - - /* Set the role and target name */ - self->role = g_strdup (wp_properties_get (props, PW_KEY_MEDIA_ROLE)); - self->target = g_strdup (wp_properties_get (props, "target.name")); - - /* Emit the ports */ - emit_endpoint_ports(self); - - g_signal_connect (self->proxy_node, "param", (GCallback) node_proxy_param, - self); - wp_proxy_node_subscribe_params (self->proxy_node, 1, SPA_PARAM_Props); - - g_variant_dict_init (&d, NULL); - g_variant_dict_insert (&d, "id", "u", 0); - g_variant_dict_insert (&d, "name", "s", "default"); - wp_endpoint_register_stream (WP_ENDPOINT (self), g_variant_dict_end (&d)); - - /* Audio streams have volume & mute controls */ - if (g_strrstr (wp_endpoint_get_media_class (WP_ENDPOINT (self)), "Audio")) { - g_variant_dict_init (&d, NULL); - g_variant_dict_insert (&d, "id", "u", CONTROL_VOLUME); - g_variant_dict_insert (&d, "stream-id", "u", 0); - g_variant_dict_insert (&d, "name", "s", "volume"); - g_variant_dict_insert (&d, "type", "s", "d"); - g_variant_dict_insert (&d, "range", "(dd)", 0.0, 1.0); - g_variant_dict_insert (&d, "default-value", "d", 1.0); - wp_endpoint_register_control (WP_ENDPOINT (self), g_variant_dict_end (&d)); - - g_variant_dict_init (&d, NULL); - g_variant_dict_insert (&d, "id", "u", CONTROL_MUTE); - g_variant_dict_insert (&d, "stream-id", "u", 0); - g_variant_dict_insert (&d, "name", "s", "mute"); - g_variant_dict_insert (&d, "type", "s", "b"); - g_variant_dict_insert (&d, "default-value", "b", FALSE); - wp_endpoint_register_control (WP_ENDPOINT (self), g_variant_dict_end (&d)); - } -} - -static void -wp_simple_endpoint_init_async (GAsyncInitable *initable, int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data) -{ - WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (initable); - g_autoptr (WpCore) core = wp_endpoint_get_core(WP_ENDPOINT(self)); - - /* Create the async task */ - self->init_task = g_task_new (initable, cancellable, callback, data); - - /* Register a port_added callback */ - g_signal_connect_object (core, "remote-global-added::port", - (GCallback) on_port_added, self, 0); - - /* Augment to get the info */ - wp_proxy_augment (WP_PROXY (self->proxy_node), - WP_PROXY_FEATURE_PW_PROXY | WP_PROXY_FEATURE_INFO, cancellable, - (GAsyncReadyCallback) on_proxy_node_augmented, self); - - /* Call the parent interface */ - wp_simple_endpoint_parent_interface->init_async (initable, io_priority, - cancellable, callback, data); -} - -static void -wp_simple_endpoint_async_initable_init (gpointer iface, gpointer iface_data) -{ - GAsyncInitableIface *ai_iface = iface; - - /* Set the parent interface */ - wp_simple_endpoint_parent_interface = g_type_interface_peek_parent (iface); - - /* Only set the init_async */ - ai_iface->init_async = wp_simple_endpoint_init_async; -} - -static void -simple_endpoint_init (WpPipewireSimpleEndpoint * self) -{ - self->creation_time = (guint64) g_get_monotonic_time (); - self->proxies_port = g_ptr_array_new_full(2, (GDestroyNotify)g_object_unref); -} - -static void -simple_endpoint_finalize (GObject * object) -{ - WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (object); - - /* Destroy the proxies port */ - g_clear_pointer (&self->proxies_port, g_ptr_array_unref); - - /* Destroy the proxy node */ - g_clear_object(&self->proxy_node); - - /* Destroy the done task */ - g_clear_object(&self->init_task); - - g_free (self->role); - - G_OBJECT_CLASS (simple_endpoint_parent_class)->finalize (object); -} - -static void -simple_endpoint_set_property (GObject * object, guint property_id, - const GValue * value, GParamSpec * pspec) -{ - WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (object); - - switch (property_id) { - case PROP_PROXY_NODE: - self->proxy_node = g_value_dup_object (value); - break; - case PROP_ROLE: - g_free (self->role); - self->role = g_value_dup_string (value); - break; - case PROP_TARGET: - g_free (self->target); - self->target = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -simple_endpoint_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (object); - - switch (property_id) { - case PROP_PROXY_NODE: - g_value_set_object (value, self->proxy_node); - break; - case PROP_ROLE: - g_value_set_string (value, self->role); - break; - case PROP_CREATION_TIME: - g_value_set_uint64 (value, self->creation_time); - break; - case PROP_TARGET: - g_value_set_string (value, self->target); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -proxies_port_foreach_func(gpointer data, gpointer user_data) -{ - GVariantBuilder *b = user_data; - g_variant_builder_add (b, "t", data); -} - -static gboolean -simple_endpoint_prepare_link (WpEndpoint * ep, guint32 stream_id, - WpEndpointLink * link, GVariant ** properties, GError ** error) -{ - WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (ep); - GVariantBuilder b, *b_ports; - GVariant *v_ports; - - /* Create a variant array with all the ports */ - b_ports = g_variant_builder_new (G_VARIANT_TYPE ("at")); - g_ptr_array_foreach(self->proxies_port, proxies_port_foreach_func, b_ports); - v_ports = g_variant_builder_end (b_ports); - - /* Set the properties */ - g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&b, "{sv}", "node-id", g_variant_new_uint32 ( - wp_proxy_get_global_id (WP_PROXY (self->proxy_node)))); - g_variant_builder_add (&b, "{sv}", "ports", v_ports); - *properties = g_variant_builder_end (&b); - - return TRUE; -} - -static GVariant * -simple_endpoint_get_control_value (WpEndpoint * ep, guint32 control_id) -{ - WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (ep); - - switch (control_id) { - case CONTROL_VOLUME: - return g_variant_new_double (self->volume); - case CONTROL_MUTE: - return g_variant_new_boolean (self->mute); - default: - g_warning ("Unknown control id %u", control_id); - return NULL; - } -} - -static gboolean -simple_endpoint_set_control_value (WpEndpoint * ep, guint32 control_id, - GVariant * value) -{ - WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (ep); - char buf[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); - float volume; - bool mute; - - switch (control_id) { - case CONTROL_VOLUME: - volume = g_variant_get_double (value); - - g_debug("WpEndpoint:%p set volume control (%u) value, vol:%f", self, - control_id, volume); - - wp_proxy_node_set_param (self->proxy_node, - SPA_PARAM_Props, 0, - spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, - SPA_PROP_volume, SPA_POD_Float(volume), - NULL)); - break; - - case CONTROL_MUTE: - mute = g_variant_get_boolean (value); - - g_debug("WpEndpoint:%p set mute control (%u) value, mute:%d", self, - control_id, mute); - - wp_proxy_node_set_param (self->proxy_node, - SPA_PARAM_Props, 0, - spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, - SPA_PROP_mute, SPA_POD_Bool(mute), - NULL)); - break; - - default: - g_warning ("Unknown control id %u", control_id); - return FALSE; - } - - return TRUE; -} - -static void -simple_endpoint_class_init (WpPipewireSimpleEndpointClass * klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - WpEndpointClass *endpoint_class = (WpEndpointClass *) klass; - - object_class->finalize = simple_endpoint_finalize; - object_class->set_property = simple_endpoint_set_property; - object_class->get_property = simple_endpoint_get_property; - - endpoint_class->prepare_link = simple_endpoint_prepare_link; - endpoint_class->get_control_value = simple_endpoint_get_control_value; - endpoint_class->set_control_value = simple_endpoint_set_control_value; - - g_object_class_install_property (object_class, PROP_PROXY_NODE, - g_param_spec_object ("proxy-node", "proxy-node", - "The node this endpoint refers to", WP_TYPE_PROXY_NODE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, PROP_ROLE, - g_param_spec_string ("role", "role", "The role of the wrapped node", NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, PROP_CREATION_TIME, - g_param_spec_uint64 ("creation-time", "creation-time", - "The time that this endpoint was created, in monotonic time", - 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (object_class, PROP_TARGET, - g_param_spec_string ("target", "target", "The target of the wrapped node", NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -void -simple_endpoint_factory (WpFactory * factory, GType type, - GVariant * properties, GAsyncReadyCallback ready, gpointer user_data) -{ - g_autoptr (WpCore) core = NULL; - const gchar *name, *media_class; - guint direction; - guint64 node; - - /* Make sure the type is correct */ - g_return_if_fail (type == WP_TYPE_ENDPOINT); - - /* Get the Core */ - core = wp_factory_get_core (factory); - g_return_if_fail (core); - - /* Get the properties */ - if (!g_variant_lookup (properties, "name", "&s", &name)) - return; - if (!g_variant_lookup (properties, "media-class", "&s", &media_class)) - return; - if (!g_variant_lookup (properties, "direction", "u", &direction)) - return; - if (!g_variant_lookup (properties, "proxy-node", "t", &node)) - return; - - g_async_initable_new_async ( - simple_endpoint_get_type (), G_PRIORITY_DEFAULT, NULL, ready, user_data, - "core", core, - "name", name, - "media-class", media_class, - "direction", direction, - "proxy-node", (gpointer) node, - NULL); -} diff --git a/modules/module-pw-audio-client.c b/modules/module-pw-audio-client.c index 089d4eb59c66a61aafba503dfd082227ffef93c9..7528a759dbc70a47f8b7b1d1319b899bf39834d4 100644 --- a/modules/module-pw-audio-client.c +++ b/modules/module-pw-audio-client.c @@ -95,7 +95,7 @@ on_node_added (WpCore *core, WpProxy *proxy, gpointer d) endpoint_props = g_variant_builder_end (&b); /* Create the endpoint async */ - wp_factory_make (core, "pipewire-simple-endpoint", WP_TYPE_ENDPOINT, + wp_factory_make (core, "pw-audio-softdsp-endpoint", WP_TYPE_ENDPOINT, endpoint_props, on_endpoint_created, data); } diff --git a/modules/module-pw-audio-softdsp-endpoint.c b/modules/module-pw-audio-softdsp-endpoint.c index 81a3451d8550c80886f5a6e1160f7a5049261cd4..606c2e0f7e85ba3730f7b6f378ef0802e87d0fd8 100644 --- a/modules/module-pw-audio-softdsp-endpoint.c +++ b/modules/module-pw-audio-softdsp-endpoint.c @@ -34,6 +34,7 @@ struct _WpPwAudioSoftdspEndpoint /* Properties */ WpProxyNode *proxy_node; GVariant *streams; + char *role; guint stream_count; gboolean selected; @@ -50,6 +51,7 @@ enum { PROP_0, PROP_PROXY_NODE, PROP_STREAMS, + PROP_ROLE, }; static GAsyncInitableIface *wp_endpoint_parent_interface = NULL; @@ -96,6 +98,10 @@ endpoint_prepare_link (WpEndpoint * ep, guint32 stream_id, WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (ep); WpAudioStream *stream = NULL; + /* Link with the adapter if stream id is none */ + if (stream_id == WP_STREAM_ID_NONE) + return wp_audio_stream_prepare_link (self->adapter, properties, error); + /* Make sure the stream Id is valid */ g_return_val_if_fail(stream_id < self->converters->len, FALSE); @@ -180,6 +186,13 @@ on_audio_adapter_created(GObject *initable, GAsyncResult *res, g_object_set (self, "name", name, NULL); } + /* Set the role */ + self->role = g_strdup (wp_properties_get (props, PW_KEY_MEDIA_ROLE)); + + /* Just finish if no streams need to be created */ + if (!self->streams) + return finish_endpoint_creation (self); + /* Create the audio converters */ g_variant_iter_init (&iter, self->streams); for (i = 0; g_variant_iter_next (&iter, "&s", &stream); i++) { @@ -212,6 +225,7 @@ endpoint_finalize (GObject * object) g_clear_object(&self->init_task); g_clear_object(&self->proxy_node); + g_free (self->role); G_OBJECT_CLASS (endpoint_parent_class)->finalize (object); } @@ -229,6 +243,10 @@ endpoint_set_property (GObject * object, guint property_id, case PROP_STREAMS: self->streams = g_value_dup_variant(value); break; + case PROP_ROLE: + g_free (self->role); + self->role = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -248,6 +266,9 @@ endpoint_get_property (GObject * object, guint property_id, case PROP_STREAMS: g_value_set_variant (value, self->streams); break; + case PROP_ROLE: + g_value_set_string (value, self->role); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -376,6 +397,10 @@ endpoint_class_init (WpPwAudioSoftdspEndpointClass * klass) "The stream names for the streams to create", G_VARIANT_TYPE ("as"), NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_ROLE, + g_param_spec_string ("role", "role", "The role of the wrapped node", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } void @@ -404,9 +429,8 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties, return; if (!g_variant_lookup (properties, "proxy-node", "t", &node)) return; - if (!(streams = g_variant_lookup_value (properties, "streams", - G_VARIANT_TYPE ("as")))) - return; + streams = g_variant_lookup_value (properties, "streams", + G_VARIANT_TYPE ("as")); /* Create and return the softdsp endpoint object */ g_async_initable_new_async ( diff --git a/modules/module-pw-audio-softdsp-endpoint/adapter.c b/modules/module-pw-audio-softdsp-endpoint/adapter.c index 371d241e82811fb805f1298c5e0f943fc901feca..84cfc51269efb5d5ab34da74584d74a1ce6eccfe 100644 --- a/modules/module-pw-audio-softdsp-endpoint/adapter.c +++ b/modules/module-pw-audio-softdsp-endpoint/adapter.c @@ -35,49 +35,36 @@ G_DEFINE_TYPE_WITH_CODE (WpAudioAdapter, wp_audio_adapter, WP_TYPE_AUDIO_STREAM, wp_audio_adapter_async_initable_init)) static void -on_proxy_enum_format_done (WpProxyNode *proxy, GAsyncResult *res, - WpAudioAdapter *self) +wp_audio_adapter_init_async (GAsyncInitable *initable, int io_priority, + GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data) { - g_autoptr (GPtrArray) formats = NULL; - g_autoptr (GError) error = NULL; + WpAudioAdapter *self = WP_AUDIO_ADAPTER(initable); enum pw_direction direction = wp_audio_stream_get_direction (WP_AUDIO_STREAM (self)); uint8_t buf[1024]; struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); struct spa_pod *param; - uint32_t media_type, media_subtype; struct spa_audio_info_raw fmt_raw; - formats = wp_proxy_node_enum_params_collect_finish (proxy, res, &error); - if (error) { - g_message("WpAudioAdapter:%p enum format error: %s", self, error->message); - wp_audio_stream_init_task_finish (WP_AUDIO_STREAM (self), - g_steal_pointer (&error)); - return; - } - - if (formats->len == 0 || - !(param = g_ptr_array_index (formats, 0)) || - spa_format_parse (param, &media_type, &media_subtype) < 0 || - media_type != SPA_MEDIA_TYPE_audio || - media_subtype != SPA_MEDIA_SUBTYPE_raw) { - g_message("WpAudioAdapter:%p node does not support audio/raw format", self); - wp_audio_stream_init_task_finish (WP_AUDIO_STREAM (self), - g_error_new (WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED, - "node does not support audio/raw format")); - return; - } - - /* Parse the raw audio format */ - spa_pod_fixate (param); - spa_format_audio_raw_parse (param, &fmt_raw); + /* Call the parent interface */ + /* This will also augment the proxy and therefore bind it */ + wp_audio_adapter_parent_interface->init_async (initable, io_priority, + cancellable, callback, data); + /* Emit the ports */ if (self->convert) { param = spa_pod_builder_add_object(&pod_builder, SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction), SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_convert)); } else { + /* Use the default format */ + fmt_raw.format = SPA_AUDIO_FORMAT_F32P; + fmt_raw.flags = 1; + fmt_raw.rate = 48000; + fmt_raw.channels = 2; + fmt_raw.position[0] = SPA_AUDIO_CHANNEL_FL; + fmt_raw.position[1] = SPA_AUDIO_CHANNEL_FR; param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &fmt_raw); param = spa_pod_builder_add_object(&pod_builder, SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, @@ -85,26 +72,9 @@ on_proxy_enum_format_done (WpProxyNode *proxy, GAsyncResult *res, SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp), SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param)); } - wp_audio_stream_set_port_config (WP_AUDIO_STREAM (self), param); } -static void -wp_audio_adapter_init_async (GAsyncInitable *initable, int io_priority, - GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data) -{ - WpAudioAdapter *self = WP_AUDIO_ADAPTER(initable); - WpProxyNode *proxy = wp_audio_stream_get_proxy_node (WP_AUDIO_STREAM (self)); - - /* Call the parent interface */ - /* This will also augment the proxy and therefore bind it */ - wp_audio_adapter_parent_interface->init_async (initable, io_priority, - cancellable, callback, data); - - wp_proxy_node_enum_params_collect (proxy, SPA_PARAM_EnumFormat, NULL, NULL, - (GAsyncReadyCallback) on_proxy_enum_format_done, self); -} - static void wp_audio_adapter_async_initable_init (gpointer iface, gpointer iface_data) { diff --git a/modules/module-simple-policy.c b/modules/module-simple-policy.c index 7e413387bff57d7209e8368d71d257e23d616715..d02057bac2e0d91beae77665de5b95f7b0ae0da5 100644 --- a/modules/module-simple-policy.c +++ b/modules/module-simple-policy.c @@ -372,10 +372,10 @@ link_endpoint (WpPolicy *policy, WpEndpoint *ep, GVariant *target_props) /* Link the endpoint with the target */ if (is_capture) { - wp_endpoint_link_new (core, target, stream_id, ep, 0, + wp_endpoint_link_new (core, target, stream_id, ep, WP_STREAM_ID_NONE, on_endpoint_link_created, NULL); } else { - wp_endpoint_link_new (core, ep, 0, target, stream_id, + wp_endpoint_link_new (core, ep, WP_STREAM_ID_NONE, target, stream_id, on_endpoint_link_created, NULL); } @@ -388,7 +388,7 @@ handle_client (WpPolicy *policy, WpEndpoint *ep) const char *media_class = wp_endpoint_get_media_class(ep); GVariantDict d; gboolean is_capture = FALSE; - const gchar *role, *target_name = NULL; + const gchar *role; /* Detect if the client is doing capture or playback */ is_capture = g_str_has_prefix (media_class, "Stream/Input"); @@ -424,9 +424,6 @@ handle_client (WpPolicy *policy, WpEndpoint *ep) g_object_get (ep, "role", &role, NULL); if (role) g_variant_dict_insert (&d, "media.role", "s", role); - g_object_get (ep, "target", &target_name, NULL); - if (target_name) - g_variant_dict_insert (&d, "media.name", "s", target_name); if (!link_endpoint (policy, ep, g_variant_dict_end (&d))) g_info ("Could not find alsa target endpoint for client stream"); } @@ -504,18 +501,6 @@ compare_client_priority (gconstpointer a, gconstpointer b, gpointer user_data) ret = b_priority - a_priority; } - /* when role priority is equal, the newest client wins */ - if (ret == 0) { - guint64 a_time = 0, b_time = 0; - - g_object_get (ae, "creation-time", &a_time, NULL); - g_object_get (be, "creation-time", &b_time, NULL); - - /* since a_time and b_time are expressed in system monotonic time, - * there is absolutely no chance that they will be equal */ - ret = (b_time > a_time) ? 1 : -1; - } - return ret; } @@ -653,7 +638,6 @@ simple_policy_find_endpoint (WpPolicy *policy, GVariant *props, g_autoptr (WpCore) core = NULL; g_autoptr (GPtrArray) ptr_array = NULL; const char *action = NULL; - const char *name = NULL; const char *media_class = NULL; const char *role = NULL; WpEndpoint *ep; @@ -662,7 +646,6 @@ simple_policy_find_endpoint (WpPolicy *policy, GVariant *props, core = wp_policy_get_core (policy); g_variant_lookup (props, "action", "&s", &action); - g_variant_lookup (props, "media.name", "&s", &name); /* Get all the endpoints with the specific media class*/ g_variant_lookup (props, "media.class", "&s", &media_class); @@ -670,16 +653,10 @@ simple_policy_find_endpoint (WpPolicy *policy, GVariant *props, if (!ptr_array) return NULL; - /* Find the endpoint with the matching name, otherwise get the one with the - * "selected" flag (if it is an alsa endpoint) */ + /* Get the endpoint with the "selected" flag (if it is an alsa endpoint) */ for (i = 0; i < ptr_array->len; i++) { ep = g_ptr_array_index (ptr_array, i); - if (name) { - if (g_str_has_prefix(wp_endpoint_get_name (ep), name)) { - g_object_ref (ep); - goto select_stream; - } - } else if (g_str_has_prefix (media_class, "Alsa/")) { + if (g_str_has_prefix (media_class, "Alsa/")) { g_autoptr (GVariant) value = NULL; guint id;