xref: /freebsd/lib/libmixer/mixer.3 (revision 5bb3134a8c21cb87b30e135ef168483f0333dabb)
1.\"-
2.\" Copyright (c) 2021 Christos Margiolis <christos@FreeBSD.org>
3.\"
4.\" Permission is hereby granted, free of charge, to any person obtaining a copy
5.\" of this software and associated documentation files (the "Software"), to deal
6.\" in the Software without restriction, including without limitation the rights
7.\" to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8.\" copies of the Software, and to permit persons to whom the Software is
9.\" furnished to do so, subject to the following conditions:
10.\"
11.\" The above copyright notice and this permission notice shall be included in
12.\" all copies or substantial portions of the Software.
13.\"
14.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15.\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16.\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17.\" AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18.\" LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19.\" OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20.\" THE SOFTWARE.
21.\"
22.\" $FreeBSD$
23.\"
24
25.Dd September 22, 2021
26.Dt mixer 3
27.Os
28.Sh NAME
29.Nm mixer_open ,
30.Nm mixer_close ,
31.Nm mixer_get_dev ,
32.Nm mixer_get_dev_byname ,
33.Nm mixer_add_ctl ,
34.Nm mixer_add_ctl_s ,
35.Nm mixer_remove_ctl ,
36.Nm mixer_get_ctl ,
37.Nm mixer_get_ctl_byname ,
38.Nm mixer_set_vol ,
39.Nm mixer_set_mute ,
40.Nm mixer_mod_recsrc ,
41.Nm mixer_get_dunit ,
42.Nm mixer_set_dunit ,
43.Nm mixer_get_mode,
44.Nm mixer_get_nmixers ,
45.Nm MIX_ISDEV ,
46.Nm MIX_ISMUTE ,
47.Nm MIX_ISREC ,
48.Nm MIX_ISRECSRC ,
49.Nm MIX_VOLNORM ,
50.Nm MIX_VOLDENORM
51.Nd interface to OSS mixers
52.Sh LIBRARY
53Mixer library (libmixer, -lmixer)
54.Sh SYNOPSIS
55.In mixer.h
56.Ft struct mixer *
57.Fn mixer_open "const char *name"
58.Ft int
59.Fn mixer_close "struct mixer *m"
60.Ft struct mix_dev *
61.Fn mixer_get_dev "struct mixer *m" "int devno"
62.Ft struct mix_dev *
63.Fn mixer_get_dev_byname "struct mixer *m" "name"
64.Ft int
65.Fn mixer_add_ctl "struct mix_dev *parent" "int id" "const char *name" \
66    "int (*mod)(struct mix_dev *d, void *p)" \
67    "int (*print)(struct mix_dev *d, void *p)
68.Ft int
69.Fn mixer_add_ctl_s "mix_ctl_t *ctl"
70.Ft int
71.Fn mixer_remove_ctl "mix_ctl_t *ctl"
72.Ft mix_ctl_t *
73.Fn mixer_get_ctl "struct mix_dev *d" "int id"
74.Ft mix_ctl_t *
75.Fn mixer_get_ctl_byname "struct mix_dev *d" "const char *name"
76.Ft int
77.Fn mixer_set_vol "struct mixer *m" "mix_volume_t vol"
78.Ft int
79.Fn mixer_set_mute "struct mixer *m" "int opt"
80.Ft int
81.Fn mixer_mod_recsrc "struct mixer *m" "int opt"
82.Ft int
83.Fn mixer_get_dunit "void"
84.Ft int
85.Fn mixer_set_dunit "struct mixer *m" "int unit"
86.Ft int
87.Fn mixer_get_mode "int unit"
88.Ft int
89.Fn mixer_get_nmixers "void"
90.Ft int
91.Fn MIX_ISDEV "struct mixer *m" "int devno"
92.Ft int
93.Fn MIX_ISMUTE "struct mixer *m" "int devno"
94.Ft int
95.Fn MIX_ISREC "struct mixer *m" "int devno"
96.Ft int
97.Fn MIX_ISRECSRC "struct mixer *m" "int devno"
98.Ft float
99.Fn MIX_VOLNORM "int v"
100.Ft int
101.Fn MIX_VOLDENORM "float v"
102.Sh DESCRIPTION
103The
104.Nm mixer
105library allows userspace programs to access and manipulate OSS sound mixers in
106a simple way.
107.Ss Mixer
108.Pp
109A mixer is described by the following structure:
110.Bd -literal
111struct mixer {
112	TAILQ_HEAD(, mix_dev) devs;		/* device list */
113	struct mix_dev *dev;			/* selected device */
114	oss_mixerinfo mi;			/* mixer info */
115	oss_card_info ci;			/* audio card info */
116	char name[NAME_MAX];			/* mixer name (e.g /dev/mixer0) */
117	int fd;					/* file descriptor */
118	int unit;				/* audio card unit */
119	int ndev;				/* number of devices */
120	int devmask;				/* supported devices */
121#define MIX_MUTE		0x01
122#define MIX_UNMUTE		0x02
123#define MIX_TOGGLEMUTE		0x04
124	int mutemask;				/* muted devices */
125	int recmask;				/* recording devices */
126#define MIX_ADDRECSRC		0x01
127#define MIX_REMOVERECSRC	0x02
128#define MIX_SETRECSRC		0x04
129#define MIX_TOGGLERECSRC	0x08
130	int recsrc;				/* recording sources */
131#define MIX_MODE_MIXER		0x01
132#define MIX_MODE_PLAY		0x02
133#define MIX_MODE_REC		0x04
134	int mode;				/* dev.pcm.X.mode sysctl */
135	int f_default;				/* default mixer flag */
136};
137.Ed
138.Pp
139The fields are follows:
140.Bl -tag -width "f_default"
141.It Fa devs
142A tail queue structure containing all supported mixer devices.
143.It Fa dev
144A pointer to the currently selected device. The device is one of the elements in
145.Ar devs .
146.It Fa mi
147OSS information about the mixer. Look at the definition of the
148.Ft oss_mixerinfo
149structure in
150.In sys/soundcard.h
151to see its fields.
152.It Fa ci
153OSS audio card information. This structure is also defined in
154.In sys/soundcard.h .
155.It Fa name
156Path to the mixer (e.g /dev/mixer0).
157.It Fa fd
158File descriptor returned when the mixer is opened in
159.Fn mixer_open .
160.It Fa unit
161Audio card unit. Since each mixer device maps to a pcmX device,
162.Ar unit
163is always equal to the number of that pcmX device. For example, if the audio
164device's number is 0 (i.e pcm0), then
165.Ar unit
166is 0 as well. This number is useful when checking if the mixer's audio
167card is the default one.
168.It Fa ndev
169Number of devices in
170.Ar devs .
171.It Fa devmask
172Bit mask containing all supported devices for the mixer. For example
173if device 10 is supported, then the 10th bit in the mask will be set. By default,
174.Fn mixer_open
175stores only the supported devices in devs, so it's very unlikely this mask will
176be needed.
177.It Fa mutemask
178Bit mask containing all muted devices. The logic is the same as with
179.Ar devmask .
180.It Fa recmask
181Bit mask containing all recording devices. Again, same logic as with the
182other masks.
183.It Fa recsrc
184Bit mask containing all recording sources. Yes, same logic again.
185.It Fa mode
186Bit mask containing the supported modes for this audio device. It holds the value
187of the
188.Ar dev.pcm.X.mode
189sysctl.
190.It Fa f_default
191Flag which tells whether the mixer's audio card is the default one.
192.El
193.Ss Mixer device
194.Pp
195Each mixer device stored in a mixer is described as follows:
196.Bd -literal
197struct mix_dev {
198	struct mixer *parent_mixer;		/* parent mixer */
199	char name[NAME_MAX];			/* device name (e.g "vol") */
200	int devno;				/* device number */
201	struct mix_volume {
202#define MIX_VOLMIN		0.0f
203#define MIX_VOLMAX		1.0f
204#define MIX_VOLNORM(v)		((v) / 100.0f)
205#define MIX_VOLDENORM(v)	((int)((v) * 100.0f + 0.5f))
206		float left;			/* left volume */
207		float right;			/* right volume */
208	} vol;
209	int nctl;				/* number of controls */
210	TAILQ_HEAD(, mix_ctl) ctls;		/* control list */
211	TAILQ_ENTRY(mix_dev) devs;
212};
213.Ed
214.Pp
215The fields are follows:
216.Bl -tag -width "parent_mixer"
217.It Fa parent_mixer
218Pointer to the mixer the device is attached to.
219.It Fa name
220Device name given by the OSS API. Devices can have one of the following names:
221.Bd -ragged
222vol, bass, treble, synth, pcm, speaker, line, mic, cd, mix,
223pcm2, rec, igain, ogain, line1, line2, line3, dig1, dig2, dig3,
224phin, phout, video, radio, and monitor.
225.Ed
226.It Fa devno
227Device's index in the SOUND_MIXER_NRDEVICES macro defined in
228.In sys/soundcard.h .
229This number is used to check against the masks defined in the
230.Ar mixer
231structure.
232.It Fa left, right
233Left and right-ear volumes. Although the OSS API stores volumes in integers from
2340-100, we normalize them to 32-bit floating point numbers. However, the volumes
235can be denormalized using the
236.Ar MIX_VOLDENORM
237macro if needed.
238.It Fa nctl
239Number of user-defined mixer controls associated with the device.
240.It Fa ctls
241A tail queue containing user-defined mixer controls.
242.El
243.Ss User-defined mixer controls
244.Pp
245Each mixer device can have user-defined controls. The control structure
246is defined as follows:
247.Bd -literal
248struct mix_ctl {
249	struct mix_dev *parent_dev;		/* parent device */
250	int id;					/* control id */
251	char name[NAME_MAX];			/* control name */
252	int (*mod)(struct mix_dev *, void *);	/* modify control values */
253	int (*print)(struct mix_dev *, void *);	/* print control */
254	TAILQ_ENTRY(mix_ctl) ctls;
255};
256.Ed
257.Pp
258The fields are follows:
259.Bl -tag -width "parent_dev"
260.It Fa parent_dev
261Pointer to the device the control is attached to.
262.It Fa id
263Control ID assigned by the caller. Even though the library will
264report it, care has to be taken to not give a control the same ID in case
265the caller has to choose controls using their ID.
266.It Fa name
267Control name. As with
268.Ar id ,
269the caller has to make sure the same name is not used more than once.
270.It Fa mod
271Function pointer to a control modification function. As in
272.Xr mixer 8 ,
273each mixer control's values can be modified. For example, if we have a
274volume control, the
275.Ar mod
276function will be responsible for handling volume changes.
277.It Fa print
278Function pointer to a control print function.
279.El
280.Ss Opening and closing the mixer
281.Pp
282The application must first call the
283.Fn mixer_open
284function to obtain a handle to the device, which is used as an argument
285in most other functions and macros. The parameter
286.Ar name
287specifies the path to the mixer. OSS mixers are stored under
288.Ar /dev/mixerN
289where
290.Ar N
291is the number of the mixer device. Each device maps to an actual
292.Ar pcm
293audio card, so
294.Ar /dev/mixer0
295is the mixer for
296.Ar pcm0 ,
297and so on. If
298.Ar name
299is
300.Ar NULL
301or
302.Ar /dev/mixer ,
303.Fn mixer_open
304opens the default mixer (hw.snd.defaul_unit).
305.Pp
306The
307.Fn mixer_close
308function frees resources and closes the mixer device. It's a good practice to
309always call it when the application is done using the mixer.
310.Ss Manipulating the mixer
311.Pp
312The
313.Fn mixer_get_dev
314and
315.Fn mixer_get_dev_byname
316functions select a mixer device, either by its number or by its name
317respectively. The mixer structure keeps a list of all the devices, but only
318one can be manipulated at a time. Each time a new device is to be manipulated,
319one of the two functions has to be called.
320.Pp
321The
322.Fn mixer_set_vol
323function changes the volume of the selected mixer device. The
324.Ar vol
325parameter is a structure that stores the left and right volumes of a given
326device. The allowed volume values are between MIX_VOLMIN (0.0) and
327MIX_VOLMAX (1.0).
328.Pp
329The
330.Fn mixer_set_mute
331function modifies the mute of a selected device. The
332.Ar opt
333parameter has to be one of the following options:
334.Bl -tag -width MIX_TOGGLEMUTE -offset indent
335.It Dv MIX_MUTE
336Mute the device.
337.It Dv MIX_UNMUTE
338Unmute the device.
339.It Dv MIX_TOGGLEMUTE
340Toggle the device's mute (e.g mute if unmuted and unmute if muted).
341.El
342.Pp
343The
344.Fn mixer_mod_recsrc
345function modifies a recording device. The selected device has to be
346a recording device, otherwise the function will fail. The
347.Ar opt
348parameter has to be one of the following options:
349.Bl -tag -width MIX_REMOVERECSRC -offset indent
350.It Dv MIX_ADDRECSRC
351Add device to the recording sources.
352.It Dv MIX_REMOVERECSRC
353Remove device from the recording sources.
354.It Dv MIX_SETRECSRC
355Set device as the only recording source.
356.It Dv MIX_TOGGLERECSRC
357Toggle device from the recording sources.
358.El
359.Pp
360The
361.Fn mixer_get_dunit
362and
363.Fn mixer_set_dunit
364functions get and set the default audio card in the system. Although this is
365not really a mixer feature, it's useful to have instead of having to use
366the
367.Xr sysctl 3
368controls.
369.Pp
370The
371.Fn mixer_get_mode
372function returns the playback/recording mode of the audio device the mixer
373belongs to. The available values are the following:
374.Bl -tag -width "MIX_STATUS_PLAY | MIX_STATUS_REC" -offset indent
375.It Dv MIX_STATUS_NONE
376Neither playback nor recording.
377.It Dv MIX_STATUS_PLAY
378Playback.
379.It Dv MIX_STATUS_REC
380Recording.
381.It Dv MIX_STATUS_PLAY | MIX_STATUS_REC
382Playback and recording.
383.El
384.Pp
385The
386.Fn mixer_get_nmixers
387function returns the total number of mixer devices in the system.
388.Pp
389The
390.Fn MIX_ISDEV
391macro checks if a device is actually a valid device for a given mixer. It's very
392unlikely that this macro will ever be needed since the library stores only
393valid devices by default.
394.Pp
395The
396.Fn MIX_ISMUTE
397macro checks if a device is muted.
398.Pp
399The
400.Fn MIX_ISREC
401macro checks if a device is a recording device.
402.Pp
403The
404.Fn MIX_ISRECSRC
405macro checks if a device is a recording source.
406.Pp
407The
408.Fn MIX_VOLNORM
409macro normalizes a value to 32-bit floating point number. It's used
410to normalize the volumes read from the OSS API.
411.Pp
412The
413.Fn MIX_VOLDENORM
414macro denormalizes the left and right volumes stores in the
415.Ft mix_dev
416structure.
417.Ss Defining and using mixer controls
418.Pp
419The
420.Fn mix_add_ctl
421function creates a control and attaches it to the device specified in the
422.Ar parent
423argument.
424.Pp
425The
426.Fn mix_add_ctl_s
427function does the same thing as with
428.Fn mix_add_ctl
429but the caller passes a
430.Ft mix_ctl_t *
431structure instead of each field as a seperate argument.
432.Pp
433The
434.Fn mixer_remove_ctl
435functions removes a control from the device its attached to.
436.Pp
437The
438.Fn mixer_get_ctl
439function searches for a control in the device specified in the
440.Ar d
441argument and returns a pointer to it. The search is done using the control's ID.
442.Pp
443The
444.Fn mixer_get_ctl_byname
445function is the same as with
446.Fn mixer_get_ctl
447but the search is done using the control's name.
448.Sh RETURN VALUES
449.Pp
450The
451.Fn mixer_open
452function returns the newly created handle on success and NULL on failure.
453.Pp
454The
455.Fn mixer_close ,
456.Fn mixer_set_vol ,
457.Fn mixer_set_mute ,
458.Fn mixer_mod_recsrc ,
459.Fn mixer_get_dunut ,
460.Fn mixer_set_dunit
461and
462.Fn mixer_get_nmixers
463functions return 0 or positive values on success and -1 on failure.
464.Pp
465The
466.Fn mixer_get_dev
467and
468.Fn mixer_get_dev_byname
469functions return the selected device on success and NULL on failure.
470.Pp
471All functions set the value of
472.Ar errno
473on failure.
474.Sh EXAMPLES
475.Ss Change the volume of a device
476.Bd -literal
477struct mixer *m;
478mix_volume_t vol;
479char *mix_name, *dev_name;
480
481mix_name = ...;
482if ((m = mixer_open(mix_name)) == NULL)
483	err(1, "mixer_open: %s", mix_name);
484
485dev_name = ...;
486if ((m->dev = mixer_get_dev_byname(m, dev_name)) < 0)
487	err(1, "unknown device: %s", dev_name);
488
489vol.left = ...;
490vol.right = ....;
491if (mixer_set_vol(m, vol) < 0)
492	warn("cannot change volume");
493
494(void)mixer_close(m);
495.Ed
496.Ss Mute all unmuted devices
497.Bd -literal
498struct mixer *m;
499struct mix_dev *dp;
500
501if ((m = mixer_open(NULL)) == NULL)	/* Open the default mixer. */
502	err(1, "mixer_open");
503TAILQ_FOREACH(dp, &m->devs, devs) {
504	m->dev = dp;			/* Select device. */
505	if (M_ISMUTE(m, dp->devno))
506		continue;
507	if (mixer_set_mute(m, MIX_MUTE) < 0)
508		warn("cannot mute device: %s", dp->name);
509}
510
511(void)mixer_close(m);
512.Ed
513.Ss Print all recording sources' names and volumes
514.Bd -literal
515struct mixer *m;
516struct mix_dev *dp;
517
518char *mix_name, *dev_name;
519
520mix_name = ...;
521if ((m = mixer_open(mix_name)) == NULL)
522	err(1, "mixer_open: %s", mix_name);
523
524TAILQ_FOREACH(dp, &m->devs, devs) {
525	if (M_ISRECSRC(m, dp->devno))
526		printf("%s\\t%.2f:%.2f\\n",
527		    dp->name, dp->vol.left, dp->vol.right);
528}
529
530(void)mixer_close(m);
531.Ed
532.Sh SEE ALSO
533.Xr mixer 8 ,
534.Xr sound 4 ,
535.Xr sysctl 3 ,
536.Xr queue 3
537and
538.Xr errno 2
539.Sh AUTHORS
540.An Christos Margiolis Aq Mt christos@FreeBSD.org
541