From f7606a144b7147e493304278d321ab2ed7996bb8 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 30 Sep 2022 22:02:23 +0200 Subject: Give error when using an invalid audio input with pipewire --- src/main.cpp | 22 ++++++++++++++++++ src/sound.cpp | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 94 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index caea9b6..61eb5cf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1073,6 +1073,28 @@ int main(int argc, char **argv) { } Arg &audio_input_arg = args["-a"]; + const std::vector audio_inputs = get_pulseaudio_inputs(); + + // Manually check if the audio inputs we give exist. This is only needed for pipewire, not pulseaudio. + // Pipewire instead DEFAULTS TO THE DEFAULT AUDIO INPUT. THAT'S RETARDED. + // OH, YOU MISSPELLED THE AUDIO INPUT? FUCK YOU + for(const char *audio_input : audio_input_arg.values) { + bool match = false; + for(const auto &existing_audio_input : audio_inputs) { + if(strcmp(audio_input, existing_audio_input.name.c_str()) == 0) { + match = true; + break; + } + } + + if(!match) { + fprintf(stderr, "Error: Audio input device '%s' is not a valid input device. Expected one of:\n", audio_input); + for(const auto &existing_audio_input : audio_inputs) { + fprintf(stderr, " %s\n", existing_audio_input.name.c_str()); + } + exit(2); + } + } uint32_t region_x = 0; uint32_t region_y = 0; diff --git a/src/sound.cpp b/src/sound.cpp index abd2e65..0fd1333 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -277,7 +277,7 @@ int sound_device_get_by_name(SoundDevice *device, const char *name, unsigned int pa_handle *handle = pa_sound_device_new(nullptr, stream_name, name, stream_name, &ss, &buffer_attr, &error); if(!handle) { - fprintf(stderr, "pa_simple_new() failed: %s. Audio input device %s might not be valid\n", pa_strerror(error), name); + fprintf(stderr, "pa_sound_device_new() failed: %s. Audio input device %s might not be valid\n", pa_strerror(error), name); return -1; } @@ -298,4 +298,75 @@ int sound_device_read_next_chunk(SoundDevice *device, void **buffer) { } *buffer = pa->output_data; return device->frames; +} + +static void pa_state_cb(pa_context *c, void *userdata) { + pa_context_state state = pa_context_get_state(c); + int *pa_ready = (int*)userdata; + switch(state) { + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + default: + break; + case PA_CONTEXT_FAILED: + case PA_CONTEXT_TERMINATED: + *pa_ready = 2; + break; + case PA_CONTEXT_READY: + *pa_ready = 1; + break; + } +} + +static void pa_sourcelist_cb(pa_context *ctx, const pa_source_info *source_info, int eol, void *userdata) { + if(eol > 0) + return; + + std::vector *inputs = (std::vector*)userdata; + inputs->push_back({ source_info->name, source_info->description }); +} + +std::vector get_pulseaudio_inputs() { + std::vector inputs; + pa_mainloop *main_loop = pa_mainloop_new(); + + pa_context *ctx = pa_context_new(pa_mainloop_get_api(main_loop), "gpu-screen-recorder"); + pa_context_connect(ctx, NULL, PA_CONTEXT_NOFLAGS, NULL); + int state = 0; + int pa_ready = 0; + pa_context_set_state_callback(ctx, pa_state_cb, &pa_ready); + + pa_operation *pa_op = NULL; + + for(;;) { + // Not ready + if(pa_ready == 0) { + pa_mainloop_iterate(main_loop, 1, NULL); + continue; + } + + switch(state) { + case 0: { + pa_op = pa_context_get_source_info_list(ctx, pa_sourcelist_cb, &inputs); + ++state; + break; + } + } + + // Couldn't get connection to the server + if(pa_ready == 2 || (state == 1 && pa_op && pa_operation_get_state(pa_op) == PA_OPERATION_DONE)) { + if(pa_op) + pa_operation_unref(pa_op); + pa_context_disconnect(ctx); + pa_context_unref(ctx); + pa_mainloop_free(main_loop); + return inputs; + } + + pa_mainloop_iterate(main_loop, 1, NULL); + } + + pa_mainloop_free(main_loop); } \ No newline at end of file -- cgit v1.2.3