pipewire: Update default audio devices during runtime Make the default device metadata node persist for the lifetime of the hotplug loop so the default source/sink devices will be updated if they change during runtime.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c
index fd703ec..78d47d9 100644
--- a/src/audio/pipewire/SDL_pipewire.c
+++ b/src/audio/pipewire/SDL_pipewire.c
@@ -236,8 +236,9 @@ struct node_object
{
struct spa_list link;
- Uint32 id;
- int seq;
+ Uint32 id;
+ int seq;
+ SDL_bool persist;
/*
* NOTE: If used, this is *must* be allocated with SDL_malloc() or similar
@@ -491,7 +492,7 @@ core_events_metadata_callback(void *object, uint32_t id, int seq)
{
struct node_object *node = object;
- if (id == PW_ID_CORE && seq == node->seq) {
+ if (id == PW_ID_CORE && seq == node->seq && !node->persist) {
node_object_destroy(node);
}
}
@@ -646,17 +647,21 @@ get_name_from_json(const char *json)
static int
metadata_property(void *object, Uint32 subject, const char *key, const char *type, const char *value)
{
+ struct node_object *node = object;
+
if (subject == PW_ID_CORE && key != NULL && value != NULL) {
if (!SDL_strcmp(key, "default.audio.sink")) {
if (pipewire_default_sink_id != NULL) {
SDL_free(pipewire_default_sink_id);
}
pipewire_default_sink_id = get_name_from_json(value);
+ node->persist = SDL_TRUE;
} else if (!SDL_strcmp(key, "default.audio.source")) {
if (pipewire_default_source_id != NULL) {
SDL_free(pipewire_default_source_id);
}
pipewire_default_source_id = get_name_from_json(value);
+ node->persist = SDL_TRUE;
}
}
@@ -1286,31 +1291,38 @@ PIPEWIRE_GetDefaultAudioInfo(char **name, SDL_AudioSpec *spec, int iscapture)
{
struct io_node *node;
char *target;
+ int ret = 0;
+
+ PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
+
if (iscapture) {
if (pipewire_default_source_id == NULL) {
- return SDL_SetError("PipeWire could not find a default source");
+ ret = SDL_SetError("PipeWire could not find a default source");
+ goto failed;
}
target = pipewire_default_source_id;
} else {
if (pipewire_default_sink_id == NULL) {
- return SDL_SetError("PipeWire could not find a default sink");
+ ret = SDL_SetError("PipeWire could not find a default sink");
+ goto failed;
}
target = pipewire_default_sink_id;
}
- PIPEWIRE_pw_thread_loop_lock(hotplug_loop);
node = io_list_get(target);
if (node == NULL) {
- PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
- return SDL_SetError("PipeWire device list is out of sync with defaults");
+ ret = SDL_SetError("PipeWire device list is out of sync with defaults");
+ goto failed;
}
if (name != NULL) {
*name = SDL_strdup(node->name);
}
SDL_copyp(spec, &node->spec);
+
+failed:
PIPEWIRE_pw_thread_loop_unlock(hotplug_loop);
- return 0;
+ return ret;
}
static void