2 * PROJECT: ReactOS Sound System
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/wdmaud.drv/mmixer.c
6 * PURPOSE: WDM Audio Mixer API (User-mode part)
7 * PROGRAMMERS: Johannes Anderwald
13 PVOID
Alloc(ULONG NumBytes
);
14 MIXER_STATUS
Close(HANDLE hDevice
);
15 VOID
Free(PVOID Block
);
16 VOID
Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
);
17 MIXER_STATUS
Open(IN LPWSTR DevicePath
, OUT PHANDLE hDevice
);
18 MIXER_STATUS
Control(IN HANDLE hMixer
, IN ULONG dwIoControlCode
, IN PVOID lpInBuffer
, IN ULONG nInBufferSize
, OUT PVOID lpOutBuffer
, ULONG nOutBufferSize
, PULONG lpBytesReturned
);
19 MIXER_STATUS
Enum(IN PVOID EnumContext
, IN ULONG DeviceIndex
, OUT LPWSTR
* DeviceName
, OUT PHANDLE OutHandle
);
21 MIXER_CONTEXT MixerContext
=
23 sizeof(MIXER_CONTEXT
),
33 GUID CategoryGuid
= {STATIC_KSCATEGORY_AUDIO
};
35 PVOID
Alloc(ULONG NumBytes
)
37 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, NumBytes
);
43 if (CloseHandle(hDevice
))
44 return MM_STATUS_SUCCESS
;
46 return MM_STATUS_UNSUCCESSFUL
;
52 HeapFree(GetProcessHeap(), 0, Block
);
56 Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
)
58 CopyMemory(Src
, Dst
, NumBytes
);
66 DevicePath
[1] = L
'\\';
67 *hDevice
= CreateFileW(DevicePath
,
68 GENERIC_READ
| GENERIC_WRITE
,
74 if (*hDevice
== INVALID_HANDLE_VALUE
)
76 return MM_STATUS_UNSUCCESSFUL
;
79 return MM_STATUS_SUCCESS
;
85 IN ULONG dwIoControlCode
,
87 IN ULONG nInBufferSize
,
88 OUT PVOID lpOutBuffer
,
90 PULONG lpBytesReturned
)
92 OVERLAPPED Overlapped
;
94 DWORD Transferred
= 0;
96 /* Overlapped I/O is done here - this is used for waiting for completion */
97 ZeroMemory(&Overlapped
, sizeof(OVERLAPPED
));
98 Overlapped
.hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
100 if ( ! Overlapped
.hEvent
)
101 return MM_STATUS_NO_MEMORY
;
103 /* Talk to the device */
104 IoResult
= DeviceIoControl(hMixer
,
113 /* If failure occurs, make sure it's not just due to the overlapped I/O */
116 if ( GetLastError() != ERROR_IO_PENDING
)
118 CloseHandle(Overlapped
.hEvent
);
120 if (GetLastError() == ERROR_MORE_DATA
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
122 if ( lpBytesReturned
)
123 *lpBytesReturned
= Transferred
;
124 return MM_STATUS_MORE_ENTRIES
;
127 return MM_STATUS_UNSUCCESSFUL
;
131 /* Wait for the I/O to complete */
132 IoResult
= GetOverlappedResult(hMixer
,
137 /* Don't need this any more */
138 CloseHandle(Overlapped
.hEvent
);
141 return MM_STATUS_UNSUCCESSFUL
;
143 if ( lpBytesReturned
)
144 *lpBytesReturned
= Transferred
;
146 return MM_STATUS_SUCCESS
;
151 IN PVOID EnumContext
,
152 IN ULONG DeviceIndex
,
153 OUT LPWSTR
* DeviceName
,
154 OUT PHANDLE OutHandle
)
156 SP_DEVICE_INTERFACE_DATA InterfaceData
;
157 SP_DEVINFO_DATA DeviceData
;
158 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData
;
162 //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);
164 InterfaceData
.cbSize
= sizeof(InterfaceData
);
165 InterfaceData
.Reserved
= 0;
167 Result
= SetupDiEnumDeviceInterfaces(EnumContext
,
175 if (GetLastError() == ERROR_NO_MORE_ITEMS
)
177 return MM_STATUS_NO_MORE_DEVICES
;
179 return MM_STATUS_UNSUCCESSFUL
;
182 Length
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) + MAX_PATH
* sizeof(WCHAR
);
183 DetailData
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(),
186 DetailData
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
187 DeviceData
.cbSize
= sizeof(DeviceData
);
188 DeviceData
.Reserved
= 0;
190 Result
= SetupDiGetDeviceInterfaceDetailW(EnumContext
,
199 return MM_STATUS_UNSUCCESSFUL
;
203 *DeviceName
= (LPWSTR
)&DetailData
->DevicePath
[0];
204 return Open(DetailData
->DevicePath
, OutHandle
);
208 WdmAudInitUserModeMixer()
210 HDEVINFO DeviceHandle
;
213 /* create a device list */
214 DeviceHandle
= SetupDiGetClassDevs(&CategoryGuid
,
217 DIGCF_DEVICEINTERFACE
|DIGCF_PRESENT
);
219 if (DeviceHandle
== INVALID_HANDLE_VALUE
)
221 /* failed to create a device list */
226 /* initialize the mixer library */
227 Status
= MMixerInitialize(&MixerContext
, Enum
, (PVOID
)DeviceHandle
);
229 /* free device list */
230 SetupDiDestroyDeviceInfoList(DeviceHandle
);
232 if (Status
!= MM_STATUS_SUCCESS
)
234 /* failed to initialize mixer library */
235 DPRINT1("Failed to initialize mixer library with %x\n", Status
);
239 /* completed successfully */
244 WdmAudGetMixerCount()
246 /* return number of mixers available */
247 return MMixerGetCount(&MixerContext
);
251 WdmAudGetMixerCapabilties(
253 LPMIXERCAPSW Capabilities
)
255 if (MMixerGetCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
256 return MMSYSERR_NOERROR
;
258 return MMSYSERR_BADDEVICEID
;
264 IN HANDLE hNotifyEvent
)
267 return MMSYSERR_NOERROR
;
274 IN HANDLE hNotifyEvent
)
276 if (MMixerOpen(&MixerContext
, DeviceId
, hNotifyEvent
, NULL
/* FIXME */, hMixer
) == MM_STATUS_SUCCESS
)
277 return MMSYSERR_NOERROR
;
279 return MMSYSERR_BADDEVICEID
;
285 IN LPMIXERLINE MixLine
,
288 if (MMixerGetLineInfo(&MixerContext
, hMixer
, Flags
, MixLine
) == MM_STATUS_SUCCESS
)
289 return MMSYSERR_NOERROR
;
291 return MMSYSERR_ERROR
;
295 WdmAudGetLineControls(
297 IN LPMIXERLINECONTROLSW MixControls
,
300 if (MMixerGetLineControls(&MixerContext
, hMixer
, Flags
, MixControls
) == MM_STATUS_SUCCESS
)
301 return MMSYSERR_NOERROR
;
303 return MMSYSERR_ERROR
;
307 WdmAudSetControlDetails(
309 IN LPMIXERCONTROLDETAILS MixDetails
,
312 if (MMixerSetControlDetails(&MixerContext
, hMixer
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
313 return MMSYSERR_NOERROR
;
315 return MMSYSERR_ERROR
;
320 WdmAudGetControlDetails(
322 IN LPMIXERCONTROLDETAILS MixDetails
,
325 if (MMixerGetControlDetails(&MixerContext
, hMixer
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
326 return MMSYSERR_NOERROR
;
328 return MMSYSERR_ERROR
;