src - FreeBSD source tree

6 min read Original article ↗

We now have devd rules in snd.conf that achieve this in a much cleaner way. This reverts commit 9aac27599acaffa21ff69c5be8a2d71d29cc3d6b. Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D55532

@@ -19,7 +19,7 @@

.\" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN

.\" THE SOFTWARE.

.\"

-.Dd October 31, 2025

+.Dd February 26, 2026

.Dt MIXER 8

.Os

.Sh NAME

@@ -28,7 +28,7 @@

.Sh SYNOPSIS

.Nm

.Op Fl f Ar device

-.Op Fl d Ar pcmX | X Op Fl V Ar voss_device:mode

+.Op Fl d Ar pcmX | X

.Op Fl os

.Op Ar dev Ns Op Cm \&. Ns Ar control Ns Op Cm \&= Ns Ar value

.Ar ...

@@ -43,7 +43,7 @@ The

utility is used to set and display soundcard mixer device controls.

.Pp

The options are as follows:

-.Bl -tag -width "-V voss_device:mode"

+.Bl -tag -width "-d pcmN | N"

.It Fl a

Print the values for all mixer devices available in the system

.Pq see Sx FILES .

@@ -54,30 +54,6 @@ where X is the device's unit number (e.g for pcm0, the unit number is 0).

See

.Sx EXAMPLES

on how to list all available audio devices in the system.

-.Pp

-There is also the possibility of hot-swapping to the new default device if

-.Xr virtual_oss 8

-exists in the system and is running, in which case the

-.Fl V

-option needs to be specified as well.

-.Pp

-Hot-swapping generally cannot happen with plain

-.Xr sound 4 ,

-so the user has to restart the track in order to get sound coming out of the

-new default device.

-This is because applications usually open a device at the start of the track

-and do not check for default device changes, in order to open the new device

-mid-track.

-.Xr virtual_oss 8 ,

-on the other hand, can do hot-swapping, because it creates a virtual device for

-applications to open, and then does all the necessary routing and conversions

-to the appropriate device(s).

-.Pp

-Note that hot-swapping will work only for applications that are using

-.Xr virtual_oss 8

-devices, and not plain

-.Xr sound 4

-ones.

.It Fl f Ar device

Open

.Ar device

@@ -90,33 +66,6 @@ Print mixer values in a format suitable for use inside scripts.

The mixer's header (name, audio card name, ...) will not be printed.

.It Fl s

Print only the recording source(s) of the mixer device.

-.It Fl V Ar voss_device:mode

-Specify a

-.Xr virtual_oss 8

-control device, as well as a mode (see below), in order to hot-swap devices.

-This option is meant to only be used in combination with the

-.Fl d

-option.

-.Pp

-The available modes are as follows:

-.Bl -column play

-.It Sy Mode Ta Sy Action

-.It all Ta Playback and recording

-.It play Ta Playback

-.It rec Ta Recording

-.El

-.Pp

-The

-.Pa mode

-part is needed, so that

-.Nm

-will not accidentally hot-swap both the recording and playback device in

-.Xr virtual_oss 8 ,

-if only one direction is to be hot-swapped.

-.Pp

-See

-.Sx EXAMPLES

-on how to use this option.

.El

.Pp

The list of mixer devices that may be modified are:

@@ -316,26 +265,10 @@ $ mixer -f /dev/mixer0 -o > info

\&...

$ mixer -f /dev/mixer0 `cat info`

.Ed

-.Pp

-Suppose

-.Xr virtual_oss 8

-is running with

-.Pa /dev/vdsp.ctl

-as its control device, and

-.Pa pcm0

-as the playback device.

-Change the default device to

-.Pa pcm1 ,

-and hot-swap to it for both recording and playback in

-.Xr virtual_oss 8 :

-.Bd -literal -offset indent

-$ mixer -d pcm1 -V /dev/vdsp.ctl:all

-.Ed

.Sh SEE ALSO

.Xr mixer 3 ,

.Xr sound 4 ,

-.Xr sysctl 8 ,

-.Xr virtual_oss 8

+.Xr sysctl 8

.Sh HISTORY

The

.Nm

@@ -20,9 +20,6 @@

* THE SOFTWARE.

*/

-#include <sys/sysctl.h>

-#include <sys/wait.h>

-

#include <err.h>

#include <errno.h>

#include <mixer.h>

@@ -43,7 +40,7 @@ static void printall(struct mixer *, int);

