[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 {
147 SP_DEVICE_INTERFACE_DATA InterfaceData;
148 SP_DEVINFO_DATA DeviceData;
149 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData;
150 BOOL Result;
151 DWORD Length;
152
153 //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);
154
155 InterfaceData.cbSize = sizeof(InterfaceData);
156 InterfaceData.Reserved = 0;
157
158 Result = SetupDiEnumDeviceInterfaces(EnumContext,
159 NULL,
160 &CategoryGuid,
161 DeviceIndex,
162 &InterfaceData);
163
164 if (!Result)
165 {
166 if (GetLastError() == ERROR_NO_MORE_ITEMS)
167 {
168 printf("LastDevice\n");
169 return MM_STATUS_NO_MORE_DEVICES;
170 }
171 printf("SetupDiEnumDeviceInterfaces failed with %lu\n", GetLastError());
172 return MM_STATUS_UNSUCCESSFUL;
173 }
174
175 Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR);
176 DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(),
177 0,
178 Length);
179 DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
180 DeviceData.cbSize = sizeof(DeviceData);
181 DeviceData.Reserved = 0;
182
183 Result = SetupDiGetDeviceInterfaceDetailW(EnumContext,
184 &InterfaceData,
185 DetailData,
186 Length,
187 NULL,
188 &DeviceData);
189
190 if (!Result)
191 {
192 printf("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError());
193 return MM_STATUS_UNSUCCESSFUL;
194 }
195
196 // copy path
197 *DeviceName = (LPWSTR)&DetailData->DevicePath[0];
198 return Open(DetailData->DevicePath, OutHandle);
199 }
200
201
202 int main(int argc, char**argv)
203 {
204 MIXER_STATUS Status;
205 HDEVINFO DeviceHandle;
206 MIXERCAPSW MixCaps1, MixCaps2;
207 ULONG Index, SubIndex;
208 HANDLE hMixer2;
209 HMIXER hMixer1;
210 MIXERLINEW MixerLine1, MixerLine2;
211 MIXERLINECONTROLS Controls1, Controls2;
212
213 ZeroMemory(&MixerContext, sizeof(MIXER_CONTEXT));
214
215 DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
216 NULL,
217 NULL,
218 DIGCF_DEVICEINTERFACE|DIGCF_PRESENT);
219 if (DeviceHandle == INVALID_HANDLE_VALUE)
220 {
221 printf("SetupDiGetClassDevs failed with %lx\n", GetLastError());
222 return 0;
223 }
224
225 printf("DeviceHandle %p\n", DeviceHandle);
226
227 MixerContext.SizeOfStruct = sizeof(MIXER_CONTEXT);
228 MixerContext.Alloc = Alloc;
229 MixerContext.Close = Close;
230 MixerContext.Control = Control;
231 MixerContext.Copy = Copy;
232 MixerContext.Free = Free;
233 MixerContext.Open = Open;
234
235 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceHandle);
236
237 printf("Status %x\n", Status);
238 printf("NumberOfMixers %lu mixerGetNumDevs %u\n", MMixerGetCount(&MixerContext), mixerGetNumDevs());
239
240 for(Index = 0; Index < MMixerGetCount(&MixerContext); Index++)
241 {
242 mixerGetDevCapsW(Index, &MixCaps1, sizeof(MIXERCAPSW));
243 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);
244 MMixerGetCapabilities(&MixerContext, Index, &MixCaps2);
245 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);
246
247 mixerOpen(&hMixer1, Index, 0, 0, MIXER_OBJECTF_HMIXER);
248 MMixerOpen(&MixerContext, Index, NULL, NULL, &hMixer2);
249
250 ZeroMemory(&MixerLine1, sizeof(MIXERLINEW));
251 ZeroMemory(&MixerLine2, sizeof(MIXERLINEW));
252 MixerLine1.cbStruct = sizeof(MIXERLINEW);
253 MixerLine2.cbStruct = sizeof(MIXERLINEW);
254 mixerGetLineInfoW((HMIXEROBJ)hMixer1, &MixerLine1, MIXER_GETLINEINFOF_DESTINATION);
255 MMixerGetLineInfo(&MixerContext, hMixer2, MIXER_GETLINEINFOF_DESTINATION, &MixerLine2);
256
257 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",
258 MixerLine1.dwDestination, MixerLine1.dwSource, MixerLine1.dwLineID, MixerLine1.dwUser, MixerLine1.dwComponentType, MixerLine1.cChannels, MixerLine1.cConnections, MixerLine1.cControls, MixerLine1.szShortName, MixerLine1.szName);
259
260 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",
261 MixerLine2.dwDestination, MixerLine2.dwSource, MixerLine2.dwLineID, MixerLine2.dwUser, MixerLine2.dwComponentType, MixerLine2.cChannels, MixerLine2.cConnections, MixerLine2.cControls, MixerLine2.szShortName, MixerLine2.szName);
262
263 Controls1.cbStruct = sizeof(MIXERLINECONTROLS);
264 Controls2.cbStruct = sizeof(MIXERLINECONTROLS);
265
266 Controls1.cbmxctrl = sizeof(MIXERCONTROL);
267 Controls2.cbmxctrl = sizeof(MIXERCONTROL);
268
269 Controls1.cControls = MixerLine1.cControls;
270 Controls2.cControls = MixerLine2.cControls;
271
272 Controls1.dwLineID = MixerLine1.dwLineID;
273 Controls2.dwLineID = MixerLine2.dwLineID;
274
275
276
277 Controls1.pamxctrl = (LPMIXERCONTROL)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIXERCONTROL) * Controls1.cControls);
278 Controls2.pamxctrl = (LPMIXERCONTROL)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIXERCONTROL) * Controls2.cControls);
279
280 for(SubIndex = 0; SubIndex < Controls1.cControls; SubIndex++)
281 Controls1.pamxctrl[SubIndex].cbStruct = sizeof(MIXERCONTROL);
282
283 for(SubIndex = 0; SubIndex < Controls2.cControls; SubIndex++)
284 Controls2.pamxctrl[SubIndex].cbStruct = sizeof(MIXERCONTROL);
285
286 mixerGetLineControls((HMIXEROBJ)hMixer1, &Controls1, MIXER_GETLINECONTROLSF_ALL);
287
288 wprintf(L"----------------------------------------\n");
289 for(SubIndex = 0; SubIndex < Controls1.cControls; SubIndex++)
290 {
291 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);
292 }
293 wprintf(L"----------------------------------------\n");
294
295
296 wprintf(L"=======================\n");
297 }
298 return 0;
299 }