Client applications must open an audio device before using it, and close the device after using it so the device will be available to other applications. It is possible for a device driver to support more than one client simultaneously.
If the driver supports multiple clients, the appropriate _GETNUMDEVS message can return a value other than 1. In some cases, returning a value of 1 is the best option. For example, if the device driver supports multiple clients for simultaneous PCM waveform playback, you might want the WODM_GETNUMDEVS message to return 1 and allow multiple WODM_OPEN messages. However, if your driver supports completely different playback formats (or routing to different playback hardware), it might be better for WODM_GETNUMDEVS to return the number of formats. In this case, remember to always check the uDeviceID parameter to determine which device is being accessed. Also remember to set the appropriate DEVCAPS structure so that clients can tell the difference between the devices. For example, a MIDI output driver might support both an external MIDI port and an internal synthesizer. It makes sense for the MDOM_GETNUMDEVS message to return 2 - where the port is device 0, and the synthesizer is device 1.
Auxiliary audio devices are handled differently from waveform and MIDI devices. They don't have to be opened, because they don't have the same resource allocation requirements. Also, there is no interrupt level or continuous data transfer associated with auxiliary audio devices.
When a driver receives an open request with a WODM_OPEN, WIDM_OPEN, MODM_OPEN, or MIDM_OPEN message, the dwUser parameter of its entry-point function points to a location that the driver can fill with a DWORD of instance data. This instance data is returned to the driver in the same dwUser parameter when other messages are sent to the driver. Drivers should use this instance data for information related to the client that opened a device. The following code fragment illustrates how the modMessage MIDI output entry-point function might handle the MODM_OPEN message:
typedef struct portalloc_tag { DWORD dwCallback; /* client's callback */ DWORD dwInstance; /* client's instance data */ HMIDIOUT hMidi; /* handle for stream */ DWORD dwFlags; /* allocation flags */ } PORTALLOC; PORTALLOC gMidiOutClient; case MODM_OPEN: /* Attempt to 'acquire' the MIDI output hardware. If the * output port is already in use by another client or * another VM owns the Sound Blaster hardware, then * return MMSYSERR_ALLOCATED. */ if ( modAcquireHardware() ) return MMSYSERR_ALLOCATED /* Save client information */ gMidiOutClient.dwCallback = ((LPMIDIOPENDESC)dwParam1)->>dwCallback<R> gMidiOutClient.dwInstance = ((LPMIDIOPENDESC)dwParam1)->>dwInstance gMidiOutClient.hMidi = ((LPMIDIOPENDESC)dwParam1)->>hMidi; gMidiOutClient.dwFlags = dwParam2; /* Reset running status...*/ gbMidiOutCurrentStatus = 0; /* Notify client...*/ midiCallback(&gMidiOutClient, MOM_OPEN, 0L, 0L); /* Return success. */ return 0L;