xref: /freebsd/lib/libmixer/mixer.3 (revision b85b9c88eb02298ea7fa3885619f54ac0e930ba4)
1.\"-
2.\" Copyright (c) 2021-2022 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 March 19, 2022
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
108A mixer is described by the following structure:
109.Bd -literal
110struct mixer {
111	TAILQ_HEAD(, mix_dev) devs;		/* device list */
112	struct mix_dev *dev;			/* selected device */
113	oss_mixerinfo mi;			/* mixer info */
114	oss_card_info ci;			/* audio card info */
115	char name[NAME_MAX];			/* mixer name (e.g /dev/mixer0) */
116	int fd;					/* file descriptor */
117	int unit;				/* audio card unit */
118	int ndev;				/* number of devices */
119	int devmask;				/* supported devices */
120#define MIX_MUTE		0x01
121#define MIX_UNMUTE		0x02
122#define MIX_TOGGLEMUTE		0x04
123	int mutemask;				/* muted devices */
124	int recmask;				/* recording devices */
125#define MIX_ADDRECSRC		0x01
126#define MIX_REMOVERECSRC	0x02
127#define MIX_SETRECSRC		0x04
128#define MIX_TOGGLERECSRC	0x08
129	int recsrc;				/* recording sources */
130#define MIX_MODE_MIXER		0x01
131#define MIX_MODE_PLAY		0x02
132#define MIX_MODE_REC		0x04
133	int mode;				/* dev.pcm.X.mode sysctl */
134	int f_default;				/* default mixer flag */
135};
136.Ed
137.Pp
138The fields are follows:
139.Bl -tag -width "f_default"
140.It Fa devs
141A tail queue structure containing all supported mixer devices.
142.It Fa dev
143A pointer to the currently selected device.
144The device is one of the elements in
145.Ar devs .
146.It Fa mi
147OSS information about the mixer.
148Look at the definition of the
149.Ft oss_mixerinfo
150structure in
151.In sys/soundcard.h
152to see its fields.
153.It Fa ci
154OSS audio card information.
155This structure is also defined in
156.In sys/soundcard.h .
157.It Fa name
158Path to the mixer (e.g /dev/mixer0).
159.It Fa fd
160File descriptor returned when the mixer is opened in
161.Fn mixer_open .
162.It Fa unit
163Audio card unit.
164Since each mixer device maps to a pcmX device,
165.Ar unit
166is always equal to the number of that pcmX device.
167For example, if the audio device's number is 0 (i.e pcm0), then
168.Ar unit
169is 0 as well.
170This number is useful when checking if the mixer's audio card is the default one.
171.It Fa ndev
172Number of devices in
173.Ar devs .
174.It Fa devmask
175Bit mask containing all supported devices for the mixer.
176For example, if device 10 is supported, then the 10th bit in the mask will be set.
177By default,
178.Fn mixer_open
179stores only the supported devices in devs, so it is very unlikely this mask will
180be needed.
181.It Fa mutemask
182Bit mask containing all muted devices.
183The logic is the same as with
184.Ar devmask .
185.It Fa recmask
186Bit mask containing all recording devices.
187Again, same logic as with the other masks.
188.It Fa recsrc
189Bit mask containing all recording sources.
190Yes, same logic again.
191.It Fa mode
192Bit mask containing the supported modes for this audio device.
193It holds the value of the
194.Ar dev.pcm.X.mode
195sysctl.
196.It Fa f_default
197Flag which tells whether the mixer's audio card is the default one.
198.El
199.Ss Mixer device
200Each mixer device stored in a mixer is described as follows:
201.Bd -literal
202struct mix_dev {
203	struct mixer *parent_mixer;		/* parent mixer */
204	char name[NAME_MAX];			/* device name (e.g "vol") */
205	int devno;				/* device number */
206	struct mix_volume {
207#define MIX_VOLMIN		0.0f
208#define MIX_VOLMAX		1.0f
209#define MIX_VOLNORM(v)		((v) / 100.0f)
210#define MIX_VOLDENORM(v)	((int)((v) * 100.0f + 0.5f))
211		float left;			/* left volume */
212		float right;			/* right volume */
213	} vol;
214	int nctl;				/* number of controls */
215	TAILQ_HEAD(, mix_ctl) ctls;		/* control list */
216	TAILQ_ENTRY(mix_dev) devs;
217};
218.Ed
219.Pp
220The fields are follows:
221.Bl -tag -width "parent_mixer"
222.It Fa parent_mixer
223Pointer to the mixer the device is attached to.
224.It Fa name
225Device name given by the OSS API.
226Devices can have one of the following names:
227.Bd -ragged
228vol, bass, treble, synth, pcm, speaker, line, mic, cd, mix,
229pcm2, rec, igain, ogain, line1, line2, line3, dig1, dig2, dig3,
230phin, phout, video, radio, and monitor.
231.Ed
232.It Fa devno
233Device's index in the SOUND_MIXER_NRDEVICES macro defined in
234.In sys/soundcard.h .
235This number is used to check against the masks defined in the
236.Ar mixer
237structure.
238.It Fa left right
239Left and right-ear volumes.
240Although the OSS API stores volumes in integers from 0-100, \
241we normalize them to 32-bit floating point numbers.
242However, the volumes can be denormalized using the
243.Ar MIX_VOLDENORM
244macro if needed.
245.It Fa nctl
246Number of user-defined mixer controls associated with the device.
247.It Fa ctls
248A tail queue containing user-defined mixer controls.
249.El
250.Ss User-defined mixer controls
251Each mixer device can have user-defined controls.
252The control structure is defined as follows:
253.Bd -literal
254struct mix_ctl {
255	struct mix_dev *parent_dev;		/* parent device */
256	int id;					/* control id */
257	char name[NAME_MAX];			/* control name */
258	int (*mod)(struct mix_dev *, void *);	/* modify control values */
259	int (*print)(struct mix_dev *, void *);	/* print control */
260	TAILQ_ENTRY(mix_ctl) ctls;
261};
262.Ed
263.Pp
264The fields are follows:
265.Bl -tag -width "parent_dev"
266.It Fa parent_dev
267Pointer to the device the control is attached to.
268.It Fa id
269Control ID assigned by the caller.
270Even though the library will report it, care has to be taken to not give \
271a control the same ID in case the caller has to choose controls using their ID.
272.It Fa name
273Control name.
274As with
275.Ar id ,
276the caller has to make sure the same name is not used more than once.
277.It Fa mod
278Function pointer to a control modification function.
279As in
280.Xr mixer 8 ,
281each mixer control's values can be modified.
282For example, if we have a volume control, the
283.Ar mod
284function will be responsible for handling volume changes.
285.It Fa print
286Function pointer to a control print function.
287.El
288.Ss Opening and closing the mixer
289The application must first call the
290.Fn mixer_open
291function to obtain a handle to the device, which is used as an argument \
292in most other functions and macros.
293The parameter
294.Ar name
295specifies the path to the mixer.
296OSS mixers are stored under
297.Ar /dev/mixerN
298where
299.Ar N
300is the number of the mixer device.
301Each device maps to an actual
302.Ar pcm
303audio card, so
304.Ar /dev/mixer0
305is the mixer for
306.Ar pcm0 ,
307and so on.
308If
309.Ar name
310is
311.Ar NULL
312or
313.Ar /dev/mixer ,
314.Fn mixer_open
315opens the default mixer (hw.snd.default_unit).
316.Pp
317The
318.Fn mixer_close
319function frees resources and closes the mixer device.
320It is a good practice to always call it when the application is done using the mixer.
321.Ss Manipulating the mixer
322The
323.Fn mixer_get_dev
324and
325.Fn mixer_get_dev_byname
326functions select a mixer device, either by its number or by its name respectively.
327The mixer structure keeps a list of all the devices, but only \
328one can be manipulated at a time.
329Each time a new device is to be manipulated, one of the two functions has to be called.
330.Pp
331The
332.Fn mixer_set_vol
333function changes the volume of the selected mixer device.
334The
335.Ar vol
336parameter is a structure that stores the left and right volumes of a given device.
337The allowed volume values are between MIX_VOLMIN (0.0) and MIX_VOLMAX (1.0).
338.Pp
339The
340.Fn mixer_set_mute
341function modifies the mute of a selected device.
342The
343.Ar opt
344parameter has to be one of the following options:
345.Bl -tag -width MIX_TOGGLEMUTE -offset indent
346.It Dv MIX_MUTE
347Mute the device.
348.It Dv MIX_UNMUTE
349Unmute the device.
350.It Dv MIX_TOGGLEMUTE
351Toggle the device's mute (e.g mute if unmuted and unmute if muted).
352.El
353.Pp
354The
355.Fn mixer_mod_recsrc
356function modifies a recording device.
357The selected device has to be a recording device, otherwise the function will fail.
358The
359.Ar opt
360parameter has to be one of the following options:
361.Bl -tag -width MIX_REMOVERECSRC -offset indent
362.It Dv MIX_ADDRECSRC
363Add device to the recording sources.
364.It Dv MIX_REMOVERECSRC
365Remove device from the recording sources.
366.It Dv MIX_SETRECSRC
367Set device as the only recording source.
368.It Dv MIX_TOGGLERECSRC
369Toggle device from the recording sources.
370.El
371.Pp
372The
373.Fn mixer_get_dunit
374and
375.Fn mixer_set_dunit
376functions get and set the default audio card in the system.
377Although this is not really a mixer feature, it is useful to have instead of \
378having to use the
379.Xr sysctl 3
380controls.
381.Pp
382The
383.Fn mixer_get_mode
384function returns the playback/recording mode of the audio device the mixer \
385belongs to.
386The available values are the following:
387.Bl -tag -width "MIX_STATUS_PLAY | MIX_STATUS_REC" -offset indent
388.It Dv MIX_STATUS_NONE
389Neither playback nor recording.
390.It Dv MIX_STATUS_PLAY
391Playback.
392.It Dv MIX_STATUS_REC
393Recording.
394.It Dv MIX_STATUS_PLAY | MIX_STATUS_REC
395Playback and recording.
396.El
397.Pp
398The
399.Fn mixer_get_nmixers
400function returns the total number of mixer devices in the system.
401.Pp
402The
403.Fn MIX_ISDEV
404macro checks if a device is actually a valid device for a given mixer.
405It is very unlikely that this macro will ever be needed since the library \
406stores only valid devices by default.
407.Pp
408The
409.Fn MIX_ISMUTE
410macro checks if a device is muted.
411.Pp
412The
413.Fn MIX_ISREC
414macro checks if a device is a recording device.
415.Pp
416The
417.Fn MIX_ISRECSRC
418macro checks if a device is a recording source.
419.Pp
420The
421.Fn MIX_VOLNORM
422macro normalizes a value to 32-bit floating point number.
423It is used to normalize the volumes read from the OSS API.
424.Pp
425The
426.Fn MIX_VOLDENORM
427macro denormalizes the left and right volumes stores in the
428.Ft mix_dev
429structure.
430.Ss Defining and using mixer controls
431The
432.Fn mix_add_ctl
433function creates a control and attaches it to the device specified in the
434.Ar parent
435argument.
436.Pp
437The
438.Fn mix_add_ctl_s
439function does the same thing as with
440.Fn mix_add_ctl
441but the caller passes a
442.Ft mix_ctl_t *
443structure instead of each field as a separate argument.
444.Pp
445The
446.Fn mixer_remove_ctl
447functions removes a control from the device its attached to.
448.Pp
449The
450.Fn mixer_get_ctl
451function searches for a control in the device specified in the
452.Ar d
453argument and returns a pointer to it.
454The search is done using the control's ID.
455.Pp
456The
457.Fn mixer_get_ctl_byname
458function is the same as with
459.Fn mixer_get_ctl
460but the search is done using the control's name.
461.Sh RETURN VALUES
462The
463.Fn mixer_open
464function returns the newly created handle on success and NULL on failure.
465.Pp
466The
467.Fn mixer_close ,
468.Fn mixer_set_vol ,
469.Fn mixer_set_mute ,
470.Fn mixer_mod_recsrc ,
471.Fn mixer_get_dunut ,
472.Fn mixer_set_dunit
473and
474.Fn mixer_get_nmixers
475functions return 0 or positive values on success and -1 on failure.
476.Pp
477The
478.Fn mixer_get_dev
479and
480.Fn mixer_get_dev_byname
481functions return the selected device on success and NULL on failure.
482.Pp
483All functions set the value of
484.Ar errno
485on failure.
486.Sh EXAMPLES
487.Ss Change the volume of a device
488.Bd -literal
489struct mixer *m;
490mix_volume_t vol;
491char *mix_name, *dev_name;
492
493mix_name = ...;
494if ((m = mixer_open(mix_name)) == NULL)
495	err(1, "mixer_open: %s", mix_name);
496
497dev_name = ...;
498if ((m->dev = mixer_get_dev_byname(m, dev_name)) < 0)
499	err(1, "unknown device: %s", dev_name);
500
501vol.left = ...;
502vol.right = ....;
503if (mixer_set_vol(m, vol) < 0)
504	warn("cannot change volume");
505
506(void)mixer_close(m);
507.Ed
508.Ss Mute all unmuted devices
509.Bd -literal
510struct mixer *m;
511struct mix_dev *dp;
512
513if ((m = mixer_open(NULL)) == NULL)	/* Open the default mixer. */
514	err(1, "mixer_open");
515TAILQ_FOREACH(dp, &m->devs, devs) {
516	m->dev = dp;			/* Select device. */
517	if (M_ISMUTE(m, dp->devno))
518		continue;
519	if (mixer_set_mute(m, MIX_MUTE) < 0)
520		warn("cannot mute device: %s", dp->name);
521}
522
523(void)mixer_close(m);
524.Ed
525.Ss Print all recording sources' names and volumes
526.Bd -literal
527struct mixer *m;
528struct mix_dev *dp;
529
530char *mix_name, *dev_name;
531
532mix_name = ...;
533if ((m = mixer_open(mix_name)) == NULL)
534	err(1, "mixer_open: %s", mix_name);
535
536TAILQ_FOREACH(dp, &m->devs, devs) {
537	if (M_ISRECSRC(m, dp->devno))
538		printf("%s\\t%.2f:%.2f\\n",
539		    dp->name, dp->vol.left, dp->vol.right);
540}
541
542(void)mixer_close(m);
543.Ed
544.Sh SEE ALSO
545.Xr queue 3 ,
546.Xr sysctl 3 ,
547.Xr sound 4 ,
548.Xr mixer 8
549and
550.Xr errno 2
551.Sh AUTHORS
552.An Christos Margiolis Aq Mt christos@FreeBSD.org
553