Commit cd3401bc authored by Julian Bouzas's avatar Julian Bouzas
Browse files

dbus-device-reservation: add owner-appeared/owner-vanished signals, and remove acquired callback

parent c8582d25
......@@ -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)
/* If the JACK server owns the audio device, we disable the audio device and
* enable the JACK device */
if (name && g_strcmp0 (name, JACK_APPLICATION_NAME) == 0) {
if (device)
set_device_profile (device, 0);
enable_jack_device (self);
return;
}
/* 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;
}
/* 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_acquired (GObject *obj, GAsyncResult *res, gpointer user_data)
on_reservation_owner_appeared (WpDbusDeviceReservation *reservation,
const gchar *owner, WpReserveDevice *self)
{
WpReserveDevice *self = user_data;
g_autoptr (GError) e = NULL;
g_autoptr (WpProxy) device = NULL;
/* 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);
}
/* If the audio device could not be acquired, check who owns it and maybe
* 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);
return;
}
static void
on_reservation_owner_vanished (WpDbusDeviceReservation *reservation,
WpReserveDevice *self)
{
g_autoptr (WpProxy) device = g_weak_ref_get (&self->device);
/* Always disable the JACK device because we are the owner */
disable_jack_device (self);
wp_info_object (self, "owner vanished");
/* Enable Audio device */
device = g_weak_ref_get (&self->device);
/* 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;
......
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