From a1e99d79037fdcf1f394cd46a953cbe6189a7a43 Mon Sep 17 00:00:00 2001 From: Ka Ho Ng Date: Wed, 5 Aug 2020 02:55:24 +0800 Subject: [PATCH] oss-audio: Improve /dev/sndstat parsing on FreeBSD This commit targets FreeBSD and potentially DragonFly BSD. The commit fixes issue parsing /dev/sndstat when hw.snd.verbose is greater than 0. Besides, the commit also adds support for audio devices created by user space daemons, such as virtual_oss. --- plugins/oss-audio/oss-input.c | 86 +++++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 15 deletions(-) diff --git a/plugins/oss-audio/oss-input.c b/plugins/oss-audio/oss-input.c index 699cf9ec0..368ca5acf 100644 --- a/plugins/oss-audio/oss-input.c +++ b/plugins/oss-audio/oss-input.c @@ -21,6 +21,7 @@ along with this program. If not, see . #include #include +#include #include #include #include @@ -38,6 +39,10 @@ along with this program. If not, see . #define OSS_RATE_DEFAULT 48000 #define OSS_CHANNELS_DEFAULT 2 +#define OSS_DEVICE_BEGIN "Installed devices:" +#define OSS_USERDEVICE_BEGIN "Installed devices from userspace:" +#define OSS_FV_BEGIN "File Versions:" + /** * Control block of plugin instance */ @@ -215,6 +220,7 @@ static void *oss_reader_thr(void *vptr) size_t framesize; framesize = oss_calc_framesize(handle->channels, handle->sample_fmt); + fds[0].fd = handle->dsp_fd; fds[0].events = POLLIN; fds[1].fd = handle->notify_pipe[0]; @@ -460,6 +466,8 @@ static void oss_prop_add_devices(obs_property_t *p) char *line = NULL; size_t linecap = 0; FILE *fp; + bool ud_matching = false; + bool skipall = false; fp = fopen(OSS_SNDSTAT_PATH, "r"); if (fp == NULL) { @@ -470,35 +478,83 @@ static void oss_prop_add_devices(obs_property_t *p) while (getline(&line, &linecap, fp) > 0) { int pcm; - char *ptr, *pdesc, *descr, *devname, *pmode; + char *ptr, *pdesc, *pmode; + char *descr = NULL, *devname = NULL; + char *udname = NULL; - if (sscanf(line, "pcm%i: ", &pcm) != 1) + if (!strncmp(line, OSS_FV_BEGIN, strlen(OSS_FV_BEGIN))) { + skipall = true; continue; + } + if (!strncmp(line, OSS_DEVICE_BEGIN, + strlen(OSS_DEVICE_BEGIN))) { + ud_matching = false; + skipall = false; + continue; + } + if (!strncmp(line, OSS_USERDEVICE_BEGIN, + strlen(OSS_USERDEVICE_BEGIN))) { + ud_matching = true; + skipall = false; + continue; + } + if (skipall || isblank(line[0])) + continue; + + if (!ud_matching) { + if (sscanf(line, "pcm%i: ", &pcm) != 1) + continue; + } else { + char *end = strchr(line, ':'); + if (end == NULL || end - line == 0) + continue; + + udname = strndup(line, end - line); + if (udname == NULL) + continue; + } if ((ptr = strchr(line, '<')) == NULL) - continue; + goto free_all_str; pdesc = ptr + 1; if ((ptr = strrchr(pdesc, '>')) == NULL) - continue; + goto free_all_str; *ptr++ = '\0'; - if (*ptr++ != ' ' || *ptr++ != '(') - continue; - pmode = ptr; + if ((pmode = strchr(ptr, '(')) == NULL) + goto free_all_str; + pmode++; if ((ptr = strrchr(pmode, ')')) == NULL) - continue; + goto free_all_str; *ptr++ = '\0'; - if (strcmp(pmode, "rec") != 0 && strcmp(pmode, "play/rec") != 0) - continue; - if (asprintf(&descr, "pcm%i: %s", pcm, pdesc) == -1) - continue; - if (asprintf(&devname, "/dev/dsp%i", pcm) == -1) { - free(descr); - continue; + if (!isdigit(pmode[0])) { + if (strcmp(pmode, "rec") != 0 && + strcmp(pmode, "play/rec") != 0) + goto free_all_str; + } else { + int npcs, nrcs; + if (sscanf(pmode, "%dp:%*dv/%dr:%*dv", &npcs, &nrcs) != + 2) + goto free_all_str; + if (nrcs < 1) + goto free_all_str; + } + if (!ud_matching) { + if (asprintf(&descr, "pcm%i: %s", pcm, pdesc) == -1) + goto free_all_str; + if (asprintf(&devname, "/dev/dsp%i", pcm) == -1) + goto free_all_str; + } else { + if (asprintf(&descr, "%s: %s", udname, pdesc) == -1) + goto free_all_str; + if (asprintf(&devname, "/dev/%s", udname) == -1) + goto free_all_str; } obs_property_list_add_string(p, descr, devname); + free_all_str: free(descr); free(devname); + free(udname); } free(line);