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}};
20 DWORD SampleFrequency
,
21 LPWAVEFORMATEX WaveFormatEx
,
22 DWORD MinimumBitsPerSample
,
23 DWORD MaximumBitsPerSample
,
24 DWORD MaximumChannels
,
25 LPWAVEFORMATEX WaveFormatOut
)
27 DWORD nChannels
, nBitsPerSample
;
28 KSDATAFORMAT_WAVEFORMATEX WaveFormat
;
30 PKSMULTIPLE_ITEM Item
;
31 PKSDATAFORMAT_WAVEFORMATEX DataFormat
;
34 /* allocate request */
35 Pin
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(KSP_PIN
) + sizeof(KSMULTIPLE_ITEM
) + sizeof(KSDATAFORMAT_WAVEFORMATEX
));
42 Item
= (PKSMULTIPLE_ITEM
)(Pin
+ 1);
43 DataFormat
= (PKSDATAFORMAT_WAVEFORMATEX
)(Item
+ 1);
47 Pin
->Property
.Flags
= KSPROPERTY_TYPE_GET
;
48 Pin
->Property
.Set
= KSPROPSETID_Pin
;
49 Pin
->Property
.Id
= KSPROPERTY_PIN_DATAINTERSECTION
;
51 Item
->Size
= sizeof(KSDATAFORMAT_WAVEFORMATEX
);
54 DataFormat
->WaveFormatEx
.wFormatTag
= WaveFormatEx
->wFormatTag
;
55 DataFormat
->WaveFormatEx
.nSamplesPerSec
= SampleFrequency
;
56 DataFormat
->WaveFormatEx
.nBlockAlign
= WaveFormatEx
->nBlockAlign
;
57 DataFormat
->WaveFormatEx
.cbSize
= 0;
58 DataFormat
->DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
59 DataFormat
->DataFormat
.Flags
= 0;
60 DataFormat
->DataFormat
.Reserved
= 0;
61 DataFormat
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
62 DataFormat
->DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
63 DataFormat
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
64 DataFormat
->DataFormat
.SampleSize
= 4;
66 for(nChannels
= 1; nChannels
<= 2; nChannels
++)
68 for(nBitsPerSample
= MinimumBitsPerSample
; nBitsPerSample
<= MaximumBitsPerSample
; nBitsPerSample
+= 8)
70 DataFormat
->WaveFormatEx
.nChannels
= nChannels
;
71 DataFormat
->WaveFormatEx
.nAvgBytesPerSec
= (nBitsPerSample
/ 8) * nChannels
* SampleFrequency
;
72 DataFormat
->WaveFormatEx
.wBitsPerSample
= nBitsPerSample
;
74 DPRINT("CurrentFormat: InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\n",
75 nChannels
, nBitsPerSample
, SampleFrequency
);
77 dwResult
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)Pin
, sizeof(KSP_PIN
) + sizeof(KSMULTIPLE_ITEM
) + sizeof(KSDATAFORMAT_WAVEFORMATEX
),
78 (LPVOID
)&WaveFormat
, sizeof(KSDATAFORMAT_WAVEFORMATEX
), NULL
);
80 DPRINT("dwResult %x\n", dwResult
);
83 if (dwResult
== ERROR_SUCCESS
)
85 /* found a compatible audio range */
86 WaveFormatOut
->cbSize
= 0;
87 WaveFormatOut
->nBlockAlign
= WaveFormatEx
->nBlockAlign
;
88 WaveFormatOut
->wFormatTag
= WaveFormatEx
->wFormatTag
;
89 WaveFormatOut
->nAvgBytesPerSec
= (nBitsPerSample
/ 8) * nChannels
* SampleFrequency
;
90 WaveFormatOut
->wBitsPerSample
= nBitsPerSample
;
91 WaveFormatOut
->nSamplesPerSec
= SampleFrequency
;
92 WaveFormatOut
->nChannels
= nChannels
;
95 HeapFree(GetProcessHeap(), 0, Pin
);
97 DPRINT("InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\nOutFormat nChannels %u nBitsPerSample %u nSamplesPerSec %u\n",
98 WaveFormatEx
->nChannels
, WaveFormatEx
->wBitsPerSample
, WaveFormatEx
->nSamplesPerSec
,
99 WaveFormatOut
->nChannels
, WaveFormatOut
->wBitsPerSample
, WaveFormatOut
->nSamplesPerSec
);
107 HeapFree(GetProcessHeap(), 0, Pin
);
116 LPWAVEFORMATEX WaveFormatEx
,
121 PKSPIN_CONNECT PinConnect
;
122 PKSDATAFORMAT_WAVEFORMATEX DataFormat
;
124 /* calculate request size */
125 Size
= sizeof(KSPIN_CONNECT
) + sizeof(KSDATAFORMAT_WAVEFORMATEX
);
127 PinConnect
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
130 /* not enough memory */
131 return DSERR_OUTOFMEMORY
;
133 /* build pin request */
134 PinConnect
->Interface
.Set
= KSINTERFACESETID_Standard
;
137 PinConnect
->Interface
.Id
= KSINTERFACE_STANDARD_LOOPED_STREAMING
;
139 PinConnect
->Interface
.Id
= KSINTERFACE_STANDARD_STREAMING
;
141 PinConnect
->Interface
.Flags
= 0;
142 PinConnect
->Medium
.Set
= KSMEDIUMSETID_Standard
;
143 PinConnect
->Medium
.Id
= KSMEDIUM_TYPE_ANYINSTANCE
;
144 PinConnect
->Medium
.Flags
= 0;
145 PinConnect
->PinToHandle
= NULL
;
146 PinConnect
->PinId
= PinId
;
147 PinConnect
->Priority
.PriorityClass
= KSPRIORITY_NORMAL
;
148 PinConnect
->Priority
.PrioritySubClass
= 1;
150 DataFormat
= (PKSDATAFORMAT_WAVEFORMATEX
) (PinConnect
+ 1);
152 /* initialize data format */
153 DataFormat
->WaveFormatEx
.wFormatTag
= WaveFormatEx
->wFormatTag
;
154 DataFormat
->WaveFormatEx
.nChannels
= WaveFormatEx
->nChannels
;
155 DataFormat
->WaveFormatEx
.nSamplesPerSec
= WaveFormatEx
->nSamplesPerSec
;
156 DataFormat
->WaveFormatEx
.nBlockAlign
= WaveFormatEx
->nBlockAlign
;
157 DataFormat
->WaveFormatEx
.nAvgBytesPerSec
= WaveFormatEx
->nAvgBytesPerSec
;
158 DataFormat
->WaveFormatEx
.wBitsPerSample
= WaveFormatEx
->wBitsPerSample
;
159 DataFormat
->WaveFormatEx
.cbSize
= 0;
160 DataFormat
->DataFormat
.FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
);
161 DataFormat
->DataFormat
.Flags
= 0;
162 DataFormat
->DataFormat
.Reserved
= 0;
163 DataFormat
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
165 DataFormat
->DataFormat
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
166 DataFormat
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
167 DataFormat
->DataFormat
.SampleSize
= 4;
169 Result
= KsCreatePin(hFilter
, PinConnect
, GENERIC_READ
| GENERIC_WRITE
, hPin
);
171 HeapFree(GetProcessHeap(), 0, PinConnect
);
179 IN LPCWSTR lpFileName
,
180 IN PHANDLE OutHandle
)
184 /* open the filter */
185 Handle
= CreateFileW(lpFileName
, GENERIC_WRITE
| GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_OVERLAPPED
, NULL
);
187 /* check for success */
188 if (Handle
== INVALID_HANDLE_VALUE
)
190 DPRINT("Failed to open Filter %ws\n", lpFileName
);
191 return GetLastError();
195 return ERROR_SUCCESS
;
199 SyncOverlappedDeviceIoControl(
201 IN DWORD IoControlCode
,
203 IN DWORD InBufferSize
,
204 OUT LPVOID OutBuffer
,
205 IN DWORD OutBufferSize
,
206 OUT LPDWORD BytesTransferred OPTIONAL
)
208 OVERLAPPED Overlapped
;
210 DWORD Transferred
= 0;
212 /* Overlapped I/O is done here - this is used for waiting for completion */
213 ZeroMemory(&Overlapped
, sizeof(OVERLAPPED
));
214 Overlapped
.hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
216 if (!Overlapped
.hEvent
)
217 return GetLastError();
219 /* Talk to the device */
220 IoResult
= DeviceIoControl(Handle
,
229 /* If failure occurs, make sure it's not just due to the overlapped I/O */
232 if ( GetLastError() != ERROR_IO_PENDING
)
234 CloseHandle(Overlapped
.hEvent
);
235 return GetLastError();
239 /* Wait for the I/O to complete */
240 IoResult
= GetOverlappedResult(Handle
,
245 /* Don't need this any more */
246 CloseHandle(Overlapped
.hEvent
);
249 return GetLastError();
251 if ( BytesTransferred
)
252 *BytesTransferred
= Transferred
;
254 return ERROR_SUCCESS
;
266 /* setup the pin request */
267 Pin
.Flags
= KSPROPERTY_TYPE_GET
;
268 Pin
.Set
= KSPROPSETID_Pin
;
269 Pin
.Id
= KSPROPERTY_PIN_CTYPES
;
271 /* query the device */
272 return SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Pin
, sizeof(KSPROPERTY
), (PVOID
)NumPins
, sizeof(ULONG
), NULL
);
276 GetFilterNodeProperty(
279 OUT PKSMULTIPLE_ITEM
*OutMultipleItem
)
281 DWORD Status
, BytesReturned
;
282 PKSMULTIPLE_ITEM MultipleItem
;
285 /* setup query request */
286 Property
.Id
= PropertyId
;
287 Property
.Flags
= KSPROPERTY_TYPE_GET
;
288 Property
.Set
= KSPROPSETID_Topology
;
291 Status
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSPROPERTY
), NULL
, 0, &BytesReturned
);
293 if (Status
!= ERROR_MORE_DATA
)
296 DPRINT("Failed to query PropertyId %lu ErrorCode %lx\n", PropertyId
, Status
);
300 MultipleItem
= HeapAlloc(GetProcessHeap(), 0, BytesReturned
);
303 /* not enough memory */
304 DPRINT("Failed to allocate %u Bytes\n", BytesReturned
);
305 return ERROR_OUTOFMEMORY
;
308 /* retrieve data ranges */
309 Status
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), (LPVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
312 if (Status
!= ERROR_SUCCESS
)
314 /* failed to get data ranges */
315 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status
);
317 HeapFree(GetProcessHeap(), 0, MultipleItem
);
322 *OutMultipleItem
= MultipleItem
;
328 GetFilterPinCommunication(
331 OUT PKSPIN_COMMUNICATION Communication
)
335 Property
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
336 Property
.Property
.Set
= KSPROPSETID_Pin
;
337 Property
.Property
.Id
= KSPROPERTY_PIN_COMMUNICATION
;
338 Property
.PinId
= PinId
;
339 Property
.Reserved
= 0;
341 return SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), (LPVOID
)Communication
, sizeof(KSPIN_COMMUNICATION
), NULL
);
345 GetFilterPinDataFlow(
348 OUT PKSPIN_DATAFLOW DataFlow
)
352 Property
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
353 Property
.Property
.Set
= KSPROPSETID_Pin
;
354 Property
.Property
.Id
= KSPROPERTY_PIN_DATAFLOW
;
355 Property
.PinId
= PinId
;
356 Property
.Reserved
= 0;
358 return SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), (LPVOID
)DataFlow
, sizeof(KSPIN_DATAFLOW
), NULL
);
362 GetFilterPinDataRanges(
365 IN OUT PKSMULTIPLE_ITEM
* OutMultipleItem
)
368 ULONG BytesReturned
= 0;
370 PKSMULTIPLE_ITEM MultipleItem
;
372 /* prepare request */
373 Property
.Reserved
= 0;
374 Property
.PinId
= PinId
;
375 Property
.Property
.Set
= KSPROPSETID_Pin
;
376 Property
.Property
.Id
= KSPROPERTY_PIN_DATARANGES
;
377 Property
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
379 /* retrieve size of data ranges buffer */
380 Status
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), NULL
, 0, &BytesReturned
);
383 if (Status
!= ERROR_MORE_DATA
)
385 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status
);
390 ASSERT(BytesReturned
);
391 MultipleItem
= HeapAlloc(GetProcessHeap(), 0, BytesReturned
);
394 /* not enough memory */
395 DPRINT("Failed to allocate %u Bytes\n", BytesReturned
);
396 return ERROR_OUTOFMEMORY
;
399 /* retrieve data ranges */
400 Status
= SyncOverlappedDeviceIoControl(hFilter
, IOCTL_KS_PROPERTY
, (LPVOID
)&Property
, sizeof(KSP_PIN
), (LPVOID
)MultipleItem
, BytesReturned
, &BytesReturned
);
403 if (Status
!= ERROR_SUCCESS
)
405 /* failed to get data ranges */
406 DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status
);
408 HeapFree(GetProcessHeap(), 0, MultipleItem
);
413 *OutMultipleItem
= MultipleItem
;
422 IN LPWAVEFORMATEX WaveFormatEx
,
423 OUT LPWAVEFORMATEX WaveFormatOut
,
426 PKSMULTIPLE_ITEM Item
= NULL
;
427 PKSDATARANGE_AUDIO AudioRange
;
429 DWORD dwIndex
, nChannels
;
431 dwResult
= GetFilterPinDataRanges(hFilter
, PinId
, &Item
);
433 if (dwResult
!= ERROR_SUCCESS
)
435 /* failed to get data ranges */
439 CopyMemory(WaveFormatOut
, WaveFormatEx
, sizeof(WAVEFORMATEX
));
441 /* iterate through all dataranges */
442 AudioRange
= (PKSDATARANGE_AUDIO
)(Item
+ 1);
443 for(dwIndex
= 0; dwIndex
< Item
->Count
; dwIndex
++)
445 if (AudioRange
->DataRange
.FormatSize
!= sizeof(KSDATARANGE_AUDIO
))
448 AudioRange
= (PKSDATARANGE_AUDIO
)((PUCHAR
)AudioRange
+ AudioRange
->DataRange
.FormatSize
);
452 if (WaveFormatOut
->nSamplesPerSec
< AudioRange
->MinimumSampleFrequency
)
453 WaveFormatOut
->nSamplesPerSec
= AudioRange
->MinimumSampleFrequency
;
454 else if (WaveFormatOut
->nSamplesPerSec
> AudioRange
->MaximumSampleFrequency
)
455 WaveFormatOut
->nSamplesPerSec
= AudioRange
->MaximumSampleFrequency
;
457 if (WaveFormatOut
->wBitsPerSample
< AudioRange
->MinimumBitsPerSample
)
458 WaveFormatOut
->wBitsPerSample
= AudioRange
->MinimumBitsPerSample
;
459 else if (WaveFormatOut
->wBitsPerSample
> AudioRange
->MaximumBitsPerSample
)
460 WaveFormatOut
->wBitsPerSample
= AudioRange
->MaximumBitsPerSample
;
462 DPRINT1("MinimumBitsPerSample %u MaximumBitsPerSample %u MinimumSampleFrequency %u MaximumSampleFrequency %u\n",
463 AudioRange
->MinimumBitsPerSample
, AudioRange
->MaximumBitsPerSample
, AudioRange
->MinimumSampleFrequency
, AudioRange
->MaximumSampleFrequency
);
465 for(nChannels
= 1; nChannels
<= AudioRange
->MaximumChannels
; nChannels
++)
467 WaveFormatOut
->nChannels
= nChannels
;
469 DPRINT("InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\nOutFormat nChannels %u nBitsPerSample %u nSamplesPerSec %u\n",
470 WaveFormatEx
->nChannels
, WaveFormatEx
->wBitsPerSample
, WaveFormatEx
->nSamplesPerSec
,
471 WaveFormatOut
->nChannels
, WaveFormatOut
->wBitsPerSample
, WaveFormatOut
->nSamplesPerSec
);
473 dwResult
= OpenPin(hFilter
, PinId
, WaveFormatOut
, hPin
, TRUE
);
474 if (dwResult
== ERROR_SUCCESS
)
477 HeapFree(GetProcessHeap(), 0, Item
);
481 AudioRange
= (PKSDATARANGE_AUDIO
)((PUCHAR
)AudioRange
+ AudioRange
->DataRange
.FormatSize
);
485 HeapFree(GetProcessHeap(), 0, Item
);