mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-05 08:58:01 +02:00
dbus-device-reservation: add owner-appeared/owner-vanished signals, and remove acquired callback
This commit is contained in:
parent
c8582d255e
commit
cd3401bcb5
4 changed files with 107 additions and 72 deletions
|
|
@ -29,6 +29,7 @@ struct _WpDbusDeviceReservation
|
|||
char *service_name;
|
||||
char *object_path;
|
||||
GDBusConnection *connection;
|
||||
guint watcher_id;
|
||||
guint owner_id;
|
||||
guint registered_id;
|
||||
GDBusMethodInvocation *pending_release;
|
||||
|
|
@ -48,6 +49,8 @@ enum {
|
|||
enum
|
||||
{
|
||||
SIGNAL_RELEASE,
|
||||
SIGNAL_OWNER_APPEARED,
|
||||
SIGNAL_OWNER_VANISHED,
|
||||
SIGNAL_LAST,
|
||||
};
|
||||
|
||||
|
|
@ -130,12 +133,6 @@ on_name_acquired (GDBusConnection *connection, const gchar *name,
|
|||
wp_debug_object (self, "name acquired");
|
||||
|
||||
self->connection = connection;
|
||||
|
||||
/* Trigger the acquired task */
|
||||
if (self->pending_task) {
|
||||
g_autoptr (GTask) task = g_steal_pointer (&self->pending_task);
|
||||
g_task_return_pointer (task, GUINT_TO_POINTER (TRUE), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -160,19 +157,25 @@ on_name_lost (GDBusConnection *connection, const gchar *name,
|
|||
/* Unregister object */
|
||||
wp_dbus_device_reservation_unregister_object (self);
|
||||
|
||||
/* If pending task is set, it means that we could not acquire the device, so
|
||||
* just return the pending task with an error. If pending task is not set, it
|
||||
* means that another audio server acquired the device with replacement, so we
|
||||
* trigger the release signal with forced set to TRUE */
|
||||
if (self->pending_task) {
|
||||
g_autoptr (GTask) task = g_steal_pointer (&self->pending_task);
|
||||
GError *error = g_error_new (WP_DOMAIN_LIBRARY,
|
||||
WP_LIBRARY_ERROR_OPERATION_FAILED,
|
||||
"dbus name lost before acquiring (connection=%p)", connection);
|
||||
g_task_return_error (task, error);
|
||||
} else {
|
||||
g_signal_emit (self, device_reservation_signals[SIGNAL_RELEASE], 0, TRUE);
|
||||
}
|
||||
/* Emit release signal with forced set to TRUE */
|
||||
g_signal_emit (self, device_reservation_signals[SIGNAL_RELEASE], 0, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_name_appeared (GDBusConnection *connection, const gchar *name,
|
||||
const gchar *owner, gpointer user_data)
|
||||
{
|
||||
WpDbusDeviceReservation *self = user_data;
|
||||
g_signal_emit (self, device_reservation_signals[SIGNAL_OWNER_APPEARED], 0,
|
||||
owner);
|
||||
}
|
||||
|
||||
static void
|
||||
on_name_vanished (GDBusConnection *connection, const gchar *name,
|
||||
gpointer user_data)
|
||||
{
|
||||
WpDbusDeviceReservation *self = user_data;
|
||||
g_signal_emit (self, device_reservation_signals[SIGNAL_OWNER_VANISHED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -186,6 +189,12 @@ wp_dbus_device_reservation_constructed (GObject * object)
|
|||
self->object_path = g_strdup_printf (DEVICE_RESERVATION_OBJECT_PREFIX
|
||||
"Audio%d", self->card_id);
|
||||
|
||||
/* Watch for the name */
|
||||
self->watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION, self->service_name,
|
||||
G_BUS_NAME_WATCHER_FLAGS_NONE, on_name_appeared, on_name_vanished, self,
|
||||
NULL);
|
||||
g_return_if_fail (self->watcher_id > 0);
|
||||
|
||||
G_OBJECT_CLASS (wp_dbus_device_reservation_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
|
|
@ -255,6 +264,10 @@ wp_dbus_device_reservation_finalize (GObject * object)
|
|||
}
|
||||
g_clear_pointer (&self->pending_property_name, g_free);
|
||||
|
||||
/* Unwatch the name */
|
||||
if (self->watcher_id > 0)
|
||||
g_bus_unwatch_name (self->watcher_id);
|
||||
|
||||
/* Unregister and release */
|
||||
wp_dbus_device_reservation_unregister_object (self);
|
||||
wp_dbus_device_reservation_release (self);
|
||||
|
|
@ -307,6 +320,12 @@ wp_dbus_device_reservation_class_init (WpDbusDeviceReservationClass * klass)
|
|||
device_reservation_signals[SIGNAL_RELEASE] = g_signal_new (
|
||||
"release", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
||||
device_reservation_signals[SIGNAL_OWNER_APPEARED] = g_signal_new (
|
||||
"owner-appeared", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING);
|
||||
device_reservation_signals[SIGNAL_OWNER_VANISHED] = g_signal_new (
|
||||
"owner-vanished", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL, G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
WpDbusDeviceReservation *
|
||||
|
|
@ -356,17 +375,13 @@ on_unowned (gpointer user_data)
|
|||
}
|
||||
|
||||
gboolean
|
||||
wp_dbus_device_reservation_acquire (WpDbusDeviceReservation *self,
|
||||
GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
|
||||
wp_dbus_device_reservation_acquire (WpDbusDeviceReservation *self)
|
||||
{
|
||||
g_return_val_if_fail (WP_IS_DBUS_DEVICE_RESERVATION (self), FALSE);
|
||||
g_return_val_if_fail (!self->pending_task, FALSE);
|
||||
if (self->owner_id > 0)
|
||||
return FALSE;
|
||||
|
||||
/* Set the new task */
|
||||
self->pending_task = g_task_new (self, cancellable, callback, user_data);
|
||||
|
||||
/* Aquire */
|
||||
self->owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, self->service_name,
|
||||
self->priority < INT32_MAX ?
|
||||
|
|
|
|||
|
|
@ -30,9 +30,7 @@ void wp_dbus_device_reservation_release (WpDbusDeviceReservation *self);
|
|||
void wp_dbus_device_reservation_complete_release (WpDbusDeviceReservation *self,
|
||||
gboolean res);
|
||||
|
||||
gboolean wp_dbus_device_reservation_acquire (WpDbusDeviceReservation *self,
|
||||
GCancellable *cancellable, GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gboolean wp_dbus_device_reservation_acquire (WpDbusDeviceReservation *self);
|
||||
|
||||
gboolean wp_dbus_device_reservation_request_release (
|
||||
WpDbusDeviceReservation *self, GCancellable *cancellable,
|
||||
|
|
|
|||
|
|
@ -108,9 +108,10 @@ on_device_done (WpCore *core, GAsyncResult *res, WpReserveDevice *self)
|
|||
}
|
||||
|
||||
static void
|
||||
on_application_name_done (GObject *obj, GAsyncResult *res, gpointer user_data)
|
||||
on_application_name_appeared (GObject *obj, GAsyncResult *res, gpointer data)
|
||||
{
|
||||
WpReserveDevice *self = user_data;
|
||||
WpReserveDevice *self = data;
|
||||
g_autoptr (WpProxy) device = g_weak_ref_get (&self->device);
|
||||
g_autoptr (GError) e = NULL;
|
||||
g_autofree gchar *name = NULL;
|
||||
|
||||
|
|
@ -123,36 +124,57 @@ on_application_name_done (GObject *obj, GAsyncResult *res, gpointer user_data)
|
|||
return;
|
||||
}
|
||||
|
||||
wp_info_object (self, "owner: %s", name ? name : "unknown");
|
||||
wp_info_object (self, "owner appeared: %s", name ? name : "unknown");
|
||||
|
||||
/* Only enable the JACK device if the owner is the JACK audio server */
|
||||
if (name && g_strcmp0 (name, JACK_APPLICATION_NAME) == 0)
|
||||
enable_jack_device (self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_reservation_acquired (GObject *obj, GAsyncResult *res, gpointer user_data)
|
||||
{
|
||||
WpReserveDevice *self = user_data;
|
||||
g_autoptr (GError) e = NULL;
|
||||
g_autoptr (WpProxy) device = NULL;
|
||||
|
||||
/* If the audio device could not be acquired, check who owns it and maybe
|
||||
/* If the JACK server owns the audio device, we disable the audio device and
|
||||
* enable the JACK device */
|
||||
if (!wp_dbus_device_reservation_async_finish (self->reservation, res, &e)) {
|
||||
wp_info_object (self, "could not own device: %s", e->message);
|
||||
wp_dbus_device_reservation_request_property (self->reservation,
|
||||
"ApplicationName", NULL, on_application_name_done, self);
|
||||
if (name && g_strcmp0 (name, JACK_APPLICATION_NAME) == 0) {
|
||||
if (device)
|
||||
set_device_profile (device, 0);
|
||||
enable_jack_device (self);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Always disable the JACK device because we are the owner */
|
||||
disable_jack_device (self);
|
||||
/* If we (PipeWire) own the audio device, we enable the audio device and
|
||||
* disable the JACK device */
|
||||
else if (name && g_strcmp0 (name, PIPEWIRE_APPLICATION_NAME) == 0) {
|
||||
disable_jack_device (self);
|
||||
if (device)
|
||||
set_device_profile (device, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable Audio device */
|
||||
device = g_weak_ref_get (&self->device);
|
||||
/* If another server different to JACK and PipeWire (ie PulseAudio) owns the
|
||||
* device, we disable both the audio device and the JACK device */
|
||||
else {
|
||||
disable_jack_device (self);
|
||||
if (device)
|
||||
set_device_profile (device, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_reservation_owner_appeared (WpDbusDeviceReservation *reservation,
|
||||
const gchar *owner, WpReserveDevice *self)
|
||||
{
|
||||
/* Request the application name to know who is the new owner */
|
||||
wp_dbus_device_reservation_request_property (self->reservation,
|
||||
"ApplicationName", NULL, on_application_name_appeared, self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_reservation_owner_vanished (WpDbusDeviceReservation *reservation,
|
||||
WpReserveDevice *self)
|
||||
{
|
||||
g_autoptr (WpProxy) device = g_weak_ref_get (&self->device);
|
||||
|
||||
wp_info_object (self, "owner vanished");
|
||||
|
||||
/* Always disable both JACK device and audio device when owner vanishes. The
|
||||
* devices will always be enabled later when a new owner appears */
|
||||
disable_jack_device (self);
|
||||
if (device)
|
||||
set_device_profile (device, 1);
|
||||
set_device_profile (device, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -215,12 +237,15 @@ wp_reserve_device_constructed (GObject * object)
|
|||
|
||||
/* Handle the reservation signals */
|
||||
g_return_if_fail (self->reservation);
|
||||
g_signal_connect_object (self->reservation, "owner-appeared",
|
||||
(GCallback) on_reservation_owner_appeared, self, 0);
|
||||
g_signal_connect_object (self->reservation, "owner-vanished",
|
||||
(GCallback) on_reservation_owner_vanished, self, 0);
|
||||
g_signal_connect_object (self->reservation, "release",
|
||||
(GCallback) on_reservation_release, self, 0);
|
||||
|
||||
/* Try to acquire the device */
|
||||
wp_dbus_device_reservation_acquire (self->reservation, NULL,
|
||||
on_reservation_acquired, self);
|
||||
wp_dbus_device_reservation_acquire (self->reservation);
|
||||
|
||||
G_OBJECT_CLASS (wp_reserve_device_parent_class)->constructed (object);
|
||||
}
|
||||
|
|
@ -325,8 +350,7 @@ wp_reserve_device_acquire (WpReserveDevice *self)
|
|||
g_return_if_fail (self->reservation);
|
||||
|
||||
if (self->n_acquired == 0)
|
||||
wp_dbus_device_reservation_acquire (self->reservation, NULL,
|
||||
on_reservation_acquired, self);
|
||||
wp_dbus_device_reservation_acquire (self->reservation);
|
||||
|
||||
self->n_acquired++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
typedef struct {
|
||||
GTestDBus *dbus_test;
|
||||
GMainLoop *loop;
|
||||
gboolean acquired;
|
||||
gboolean owner_appeared;
|
||||
gboolean released;
|
||||
gpointer property;
|
||||
} TestDbusFixture;
|
||||
|
|
@ -45,14 +45,10 @@ on_reservation_release (WpDbusDeviceReservation *reservation,
|
|||
}
|
||||
|
||||
static void
|
||||
on_acquired_done (GObject *obj, GAsyncResult *res, gpointer user_data)
|
||||
on_reservation_owner_appeared (WpDbusDeviceReservation *reservation,
|
||||
const gchar *owner, TestDbusFixture *self)
|
||||
{
|
||||
TestDbusFixture *self = user_data;
|
||||
WpDbusDeviceReservation *r = WP_DBUS_DEVICE_RESERVATION (obj);
|
||||
g_autoptr (GError) e = NULL;
|
||||
wp_dbus_device_reservation_async_finish (r, res, &e);
|
||||
g_assert_null (e);
|
||||
self->acquired = TRUE;
|
||||
self->owner_appeared = TRUE;
|
||||
g_main_loop_quit (self->loop);
|
||||
}
|
||||
|
||||
|
|
@ -102,12 +98,15 @@ test_dbus_basic (TestDbusFixture *self, gconstpointer data)
|
|||
r1 = create_representation (self, 0, "Server", 10, "hw:0,0");
|
||||
r2 = create_representation (self, 0, "PipeWire", 15, "hw:0,0");
|
||||
|
||||
/* Only handle owner-appeared on r1 */
|
||||
g_signal_connect (r1, "owner-appeared",
|
||||
(GCallback) on_reservation_owner_appeared, self);
|
||||
|
||||
/* Acquire the device on r1 */
|
||||
self->acquired = FALSE;
|
||||
g_assert_true (wp_dbus_device_reservation_acquire (r1, NULL,
|
||||
on_acquired_done, self));
|
||||
self->owner_appeared = FALSE;
|
||||
g_assert_true (wp_dbus_device_reservation_acquire (r1));
|
||||
g_main_loop_run (self->loop);
|
||||
g_assert_true (self->acquired);
|
||||
g_assert_true (self->owner_appeared);
|
||||
|
||||
/* Request the priority property on r1 and make sure it is 10 */
|
||||
self->property = NULL;
|
||||
|
|
@ -152,11 +151,10 @@ test_dbus_basic (TestDbusFixture *self, gconstpointer data)
|
|||
g_assert_true (self->released);
|
||||
|
||||
/* Acquire the device on r2 */
|
||||
self->acquired = FALSE;
|
||||
g_assert_true (wp_dbus_device_reservation_acquire (r2, NULL,
|
||||
on_acquired_done, self));
|
||||
self->owner_appeared = FALSE;
|
||||
g_assert_true (wp_dbus_device_reservation_acquire (r2));
|
||||
g_main_loop_run (self->loop);
|
||||
g_assert_true (self->acquired);
|
||||
g_assert_true (self->owner_appeared);
|
||||
|
||||
/* Request the priority property on r2 and make sure it is 15 */
|
||||
self->property = NULL;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue