Merry Xmas dear FreeBSD community!
A few days ago in the profile posts the user rsronin asked if anyone had success with audio/cava displaying these delicious visualization bars. audio/cava supports almost every important audio backend out there, e.g., alsa, pulseaudio, pipewire, sndio. It can definitly work with sndio or pulseaudio on FreeBSD. BUT what about our beloved almighty superior OSS? It can't be so difficult to add OSS support to audio/cava. Yeah, "Talk is cheap. Show me the code.", so here we go:
I used a 13.2-RELEASE chroot(8) as my build environment. So prepare the build environment anyway you like, i.e. chroot, jail or directly on your host system. I assume we are on
Install the build dependencies (no external audio library needed, har har har, begone pulseaudio!):
Go to the sourcecode and autogen it:
Apply the following diffs to make cava ready of the one and only OSS:
The real juice is still missing. We need input/oss.h
and input/oss.c
A few days ago in the profile posts the user rsronin asked if anyone had success with audio/cava displaying these delicious visualization bars. audio/cava supports almost every important audio backend out there, e.g., alsa, pulseaudio, pipewire, sndio. It can definitly work with sndio or pulseaudio on FreeBSD. BUT what about our beloved almighty superior OSS? It can't be so difficult to add OSS support to audio/cava. Yeah, "Talk is cheap. Show me the code.", so here we go:
I used a 13.2-RELEASE chroot(8) as my build environment. So prepare the build environment anyway you like, i.e. chroot, jail or directly on your host system. I assume we are on
/
of the build environment and network is up. We are going to compile the latest released version of cava manually from source, because the port is still on a version from over two years ago. Fetch the sourcecode:
Code:
fetch -o - https://github.com/karlstav/cava/archive/refs/tags/0.9.1.tar.gz | tar -xf -
Code:
pkg install autotools fftw3 iniparser pkgconf
Code:
cd /cava-0.9.1
./autogen.sh
Diff:
--- ../cava-0.9.1-orig/Makefile.am 2023-08-12 17:47:21.000000000 +0200
+++ Makefile.am 2023-12-23 01:24:21.247610000 +0100
@@ -3,10 +3,10 @@
ACLOCAL_AMFLAGS = -I m4
bin_PROGRAMS = cava
-cava_SOURCES = cava.c cavacore.c config.c input/common.c input/fifo.c input/shmem.c \
+cava_SOURCES = cava.c cavacore.c config.c input/common.c input/fifo.c input/shmem.c input/oss.c \
output/terminal_noncurses.c output/raw.c output/noritake.c
cava_CPPFLAGS = -DPACKAGE=\"$(PACKAGE)\" -DVERSION=\"$(VERSION)\" \
- -D_POSIX_SOURCE -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE_EXTENDED \
+ -D_POSIX_SOURCE -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE_EXTENDED -D__BSD_VISIBLE \
-DFONTDIR=\"@FONT_DIR@\"
cava_CFLAGS = -std=c99 -Wall -Wextra -Wno-unused-result -Wno-unknown-warning-option -Wno-maybe-uninitialized -Wno-vla-parameter
Diff:
--- ../cava-0.9.1-orig/cava.c 2023-08-12 17:47:21.000000000 +0200
+++ cava.c 2023-12-23 00:59:35.228339000 +0100
@@ -75,6 +75,7 @@
#include "input/pulse.h"
#include "input/shmem.h"
#include "input/sndio.h"
+#include "input/oss.h"
#endif
#ifdef __GNUC__
@@ -407,6 +408,11 @@
audio.format = 16;
thr_id = pthread_create(&p_thread, NULL, input_shmem, (void *)&audio);
break;
+ case INPUT_OSS:
+ audio.format = 16;
+ audio.rate = 44100;
+ thr_id = pthread_create(&p_thread, NULL, input_oss, (void *)&audio);
+ break;
#ifdef PORTAUDIO
case INPUT_PORTAUDIO:
audio.format = 16;
Diff:
--- ../cava-0.9.1-orig/config.c 2023-08-12 17:47:21.000000000 +0200
+++ config.c 2023-12-23 10:30:13.145505000 +0100
@@ -45,19 +45,19 @@
double smoothDef[5] = {1, 1, 1, 1, 1};
enum input_method default_methods[] = {
- INPUT_FIFO, INPUT_PORTAUDIO, INPUT_ALSA, INPUT_PIPEWIRE, INPUT_PULSE, INPUT_WINSCAP,
+ INPUT_FIFO, INPUT_PORTAUDIO, INPUT_ALSA, INPUT_PIPEWIRE, INPUT_PULSE, INPUT_WINSCAP, INPUT_OSS,
};
char *outputMethod, *orientation, *channels, *xaxisScale, *monoOption, *fragmentShader,
*vertexShader;
const char *input_method_names[] = {
- "fifo", "portaudio", "pipewire", "alsa", "pulse", "sndio", "shmem", "winscap",
+ "fifo", "portaudio", "pipewire", "alsa", "pulse", "sndio", "shmem", "winscap", "oss",
};
const bool has_input_method[] = {
HAS_FIFO, /** Always have at least FIFO and shmem input. */
- HAS_PORTAUDIO, HAS_PIPEWIRE, HAS_ALSA, HAS_PULSE, HAS_SNDIO, HAS_SHMEM, HAS_WINSCAP,
+ HAS_PORTAUDIO, HAS_PIPEWIRE, HAS_ALSA, HAS_PULSE, HAS_SNDIO, HAS_SHMEM, HAS_WINSCAP, HAS_OSS,
};
enum input_method input_method_by_name(const char *str) {
@@ -695,6 +695,9 @@
p->fifoSample = iniparser_getint(ini, "input:sample_rate", 44100);
p->fifoSampleBits = iniparser_getint(ini, "input:sample_bits", 16);
break;
+ case INPUT_OSS:
+ p->audio_source = strdup(iniparser_getstring(ini, "input:source", "/dev/dsp"));
+ break;
#ifdef PULSE
case INPUT_PULSE:
p->audio_source = strdup(iniparser_getstring(ini, "input:source", "auto"));
Diff:
--- ../cava-0.9.1-orig/config.h 2023-08-12 17:47:21.000000000 +0200
+++ config.h 2023-12-23 00:49:44.108221000 +0100
@@ -42,11 +42,13 @@
#define SDL true
#define HAS_FIFO false
#define HAS_SHMEM false
+#define HAS_OSS false
#define PATH_MAX 260
#else
#define HAS_WINSCAP false
#define HAS_FIFO true
#define HAS_SHMEM true
+#define HAS_OSS true
#endif
@@ -61,6 +63,7 @@
INPUT_SNDIO,
INPUT_SHMEM,
INPUT_WINSCAP,
+ INPUT_OSS,
INPUT_MAX,
};
C:
// header file for oss, part of cava.
#pragma once
void *input_oss(void *data);
C:
#include <stdbool.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include "input/common.h"
#include "input/oss.h"
void* input_oss(void* data) {
static const int flags = O_RDONLY;
struct audio_data* audio = (struct audio_data*)data;
int fmt = AFMT_S16_LE;
int channels = 2;
int speed = 44100;
int buf_size = audio->input_buffer_size * 2 * 2;
int fd = -1;
void* buf = NULL;
bool success = false;
if ((fd = open(audio->source, flags, 0)) == -1) {
fprintf(stderr, __FILE__ ": Could not open oss source '%s': %s\n", audio->source, strerror(errno));
goto cleanup;
}
if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) == -1)
fprintf(stderr, __FILE__ ": ioctl(SNDCTL_DSP_SETFMT) failed: %s\n", strerror(errno));
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1)
fprintf(stderr, __FILE__ ": ioctl(SNDCTL_DSP_CHANNELS) failed: %s\n", strerror(errno));
if (ioctl(fd, SNDCTL_DSP_SPEED, &speed) == -1)
fprintf(stderr, __FILE__ ": ioctl(SNDCTL_DSP_SPEED) failed: %s\n", strerror(errno));
if ((buf = malloc(buf_size)) == NULL) {
fprintf(stderr, __FILE__ ": malloc() failed: %s\n", strerror(errno));
goto cleanup;
}
while (audio->terminate != 1) {
if (read(fd, buf, buf_size) == -1) {
fprintf(stderr, __FILE__ ": read() failed: %s\n", strerror(errno));
goto cleanup;
}
write_to_cava_input_buffers(audio->input_buffer_size, buf, audio);
}
success = true;
cleanup:
free(buf);
if ((fd >= 0) && (close(fd) == -1)) {
fprintf(stderr, __FILE__ ": close() failed: %s\n", strerror(errno));
success = false;
}
if (!success)
exit(EXIT_FAILURE);
return NULL;
}
Last edited: