OSS Mixer extension API sample program ====================================== This program (mixext.c) is a simple program that demonstrates how to read and write certain parameters using the mixer extension API of OSS. This API will be released officially in OSS v4.0 and until that we reserve all rights to do changes to it without notice. However such changes should not require more than recompile of the application. It should be pointed out that the mixer extension API is fully dynamic in nature. It's possible that structure of the mixer changes on fly if some "master setting" gets changed by some other application or user. For this reason the information obtained using the SNDCTL_MIX_EXTINFO ioctl is not "cacheable". In particular the controls are identified by name. The ID numbers assigned to them are only valid immediately after they have been read with SNDCTL_MIX_EXTINFO. After that they may change without notice (the time stamp feature used by the API prevents applications from setting wrong controls if this happens). Another important point is that there is no naming standard for the controls. This means that any application using this API will only work with low level devices it's written for. Different devices may have similar settings but they are under different names. Also the names used by the ossmix and ossxmix applications included in OSS are created from the names returned by SNDCTL_MIX_EXTINFO using some algorithm. Writing mixer applications that can handle the above problems is beyond the scope of this file and the mixext.c program. Full document for doing programs like ossxmix will be released later (no known dates yet). So the purpose of this program is to demonstrate how to: - Find out the control names that are used by the current device. - Set a value of a mixer control with given mame. The program intentionally skips all controls before special MIXT_MARKER entry. Such controls are aliases created automatically for the "ordinary" mixer controls. You should use the original SOUND_MIXER_* API to access such controls instead of using this program (major modifications will be required). Compiling the program --------------------- cc mixext.c -o mixext Listing the controls -------------------- Execute the mixext program as ./mixext This shows a list of control names, their types and their values. The usefull mixer control types will be listed at the end of this document. The argument is an integer between 0 and N. See the printout produced by cat /dev/sndstat for the list of available mixers. Changing a control ------------------ Execute the program as: ./mixext The is one of the mixer control names shown by the mixext program in the "list mode". Node that with some devices there may be several entries with exactly the same name. This program can access only the first of them. To make this program to work with such devices you need to do some hacking (see the Theory section below). The is a decimal value (some controls require hex value). Theory behind mixer extensions ------------------------------ Take a look at the printout produced by the ossmix program in list mode. Also take a look at the mixext.c program since otherwise the following description is not understandable. As you may notice the entries listed form a tree like structure. The entry number 0 is always the device root (type=MIXT_DEVROOT). For all control entries the parent field shows the parent node. In addition to MIXT_DEVROOT also MIXT_GROUP can work as a parent node (other controls can't be parents of any other control). The parent node has always smaller entry number than any of the daughter controls that belong to them. Some of the extensions are just aliases for the "normal" mixer controls that are accessible by the ordinary OSS mixer API (SOUND_MIXER_*). These aliases are listed first and the "real" extensions come after the MIXT_MARKER entry. There are many tricky parts in handling those aliases so it's highly recommended to ignore everything before MIXT_MARKER. Most of the mixer controls have a name but not all of them (in particular the ones before MIXT_MARKER). The ossmix program shipped with OSS uses a special algorithm to convert the names provided by the SNDCTL_MIX_EXTINFO ioctl to the "external" names. This algorithm use "." as the separator between the parts of the name (the names may contain most other special characters including (but not limiting to) /@,:). Names may not contain spaces. For example if a control is "ENVY24_RATELOCK" and it's parent is "ENVY24" the name used by ossmix will become envy24.ratelock. There are many rules ane exceptions so the required algorithm will later be published as a library routine. The application should skip all records whose type is not known. The following kind of mixer extension types are available: MIXT_DEVROOT MIXT_GROUP These are group entries that don't have any readable/writeable value. They are just used to group other entries together. MIXT_DEVROOT is just a special group that always has entry number 0. MIXT_MARKER is another special entry. It's used as a separator between the "alias" controls and the controls that are only accessible with the mixer extension API. To make your life easier you should always ignore MIXT_MARKER and everything before it (except the root entry of course). MIXT_ONOFF MIXT_MUTE MIXT_ENUM These controls are quite similar. MIXT_ONOFF and MIXT_MUTE have only two possible values that are 0 (OFF) and 1 (ON). MIXT_ENUM has more alternatives (the available values are 0 to maxvalue (returned by the SNDCTL_MIX_EXTINFO ioctl call. However there is still one more thing. Some of the enum values are not always available. For this the application should check the enum_present field to see which values are actually permitted (Note! the following is just pseudocode): #define enum_check(ix) (enum_present[ix/8] & (1<<(ix%8)))) if (enum_check(0)) printf("FRONT is permitted\n"); if (enum_check(1)) printf("REAR is permitted\n"); Note! In some earlier OSS versions the field was called enum_mask and it had different usage. MIXT_MONOSLIDER MIXT_STEREOSLIDER These are sliders used to control volumes and other similar things. The value field has separate fields for left and right channels: left = value & 0xff; right = (value >> 8) & 0xff; The maximum value for both fields is given in the maxvalue field. Both channel fields are used also by MIXT_MONOSLIDER but only the left channel value is valid (the right channel field is assumed to be set to the same value). MIXT_MONOSLIDER16 MIXT_STEREOSLIDER16 These are replacementsof MIXT_MONOSLIDER and MIXT_STEREOSLIDER. The only difference is that their value range has been expanded to 0-32767. left = value & 0xffff; right = (value >> 16) & 0xffff; MIXT_SLIDER is yet another slider but at this time the whole int field is allocated for a single value (there are no separate left and right fields). The maxvalue field shows the maximum permitted value. MIXT_MONOPEAK MIXT_STEREOPEAK These are peak meters (usually read only). These meters hold the maximum signal values since the control was previously read. Reading the value resets it to 0. This kind of controls can be used to implement LED bar displays and similar things. MIXT_MONOPEAK is 1 channel controls while MIXT_STEREOPEAK is stereo one (the channel values are returned using the same value format than with MIXT_STEREOSLIDER). MIXT_MONODB MIXT_STEREODB These are obsolete control types and will not be used by any OSS drivers. MIXT_VALUE MIXT_HEXVALUE These types are used for controls that are integer values. The difference is the radix that should be sued when presenting the value to the user. The following control types are reserved for future use (if any). They should not be used by any applications since they may be removed from future OSS versions: MIXT_RADIOGROUP MIXT_3D MIXT_MESSAGE MIXT_MONOVU MIXT_STEREOVU Reading and writing the controls -------------------------------- The SNDCTL_MIX_READ and SNDCTL_MIX_WRITE controls can be used to read or write the controls (respectively). The following fields of the argument structure should be set prior the call: dev is the mixer device to use (0 to N). ctrl is the controller number. timestamp should be copied from the structure returned by the SNDCTL_MIX_EXTINFO call. The application should check the flags field returned by SNDCTL_MIX_EXTINFO before trying to read or change the value. The MIXF_WRITEABLE and MIXF_READABLE bits tell if the value is writeable or readable. OSS will compare the timestamp field against it's internal list of currently available controls. If the timestamp doesn't match the ioctl call will return -1 with errno=EIDRM. This happens if the mixer structure has changed between SNDCTL_MIX_EXTINFO and the SNDCTL_MIX_READ/SNDCTL_MIX_WRITE calls. The only way to recover is re-loading the SNDCTL_MIX_EXTINFO info and trying again. In case of problems please don't hesitate to contact hannu@opensound.com for info.