mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-22 11:38:13 +02:00
modules: add monitor reservation data API
This commit is contained in:
parent
daa8091666
commit
8887cce5b4
3 changed files with 505 additions and 0 deletions
|
|
@ -24,6 +24,7 @@ shared_library(
|
|||
'wireplumber-module-monitor',
|
||||
[
|
||||
'module-monitor.c',
|
||||
'module-monitor/reservation-data.c',
|
||||
'module-monitor/dbus-device-reservation.c',
|
||||
reserve_device_interface_src,
|
||||
],
|
||||
|
|
|
|||
450
modules/module-monitor/reservation-data.c
Normal file
450
modules/module-monitor/reservation-data.c
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2020 Collabora Ltd.
|
||||
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "reservation-data.h"
|
||||
|
||||
#include <spa/pod/builder.h>
|
||||
#include <pipewire/pipewire.h>
|
||||
|
||||
struct _WpMonitorDeviceReservationData
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
/* Props */
|
||||
GWeakRef device;
|
||||
WpMonitorDbusDeviceReservation *reservation;
|
||||
|
||||
guint n_acquired;
|
||||
};
|
||||
|
||||
enum {
|
||||
DEVICE_PROP_0,
|
||||
DEVICE_PROP_DEVICE,
|
||||
DEVICE_PROP_RESERVATION,
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (WpMonitorDeviceReservationData,
|
||||
wp_monitor_device_reservation_data, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
on_device_done (WpCore *core, GAsyncResult *res,
|
||||
WpMonitorDeviceReservationData *self)
|
||||
{
|
||||
if (self->reservation)
|
||||
wp_monitor_dbus_device_reservation_complete_release (self->reservation, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_reservation_acquired (GObject *obj, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
WpMonitorDeviceReservationData *self = user_data;
|
||||
WpMonitorDbusDeviceReservation *reserv =
|
||||
WP_MONITOR_DBUS_DEVICE_RESERVATION (obj);
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (WpProxy) device = NULL;
|
||||
char buf[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof(buf));
|
||||
|
||||
/* Finish */
|
||||
if (!wp_monitor_dbus_device_reservation_async_finish (reserv, res, &error)) {
|
||||
g_warning ("%s", error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the device */
|
||||
device = g_weak_ref_get (&self->device);
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
/* Set profile 1 */
|
||||
wp_proxy_set_param (device, SPA_PARAM_Profile, 0,
|
||||
spa_pod_builder_add_object(&b,
|
||||
SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
|
||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(1)));
|
||||
}
|
||||
|
||||
static void
|
||||
on_reservation_release (WpMonitorDbusDeviceReservation *reservation, int forced,
|
||||
WpMonitorDeviceReservationData *self)
|
||||
{
|
||||
g_autoptr (WpProxy) device = NULL;
|
||||
g_autoptr (WpCore) core = NULL;
|
||||
char buf[1024];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof(buf));
|
||||
|
||||
/* Get the device and core */
|
||||
device = g_weak_ref_get (&self->device);
|
||||
if (!device)
|
||||
return;
|
||||
core = wp_proxy_get_core (device);
|
||||
if (!core)
|
||||
return;
|
||||
|
||||
/* Set profile 0 */
|
||||
wp_proxy_set_param (device, SPA_PARAM_Profile, 0,
|
||||
spa_pod_builder_add_object(&b,
|
||||
SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
|
||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(0)));
|
||||
|
||||
/* Complete release on done */
|
||||
wp_core_sync (core, NULL, (GAsyncReadyCallback)on_device_done, self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_device_destroyed (WpProxy *device, WpMonitorDeviceReservationData *self)
|
||||
{
|
||||
wp_monitor_dbus_device_reservation_release (self->reservation);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_device_reservation_data_constructed (GObject * object)
|
||||
{
|
||||
WpMonitorDeviceReservationData *self =
|
||||
WP_MONITOR_DEVICE_RESERVATION_DATA (object);
|
||||
g_autoptr (WpProxy) device = g_weak_ref_get (&self->device);
|
||||
|
||||
/* Make sure the device is released when the pw proxy device is destroyed */
|
||||
g_return_if_fail (device);
|
||||
g_signal_connect_object (device, "pw-proxy-destroyed",
|
||||
(GCallback) on_device_destroyed, self, 0);
|
||||
|
||||
/* Handle the reservation signals */
|
||||
g_return_if_fail (self->reservation);
|
||||
g_signal_connect_object (self->reservation, "release",
|
||||
(GCallback) on_reservation_release, self, 0);
|
||||
|
||||
/* Try to acquire the device */
|
||||
wp_monitor_dbus_device_reservation_acquire (self->reservation, NULL,
|
||||
on_reservation_acquired, self);
|
||||
|
||||
G_OBJECT_CLASS (wp_monitor_device_reservation_data_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_device_reservation_data_get_property (GObject * object,
|
||||
guint property_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpMonitorDeviceReservationData *self =
|
||||
WP_MONITOR_DEVICE_RESERVATION_DATA (object);
|
||||
|
||||
switch (property_id) {
|
||||
case DEVICE_PROP_DEVICE:
|
||||
g_value_take_object (value, g_weak_ref_get (&self->device));
|
||||
break;
|
||||
case DEVICE_PROP_RESERVATION:
|
||||
g_value_set_object (value, self->reservation);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_device_reservation_data_set_property (GObject * object,
|
||||
guint property_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpMonitorDeviceReservationData *self =
|
||||
WP_MONITOR_DEVICE_RESERVATION_DATA (object);
|
||||
|
||||
switch (property_id) {
|
||||
case DEVICE_PROP_DEVICE:
|
||||
g_weak_ref_set (&self->device, g_value_get_object (value));
|
||||
break;
|
||||
case DEVICE_PROP_RESERVATION:
|
||||
self->reservation = g_value_dup_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_device_reservation_data_finalize (GObject * object)
|
||||
{
|
||||
WpMonitorDeviceReservationData *self =
|
||||
WP_MONITOR_DEVICE_RESERVATION_DATA (object);
|
||||
|
||||
wp_monitor_dbus_device_reservation_release (self->reservation);
|
||||
|
||||
/* Props */
|
||||
g_weak_ref_clear (&self->device);
|
||||
g_clear_object (&self->reservation);
|
||||
|
||||
G_OBJECT_CLASS (wp_monitor_device_reservation_data_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_device_reservation_data_init (WpMonitorDeviceReservationData * self)
|
||||
{
|
||||
/* Props */
|
||||
g_weak_ref_init (&self->device, NULL);
|
||||
|
||||
self->n_acquired = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_device_reservation_data_class_init (
|
||||
WpMonitorDeviceReservationDataClass * klass)
|
||||
{
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
|
||||
object_class->constructed = wp_monitor_device_reservation_data_constructed;
|
||||
object_class->get_property = wp_monitor_device_reservation_data_get_property;
|
||||
object_class->set_property = wp_monitor_device_reservation_data_set_property;
|
||||
object_class->finalize = wp_monitor_device_reservation_data_finalize;
|
||||
|
||||
/* Props */
|
||||
g_object_class_install_property (object_class, DEVICE_PROP_DEVICE,
|
||||
g_param_spec_object ("device", "device", "The device", WP_TYPE_PROXY,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (object_class, DEVICE_PROP_RESERVATION,
|
||||
g_param_spec_object ("reservation", "reservation",
|
||||
"The dbus device reservation", WP_TYPE_MONITOR_DBUS_DEVICE_RESERVATION,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
WpMonitorDeviceReservationData *
|
||||
wp_monitor_device_reservation_data_new (WpProxy *device,
|
||||
WpMonitorDbusDeviceReservation *reservation)
|
||||
{
|
||||
return g_object_new (WP_TYPE_MONITOR_DEVICE_RESERVATION_DATA,
|
||||
"device", device,
|
||||
"reservation", reservation,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
wp_monitor_device_reservation_data_acquire (
|
||||
WpMonitorDeviceReservationData *self)
|
||||
{
|
||||
g_return_if_fail (WP_IS_MONITOR_DEVICE_RESERVATION_DATA (self));
|
||||
g_return_if_fail (self->reservation);
|
||||
|
||||
if (self->n_acquired == 0)
|
||||
wp_monitor_dbus_device_reservation_acquire (self->reservation, NULL,
|
||||
on_reservation_acquired, self);
|
||||
|
||||
self->n_acquired++;
|
||||
}
|
||||
|
||||
void
|
||||
wp_monitor_device_reservation_data_release (
|
||||
WpMonitorDeviceReservationData *self)
|
||||
{
|
||||
g_return_if_fail (WP_IS_MONITOR_DEVICE_RESERVATION_DATA (self));
|
||||
g_return_if_fail (self->reservation);
|
||||
|
||||
if (self->n_acquired == 1)
|
||||
wp_monitor_dbus_device_reservation_release (self->reservation);
|
||||
|
||||
self->n_acquired--;
|
||||
}
|
||||
|
||||
|
||||
struct _WpMonitorNodeReservationData
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
/* Props */
|
||||
GWeakRef node;
|
||||
WpMonitorDeviceReservationData *device_data;
|
||||
|
||||
gboolean acquired;
|
||||
GSource *timeout_source;
|
||||
};
|
||||
|
||||
enum {
|
||||
NODE_PROP_0,
|
||||
NODE_PROP_NODE,
|
||||
NODE_PROP_DEVICE_DATA,
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (WpMonitorNodeReservationData,
|
||||
wp_monitor_node_reservation_data, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
on_node_destroyed (WpProxy *node, WpMonitorNodeReservationData *self)
|
||||
{
|
||||
if (self->acquired)
|
||||
wp_monitor_device_reservation_data_release (self->device_data);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_node_reservation_data_constructed (GObject * object)
|
||||
{
|
||||
WpMonitorNodeReservationData *self =
|
||||
WP_MONITOR_NODE_RESERVATION_DATA (object);
|
||||
WpProxy *node = g_weak_ref_get (&self->node);
|
||||
|
||||
g_return_if_fail (node);
|
||||
|
||||
/* Make sure the device is released when the pw proxy node is destroyed */
|
||||
g_signal_connect_object (node, "pw-proxy-destroyed",
|
||||
(GCallback) on_node_destroyed, self, 0);
|
||||
|
||||
G_OBJECT_CLASS (wp_monitor_node_reservation_data_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_node_reservation_data_get_property (GObject * object,
|
||||
guint property_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpMonitorNodeReservationData *self =
|
||||
WP_MONITOR_NODE_RESERVATION_DATA (object);
|
||||
|
||||
switch (property_id) {
|
||||
case NODE_PROP_NODE:
|
||||
g_value_take_object (value, g_weak_ref_get (&self->node));
|
||||
break;
|
||||
case NODE_PROP_DEVICE_DATA:
|
||||
g_value_set_object (value, self->device_data);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_node_reservation_data_set_property (GObject * object,
|
||||
guint property_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
WpMonitorNodeReservationData *self =
|
||||
WP_MONITOR_NODE_RESERVATION_DATA (object);
|
||||
|
||||
switch (property_id) {
|
||||
case NODE_PROP_NODE:
|
||||
g_weak_ref_set (&self->node, g_value_get_object (value));
|
||||
break;
|
||||
case NODE_PROP_DEVICE_DATA:
|
||||
self->device_data = g_value_dup_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_node_reservation_data_finalize (GObject * object)
|
||||
{
|
||||
WpMonitorNodeReservationData *self =
|
||||
WP_MONITOR_NODE_RESERVATION_DATA (object);
|
||||
|
||||
/* Clear the current timeout release callback */
|
||||
if (self->timeout_source)
|
||||
g_source_destroy (self->timeout_source);
|
||||
g_clear_pointer (&self->timeout_source, g_source_unref);
|
||||
|
||||
/* Release device if acquired */
|
||||
if (self->acquired)
|
||||
wp_monitor_device_reservation_data_release (self->device_data);
|
||||
|
||||
/* Props */
|
||||
g_weak_ref_clear (&self->node);
|
||||
g_clear_object (&self->device_data);
|
||||
|
||||
G_OBJECT_CLASS (wp_monitor_node_reservation_data_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_node_reservation_data_init (WpMonitorNodeReservationData * self)
|
||||
{
|
||||
/* Props */
|
||||
g_weak_ref_init (&self->node, NULL);
|
||||
|
||||
self->acquired = FALSE;
|
||||
self->timeout_source = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
wp_monitor_node_reservation_data_class_init (
|
||||
WpMonitorNodeReservationDataClass * klass)
|
||||
{
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
|
||||
object_class->constructed = wp_monitor_node_reservation_data_constructed;
|
||||
object_class->get_property = wp_monitor_node_reservation_data_get_property;
|
||||
object_class->set_property = wp_monitor_node_reservation_data_set_property;
|
||||
object_class->finalize = wp_monitor_node_reservation_data_finalize;
|
||||
|
||||
/* Props */
|
||||
g_object_class_install_property (object_class, NODE_PROP_NODE,
|
||||
g_param_spec_object ("node", "node", "The node", WP_TYPE_PROXY,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
g_object_class_install_property (object_class, NODE_PROP_DEVICE_DATA,
|
||||
g_param_spec_object ("device-data", "device-data",
|
||||
"The monitor device reservation data", WP_TYPE_MONITOR_DEVICE_RESERVATION_DATA,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
WpMonitorNodeReservationData *
|
||||
wp_monitor_node_reservation_data_new (WpProxy *node,
|
||||
WpMonitorDeviceReservationData *device_data)
|
||||
{
|
||||
return g_object_new (WP_TYPE_MONITOR_NODE_RESERVATION_DATA,
|
||||
"node", node,
|
||||
"device-data", device_data,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout_release_callback (gpointer data)
|
||||
{
|
||||
WpMonitorNodeReservationData *self = data;
|
||||
g_return_val_if_fail (self, G_SOURCE_REMOVE);
|
||||
|
||||
wp_monitor_device_reservation_data_release (self->device_data);
|
||||
self->acquired = FALSE;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
wp_monitor_node_reservation_data_timeout_release (
|
||||
WpMonitorNodeReservationData *self, guint64 timeout_ms)
|
||||
{
|
||||
g_autoptr (WpProxy) node = NULL;
|
||||
g_autoptr (WpCore) core = NULL;
|
||||
g_return_if_fail (WP_IS_MONITOR_NODE_RESERVATION_DATA (self));
|
||||
|
||||
node = g_weak_ref_get (&self->node);
|
||||
g_return_if_fail (node);
|
||||
core = wp_proxy_get_core (node);
|
||||
g_return_if_fail (core);
|
||||
|
||||
/* Clear the current timeout release callback */
|
||||
if (self->timeout_source)
|
||||
g_source_destroy (self->timeout_source);
|
||||
g_clear_pointer (&self->timeout_source, g_source_unref);
|
||||
|
||||
/* Add new timeout release callback */
|
||||
wp_core_timeout_add (core, &self->timeout_source, timeout_ms,
|
||||
timeout_release_callback, g_object_ref (self), g_object_unref);
|
||||
}
|
||||
|
||||
void
|
||||
wp_monitor_node_reservation_data_acquire (WpMonitorNodeReservationData *self)
|
||||
{
|
||||
g_return_if_fail (WP_IS_MONITOR_NODE_RESERVATION_DATA (self));
|
||||
|
||||
/* Clear the current timeout release callback */
|
||||
if (self->timeout_source)
|
||||
g_source_destroy (self->timeout_source);
|
||||
g_clear_pointer (&self->timeout_source, g_source_unref);
|
||||
|
||||
/* Don't do anything if already acquired */
|
||||
if (self->acquired)
|
||||
return;
|
||||
|
||||
/* Acquire the device */
|
||||
wp_monitor_device_reservation_data_acquire (self->device_data);
|
||||
self->acquired = TRUE;
|
||||
}
|
||||
|
||||
54
modules/module-monitor/reservation-data.h
Normal file
54
modules/module-monitor/reservation-data.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2020 Collabora Ltd.
|
||||
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef __WIREPLUMBER_MONITOR_RESERVATION_DATA_H__
|
||||
#define __WIREPLUMBER_MONITOR_RESERVATION_DATA_H__
|
||||
|
||||
#include <wp/wp.h>
|
||||
|
||||
#include "dbus-device-reservation.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define WP_TYPE_MONITOR_DEVICE_RESERVATION_DATA (wp_monitor_device_reservation_data_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpMonitorDeviceReservationData,
|
||||
wp_monitor_device_reservation_data, WP, MONITOR_DEVICE_RESERVATION_DATA,
|
||||
GObject)
|
||||
|
||||
WpMonitorDeviceReservationData * wp_monitor_device_reservation_data_new (
|
||||
WpProxy *device, WpMonitorDbusDeviceReservation *reservation);
|
||||
|
||||
void
|
||||
wp_monitor_device_reservation_data_acquire (
|
||||
WpMonitorDeviceReservationData *self);
|
||||
|
||||
void
|
||||
wp_monitor_device_reservation_data_release (
|
||||
WpMonitorDeviceReservationData *self);
|
||||
|
||||
|
||||
#define WP_TYPE_MONITOR_NODE_RESERVATION_DATA (wp_monitor_node_reservation_data_get_type ())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpMonitorNodeReservationData,
|
||||
wp_monitor_node_reservation_data, WP, MONITOR_NODE_RESERVATION_DATA,
|
||||
GObject)
|
||||
|
||||
WpMonitorNodeReservationData * wp_monitor_node_reservation_data_new (
|
||||
WpProxy *node, WpMonitorDeviceReservationData *device_data);
|
||||
|
||||
void
|
||||
wp_monitor_node_reservation_data_timeout_release (
|
||||
WpMonitorNodeReservationData *self, guint64 timeout_ms);
|
||||
|
||||
void
|
||||
wp_monitor_node_reservation_data_acquire (WpMonitorNodeReservationData *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue