2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Configuration of network devices
4 * FILE: dll/directx/dsound_new/misc.c
5 * PURPOSE: Misc support routines
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
12 const GUID KSPROPSETID_Pin
= {0x8C134960L
, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
13 const GUID KSPROPSETID_Topology
= {0x720D4AC0L
, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
14 const GUID KSPROPSETID_Audio
= {0x45FFAAA0L
, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
19 IN LPWAVEFORMATEX WaveFormatEx
)
23 KSDATAFORMAT_WAVEFORMATEX DataFormat
;
25 /* setup connection request */
26 Property
.Id
= KSPROPERTY_CONNECTION_DATAFORMAT
;
27 Property
.Set
= KSPROPSETID_Connection
;
28 Property
.Flags
= KSPROPERTY_TYPE_SET
;
30 /* setup data format */
31 DataFormat
.WaveFormatEx
.wFormatTag
= WaveFormatEx
->wFormatTag
;
32 DataFormat
.WaveFormatEx
.nSamplesPerSec
= WaveFormatEx
->nSamplesPerSec
;
33 DataFormat
.WaveFormatEx
.nBlockAlign
= WaveFormatEx
->nBlockAlign
;
34 DataFormat
.WaveFormatEx
.cbSize
= 0;
35 DataFormat
.DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
36 DataFormat
.DataFormat
.Flags
= 0;
37 DataFormat
.DataFormat
.Reserved
= 0;
38 DataFormat
.DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
39 DataFormat
.DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
40 DataFormat
.DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
41 DataFormat
.DataFormat
.SampleSize
= 4;
42 DataFormat
.WaveFormatEx
.nChannels
= WaveFormatEx
->nChannels
;
43 DataFormat
.WaveFormatEx
.nAvgBytesPerSec
= WaveFormatEx
->nAvgBytesPerSec
;
44 DataFormat
.WaveFormatEx
.wBitsPerSample
= WaveFormatEx
->wBitsPerSample
;
46 dwResult
= SyncOverlappedDeviceIoControl(hPin
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSPROPERTY
),(LPVOID
)&DataFormat
, sizeof(KSDATAFORMAT_WAVEFORMATEX
), NULL
);
48 if (dwResult
== ERROR_SUCCESS
)
59 DWORD SampleFrequency
,
60 LPWAVEFORMATEX WaveFormatEx
,
61 DWORD MinimumBitsPerSample
,
62 DWORD MaximumBitsPerSample
,
63 DWORD MaximumChannels
,
64 LPWAVEFORMATEX WaveFormatOut
)
66 DWORD nChannels
, nBitsPerSample
;
67 KSDATAFORMAT_WAVEFORMATEX WaveFormat
;
69 PKSMULTIPLE_ITEM Item
;
70 PKSDATAFORMAT_WAVEFORMATEX DataFormat
;
73 /* allocate request */
74 Pin
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(KSP_PIN
) + sizeof(KSMULTIPLE_ITEM
) + sizeof(KSDATAFORMAT_WAVEFORMATEX
));
81 Item
= (PKSMULTIPLE_ITEM
)(Pin
+ 1);
82 DataFormat
= (PKSDATAFORMAT_WAVEFORMATEX
)(Item
+ 1);
86 Pin
->Property
.Flags
= KSPROPERTY_TYPE_GET
;
87 Pin
->Property
.Set
= KSPROPSETID_Pin
;
88 Pin
->Property
.Id
= KSPROPERTY_PIN_DATAINTERSECTION
;
90 Item
->Size
= sizeof(KSDATAFORMAT_WAVEFORMATEX
);
93 DataFormat
->WaveFormatEx
.wFormatTag
= WaveFormatEx
->wFormatTag
;
94 DataFormat
->WaveFormatEx
.nSamplesPerSec
= SampleFrequency
;
95 DataFormat
->WaveFormatEx
.nBlockAlign
= WaveFormatEx
->nBlockAlign
;
96 DataFormat
->WaveFormatEx
.cbSize
= 0;
97 DataFormat
->DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
98 DataFormat
->DataFormat
.Flags
= 0;
99 DataFormat
->DataFormat
.Reserved
= 0;
100 DataFormat
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
101 DataFormat
->DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
102 DataFormat
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
103 DataFormat
->DataFormat
.SampleSize
= 4;
105 for(nChannels
= 1; nChannels
<= 2; nChannels
++)
107 for(nBitsPerSample
= MinimumBitsPerSample
; nBitsPerSample
<= MaximumBitsPerSample
; nBitsPerSample
+= 8)
109 DataFormat
->WaveFormatEx
.nChannels
= nChannels
;
110 DataFormat
->WaveFormatEx
.nAvgBytesPerSec
= (nBitsPerSample
/ 8) * nChannels
* SampleFrequency
;
111 DataFormat
->WaveFormatEx
.wBitsPerSample
= nBitsPerSample
;
113 DPRINT("CurrentFormat: InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\n",
114 nChannels
, nBitsPerSample
, SampleFrequency
);
116 dwResult
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)Pin
, sizeof(KSP_PIN
) + sizeof(KSMULTIPLE_ITEM
) + sizeof(KSDATAFORMAT_WAVEFORMATEX
),
117 (LPVOID
)&WaveFormat
, sizeof(KSDATAFORMAT_WAVEFORMATEX
), NULL
);
119 DPRINT("dwResult %x\n", dwResult
);
122 if (dwResult
== ERROR_SUCCESS
)
124 /* found a compatible audio range */
125 WaveFormatOut
->cbSize
= 0;
126 WaveFormatOut
->nBlockAlign
= WaveFormatEx
->nBlockAlign
;
127 WaveFormatOut
->wFormatTag
= WaveFormatEx
->wFormatTag
;
128 WaveFormatOut
->nAvgBytesPerSec
= (nBitsPerSample
/ 8) * nChannels
* SampleFrequency
;
129 WaveFormatOut
->wBitsPerSample
= nBitsPerSample
;
130 WaveFormatOut
->nSamplesPerSec
= SampleFrequency
;
131 WaveFormatOut
->nChannels
= nChannels
;
134 HeapFree(GetProcessHeap(), 0, Pin
);
136 DPRINT("InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\nOutFormat nChannels %u nBitsPerSample %u nSamplesPerSec %u\n",
137 WaveFormatEx
->nChannels
, WaveFormatEx
->wBitsPerSample
, WaveFormatEx
->nSamplesPerSec
,
138 WaveFormatOut
->nChannels
, WaveFormatOut
->wBitsPerSample
, WaveFormatOut
->nSamplesPerSec
);
146 HeapFree(GetProcessHeap(), 0, Pin
);
155 LPWAVEFORMATEX WaveFormatEx
,
160 PKSPIN_CONNECT PinConnect
;
161 PKSDATAFORMAT_WAVEFORMATEX DataFormat
;
163 /* calculate request size */
164 Size
= sizeof(KSPIN_CONNECT
) + sizeof(KSDATAFORMAT_WAVEFORMATEX
);
166 PinConnect
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
169 /* not enough memory */
170 return DSERR_OUTOFMEMORY
;
172 /* build pin request */
173 PinConnect
->Interface
.Set
= KSINTERFACESETID_Standard
;
176 PinConnect
->Interface
.Id
= KSINTERFACE_STANDARD_LOOPED_STREAMING
;
178 PinConnect
->Interface
.Id
= KSINTERFACE_STANDARD_STREAMING
;
180 PinConnect
->Interface
.Flags
= 0;
181 PinConnect
->Medium
.Set
= KSMEDIUMSETID_Standard
;
182 PinConnect
->Medium
.Id
= KSMEDIUM_TYPE_ANYINSTANCE
;
183 PinConnect
->Medium
.Flags
= 0;
184 PinConnect
->PinToHandle
= NULL
;
185 PinConnect
->PinId
= PinId
;
186 PinConnect
->Priority
.PriorityClass
= KSPRIORITY_NORMAL
;
187 PinConnect
->Priority
.PrioritySubClass
= 1;
189 DataFormat
= (PKSDATAFORMAT_WAVEFORMATEX
) (PinConnect
+ 1);
191 /* initialize data format */
192 DataFormat
->WaveFormatEx
.wFormatTag
= WaveFormatEx
->wFormatTag
;
193 DataFormat
->WaveFormatEx
.nChannels
= WaveFormatEx
->nChannels
;
194 DataFormat
->WaveFormatEx
.nSamplesPerSec
= WaveFormatEx
->nSamplesPerSec
;
195 DataFormat
->WaveFormatEx
.nBlockAlign
= WaveFormatEx
->nBlockAlign
;
196 DataFormat
->WaveFormatEx
.nAvgBytesPerSec
= WaveFormatEx
->nAvgBytesPerSec
;
197 DataFormat
->WaveFormatEx
.wBitsPerSample
= WaveFormatEx
->wBitsPerSample
;
198 DataFormat
->WaveFormatEx
.cbSize
= 0;
199 DataFormat
->DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
200 DataFormat
->DataFormat
.Flags
= 0;
201 DataFormat
->DataFormat
.Reserved
= 0;
202 DataFormat
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
204 DataFormat
->DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
205 DataFormat
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
206 DataFormat
->DataFormat
.SampleSize
= 4;
208 Result
= KsCreatePin(hFilter
, PinConnect
, GENERIC_READ
| GENERIC_WRITE
, hPin
);
210 HeapFree(GetProcessHeap(), 0, PinConnect
);
218 IN LPCWSTR lpFileName
,
219 IN PHANDLE OutHandle
)
223 /* open the filter */
224 Handle
= CreateFileW(lpFileName
, GENERIC_WRITE
| GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
, NULL
);
226 /* check for success */
227 if (Handle
== INVALID_HANDLE_VALUE
)
229 DPRINT("Failed to open Filter %ws\n", lpFileName
);
230 return GetLastError();
234 return ERROR_SUCCESS
;
238 SyncOverlappedDeviceIoControl(
240 IN DWORD IoControlCode
,
242 IN DWORD InBufferSize
,
243 OUT LPVOID OutBuffer
,
244 IN DWORD OutBufferSize
,
245 OUT LPDWORD BytesTransferred OPTIONAL
)
247 OVERLAPPED Overlapped
;
249 DWORD Transferred
= 0;
251 /* Overlapped I/O is done here - this is used for waiting for completion */
252 ZeroMemory(&Overlapped
, sizeof(OVERLAPPED
));
253 Overlapped
.hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
255 if (!Overlapped
.hEvent
)
256 return GetLastError();
258 /* Talk to the device */
259 IoResult
= DeviceIoControl(Handle
,
268 /* If failure occurs, make sure it's not just due to the overlapped I/O */
271 if ( GetLastError() != ERROR_IO_PENDING
)
273 CloseHandle(Overlapped
.hEvent
);
274 return GetLastError();
278 /* Wait for the I/O to complete */
279 IoResult
= GetOverlappedResult(Handle
,
284 /* Don't need this any more */
285 CloseHandle(Overlapped
.hEvent
);
288 return GetLastError();
290 if ( BytesTransferred
)
291 *BytesTransferred
= Transferred
;
293 return ERROR_SUCCESS
;
305 /* setup the pin request */
306 Pin
.Flags
= KSPROPERTY_TYPE_GET
;
307 Pin
.Set
= KSPROPSETID_Pin
;
308 Pin
.Id
= KSPROPERTY_PIN_CTYPES
;
310 /* query the device */
311 return SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)NumPins
, sizeof(ULONG
), NULL
);
315 GetFilterNodeProperty(
318 OUT PKSMULTIPLE_ITEM
*OutMultipleItem
)
320 DWORD Status
, BytesReturned
;
321 PKSMULTIPLE_ITEM MultipleItem
;
324 /* setup query request */
325 Property
.Id
= PropertyId
;
326 Property
.Flags
= KSPROPERTY_TYPE_GET
;
327 Property
.Set
= KSPROPSETID_Topology
;
330 Status
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSPROPERTY
), NULL
, 0, &BytesReturned
);
332 if (Status
!= ERROR_MORE_DATA
)
335 DPRINT("Failed to query PropertyId %lu ErrorCode %lx\n", PropertyId
, Status
);
339 MultipleItem
= HeapAlloc(GetProcessHeap(), 0, BytesReturned
);
342 /* not enough memory */
343 DPRINT("Failed to allocate %u Bytes\n", BytesReturned
);
344 return ERROR_OUTOFMEMORY
;
347 /* retrieve data ranges */
348 Status
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), (LPVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
351 if (Status
!= ERROR_SUCCESS
)
353 /* failed to get data ranges */
354 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status
);
356 HeapFree(GetProcessHeap(), 0, MultipleItem
);
361 *OutMultipleItem
= MultipleItem
;
367 GetFilterPinCommunication(
370 OUT PKSPIN_COMMUNICATION Communication
)
374 Property
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
375 Property
.Property
.Set
= KSPROPSETID_Pin
;
376 Property
.Property
.Id
= KSPROPERTY_PIN_COMMUNICATION
;
377 Property
.PinId
= PinId
;
378 Property
.Reserved
= 0;
380 return SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), (LPVOID
)Communication
, sizeof(KSPIN_COMMUNICATION
), NULL
);
384 GetFilterPinDataFlow(
387 OUT PKSPIN_DATAFLOW DataFlow
)
391 Property
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
392 Property
.Property
.Set
= KSPROPSETID_Pin
;
393 Property
.Property
.Id
= KSPROPERTY_PIN_DATAFLOW
;
394 Property
.PinId
= PinId
;
395 Property
.Reserved
= 0;
397 return SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), (LPVOID
)DataFlow
, sizeof(KSPIN_DATAFLOW
), NULL
);
401 GetFilterPinDataRanges(
404 IN OUT PKSMULTIPLE_ITEM
* OutMultipleItem
)
407 ULONG BytesReturned
= 0;
409 PKSMULTIPLE_ITEM MultipleItem
;
411 /* prepare request */
412 Property
.Reserved
= 0;
413 Property
.PinId
= PinId
;
414 Property
.Property
.Set
= KSPROPSETID_Pin
;
415 Property
.Property
.Id
= KSPROPERTY_PIN_DATARANGES
;
416 Property
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
418 /* retrieve size of data ranges buffer */
419 Status
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), NULL
, 0, &BytesReturned
);
422 if (Status
!= ERROR_MORE_DATA
)
424 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status
);
429 ASSERT(BytesReturned
);
430 MultipleItem
= HeapAlloc(GetProcessHeap(), 0, BytesReturned
);
433 /* not enough memory */
434 DPRINT("Failed to allocate %u Bytes\n", BytesReturned
);
435 return ERROR_OUTOFMEMORY
;
438 /* retrieve data ranges */
439 Status
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), (LPVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
442 if (Status
!= ERROR_SUCCESS
)
444 /* failed to get data ranges */
445 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status
);
447 HeapFree(GetProcessHeap(), 0, MultipleItem
);
452 *OutMultipleItem
= MultipleItem
;
461 IN LPWAVEFORMATEX WaveFormatEx
,
462 OUT LPWAVEFORMATEX WaveFormatOut
,
465 PKSMULTIPLE_ITEM Item
= NULL
;
466 PKSDATARANGE_AUDIO AudioRange
;
468 DWORD dwIndex
, nChannels
;
470 dwResult
= GetFilterPinDataRanges(hFilter
, PinId
, &Item
);
472 if (dwResult
!= ERROR_SUCCESS
)
474 /* failed to get data ranges */
478 CopyMemory(WaveFormatOut
, WaveFormatEx
, sizeof(WAVEFORMATEX
));
480 /* iterate through all dataranges */
481 AudioRange
= (PKSDATARANGE_AUDIO
)(Item
+ 1);
482 for(dwIndex
= 0; dwIndex
< Item
->Count
; dwIndex
++)
484 if (AudioRange
->DataRange
.FormatSize
!= sizeof(KSDATARANGE_AUDIO
))
487 AudioRange
= (PKSDATARANGE_AUDIO
)((PUCHAR
)AudioRange
+ AudioRange
->DataRange
.FormatSize
);
491 if (WaveFormatOut
->nSamplesPerSec
< AudioRange
->MinimumSampleFrequency
)
492 WaveFormatOut
->nSamplesPerSec
= AudioRange
->MinimumSampleFrequency
;
493 else if (WaveFormatOut
->nSamplesPerSec
> AudioRange
->MaximumSampleFrequency
)
494 WaveFormatOut
->nSamplesPerSec
= AudioRange
->MaximumSampleFrequency
;
496 if (WaveFormatOut
->wBitsPerSample
< AudioRange
->MinimumBitsPerSample
)
497 WaveFormatOut
->wBitsPerSample
= AudioRange
->MinimumBitsPerSample
;
498 else if (WaveFormatOut
->wBitsPerSample
> AudioRange
->MaximumBitsPerSample
)
499 WaveFormatOut
->wBitsPerSample
= AudioRange
->MaximumBitsPerSample
;
501 DPRINT1("MinimumBitsPerSample %u MaximumBitsPerSample %u MinimumSampleFrequency %u MaximumSampleFrequency %u\n",
502 AudioRange
->MinimumBitsPerSample
, AudioRange
->MaximumBitsPerSample
, AudioRange
->MinimumSampleFrequency
, AudioRange
->MaximumSampleFrequency
);
504 for(nChannels
= 1; nChannels
<= AudioRange
->MaximumChannels
; nChannels
++)
506 WaveFormatOut
->nChannels
= nChannels
;
508 DPRINT("InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\nOutFormat nChannels %u nBitsPerSample %u nSamplesPerSec %u\n",
509 WaveFormatEx
->nChannels
, WaveFormatEx
->wBitsPerSample
, WaveFormatEx
->nSamplesPerSec
,
510 WaveFormatOut
->nChannels
, WaveFormatOut
->wBitsPerSample
, WaveFormatOut
->nSamplesPerSec
);
512 dwResult
= OpenPin(hFilter
, PinId
, WaveFormatOut
, hPin
, TRUE
);
513 if (dwResult
== ERROR_SUCCESS
)
516 HeapFree(GetProcessHeap(), 0, Item
);
520 AudioRange
= (PKSDATARANGE_AUDIO
)((PUCHAR
)AudioRange
+ AudioRange
->DataRange
.FormatSize
);
524 HeapFree(GetProcessHeap(), 0, Item
);