Commit 9667cccb authored by Julian Bouzas's avatar Julian Bouzas
Browse files

modules: move monitor device activation logic into a new device-activation module

parent 5a9cb768
Pipeline #151543 passed with stages
in 1 minute and 11 seconds
......@@ -15,7 +15,7 @@ shared_library(
)
reserve_device_interface_src = gnome.gdbus_codegen('reserve-device-interface',
sources: 'module-monitor/org.freedesktop.ReserveDevice1.xml',
sources: 'module-device-activation/org.freedesktop.ReserveDevice1.xml',
interface_prefix : 'org.freedesktop.ReserveDevice1.',
namespace : 'Wp'
)
......@@ -24,14 +24,25 @@ shared_library(
'wireplumber-module-monitor',
[
'module-monitor.c',
'module-monitor/reserve-node.c',
'module-monitor/reserve-device.c',
'module-monitor/dbus-device-reservation.c',
reserve_device_interface_src,
],
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-device-activation',
[
'module-device-activation.c',
'module-device-activation/reserve-node.c',
'module-device-activation/reserve-device.c',
'module-device-activation/dbus-device-reservation.c',
reserve_device_interface_src,
],
c_args : [common_c_args, '-DG_LOG_DOMAIN="m-device-activation"'],
install : true,
install_dir : wireplumber_module_dir,
dependencies : [wp_dep, pipewire_dep, giounix_dep],
)
......
/* WirePlumber
*
* Copyright © 2020 Collabora Ltd.
* @author Julian Bouzas <julian.bouzas@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include <wp/wp.h>
#include <pipewire/pipewire.h>
#include <spa/utils/keys.h>
#include "module-device-activation/reserve-device.h"
#include "module-device-activation/reserve-node.h"
G_DEFINE_QUARK (wp-module-device-activation-reserve, reserve);
enum {
PROP_0,
PROP_MODE,
};
struct _WpDeviceActivation
{
WpPlugin parent;
/* Props */
gchar *mode;
WpObjectManager *spa_devices_om;
WpObjectManager *nodes_om;
};
G_DECLARE_FINAL_TYPE (WpDeviceActivation, wp_device_activation, WP,
DEVICE_ACTIVATION, WpPlugin)
G_DEFINE_TYPE (WpDeviceActivation, wp_device_activation, WP_TYPE_PLUGIN)
static void
on_node_state_changed (WpNode * node, WpNodeState old, WpNodeState curr,
WpReserveNode * node_data)
{
g_return_if_fail (node_data);
switch (curr) {
case WP_NODE_STATE_IDLE:
/* Release reservation after 3 seconds */
wp_reserve_node_timeout_release (node_data, 3000);
break;
case WP_NODE_STATE_RUNNING:
/* Clear pending timeout if any and acquire reservation */
wp_reserve_node_acquire (node_data);
break;
default:
break;
}
}
static void
add_reserve_node_data (WpDeviceActivation * self, WpProxy *node,
WpProxy *device)
{
WpReserveDevice *device_data = NULL;
g_autoptr (WpReserveNode) node_data = NULL;
/* Only add reservation data on nodes whose device has reservation data */
device_data = g_object_get_qdata (G_OBJECT (device), reserve_quark ());
if (!device_data)
return;
/* Create the node reservation data */
node_data = wp_reserve_node_new (node, device_data);
/* Set the reserve node data on the node */
g_object_set_qdata_full (G_OBJECT (node), reserve_quark (), node_data,
g_object_unref);
/* Handle the info signal */
g_signal_connect_object (WP_NODE (node), "state-changed",
(GCallback) on_node_state_changed, node_data, 0);
}
static void
on_node_added (WpObjectManager *om, WpProxy *proxy, gpointer d)
{
WpDeviceActivation *self = WP_DEVICE_ACTIVATION (d);
const gchar *device_id = NULL;
g_autoptr (WpProxy) device = NULL;
/* Get the device associated with the node */
device_id = wp_proxy_get_property (proxy, PW_KEY_DEVICE_ID);
if (!device_id)
return;
device = wp_object_manager_lookup (self->spa_devices_om, WP_TYPE_SPA_DEVICE,
WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=i", atoi (device_id), NULL);
if (!device) {
wp_warning_object (self, "cannot find device for node reservation data");
return;
}
/* Add reserve data */
add_reserve_node_data (self, proxy, device);
}
static void
add_reserve_device_data (WpDeviceActivation * self, WpProxy *device,
gint card_id)
{
g_autoptr (WpCore) core = wp_proxy_get_core (WP_PROXY (device));
g_autoptr (WpProperties) props = wp_proxy_get_properties (device);
const char *app_dev_name = NULL;
g_autoptr (WpDbusDeviceReservation) reservation = NULL;
g_autoptr (WpReserveDevice) device_data = NULL;
app_dev_name = wp_properties_get (props, SPA_KEY_API_ALSA_PATH);
/* Create the dbus device reservation */
reservation = wp_dbus_device_reservation_new (card_id, "PipeWire", 10,
app_dev_name);
/* Create the reserve device data */
device_data = wp_reserve_device_new (device, reservation);
/* Set the reserve device data on the device */
g_object_set_qdata_full (G_OBJECT (device), reserve_quark (),
g_steal_pointer (&device_data), g_object_unref);
}
static void
on_device_added (WpObjectManager *om, WpProxy *proxy, gpointer d)
{
WpDeviceActivation *self = WP_DEVICE_ACTIVATION (d);
const gchar *card_id = NULL;
/* TODO: for now we only activate devices with the ALSA Card property set.
* However, we eventually need to handle Video and MIDI devices too */
card_id = wp_proxy_get_property (proxy, SPA_KEY_API_ALSA_CARD);
if (!card_id)
return;
/* Depending on the mode, activate or let dbus activate the devices */
if (self->mode && g_strcmp0 (self->mode, "dbus") == 0) {
add_reserve_device_data (self, proxy, atoi (card_id));
} else {
g_autoptr (WpSpaPod) profile = wp_spa_pod_new_object (
"Profile", "Profile",
"index", "i", 1,
NULL);
wp_proxy_set_param (proxy, "Profile", profile);
}
}
static void
wp_device_activation_activate (WpPlugin * plugin)
{
WpDeviceActivation *self = WP_DEVICE_ACTIVATION (plugin);
g_autoptr (WpCore) core = wp_plugin_get_core (WP_PLUGIN (self));
/* Create the devices object manager and handle the device added signal */
self->spa_devices_om = wp_object_manager_new ();
wp_object_manager_add_interest (self->spa_devices_om, WP_TYPE_SPA_DEVICE,
NULL);
wp_object_manager_request_proxy_features (self->spa_devices_om,
WP_TYPE_SPA_DEVICE, WP_PROXY_FEATURE_BOUND);
g_signal_connect_object (self->spa_devices_om, "object-added",
G_CALLBACK (on_device_added), self, 0);
wp_core_install_object_manager (core, self->spa_devices_om);
/* Create the nodes object manager and handle the node added signal */
self->nodes_om = wp_object_manager_new ();
wp_object_manager_add_interest (self->nodes_om, WP_TYPE_NODE, NULL);
wp_object_manager_request_proxy_features (self->nodes_om, WP_TYPE_NODE,
WP_PROXY_FEATURES_STANDARD);
g_signal_connect_object (self->nodes_om, "object-added",
G_CALLBACK (on_node_added), self, 0);
wp_core_install_object_manager (core, self->nodes_om);
}
static void
wp_device_activation_deactivate (WpPlugin * plugin)
{
WpDeviceActivation *self = WP_DEVICE_ACTIVATION (plugin);
g_clear_object (&self->nodes_om);
g_clear_object (&self->spa_devices_om);
}
static void
wp_monitor_set_property (GObject * object, guint property_id,
const GValue * value, GParamSpec * pspec)
{
WpDeviceActivation *self = WP_DEVICE_ACTIVATION (object);
switch (property_id) {
case PROP_MODE:
g_clear_pointer (&self->mode, g_free);
self->mode = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
wp_monitor_get_property (GObject * object, guint property_id, GValue * value,
GParamSpec * pspec)
{
WpDeviceActivation *self = WP_DEVICE_ACTIVATION (object);
switch (property_id) {
case PROP_MODE:
g_value_set_string (value, self->mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
wp_monitor_finalize (GObject * object)
{
WpDeviceActivation *self = WP_DEVICE_ACTIVATION (object);
g_clear_pointer (&self->mode, g_free);
G_OBJECT_CLASS (wp_device_activation_parent_class)->finalize (object);
}
static void
wp_device_activation_init (WpDeviceActivation * self)
{
}
static void
wp_device_activation_class_init (WpDeviceActivationClass * klass)
{
GObjectClass *object_class = (GObjectClass *) klass;
WpPluginClass *plugin_class = (WpPluginClass *) klass;
object_class->finalize = wp_monitor_finalize;
object_class->set_property = wp_monitor_set_property;
object_class->get_property = wp_monitor_get_property;
plugin_class->activate = wp_device_activation_activate;
plugin_class->deactivate = wp_device_activation_deactivate;
/* Properties */
g_object_class_install_property (object_class, PROP_MODE,
g_param_spec_string ("mode", "mode",
"The mode to activate devices", NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
}
WP_PLUGIN_EXPORT void
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
{
const gchar *mode = NULL;
/* Get the mode */
g_variant_lookup (args, "mode", "s", &mode);
wp_plugin_register (g_object_new (wp_device_activation_get_type (),
"module", module,
"mode", mode,
NULL));
}
......@@ -14,18 +14,12 @@
#include <spa/monitor/device.h>
#include <spa/pod/builder.h>
#include "module-monitor/reserve-device.h"
#include "module-monitor/reserve-node.h"
G_DEFINE_QUARK (wp-module-monitor-id, id);
G_DEFINE_QUARK (wp-module-monitor-children, children);
G_DEFINE_QUARK (wp-module-monitor-data, data);
typedef enum {
FLAG_LOCAL_NODES = (1 << 0),
FLAG_USE_ADAPTER = (1 << 1),
FLAG_ACTIVATE_DEVICES = (1 << 2),
FLAG_DBUS_RESERVATION = (1 << 3),
} MonitorFlags;
static const struct {
......@@ -34,8 +28,6 @@ static const struct {
} flag_names[] = {
{ FLAG_LOCAL_NODES, "local-nodes" },
{ FLAG_USE_ADAPTER, "use-adapter" },
{ FLAG_ACTIVATE_DEVICES, "activate-devices" },
{ FLAG_DBUS_RESERVATION, "dbus-reservation" }
};
enum {
......@@ -280,54 +272,6 @@ find_child (GObject * parent, guint32 id, GList ** children, GList ** link,
}
}
static void
on_node_event_info (WpProxy * proxy, GParamSpec *spec, gpointer data)
{
WpReserveNode *node_data = data;
const struct pw_node_info *info = wp_proxy_get_info (proxy);
g_return_if_fail (node_data);
/* handle the different states */
switch (info->state) {
case PW_NODE_STATE_IDLE:
/* Release reservation after 3 seconds */
wp_reserve_node_timeout_release (node_data, 3000);
break;
case PW_NODE_STATE_RUNNING:
/* Clear pending timeout if any and acquire reservation */
wp_reserve_node_acquire (node_data);
break;
case PW_NODE_STATE_SUSPENDED:
break;
default:
break;
}
}
static void
add_reserve_node_data (WpMonitor * self, WpProxy *node, WpProxy *device)
{
WpReserveDevice *device_data = NULL;
g_autoptr (WpReserveNode) node_data = NULL;
/* Only add reservation data on nodes whose device has reservation data */
device_data = g_object_get_qdata (G_OBJECT (device), data_quark ());
if (!device_data)
return;
/* Create the node reservation data */
node_data = wp_reserve_node_new (node, device_data);
/* Handle the info signal */
g_signal_connect_object (WP_NODE (node), "notify::info",
(GCallback) on_node_event_info, node_data, 0);
/* Set the reserve node data on the node */
g_object_set_qdata_full (G_OBJECT (node), data_quark (),
g_steal_pointer (&node_data), g_object_unref);
}
static void
create_node (WpMonitor * self, WpProxy * parent, GList ** children,
guint id, const gchar * spa_factory, WpProperties * props,
......@@ -366,39 +310,6 @@ create_node (WpMonitor * self, WpProxy * parent, GList ** children,
g_object_set_qdata (G_OBJECT (node), id_quark (), GUINT_TO_POINTER (id));
*children = g_list_prepend (*children, node);
add_reserve_node_data (self, node, parent);
}
static void
add_reserve_device_data (WpMonitor * self, WpProxy *device)
{
g_autoptr (WpCore) core = wp_proxy_get_core (WP_PROXY (device));
g_autoptr (WpProperties) props = wp_proxy_get_properties (device);
const char *card_id = NULL;
const char *app_dev_name = NULL;
g_autoptr (WpDbusDeviceReservation) reservation = NULL;
g_autoptr (WpReserveDevice) device_data = NULL;
if ((self->flags & FLAG_DBUS_RESERVATION) == 0)
return;
card_id = wp_properties_get (props, SPA_KEY_API_ALSA_CARD);
if (!card_id)
return;
app_dev_name = wp_properties_get (props, SPA_KEY_API_ALSA_PATH);
/* Create the dbus device reservation */
reservation = wp_dbus_device_reservation_new (atoi(card_id),
"PipeWire", 10, app_dev_name);
/* Create the reserve device data */
device_data = wp_reserve_device_new (device, reservation);
/* Set the reserve device data on the device */
g_object_set_qdata_full (G_OBJECT (device), data_quark (),
g_steal_pointer (&device_data), g_object_unref);
}
static void
......@@ -411,16 +322,6 @@ device_created (GObject * proxy, GAsyncResult * res, gpointer user_data)
wp_warning_object (self, "%s", error->message);
return;
}
if (self->flags & FLAG_DBUS_RESERVATION) {
add_reserve_device_data (self, WP_PROXY (proxy));
} else if (self->flags & FLAG_ACTIVATE_DEVICES) {
g_autoptr (WpSpaPod) profile = wp_spa_pod_new_object (
"Profile", "Profile",
"index", "i", 1,
NULL);
wp_proxy_set_param (WP_PROXY (proxy), "Profile", profile);
}
}
static void
......
......@@ -21,7 +21,7 @@ load-module C libwireplumber-module-jack-device
load-module C libwireplumber-module-monitor {
"factory": <"api.alsa.enum.udev">,
"flags": <["use-adapter", "activate-devices", "dbus-reservation"]>
"flags": <["use-adapter"]>
}
# load-module C libwireplumber-module-monitor {
......@@ -33,6 +33,10 @@ load-module C libwireplumber-module-monitor {
"factory": <"api.v4l2.enum.udev">
}
load-module C libwireplumber-module-device-activation {
"mode": <"dbus">
}
load-module C libwireplumber-module-node-suspension
load-module C libwireplumber-module-session-settings
......
......@@ -9,7 +9,7 @@
#include <wp/wp.h>
#include <pipewire/pipewire.h>
#include "../../modules/module-monitor/dbus-device-reservation.h"
#include "../../modules/module-device-activation/dbus-device-reservation.h"
typedef struct {
GTestDBus *dbus_test;
......
......@@ -55,7 +55,7 @@ test(
executable('test-dbus-device-reservation',
[
'dbus-device-reservation.c',
'../../modules/module-monitor/dbus-device-reservation.c',
'../../modules/module-device-activation/dbus-device-reservation.c',
reserve_device_interface_src,
],
dependencies: common_deps + [giounix_dep], c_args: common_args),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment