FOSS Mixer

FOSS Mixer is mixer application for FreeBSD with OSS audio backend to set soundcard parameters. Mixer can be use to control audio levels, set recording source, and it includes white noise generator for testing the audio output. It is pretty much what mixer(8) does.

FOSS Mixer supports only FreeBSD, there is no way to get it to work on other systems.

User interface

There is various knobs for controlling the mixers, most notably knob for changing the mixer on upper right corner, and recording source selector on the upper left corner. Rest of the knobs and sliders should be clear what they are for. Each control has little green light nearby which lights if that control is supported by the mixer currently selected. When the light is yellow, it indicates currently selected recording source.

If Bass and Treble controls are disabled (the green led is off), try setting:

hint.pcm.0.eq="1"
hint.pcm.1.eq="1"

in /boot/device.hints. Check the right pcm device numbers in your system from /dev/sndstat.

White noise generator is useful to test if selected audio output works. Please note that audio level of the noise can be quite loud. Roll the Noise Vol down before switching the noise on, especially if you are using headphones!

Compilation

Go to apps directory in package root, and run ./build.sh fossmixer to distribute needed files to package's root directory. After that, go back to .. and run ./configure and gmake, then start or install the application.

Example steps:

$ cd apps
$ ./build.sh fossmixer
$ cd ..

To try app without installing it:

$ ./configure --prefix=`pwd` \
              --enable-debug \
              --disable-bob \
              --disable-clock \
              --disable-color \
              --disable-coords \
              --disable-draw \
              --disable-extended \
              --disable-image \
              --disable-log \
              --disable-math \
              --disable-menu \
              --disable-message \
              --disable-output \
              --disable-remote \
              --disable-store \
              --with-libiconv=/where/is/your/libiconv \
              --with-libintl=/where/is/your/libintl
$ gmake
$ ./fossmixer.debug

Or, to install fossmixer:

$ ./configure --prefix=/install/root/for/app \
              --enable-native \
              --disable-bob \
              --disable-clock \
              --disable-color \
              --disable-coords \
              --disable-draw \
              --disable-extended \
              --disable-image \
              --disable-log \
              --disable-math \
              --disable-menu \
              --disable-message \
              --disable-output \
              --disable-remote \
              --disable-store \
              --with-libiconv=/where/is/your/libiconv \
              --with-libintl=/where/is/your/libintl
$ gmake
$ gmake install
$ /install/root/for/app/bin/fossmixer

Try setting fossmixer.widget.fontFace to Acme-Regular.ttf or Antonio-Regular.ttf font from Google in fossmixer.res, they look very nice with FOSS Mixer, much better than default Noto font.

Makefile rules

Makefile has couple of handy rules:

Preview

;
; @ANO_SCRIPT_NAME		FOSSMixer
; @ANO_SCRIPT_VERSION		0.0.6
; @ANO_SCRIPT_DESCRIPTION	FreeBSD OSS Mixer
; @ANO_SCRIPT_COPYRIGHT		Jani Salonen <salojan@goto10.co>
;
; Named parameters for Ano script binded functions are defined here:
;
; @ANO_FN_NAMED_PARAMS		"apps/fossmixer/fossmixer_fn_params.txt"
;
; @ANO_FLAGS_USE_PROTOS		[ ]
; @ANO_FLAGS_VAR_NAME_SUBS	[x]
; @ANO_FLAGS_VAR_WARN_UNUSED	[ ]
;
; @TAG_ATTR_CONTACT		Jani Salonen <salojan@goto10.co>
; @TAG_ATTR_HOMEPAGE		https://detroit.sourceforge.net/app_fossmixer.html
;
; Copyright (c) 2016-2025, Jani Salonen <salojan@goto10.co>
; All rights reserved.
;

