Open Sound System |
Do you have problems with sound/audio application development? Don't panic! Click here for help! |
oss_audioinfo ai;
ai.dev = The audio device number.
ioctl(fd, SNDCTL_AUDIOINFO, &ai);
ioctl(fd, SNDCTL_AUDIOINFO_EX, &ai);
ioctl(fd, SNDCTL_ENGINEINFO, &ai);
The above code fragment lacks all error checks for clarity. Real world applications must always check for the errors and handle them as described below. Also most OSS ioctl calls will return information in the argument variable and it's usually necessary to check it too.
These ioctl calls are supported by all OSS devices, including audio, mixer and MIDI devices. The device for which the information is returned is selected by the dev
field of the argument. If dev is set to -1 then information for the current audio device pointed by the file descriptor (fd
) will be returned. However the dev=-1 method works only with SNDCTL_ENGINEINFO because open file descriptors are bound directly to specific audio engines.
Applications must be very carefull when using these ioctl calls to see what is possible with the device and what is not. These calls will return information directly from the low level driver. Even the device itself doesn't support certain feature it's probaly supported by the upper levels of the audio core.
For example most sound cards support only mono and stereo (min_channels=1 and max_channels=2). It might seem to be a good idea to prevent the application from playing multichannel audio (say 5.1) with such devices. However this is not necessarily what the user wants. Future OSS versions will contain an 3D expander that makes it possible to play 5.1 channel audio streams with good results. If the application just tries to set the 6 channel mode using SNDCTL_DSP_CHANNELS it will work correctly both with the current and the future versions of OSS.
OSS 4.0 has new audio device model. Instead of the earlier flat audio device numbering there are now two levels of audio devices. The higher level object is audio device file. Each audio device file has a visible device node in the /dev directory (actually there are two of them). Each audio device file has one or more audio engines. Audio device files that have multiple engines can be shared by multiple applications because each application (instance) will be directed to a different audio engine. In some cases these audio engines are real hardware level devices (hardware mixing). However in most cases these engines are software level virtual devices (virtual mixing).
Under some operating systems (older versions of FreeBSD at this moment) there is no difference between audio engines and device files. Since the operating system doesn't support device redirection OSS will create a device file for each audio engine. So both SNDCTL_AUDIOINFO and SNDCTL_ENGINEINFO will return the same information.
Audio device files are objects that applications can access directly by opening a device file located in /dev. The SNDCTL_AUDIOINFO ioctl call can be used to get information about the audio device files. Number of audio devices available in the system is returned by SNDCTL_SYSINFO in the numaudios
field.
The device file entry returned by SNDCTL_AUDIOINFO contains information about the primary audio engine of this device. Each device file may have additional engines that are ordered in two chains. The next_play_engine
field contains the engine number (see below) of the next playback engine and the next_rec_engine
field in turn returns the next recording engine. If the engine numbers returned in these fields are the same then the additional engines are duplex engines and both chains will be identical (engine number 0 means that there are no addtional engines).
When an application opens an audio device files the engine that will actually be used depends on the device type. With devices that support hardware mixing the first application opening the device file will get the primary engine. Subsequent applications will get the next free engine from the play or record engine chain. However with devices using virtual mixing the primary engine will be used by the virtual mixer drivers and applications will be given the next free engine from the chain.
When an audio device file is opened normally it's likely that the application will get connected to one of the virtual mixer engines instead of the actual physical audio device itself. The virtual devices may have different capabilities than the actual physical device. For this reason SNDCTL_AUDIOINFO will return device capabilities that match the virtual engines.
Applications that use O_EXCL to open the physical device directly must use SNDCTL_AUDIOINFO_EX to check the device capabilities. This variation of SNDCTL_AUDIOINFO will report only the capabilities of the physical device itself. See the The open() system call section for more info.
Audio engines are the second level in the audio device hierarchy. The SNDCTL_ENGINEINFO ioctl call can be used to obtain information about the engines. The numaudioengines
field returned by SNDCTL_SYSINFO will return the total number of audio engines currently in the system.
Applications cannot select the audio engine directly. Instead OSS will select the engine when the application opens some audio device file. For this reason some fields will return information about the parent device file object.
The oss_audioinfo
structure contains the following fields.
Field | Description |
dev | The audio device number. Must be set prior the call (see above). Note that this field is just an arbitrary number between 0 and SNDCTL_SYSINFO.numaudios-1. It no longer matches the /dev/dsp# device number. For best results all applications written for OSS 4.0 and later should use the devnode field to find out which device to open. |
name | A string that contains the "full" description of the device. |
busy | Se to 0 if the device is not open by any applications. Other alternatives are OSS_OPEN_READ, OSS_OPEN_WRITE or OSS_OPEN_READWRITE. |
pid | The PID number of the process that is currently using this device. Value of -1 means that this information is not available or the device is currently not open. Just few operating systems support this field. See the cmd field. |
caps | Capabilities of the device. See the Audio device capabilities section for more info. |
iformats | Bitmask for the natively supported recording formats. |
oformats | Bitmask for the natively supported playback formats. |
magic | Reserved for internal use by OSS. |
cmd | The command (program) name of the process using this device or empty string if no command name is available. Only supported under Linux at this moment. |
card_number | Number of the sound card where this device belongs or -1 if this information is not available. Applications should normally not use this field for any purpose. |
song_name | Name of the current song this device is playing. Empty string means no song name is assigned. See the Application assigned metadata section for more info. |
label | Label attached to this device. Empty string means no label is assigned. See the Application assigned metadata section for more info. |
port_number | This field tells the port/device number within the device (card_number). |
mixer_dev | The mixer device number of the mixer that is related with this audio device or -1 if no mixer is available. |
legacy_device | *OBSOLETE* Use the devnode field instead. This field is the /dev/dsp# "legacy" device number. The device number for given device may change without notice. Applications that store the device numbers in their configuration files are likely to cause serious privacy problems when device numbers change. New applications written for OSS 4.0 or later should use the devnode field to find out which device file to open. Value of -1 means that this device doesn't have any legacy /dev/dsp# device (this alternative is used with certain special purpose devices). |
devnode | The device special file name associated with this audio device. Note that this field has been added to the oss_audioinfo structure recently and it will be empty with earlier OSS versions. In that case applications should use the legacy_device field as the /dev/dsp# number for this device. |
enabled | Usually 1. However it will be set to 0 if the device is (temporarily) unavailable. This may happen for example if an USB device is "hot" unplugged from the system. |
flags | Reserved for future use. |
min_rate | Minimum sampling rate supported by the device (see below). |
max_rate | Maximum sampling rate supported by the device (see below). |
nrates | Number of sampling rates supported by the device (see below). |
rates | Array containing the list of supported sampling rates (see below). |
min_channels | Minimum number of channels (see below). |
max_channels | Maximum number of channels (see below). |
binding | Reserved for future use. |
rate_source | Number of the sample rate group this device belongs to (see below). -1 means that the rate source is not known. |
handle | A short identifier (string) that uniquely identifies the physical hardware device/port. The device number (dev as well as the card_number fields may change if a new audio device is installed in the system. This field is designed to have the same value even after that (provided that the device is not moved to some other PCI slot or USB port. This is just an arbitrary character string that the applications should not try to interpret. The only permitted use is comparing against some previously stored handle in application's configuration files. |
next_play_engine | Next playback engine in the chain (0 means none). |
next_rec_engine | Next record engine in the chain (0 means none). |
OSS is designed to support any common sample formats by doing automatic conversions in the driver level. For this reason applications don't normally need to check which formats are supported in hardware level. Checking this is only necessary in rare special cases when no kind of conversions are allowed. Sample format conversions don't cause any quality loss so there is no need to be worried about.
Some devices support different formats during recording and playback. The iformats
and oformats
fields give the formats for both directions. If the device is opened with O_RDWR then the intersection of these two sets (iformats
and oformats
) gives the formats that are possible in this situation.
This also explains why some devices support more sample formats when opened with O_WRONLY than with O_RDWR.
Normal applications don't need to know what sampling rates are really supported. OSS will do automatic sample rate conversions in driver level if they are necessay. There are just few special cases where checking this is necessary.
There are two kind of devices. Some of them support all sampling rates withing the min_rate
to max_rate
range. It's possible to identify such devices by checking if the PCM_CAP_FREERATE capability is reported in the caps
field.
The remaining devices support one or few sampling rates. To find it out the application should look at the rates
/nrates
array. It's also necessary to check that the rates are within the min_rate
to max_rate
range (some of the rates given in the rates
array may be outside this range in some situations.
Elements of the rates
array are not necessarily sorted. Applications must not assume that they are in ascending or descending order.
Normal applications don't need to check how many channels the device really supports. OSS will do the necesary up and down sampling operations automatically in the driver level. All the application needs to do is trying to change the number of channels to the required value (using SNDCTL_DSP_CHANNELS) and the check how many channels were actually allocated. Please see the Using multiple channels with OSS section for more info.
The min_channels
and max_channels
fields define the limits for the number of channels. However some devices don't support all channels within this range. It's possible that the odd values (3, 5, 7, 9, etc). are not supported. There is currently no way to check for this other checking if SNDCTL_DSP_CHANNELS accepts the requested value. Another approach is trying to avoid using odd number of channels.
Most sound cards have several independednt audio recording and playback engines that are driven by a common crystal oscillator. Such engines are guaranteed to run excatly at the same rate (provided that they are programmed to the same sampling rate.
However in general audio engines that belong to different souncards will use slightly different sampling rates even the nominal rate is the same. This means that after few seconds or minutes the devices will be out of sync. In some applications such as digital audio workstations (DAW) this will cause serious problems in keeping the tracks in sync.
The rate_source
field returned by this ioctl call can be used to find out if the devices are likely to be able to work in sync. If rate sources of two devices have the same value then this is guaranteed. However even the rate sources are different then it's still possible that the devices are synchronized to the same external clock signal (such as word clock or digital S/PDIF signal). So applications should accept devices with different rate sources. However it may be a good idea to show a warning about this.
Value of -1 in the rate_source field means that the OSS implementation or the driver doesn't support rate source management.
Earlier the audio device numbering scheme used by OSS was completely flat. All devices are directly accessible and the dev
and the legacy_device
fields are set to the same value.
Starting from OSS 4.0 the dev
and legacy_device
fields are just arbitrary numbers that may change randomly when OSS configuration is changed. New applications should use the device special file name given in the devnode
field to find out which device file to open.
To find the engine(s) for a given /dev/dsp# device you need to search the whole list of devices and pick the ones with the right value in the legacy_device
field. The only difference between the engines is that some of them are in use while some others are free.
You can use the SNDCTL_SYSINFO ioctl to find out how many audio devices there are in the system.
The return value from the OSS ioctl calls will be -1 if a fatal error occurred. Other values mean that the ioctl call was more or less successful. However in most cases the application must check the value returned in the argument to see what was the accepted value.
Please see the Possible error codes (errno) returned by OSS calls section for more info about the error codes returned by OSS.
osstest.c | The osstest program shipped with OSS |
ossinfo.c | The ossinfo program that is included in the OSS package. |
ossxmix.c | This is the ossxmix (GTK++ GUI) program shipped with OSS |
ossmix.c | Sources for the ossmix command line mixer shipped with OSS |
ossplay.c | Sources for the ossplay audio player and for the ossrecord |
fulldup.c | Full duplex sample program using the single device approach. |
mmap_test.c | A sample program for using mmap() |