pipewire: Hooked up default device change notifications.

main
Ryan C. Gordon 2023-07-03 03:05:51 -04:00
parent a93fcf2444
commit 1dffb72c1d
No known key found for this signature in database
GPG Key ID: FA148B892AB48044
2 changed files with 34 additions and 87 deletions

View File

@ -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?

View File

@ -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;