main {
	; Initialize audio system for noise generator...
	;
	audio_enabled {
		audio_init (\
			cb_track_play:		NULL, \
			cb_track_mode:		NULL, \
			cb_track_finish:	NULL, \
			cb_track_restart:	NULL, \
			cb_track_cancel:	NULL, \
			cb_track_pan:		NULL, \
			cb_track_vol:		NULL, \
			cb_master_vol:		NULL, \
			cb_buffer_start:	NULL, \
			cb_buffer_done:		NULL)
	}

	; ...then initialize windowing system...
	;
	gui_enabled {
		window_init

		; ...and open main window
		;
		mov _w ([uint] 1200)

		audio_enabled {
			add _w (178)
		}

		window_open (\
			title_name:		"FOSS Mixer", \
			title_charset:		NULL, \
			parent_handle:		NOPARENT, \
			widget_stack_id:	1, \
			widget_set:		0, \
			window_refresh_divider:	PASSIVE_REFRESH, \
			position_x:		POS_CENTERED, \
			position_y:		POS_CENTERED, \
			size_width:		_w, \
			size_height:		620, \
			cb_main_loop:		NULL, \
			cb_expose:		NULL, \
			cb_key_press:		NULL, \
			cb_key_release:		NULL, \
			cb_button_press:	NULL, \
			cb_button_release:	NULL, \
			cb_client_message:	NULL, \
			cb_save_yourself:	NULL, \
			cb_configure_notify:	NULL, \
			cb_destroy_notify:	"cb_destroy", \
			cb_motion_notify:	NULL, \
			cb_map_notify:		NULL, \
			cb_unmap_notify:	NULL, \
			cb_open_notify:		"cb_open")
	}
}

;
; Window callbacks
;

_WINCB_OPEN_ callback cb_open (_hnd) {
	; Construct user interface...
	;
	bsd_prepare (\
		window_handle: _hnd)

	if rc == 0 : cb_open_ok

	; ...but give up if it failed
	;
	_hnd.destroy()

	exit

cb_open_ok:
	; If constructing user interface was ok, ask for fetching settings
	; and saving them for these knobs and window position
	;
	settings_register (\
		consumer_name: "mixer_noise_vol", \
		consumer_class: SETTINGS_WIDGET)

	settings_register (\
		consumer_name: "mixer_noise_pan", \
		consumer_class: SETTINGS_WIDGET)

	settings_register (\
		consumer_name: "mixer_wave_vol", \
		consumer_class: SETTINGS_WIDGET)

	settings_register (\
		consumer_name: "mixer_wave_pan", \
		consumer_class: SETTINGS_WIDGET)

	settings_register (\
		consumer_name: "mixer_wave_sel", \
		consumer_class: SETTINGS_WIDGET)

	settings_register (\
		consumer_name: "FOSS Mixer", \
		consumer_class: SETTINGS_WINDOW)

	; Map main window
	;
	_hnd.map()
}

_WINCB_DESTROY_ callback cb_destroy (_hnd) {
	; Window is closing, free everything attached to it...
	;
	_hnd.destroy()

	; ...and close mixer device
	;
	bsd_disperse

	exit
}

;
; Widget callbacks
;

_WIDGETCB_TURN_ callback cb_turn_mixer_sel (_name, _id, _min, _max, _steps, _step) {
	; Mixer selector
	;
	bsd_mixer_sel (\
		widget_name: _name, \
		steps: _steps, step: _step)
}

_WIDGETCB_TURN_ callback cb_turn_mixer_rec (_name, _id, _min, _max, _steps, _step) {
	; Recording source selector
	;
	bsd_mixer_rec (\
		widget_name: _name, \
		steps: _steps, step: _step)
}

_WIDGETCB_TURN_ callback cb_turn_mixer_mix (_name, _id, _min, _max, _steps, _step) {
	; Mixer sliders, all of them
	;
	bsd_mixer_mix (\
		widget_name: _name, \
		steps: _steps, step: _step)
}

_WIDGETCB_TURN_ callback cb_turn_mixer_ext (_name, _id, _min, _max, _steps, _step) {
	; All other extra mixer knobs, like bass and treble
	;
	bsd_mixer_ext (\
		widget_name: _name, \
		steps: _steps, step: _step)
}

