mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-05 05:28:01 +02:00
modules: implement a new module-monitor
This is a generic WpMonitor loader that sets up the WpMonitor properties from the module arguments and applies some well-known properties to the device & node objects
This commit is contained in:
parent
302e991b28
commit
e3ac60c0c0
2 changed files with 261 additions and 0 deletions
|
|
@ -25,6 +25,17 @@ shared_library(
|
|||
dependencies : [wp_dep],
|
||||
)
|
||||
|
||||
shared_library(
|
||||
'wireplumber-module-monitor',
|
||||
[
|
||||
'module-monitor.c',
|
||||
],
|
||||
c_args : [common_c_args, '-DG_LOG_DOMAIN="m-monitor"'],
|
||||
install : true,
|
||||
install_dir : wireplumber_module_dir,
|
||||
dependencies : [wp_dep, pipewire_dep],
|
||||
)
|
||||
|
||||
shared_library(
|
||||
'wireplumber-module-pipewire',
|
||||
[
|
||||
|
|
|
|||
250
modules/module-monitor.c
Normal file
250
modules/module-monitor.c
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/* 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 <spa/monitor/monitor.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")) {
|
||||
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, 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);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue