aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2021-09-22 13:42:51 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2021-09-22 17:43:56 +0000
commit903873ce15600fc02a0ea42cbf888cff232b411d (patch)
treeff78e316bb0cc47612311aca4f32331e84d35c5a
parent884f38590c3cc0b1a2c00904c1f1f6c791376308 (diff)
downloadsrc-903873ce15600fc02a0ea42cbf888cff232b411d.tar.gz
src-903873ce15600fc02a0ea42cbf888cff232b411d.zip
Implement and use new mixer(3) library for FreeBSD.
Wiki article: https://wiki.freebsd.org/SummerOfCode2021Projects/SoundMixerImprovements This project was part of Google Summer of Code 2021. Submitted by: christos@ Differential Revision: https://reviews.freebsd.org/D31636 Sponsored by: NVIDIA Networking
-rw-r--r--lib/Makefile1
-rw-r--r--lib/libmixer/Makefile8
-rw-r--r--lib/libmixer/mixer.3540
-rw-r--r--lib/libmixer/mixer.c493
-rw-r--r--lib/libmixer/mixer.h123
-rw-r--r--usr.sbin/mixer/Makefile9
-rw-r--r--usr.sbin/mixer/mixer.8306
-rw-r--r--usr.sbin/mixer/mixer.c723
-rw-r--r--usr.sbin/mixer/tests/Makefile5
-rwxr-xr-xusr.sbin/mixer/tests/mixer_test.sh123
10 files changed, 1787 insertions, 544 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 1e375bb456e6..038763bfcba8 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -69,6 +69,7 @@ SUBDIR= ${SUBDIR_BOOTSTRAP} \
liblzma \
libmemstat \
libmd \
+ libmixer \
libmt \
lib80211 \
libnetbsd \
diff --git a/lib/libmixer/Makefile b/lib/libmixer/Makefile
new file mode 100644
index 000000000000..12081ee3835b
--- /dev/null
+++ b/lib/libmixer/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+LIB= mixer
+SRCS= ${LIB}.c
+INCS= ${LIB}.h
+MAN= ${LIB}.3
+
+.include <bsd.lib.mk>
diff --git a/lib/libmixer/mixer.3 b/lib/libmixer/mixer.3
new file mode 100644
index 000000000000..f97a88bb79a0
--- /dev/null
+++ b/lib/libmixer/mixer.3
@@ -0,0 +1,540 @@
+.\"-
+.\" Copyright (c) 2021 Christos Margiolis <christos@FreeBSD.org>
+.\"
+.\" Permission is hereby granted, free of charge, to any person obtaining a copy
+.\" of this software and associated documentation files (the "Software"), to deal
+.\" in the Software without restriction, including without limitation the rights
+.\" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+.\" copies of the Software, and to permit persons to whom the Software is
+.\" furnished to do so, subject to the following conditions:
+.\"
+.\" The above copyright notice and this permission notice shall be included in
+.\" all copies or substantial portions of the Software.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+.\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+.\" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+.\" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+.\" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+.\" THE SOFTWARE.
+.\"
+.\" $FreeBSD$
+.\"
+
+.Dd June 30, 2021
+.Dt mixer 3
+.Os
+.Sh NAME
+.Nm mixer_open ,
+.Nm mixer_close ,
+.Nm mixer_get_dev ,
+.Nm mixer_get_dev_byname ,
+.Nm mixer_add_ctl ,
+.Nm mixer_add_ctl_s ,
+.Nm mixer_remove_ctl ,
+.Nm mixer_get_ctl ,
+.Nm mixer_get_ctl_byname ,
+.Nm mixer_set_vol ,
+.Nm mixer_set_mute ,
+.Nm mixer_mod_recsrc ,
+.Nm mixer_get_dunit ,
+.Nm mixer_set_dunit ,
+.Nm mixer_get_mode,
+.Nm mixer_get_nmixers ,
+.Nm MIX_ISDEV ,
+.Nm MIX_ISMUTE ,
+.Nm MIX_ISREC ,
+.Nm MIX_ISRECSRC ,
+.Nm MIX_VOLNORM ,
+.Nm MIX_VOLDENORM
+.Nd interface to OSS mixers
+.Sh LIBRARY
+Mixer library (libmixer, -lmixer)
+.Sh SYNOPSIS
+.In mixer.h
+.Ft struct mixer *
+.Fn mixer_open "const char *name"
+.Ft int
+.Fn mixer_close "struct mixer *m"
+.Ft struct mix_dev *
+.Fn mixer_get_dev "struct mixer *m" "int devno"
+.Ft struct mix_dev *
+.Fn mixer_get_dev_byname "struct mixer *m" "name"
+.Ft int
+.Fn mixer_add_ctl "struct mix_dev *parent" "int id" "const char *name" \
+ "int (*mod)(struct mix_dev *d, void *p)" \
+ "int (*print)(struct mix_dev *d, void *p)
+.Ft int
+.Fn mixer_add_ctl_s "mix_ctl_t *ctl"
+.Ft int
+.Fn mixer_remove_ctl "mix_ctl_t *ctl"
+.Ft mix_ctl_t *
+.Fn mixer_get_ctl "struct mix_dev *d" "int id"
+.Ft mix_ctl_t *
+.Fn mixer_get_ctl_byname "struct mix_dev *d" "const char *name"
+.Ft int
+.Fn mixer_set_vol "struct mixer *m" "mix_volume_t vol"
+.Ft int
+.Fn mixer_set_mute "struct mixer *m" "int opt"
+.Ft int
+.Fn mixer_mod_recsrc "struct mixer *m" "int opt"
+.Ft int
+.Fn mixer_get_dunit "void"
+.Ft int
+.Fn mixer_set_dunit "struct mixer *m" "int unit"
+.Ft int
+.Fn mixer_get_mode "int unit"
+.Ft int
+.Fn mixer_get_nmixers "void"
+.Ft int
+.Fn MIX_ISDEV "struct mixer *m" "int devno"
+.Ft int
+.Fn MIX_ISMUTE "struct mixer *m" "int devno"
+.Ft int
+.Fn MIX_ISREC "struct mixer *m" "int devno"
+.Ft int
+.Fn MIX_ISRECSRC "struct mixer *m" "int devno"
+.Ft float
+.Fn MIX_VOLNORM "int v"
+.Ft int
+.Fn MIX_VOLDENORM "float v"
+.Sh DESCRIPTION
+The
+.Nm mixer
+library allows userspace programs to access and manipulate OSS sound mixers in
+a simple way.
+.Ss Mixer
+.Pp
+A mixer is described by the following structure:
+.Bd -literal
+struct mixer {
+ TAILQ_HEAD(, mix_dev) devs; /* device list */
+ struct mix_dev *dev; /* selected device */
+ oss_mixerinfo mi; /* mixer info */
+ oss_card_info ci; /* audio card info */
+ char name[NAME_MAX]; /* mixer name (e.g /dev/mixer0) */
+ int fd; /* file descriptor */
+ int unit; /* audio card unit */
+ int ndev; /* number of devices */
+ int devmask; /* supported devices */
+#define MIX_MUTE 0x01
+#define MIX_UNMUTE 0x02
+#define MIX_TOGGLEMUTE 0x04
+ int mutemask; /* muted devices */
+ int recmask; /* recording devices */
+#define MIX_ADDRECSRC 0x01
+#define MIX_REMOVERECSRC 0x02
+#define MIX_SETRECSRC 0x04
+#define MIX_TOGGLERECSRC 0x08
+ int recsrc; /* recording sources */
+#define MIX_MODE_MIXER 0x01
+#define MIX_MODE_PLAY 0x02
+#define MIX_MODE_REC 0x04
+ int mode; /* dev.pcm.X.mode sysctl */
+ int f_default; /* default mixer flag */
+};
+.Ed
+.Pp
+The fields are follows:
+.Bl -tag -width "f_default"
+.It Fa devs
+A tail queue structure containing all supported mixer devices.
+.It Fa dev
+A pointer to the currently selected device. The device is one of the elements in
+.Ar devs .
+.It Fa mi
+OSS information about the mixer. Look at the definition of the
+.Ft oss_mixerinfo
+structure in
+.In sys/soundcard.h
+to see its fields.
+.It Fa ci
+OSS audio card information. This structure is also defined in
+.In sys/soundcard.h .
+.It Fa name
+Path to the mixer (e.g /dev/mixer0).
+.It Fa fd
+File descriptor returned when the mixer is opened in
+.Fn mixer_open .
+.It Fa unit
+Audio card unit. Since each mixer device maps to a pcmX device,
+.Ar unit
+is always equal to the number of that pcmX device. For example, if the audio
+device's number is 0 (i.e pcm0), then
+.Ar unit
+is 0 as well. This number is useful when checking if the mixer's audio
+card is the default one.
+.It Fa ndev
+Number of devices in
+.Ar devs .
+.It Fa devmask
+Bit mask containing all supported devices for the mixer. For example
+if device 10 is supported, then the 10th bit in the mask will be set. By default,
+.Fn mixer_open
+stores only the supported devices in devs, so it's very unlikely this mask will
+be needed.
+.It Fa mutemask
+Bit mask containing all muted devices. The logic is the same as with
+.Ar devmask .
+.It Fa recmask
+Bit mask containing all recording devices. Again, same logic as with the
+other masks.
+.It Fa recsrc
+Bit mask containing all recording sources. Yes, same logic again.
+.It Fa mode
+Bit mask containing the supported modes for this audio device. It holds the value
+of the
+.Ar dev.pcm.X.mode
+sysctl.
+.It Fa f_default
+Flag which tells whether the mixer's audio card is the default one.
+.El
+.Ss Mixer device
+.Pp
+Each mixer device stored in a mixer is described as follows:
+.Bd -literal
+struct mix_dev {
+ struct mixer *parent_mixer; /* parent mixer */
+ char name[NAME_MAX]; /* device name (e.g "vol") */
+ int devno; /* device number */
+ struct mix_volume {
+#define MIX_VOLMIN 0.0f
+#define MIX_VOLMAX 1.0f
+#define MIX_VOLNORM(v) ((v) / 100.0f)
+#define MIX_VOLDENORM(v) ((int)((v) * 100.0f + 0.5f))
+ float left; /* left volume */
+ float right; /* right volume */
+ } vol;
+ int nctl; /* number of controls */
+ TAILQ_HEAD(, mix_ctl) ctls; /* control list */
+ TAILQ_ENTRY(mix_dev) devs;
+};
+.Ed
+.Pp
+The fields are follows:
+.Bl -tag -width "parent_mixer"
+.It Fa parent_mixer
+Pointer to the mixer the device is attached to.
+.It Fa name
+Device name given by the OSS API. Devices can have one of the following names:
+.Bd -ragged
+vol, bass, treble, synth, pcm, speaker, line, mic, cd, mix,
+pcm2, rec, igain, ogain, line1, line2, line3, dig1, dig2, dig3,
+phin, phout, video, radio, and monitor.
+.Ed
+.It Fa devno
+Device's index in the SOUND_MIXER_NRDEVICES macro defined in
+.In sys/soundcard.h .
+This number is used to check against the masks defined in the
+.Ar mixer
+structure.
+.It Fa left, right
+Left and right-ear volumes. Although the OSS API stores volumes in integers from
+0-100, we normalize them to 32-bit floating point numbers. However, the volumes
+can be denormalized using the
+.Ar MIX_VOLDENORM
+macro if needed.
+.It Fa nctl
+Number of user-defined mixer controls associated with the device.
+.It Fa ctls
+A tail queue containing user-defined mixer controls.
+.El
+.Ss User-defined mixer controls
+.Pp
+Each mixer device can have user-defined controls. The control structure
+is defined as follows:
+.Bd -literal
+struct mix_ctl {
+ struct mix_dev *parent_dev; /* parent device */
+ int id; /* control id */
+ char name[NAME_MAX]; /* control name */
+ int (*mod)(struct mix_dev *, void *); /* modify control values */
+ int (*print)(struct mix_dev *, void *); /* print control */
+ TAILQ_ENTRY(mix_ctl) ctls;
+};
+.Ed
+.Pp
+The fields are follows:
+.Bl -tag -width "parent_dev"
+.It Fa parent_dev
+Pointer to the device the control is attached to.
+.It Fa id
+Control ID assigned by the caller. Even though the library will
+report it, care has to be taken to not give a control the same ID in case
+the caller has to choose controls using their ID.
+.It Fa name
+Control name. As with
+.Ar id ,
+the caller has to make sure the same name is not used more than once.
+.It Fa mod
+Function pointer to a control modification function. As in
+.Xr mixer 8 ,
+each mixer control's values can be modified. For example, if we have a
+volume control, the
+.Ar mod
+function will be responsible for handling volume changes.
+.It Fa print
+Function pointer to a control print function.
+.El
+.Ss Opening and closing the mixer
+.Pp
+The application must first call the
+.Fn mixer_open
+function to obtain a handle to the device, which is used as an argument
+in most other functions and macros. The parameter
+.Ar name
+specifies the path to the mixer. OSS mixers are stored under
+.Ar /dev/mixerN
+where
+.Ar N
+is the number of the mixer device. Each device maps to an actual
+.Ar pcm
+audio card, so
+.Ar /dev/mixer0
+is the mixer for
+.Ar pcm0 ,
+and so on. If
+.Ar name
+is
+.Ar NULL
+or
+.Ar /dev/mixer ,
+.Fn mixer_open
+opens the default mixer (hw.snd.defaul_unit).
+.Pp
+The
+.Fn mixer_close
+function frees resources and closes the mixer device. It's a good practice to
+always call it when the application is done using the mixer.
+.Ss Manipulating the mixer
+.Pp
+The
+.Fn mixer_get_dev
+and
+.Fn mixer_get_dev_byname
+functions select a mixer device, either by its number or by its name
+respectively. The mixer structure keeps a list of all the devices, but only
+one can be manipulated at a time. Each time a new device is to be manipulated,
+one of the two functions has to be called.
+.Pp
+The
+.Fn mixer_set_vol
+function changes the volume of the selected mixer device. The
+.Ar vol
+parameter is a structure that stores the left and right volumes of a given
+device. The allowed volume values are between MIX_VOLMIN (0.0) and
+MIX_VOLMAX (1.0).
+.Pp
+The
+.Fn mixer_set_mute
+function modifies the mute of a selected device. The
+.Ar opt
+parameter has to be one of the following options:
+.Bl -tag -width MIX_TOGGLEMUTE -offset indent
+.It Dv MIX_MUTE
+Mute the device.
+.It Dv MIX_UNMUTE
+Unmute the device.
+.It Dv MIX_TOGGLEMUTE
+Toggle the device's mute (e.g mute if unmuted and unmute if muted).
+.El
+.Pp
+The
+.Fn mixer_mod_recsrc
+function modifies a recording