[MMIXER_TEST]
[reactos.git] / rostests / tests / mmixer_test / test.c
1 #include <windows.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <setupapi.h>
5 #include <ksmedia.h>
6 #include <mmsystem.h>
7 #include <mmreg.h>
8 #include "mmixer.h"
9
10 MIXER_CONTEXT MixerContext;
11 GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO};
12
13 PVOID Alloc(ULONG NumBytes)
14 {
15 //printf("Alloc: %lu\n", NumBytes);
16 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NumBytes);
17 }
18
19 MIXER_STATUS
20 Close(HANDLE hDevice)
21 {
22 //printf("Close: Handle %p\n", hDevice);
23 if (CloseHandle(hDevice))
24 return MM_STATUS_SUCCESS;
25 else
26 return MM_STATUS_UNSUCCESSFUL;
27 }
28
29 VOID
30 Free(PVOID Block)
31 {
32 //printf("Free: %p\n", Block);
33 HeapFree(GetProcessHeap(), 0, Block);
34 }
35
36 VOID
37 Copy(PVOID Src, PVOID Dst, ULONG NumBytes)
38 {
39 //printf("Copy: Src %p Dst %p NumBytes %lu\n", Src, Dst, NumBytes);
40 CopyMemory(Src, Dst, NumBytes);
41 }
42
43 MIXER_STATUS
44 Open(
45 IN LPWSTR DevicePath,
46 OUT PHANDLE hDevice)
47 {
48 DevicePath[1] = L'\\';
49 *hDevice = CreateFileW(DevicePath,
50 GENERIC_READ | GENERIC_WRITE,
51 0,
52 NULL,
53 OPEN_EXISTING,
54 FILE_FLAG_OVERLAPPED,
55 NULL);
56 if (*hDevice == INVALID_HANDLE_VALUE)
57 {
58 //wprintf(L" Failed to open %s Error %lu\n", DevicePath, GetLastError());
59 return MM_STATUS_UNSUCCESSFUL;
60 }
61 wprintf(L"Open: %s hDevice %p\n", DevicePath, *hDevice);
62
63 return MM_STATUS_SUCCESS;
64 }
65
66 MIXER_STATUS
67 Control(
68 IN HANDLE hMixer,
69 IN ULONG dwIoControlCode,
70 IN PVOID lpInBuffer,
71 IN ULONG nInBufferSize,
72 OUT PVOID lpOutBuffer,
73 ULONG nOutBufferSize,
74 PULONG lpBytesReturned)
75 {
76 OVERLAPPED Overlapped;
77 BOOLEAN IoResult;
78 DWORD Transferred = 0;
79
80 //printf("hMixer %p dwIoControlCode %lx lpInBuffer %p nInBufferSize %lu lpOutBuffer %p nOutBufferSize %lu lpBytesReturned %p\n",
81 // hMixer, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned);
82
83 /* Overlapped I/O is done here - this is used for waiting for completion */
84 ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
85 Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
86
87 if ( ! Overlapped.hEvent )
88 return MM_STATUS_NO_MEMORY;
89
90 /* Talk to the device */
91 IoResult = DeviceIoControl(hMixer,
92 dwIoControlCode,
93 lpInBuffer,
94 nInBufferSize,
95 lpOutBuffer,
96 nOutBufferSize,
97 &Transferred,
98 &Overlapped);
99
100 /* If failure occurs, make sure it's not just due to the overlapped I/O */
101 if ( ! IoResult )
102 {
103 if ( GetLastError() != ERROR_IO_PENDING )
104 {
105 CloseHandle(Overlapped.hEvent);
106
107 //printf("Control: Failed with %lu Transferred %lu\n", GetLastError(), Transferred);
108
109 if (GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
110 {
111 if ( lpBytesReturned )
112 *lpBytesReturned = Transferred;
113 return MM_STATUS_MORE_ENTRIES;
114 }
115
116 return MM_STATUS_UNSUCCESSFUL;
117 }
118 }
119
120 /* Wait for the I/O to complete */
121 IoResult = GetOverlappedResult(hMixer,
122 &Overlapped,
123 &Transferred,
124 TRUE);
125
126 /* Don't need this any more */
127 CloseHandle(Overlapped.hEvent);
128
129 if ( ! IoResult )
130 return MM_STATUS_UNSUCCESSFUL;
131
132 //printf("Transferred %lu bytes in Sync overlapped I/O\n", Transferred);
133
134 if ( lpBytesReturned )
135 *lpBytesReturned = Transferred;
136
137 return MM_STATUS_SUCCESS;
138 }
139
140 MIXER_STATUS
141 Enum(
142 IN PVOID EnumContext,
143 IN ULONG DeviceIndex,
144 OUT LPWSTR * DeviceName,
145 OUT PHANDLE OutHandle,
146 OUT PHANDLE OutKey)
147 {
148 SP_DEVICE_INTERFACE_DATA InterfaceData;
149 SP_DEVINFO_DATA DeviceData;
150 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData;
151 BOOL Result;
152 DWORD Length;
153 MIXER_STATUS Status;
154
155 //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);
156
157 InterfaceData.cbSize = sizeof(InterfaceData);
158 InterfaceData.Reserved = 0;
159
160 Result = SetupDiEnumDeviceInterfaces(EnumContext,
161 NULL,
162 &CategoryGuid,
163 DeviceIndex,
164 &InterfaceData);
165
166 if (!Result)
167 {
168 if (GetLastError() == ERROR_NO_MORE_ITEMS)
169 {
170 printf("LastDevice\n");
171 return MM_STATUS_NO_MORE_DEVICES;
172 }
173 printf("SetupDiEnumDeviceInterfaces failed with %lu\n", GetLastError());
174 return MM_STATUS_UNSUCCESSFUL;
175 }
176
177 Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR);
178 DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(),
179 0,
180 Length);
181 DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
182 DeviceData.cbSize = sizeof(DeviceData);
183 DeviceData.Reserved = 0;
184
185 Result = SetupDiGetDeviceInterfaceDetailW(EnumContext,
186 &InterfaceData,
187 DetailData,
188 Length,
189 NULL,
190 &DeviceData);
191
192 if (!Result)
193 {
194 printf("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError());
195 return MM_STATUS_UNSUCCESSFUL;
196 }
197
198
199 *OutKey = SetupDiOpenDeviceInterfaceRegKey(EnumContext, &InterfaceData, 0, KEY_READ);
200 if ((HKEY)*OutKey == INVALID_HANDLE_VALUE)
201 {
202 printf("SetupDiOpenDeviceInterfaceRegKey failed with %lx\n", GetLastError());
203 HeapFree(GetProcessHeap(), 0, DetailData);
204 return MM_STATUS_UNSUCCESSFUL;
205 }
206
207 Status = Open(DetailData->DevicePath, OutHandle);
208
209 if (Status != MM_STATUS_SUCCESS)
210 {
211 RegCloseKey((HKEY)*OutKey);
212 HeapFree(GetProcessHeap(), 0, DetailData);
213 return Status;
214 }
215
216 *DeviceName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData->DevicePath)+1) * sizeof(WCHAR));
217 if (*DeviceName == NULL)
218 {
219 CloseHandle(*OutHandle);
220 RegCloseKey((HKEY)*OutKey);
221 HeapFree(GetProcessHeap(), 0, DetailData);
222 return MM_STATUS_NO_MEMORY;
223 }
224
225 wcscpy(*DeviceName, DetailData->DevicePath);
226 HeapFree(GetProcessHeap(), 0, DetailData);
227
228 return Status;
229 }
230
231 MIXER_STATUS
232 QueryKeyValue(
233 IN HANDLE hKey,
234 IN LPWSTR KeyName,
235 OUT PVOID * ResultBuffer,
236 OUT PULONG ResultLength,
237 OUT PULONG KeyType)
238 {
239 if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, NULL, ResultLength) == ERROR_FILE_NOT_FOUND)
240 return MM_STATUS_UNSUCCESSFUL;
241
242 *ResultBuffer = HeapAlloc(GetProcessHeap(), 0, *ResultLength);
243 if (*ResultBuffer == NULL)
244 return MM_STATUS_NO_MEMORY;
245
246 if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, *ResultBuffer, ResultLength) != ERROR_SUCCESS)
247 {
248 HeapFree(GetProcessHeap(), 0, *ResultBuffer);
249 return MM_STATUS_UNSUCCESSFUL;
250 }
251 return MM_STATUS_SUCCESS;
252 }
253
254 MIXER_STATUS
255 OpenKey(
256 IN HANDLE hKey,
257 IN LPWSTR SubKey,
258 IN ULONG DesiredAccess,
259 OUT PHANDLE OutKey)
260 {
261 if (RegOpenKeyExW((HKEY)hKey, SubKey, 0, DesiredAccess, (PHKEY)OutKey) == ERROR_SUCCESS)
262 return MM_STATUS_SUCCESS;
263
264 return MM_STATUS_UNSUCCESSFUL;
265 }
266
267 MIXER_STATUS
268 CloseKey(
269 IN HANDLE hKey)
270 {
271 RegCloseKey((HKEY)hKey);
272 return MM_STATUS_SUCCESS;
273 }
274
275
276 int main(int argc, char**argv)
277 {
278 MIXER_STATUS Status;
279 HDEVINFO DeviceHandle;
280 MIXERCAPSW MixCaps1, MixCaps2;
281 ULONG Index, SubIndex;
282 HANDLE hMixer2;
283 HMIXER hMixer1;
284 MIXERLINEW MixerLine1, MixerLine2;
285 MIXERLINECONTROLSW Controls1, Controls2;
286
287 ZeroMemory(&MixerContext, sizeof(MIXER_CONTEXT));
288
289 DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
290 NULL,
291 NULL,
292 DIGCF_DEVICEINTERFACE/*|DIGCF_PRESENT */);
293 if (DeviceHandle == INVALID_HANDLE_VALUE)
294 {
295 printf("SetupDiGetClassDevs failed with %lx\n", GetLastError());
296 return 0;
297 }
298
299 printf("DeviceHandle %p\n", DeviceHandle);
300
301 MixerContext.SizeOfStruct = sizeof(MIXER_CONTEXT);
302 MixerContext.Alloc = Alloc;
303 MixerContext.Close = Close;
304 MixerContext.Control = Control;
305 MixerContext.Copy = Copy;
306 MixerContext.Free = Free;
307 MixerContext.Open = Open;
308 MixerContext.OpenKey = OpenKey;
309 MixerContext.CloseKey = CloseKey;
310 MixerContext.QueryKeyValue = QueryKeyValue;
311
312 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceHandle);
313
314 printf("Status %x\n", Status);
315 printf("NumberOfMixers %lu mixerGetNumDevs %u\n", MMixerGetCount(&MixerContext), mixerGetNumDevs());
316
317 for(Index = 0; Index < MMixerGetCount(&MixerContext); Index++)
318 {
319 mixerGetDevCapsW(Index, &MixCaps1, sizeof(MIXERCAPSW));
320 wprintf(L"WINM: cDestination %u fdwSupport %lx szPname %s vDriverVersion %u wMid %x wPid %x\n", MixCaps1.cDestinations, MixCaps1.fdwSupport, MixCaps1.szPname, MixCaps1.vDriverVersion, MixCaps1.wMid, MixCaps1.wPid);
321 MMixerGetCapabilities(&MixerContext, Index, &MixCaps2);
322 wprintf(L"MMIX: cDestination %u fdwSupport %lx szPname %s vDriverVersion %u wMid %x wPid %x\n", MixCaps2.cDestinations, MixCaps2.fdwSupport, MixCaps2.szPname, MixCaps2.vDriverVersion, MixCaps2.wMid, MixCaps2.wPid);
323
324 mixerOpen(&hMixer1, Index, 0, 0, MIXER_OBJECTF_HMIXER);
325 MMixerOpen(&MixerContext, Index, NULL, NULL, &hMixer2);
326
327 ZeroMemory(&MixerLine1, sizeof(MIXERLINEW));
328 ZeroMemory(&MixerLine2, sizeof(MIXERLINEW));
329 MixerLine1.cbStruct = sizeof(MIXERLINEW);
330 MixerLine2.cbStruct = sizeof(MIXERLINEW);
331 mixerGetLineInfoW((HMIXEROBJ)hMixer1, &MixerLine1, MIXER_GETLINEINFOF_DESTINATION);
332 MMixerGetLineInfo(&MixerContext, hMixer2, MIXER_GETLINEINFOF_DESTINATION, &MixerLine2);
333
334 wprintf(L"WINM: dwDestination %lx dwSource %lx dwLineID %lx dwUser %lx dwComponentType %lx cChannels %lx cConnections %lx cControls %lx szShortName %s szName %s\n\n",
335 MixerLine1.dwDestination, MixerLine1.dwSource, MixerLine1.dwLineID, MixerLine1.dwUser, MixerLine1.dwComponentType, MixerLine1.cChannels, MixerLine1.cConnections, MixerLine1.cControls, MixerLine1.szShortName, MixerLine1.szName);
336
337 wprintf(L"MMIX: dwDestination %lx dwSource %lx dwLineID %lx dwUser %lx dwComponentType %lx cChannels %lx cConnections %lx cControls %lx szShortName %s szName %s\n\n",
338 MixerLine2.dwDestination, MixerLine2.dwSource, MixerLine2.dwLineID, MixerLine2.dwUser, MixerLine2.dwComponentType, MixerLine2.cChannels, MixerLine2.cConnections, MixerLine2.cControls, MixerLine2.szShortName, MixerLine2.szName);
339
340 Controls1.cbStruct = sizeof(MIXERLINECONTROLSW);
341 Controls2.cbStruct = sizeof(MIXERLINECONTROLSW);
342
343 Controls1.cbmxctrl = sizeof(MIXERCONTROL);
344 Controls2.cbmxctrl = sizeof(MIXERCONTROL);
345
346 Controls1.cControls = MixerLine1.cControls;
347 Controls2.cControls = MixerLine2.cControls;
348
349 Controls1.dwLineID = MixerLine1.dwLineID;
350 Controls2.dwLineID = MixerLine2.dwLineID;
351
352
353
354 Controls1.pamxctrl = (LPMIXERCONTROLW)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIXERCONTROLW) * Controls1.cControls);
355 Controls2.pamxctrl = (LPMIXERCONTROLW)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIXERCONTROLW) * Controls2.cControls);
356
357 for(SubIndex = 0; SubIndex < Controls1.cControls; SubIndex++)
358 Controls1.pamxctrl[SubIndex].cbStruct = sizeof(MIXERCONTROLW);
359
360 for(SubIndex = 0; SubIndex < Controls2.cControls; SubIndex++)
361 Controls2.pamxctrl[SubIndex].cbStruct = sizeof(MIXERCONTROLW);
362
363 mixerGetLineControlsW((HMIXEROBJ)hMixer1, &Controls1, MIXER_GETLINECONTROLSF_ALL);
364 MMixerGetLineControls(&MixerContext, hMixer2, MIXER_GETLINECONTROLSF_ALL, &Controls2);
365
366 wprintf(L"----------------------------------------\n");
367 for(SubIndex = 0; SubIndex < Controls1.cControls || SubIndex < Controls2.cControls; SubIndex++)
368 {
369 if (SubIndex < Controls1.cControls)
370 {
371 wprintf(L"WINM: Index %d dwControlID %lx dwControlType %lx fdwControl %lx cMultipleItems %lx szName %s szShortName %s \n", SubIndex, Controls1.pamxctrl[SubIndex].dwControlID, Controls1.pamxctrl[SubIndex].dwControlType, Controls1.pamxctrl[SubIndex].fdwControl, Controls1.pamxctrl[SubIndex].cMultipleItems, Controls1.pamxctrl[SubIndex].szName, Controls1.pamxctrl[SubIndex].szShortName);
372 }
373
374 if (SubIndex < Controls2.cControls)
375 {
376 wprintf(L"MMIX: Index %d dwControlID %lx dwControlType %lx fdwControl %lx cMultipleItems %lx szName %s szShortName %s \n", SubIndex, Controls2.pamxctrl[SubIndex].dwControlID, Controls2.pamxctrl[SubIndex].dwControlType, Controls2.pamxctrl[SubIndex].fdwControl, Controls2.pamxctrl[SubIndex].cMultipleItems, Controls2.pamxctrl[SubIndex].szName, Controls2.pamxctrl[SubIndex].szShortName);
377 }
378
379 }
380 wprintf(L"----------------------------------------\n");
381
382
383 wprintf(L"=======================\n");
384 }
385 return 0;
386 }