SIOCTL_OPEN(3)

πŸ“¦
version 1.10.0 Β· 3 versions
, in alpine 3.24, arch rolling, debian trixie, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0, ubuntu resolute, ubuntu stonking

πŸ’– SIOCTL_OPEN(3) πŸ’– β€” the sioctl_* besties, aka ur interface to audio parameters πŸŽ›οΈβœ¨

okay so bestie, this whole page lives in the Library Functions Manual, and it's about the sioctl_open squad: sioctl_open, sioctl_close, sioctl_ondesc, sioctl_onval, sioctl_setval, sioctl_nfds, sioctl_pollfd, sioctl_eof. yes that's a LOT of them. we're getting through all of them, no skips, periodt. 🫢


✨ SYNOPSIS ✨

#include <sndio.h>

struct sioctl_hdl *
sioctl_open(const char *name, unsigned int mode, int nbio_flag);

void
sioctl_close(struct sioctl_hdl *hdl);

int
sioctl_ondesc(struct sioctl_hdl *hdl,
    void (*cb)(void *arg, struct sioctl_desc *desc, int val),
    void *arg);

int
sioctl_onval(struct sioctl_hdl *hdl,
    void (*cb)(void *arg, unsigned int addr, unsigned int val),
    void *arg);

int
sioctl_setval(struct sioctl_hdl *hdl, unsigned int addr,
    unsigned int val);

int
sioctl_nfds(struct sioctl_hdl *hdl);

int
sioctl_pollfd(struct sioctl_hdl *hdl, struct pollfd *pfd, int events);

int
sioctl_revents(struct sioctl_hdl *hdl, struct pollfd *pfd);

int
sioctl_eof(struct sioctl_hdl *hdl);

🌸 DESCRIPTION 🌸

so audio devices can expose a bunch of controls, like the playback volume control, right? every control has an integer address and an integer value. some values are booleans and literally can only be flipped to either 0 (off) or 1 (on). any control can be changed by submitting a new value to its address. and when values change? asynchronous notifications get sent out. it's giving push notifications but for ur mixer. πŸ’…

control descriptions are available too, which lets them be grouped and shown in a human readable form. cute!

πŸŽ€ Opening and closing the control device πŸŽ€

first, ur app has to call sioctl_open() to get a handle. that handle is the hdl argument you'll be passing to all the other functions. it's the main character, everyone else is a supporting actor. πŸ‘‘

the name parameter gives the device string discussed in sndio(7). in most cases it should be set to SIO_DEVANY so the user can pick it with the AUDIODEVICE environment variable. let the people choose, bestie. ✨

the mode parameter is a bitmap of the SIOCTL_READ and SIOCTL_WRITE constants, saying whether control values can be read and modified respectively.

if the nbio_flag argument is 1, then the sioctl_setval() function (peep below) may fail instead of blocking, and the sioctl_ondesc() function doesn't block.

the sioctl_close() function closes the control device and frees any allocated resources tied to the handle. cleanup queen. 🧹

πŸ¦‹ Control descriptions πŸ¦‹

the sioctl_ondesc() function is how you get the description of all available controls plus their initial values. it registers a callback function that gets immediately invoked for all controls. and it's called once with a NULL argument to signal that the full description was sent, and that the caller now has a consistent representation of the control set. that NULL is like the "ok that's everyone, u can stop looking now" moment. 😌

then, whenever a control description changes, the callback gets invoked with the updated info, followed by a call with a NULL argument.

controls are described by the sioctl_desc structure, like this:

struct sioctl_node {
        char name[SIOCTL_NAMEMAX];      /* ex. "spkr" */
        int unit;                       /* optional number or -1 */
};

