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 noise and wave generator for testing 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.
FOSS Mixer is licensed under the same three clause BSD-license terms as Detroit engine.
The program requires root privileges to set certain sound card parameters. It is recommended to set the so-called suid bit in the fossmixer binary file, otherwise the settings for sample rate, sample bit depth, per-channel volume, and so on will not work. If program has no permission to set soundcard parameters, it will blink red error led and print error message to console. Setting suid bit can be done as follows:
$ su - # chown root /usr/local/bin/fossmixer # chmod +s /usr/local/bin/fossmixer
User interface
There is various knobs for controlling the mixers, most notably knob for changing the mixer near upper right corner, and recording source selector next to it. Recording source selector is there only if there is something to select, otherwise it is hidden. 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.
Mixer knob has shortcut menu attached to it, which can be opened by clicking middle mouse button on mixer selection knob, or by pressing Menu button on keyboard. Menu button is usually located at right side of spacebar.
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. Also, if sample rate setting does not work, try setting mixer to passthrough mode. It can be set in Sample menu by clicking middle mouse button anywhere on background image, or any other button with <ctrl> key pressed simultaneously.
Noise and wave 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!
FOSS Mixer includes menu system as well, which can be popped up by clicking middle mouse button somewhere on background image, or any other button with <ctrl> key pressed simultaneously. Menu will not pop up when mouse is pressed on widget, that is, knob or slider and others.
Beneath Digital C knob there is a small red led. That led may blink sometimes, and if it will, it means that something went wrong or did not succeed. If you want to know what is going on, start FOSS Mixer from console and examine its output when error led blinks. Most likely it is because of permissions to set certain soundcard settings.
User interface customizations
⭐ New in 0.0.7.
There are couple of ways to alter FOSS Mixer default outlook, for example -uc and -us command line switches to change label color and default slider knob:
$ fossmixer -uc banana $ fossmixer -us oval
These settings can be put in FOSS Mixer config file PREFIX/etc/fossmixer.conf. Config file keywords for above settings are ui_label_color for -uc command line switch and ui_slider_style for -us.
Another way to customize UI is to fiddle with widget tuned attributes. Each widget has some tunables to set in X resources. See PREFIX/etc/fossmixer.res and X resources for more information about tuned attributes. To tune widget attributes, widget name must be known and set in X resources or FOSS Mixer resource file, PREFIX/etc/fossmixer.res, along with attribute name and its new value.
For example, background widget name is bg, so background image can be changed by using following widget attribute with it: fossmixer.widget.tunedAttributes: bg.image=/path/to/image.tga
Also, default background image color can be changed easily, add 20 to color value to make color a bit brighter, and decrement hue by 250 degrees to make blue to turn pink: fossmixer.widget.tunedAttributes: bg.value=+20, bg.hue=-250
Slider widgets are named as follows:
- mixer_bsd_preamp for preamp slider,
- mixer_bsd_vpc for per channel volume slider, and
- mixer_mix_line,
- mixer_mix_mic,
- mixer_mix_mix,
- mixer_mix_monitor,
- mixer_mix_pcm2,
- mixer_mix_pcm,
- mixer_mix_rec,
- mixer_mix_vol for the rest of the sliders.
Knob names are:
- mixer_bsd_frq for feeder rate selector,
- mixer_dpt for sample bit depth selector, and
- mixer_ext_bass,
- mixer_ext_dig1,
- mixer_ext_dig2,
- mixer_ext_dig3,
- mixer_ext_igain,
- mixer_ext_ogain,
- mixer_ext_treble for general tuning knobs,
- mixer_floor_pan,
- mixer_floor_sel,
- mixer_floor_vol,
- mixer_noise_pan,
- mixer_noise_vol for noise and wave knobs,
- mixer_rec for recording source knob,
- mixer_sel for mixer selector, and
- mixer_srt for sample rate selector.
Some buttons:
- mixer_bit for bit perfect button,
- mixer_end for endianess button, and
- mixer_brown_play,
- mixer_pink_play,
- mixer_rand_play,
- mixer_sine_play,
- mixer_white_play for noise and wave buttons.
Indicator leds:
- mixer_ext_bass_on for small round indicator led for bass, and
- mixer_ext_dig1_on,
- mixer_ext_dig2_on,
- mixer_ext_dig3_on,
- mixer_ext_igain_on,
- mixer_ext_ogain_on,
- mixer_ext_treble_on the rest of the small round indicators, and
- mixer_mix_line_on,
- mixer_mix_mic_on,
- mixer_mix_mix_on,
- mixer_mix_monitor_on,
- mixer_mix_pcm2_on,
- mixer_mix_pcm_on,
- mixer_mix_rec_on,
- mixer_mix_vol_on for mixer slider leds, and
- sel_mix, the flashing error led.
VU meter:
- vu_rec_l for left rec level bar,
- vu_rec_r for right rec level bar,
- vu_rec_tc for rec level title, and
- vu_rec_tl,
- vu_rec_tr for rec level peak labels, and
- vu_rec_dl,
- vu_rec_dr for rec level dynamic range labels,
- vu_rec_on for rec level on/off button,
- vu_rec_rst for rec level reset button, and
- vu_rec_dbv for rec level dBu/dBv button.
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-collect \
--disable-color \
--disable-coords \
--disable-draw \
--disable-image \
--disable-input \
--disable-log \
--disable-math \
--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-collect \
--disable-color \
--disable-coords \
--disable-draw \
--disable-image \
--disable-input \
--disable-log \
--disable-math \
--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. Also other small UI modifications can be done there.
Makefile rules
Makefile has couple of handy rules:
- clean removes compiled application binary and object files from working directory,
- compile recompiles Ano script, menu and widget definitions,
- erase is like clean, but removes engine object files too,
- install runs install-locale and copies application files in place (that's the configure script's --prefix directory),
- install-locale installs locales in place,
- install-strip is like install, but strips the application binary,
- locale creates locale files for install-locale rule,
- pot updates locale templates for supported languages,
- reconfig runs configure script again with same flags that used in previous run, and
- uninstall reverts the installation from --prefix without affecting working directory.
Preview
;
; @ANO_SCRIPT_NAME FOSSMixer
; @ANO_SCRIPT_VERSION 0.0.7
; @ANO_SCRIPT_DESCRIPTION FreeBSD OSS Mixer
; @ANO_SCRIPT_COPYRIGHT Jani Salonen <salojan@goto10.co>
;
; @TAG_ATTR_CONTACT Jani Salonen <salojan@goto10.co>
; @TAG_ATTR_HOMEPAGE https://detroit.sourceforge.net/app_fossmixer.html
;
; @ANO_FLAGS_USE_PROTOS [ ]
; @ANO_FLAGS_VAR_NAME_SUBS [x]
; @ANO_FLAGS_VAR_WARN_UNUSED [ ]
;
; Named parameters for Ano script binded functions are defined here:
;
; @ANO_FN_NAMED_PARAMS "apps/fossmixer/fossmixer_fn_params.txt"
;
; Copyright (c) 2016-2026, Jani Salonen <salojan@goto10.co>
; All rights reserved.
;
ifndef __FreeBSD__ {
compile_error: This program is only for FreeBSD.
}
define win_title ("FOSS Mixer")
define win_appicon ("@/share/fossmixer/icon_app.tga")
define win_width (1466)
define win_adder (344)
define win_height (620)
define win_mixer_title ("FOSS Mixer - Select mixer")
; Keep in sync with WIN_MIXER_* in mixer.h
define win_mixer_width (280)
define win_mixer_block (41)
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)
}
; ...and hotplug notifications...
;
hotplug_enabled {
hotplug_init (\
cb_attach: "hp_attach", \
cb_detach: "hp_detach", \
cb_notify: NULL)
}
; ...then initialize windowing system...
;
gui_enabled {
window_init
mov win_mixer_hnd (INVALID)
; ...and open main window
;
mov _w ([uint] win_width)
audio_enabled {
; Make room for noise knobs if audio system is enabled
;
add _w (win_adder)
}
window_open (\
title_name: win_title, \
title_charset: NULL, \
flags: OBEY_GEOMETRY, \
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: win_height, \
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")
}
; No exit here as callbacks are taking over when main process is done
}
;
; WINDOW callbacks
;
_WINCB_OPEN_ callback cb_open (_hnd) {
; Set main window icon
;
_hnd.icon(win_appicon)
; 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:
; As constructing user interface was ok, ask for fetching settings
; and saving them for these knobs and window position
;
settings_enabled {
; This is for Save settings -check item
;
settings_register (\
consumer_name: "saving", \
consumer_class: SETTINGS_MENU)
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_floor_vol", \
consumer_class: SETTINGS_WIDGET)
settings_register (\
consumer_name: "mixer_floor_pan", \
consumer_class: SETTINGS_WIDGET)
settings_register (\
consumer_name: "mixer_floor_sel", \
consumer_class: SETTINGS_WIDGET)
settings_register (\
consumer_name: "vu_rec_dbv", \
consumer_class: SETTINGS_WIDGET)
settings_register (\
consumer_name: win_title, \
consumer_class: SETTINGS_WINDOW)
}
; Map main window to screen
;
_hnd.map()
}
_WINCB_DESTROY_ callback cb_destroy (_hnd) {
; Main window is closing, free everything attached to it...
;
_hnd.destroy()
; ...and close mixer device
;
bsd_disperse
exit
}
_WINCB_OPEN_ callback cb_mixer_sel_open (_hnd) {
; Generate selectable mixer blocks...
;
bsd_mixer_sel_gen (window_handle: _hnd)
if rc > 0 : _cb_mixer_sel_open_ok
; ...but give up if it failed
;
_hnd.destroy()
end
_cb_mixer_sel_open_ok:
mov win_mixer_hnd (_hnd)
_hnd.set_attrs(\
attribute: ALWAYS_ABOVE, \
attribute_value: SET_ON)
_hnd.set_attrs(\
attribute: SET_BORDER, \
attribute_value: SET_OFF)
; Map mixer selection window to screen
;
_hnd.map()
}
_WINCB_DESTROY_ callback cb_mixer_sel_destroy (_hnd) {
; Mixer selection window is closing
;
mov win_mixer_hnd (INVALID)
_hnd.destroy()
}
;
; WIDGET callbacks
;
_WIDGETCB_TURN_ callback cb_turn_mixer_sel (_name, _id, _min, _max, \
_steps, _step) {
; Mixer selector callback, if selector window was already open,
; close it
;
if win_mixer_hnd == (INVALID) : _cb_turn_mixer_sel_ok
win_mixer_hnd.destroy()
mov win_mixer_hnd (INVALID)
_cb_turn_mixer_sel_ok:
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_dpt (_name, _id, _min, _max, \
_steps, _step) {
; Sample depth selector
;
bsd_mixer_dpt (widget_name: _name, \
steps: _steps, step: _step)
}
_WIDGETCB_TURN_ callback cb_turn_mixer_srt (_name, _id, _min, _max, \
_steps, _step) {
; Sample rate selector
;
bsd_mixer_srt (widget_name: _name, \
steps: _steps, step: _step)
}
_WIDGETCB_PUSH_ callback cb_push_mixer_end (_name, _id, _min, _max, \
_steps, _step) {
; Endian button
;
bsd_mixer_end (steps: _steps, step: _step)
}
_WIDGETCB_PUSH_ callback cb_push_mixer_bit (_name, _id, _min, _max, \
_steps, _step) {
; Bitperfect button
;
bsd_mixer_bit (steps: _steps, step: _step)
}
_WIDGETCB_TURN_ callback cb_turn_mixer_bsd (_name, _id, _min, _max, \
_steps, _step) {
; System soundcard sliders
;
bsd_mixer_bsd (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, extra: [int] 0)
}
_WIDGETCB_TURN_ callback cb_turn_mixer_frq (_name, _id, _min, _max, \
_steps, _step) {
; Feeder rate quality knob
;
bsd_mixer_frq (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_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_white_play (_name, _id, _min, _max, \
_steps, _step) {
; White noise generator button
;
bsd_mixer_white_play (steps: _steps, step: _step)
}
_WIDGETCB_PUSH_ callback cb_push_pink_play (_name, _id, _min, _max, \
_steps, _step) {
; Pink noise generator button
;
bsd_mixer_pink_play (steps: _steps, step: _step)
}
_WIDGETCB_PUSH_ callback cb_push_brown_play (_name, _id, _min, _max, \
_steps, _step) {
; Brown noise generator button
;
bsd_mixer_brown_play (steps: _steps, step: _step)
}
_WIDGETCB_TURN_ callback cb_turn_floor_sel (_name, _id, _min, _max, \
_steps, _step) {
; Wave frequency
;
bsd_mixer_floor_sel (steps: _steps, step: _step)
}
_WIDGETCB_TURN_ callback cb_turn_floor_vol (_name, _id, _min, _max, \
_steps, _step) {
; Wave volume
;
bsd_mixer_floor_vol (steps: _steps, step: _step)
}
_WIDGETCB_TURN_ callback cb_turn_floor_pan (_name, _id, _min, _max, \
_steps, _step) {
; Wave panning
;
bsd_mixer_floor_pan (steps: _steps, step: _step)
}
_WIDGETCB_PUSH_ callback cb_push_sine_play (_name, _id, _min, _max, \
_steps, _step) {
; Sine wave generator button
;
bsd_mixer_sine_play (steps: _steps, step: _step)
}
_WIDGETCB_PUSH_ callback cb_push_rand_play (_name, _id, _min, _max, \
_steps, _step) {
; Random wave generator button
;
bsd_mixer_rand_play (steps: _steps, step: _step)
}
_WIDGETCB_PUSH_ callback vu_rec_on_push (_name, _id, _min, _max, \
_steps, _step) {
; Rec source VU meter on/off button
;
vu_meter_rec (steps: _steps, step: _step)
}
_WIDGETCB_PUSH_ callback vu_rec_dbv_push (_name, _id, _min, _max, \
_steps, _step) {
; dBv button for VU meter
;
vu_meter_rec_dbv (steps: _steps, step: _step)
}
_WIDGETCB_PUSH_ callback vu_rec_rst_push (_name, _id, _min, _max, \
_steps, _step) {
; Peak reset button for VU meter
;
vu_meter_rec_rst (steps: _steps, step: _step)
}
_WIDGETCB_BUTTON_ callback cb_press_mixer_sel (_hnd, _x, _y, _x_root, _y_root, \
_state, _button) {
; Mixer selector generic button press callback, if selector window was
; already open, close it
;
if win_mixer_hnd == (INVALID) : _cb_press_mixer_sel_ok
win_mixer_hnd.destroy()
mov win_mixer_hnd (INVALID)
_cb_press_mixer_sel_ok:
if _button != 2 : _cb_press_mixer_sel_ot
; Set selector window position
;
_x = bsd_mixer_sel_psx (window_handle: _hnd)
_y = bsd_mixer_sel_psy (window_handle: _hnd)
; Figure out window height
;
_h = bsd_mixer_sel_num (window_handle: _hnd)
if _h <= 0 : _cb_press_mixer_sel_ot
mul _h (win_mixer_block)
dec _h
; Get selector window width or use default
;
_w = conf_fetch_int("ui_mixer_win_width")
if _w > 0 : _cb_press_mixer_sel_op
mov _w (win_mixer_width)
_cb_press_mixer_sel_op:
window_open (\
title_name: win_mixer_title, \
title_charset: NULL, \
flags: 0, \
parent_handle: NOPARENT, \
widget_stack_id: 2, \
widget_set: 0, \
window_refresh_divider: PASSIVE_REFRESH, \
position_x: _x, \
position_y: _y, \
size_width: _w, \
size_height: _h, \
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_mixer_sel_destroy", \
cb_motion_notify: NULL, \
cb_map_notify: NULL, \
cb_unmap_notify: NULL, \
cb_open_notify: "cb_mixer_sel_open")
_cb_press_mixer_sel_ot:
}
_WIDGETCB_BUTTON_ callback cb_mixer_win (_hnd, _x, _y, _x_root, _y_root, \
_state, _button) {
floor _s (_y_root / win_mixer_block)
touint _s
bsd_mixer_m_sel (widget_name: NULL, \
steps: 0, step: _s)
_hnd.destroy()
}
_WIDGETCB_BUTTON_ callback cb_empty_for_menu (_hnd, _x, _y, _x_root, _y_root, \
_state, _button) {
}
;
; MENU item callbacks
;
_MENUCB_ITEM_ callback cb_m_quit (_item, _pos, _tag, _flag) {
; Quit
;
bsd_disperse
exit
}
_MENUCB_ITEM_ callback cb_m_mix (_item, _pos, _tag, _flag) {
; Mixer selection
;
if win_mixer_hnd == (INVALID) : _cb_m_mix_ok
win_mixer_hnd.destroy()
mov win_mixer_hnd (INVALID)
_cb_m_mix_ok:
bsd_mixer_m_sel (widget_name: NULL, \
steps: 0, step: _pos)
}
_MENUCB_ITEM_ callback cb_m_rec (_item, _pos, _tag, _flag) {
; Recording source selector
;
bsd_mixer_m_rec (widget_name: NULL, \
steps: 0, step: _pos)
}
_MENUCB_ITEM_ callback cb_m_vol (_item, _pos, _tag, _flag) {
; Mixer volume
;
mul _pos (10)
bsd_mixer_mix (widget_name: "mixer_mix_vol", \
steps: 100, step: _pos, extra: [int] 1)
}
_MENUCB_ITEM_ callback cb_m_end (_item, _pos, _tag, _flag) {
; Endian selection
;
bsd_mixer_end (steps: 0, step: _flag)
}
_MENUCB_ITEM_ callback cb_m_bit (_item, _pos, _tag, _flag) {
; Bitperfect selection
;
bsd_mixer_bit (steps: 0, step: _flag)
}
_MENUCB_ITEM_ callback cb_m_rate (_item, _pos, _tag, _flag) {
; Sample rate selection
;
bsd_mixer_srt (widget_name: NULL, \
steps: 0, step: _pos)
}
_MENUCB_ITEM_ callback cb_m_bits (_item, _pos, _tag, _flag) {
; Sample bits selection
;
bsd_mixer_dpt (widget_name: NULL, \
steps: 0, step: _pos)
}
_MENUCB_ITEM_ callback cb_m_mode (_item, _pos, _tag, _flag) {
; Sample mode selection
;
bsd_mixer_mde (widget_name: NULL, \
steps: 0, step: _pos)
}
;
; HOTPLUG notification callbacks
;
_HOTPLUG_EVENT_ callback hp_attach (_hnd, _key, _val) {
; Hotplug attach
;
bsd_hotplug_attach (key: _key)
}
_HOTPLUG_EVENT_ callback hp_detach (_hnd, _key, _val) {
; Hotplug detach
;
bsd_hotplug_detach (key: _key)
}
; ; 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_m_sel(widget_name, steps, step) bsd_mixer_m_rec(widget_name, steps, step) bsd_mixer_dpt(widget_name, steps, step) bsd_mixer_srt(widget_name, steps, step) bsd_mixer_mde(widget_name, steps, step) bsd_mixer_end(steps, step) bsd_mixer_bit(steps, step) bsd_mixer_bsd(widget_name, steps, step) bsd_mixer_mix(widget_name, steps, step, extra) bsd_mixer_frq(widget_name, steps, step) bsd_mixer_ext(widget_name, steps, step) bsd_mixer_noise_vol(steps, step) bsd_mixer_noise_pan(steps, step) bsd_mixer_white_play(steps, step) bsd_mixer_pink_play(steps, step) bsd_mixer_brown_play(steps, step) bsd_mixer_floor_sel(steps, step) bsd_mixer_floor_vol(steps, step) bsd_mixer_floor_pan(steps, step) bsd_mixer_sine_play(steps, step) bsd_mixer_rand_play(steps, step) bsd_mixer_sel_gen(window_handle) bsd_mixer_sel_num(window_handle) bsd_mixer_sel_psx(window_handle) bsd_mixer_sel_psy(window_handle) vu_meter_rec(steps, step) vu_meter_rec_dbv(steps, step) vu_meter_rec_rst(steps, step) bsd_hotplug_attach(key) bsd_hotplug_detach(key)
;
; Copyright (c) 2016-2026, Jani Salonen <salojan@goto10.co>
; All rights reserved.
;
; @WIDGET_DEFAULT_STATE enable
; @WIDGET_DEFAULT_STICKY yes
; @WIDGET_DEFAULT_TITLE_JUSTIFICATION center
; @WIDGET_DEFAULT_TYPE 1
;
; @WIDGET_USE_BOUNDING_BOXES no
;
window "1" {
set "0" {
; This is fossmixer background image, which has menu attached
; to it.
;
widget "background" {
name "bg"
image "@/share/fossmixer/fossmixer_bg.tga"
action buttonpress = cb_empty_for_menu
}
; These are VU meters for rec source.
;
widget "block" {
name "vu_rec_l"
; Keep width in sync with VU_METER_WIDTH and height
; in sync with VU_METER_SCALE_TO_MAX in mixer.h.
;
position x = 990, y = 56
size width = 8, height = 80
color rgb:0x161913
}
widget "block" {
name "vu_rec_r"
; Keep width in sync with VU_METER_WIDTH and height
; in sync with VU_METER_SCALE_TO_MAX in mixer.h.
;
position x = 1000, y = 56
size width = 8, height = 80
color rgb:0x161913
}
; These are labels for VU meters.
;
widget "label" {
name "vu_rec_tc"
position x = 999, y = 36
label "L in R", \
size = 10, color = rgb:0xf0f0f0, \
justification = center
}
widget "label" {
name "vu_rec_tl"
position x = 980, y = 56
label " ", \
size = 10, color = rgb:0xf0f0f0, \
justification = right
}
widget "label" {
name "vu_rec_tr"
position x = 1018, y = 56
label " ", \
size = 10, color = rgb:0xf0f0f0, \
justification = left
}
widget "label" {
name "vu_rec_dl"
position x = 980, y = 70
label " ", \
size = 10, color = rgb:0xf0f0f0, \
justification = right
}
widget "label" {
name "vu_rec_dr"
position x = 1018, y = 70
label " ", \
size = 10, color = rgb:0xf0f0f0, \
justification = left
}
; These are buttons for rec source VU meters.
;
widget "pushbutton_1" {
name "vu_rec_on"
position x = 934, y = 140
title "Rec level", \
position = below, x = 0, y = 2
action push = vu_rec_on_push
}
widget "pushbutton_1" {
name "vu_rec_rst"
position x = 987, y = 140
title "Reset", \
position = below, x = 0, y = 2
sticky no
action push = vu_rec_rst_push
}
widget "pushbutton_1" {
name "vu_rec_dbv"
position x = 1040, y = 140
title "dBv", \
position = below, x = 0, y = 2
action push = vu_rec_dbv_push
}
}
}
;
; Localized strings for widgets.
;
;translate {
; "Bass" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Treble" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "In Gain" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Out Gain" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Digital A" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Digital B" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Digital C" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Monitor" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Line" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Mic" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Mix" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Rec" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Aux" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "PCM" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Volume" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Mixer" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Rec Source" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Sample Bits" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Sample Rate kHz" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Noise Vol" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Noise Pan" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Wave Vol" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Wave Pan" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Wave Freq" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Endian" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Bitperf" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Channel Vol" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Preamp" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Feeder Rate" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "White" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Pink" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Brown" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Sine" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Natural" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;
; "Rec level" {
; de_DE:""
; es_ES:""
; fi_FI:""
; fr_FR:""
; }
;}
;
; Copyright (c) 2016-2026, Jani Salonen <salojan@goto10.co>
; All rights reserved.
;
; @MENU_DEFAULT_TITLE_ORIENTATION left_to_right
;
window "1" {
widget "bg" {
;
; menu "menu_name" { optional_icon
; --------- -------------
;
menu [icon: @/share/fossmixer/icon_session.tga] "Session" {
;
; type "title", id, key, callback, flags, optional_icon
; ---- ----- -- --- -------- ----- -------------
;
check "Save settings?", 1, saving, none, norun_callback_onload | \
follow_settings_saving | \
sync_settings_on_change, \
none
delim
item [icon: @/share/fossmixer/icon_session_bye.tga] "Quit", \
2, none, cb_m_quit, none, none
}
menu [icon: @/share/fossmixer/icon_mix.tga] "Mixer" {
radio "No mixers available", 110, none, cb_m_mix, disabled, \
none
}
menu [icon: @/share/fossmixer/icon_rec.tga] "Rec source" {
radio "No sources available", 210, none, cb_m_rec, disabled, \
none
}
menu [icon: @/share/fossmixer/icon_vol.tga] "Volume" {
radio "Mute", 310, vol, cb_m_vol, none, none
radio "10%", 310, vol, cb_m_vol, none, none
radio "20%", 310, vol, cb_m_vol, none, none
radio "30%", 310, vol, cb_m_vol, none, none
radio "40%", 310, vol, cb_m_vol, none, none
radio "50%", 310, vol, cb_m_vol, none, none
radio "60%", 310, vol, cb_m_vol, none, none
radio "70%", 310, vol, cb_m_vol, none, none
radio "80%", 310, vol, cb_m_vol, none, none
radio "90%", 310, vol, cb_m_vol, none, none
radio "100%", 310, vol, cb_m_vol, none, none
}
menu [icon: @/share/fossmixer/icon_bit.tga] "Sample" {
check "Bitperfect?", 400, bit, cb_m_bit, none, none
delim
menu "Sample rate kHz" {
; Obsolete rates
;radio "8", 410, rate, cb_m_rate, none, none
;radio "11", 410, rate, cb_m_rate, none, none
;radio "16", 410, rate, cb_m_rate, none, none
;radio "22", 410, rate, cb_m_rate, none, none
radio "32", 410, rate, cb_m_rate, none, none
radio "44.1", 410, rate, cb_m_rate, none, none
radio "48", 410, rate, cb_m_rate, none, none
radio "88.2", 410, rate, cb_m_rate, none, none
radio "96", 410, rate, cb_m_rate, none, none
radio "176", 410, rate, cb_m_rate, none, none
radio "192", 410, rate, cb_m_rate, none, none
radio "352", 410, rate, cb_m_rate, none, none
radio "384", 410, rate, cb_m_rate, none, none
; For future endeavours
;radio "705", 410, rate, cb_m_rate, none, none
;radio "768", 410, rate, cb_m_rate, none, none
}
delim
menu "Sample bits" {
radio "s8", 510, bits, cb_m_bits, none, none
radio "s16", 510, bits, cb_m_bits, none, none
radio "s24", 510, bits, cb_m_bits, none, none
radio "s32", 510, bits, cb_m_bits, none, none
radio "u8", 510, bits, cb_m_bits, none, none
radio "u16", 510, bits, cb_m_bits, none, none
radio "u24", 510, bits, cb_m_bits, none, none
radio "u32", 510, bits, cb_m_bits, none, none
radio "f32", 510, bits, cb_m_bits, none, none
delim
check "Big endian?", 500, end, cb_m_end, none, none
}
delim
menu "Sample mode" {
radio "Fixed", 610, mode, cb_m_mode, none, none
radio "Passthrough", 610, mode, cb_m_mode, none, none
radio "Adaptive", 610, mode, cb_m_mode, none, none
}
}
}
}
;
; Localized strings for menu items.
;
translate {
"Session" {
de_DE:"Sitzung"
es_ES:"Sesión"
fi_FI:"Istunto"
fr_FR:"Session"
}
"Save settings?" {
de_DE:"Einstellungen speichern?"
es_ES:"Guardar configuración?"
fi_FI:"Tallenna asetukset?"
fr_FR:"Enregistrer les paramètres?"
}
"Quit" {
de_DE:"Aufhören"
es_ES:"Salida"
fi_FI:"Lopeta"
fr_FR:"Sortie"
}
"Mixer" {
de_DE:"Mischpult"
es_ES:"Mezclador"
fi_FI:"Mikseri"
fr_FR:"Mixeur"
}
"No mixers available" {
de_DE:"Keine Tonmischpulte verfügbar"
es_ES:"Sin mezcladores"
fi_FI:"Ei miksereitä"
fr_FR:"Pas de mixeurs"
}
"Rec source" {
de_DE:"Tonaufnahmequelle"
es_ES:"Fuente de grabación"
fi_FI:"Äänityslähde"
fr_FR:"Source d'enregistrement"
}
"No sources available" {
de_DE:"Keine Tonaufnahmequellen verfügbar"
es_ES:"Sin fuentes de grabación"
fi_FI:"Ei äänityslähteitä"
fr_FR:"Aucune source d'enregistrement"
}
"Volume" {
de_DE:"Lautstärke"
es_ES:"Volumen"
fi_FI:"Äänenvoimakkuus"
fr_FR:"Volume"
}
"Mute" {
de_DE:"Stumm"
es_ES:"Silencio"
fi_FI:"Hiljennä"
fr_FR:"Silence"
}
"Sample" {
de_DE:"Probe"
es_ES:"Muestra"
fi_FI:"Näyte"
fr_FR:"Échantillon"
}
"Bitperfect?" {
de_DE:"Bitperfect?"
es_ES:"Bitperfect?"
fi_FI:"Bitperfect?"
fr_FR:"Bitperfect?"
}
"Sample rate kHz" {
de_DE:"Abtastrate kHz"
es_ES:"Frecuencia de muestreo kHz"
fi_FI:"Näytetaajuus kHz"
fr_FR:"Taux d'échantillonnage kHz"
}
"Sample bits" {
de_DE:"Probenahmetiefe"
es_ES:"Tamaño de bits de muestra"
fi_FI:"Näytebittejä"
fr_FR:"Taille de l'échantillon en bits"
}
"Big endian?" {
de_DE:"Big endian?"
es_ES:"Big endian?"
fi_FI:"Big endian?"
fr_FR:"Big endian?"
}
"Sample mode" {
de_DE:"Sample-Modus"
es_ES:"Modo de muestra"
fi_FI:"Näytetila"
fr_FR:"Mode échantillon"
}
"Fixed" {
de_DE:"Behoben"
es_ES:"Fijado"
fi_FI:"Kiinteä"
fr_FR:"Fixé"
}
"Passthrough" {
de_DE:"Penetration"
es_ES:"Penetración"
fi_FI:"Läpivienti"
fr_FR:"Pénétration"
}
"Adaptive" {
de_DE:"Adaptiv"
es_ES:"Adaptado"
fi_FI:"Adaptiivinen"
fr_FR:"Adaptatif"
}
}
Screenshots
Click to enlarge.
Copyright © 2026, Jani Salonen <salojan at goto10 piste co>. Piste is finnish word and means dot. All rights reserved.

