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