Wine and Multimedia This file contains information about the implementation of the multimedia layer of Wine. The implementation can be found in the dlls/winmm/ directory (and in many of its subdirectories), but also in dlls/msacm/ (for the audio compression/decompression manager) and dlls/msvideo/ (for the video compression/decompression manager). Overview The multimedia stuff is split into 3 layers. The low level (device drivers), mid level (MCI commands) and high level abstraction layers. The low level layer has also some helper DLLs (like the MSACM/MSACM32 and MSVIDEO/MSVFW32 pairs). All of those components are defined as DLLs (one by one). The low level layer may depend on current hardware and OS services (like OSS on Unix). It provides the core of playback/record using fine grain objects (audio/midi streams...). Mid level (MCI) and high level layers must be written independently from the hardware and OS services. MCI level provides some coarser grain operations (like playing a Midi file, or playing a video stream). Multimedia architecture Windows 95 multimedia architecture | Kernel space | Client applications | | | | ^ ^ | | | | | 16>| |<32 16>| |<32 16>| |<32 16>| |<32 | | v | | | v | v | +----|-----------|---------|------------|-------+ | | | | | | | WinMM.dll | | | | | | | 32 bit | +----|-----------|---------|------------|-------+ | | | | ^ | | | | +------+ | |<16 | | | |<16 | | | 16>| | | | | | | | | | v v v | | v v v | | +---------------+---+-------------+-------------+ | | | waveInXXX | | mciXXX | *playSound* | | | | waveOutXXX | | | mmioXXX | | | | midiInXXX | | | timeXXX | | | | midiOutXXX | | | driverXXX | | | | midiStreamXXX | | | | MMSystem.dll | | | mixerXXX | | | | 16 bit +--------+ | | | auxXXX +---+ +---+ mmThread| | |MMDEVLDR|<------->| joyXXX | Call back | mmTask | | +--------+ | | +-----------+-----------+---------+-------------+ ^ | | | ^ ^ | ^ | | | 16>| |<16>| 16>| |<16 v | | v | | v | +--------+ | | +-------------+ +----------+ | VxD |<------->| *.drv | | mci*.drv | +--------+ | | +--------------+ +-----------+ | | | msacm.drv | | mciwave | | | +--------------+ +-----------+ | | | midimap.drv | | mcimidi | | | +-------------+ +-----------+ | | Low-level drivers | ... | MCI drivers | | +----------+ | | | | | |<16 | +-------------------------------+ | The important points to notice are: all drivers (and most of the core code) is 16 bit all hardware (or most of it) dependent code reside in the kernel space (which is not surprising) Windows NT multimedia architecture Note that Win 98 has mixed 95/NT architecture, so when speaking about Windows 95 (resp. NT) architecture, it refers to the type of architecture, not what's actually implemented. For example, Windows 98 implements both types of architectures. The important points to notice (compared to the Windows 95 architecture) are: drivers (low level, MCIs...) are 32 bit and Unicode the interfaces between kernel and user drivers has changed, but it doesn't impact much Wine. Those changes allow some good things (like kernel mixing, where different apps share the audio hardware) and of course bad things (like kernel mixing, which adds latency). Wine multimedia architecture | Kernel space | Client applications | | | | ^ ^ | | | | | 16>| |<32 16>| |<32 16>| |<32 16>| |<32 | | | | | | | | | | +------+ | | | | | | | | | |32/16>| | | | | | | | | | | v v v | | v v v v | | +---------------+---+-------------+-------------+ | | | waveInXXX | | mciXXX | *playSound* | | | | waveOutXXX | | | mmioXXX | WinMM.dll | | | midiInXXX | | | timeXXX | 32 bit | | | midiOutXXX | | | driverXXX | | | | midiStreamXXX | | | | MMSystem.dll | | | mixerXXX | | | | 16 bit | | | auxXXX +---+ +---+ mmThread| | | | | joyXXX | Call back | mmTask | | | | +-----------+-----------+---------+-------------+ | | || ^ ^ | ^ | | 16>||<32 |<16>| 16>| |<16 | | vv |<32>| 32>v |<32 +---------+ | | +-------------+ +----------+ |HW driver|<------->| *.drv | | mci*.drv | +---------+ | | +--------------+ +-----------+ | | | msacm.drv | | mciwave | | | +--------------+ +-----------+ | | | midimap.drv | | mcimidi | | | +-------------+ +-----------+ | | Low-level drivers | ... | MCI drivers | | +----------+ | | | | | |<32/16 | +-------------------------------+ | From the previous drawings, the most noticeable differences are: low-level drivers can either be 16 or 32 bit (in fact, Wine supports only native wave and audio mappers). MCI drivers can either be 16 or 32 bit all built-in drivers (low-level and MCI) will be written as 32 bit drivers Wine's WinMM automatically adapts the messages to be sent to a driver so that it can convert it to 16 or 32 bit interfaces. Low level layers The low level drivers abstract the hardware specific features from the rest of the multimedia code. Those are implemented with a well defined set of APIs, as windows do. Please note that native low level drivers are not currently supported in Wine, because they either access hardware components or require VxDs to be loaded; Wine does not correctly supports those two so far. There are two specific low level drivers (msacm.drv for wave input/output, midimap.drv for MIDI output only). These drivers (also present in Windows) allow: choosing one low level driver between many (we'll discuss how the choice is made later on) add the possibility to convert stream's format (ie ADPCM => PCM) (this is useful if the format required by the application for playback isn't supported by the soundcard). add the possibility to filter a stream (adding echo, equalizer... to a wave stream, or modify the instruments that have to be played for a MIDI stream). Hardware-bound low level drivers Each low lever driver has to implement at least one of the following functionality, through the named function: Waveform audio: out for playback, and in for recording. MMSYSTEM and WINMM call the real low level audio driver using the driver's wodMessage and widMessage functions which handle the different requests. MIDI (Musical Instrument Digital Interface): out for playback, and in for recording. MMSYSTEM and WINMM call the low level driver functions using the driver's midMessage and the modMessage functions. Mixer: this allows setting the volume for each one of the other functionnality (and also some specific attributes, like left/right balance for stereo streams...). MMSYSTEM and WINMM call the low level driver functions using the mxdMessage function. Aux: this is the predecessor of the mixer functionnality (introduced in Win 95). Its usage has been deprecated in favor of mixer interfaces. Wine currently supports the following (kernel) multimedia interfaces. Open Sound System (OSS) as supplied in the Linux and FreeBSD kernels by 4Front Technologies. The presence of this driver is checked by configure (depends on the <sys/soundcard.h> file). Source code resides in dlls/winmm/wineoss. Advanced Linux Sound Architecture (ALSA) as supplied in the Linux kernel. Source code resides in dlls/winmm/winealsa. Analog RealTime Synthetizer (aRts): a network server (and virtual mixer) used in the KDE project. Network Audio Server (NAS): an audio server. Jack: a low latency audio server. AudioIO: the native Solaris audio interface. The supported functionnalities per driver is as follows (this table lists the available features of the products, not exactly what's actually implemented on Wine): Wine multimedia drivers' functionalities Driver Wave Out Wave In Midi Out Midi In Mixer (and Aux) OSS Yes Yes Yes Yes Yes ALSA Yes Yes Yes Yes Yes aRts Yes Yes No No Yes NAS Yes Yes No No Yes AudioIO Yes Yes No No Yes Jack Yes Yes No No Yes
Lots of listed drivers won't support Midi (in a short time) because the exposed "Un*x" native interfaces don't. This would require using some kind as software synthesis (as Timidity), but we cannot incorporate as it's GPL'ed.
Wave mapper (msacm.drv) The Wave mapper device allows to load on-demand audio codecs in order to perform software conversion for the types the actual low level driver (hardware). Those codecs are provided through the standard ACM drivers in MSACM32.DLL. Wave mapper driver implementation can be found in dlls/winmm/wavemap/ directory. This driver heavily relies on MSACM and MSACM32 DLLs which can be found in dlls/msacm and dlls/msacm32. Those DLLs load ACM drivers which provide the conversion to PCM format (which is normally supported by low level drivers). A Law, uLaw, ADPCM, MP3... fit into the category of non PCM formats. MIDI mapper (midimap.drv) Midi mapper allows to map each one of 16 MIDI channels to a specific instrument on an installed sound card. This allows for example to support different MIDI instrument definitions (XM, GM...). It also permits to output on a per channel basis to different MIDI renderers. A built-in MIDI mapper can be found in dlls/winmm/midimap/. It partly provides the same functionality as the Windows' one. It allows to pick up destination channels: you can map a given channel to a specific playback device channel (see the configuration bits for more details).
Mid level drivers (MCI) The mid level drivers are represented by some common API functions, mostly mciSendCommand and mciSendString. Wine implements several MCI mid level drivers. Wine MCI drivers MCI Name DLL Name Role Location Comments CdAudio MciCDA.drv MCI interface to a CD audio player dlls/winmm/mcicda/ Relies on NTDLL CdRom raw interface (through DeviceIoControl). WaveAudio MciWave.drv MCI interface for wave playback and record dlls/winmm/mciwave/ It uses the low level audio API. Sequencer MciSeq.drv Midi Sequencer (playback) dlls/winmm/mciseq/ It uses the low level midi APIs AviVideo MciAvi.drv AVI playback and record dlls/winmm/mciavi/ It rather heavily relies on MSVIDEO/MSVFW32 DLLs pair to work.
The MCI Name column is the name of the MCI driver, as it is searched in configuration. The DLL Name column is the name of the DLL the configuration provides as a value. The name listed here is the default one (see the configuration section for the details).
Adding a new MCI driver is just a matter of writing the corresponding DLL with the correct interface (see existing MCI drivers for the details), and to provide the relevant setup information for wine.inf
High level layers WINMM (and MMSYSTEM) The high level layers encompass basically the MMSYSTEM and WINMM DLLs exported APIs. It also provides the skeleton for the core functionality for multimedia playback and recording. Note that native MMSYSTEM and WINMM do not currently work under Wine and there is no plan to support them (it would require to also fully support VxD, which is not done yet). WINMM and MMSYSTEM in Wine can handle both 16 bit and 32 bit drivers (for low level and MCI drivers). It will handle all the conversions transparently for the all the calls to WINMM and MMSYSTEM, as it knows what the driver interface is (16 bit or 32 bit) and it manages the information sent accordingly. MCI drivers are seen as regular Wine modules, and can be loaded (with a correct load order between builtin, native), as any other DLL. Please note, that MCI drivers module names must bear the .drv extension to be correctly understood. Multimedia timers are implemented with a dedicated thread, run in the context of the calling process, which should correctly mimic Windows behavior. The only drawback is that the thread will appear the calling process if it enumerates the running processes. DSOUND Wine also provide a DSound (DirectX) DLL with the proper COM implementation. Note that a Wine specific flag has been added to the wodOpen function, so that the DSound DLL can get a reference to a COM sound object from a given WINMM wave output device. This should be changed in the future. MS ACM Dlls Contents The MSACM32 (and its 16 bit sibbling MSACM) provide a way to map a given wave format to another format. It also provides filtering capabilities. Those DLLs only implement the proper switch between a caller and a driver providing the implementation of the requested format change or filter operation. There's nothing specific in Wine's implementation compared to Windows' one. Here's however a list of the builtin format change drivers (there's no filter driver yet): Wine ACM drivers Name Provides imaadp32 IMA ADPCM (adaptative PCM) msadp32 Microsoft's ADPCM (adaptative PCM) msg711 Microsoft's G.711 (A-Law and µ-Law) winemp3 Wine's MP3 (MPEG Layer 3), based on mpglib library
Note that Wine also supports native audio codecs as well. All builtin ACM drivers are 32 bit Unicode DLLs
Caching The MSACM/MSACM32 keeps some data cached for all known ACM drivers. Under the key Software\Microsoft\AudioCompressionManager\DriverCache\<driver name> , are kept for values: aFormatTagCache which contains an array of DWORD. There are two DWORDs per cFormatTags entry. The first DWORD contains a format tag value, and the second the associated maximum size for a WAVEFORMATEX structure. (Fields dwFormatTag and cbFormatSize from ACMFORMATDETAILS) cFilterTags contains the number of tags supported by the driver for filtering. cFormatTags contains the number of tags support by the driver for conversions. fdwSupport (the same as the one returned from acmDriverDetails). The cFilterTags, cFormatTags, fdwSupport are the same values as the ones returned from acmDriverDetails function.
MS Video Dlls Contents The MSVFW32 (and its 16 bit sibbling MSVIDEO) provide encode/decode video streams. Those DLLs only implement the proper switch between a caller and a driver providing the implementation of the requested format coding/decoding operation. There's nothing specific in Wine's implementation compared to Windows' one. Here's however a list of the builtin decoding drivers: Wine VIDC drivers Name Provides msrle32 Microsoft's RLE (Run-Length encoded) msvidc32 Microsoft's Video-1 iccvid Radius Cinepak Video Decoder
Note that Wine also supports native video codecs as well. All builtin VIDC drivers are 32 bit Unicode DLLs
Multimedia configuration Unfortunately, multimedia configuration evolved over time: In the early days on Windows 3.x, configuration was stored in system.in file, under various sections ([drivers] for low level drivers, [mci] (resp. [mci32]) for 16 bit (resp. 32 bit) MCI drivers...). With the apparition of the registry, in Windows 95, configuration as been duplicated there, under the key HKLM\System\CurrentControlSet\Control\MediaResources Windows NT also adopted the registry, but decided to store the configuration information under another key than Windows 9x did. HKLM\Software\Microsoft\Windows NT\CurrentVersion And with a different layout of keys and values beneath this key. Currently, Wine tries to load first a driver (low-level or MCI) from the NT registry settings. If it fails, it will try the system.ini configuration. An out-of-the-box configuration is provided in wine.inf, and shall be stored in registry and system.ini at Wine installation time. It will setup correctly the MCI drivers' configuration (as well as the wave and MIDI mappers). As the low-level drivers depend on hardware, their setup will be handled by winecfg. Wine multimedia configuration scheme Driver Read from NT registry Read from system.ini Setup by wine.inf Setup by winecfg MCI drivers Yes (1) Yes (2) Yes No Wave and MIDI mappers Yes No Yes No Hardware-bound low level drivers Yes No No Yes ACM and VIDC drivers (audio & video codecs) No Yes Yes No
This will allow most settings to be correctly loaded and handled. However, it won't if an app tries to search directly the registry for the actual configuration, as the three potential configuration places may not be in sync. It still lacks a correct installation scheme (as any multimedia device under Windows), so that all the correct keys are created in the registry. This requires an advanced model since, for example, the number of wave out devices can only be known on the destination system (depends on the sound card driven by the OSS interface). The following sections describe which type of information (depending on the location) Wine's multimedia DLLs understand. NT configuration Under the HKLM\Software\Microsoft\Windows NT\CurrentVersion key, are stored the names of the DLLs to be loaded for each MCI driver name: "cdaudio"="mcicda.drv" "sequencer"="mciseq.drv" "waveaudio"="mciwave.drv" "avivideo"="mciavi.drv" "videodisc"="mcipionr.drv" "vcr"="mcivisca.drv" "MPEGVideo"="mciqtz.drv" <filename>system.ini</filename> Wine will read the MCI drivers from the [mci] or [mci32] section. Wine won't make any difference between the two. Here's a sample configuration: [mci] cdaudio=mcicda.drv sequencer=mciseq.drv waveaudio=mciwave.drv avivideo=mciavi.drv videodisc=mcipionr.drv vcr=mcivisca.drv MPEGVideo=mciqtz.drv ACM drivers' configuration is read (only so far) from the system.ini (and setup at Wine installation from the wine.inf file). [drivers32] MSACM.imaadpcm=imaadp32.acm MSACM.msadpcm=msadp32.acm MSACM.msg711=msg711.acm MSACM.winemp3=winemp3.acm Video (aka vidc) drivers' configuration is read (only so far) from the system.ini (and setup at Wine installation from the wine.inf file). [drivers32] VIDC.MRLE=msrle32.dll VIDC.MSVC=msvidc32.dll VIDC.CVID=iccvid.dll See also the configuration part of the User's Guide for other information on low level drivers. Per driver/DLL configuration Midi mapper The Midi mapper configuration is the same as on Windows 9x. Under the key: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Multimedia\MIDIMap if the UseScheme value is not set, or is set to a null value, the MIDI mapper will always use the driver identified by the CurrentInstrument value. Note: Wine (for simplicity while installing) allows to define CurrentInstrument as #n (where n is a number), whereas Windows only allows the real device name here. If UseScheme is set to a non null value, CurrentScheme defines the name of the scheme to map the different channels. All the schemes are available with keys like HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\Midi\Schemes\%name_of_scheme% For every scheme, under this key, will be a sub-key (which name is usually a two digit index, starting at 00). Its default value is the name of the output driver, and the value Channels lists all channels (of the 16 standard MIDI ones) which have to be copied to this driver. To provide enhanced configuration and mapping capabilities, each driver can define under the key HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\Midi\Ports\%driver_name% a link to and .IDF file which allows to remap channels internally (for example 9 -> 16), to change instruments identification, event controllers values. See the source file dlls/winmm/midimap/midimap.c for the details (this isn't implemented yet).