SND_ASSERT( SoundDevice );
SND_ASSERT( Capabilities );
- SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities\n");
-
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
SND_ASSERT( Result == MMSYSERR_NOERROR );
if ( ! MMSUCCESS(Result) )
return Result;
+ SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId);
ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
DeviceInfo.DeviceType = DeviceType;
return TranslateInternalMmResult(Result);
}
- SND_TRACE(L"WDMAUD Name %S\n", DeviceInfo.u.WaveOutCaps.szPname);
-
/* This is pretty much a big hack right now */
switch ( DeviceType )
{
{
LPMIXERCAPS MixerCaps = (LPMIXERCAPS) Capabilities;
- CopyWideString(MixerCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
+ DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0';
+ CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname);
MixerCaps->cDestinations = DeviceInfo.u.MixCaps.cDestinations;
MixerCaps->fdwSupport = DeviceInfo.u.MixCaps.fdwSupport;
case WAVE_OUT_DEVICE_TYPE :
{
LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) Capabilities;
+
+ DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0';
WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid;
WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid;
}
case WAVE_IN_DEVICE_TYPE :
{
- LPWAVEINCAPS WaveInCaps = (LPWAVEINCAPS) Capabilities;
- CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
- /* TODO... other fields */
+ LPWAVEINCAPSW WaveInCaps = (LPWAVEINCAPSW) Capabilities;
+
+ DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0';
+
+ WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid;
+ WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid;
+
+ WaveInCaps->vDriverVersion = 0x0001;
+ CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname);
+
+ WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats;
+ WaveInCaps->wChannels = DeviceInfo.u.WaveInCaps.wChannels;
+ WaveInCaps->wReserved1 = 0;
break;
}
}
NULL);
}
+ if (DeviceType == MIXER_DEVICE_TYPE)
+ {
+ SetEvent(SoundDeviceInstance->hStopEvent);
+ CloseHandle(SoundDeviceInstance->hStopEvent);
+ CloseHandle(SoundDeviceInstance->hNotifyEvent);
+ }
+
--OpenCount;
if ( OpenCount < 1 )
}
+DWORD
+WINAPI
+MixerEventThreadRoutine(
+ LPVOID Parameter)
+{
+ HANDLE WaitObjects[2];
+ DWORD dwResult;
+ MMRESULT Result;
+ WDMAUD_DEVICE_INFO DeviceInfo;
+ PSOUND_DEVICE_INSTANCE Instance = (PSOUND_DEVICE_INSTANCE)Parameter;
+
+ /* setup wait objects */
+ WaitObjects[0] = Instance->hNotifyEvent;
+ WaitObjects[1] = Instance->hStopEvent;
+
+ /* zero device info */
+ ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+
+ DeviceInfo.hDevice = Instance->Handle;
+ DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
+
+ do
+ {
+ dwResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE);
+
+ if (dwResult == WAIT_OBJECT_0 + 1)
+ {
+ /* stop event was signalled */
+ break;
+ }
+
+ do
+ {
+ Result = SyncOverlappedDeviceIoControl(KernelHandle,
+ IOCTL_GET_MIXER_EVENT,
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ NULL);
+
+ if (Result == MMSYSERR_NOERROR)
+ {
+ DriverCallback(Instance->WinMM.ClientCallback,
+ HIWORD(Instance->WinMM.Flags),
+ Instance->WinMM.Handle,
+ DeviceInfo.u.MixerEvent.NotificationType,
+ Instance->WinMM.ClientCallbackInstanceData,
+ (DWORD_PTR)DeviceInfo.u.MixerEvent.Value,
+ 0);
+ }
+ }while(Result == MMSYSERR_NOERROR);
+ }while(TRUE);
+
+ /* done */
+ return 0;
+}
+
+
MMRESULT
SetWdmMixerDeviceFormat(
IN PSOUND_DEVICE_INSTANCE Instance,
IN DWORD WaveFormatSize)
{
MMRESULT Result;
- PSOUND_DEVICE SoundDevice;
- PVOID Identifier;
WDMAUD_DEVICE_INFO DeviceInfo;
- MMDEVICE_TYPE DeviceType;
-
- Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
-
- if ( ! MMSUCCESS(Result) )
- {
- return TranslateInternalMmResult(Result);
- }
-
- Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier);
-
- if ( ! MMSUCCESS(Result) )
- {
- return TranslateInternalMmResult(Result);
- }
+ HANDLE hThread;
if (Instance->Handle != KernelHandle)
{
return MMSYSERR_NOERROR;
}
+ Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+ if ( ! Instance->hNotifyEvent )
+ return MMSYSERR_NOMEM;
- Result = GetSoundDeviceType(SoundDevice, &DeviceType);
- SND_ASSERT( Result == MMSYSERR_NOERROR );
+ Instance->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+ if ( ! Instance->hStopEvent )
+ return MMSYSERR_NOMEM;
ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
- DeviceInfo.DeviceType = DeviceType;
+ DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
DeviceInfo.DeviceIndex = DeviceId;
+ DeviceInfo.u.hNotifyEvent = Instance->hNotifyEvent;
Result = SyncOverlappedDeviceIoControl(KernelHandle,
IOCTL_OPEN_WDMAUD,
if ( ! MMSUCCESS(Result) )
{
+ CloseHandle(Instance->hNotifyEvent);
+ CloseHandle(Instance->hStopEvent);
return TranslateInternalMmResult(Result);
}
+ hThread = CreateThread(NULL, 0, MixerEventThreadRoutine, (LPVOID)Instance, 0, NULL);
+ if ( hThread )
+ {
+ CloseHandle(hThread);
+ }
+
/* Store sound device handle instance handle */
Instance->Handle = (PVOID)DeviceInfo.hDevice;
ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
DeviceInfo.DeviceType = DeviceType;
DeviceInfo.DeviceIndex = DeviceId;
- DeviceInfo.u.WaveFormatEx.cbSize = WaveFormat->cbSize;
+ DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); //WaveFormat->cbSize;
DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
#ifdef USERMODE_MIXER
DeviceInfo.u.WaveFormatEx.nChannels = 2;
{
if (DeviceInfo.u.FrameSize)
{
- //Instance->FrameSize = DeviceInfo.u.FrameSize;
+ Instance->FrameSize = DeviceInfo.u.FrameSize * 2;
Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize;
SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount);
}
}
+ else
+ {
+ // use a default of 100 buffers
+ Instance->BufferCount = 100;
+ }
- /* Now start the stream */
- DeviceInfo.u.State = KSSTATE_RUN;
- SyncOverlappedDeviceIoControl(KernelHandle,
- IOCTL_SETDEVICE_STATE,
- (LPVOID) &DeviceInfo,
- sizeof(WDMAUD_DEVICE_INFO),
- (LPVOID) &DeviceInfo,
- sizeof(WDMAUD_DEVICE_INFO),
- NULL);
+ if (DeviceType == WAVE_OUT_DEVICE_TYPE)
+ {
+ /* Now start the stream */
+ DeviceInfo.u.State = KSSTATE_RUN;
+ SyncOverlappedDeviceIoControl(KernelHandle,
+ IOCTL_SETDEVICE_STATE,
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ NULL);
+ }
return MMSYSERR_NOERROR;
}
IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
{
HANDLE Handle;
+ MMRESULT Result;
WDMAUD_DEVICE_INFO DeviceInfo;
-
+ PSOUND_DEVICE SoundDevice;
+ MMDEVICE_TYPE DeviceType;
+ BOOL Ret;
VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
VALIDATE_MMSYS_PARAMETER( OffsetPtr );
GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+
+ Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
+
+ if ( ! MMSUCCESS(Result) )
+ {
+ return TranslateInternalMmResult(Result);
+ }
+
+ Result = GetSoundDeviceType(SoundDevice, &DeviceType);
+ SND_ASSERT( Result == MMSYSERR_NOERROR );
+
SND_ASSERT(Handle);
ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+
DeviceInfo.Header.FrameExtent = Length;
- DeviceInfo.Header.DataUsed = Length;
+ if (DeviceType == WAVE_OUT_DEVICE_TYPE)
+ {
+ DeviceInfo.Header.DataUsed = Length;
+ }
DeviceInfo.Header.Data = OffsetPtr;
- DeviceInfo.Header.Size = sizeof(KSSTREAM_HEADER);
+ DeviceInfo.Header.Size = sizeof(WDMAUD_DEVICE_INFO);
DeviceInfo.Header.PresentationTime.Numerator = 1;
DeviceInfo.Header.PresentationTime.Denominator = 1;
DeviceInfo.hDevice = Handle;
- DeviceInfo.DeviceType = WAVE_OUT_DEVICE_TYPE; //FIXME
+ DeviceInfo.DeviceType = DeviceType;
Overlap->Standard.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
- if ( ! WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine))
+ if (DeviceType == WAVE_OUT_DEVICE_TYPE)
+ {
+ Ret = WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
+ if (Ret)
+ WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
+ }
+ else if (DeviceType == WAVE_IN_DEVICE_TYPE)
{
- SND_TRACE(L"WriteFileEx failed with %x\n", GetLastError());
+ Ret = ReadFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
+ //if (Ret)
+ // WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
}
+
+ return MMSYSERR_NOERROR;
+}
+
+MMRESULT
+SetWdmWaveState(
+ IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
+ IN BOOL bStart)
+{
+ MMRESULT Result;
+ PSOUND_DEVICE SoundDevice;
+ WDMAUD_DEVICE_INFO DeviceInfo;
+ MMDEVICE_TYPE DeviceType;
+ HANDLE Handle;
+
+ Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
+
+ if ( ! MMSUCCESS(Result) )
+ {
+ return TranslateInternalMmResult(Result);
+ }
+
+ Result = GetSoundDeviceType(SoundDevice, &DeviceType);
+ SND_ASSERT( Result == MMSYSERR_NOERROR );
+
+ Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+ SND_ASSERT( Result == MMSYSERR_NOERROR );
+
+ ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+ DeviceInfo.hDevice = Handle;
+ DeviceInfo.DeviceType = DeviceType;
+
+ if (bStart)
+ DeviceInfo.u.State = KSSTATE_RUN;
else
+ DeviceInfo.u.State = KSSTATE_PAUSE;
+ Result = SyncOverlappedDeviceIoControl(KernelHandle,
+ IOCTL_SETDEVICE_STATE,
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ NULL);
+
+ return Result;
+}
+
+MMRESULT
+GetDeviceInterfaceString(
+ IN MMDEVICE_TYPE DeviceType,
+ IN DWORD DeviceId,
+ IN LPWSTR Interface,
+ IN DWORD InterfaceLength,
+ OUT DWORD * InterfaceSize)
+{
+ WDMAUD_DEVICE_INFO DeviceInfo;
+ MMRESULT Result;
+
+ ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+ DeviceInfo.DeviceType = DeviceType;
+ DeviceInfo.DeviceIndex = DeviceId;
+
+
+ Result = SyncOverlappedDeviceIoControl(KernelHandle,
+ IOCTL_QUERYDEVICEINTERFACESTRING,
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ NULL);
+
+
+ if ( ! MMSUCCESS(Result) )
+ {
+ return TranslateInternalMmResult(Result);
+ }
+
+
+ if (!Interface)
{
- WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
+ SND_ASSERT(InterfaceSize);
+ *InterfaceSize = DeviceInfo.u.Interface.DeviceInterfaceStringSize;
+ return MMSYSERR_NOERROR;
}
- return MMSYSERR_NOERROR;
+ if (InterfaceLength < DeviceInfo.u.Interface.DeviceInterfaceStringSize)
+ {
+ /* buffer is too small */
+ return MMSYSERR_MOREDATA;
+ }
+
+ DeviceInfo.u.Interface.DeviceInterfaceStringSize = InterfaceLength;
+ DeviceInfo.u.Interface.DeviceInterfaceString = Interface;
+
+ Result = SyncOverlappedDeviceIoControl(KernelHandle,
+ IOCTL_QUERYDEVICEINTERFACESTRING,
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ NULL);
+
+ if ( MMSUCCESS(Result) && InterfaceLength > 2)
+ {
+ Interface[1] = L'\\';
+ Interface[InterfaceLength-1] = L'\0';
+ }
+
+ return Result;
}
MMRESULT
return MMSYSERR_NOERROR;
}
+MMRESULT
+ResetStream(
+ IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
+ IN MMDEVICE_TYPE DeviceType,
+ IN BOOLEAN bStartReset)
+{
+ MMRESULT Result;
+ HANDLE Handle;
+ WDMAUD_DEVICE_INFO DeviceInfo;
+
+ Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+ SND_ASSERT( Result == MMSYSERR_NOERROR );
+
+ ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+ DeviceInfo.hDevice = Handle;
+ DeviceInfo.DeviceType = DeviceType;
+ DeviceInfo.u.ResetStream = (bStartReset ? KSRESET_BEGIN : KSRESET_END);
+
+ Result = SyncOverlappedDeviceIoControl(KernelHandle,
+ IOCTL_RESET_STREAM,
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ NULL);
+ return Result;
+}
+
+
+MMRESULT
+QueryMixerInfo(
+ IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
+ IN UINT uMsg,
+ IN LPVOID Parameter,
+ IN DWORD Flags)
+{
+ MMRESULT Result;
+ WDMAUD_DEVICE_INFO DeviceInfo;
+ HANDLE Handle;
+ DWORD IoControlCode;
+ LPMIXERLINEW MixLine;
+ LPMIXERLINECONTROLSW MixControls;
+ LPMIXERCONTROLDETAILS MixDetails;
+
+ SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags);
+
+ Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
+ SND_ASSERT( Result == MMSYSERR_NOERROR );
+
+ ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
+ DeviceInfo.hDevice = Handle;
+ DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
+ DeviceInfo.Flags = Flags;
+
+ MixLine = (LPMIXERLINEW)Parameter;
+ MixControls = (LPMIXERLINECONTROLSW)Parameter;
+ MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
+
+ switch(uMsg)
+ {
+ case MXDM_GETLINEINFO:
+ RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW));
+ IoControlCode = IOCTL_GETLINEINFO;
+ break;
+ case MXDM_GETLINECONTROLS:
+ RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW));
+ IoControlCode = IOCTL_GETLINECONTROLS;
+ break;
+ case MXDM_SETCONTROLDETAILS:
+ RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
+ IoControlCode = IOCTL_SETCONTROLDETAILS;
+ break;
+ case MXDM_GETCONTROLDETAILS:
+ RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
+ IoControlCode = IOCTL_GETCONTROLDETAILS;
+ break;
+ default:
+ SND_ASSERT(0);
+ return MMSYSERR_NOTSUPPORTED;
+ }
+
+ Result = SyncOverlappedDeviceIoControl(KernelHandle,
+ IoControlCode,
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ (LPVOID) &DeviceInfo,
+ sizeof(WDMAUD_DEVICE_INFO),
+ NULL);
+
+ if ( ! MMSUCCESS(Result) )
+ {
+ return Result;
+ }
+
+ switch(uMsg)
+ {
+ case MXDM_GETLINEINFO:
+ {
+ RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW));
+ break;
+ }
+ }
+
+ return Result;
+}
+
MMRESULT
PopulateWdmDeviceList(
for ( i = 0; i < DeviceCount; ++ i )
{
- Result = ListSoundDevice(DeviceType, (PVOID) i, &SoundDevice);
+ Result = ListSoundDevice(DeviceType, UlongToPtr(i), &SoundDevice);
if ( ! MMSUCCESS(Result) )
{
if (DeviceType == MIXER_DEVICE_TYPE)
{
FuncTable.SetWaveFormat = SetWdmMixerDeviceFormat;
+ FuncTable.QueryMixerInfo = QueryMixerInfo;
}
else
{
FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat;
}
+ if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
+ {
+ FuncTable.SetState = SetWdmWaveState;
+ FuncTable.ResetStream = ResetStream;
+ }
+
FuncTable.Open = OpenWdmSoundDevice;
FuncTable.Close = CloseWdmSoundDevice;
+ FuncTable.GetDeviceInterfaceString = GetDeviceInterfaceString;
#ifndef USERMODE_MIXER
FuncTable.CommitWaveBuffer = WriteFileEx_Committer2;
#else