MMRESULT MmeGetLineInfo( IN UINT DeviceId, IN UINT Message, IN DWORD_PTR PrivateHandle, IN DWORD_PTR Parameter1, IN DWORD_PTR Parameter2) { MMRESULT Result; PSOUND_DEVICE_INSTANCE SoundDeviceInstance; PSOUND_DEVICE SoundDevice; PMMFUNCTION_TABLE FunctionTable; //SND_TRACE(L"Getting mixer info %u\n", Message); if ( PrivateHandle == 0 ) { Result = GetSoundDevice(MIXER_DEVICE_TYPE, DeviceId, &SoundDevice); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); Result = FunctionTable->QueryMixerInfo(NULL, DeviceId, Message, (LPVOID)Parameter1, Parameter2); return Result; } VALIDATE_MMSYS_PARAMETER( PrivateHandle ); SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle; Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); if ( ! FunctionTable->QueryMixerInfo ) return MMSYSERR_NOTSUPPORTED; Result = FunctionTable->QueryMixerInfo(SoundDeviceInstance, DeviceId, Message, (LPVOID)Parameter1, Parameter2); return Result; }
MMRESULT QueryWaveDeviceFormatSupport( IN PSOUND_DEVICE SoundDevice, IN LPWAVEFORMATEX Format, IN DWORD FormatSize) { MMRESULT Result; MMDEVICE_TYPE DeviceType; PMMFUNCTION_TABLE FunctionTable; SND_TRACE(L"Querying wave format support\n"); VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) ); VALIDATE_MMSYS_PARAMETER( Format ); VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) ); Result = GetSoundDeviceType(SoundDevice, &DeviceType); SND_ASSERT( Result == MMSYSERR_NOERROR ); /* Ensure we have a wave device (TODO: check if this applies to wavein as well) */ VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) ); /* Obtain the function table */ Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); SND_ASSERT( Result == MMSYSERR_NOERROR ); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); if ( ! FunctionTable->QueryWaveFormatSupport ) return MMSYSERR_NOTSUPPORTED; return FunctionTable->QueryWaveFormatSupport(SoundDevice, Format, FormatSize); }
MMRESULT SetWaveDeviceFormat( IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN DWORD DeviceId, IN LPWAVEFORMATEX Format, IN DWORD FormatSize) { MMRESULT Result; MMDEVICE_TYPE DeviceType; PMMFUNCTION_TABLE FunctionTable; PSOUND_DEVICE SoundDevice; SND_TRACE(L"Setting wave format\n"); VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) ); Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); Result = GetSoundDeviceType(SoundDevice, &DeviceType); SND_ASSERT( Result == MMSYSERR_NOERROR ); if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) { VALIDATE_MMSYS_PARAMETER( Format ); VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) ); } /* Ensure we have a wave device (TODO: check if this applies to wavein as well) */ VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) || IS_MIDI_DEVICE_TYPE(DeviceType) || IS_MIXER_DEVICE_TYPE(DeviceType)); /* Obtain the function table */ Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); SND_ASSERT( Result == MMSYSERR_NOERROR ); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); if ( ! FunctionTable->SetWaveFormat ) return MMSYSERR_NOTSUPPORTED; return FunctionTable->SetWaveFormat(SoundDeviceInstance, DeviceId, Format, FormatSize); }
MMRESULT DestroySoundDeviceInstance( IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) { MMRESULT Result; PMMFUNCTION_TABLE FunctionTable; PSOUND_DEVICE SoundDevice; PVOID Handle; SND_TRACE(L"Destroying a sound device instance\n"); VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) ); Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); /* Get the "close" routine from the function table, and validate it */ Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); SND_ASSERT( FunctionTable->Close ); if ( FunctionTable->Close == NULL ) { /* This indicates bad practice, really! If you can open, why not close?! */ return MMSYSERR_NOTSUPPORTED; } /* Stop the streaming thread */ if ( SoundDeviceInstance->Thread ) { Result = DestroySoundThread(SoundDeviceInstance->Thread); SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */ if ( ! MMSUCCESS(Result ) ) { return TranslateInternalMmResult(Result); } } /* Blank this out here */ SoundDeviceInstance->Thread = NULL; /* Try and close the device */ Result = FunctionTable->Close(SoundDeviceInstance, Handle); SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */ if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); /* Drop it from the list */ Result = UnlistSoundDeviceInstance(SoundDeviceInstance); SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */ if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); FreeSoundDeviceInstance(SoundDeviceInstance); return MMSYSERR_NOERROR; }
MMRESULT CreateSoundDeviceInstance( IN PSOUND_DEVICE SoundDevice, OUT PSOUND_DEVICE_INSTANCE* SoundDeviceInstance) { MMRESULT Result; PMMFUNCTION_TABLE FunctionTable; SND_TRACE(L"Creating a sound device instance\n"); VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) ); VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance != NULL ); Result = AllocateSoundDeviceInstance(SoundDeviceInstance); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); /* Get the "open" routine from the function table, and validate it */ Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); if ( ! MMSUCCESS(Result) ) { FreeSoundDeviceInstance(*SoundDeviceInstance); return TranslateInternalMmResult(Result); } if ( FunctionTable->Open == NULL ) { FreeSoundDeviceInstance(*SoundDeviceInstance); return MMSYSERR_NOTSUPPORTED; } /* Set up the members of the structure */ (*SoundDeviceInstance)->Next = NULL; (*SoundDeviceInstance)->Device = SoundDevice; (*SoundDeviceInstance)->Handle = NULL; (*SoundDeviceInstance)->Thread = NULL; (*SoundDeviceInstance)->WinMM.Handle = INVALID_HANDLE_VALUE; (*SoundDeviceInstance)->WinMM.ClientCallback = 0; (*SoundDeviceInstance)->WinMM.ClientCallbackInstanceData = 0; (*SoundDeviceInstance)->WinMM.Flags = 0; /* Initialise the members of the struct used by the sound thread */ (*SoundDeviceInstance)->HeadWaveHeader = NULL; (*SoundDeviceInstance)->TailWaveHeader = NULL; (*SoundDeviceInstance)->OutstandingBuffers = 0; (*SoundDeviceInstance)->LoopsRemaining = 0; /* Create the streaming thread (TODO - is this for wave only?) */ Result = CreateSoundThread(&(*SoundDeviceInstance)->Thread); if ( ! MMSUCCESS(Result) ) { FreeSoundDeviceInstance(*SoundDeviceInstance); return TranslateInternalMmResult(Result); } /* Add the instance to the list */ Result = ListSoundDeviceInstance(SoundDevice, *SoundDeviceInstance); if ( ! MMSUCCESS(Result) ) { FreeSoundDeviceInstance(*SoundDeviceInstance); return TranslateInternalMmResult(Result); } /* Try and open the device */ Result = FunctionTable->Open(SoundDevice, (&(*SoundDeviceInstance)->Handle)); if ( ! MMSUCCESS(Result) ) { UnlistSoundDeviceInstance(*SoundDeviceInstance); FreeSoundDeviceInstance(*SoundDeviceInstance); return TranslateInternalMmResult(Result); } return MMSYSERR_NOERROR; }