From 90371440b0c35447b760eb4df606e76c50b5b21d Mon Sep 17 00:00:00 2001 From: Julian Bouzas Date: Thu, 19 Aug 2021 12:14:37 -0400 Subject: [PATCH] media-session: add alsa-no-dsp module Instruct the policy to not configure audio adapter nodes in DSP mode. Instead, Device nodes will always be configured in passthrough mode, and client nodes will be configured in convert or passthrough mode depending on whether the client format matches the device format or not. --- src/daemon/media-session.d/media-session.conf | 1 + src/examples/media-session/alsa-no-dsp.c | 51 +++++++++++++++++++ src/examples/media-session/media-session.c | 2 + src/examples/media-session/policy-node.c | 19 ++++++- src/examples/meson.build | 1 + 5 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 src/examples/media-session/alsa-no-dsp.c diff --git a/src/daemon/media-session.d/media-session.conf b/src/daemon/media-session.d/media-session.conf index b724d1e94..a32a23d73 100644 --- a/src/daemon/media-session.d/media-session.conf +++ b/src/daemon/media-session.d/media-session.conf @@ -84,6 +84,7 @@ session.modules = { #default-profile # restore default profiles #default-routes # restore default route #streams-follow-default # move streams when default changes + #alsa-no-dsp # do not configure audio nodes in DSP mode #alsa-seq # alsa seq midi support #alsa-monitor # alsa udev detection #bluez5 # bluetooth support diff --git a/src/examples/media-session/alsa-no-dsp.c b/src/examples/media-session/alsa-no-dsp.c new file mode 100644 index 000000000..ac78d101b --- /dev/null +++ b/src/examples/media-session/alsa-no-dsp.c @@ -0,0 +1,51 @@ +/* PipeWire + * + * Copyright © 2021 Collabora Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* + * Instruct policy-node to not configure audio adapter nodes in DSP mode. + * Device nodes will always be configured in passthrough mode. If a client node + * wants to be linked with a device node that has a different format, then the + * policy will configure the client node in convert mode so that both nodes + * have the same format. + * + * This is done by just setting a session property flag, and policy-node does the rest. + */ + +#include "config.h" + +#include "pipewire/pipewire.h" +#include "pipewire/extensions/metadata.h" + +#include "media-session.h" + +/** \page page_media_session_module_no_dsp Media Session Module: No DSP + */ + +#define KEY_NAME "policy-node.alsa-no-dsp" + +int sm_alsa_no_dsp_start(struct sm_media_session *session) +{ + pw_properties_set(session->props, KEY_NAME, "true"); + return 0; +} diff --git a/src/examples/media-session/media-session.c b/src/examples/media-session/media-session.c index 2f01f756e..7b94e5ba5 100644 --- a/src/examples/media-session/media-session.c +++ b/src/examples/media-session/media-session.c @@ -90,6 +90,7 @@ int sm_default_profile_start(struct sm_media_session *sess); int sm_default_routes_start(struct sm_media_session *sess); int sm_restore_stream_start(struct sm_media_session *sess); int sm_streams_follow_default_start(struct sm_media_session *sess); +int sm_alsa_no_dsp_start(struct sm_media_session *sess); int sm_alsa_midi_start(struct sm_media_session *sess); int sm_v4l2_monitor_start(struct sm_media_session *sess); int sm_libcamera_monitor_start(struct sm_media_session *sess); @@ -2390,6 +2391,7 @@ static const struct { { "default-routes", "restore default route", sm_default_routes_start, NULL }, { "restore-stream", "restore stream settings", sm_restore_stream_start, NULL }, { "streams-follow-default", "move streams when default changes", sm_streams_follow_default_start, NULL }, + { "alsa-no-dsp", "do not configure audio nodes in DSP mode", sm_alsa_no_dsp_start, NULL }, { "alsa-seq", "alsa seq midi support", sm_alsa_midi_start, NULL }, { "alsa-monitor", "alsa card udev detection", sm_alsa_monitor_start, NULL }, { "v4l2", "video for linux udev detection", sm_v4l2_monitor_start, NULL }, diff --git a/src/examples/media-session/policy-node.c b/src/examples/media-session/policy-node.c index 67e86e0f9..842001a10 100644 --- a/src/examples/media-session/policy-node.c +++ b/src/examples/media-session/policy-node.c @@ -92,6 +92,7 @@ struct impl { struct default_node defaults[4]; bool streams_follow_default; + bool alsa_no_dsp; }; struct node { @@ -279,6 +280,7 @@ static int configure_node(struct node *node, struct spa_audio_info *info, bool f struct spa_pod *param; struct spa_audio_info format; enum pw_direction direction; + uint32_t mode; if (node->configured && !force) { pw_log_debug("node %d is configured passthrough:%d", node->id, node->passthrough); @@ -292,7 +294,18 @@ static int configure_node(struct node *node, struct spa_audio_info *info, bool f format = node->format; - if (info != NULL && info->info.raw.channels > 0) { + if (impl->alsa_no_dsp) { + if ((info != NULL && memcmp(&node->format, info, sizeof(node->format)) == 0) || + node->type == NODE_TYPE_DEVICE) + mode = SPA_PARAM_PORT_CONFIG_MODE_passthrough; + else + mode = SPA_PARAM_PORT_CONFIG_MODE_convert; + } else { + mode = SPA_PARAM_PORT_CONFIG_MODE_dsp; + } + + if (mode != SPA_PARAM_PORT_CONFIG_MODE_passthrough && + info != NULL && info->info.raw.channels > 0) { pw_log_info("node %d monitor:%d channelmix %d->%d", node->id, node->monitor, format.info.raw.channels, info->info.raw.channels); @@ -313,7 +326,7 @@ static int configure_node(struct node *node, struct spa_audio_info *info, bool f param = spa_pod_builder_add_object(&b, 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_mode, SPA_POD_Id(mode), SPA_PARAM_PORT_CONFIG_monitor, SPA_POD_Bool(true), SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param)); @@ -1314,6 +1327,8 @@ int sm_policy_node_start(struct sm_media_session *session) flag = pw_properties_get(session->props, NAME ".streams-follow-default"); impl->streams_follow_default = (flag != NULL && pw_properties_parse_bool(flag)); + flag = pw_properties_get(session->props, NAME ".alsa-no-dsp"); + impl->alsa_no_dsp = (flag != NULL && pw_properties_parse_bool(flag)); spa_list_init(&impl->node_list); diff --git a/src/examples/meson.build b/src/examples/meson.build index 5d4fe27d7..e3e446297 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -66,6 +66,7 @@ if get_option('session-managers').contains('media-session') and alsa_dep.found() media_session_sources = [ 'media-session/access-flatpak.c', 'media-session/access-portal.c', + 'media-session/alsa-no-dsp.c', 'media-session/alsa-midi.c', 'media-session/alsa-monitor.c', 'media-session/alsa-endpoint.c',