static void printminfo(struct mixer *, int);

static void printdev(struct mixer *, int);

static void printrecsrc(struct mixer *, int); /* XXX: change name */

-static int set_dunit(struct mixer *, int, char *);

+static int set_dunit(struct mixer *, int);

/* Control handlers */

static int mod_volume(struct mix_dev *, void *);

static int mod_mute(struct mix_dev *, void *);

@@ -57,13 +54,13 @@ main(int argc, char *argv[])

{

struct mixer *m;

mix_ctl_t *cp;

- char *name = NULL, buf[NAME_MAX], *vctl = NULL;

+ char *name = NULL, buf[NAME_MAX];

char *p, *q, *devstr, *ctlstr, *valstr = NULL;

int dunit, i, n, pall = 1, shorthand;

int aflag = 0, dflag = 0, oflag = 0, sflag = 0;

int ch;

- while ((ch = getopt(argc, argv, "ad:f:hosV:")) != -1) {

+ while ((ch = getopt(argc, argv, "ad:f:hos")) != -1) {

switch (ch) {

case 'a':

aflag = 1;

@@ -86,9 +83,6 @@ main(int argc, char *argv[])

case 's':

sflag = 1;

break;

- case 'V':

- vctl = optarg;

- break;

case 'h': /* FALLTHROUGH */

case '?':

default:

@@ -125,7 +119,7 @@ main(int argc, char *argv[])

initctls(m);

if (dflag) {

- if (set_dunit(m, dunit, vctl) < 0)

+ if (set_dunit(m, dunit) < 0)

goto parse;

else {

/*

@@ -217,8 +211,7 @@ next:

static void __dead2

usage(void)

{

- fprintf(stderr, "usage: %1$s [-f device] [-d pcmN | N "

- "[-V voss_device:mode]] [-os] [dev[.control[=value]]] ...\n"

+ fprintf(stderr, "usage: %1$s [-f device] [-d pcmN | N] [-os] [dev[.control[=value]]] ...\n"

" %1$s [-os] -a\n"

" %1$s -h\n", getprogname());

exit(1);

@@ -331,32 +324,9 @@ printrecsrc(struct mixer *m, int oflag)

}

static int

-set_dunit(struct mixer *m, int dunit, char *vctl)

+set_dunit(struct mixer *m, int dunit)

{

- const char *opt;

- char *dev, *mode;

- char buf[32];

- size_t size;

- int n, rc;

-

- /*

- * Issue warning in case of hw.snd.basename_clone being unset. Omit the

- * check and warning if the -V flag is used, since the user is most

- * likely to be aware of this, and the warning might be confusing.

- */

- if (vctl == NULL) {

- size = sizeof(int);

- if (sysctlbyname("hw.snd.basename_clone", &n, &size,

- NULL, 0) < 0) {

- warn("hw.snd.basename_clone failed");

- return (-1);

- }

- if (n == 0) {

- warnx("warning: hw.snd.basename_clone not set. "

- "/dev/dsp is managed externally and does not "

- "change with the default unit change here.");

- }

- }

+ int n;

if ((n = mixer_get_dunit()) < 0) {

warn("cannot get default unit");

@@ -368,43 +338,6 @@ set_dunit(struct mixer *m, int dunit, char *vctl)

}

printf("default_unit: %d -> %d\n", n, dunit);

- /* Hot-swap in case virtual_oss exists and is running. */

- if (vctl != NULL) {

- dev = strsep(&vctl, ":");

- mode = vctl;

- if (dev == NULL || mode == NULL) {

- warnx("voss_device:mode tuple incomplete");

- return (-1);

- }

- if (strcmp(mode, "all") == 0)

- opt = "-f";

- else if (strcmp(mode, "play") == 0)

- opt = "-P";

- else if (strcmp(mode, "rec") == 0)

- opt = "-R";

- else {

- warnx("please use one of the following modes: "

- "all, play, rec");

- return (-1);

- }

- snprintf(buf, sizeof(buf), "/dev/dsp%d", dunit);

- switch (fork()) {

- case -1:

- warn("fork");

- break;

- case 0:

- rc = execl("/usr/sbin/virtual_oss_cmd",

- "virtual_oss_cmd", dev, opt, buf, NULL);

- if (rc < 0)

- warn("virtual_oss_cmd");

- _exit(0);

- default:

- if (wait(NULL) < 0)

- warn("wait");

- break;

- }

- }

-

return (0);

}