diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 2baa2660b1..abcd2219fa 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -571,8 +571,13 @@ int SDL_InitAudio(const char *driver_name) SDL_AudioDevice *default_capture = NULL; current_audio.impl.DetectDevices(&default_output, &default_capture); - current_audio.default_output_device_id = default_output ? default_output->instance_id : 0; - current_audio.default_capture_device_id = default_capture ? default_capture->instance_id : 0; + // these are only set if default_* is non-NULL, in case the backend just called SDL_DefaultAudioDeviceChanged directly during DetectDevices. + if (default_output) { + current_audio.default_output_device_id = default_output->instance_id; + } + if (default_capture) { + current_audio.default_capture_device_id = default_capture->instance_id; + } // !!! FIXME: if a default is zero but there are devices available, should we just pick the first one? diff --git a/src/audio/pipewire/SDL_pipewire.c b/src/audio/pipewire/SDL_pipewire.c index 5309e21310..fc8efc539a 100644 --- a/src/audio/pipewire/SDL_pipewire.c +++ b/src/audio/pipewire/SDL_pipewire.c @@ -341,31 +341,6 @@ static void io_list_remove(Uint32 id) } } -static void io_list_sort(void) -{ - struct io_node *default_sink = NULL, *default_source = NULL; - struct io_node *n, *temp; - - /* Find and move the default nodes to the beginning of the list */ - spa_list_for_each_safe (n, temp, &hotplug_io_list, link) { - if (pipewire_default_sink_id != NULL && SDL_strcmp(n->path, pipewire_default_sink_id) == 0) { - default_sink = n; - spa_list_remove(&n->link); - } else if (pipewire_default_source_id != NULL && SDL_strcmp(n->path, pipewire_default_source_id) == 0) { - default_source = n; - spa_list_remove(&n->link); - } - } - - if (default_source) { - spa_list_prepend(&hotplug_io_list, &default_source->link); - } - - if (default_sink) { - spa_list_prepend(&hotplug_io_list, &default_sink->link); - } -} - static void io_list_clear(void) { struct io_node *n, *temp; @@ -387,19 +362,6 @@ static struct io_node *io_list_get_by_id(Uint32 id) return NULL; } -#if 0 -static struct io_node *io_list_get_by_path(char *path) -{ - struct io_node *n, *temp; - spa_list_for_each_safe (n, temp, &hotplug_io_list, link) { - if (SDL_strcmp(n->path, path) == 0) { - return n; - } - } - return NULL; -} -#endif - static void node_object_destroy(struct node_object *node) { SDL_assert(node); @@ -646,6 +608,23 @@ static char *get_name_from_json(const char *json) return SDL_strdup(value); } +static void change_default_device(const char *path) +{ + if (hotplug_events_enabled) { + struct io_node *n, *temp; + spa_list_for_each_safe (n, temp, &hotplug_io_list, link) { + if (SDL_strcmp(n->path, path) == 0) { + SDL_AudioDevice *device = SDL_ObtainPhysicalAudioDeviceByHandle(PW_ID_TO_HANDLE(n->id)); + if (device) { + SDL_UnlockMutex(device->lock); + SDL_DefaultAudioDeviceChanged(device); + } + return; // found it, we're done. + } + } + } +} + /* Metadata node callback */ static int metadata_property(void *object, Uint32 subject, const char *key, const char *type, const char *value) { @@ -658,12 +637,14 @@ static int metadata_property(void *object, Uint32 subject, const char *key, cons } pipewire_default_sink_id = get_name_from_json(value); node->persist = SDL_TRUE; + change_default_device(pipewire_default_sink_id); } 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; + change_default_device(pipewire_default_source_id); } } @@ -850,14 +831,15 @@ static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDe PIPEWIRE_pw_thread_loop_wait(hotplug_loop); } - /* Sort the I/O list so the default source/sink are listed first */ - io_list_sort(); - spa_list_for_each (io, &hotplug_io_list, link) { SDL_AudioDevice *device = SDL_AddAudioDevice(io->is_capture, io->name, &io->spec, PW_ID_TO_HANDLE(io->id)); -// !!! FIXME: obviously no -if (!io->is_capture && !*default_output) { *default_output = device; } -if (io->is_capture && !*default_capture) { *default_capture = device; } + if (pipewire_default_sink_id != NULL && SDL_strcmp(io->path, pipewire_default_sink_id) == 0) { + SDL_assert(!io->is_capture); + *default_output = device; + } else if (pipewire_default_source_id != NULL && SDL_strcmp(io->path, pipewire_default_source_id) == 0) { + SDL_assert(io->is_capture); + *default_capture = device; + } } hotplug_events_enabled = SDL_TRUE; @@ -1174,6 +1156,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%i", device->sample_frames, device->spec.freq); PIPEWIRE_pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", device->spec.freq); PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true"); + PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); // Requesting a specific device, don't migrate to new default hardware. /* * Pipewire 0.3.44 introduced PW_KEY_TARGET_OBJECT that takes either a path @@ -1257,46 +1240,6 @@ static void PIPEWIRE_CloseDevice(SDL_AudioDevice *device) SDL_AudioThreadFinalize(device); } -#if 0 -static int 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) { - ret = SDL_SetError("PipeWire could not find a default source"); - goto failed; - } - target = pipewire_default_source_id; - } else { - if (pipewire_default_sink_id == NULL) { - ret = SDL_SetError("PipeWire could not find a default sink"); - goto failed; - } - target = pipewire_default_sink_id; - } - - node = io_list_get_by_path(target); - if (node == NULL) { - 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 ret; -} -#endif - static void PIPEWIRE_Deinitialize(void) { if (pipewire_initialized) { @@ -1325,7 +1268,6 @@ static SDL_bool PIPEWIRE_Init(SDL_AudioDriverImpl *impl) impl->DetectDevices = PIPEWIRE_DetectDevices; impl->OpenDevice = PIPEWIRE_OpenDevice; impl->Deinitialize = PIPEWIRE_Deinitialize; - //impl->GetDefaultAudioInfo = PIPEWIRE_GetDefaultAudioInfo; impl->PlayDevice = PIPEWIRE_PlayDevice; impl->GetDeviceBuf = PIPEWIRE_GetDeviceBuf; impl->CaptureFromDevice = PIPEWIRE_CaptureFromDevice;