audio: Prefer Pipewire over Pulseaudio if the pipewire-pulse service is running

Use DBus to query Systemd to check if the pipewire-pulse service is in the "running" state. If it is, then it is certain that Pipewire is being used instead of Pulseaudio as the preferred system mixer.

If DBus support is not enabled or Systemd is not being used on the underlying system, this check will simply fail and the standard driver order will be tested.
This commit is contained in:
Frank Praznik
2024-04-01 09:07:02 -04:00
committed by Ryan C. Gordon
parent b6cb63adef
commit 60f26182c3
5 changed files with 136 additions and 5 deletions

View File

@@ -632,4 +632,73 @@ failed:
return NULL;
}
/* Check to see if a Systemd unit exists and is currently running. */
SDL_bool SDL_DBus_QuerySystemdUnitRunning(const char *unit_name, SDL_bool user_unit)
{
const char *path, *prop;
DBusError err;
SDL_bool running = SDL_FALSE;
/* Make sure we have a connection to the dbus session bus */
if (!SDL_DBus_GetContext() || !dbus.session_conn) {
/* We either cannot connect to the session bus or were unable to
* load the D-Bus library at all. */
return SDL_FALSE;
}
/* Make sure the appropriate bus is available. */
if ((user_unit && !dbus.session_conn) || (!user_unit && !dbus.system_conn)) {
return SDL_FALSE;
}
dbus.error_init(&err);
/* Get the object path for the unit. */
DBusMessage *method = dbus.message_new_method_call("org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"GetUnit");
if (!method) {
return SDL_FALSE;
}
if (!dbus.message_append_args(method, DBUS_TYPE_STRING, &unit_name, DBUS_TYPE_INVALID)) {
SDL_OutOfMemory();
dbus.message_unref(method);
return SDL_FALSE;
}
DBusMessage *reply = dbus.connection_send_with_reply_and_block(user_unit ? dbus.session_conn : dbus.system_conn, method, DBUS_TIMEOUT_USE_DEFAULT, &err);
dbus.message_unref(method);
if (!reply) {
if (dbus.error_is_set(&err)) {
SDL_SetError("%s: %s", err.name, err.message);
dbus.error_free(&err);
}
return SDL_FALSE;
}
DBusMessageIter reply_iter;
if (!dbus.message_iter_init(reply, &reply_iter)) {
goto done;
}
if (dbus.message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_OBJECT_PATH) {
goto done;
}
dbus.message_iter_get_basic(&reply_iter, &path);
/* We want to know the substate of the unit, which should be the string "running". */
if (SDL_DBus_QueryPropertyOnConnection(user_unit ? dbus.session_conn : dbus.system_conn,
"org.freedesktop.systemd1", path, "org.freedesktop.systemd1.Unit",
"SubState", DBUS_TYPE_STRING, &prop)) {
running = SDL_strcmp(prop, "running") == 0;
}
done:
dbus.message_unref(reply);
return running;
}
#endif

View File

@@ -109,6 +109,8 @@ extern char *SDL_DBus_GetLocalMachineId(void);
extern char **SDL_DBus_DocumentsPortalRetrieveFiles(const char *key, int *files_count);
extern SDL_bool SDL_DBus_QuerySystemdUnitRunning(const char *unit_name, SDL_bool user_unit);
#endif /* HAVE_DBUS_DBUS_H */
#endif /* SDL_dbus_h_ */