0bf6915b6e4931a76b33b883c7a57c37d1137d61
[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 HeapFree(GetProcessHeap(), 0, DetailData);
203 return MM_STATUS_UNSUCCESSFUL;
204 }
205
206 Status = Open(DetailData->DevicePath, OutHandle);
207
208 if (Status != MM_STATUS_SUCCESS)
209 {
210 RegCloseKey((HKEY)*OutKey);
211 HeapFree(GetProcessHeap(), 0, DetailData);
212 return Status;
213 }
214
215 *DeviceName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData->DevicePath)+1) * sizeof(WCHAR));
216 if (*DeviceName == NULL)
217 {
218 CloseHandle(*OutHandle);
219 RegCloseKey((HKEY)*OutKey);
220 HeapFree(GetProcessHeap(), 0, DetailData);
221 return MM_STATUS_NO_MEMORY;
222 }
223
224 wcscpy(*DeviceName, DetailData->DevicePath);
225 HeapFree(GetProcessHeap(), 0, DetailData);
226
227 return Status;
228 }
229
230 MIXER_STATUS
231 QueryKeyValue(
232 IN HANDLE hKey,
233 IN LPWSTR KeyName,
234 OUT PVOID * ResultBuffer,
235 OUT PULONG ResultLength,
236 OUT PULONG KeyType)
237 {
238 if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, NULL, ResultLength) == ERROR_FILE_NOT_FOUND)
239 return MM_STATUS_UNSUCCESSFUL;
240
241 *ResultBuffer = HeapAlloc(GetProcessHeap(), 0, *ResultLength);
242 if (*ResultBuffer == NULL)
243 return MM_STATUS_NO_MEMORY;
244
245 if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, *ResultBuffer, ResultLength) != ERROR_SUCCESS)
246 {
247 HeapFree(GetProcessHeap(), 0, *ResultBuffer);
248 return MM_STATUS_UNSUCCESSFUL;
249 }
250 return MM_STATUS_SUCCESS;
251 }
252
253 MIXER_STATUS
254 OpenKey(
255 IN HANDLE hKey,
256 IN LPWSTR SubKey,
257 IN ULONG DesiredAccess,
258 OUT PHANDLE OutKey)
259 {
260 if (RegOpenKeyExW((HKEY)hKey, SubKey, 0, DesiredAccess, (PHKEY)OutKey) == ERROR_SUCCESS)
261 return MM_STATUS_SUCCESS;
262
263 return MM_STATUS_UNSUCCESSFUL;
264 }
265
266 MIXER_STATUS
267 CloseKey(
268 IN HANDLE hKey)
269 {
270 RegCloseKey((HKEY)hKey);
271 return MM_STATUS_SUCCESS;
272 }
273
274
275 int main(int argc, char**argv)
276 {
277 MIXER_STATUS Status;
278 HDEVINFO DeviceHandle;
279 MIXERCAPSW MixCaps1, MixCaps2;
280 ULONG Index, SubIndex;
281 HANDLE hMixer2;
282 HMIXER hMixer1;
283 MIXERLINEW MixerLine1, MixerLine2;
284 MIXERLINECONTROLS Controls1, Controls2;
285
286 ZeroMemory(&MixerContext, sizeof(MIXER_CONTEXT));
287
288 DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
289 NULL,
290 NULL,
291 DIGCF_DEVICEINTERFACE|DIGCF_PRESENT);
292 if (DeviceHandle == INVALID_HANDLE_VALUE)
293 {
294 printf("SetupDiGetClassDevs failed with %lx\n", GetLastError());
295 return 0;
296 }
297
298 printf("DeviceHandle %p\n", DeviceHandle);
299
300 MixerContext.SizeOfStruct = sizeof(MIXER_CONTEXT);
301 MixerContext.Alloc = Alloc;
302 MixerContext.Close = Close;
303 MixerContext.Control = Control;
304 MixerContext.Copy = Copy;
305 MixerContext.Free = Free;
306 MixerContext.Open = Open;
307 MixerContext.OpenKey = OpenKey;
308 MixerContext.CloseKey = CloseKey;
309 MixerContext.QueryKeyValue = QueryKeyValue;
310
311 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceHandle);
312
313 printf("Status %x\n", Status);
314 printf("NumberOfMixers %lu mixerGetNumDevs %u\n", MMixerGetCount(&MixerContext), mixerGetNumDevs());
315
316 for(Index = 0; Index < MMixerGetCount(&MixerContext); Index++)
317 {
318 mixerGetDevCapsW(Index, &MixCaps1, sizeof(MIXERCAPSW));
319 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);
320 MMixerGetCapabilities(&MixerContext, Index, &MixCaps2);
321 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);
322
323 mixerOpen(&hMixer1, Index, 0, 0, MIXER_OBJECTF_HMIXER);
324 MMixerOpen(&MixerContext, Index, NULL, NULL, &hMixer2);
325
326 ZeroMemory(&MixerLine1, sizeof(MIXERLINEW));
327 ZeroMemory(&MixerLine2, sizeof(MIXERLINEW));
328 MixerLine1.cbStruct = sizeof(MIXERLINEW);
329 MixerLine2.cbStruct = sizeof(MIXERLINEW);
330 mixerGetLineInfoW((HMIXEROBJ)hMixer1, &MixerLine1, MIXER_GETLINEINFOF_DESTINATION);
331 MMixerGetLineInfo(&MixerContext, hMixer2, MIXER_GETLINEINFOF_DESTINATION, &MixerLine2);
332
333 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",
334 MixerLine1.dwDestination, MixerLine1.dwSource, MixerLine1.dwLineID, MixerLine1.dwUser, MixerLine1.dwComponentType, MixerLine1.cChannels, MixerLine1.cConnections, MixerLine1.cControls, MixerLine1.szShortName, MixerLine1.szName);
335
336 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",
337 MixerLine2.dwDestination, MixerLine2.dwSource, MixerLine2.dwLineID, MixerLine2.dwUser, MixerLine2.dwComponentType, MixerLine2.cChannels, MixerLine2.cConnections, MixerLine2.cControls, MixerLine2.szShortName, MixerLine2.szName);
338
339 Controls1.cbStruct = sizeof(MIXERLINECONTROLS);
340 Controls2.cbStruct = sizeof(MIXERLINECONTROLS);
341
342 Controls1.cbmxctrl = sizeof(MIXERCONTROL);
343 Controls2.cbmxctrl = sizeof(MIXERCONTROL);
344
345 Controls1.cControls = MixerLine1.cControls;
346 Controls2.cControls = MixerLine2.cControls;
347
348 Controls1.dwLineID = MixerLine1.dwLineID;
349 Controls2.dwLineID = MixerLine2.dwLineID;
350
351
352
353 Controls1.pamxctrl = (LPMIXERCONTROL)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIXERCONTROL) * Controls1.cControls);
354 Controls2.pamxctrl = (LPMIXERCONTROL)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIXERCONTROL) * Controls2.cControls);
355
356 for(SubIndex = 0; SubIndex < Controls1.cControls; SubIndex++)
357 Controls1.pamxctrl[SubIndex].cbStruct = sizeof(MIXERCONTROL);
358
359 for(SubIndex = 0; SubIndex < Controls2.cControls; SubIndex++)
360 Controls2.pamxctrl[SubIndex].cbStruct = sizeof(MIXERCONTROL);
361
362 mixerGetLineControls((HMIXEROBJ)hMixer1, &Controls1, MIXER_GETLINECONTROLSF_ALL);
363
364 wprintf(L"----------------------------------------\n");
365 for(SubIndex = 0; SubIndex < Controls1.cControls; SubIndex++)
366 {
367 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);
368 }
369 wprintf(L"----------------------------------------\n");
370
371
372 wprintf(L"=======================\n");
373 }
374 return 0;
375 }