diff options
| author | dec05eba <dec05eba@protonmail.com> | 2026-08-01 21:07:12 +0200 |
|---|---|---|
| committer | dec05eba <dec05eba@protonmail.com> | 2026-08-01 21:07:12 +0200 |
| commit | 2b47b9926966b6e81ffda188193eb80653c6f14f (patch) | |
| tree | 9831173b025b726cf189e798cb18d03e756a954c /src | |
| parent | 5611e6a7a70b79496da20ffd171d636c2d3c9065 (diff) | |
Rewrite sound.cpp in C as sound.c
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.cpp | 85 | ||||
| -rw-r--r-- | src/sound.c (renamed from src/sound.cpp) | 154 |
2 files changed, 151 insertions, 88 deletions
diff --git a/src/main.cpp b/src/main.cpp index a2933f3..6862b99 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,6 +36,8 @@ extern "C" { #include <stdio.h> #include <stdlib.h> #include <string> +#include <vector> +#include <optional> #include <thread> #include <mutex> #include <signal.h> @@ -46,7 +48,7 @@ extern "C" { #include <libgen.h> #include <malloc.h> -#include "../include/sound.hpp" +#include "../include/sound.h" extern "C" { #include <libavutil/pixfmt.h> @@ -68,6 +70,23 @@ extern "C" { #define GSR_VERSION "unknown" #endif +enum class AudioInputType { + DEVICE, + APPLICATION +}; + +struct AudioInput { + std::string name; + AudioInputType type = AudioInputType::DEVICE; + bool inverted = false; +}; + +struct MergedAudioInputs { + std::optional<std::string> custom_name; + std::string track_name; + std::vector<AudioInput> audio_inputs; +}; + // TODO: If options are not supported then they are returned (allocated) in the options. This should be free'd. // TODO: Remove LIBAVUTIL_VERSION_MAJOR checks in the future when ubuntu, pop os LTS etc update ffmpeg to >= 5.0 @@ -227,21 +246,21 @@ static int64_t audio_codec_get_get_bitrate(gsr_audio_codec audio_codec) { return 128000; } -static AudioFormat audio_codec_context_get_audio_format(const AVCodecContext *audio_codec_context) { +static gsr_audio_format audio_codec_context_get_audio_format(const AVCodecContext *audio_codec_context) { switch(audio_codec_context->sample_fmt) { - case AV_SAMPLE_FMT_FLT: return F32; - case AV_SAMPLE_FMT_FLTP: return S32; - case AV_SAMPLE_FMT_S16: return S16; - case AV_SAMPLE_FMT_S32: return S32; - default: return S16; + case AV_SAMPLE_FMT_FLT: return GSR_AUDIO_FORMAT_F32; + case AV_SAMPLE_FMT_FLTP: return GSR_AUDIO_FORMAT_S32; + case AV_SAMPLE_FMT_S16: return GSR_AUDIO_FORMAT_S16; + case AV_SAMPLE_FMT_S32: return GSR_AUDIO_FORMAT_S32; + default: return GSR_AUDIO_FORMAT_S16; } } -static AVSampleFormat audio_format_to_sample_format(const AudioFormat audio_format) { +static AVSampleFormat audio_format_to_sample_format(const gsr_audio_format audio_format) { switch(audio_format) { - case S16: return AV_SAMPLE_FMT_S16; - case S32: return AV_SAMPLE_FMT_S32; - case F32: return AV_SAMPLE_FMT_FLT; + case GSR_AUDIO_FORMAT_S16: return AV_SAMPLE_FMT_S16; + case GSR_AUDIO_FORMAT_S32: return AV_SAMPLE_FMT_S32; + case GSR_AUDIO_FORMAT_F32: return AV_SAMPLE_FMT_FLT; } assert(false); return AV_SAMPLE_FMT_S16; @@ -1220,10 +1239,10 @@ static bool save_replay_async(AVCodecContext *video_codec_context, int video_str return true; } -static const AudioDevice* get_audio_device_by_name(const std::vector<AudioDevice> &audio_devices, const char *name) { - for(const auto &audio_device : audio_devices) { - if(strcmp(audio_device.name.c_str(), name) == 0) - return &audio_device; +static const gsr_audio_device* get_audio_device_by_name(const gsr_audio_devices *audio_devices, const char *name) { + for(size_t i = 0; i < audio_devices->num_items; ++i) { + if(strcmp(audio_devices->items[i].name, name) == 0) + return &audio_devices->items[i]; } return nullptr; } @@ -1840,18 +1859,20 @@ static void info_command(void *userdata) { static void list_audio_devices_command(void *userdata) { (void)userdata; - const AudioDevices audio_devices = get_pulseaudio_inputs(); + gsr_audio_devices audio_devices; + get_pulseaudio_inputs(&audio_devices); - if(!audio_devices.default_output.empty()) + if(audio_devices.default_output[0] != '\0') puts("default_output|Default output"); - if(!audio_devices.default_input.empty()) + if(audio_devices.default_input[0] != '\0') puts("default_input|Default input"); - for(const auto &audio_input : audio_devices.audio_inputs) { - printf("%s|%s\n", audio_input.name.c_str(), audio_input.description.c_str()); + for(size_t i = 0; i < audio_devices.num_items; ++i) { + printf("%s|%s\n", audio_devices.items[i].name, audio_devices.items[i].description); } + gsr_audio_devices_deinit(&audio_devices); fflush(stdout); _exit(0); } @@ -2549,7 +2570,7 @@ struct AudioTrackDescription { // 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 -static std::vector<MergedAudioInputs> parse_audio_inputs(const AudioDevices &audio_devices, const Arg *audio_input_arg) { +static std::vector<MergedAudioInputs> parse_audio_inputs(const gsr_audio_devices *audio_devices, const Arg *audio_input_arg) { std::vector<MergedAudioInputs> requested_audio_inputs; for(int i = 0; i < audio_input_arg->num_values; ++i) { @@ -2574,21 +2595,21 @@ static std::vector<MergedAudioInputs> parse_audio_inputs(const AudioDevices &aud bool match = false; if(request_audio_input.name == "default_output") { - if(audio_devices.default_output.empty()) { + if(audio_devices->default_output[0] == '\0') { gsr_log(GSR_LOG_LEVEL_ERROR, "-a default_output was specified but no default audio output is specified in the audio server"); _exit(2); } match = true; audio_track_description.devices.push_back("Default output"); } else if(request_audio_input.name == "default_input") { - if(audio_devices.default_input.empty()) { + if(audio_devices->default_input[0] == '\0') { gsr_log(GSR_LOG_LEVEL_ERROR, "-a default_input was specified but no default audio input is specified in the audio server"); _exit(2); } match = true; audio_track_description.devices.push_back("Default input"); } else { - const AudioDevice *audio_device = get_audio_device_by_name(audio_devices.audio_inputs, request_audio_input.name.c_str()); + const gsr_audio_device *audio_device = get_audio_device_by_name(audio_devices, request_audio_input.name.c_str()); if(audio_device) { match = true; audio_track_description.devices.push_back(audio_device->description); @@ -2597,12 +2618,12 @@ static std::vector<MergedAudioInputs> parse_audio_inputs(const AudioDevices &aud if(!match) { gsr_log(GSR_LOG_LEVEL_ERROR, "Audio device '%s' is not a valid audio device, expected one of:", request_audio_input.name.c_str()); - if(!audio_devices.default_output.empty()) + if(audio_devices->default_output[0] != '\0') fprintf(stderr, " default_output (Default output)\n"); - if(!audio_devices.default_input.empty()) + if(audio_devices->default_input[0] != '\0') fprintf(stderr, " default_input (Default input)\n"); - for(const auto &audio_device_input : audio_devices.audio_inputs) { - fprintf(stderr, " %s (%s)\n", audio_device_input.name.c_str(), audio_device_input.description.c_str()); + for(size_t j = 0; j < audio_devices->num_items; ++j) { + fprintf(stderr, " %s (%s)\n", audio_devices->items[j].name, audio_devices->items[j].description); } _exit(50); } @@ -3671,11 +3692,13 @@ int main(int argc, char **argv) { const Arg *audio_input_arg = args_parser_get_arg(&arg_parser, "-a"); assert(audio_input_arg); - AudioDevices audio_devices; + gsr_audio_devices audio_devices; + memset(&audio_devices, 0, sizeof(audio_devices)); if(audio_input_arg->num_values > 0) - audio_devices = get_pulseaudio_inputs(); + get_pulseaudio_inputs(&audio_devices); - std::vector<MergedAudioInputs> requested_audio_inputs = parse_audio_inputs(audio_devices, audio_input_arg); + std::vector<MergedAudioInputs> requested_audio_inputs = parse_audio_inputs(&audio_devices, audio_input_arg); + gsr_audio_devices_deinit(&audio_devices); const bool uses_app_audio = merged_audio_inputs_has_app_audio(requested_audio_inputs); std::vector<std::string> app_audio_names; diff --git a/src/sound.cpp b/src/sound.c index 9a72e78..a01718b 100644 --- a/src/sound.cpp +++ b/src/sound.c @@ -1,15 +1,13 @@ -#include "../include/sound.hpp" +#include "../include/sound.h" #include "../include/log.h" -extern "C" { #include "../include/utils.h" -} #include <stdlib.h> #include <stdio.h> #include <string.h> -#include <cmath> #include <time.h> -#include <mutex> +#include <assert.h> +#include <pthread.h> #include <pulse/pulseaudio.h> #include <pulse/mainloop.h> @@ -34,13 +32,13 @@ extern "C" { } \ } while(false); -enum class DeviceType { - STANDARD, - DEFAULT_OUTPUT, - DEFAULT_INPUT -}; +typedef enum { + DEVICE_TYPE_STANDARD, + DEVICE_TYPE_DEFAULT_OUTPUT, + DEVICE_TYPE_DEFAULT_INPUT +} DeviceType; -struct pa_handle { +typedef struct { pa_context *context; pa_stream *stream; pa_mainloop *mainloop; @@ -57,7 +55,8 @@ struct pa_handle { pa_buffer_attr attr; pa_sample_spec ss; - std::mutex reconnect_mutex; + pthread_mutex_t reconnect_mutex; + bool reconnect_mutex_initialized; DeviceType device_type; char stream_name[256]; char node_name[256]; @@ -70,7 +69,7 @@ struct pa_handle { pa_proplist *proplist; bool connected; -}; +} pa_handle; static void pa_sound_device_free(pa_handle *p) { assert(p); @@ -101,17 +100,23 @@ static void pa_sound_device_free(pa_handle *p) { p->output_data = NULL; } + if (p->reconnect_mutex_initialized) { + pthread_mutex_destroy(&p->reconnect_mutex); + p->reconnect_mutex_initialized = false; + } + pa_xfree(p); } -static void subscribe_update_default_devices(pa_context*, const pa_server_info *server_info, void *userdata) { +static void subscribe_update_default_devices(pa_context *ctx, const pa_server_info *server_info, void *userdata) { + (void)ctx; pa_handle *handle = (pa_handle*)userdata; - std::lock_guard<std::mutex> lock(handle->reconnect_mutex); + pthread_mutex_lock(&handle->reconnect_mutex); if(server_info->default_sink_name) { // TODO: Size check snprintf(handle->default_output_device_name, sizeof(handle->default_output_device_name), "%s.monitor", server_info->default_sink_name); - if(handle->device_type == DeviceType::DEFAULT_OUTPUT && strcmp(handle->device_name, handle->default_output_device_name) != 0) { + if(handle->device_type == DEVICE_TYPE_DEFAULT_OUTPUT && strcmp(handle->device_name, handle->default_output_device_name) != 0) { handle->reconnect = true; handle->reconnect_last_tried_seconds = clock_get_monotonic_seconds(); // TODO: Size check @@ -122,13 +127,15 @@ static void subscribe_update_default_devices(pa_context*, const pa_server_info * if(server_info->default_source_name) { // TODO: Size check snprintf(handle->default_input_device_name, sizeof(handle->default_input_device_name), "%s", server_info->default_source_name); - if(handle->device_type == DeviceType::DEFAULT_INPUT && strcmp(handle->device_name, handle->default_input_device_name) != 0) { + if(handle->device_type == DEVICE_TYPE_DEFAULT_INPUT && strcmp(handle->device_name, handle->default_input_device_name) != 0) { handle->reconnect = true; handle->reconnect_last_tried_seconds = clock_get_monotonic_seconds(); // TODO: Size check snprintf(handle->device_name, sizeof(handle->device_name), "%s", handle->default_input_device_name); } } + + pthread_mutex_unlock(&handle->reconnect_mutex); } static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) { @@ -141,7 +148,8 @@ static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t } } -static void store_default_devices(pa_context*, const pa_server_info *server_info, void *userdata) { +static void store_default_devices(pa_context *ctx, const pa_server_info *server_info, void *userdata) { + (void)ctx; pa_handle *handle = (pa_handle*)userdata; if(server_info->default_sink_name) snprintf(handle->default_output_device_name, sizeof(handle->default_output_device_name), "%s.monitor", server_info->default_sink_name); @@ -152,7 +160,7 @@ static void store_default_devices(pa_context*, const pa_server_info *server_info static bool startup_get_default_devices(pa_handle *p, const char *device_name) { pa_operation *pa = pa_context_get_server_info(p->context, store_default_devices, p); while(pa) { - pa_operation_state state = pa_operation_get_state(pa); + pa_operation_state_t state = pa_operation_get_state(pa); if(state == PA_OPERATION_DONE) { pa_operation_unref(pa); break; @@ -170,13 +178,13 @@ static bool startup_get_default_devices(pa_handle *p, const char *device_name) { if(strcmp(device_name, "default_output") == 0) { snprintf(p->device_name, sizeof(p->device_name), "%s", p->default_output_device_name); - p->device_type = DeviceType::DEFAULT_OUTPUT; + p->device_type = DEVICE_TYPE_DEFAULT_OUTPUT; } else if(strcmp(device_name, "default_input") == 0) { snprintf(p->device_name, sizeof(p->device_name), "%s", p->default_input_device_name); - p->device_type = DeviceType::DEFAULT_INPUT; + p->device_type = DEVICE_TYPE_DEFAULT_INPUT; } else { snprintf(p->device_name, sizeof(p->device_name), "%s", device_name); - p->device_type = DeviceType::STANDARD; + p->device_type = DEVICE_TYPE_STANDARD; } return true; @@ -199,17 +207,26 @@ static pa_handle* pa_sound_device_new(const char *server, snprintf(p->node_name, sizeof(p->node_name), "%s", name); snprintf(p->stream_name, sizeof(p->stream_name), "%s", stream_name); + if(pthread_mutex_init(&p->reconnect_mutex, NULL) != 0) { + gsr_log(GSR_LOG_LEVEL_ERROR, "failed to initialize reconnect mutex"); + *rerror = -1; + pa_xfree(p); + return NULL; + } + p->reconnect_mutex_initialized = true; + p->reconnect = true; p->reconnect_last_tried_seconds = clock_get_monotonic_seconds() - (RECONNECT_TRY_TIMEOUT_SECONDS * 1000.0 * 2.0); p->default_output_device_name[0] = '\0'; p->default_input_device_name[0] = '\0'; - p->device_type = DeviceType::STANDARD; + p->device_type = DEVICE_TYPE_STANDARD; const int buffer_size = attr->fragsize; void *buffer = malloc(buffer_size); if(!buffer) { gsr_log(GSR_LOG_LEVEL_ERROR, "failed to allocate buffer for audio"); *rerror = -1; + pa_sound_device_free(p); return NULL; } @@ -291,7 +308,7 @@ static bool pa_sound_device_handle_context_recreate(pa_handle *p) { goto fail; } - if(pa_context_connect(p->context, nullptr, PA_CONTEXT_NOFLAGS, NULL) < 0) { + if(pa_context_connect(p->context, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) { gsr_log(GSR_LOG_LEVEL_ERROR, "pa_context_connect failed"); goto fail; } @@ -310,7 +327,8 @@ static bool pa_sound_device_handle_context_recreate(pa_handle *p) { } static bool pa_sound_device_should_reconnect(pa_handle *p, double now, char *device_name, size_t device_name_size) { - std::lock_guard<std::mutex> lock(p->reconnect_mutex); + bool should_reconnect = false; + pthread_mutex_lock(&p->reconnect_mutex); if(!p->reconnect && (!p->stream || !PA_STREAM_IS_GOOD(pa_stream_get_state(p->stream)))) { p->reconnect = true; @@ -321,10 +339,11 @@ static bool pa_sound_device_should_reconnect(pa_handle *p, double now, char *dev p->reconnect_last_tried_seconds = now; // TODO: Size check snprintf(device_name, device_name_size, "%s", p->device_name); - return true; + should_reconnect = true; } - return false; + pthread_mutex_unlock(&p->reconnect_mutex); + return should_reconnect; } static bool pa_sound_device_handle_reconnect(pa_handle *p, char *device_name, size_t device_name_size, double now) { @@ -363,8 +382,9 @@ static bool pa_sound_device_handle_reconnect(pa_handle *p, char *device_name, si pa_mainloop_iterate(p->mainloop, 0, NULL); - std::lock_guard<std::mutex> lock(p->reconnect_mutex); + pthread_mutex_lock(&p->reconnect_mutex); p->reconnect = false; + pthread_mutex_unlock(&p->reconnect_mutex); return true; } @@ -453,7 +473,7 @@ static int pa_sound_device_read(pa_handle *p, double timeout_seconds) { p->read_data = NULL; p->read_length = 0; p->read_index = 0; - + if(pa_stream_drop(p->stream) != 0) goto fail; @@ -470,27 +490,27 @@ static int pa_sound_device_read(pa_handle *p, double timeout_seconds) { return success ? 0 : -1; } -static pa_sample_format_t audio_format_to_pulse_audio_format(AudioFormat audio_format) { +static pa_sample_format_t audio_format_to_pulse_audio_format(gsr_audio_format audio_format) { switch(audio_format) { - case S16: return PA_SAMPLE_S16LE; - case S32: return PA_SAMPLE_S32LE; - case F32: return PA_SAMPLE_FLOAT32LE; + case GSR_AUDIO_FORMAT_S16: return PA_SAMPLE_S16LE; + case GSR_AUDIO_FORMAT_S32: return PA_SAMPLE_S32LE; + case GSR_AUDIO_FORMAT_F32: return PA_SAMPLE_FLOAT32LE; } assert(false); return PA_SAMPLE_S16LE; } -static int audio_format_to_get_bytes_per_sample(AudioFormat audio_format) { +static int audio_format_to_get_bytes_per_sample(gsr_audio_format audio_format) { switch(audio_format) { - case S16: return 2; - case S32: return 4; - case F32: return 4; + case GSR_AUDIO_FORMAT_S16: return 2; + case GSR_AUDIO_FORMAT_S32: return 4; + case GSR_AUDIO_FORMAT_F32: return 4; } assert(false); return 2; } -int sound_device_get_by_name(SoundDevice *device, const char *node_name, const char *device_name, const char *description, unsigned int num_channels, unsigned int period_frame_size, AudioFormat audio_format) { +int sound_device_get_by_name(SoundDevice *device, const char *node_name, const char *device_name, const char *description, unsigned int num_channels, unsigned int period_frame_size, gsr_audio_format audio_format) { pa_sample_spec ss; ss.format = audio_format_to_pulse_audio_format(audio_format); ss.rate = 48000; @@ -504,7 +524,7 @@ int sound_device_get_by_name(SoundDevice *device, const char *node_name, const c buffer_attr.maxlength = buffer_attr.fragsize; int error = 0; - pa_handle *handle = pa_sound_device_new(nullptr, node_name, device_name, description, &ss, &buffer_attr, &error); + pa_handle *handle = pa_sound_device_new(NULL, node_name, device_name, description, &ss, &buffer_attr, &error); if(!handle) { gsr_log(GSR_LOG_LEVEL_ERROR, "pa_sound_device_new() failed: %s. Audio input device %s might not be valid", pa_strerror(error), device_name); return -1; @@ -544,7 +564,7 @@ void sound_device_flush(SoundDevice *device) { int sound_device_read_next_chunk(SoundDevice *device, void **buffer, double timeout_sec, double *latency_seconds) { pa_handle *pa = (pa_handle*)device->handle; if(pa_sound_device_read(pa, timeout_sec) < 0) { - //fprintf(stderr, "pa_simple_read() failed: %s\n", pa_strerror(error)); + //gsr_log(GSR_LOG_LEVEL_ERROR, "pa_simple_read() failed: %s", pa_strerror(error)); *latency_seconds = 0.0; return -1; } @@ -554,7 +574,7 @@ int sound_device_read_next_chunk(SoundDevice *device, void **buffer, double time } static void pa_state_cb(pa_context *c, void *userdata) { - pa_context_state state = pa_context_get_state(c); + pa_context_state_t state = pa_context_get_state(c); int *pa_ready = (int*)userdata; switch(state) { case PA_CONTEXT_UNCONNECTED: @@ -573,29 +593,38 @@ static void pa_state_cb(pa_context *c, void *userdata) { } } -static void pa_sourcelist_cb(pa_context*, const pa_source_info *source_info, int eol, void *userdata) { +static void pa_sourcelist_cb(pa_context *ctx, const pa_source_info *source_info, int eol, void *userdata) { + (void)ctx; if(eol > 0) return; - AudioDevices *audio_devices = (AudioDevices*)userdata; - audio_devices->audio_inputs.push_back({ source_info->name, source_info->description }); + gsr_audio_devices *audio_devices = (gsr_audio_devices*)userdata; + if(!gsr_array_ensure_capacity((void**)&audio_devices->items, audio_devices->num_items, &audio_devices->capacity_items, sizeof(gsr_audio_device))) + return; + + gsr_audio_device *audio_device = &audio_devices->items[audio_devices->num_items]; + snprintf(audio_device->name, sizeof(audio_device->name), "%s", source_info->name); + snprintf(audio_device->description, sizeof(audio_device->description), "%s", source_info->description); + ++audio_devices->num_items; } -static void pa_server_info_cb(pa_context*, const pa_server_info *server_info, void *userdata) { - AudioDevices *audio_devices = (AudioDevices*)userdata; +static void pa_server_info_cb(pa_context *ctx, const pa_server_info *server_info, void *userdata) { + (void)ctx; + gsr_audio_devices *audio_devices = (gsr_audio_devices*)userdata; if(server_info->default_sink_name) - audio_devices->default_output = std::string(server_info->default_sink_name) + ".monitor"; + snprintf(audio_devices->default_output, sizeof(audio_devices->default_output), "%s.monitor", server_info->default_sink_name); if(server_info->default_source_name) - audio_devices->default_input = server_info->default_source_name; + snprintf(audio_devices->default_input, sizeof(audio_devices->default_input), "%s", server_info->default_source_name); } -static void server_info_callback(pa_context*, const pa_server_info *server_info, void *userdata) { +static void server_info_callback(pa_context *ctx, const pa_server_info *server_info, void *userdata) { + (void)ctx; bool *is_server_pipewire = (bool*)userdata; if(server_info->server_name && strstr(server_info->server_name, "PipeWire")) *is_server_pipewire = true; } -static void get_pulseaudio_default_inputs(AudioDevices &audio_devices) { +static void get_pulseaudio_default_inputs(gsr_audio_devices *audio_devices) { int state = 0; int pa_ready = 0; pa_operation *pa_op = NULL; @@ -619,7 +648,7 @@ static void get_pulseaudio_default_inputs(AudioDevices &audio_devices) { switch(state) { case 0: { - pa_op = pa_context_get_server_info(ctx, pa_server_info_cb, &audio_devices); + pa_op = pa_context_get_server_info(ctx, pa_server_info_cb, audio_devices); ++state; break; } @@ -640,8 +669,9 @@ static void get_pulseaudio_default_inputs(AudioDevices &audio_devices) { pa_mainloop_free(main_loop); } -AudioDevices get_pulseaudio_inputs() { - AudioDevices audio_devices; +void get_pulseaudio_inputs(gsr_audio_devices *audio_devices) { + memset(audio_devices, 0, sizeof(*audio_devices)); + int state = 0; int pa_ready = 0; pa_operation *pa_op = NULL; @@ -651,7 +681,7 @@ AudioDevices get_pulseaudio_inputs() { pa_mainloop *main_loop = pa_mainloop_new(); if(!main_loop) - return audio_devices; + return; pa_context *ctx = pa_context_new(pa_mainloop_get_api(main_loop), "gpu-screen-recorder"); if(pa_context_connect(ctx, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) @@ -668,7 +698,7 @@ AudioDevices get_pulseaudio_inputs() { switch(state) { case 0: { - pa_op = pa_context_get_source_info_list(ctx, pa_sourcelist_cb, &audio_devices); + pa_op = pa_context_get_source_info_list(ctx, pa_sourcelist_cb, audio_devices); ++state; break; } @@ -687,10 +717,20 @@ AudioDevices get_pulseaudio_inputs() { pa_context_disconnect(ctx); pa_context_unref(ctx); pa_mainloop_free(main_loop); - return audio_devices; } -bool pulseaudio_server_is_pipewire() { +void gsr_audio_devices_deinit(gsr_audio_devices *self) { + if(self->items) { + free(self->items); + self->items = NULL; + } + self->num_items = 0; + self->capacity_items = 0; + self->default_output[0] = '\0'; + self->default_input[0] = '\0'; +} + +bool pulseaudio_server_is_pipewire(void) { int state = 0; int pa_ready = 0; pa_operation *pa_op = NULL; |
