2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Configuration of network devices
4 * FILE: dll/directx/dsound_new/capturebuffer.c
5 * PURPOSE: IDirectSoundCaptureBuffer8 implementation
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
13 const GUID KSINTERFACESETID_Standard
= {0x1A8766A0L
, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
14 const GUID KSMEDIUMSETID_Standard
= {0x4747B320L
, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
15 const GUID KSDATAFORMAT_TYPE_AUDIO
= {0x73647561L
, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
16 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
= {0x05589f81L
, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
17 const GUID KSPROPSETID_Connection
= {0x1D58C920L
, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
22 IDirectSoundCaptureBuffer8Vtbl
*lpVtbl
;
28 LPWAVEFORMATEX Format
;
29 WAVEFORMATEX MixFormat
;
34 }CDirectSoundCaptureBufferImpl
, *LPCDirectSoundCaptureBufferImpl
;
38 IDirectSoundCaptureBufferImpl_QueryInterface(
39 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
44 LPCDirectSoundCaptureBufferImpl This
= (LPCDirectSoundCaptureBufferImpl
)CONTAINING_RECORD(iface
, CDirectSoundCaptureBufferImpl
, lpVtbl
);
46 /* check if requested interface is supported */
47 if (IsEqualIID(riid
, &IID_IUnknown
) ||
48 IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer
) ||
49 IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer8
))
51 *ppobj
= (LPVOID
)&This
->lpVtbl
;
52 InterlockedIncrement(&This
->ref
);
56 /* interface not supported */
57 if (SUCCEEDED(StringFromIID(riid
, &pStr
)))
59 DPRINT("No Interface for class %s\n", pStr
);
67 IDirectSoundCaptureBufferImpl_AddRef(
68 LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
71 LPCDirectSoundCaptureBufferImpl This
= (LPCDirectSoundCaptureBufferImpl
)CONTAINING_RECORD(iface
, CDirectSoundCaptureBufferImpl
, lpVtbl
);
73 /* increment reference count */
74 ref
= InterlockedIncrement(&This
->ref
);
82 IDirectSoundCaptureBufferImpl_Release(
83 LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
86 LPCDirectSoundCaptureBufferImpl This
= (LPCDirectSoundCaptureBufferImpl
)CONTAINING_RECORD(iface
, CDirectSoundCaptureBufferImpl
, lpVtbl
);
88 /* release reference count */
89 ref
= InterlockedDecrement(&(This
->ref
));
95 /* close pin handle */
96 CloseHandle(This
->hPin
);
99 /* free capture buffer */
100 HeapFree(GetProcessHeap(), 0, This
->Buffer
);
101 /* free wave format */
102 HeapFree(GetProcessHeap(), 0, This
->Format
);
103 /* free capture buffer */
104 HeapFree(GetProcessHeap(), 0, This
);
113 IDirectSoundCaptureBufferImpl_GetCaps(
114 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
115 LPDSCBCAPS lpDSCBCaps
)
117 LPCDirectSoundCaptureBufferImpl This
= (LPCDirectSoundCaptureBufferImpl
)CONTAINING_RECORD(iface
, CDirectSoundCaptureBufferImpl
, lpVtbl
);
121 /* invalid parameter */
122 return DSERR_INVALIDPARAM
;
125 if (lpDSCBCaps
->dwSize
!= sizeof(DSCBCAPS
))
127 /* invalid parameter */
128 return DSERR_INVALIDPARAM
;
131 lpDSCBCaps
->dwBufferBytes
= This
->BufferSize
;
132 lpDSCBCaps
->dwReserved
= 0;
133 //lpDSCBCaps->dwFlags = DSCBCAPS_WAVEMAPPED;
140 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
141 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
142 LPDWORD lpdwCapturePosition
,
143 LPDWORD lpdwReadPosition
)
145 KSAUDIO_POSITION Position
;
149 LPCDirectSoundCaptureBufferImpl This
= (LPCDirectSoundCaptureBufferImpl
)CONTAINING_RECORD(iface
, CDirectSoundCaptureBufferImpl
, lpVtbl
);
153 if (lpdwCapturePosition
)
154 *lpdwCapturePosition
= 0;
156 if (lpdwReadPosition
)
157 *lpdwReadPosition
= 0;
159 DPRINT("No Audio Pin\n");
163 /* setup audio position property request */
164 Request
.Id
= KSPROPERTY_AUDIO_POSITION
;
165 Request
.Set
= KSPROPSETID_Audio
;
166 Request
.Flags
= KSPROPERTY_TYPE_GET
;
169 Result
= SyncOverlappedDeviceIoControl(This
->hPin
, IOCTL_KS_PROPERTY
, (PVOID
)&Request
, sizeof(KSPROPERTY
), (PVOID
)&Position
, sizeof(KSAUDIO_POSITION
), NULL
);
171 if (Result
!= ERROR_SUCCESS
)
173 DPRINT("GetPosition failed with %x\n", Result
);
174 return DSERR_UNSUPPORTED
;
177 //DPRINT("Play %I64u Write %I64u \n", Position.PlayOffset, Position.WriteOffset);
179 if (lpdwCapturePosition
)
180 *lpdwCapturePosition
= (DWORD
)Position
.PlayOffset
;
182 if (lpdwReadPosition
)
183 *lpdwReadPosition
= (DWORD
)Position
.WriteOffset
;
191 IDirectSoundCaptureBufferImpl_GetFormat(
192 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
193 LPWAVEFORMATEX lpwfxFormat
,
194 DWORD dwSizeAllocated
,
195 LPDWORD lpdwSizeWritten
)
198 LPCDirectSoundCaptureBufferImpl This
= (LPCDirectSoundCaptureBufferImpl
)CONTAINING_RECORD(iface
, CDirectSoundCaptureBufferImpl
, lpVtbl
);
200 FormatSize
= sizeof(WAVEFORMATEX
) + This
->Format
->cbSize
;
202 if (!lpwfxFormat
&& !lpdwSizeWritten
)
204 /* invalid parameter */
205 return DSERR_INVALIDPARAM
;
210 /* return required format size */
211 *lpdwSizeWritten
= FormatSize
;
216 if (dwSizeAllocated
>= FormatSize
)
219 CopyMemory(lpwfxFormat
, This
->Format
, FormatSize
);
222 *lpdwSizeWritten
= FormatSize
;
226 /* buffer too small */
228 *lpdwSizeWritten
= 0;
229 return DSERR_INVALIDPARAM
;
235 IDirectSoundCaptureBufferImpl_GetStatus(
236 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
239 LPCDirectSoundCaptureBufferImpl This
= (LPCDirectSoundCaptureBufferImpl
)CONTAINING_RECORD(iface
, CDirectSoundCaptureBufferImpl
, lpVtbl
);
243 /* invalid parameter */
244 return DSERR_INVALIDPARAM
;
250 /* check if pin is running */
251 if (This
->State
== KSSTATE_RUN
)
252 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
254 /* check if a looped buffer is used */
256 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
264 IDirectSoundCaptureBufferImpl_Initialize(
265 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
266 LPDIRECTSOUNDCAPTURE lpDSC
,
267 LPCDSCBUFFERDESC lpcDSCBDesc
)
269 /* capture buffer is already initialized */
270 return DSERR_ALREADYINITIALIZED
;
275 IDirectSoundCaptureBufferImpl_Lock(
276 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
279 LPVOID
* ppvAudioPtr1
,
280 LPDWORD pdwAudioBytes1
,
281 LPVOID
* ppvAudioPtr2
,
282 LPDWORD pdwAudioBytes2
,
285 LPCDirectSoundCaptureBufferImpl This
= (LPCDirectSoundCaptureBufferImpl
)CONTAINING_RECORD(iface
, CDirectSoundCaptureBufferImpl
, lpVtbl
);
287 DPRINT("This %p dwOffset %u dwBytes %u ppvAudioPtr1 %p pdwAudioBytes1 %p ppvAudioPtr2 %p pdwAudioBytes2 %p dwFlags %x This->BufferSize %u\n",
288 This
, dwOffset
, dwBytes
, ppvAudioPtr1
, pdwAudioBytes1
, ppvAudioPtr2
, pdwAudioBytes2
, dwFlags
, This
->BufferSize
);
290 if (dwFlags
== DSBLOCK_ENTIREBUFFER
)
292 *ppvAudioPtr1
= (LPVOID
)This
->Buffer
;
293 *pdwAudioBytes1
= This
->BufferSize
;
295 *ppvAudioPtr2
= NULL
;
301 else if (dwFlags
& DSBLOCK_FROMWRITECURSOR
)
304 return DSERR_UNSUPPORTED
;
308 ASSERT(dwOffset
< This
->BufferSize
);
309 ASSERT(dwBytes
< This
->BufferSize
);
310 ASSERT(dwBytes
+ dwOffset
<= This
->BufferSize
);
312 *ppvAudioPtr1
= This
->Buffer
+ dwOffset
;
313 *pdwAudioBytes1
= dwBytes
;
315 *ppvAudioPtr2
= NULL
;
325 IDirectSoundCaptureBufferImpl_Start(
326 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
330 KSSTREAM_HEADER Header
;
331 DWORD Result
, BytesTransferred
;
332 OVERLAPPED Overlapped
;
334 LPCDirectSoundCaptureBufferImpl This
= (LPCDirectSoundCaptureBufferImpl
)CONTAINING_RECORD(iface
, CDirectSoundCaptureBufferImpl
, lpVtbl
);
336 DPRINT("IDirectSoundCaptureBufferImpl_Start Flags %x\n", dwFlags
);
337 ASSERT(dwFlags
== DSCBSTART_LOOPING
);
339 /* check if pin is already running */
340 if (This
->State
== KSSTATE_RUN
)
347 Property
.Set
= KSPROPSETID_Connection
;
348 Property
.Id
= KSPROPERTY_CONNECTION_STATE
;
349 Property
.Flags
= KSPROPERTY_TYPE_SET
;
353 Result
= SyncOverlappedDeviceIoControl(This
->hPin
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSPROPERTY
), (PVOID
)&State
, sizeof(KSSTATE
), &BytesTransferred
);
355 ASSERT(Result
== ERROR_SUCCESS
);
357 if (Result
== ERROR_SUCCESS
)
363 /* initialize overlapped struct */
364 ZeroMemory(&Overlapped
, sizeof(OVERLAPPED
));
365 Overlapped
.hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
367 /* clear stream header */
368 ZeroMemory(&Header
, sizeof(KSSTREAM_HEADER
));
370 /* initialize stream header */
371 Header
.FrameExtent
= This
->BufferSize
;
373 Header
.Data
= This
->Buffer
;
374 Header
.Size
= sizeof(KSSTREAM_HEADER
);
375 Header
.PresentationTime
.Numerator
= 1;
376 Header
.PresentationTime
.Denominator
= 1;
378 Result
= DeviceIoControl(This
->hPin
, IOCTL_KS_WRITE_STREAM
, NULL
, 0, &Header
, sizeof(KSSTREAM_HEADER
), &BytesTransferred
, &Overlapped
);
380 if (Result
!= ERROR_SUCCESS
)
382 DPRINT("Failed submit buffer with %lx\n", Result
);
383 return DSERR_GENERIC
;
391 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
394 return DSERR_INVALIDPARAM
;
399 IDirectSoundCaptureBufferImpl_Unlock(
400 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
404 DWORD dwAudioBytes2
)
411 IDirectSoundCaptureBufferImpl_GetObjectInPath(
412 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
415 REFGUID rguidInterface
,
419 return DSERR_INVALIDPARAM
;
424 IDirectSoundCaptureBufferImpl_GetFXStatus(
425 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
427 LPDWORD pdwFXStatus
)
430 return DSERR_INVALIDPARAM
;
434 static IDirectSoundCaptureBuffer8Vtbl vt_DirectSoundCaptureBuffer8
=
436 /* IUnknown methods */
437 IDirectSoundCaptureBufferImpl_QueryInterface
,
438 IDirectSoundCaptureBufferImpl_AddRef
,
439 IDirectSoundCaptureBufferImpl_Release
,
441 /* IDirectSoundCaptureBuffer methods */
442 IDirectSoundCaptureBufferImpl_GetCaps
,
443 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
444 IDirectSoundCaptureBufferImpl_GetFormat
,
445 IDirectSoundCaptureBufferImpl_GetStatus
,
446 IDirectSoundCaptureBufferImpl_Initialize
,
447 IDirectSoundCaptureBufferImpl_Lock
,
448 IDirectSoundCaptureBufferImpl_Start
,
449 IDirectSoundCaptureBufferImpl_Stop
,
450 IDirectSoundCaptureBufferImpl_Unlock
,
452 /* IDirectSoundCaptureBuffer methods */
453 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
454 IDirectSoundCaptureBufferImpl_GetFXStatus
459 NewDirectSoundCaptureBuffer(
460 LPDIRECTSOUNDCAPTUREBUFFER8
*OutBuffer
,
462 LPCDSCBUFFERDESC lpcDSBufferDesc
)
465 ULONG DeviceId
= 0, PinId
;
466 DWORD Result
= ERROR_SUCCESS
;
467 WAVEFORMATEX MixFormat
;
469 LPCDirectSoundCaptureBufferImpl This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(CDirectSoundCaptureBufferImpl
));
473 /* not enough memory */
474 return DSERR_OUTOFMEMORY
;
477 /* calculate format size */
478 FormatSize
= sizeof(WAVEFORMATEX
) + lpcDSBufferDesc
->lpwfxFormat
->cbSize
;
479 /* allocate format struct */
480 This
->Format
= HeapAlloc(GetProcessHeap(), 0, FormatSize
);
483 /* not enough memory */
484 HeapFree(GetProcessHeap(), 0, This
);
485 return DSERR_OUTOFMEMORY
;
489 ASSERT(lpcDSBufferDesc
->dwBufferBytes
);
491 /* allocate capture buffer */
492 This
->Buffer
= HeapAlloc(GetProcessHeap(), 0, lpcDSBufferDesc
->dwBufferBytes
);
495 /* not enough memory */
496 HeapFree(GetProcessHeap(), 0, This
->Format
);
497 HeapFree(GetProcessHeap(), 0, This
);
498 return DSERR_OUTOFMEMORY
;
501 /* store buffer size */
502 This
->BufferSize
= lpcDSBufferDesc
->dwBufferBytes
;
503 ASSERT(lpcDSBufferDesc
->lpwfxFormat
->cbSize
== 0);
507 /* try all available recording pins on that filter */
508 PinId
= GetPinIdFromFilter(Filter
, TRUE
, DeviceId
);
510 if (PinId
== ULONG_MAX
)
513 Result
= OpenPin(Filter
->hFilter
, PinId
, lpcDSBufferDesc
->lpwfxFormat
, &This
->hPin
, TRUE
);
514 if (Result
== ERROR_SUCCESS
)
520 if (Result
!= ERROR_SUCCESS
)
522 /* failed to instantiate the capture pin with the native format
523 * try to compute a compatible format and use that
524 * we could use the mixer api for this purpose but... the kmixer isnt working very good atm
530 /* try all available recording pins on that filter */
531 PinId
= GetPinIdFromFilter(Filter
, TRUE
, DeviceId
);
532 DPRINT("PinId %u DeviceId %u\n", PinId
, DeviceId
);
534 if (PinId
== ULONG_MAX
)
537 if (CreateCompatiblePin(Filter
->hFilter
, PinId
, TRUE
, lpcDSBufferDesc
->lpwfxFormat
, &MixFormat
, &This
->hPin
))
540 CopyMemory(&This
->MixFormat
, &MixFormat
, sizeof(WAVEFORMATEX
));
550 /* FIXME should not happen */
551 DPRINT("failed to compute a compatible format\n");
552 HeapFree(GetProcessHeap(), 0, This
->Buffer
);
553 HeapFree(GetProcessHeap(), 0, This
->Format
);
554 HeapFree(GetProcessHeap(), 0, This
);
555 return DSERR_GENERIC
;
559 /* initialize capture buffer */
561 This
->lpVtbl
= &vt_DirectSoundCaptureBuffer8
;
562 This
->Filter
= Filter
;
563 This
->State
= KSSTATE_STOP
;
566 RtlMoveMemory(This
->Format
, lpcDSBufferDesc
->lpwfxFormat
, FormatSize
);
568 *OutBuffer
= (LPDIRECTSOUNDCAPTUREBUFFER8
)&This
->lpVtbl
;