FreeBSD manual
download PDF document: mixer_get_dev.3.pdf
MIXER(3) FreeBSD Library Functions Manual MIXER(3)
NAME
mixer_open, mixer_close, mixer_get_dev, mixer_get_dev_byname,
mixer_add_ctl, mixer_add_ctl_s, mixer_remove_ctl, mixer_get_ctl,
mixer_get_ctl_byname, mixer_set_vol, mixer_set_mute, mixer_mod_recsrc,
mixer_get_dunit, mixer_set_dunit, mixer_get_mode, mixer_get_nmixers,
MIX_ISDEV, MIX_ISMUTE, MIX_ISREC, MIX_ISRECSRC, MIX_VOLNORM,
MIX_VOLDENORM - interface to OSS mixers
LIBRARY
Mixer library (libmixer, -lmixer)
SYNOPSIS
#include <mixer.h>
struct mixer *
mixer_open(const char *name);
int
mixer_close(struct mixer *m);
struct mix_dev *
mixer_get_dev(struct mixer *m, int devno);
struct mix_dev *
mixer_get_dev_byname(struct mixer *m, name);
int
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));
int
mixer_add_ctl_s(mix_ctl_t *ctl);
int
mixer_remove_ctl(mix_ctl_t *ctl);
mix_ctl_t *
mixer_get_ctl(struct mix_dev *d, int id);
mix_ctl_t *
mixer_get_ctl_byname(struct mix_dev *d, const char *name);
int
mixer_set_vol(struct mixer *m, mix_volume_t vol);
int
mixer_set_mute(struct mixer *m, int opt);
int
mixer_mod_recsrc(struct mixer *m, int opt);
int
mixer_get_dunit(void);
mixer_get_nmixers(void);
int
MIX_ISDEV(struct mixer *m, int devno);
int
MIX_ISMUTE(struct mixer *m, int devno);
int
MIX_ISREC(struct mixer *m, int devno);
int
MIX_ISRECSRC(struct mixer *m, int devno);
float
MIX_VOLNORM(int v);
int
MIX_VOLDENORM(float v);
DESCRIPTION
The mixer library allows userspace programs to access and manipulate OSS
sound mixers in a simple way.
Mixer
A mixer is described by the following structure:
struct mixer {
TAILQ_HEAD(mix_devhead, 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 */
};
The fields are follows:
devs A tail queue structure containing all supported mixer devices.
dev A pointer to the currently selected device. The device is one
<sys/soundcard.h>.
name Path to the mixer (e.g /dev/mixer0).
fd File descriptor returned when the mixer is opened in
mixer_open().
unit Audio card unit. Since each mixer device maps to a pcmX
device, 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 unit is 0 as well. This number is useful when
checking if the mixer's audio card is the default one.
ndev Number of devices in devs.
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, mixer_open() stores only the
supported devices in devs, so it is very unlikely this mask
will be needed.
mutemask Bit mask containing all muted devices. The logic is the same
as with devmask.
recmask Bit mask containing all recording devices. Again, same logic
as with the other masks.
recsrc Bit mask containing all recording sources. Yes, same logic
again.
mode Bit mask containing the supported modes for this audio device.
It holds the value of the dev.pcm.X.mode sysctl.
f_default Flag which tells whether the mixer's audio card is the default
one.
Mixer device
Each mixer device stored in a mixer is described as follows:
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_ctlhead, mix_ctl) ctls; /* control list */
TAILQ_ENTRY(mix_dev) devs;
};
The fields are follows:
parent_mixer Pointer to the mixer the device is attached to.
devno Device's index in the SOUND_MIXER_NRDEVICES macro defined
in <sys/soundcard.h>. This number is used to check against
the masks defined in the mixer structure.
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 MIX_VOLDENORM macro if needed.
nctl Number of user-defined mixer controls associated with the
device.
ctls A tail queue containing user-defined mixer controls.
User-defined mixer controls
Each mixer device can have user-defined controls. The control structure
is defined as follows:
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;
};
The fields are follows:
parent_dev Pointer to the device the control is attached to.
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.
name Control name. As with id, the caller has to make sure the
same name is not used more than once.
mod Function pointer to a control modification function. As in
mixer(8), each mixer control's values can be modified. For
example, if we have a volume control, the mod function will
be responsible for handling volume changes.
print Function pointer to a control print function.
Opening and closing the mixer
The application must first call the mixer_open() function to obtain a
handle to the device, which is used as an argument in most other
functions and macros. The parameter name specifies the path to the
mixer. OSS mixers are stored under /dev/mixerN where N is the number of
the mixer device. Each device maps to an actual pcm audio card, so
/dev/mixer0 is the mixer for pcm0, and so on. If name is NULL or
/dev/mixer, mixer_open() opens the default mixer (hw.snd.default_unit).
The mixer_close() function frees resources and closes the mixer device.
It is a good practice to always call it when the application is done
using the mixer.
The mixer_set_vol() function changes the volume of the selected mixer
device. The 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).
The mixer_set_mute() function modifies the mute of a selected device.
The opt parameter has to be one of the following options:
MIX_MUTE Mute the device.
MIX_UNMUTE Unmute the device.
MIX_TOGGLEMUTE Toggle the device's mute (e.g mute if unmuted and
unmute if muted).
The mixer_mod_recsrc() function modifies a recording device. The
selected device has to be a recording device, otherwise the function will
fail. The opt parameter has to be one of the following options:
MIX_ADDRECSRC Add device to the recording sources.
MIX_REMOVERECSRC Remove device from the recording sources.
MIX_SETRECSRC Set device as the only recording source.
MIX_TOGGLERECSRC Toggle device from the recording sources.
The mixer_get_dunit() and mixer_set_dunit() functions get and set the
default audio card in the system. Although this is not really a mixer
feature, it is useful to have instead of having to use the sysctl(3)
controls.
The mixer_get_mode() function returns the playback/recording mode of the
audio device the mixer belongs to. The available values are the
following:
MIX_STATUS_NONE Neither playback nor recording.
MIX_STATUS_PLAY Playback.
MIX_STATUS_REC Recording.
MIX_STATUS_PLAY | MIX_STATUS_REC Playback and recording.
The mixer_get_nmixers() function returns the total number of mixer
devices in the system.
The MIX_ISDEV() macro checks if a device is actually a valid device for a
given mixer. It is very unlikely that this macro will ever be needed
since the library stores only valid devices by default.
The MIX_ISMUTE() macro checks if a device is muted.
The MIX_ISREC() macro checks if a device is a recording device.
The MIX_ISRECSRC() macro checks if a device is a recording source.
The MIX_VOLNORM() macro normalizes a value to 32-bit floating point
device specified in the parent argument.
The mix_add_ctl_s() function does the same thing as with mix_add_ctl()
but the caller passes a mix_ctl_t * structure instead of each field as a
separate argument.
The mixer_remove_ctl() functions removes a control from the device its
attached to.
The mixer_get_ctl() function searches for a control in the device
specified in the d argument and returns a pointer to it. The search is
done using the control's ID.
The mixer_get_ctl_byname() function is the same as with mixer_get_ctl()
but the search is done using the control's name.
RETURN VALUES
The mixer_open() function returns the newly created handle on success and
NULL on failure.
The mixer_close(), mixer_set_vol(), mixer_set_mute(), mixer_mod_recsrc(),
mixer_get_dunut(), mixer_set_dunit() and mixer_get_nmixers() functions
return 0 or positive values on success and -1 on failure.
The mixer_get_dev() and mixer_get_dev_byname() functions return the
selected device on success and NULL on failure.
All functions set the value of errno on failure.
EXAMPLES
Change the volume of a device
struct mixer *m;
mix_volume_t vol;
char *mix_name, *dev_name;
mix_name = ...;
if ((m = mixer_open(mix_name)) == NULL)
err(1, "mixer_open: %s", mix_name);
dev_name = ...;
if ((m->dev = mixer_get_dev_byname(m, dev_name)) < 0)
err(1, "unknown device: %s", dev_name);
vol.left = ...;
vol.right = ....;
if (mixer_set_vol(m, vol) < 0)
warn("cannot change volume");
(void)mixer_close(m);
Mute all unmuted devices
struct mixer *m;
struct mix_dev *dp;
if ((m = mixer_open(NULL)) == NULL) /* Open the default mixer. */
err(1, "mixer_open");
TAILQ_FOREACH(dp, &m->devs, devs) {
m->dev = dp; /* Select device. */
if (M_ISMUTE(m, dp->devno))
Print all recording sources' names and volumes
struct mixer *m;
struct mix_dev *dp;
char *mix_name, *dev_name;
mix_name = ...;
if ((m = mixer_open(mix_name)) == NULL)
err(1, "mixer_open: %s", mix_name);
TAILQ_FOREACH(dp, &m->devs, devs) {
if (M_ISRECSRC(m, dp->devno))
printf("%s\t%.2f:%.2f\n",
dp->name, dp->vol.left, dp->vol.right);
}
(void)mixer_close(m);
SEE ALSO
queue(3), sysctl(3), sound(4), mixer(8) and errno(2)
AUTHORS
Christos Margiolis <christos@FreeBSD.org>
FreeBSD 14.0-RELEASE-p11 January 19, 2023 FreeBSD 14.0-RELEASE-p11