From 45586e83da5981bceefbcf0520e49208b4779311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Via=C4=8Das=C5=82a=C5=AD?= <viachaslavic@outlook.com> Date: Mon, 3 Feb 2025 06:30:02 +0300 Subject: [PATCH] (PipeWire) Pass the new_rate to the audio driver (#17508) Set the supported sample rate after initialization. Also a few minor fixes. --- audio/common/pipewire.c | 11 ++++----- audio/common/pipewire.h | 2 +- audio/drivers/pipewire.c | 33 ++++++++++++------------- audio/drivers_microphone/pipewire.c | 38 +++++++++++++---------------- 4 files changed, 39 insertions(+), 45 deletions(-) diff --git a/audio/common/pipewire.c b/audio/common/pipewire.c index 2f64656e62..e931254f52 100644 --- a/audio/common/pipewire.c +++ b/audio/common/pipewire.c @@ -203,20 +203,19 @@ void pipewire_core_deinit(pipewire_core_t *pw) pw_thread_loop_stop(pw->thread_loop); if (pw->registry) + { + spa_hook_remove(&pw->registry_listener); pw_proxy_destroy((struct pw_proxy*)pw->registry); + } if (pw->core) { spa_hook_remove(&pw->core_listener); - spa_zero(pw->core_listener); pw_core_disconnect(pw->core); } - if (pw->ctx) - pw_context_destroy(pw->ctx); - - if (pw->thread_loop) - pw_thread_loop_destroy(pw->thread_loop); + spa_clear_ptr(pw->ctx, pw_context_destroy); + spa_clear_ptr(pw->thread_loop, pw_thread_loop_destroy); if (pw->devicelist) string_list_free(pw->devicelist); diff --git a/audio/common/pipewire.h b/audio/common/pipewire.h index cb69c3c5a4..ee57ffb22f 100644 --- a/audio/common/pipewire.h +++ b/audio/common/pipewire.h @@ -33,7 +33,7 @@ #define PW_RARCH_MEDIA_TYPE_VIDEO "Video" #define PW_RARCH_MEDIA_TYPE_MIDI "Midi" #define PW_RARCH_MEDIA_CATEGORY_PLAYBACK "Playback" -#define PW_RARCH_MEDIA_CATEGORY_RECORD "Capture" +#define PW_RARCH_MEDIA_CATEGORY_RECORD "Capture" #define PW_RARCH_MEDIA_ROLE "Game" typedef struct pipewire_core diff --git a/audio/drivers/pipewire.c b/audio/drivers/pipewire.c index 00b51c77b2..e35548d736 100644 --- a/audio/drivers/pipewire.c +++ b/audio/drivers/pipewire.c @@ -61,6 +61,7 @@ static void playback_process_cb(void *data) uint32_t req, idx, n_bytes; int32_t avail; + retro_assert(audio); retro_assert(audio->stream); if ((b = pw_stream_dequeue_buffer(audio->stream)) == NULL) @@ -132,26 +133,22 @@ static void registry_event_global(void *data, uint32_t id, union string_list_elem_attr attr; const struct spa_dict_item *item; pipewire_core_t *pw = (pipewire_core_t*)data; - const char *media = NULL; const char *sink = NULL; - if (spa_streq(type, PW_TYPE_INTERFACE_Node)) + if (spa_streq(type, PW_TYPE_INTERFACE_Node) + && spa_streq("Audio/Sink", spa_dict_lookup(props, PW_KEY_MEDIA_CLASS))) { - media = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS); - if (media && spa_streq(media, "Audio/Sink")) + sink = spa_dict_lookup(props, PW_KEY_NODE_NAME); + if (sink && pw->devicelist) { - sink = spa_dict_lookup(props, PW_KEY_NODE_NAME); - if (sink && pw->devicelist) - { - attr.i = id; - string_list_append(pw->devicelist, sink, attr); - RARCH_LOG("[Audio] [PipeWire]: Found Sink Node: %s\n", sink); - } - - RARCH_DBG("[Audio] [PipeWire]: Object: id:%u Type:%s/%d\n", id, type, version); - spa_dict_for_each(item, props) - RARCH_DBG("[Audio] [PipeWire]: \t\t%s: \"%s\"\n", item->key, item->value); + attr.i = id; + string_list_append(pw->devicelist, sink, attr); + RARCH_LOG("[Audio] [PipeWire]: Found Sink Node: %s\n", sink); } + + RARCH_DBG("[Audio] [PipeWire]: Object: id:%u Type:%s/%d\n", id, type, version); + spa_dict_for_each(item, props) + RARCH_DBG("[Audio] [PipeWire]: \t\t%s: \"%s\"\n", item->key, item->value); } } @@ -225,15 +222,17 @@ static void *pipewire_init(const char *device, unsigned rate, PW_STREAM_FLAG_MAP_BUFFERS | PW_STREAM_FLAG_RT_PROCESS, params, 1); - if (res < 0) goto unlock_error; audio->highwater_mark = MIN(RINGBUFFER_SIZE, latency * (uint64_t)rate / 1000 * audio->frame_size); + pw_thread_loop_wait(audio->pw->thread_loop); pw_thread_loop_unlock(audio->pw->thread_loop); + *new_rate = audio->info.rate; + return audio; unlock_error: @@ -384,7 +383,7 @@ static void pipewire_free(void *data) pipewire_audio_t *audio = (pipewire_audio_t*)data; if (!audio) - return pw_deinit(); + return; if (audio->stream) { diff --git a/audio/drivers_microphone/pipewire.c b/audio/drivers_microphone/pipewire.c index 68b7bd7168..c6d2867905 100644 --- a/audio/drivers_microphone/pipewire.c +++ b/audio/drivers_microphone/pipewire.c @@ -72,7 +72,8 @@ static void capture_process_cb(void *data) uint32_t idx, offs, n_bytes; pipewire_microphone_t *mic = (pipewire_microphone_t*)data; - assert(mic->stream); + retro_assert(mic); + retro_assert(mic->stream); if (!(b = pw_stream_dequeue_buffer(mic->stream))) { @@ -120,28 +121,25 @@ static void registry_event_global(void *data, uint32_t id, union string_list_elem_attr attr; const struct spa_dict_item *item; pipewire_core_t *pw = (pipewire_core_t*)data; - const char *media = NULL; const char *sink = NULL; if (!pw) return; - if (spa_streq(type, PW_TYPE_INTERFACE_Node)) + if ( spa_streq(type, PW_TYPE_INTERFACE_Node) + && spa_streq("Audio/Source", spa_dict_lookup(props, PW_KEY_MEDIA_CLASS))) { - media = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS); - if (media && spa_streq(media, "Audio/Source")) + sink = spa_dict_lookup(props, PW_KEY_NODE_NAME); + if (sink && pw->devicelist) { - if ((sink = spa_dict_lookup(props, PW_KEY_NODE_NAME)) != NULL) - { - attr.i = id; - string_list_append(pw->devicelist, sink, attr); - RARCH_LOG("[Microphone] [PipeWire]: Found Source Node: %s\n", sink); - } - - RARCH_DBG("[Microphone] [PipeWire]: Object: id:%u Type:%s/%d\n", id, type, version); - spa_dict_for_each(item, props) - RARCH_DBG("[Microphone] [PipeWire]: \t\t%s: \"%s\"\n", item->key, item->value); + attr.i = id; + string_list_append(pw->devicelist, sink, attr); + RARCH_LOG("[Microphone] [PipeWire]: Found Source Node: %s\n", sink); } + + RARCH_DBG("[Microphone] [PipeWire]: Object: id:%u Type:%s/%d\n", id, type, version); + spa_dict_for_each(item, props) + RARCH_DBG("[Microphone] [PipeWire]: \t\t%s: \"%s\"\n", item->key, item->value); } } @@ -285,14 +283,12 @@ static void *pipewire_microphone_open_mic(void *driver_context, struct pw_properties *props = NULL; const char *error = NULL; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); - pipewire_microphone_t *mic = calloc(1, sizeof(pipewire_microphone_t)); + pipewire_microphone_t *mic = NULL; - retro_assert(driver_context); - - if (!mic) + if (!driver_context || (mic = calloc(1, sizeof(pipewire_microphone_t))) == NULL) goto error; - mic->pw = (pipewire_core_t*)driver_context; + mic->pw = (pipewire_core_t*)driver_context; pw_thread_loop_lock(mic->pw->thread_loop); @@ -393,7 +389,7 @@ static bool pipewire_microphone_stop_mic(void *driver_context, void *mic_context return false; if (pw_stream_get_state(mic->stream, &error) == PW_STREAM_STATE_STREAMING) - res = pipewire_stream_set_active(pw->thread_loop, mic->stream, false); + res = pipewire_stream_set_active(pw->thread_loop, mic->stream, false); else /* For other states we assume that the stream is inactive */ res = true;