_WIDGETCB_PUSH_ callback cb_push_noise_play (_name, _id, _min, _max, _steps, _step) {
	; First noise generator button
	;
	bsd_mixer_noise_play (\
		steps: _steps, step: _step)
}

_WIDGETCB_PUSH_ callback cb_push_noise_mute (_name, _id, _min, _max, _steps, _step) {
	; The other noise generator button
	;
	bsd_mixer_noise_mute (\
		steps: _steps, step: _step)
}

_WIDGETCB_TURN_ callback cb_turn_noise_vol (_name, _id, _min, _max, _steps, _step) {
	; Noise volume
	;
	bsd_mixer_noise_vol (\
		steps: _steps, step: _step)
}

_WIDGETCB_TURN_ callback cb_turn_noise_pan (_name, _id, _min, _max, _steps, _step) {
	; Noise panning
	;
	bsd_mixer_noise_pan (\
		steps: _steps, step: _step)
}

_WIDGETCB_PUSH_ callback cb_push_wave_play (_name, _id, _min, _max, _steps, _step) {
	; First wave generator button
	;
	bsd_mixer_wave_play (\
		steps: _steps, step: _step)
}

_WIDGETCB_PUSH_ callback cb_push_wave_mute (_name, _id, _min, _max, _steps, _step) {
	; The other wave generator button
	;
	bsd_mixer_wave_mute (\
		steps: _steps, step: _step)
}

_WIDGETCB_TURN_ callback cb_turn_wave_sel (_name, _id, _min, _max, _steps, _step) {
	; Wave frequency selector
	;
	bsd_mixer_wave_sel (\
		steps: _steps, step: _step)
}

_WIDGETCB_TURN_ callback cb_turn_wave_vol (_name, _id, _min, _max, _steps, _step) {
	; Wave volume
	;
	bsd_mixer_wave_vol (\
		steps: _steps, step: _step)
}

_WIDGETCB_TURN_ callback cb_turn_wave_pan (_name, _id, _min, _max, _steps, _step) {
	; Wave panning
	;
	bsd_mixer_wave_pan (\
		steps: _steps, step: _step)
}
;
; The purpose of this file is to allow named parameters in Ano script when
; calling functions listed below. This file is defined in Ano script by
; @ANO_FN_NAMED_PARAMS tag. See the Ano script for live use.
;
; Functions are declared as:
;
;  function_name(name_of_parameter_1, name_of_parameter_2, ...)
;
; That allows functions to be called in Ano script like:
;
;  function_name (\
;	name_of_parameter_1: value_1, \
;	name_of_parameter_2: value_2)
;
bsd_prepare(window_handle)
bsd_disperse()
bsd_mixer_sel(widget_name, steps, step)
bsd_mixer_rec(widget_name, steps, step)
bsd_mixer_mix(widget_name, steps, step)
bsd_mixer_ext(widget_name, steps, step)
bsd_mixer_noise_play(steps, step)
bsd_mixer_noise_mute(steps, step)
bsd_mixer_noise_vol(steps, step)
bsd_mixer_noise_pan(steps, step)
bsd_mixer_wave_play(steps, step)
bsd_mixer_wave_mute(steps, step)
bsd_mixer_wave_sel(steps, step)
bsd_mixer_wave_vol(steps, step)
bsd_mixer_wave_pan(steps, step)
;
; Copyright (c) 2016-2025, Jani Salonen <salojan@goto10.co>
; All rights reserved.
;
; @WIDGET_USE_BOUNDING_BOXES no
;

window "1" {
	set "0" {
		widget "background" {
			name		"bg"
			state		enable

			image		"@/share/fossmixer/fossmixer_bg.tga"
		}
	}
}

Screenshots

Click to enlarge.

FreeBSD OSS mixer

Copyright © 2025, Jani Salonen <salojan at goto10 piste co>. Piste is finnish word and means dot. All rights reserved.