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