Files
wireplumber/modules/module-monitor.c
George Kiagiadakis 5de6364ae7 monitor & softdsp: fix alsa property names and api string
The alsa.pcm devices currently use "device.api" = "alsa:pcm"
but then the node overrides this later to just "alsa", which
is confusing. For now, let's match "alsa:pcm" in the monitor,
even though this does not appear on the node later.

This commit fixes device preferences in wireplumber.conf,
which were broken because the alsa endpoint names were empty
of info about the alsa device
2019-10-15 00:12:17 +03:00

250 lines
7.5 KiB
C

/* WirePlumber
*
* Copyright © 2019 Wim Taymans
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include <wp/wp.h>
#include <pipewire/pipewire.h>
#include <spa/utils/keys.h>
static void
setup_device_props (WpMonitor *self, WpProperties *p, WpModule *module)
{
const gchar *s, *d, *api;
api = wp_properties_get (p, SPA_KEY_DEVICE_API);
/* set the device name if it's not already set */
if (!wp_properties_get (p, SPA_KEY_DEVICE_NAME)) {
if ((s = wp_properties_get (p, SPA_KEY_DEVICE_BUS_ID)) == NULL) {
if ((s = wp_properties_get (p, SPA_KEY_DEVICE_BUS_PATH)) == NULL) {
s = wp_properties_get (p, WP_MONITOR_KEY_OBJECT_ID);
}
}
if (!g_strcmp0 (api, "alsa")) {
/* what we call a "device" in pipewire, in alsa it's a "card",
so make it clear to avoid confusion */
wp_properties_setf (p, PW_KEY_DEVICE_NAME, "alsa_card.%s", s);
} else {
wp_properties_setf (p, PW_KEY_DEVICE_NAME, "%s_device.%s", api, s);
}
}
/* set the device description if it's not already set */
if (!wp_properties_get (p, PW_KEY_DEVICE_DESCRIPTION)) {
d = NULL;
if (!g_strcmp0 (api, "alsa")) {
if ((s = wp_properties_get (p, PW_KEY_DEVICE_FORM_FACTOR))
&& !g_strcmp0 (s, "internal"))
d = "Built-in Audio";
else if ((s = wp_properties_get (p, PW_KEY_DEVICE_CLASS))
&& !g_strcmp0 (s, "modem"))
d = "Modem";
}
if (!d)
d = wp_properties_get (p, PW_KEY_DEVICE_PRODUCT_NAME);
if (!d)
d = "Unknown device";
wp_properties_set (p, PW_KEY_DEVICE_DESCRIPTION, d);
}
/* set the icon name for ALSA - TODO for other APIs */
if (!wp_properties_get (p, PW_KEY_DEVICE_ICON_NAME)
&& !g_strcmp0 (api, "alsa"))
{
d = NULL;
if ((s = wp_properties_get (p, PW_KEY_DEVICE_FORM_FACTOR))) {
if (!g_strcmp0 (s, "microphone"))
d = "audio-input-microphone";
else if (!g_strcmp0 (s, "webcam"))
d = "camera-web";
else if (!g_strcmp0 (s, "computer"))
d = "computer";
else if (!g_strcmp0 (s, "handset"))
d = "phone";
else if (!g_strcmp0 (s, "portable"))
d = "multimedia-player";
else if (!g_strcmp0 (s, "tv"))
d = "video-display";
else if (!g_strcmp0 (s, "headset"))
d = "audio-headset";
else if (!g_strcmp0 (s, "headphone"))
d = "audio-headphones";
else if (!g_strcmp0 (s, "speaker"))
d = "audio-speakers";
else if (!g_strcmp0 (s, "hands-free"))
d = "audio-handsfree";
}
if (!d)
if ((s = wp_properties_get (p, PW_KEY_DEVICE_CLASS))
&& !g_strcmp0 (s, "modem"))
d = "modem";
if (!d)
d = "audio-card";
s = wp_properties_get (p, PW_KEY_DEVICE_BUS);
wp_properties_setf (p, PW_KEY_DEVICE_ICON_NAME,
"%s-analog%s%s", d, s ? "-" : "", s);
}
}
static void
setup_node_props (WpMonitor *self, WpProperties *dev_props,
WpProperties *node_props, WpModule *module)
{
const gchar *api, *name, *description, *factory;
/* Make the device properties directly available on the node */
wp_properties_copy_keys (dev_props, node_props,
SPA_KEY_DEVICE_API,
SPA_KEY_DEVICE_NAME,
SPA_KEY_DEVICE_ALIAS,
SPA_KEY_DEVICE_NICK,
SPA_KEY_DEVICE_DESCRIPTION,
SPA_KEY_DEVICE_ICON,
SPA_KEY_DEVICE_ICON_NAME,
SPA_KEY_DEVICE_PLUGGED_USEC,
SPA_KEY_DEVICE_BUS_ID,
SPA_KEY_DEVICE_BUS_PATH,
SPA_KEY_DEVICE_BUS,
SPA_KEY_DEVICE_SUBSYSTEM,
SPA_KEY_DEVICE_SYSFS_PATH,
SPA_KEY_DEVICE_VENDOR_ID,
SPA_KEY_DEVICE_VENDOR_NAME,
SPA_KEY_DEVICE_PRODUCT_ID,
SPA_KEY_DEVICE_PRODUCT_NAME,
SPA_KEY_DEVICE_SERIAL,
SPA_KEY_DEVICE_CLASS,
SPA_KEY_DEVICE_CAPABILITIES,
SPA_KEY_DEVICE_FORM_FACTOR,
PW_KEY_DEVICE_INTENDED_ROLES,
NULL);
/* get some strings that we are going to need below */
api = wp_properties_get (node_props, SPA_KEY_DEVICE_API);
factory = wp_properties_get (node_props, PW_KEY_FACTORY_NAME);
name = wp_properties_get (node_props, SPA_KEY_DEVICE_NAME);
if (G_UNLIKELY (!name))
name = wp_properties_get (node_props, SPA_KEY_DEVICE_NICK);
if (G_UNLIKELY (!name))
name = wp_properties_get (node_props, SPA_KEY_DEVICE_ALIAS);
if (G_UNLIKELY (!name))
name = "unknown-device";
description = wp_properties_get (node_props, SPA_KEY_DEVICE_DESCRIPTION);
if (!description)
description = name;
/* set ALSA specific properties */
if (!g_strcmp0 (api, "alsa:pcm")) {
const gchar *str;
/* compose the node name */
str = wp_properties_get (node_props, SPA_KEY_API_ALSA_PCM_ID);
wp_properties_setf (node_props, PW_KEY_NODE_NAME, "%s/%s/%s",
factory, name, str);
/* compose the node description */
str = wp_properties_get (node_props, SPA_KEY_API_ALSA_PCM_NAME);
wp_properties_setf (node_props, PW_KEY_NODE_DESCRIPTION, "%s: %s",
description, str);
wp_properties_copy_keys (dev_props, node_props,
SPA_KEY_API_ALSA_CARD,
SPA_KEY_API_ALSA_CARD_ID,
SPA_KEY_API_ALSA_CARD_COMPONENTS,
SPA_KEY_API_ALSA_CARD_DRIVER,
SPA_KEY_API_ALSA_CARD_NAME,
SPA_KEY_API_ALSA_CARD_LONGNAME,
SPA_KEY_API_ALSA_CARD_MIXERNAME,
NULL);
/* set BLUEZ 5 specific properties */
} else if (!g_strcmp0 (api, "bluez5")) {
const gchar *profile =
wp_properties_get (node_props, SPA_KEY_API_BLUEZ5_PROFILE);
/* compose the node name */
wp_properties_setf (node_props, PW_KEY_NODE_NAME, "%s/%s/%s",
factory, name, profile);
/* compose the node description */
wp_properties_setf (node_props, PW_KEY_NODE_DESCRIPTION, "%s (%s)",
description, profile);
wp_properties_copy_keys (dev_props, node_props,
SPA_KEY_API_BLUEZ5_PATH,
SPA_KEY_API_BLUEZ5_ADDRESS,
NULL);
/* set node properties for other APIs */
} else {
wp_properties_setf (node_props, PW_KEY_NODE_NAME, "%s/%s",
factory, name);
wp_properties_set (node_props, PW_KEY_NODE_DESCRIPTION, description);
}
}
static void
start_monitor (WpMonitor *monitor)
{
g_autoptr (GError) error = NULL;
if (!wp_monitor_start (monitor, &error)) {
g_message ("Failed to start monitor: %s", error->message);
}
}
void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
{
WpMonitor *monitor;
const gchar *factory = NULL;
WpMonitorFlags flags = 0;
GVariantIter *iter;
if (!g_variant_lookup (args, "factory", "&s", &factory)) {
g_message ("Failed to load monitor: no 'factory' key specified");
return;
}
if (g_variant_lookup (args, "flags", "as", &iter)) {
gchar *flag_str = NULL;
GFlagsValue *flag_val = NULL;
GFlagsClass *flag_class = g_type_class_ref (WP_TYPE_MONITOR_FLAGS);
while (g_variant_iter_loop (iter, "s", &flag_str)) {
flag_val = g_flags_get_value_by_nick (flag_class, flag_str);
if (flag_val)
flags |= flag_val->value;
}
g_variant_iter_free (iter);
}
monitor = wp_monitor_new (core, factory, NULL, flags);
g_signal_connect (monitor, "setup-device-props",
(GCallback) setup_device_props, module);
g_signal_connect (monitor, "setup-node-props",
(GCallback) setup_node_props, module);
wp_module_set_destroy_callback (module, g_object_unref, monitor);
/* Start the monitor when the connected callback is triggered */
g_signal_connect_object (core, "remote-state-changed::connected",
(GCallback) start_monitor, monitor, G_CONNECT_SWAPPED);
}