struct sioctl_desc {
        unsigned int addr;              /* control address */
#define SIOCTL_NONE             0       /* deleted */
#define SIOCTL_NUM              2       /* integer in the maxval range */
#define SIOCTL_SW               3       /* on/off switch (1 or 0) */
#define SIOCTL_VEC              4       /* number, element of vector */
#define SIOCTL_LIST             5       /* switch, element of a list */
#define SIOCTL_SEL              6       /* element of a selector */
        unsigned int type;              /* one of above */
        char func[SIOCTL_NAMEMAX];      /* function name, ex. "level" */
        char group[SIOCTL_NAMEMAX];     /* group this control belongs to */
        struct sioctl_node node0;       /* affected node */
        struct sioctl_node node1;       /* dito for SIOCTL_{VEC,LIST,SEL} */
        unsigned int maxval;            /* max value */
        char display[SIOCTL_DISPLAYMAX];        /* free-format hint */
};

the addr attribute is the control address, usable with sioctl_setval() to set its value. that's ur key to the kingdom, bestie. πŸ”‘

the type attribute tells you what the structure is describing. possible types are:

  • SIOCTL_NONE β€” a previously valid control was deleted. rip. 😭
  • SIOCTL_NUM β€” an integer control in the range from 0 to maxval, inclusive. for instance the volume of the speaker.
  • SIOCTL_SW β€” a boolean control. for instance the switch to mute the speaker.
  • SIOCTL_VEC β€” element of an array of integer controls. for instance the knob that controls how much signal flows from the line input to the speaker.
  • SIOCTL_LIST β€” an element of an array of boolean switches. for instance the line-in position of the speaker source selector.
  • SIOCTL_SEL β€” same as SIOCTL_LIST but exactly one element is selected at a time. no sharing, one winner only. πŸ‘‘

the func attribute is the name of the parameter being controlled. there may be no parameters of different types with the same name.

the node0 and node1 attributes are the names of the controlled nodes, typically channels of audio streams. node1 is meaningful for SIOCTL_VEC, SIOCTL_LIST, and SIOCTL_SEL only.

names in the node0 and node1 attributes and in func are strings usable as unique identifiers within the given group.

the maxval attribute is the maximum value of this control. for boolean control types it's set to 1.

the display attribute holds an optional free-format string with extra hints about the control, like the hardware model, or the units. it's the little gossip column of the struct. πŸ™ˆ

πŸ’œ Changing and reading control values πŸ’œ

controls get changed with the sioctl_setval() function, by giving the index of the control and the new value. the sioctl_onval() function registers a callback that gets invoked whenever a control changes. integer values live in the range from 0 to maxval.

🌈 Interface to poll(2) 🌈

the sioctl_pollfd() function fills the array pfd of pollfd structures β€” the ones used by poll(2) β€” with events; events is a bit-mask of the POLLIN and POLLOUT constants. sioctl_pollfd() returns the number of pollfd structures filled.

the sioctl_revents() function returns the bit-mask set by poll(2) in the pfd array of pollfd structures. if POLLOUT is set, sioctl_setval() can be called without blocking. POLLHUP may be set if an error occurs, even if it is not selected with sioctl_pollfd(). POLLIN is not used yet. (it's not slacking, it's just not deployed yet πŸ’€)

the sioctl_nfds() function returns the number of pollfd structures the caller must preallocate in order to be sure that sioctl_pollfd() will never overrun. preallocate, bestie, do not get caught slipping.


🌱 ENVIRONMENT 🌱

  • AUDIODEVICE β€” the default sndio(7) device used by sioctl_open().

πŸ‘€ SEE ALSO πŸ‘€

sndioctl(1), poll(2), sio_open(3), sndio(7)


πŸ“œ HISTORY πŸ“œ

these functions first appeared in OpenBSD 6.7. vintage, honestly.


🫢 AUTHORS 🫢

Alexandre Ratchov <ratchov@openbsd.org> β€” thank u king, we love u πŸ’–


and that's the whole page, bestie!! πŸŽ‰ this one came out of the Debian build, dated $Mdocdate$, and it lives under the SIOCTL_OPEN(3) name in the manual. slay, go forth and control ur audio parameters responsibly. πŸ’…βœ¨πŸŽ€πŸ¦‹πŸŒΈ