1 /* DirectSound capture buffer interface
3 * Copyright 2009 Maarten Lankhorst
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSSTRUCT
26 #define NONAMELESSUNION
35 #include "wine/debug.h"
38 #include "dsound_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
51 #include "dsound_private.h"
53 #ifndef DSCBPN_OFFSET_STOP
54 #define DSCBPN_OFFSET_STOP 0xffffffff
57 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM
, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
61 /* IDirectSoundCapture and IDirectSoundCapture8 are aliases */
62 HRESULT
DSOUND_CaptureCreate(REFIID riid
, IDirectSoundCapture
**cap
)
64 return DSOUND_CaptureCreate8(riid
, cap
);
67 typedef struct DSCBuffer DSCBuffer
;
69 typedef struct DSCImpl
71 const IDirectSoundCaptureVtbl
*lpVtbl
;
78 CRITICAL_SECTION crst
;
83 const IDirectSoundCaptureBuffer8Vtbl
*lpVtbl
;
84 const IDirectSoundNotifyVtbl
*lpNotVtbl
;
91 DSBPOSITIONNOTIFY
*notify
;
95 BOOL playing
, looping
;
98 static const IDirectSoundCaptureVtbl DSC_Vtbl
;
99 static const IDirectSoundCaptureBuffer8Vtbl DSCBuffer_Vtbl
;
100 static const IDirectSoundNotifyVtbl DSCNot_Vtbl
;
102 static void DSCImpl_Destroy(DSCImpl
*This
);
104 static HRESULT
DSCBuffer_Create(DSCBuffer
**buf
)
106 DSCBuffer
*This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
108 return E_OUTOFMEMORY
;
109 This
->lpVtbl
= &DSCBuffer_Vtbl
;
110 This
->lpNotVtbl
= &DSCNot_Vtbl
;
116 static void trigger_notifies(DSCBuffer
*buf
, DWORD lastpos
, DWORD curpos
)
119 if (lastpos
== curpos
)
121 for (i
= 0; i
< buf
->nnotify
; ++i
)
123 DSBPOSITIONNOTIFY
*not = &buf
->notify
[i
];
124 HANDLE event
= not->hEventNotify
;
125 DWORD ofs
= not->dwOffset
;
127 if (ofs
== DSCBPN_OFFSET_STOP
)
130 /* Wraparound case */
131 if (curpos
< lastpos
)
146 static void CALLBACK
DSCBuffer_timer(UINT timerID
, UINT msg
, DWORD_PTR dwUser
,
147 DWORD_PTR dw1
, DWORD_PTR dw2
)
149 DSCImpl
*This
= (DSCImpl
*)dwUser
;
157 EnterCriticalSection(&This
->crst
);
159 if (!buf
|| !buf
->dev
|| !buf
->playing
)
162 alcGetIntegerv(buf
->dev
, ALC_CAPTURE_SAMPLES
, 1, &avail
);
165 avail
*= buf
->format
->nBlockAlign
;
166 if (avail
+ buf
->pos
> buf
->buf_size
)
167 avail
= buf
->buf_size
- buf
->pos
;
169 alcCaptureSamples(buf
->dev
, buf
->buf
+ buf
->pos
, avail
/buf
->format
->nBlockAlign
);
170 trigger_notifies(buf
, buf
->pos
, buf
->pos
+ avail
);
173 if (buf
->pos
== buf
->buf_size
)
177 IDirectSoundCaptureBuffer_Stop((IDirectSoundCaptureBuffer
*)buf
);
181 alcGetIntegerv(buf
->dev
, ALC_CAPTURE_SAMPLES
, 1, &avail
);
182 avail
*= buf
->format
->nBlockAlign
;
183 if ((ALCuint
)avail
>= buf
->buf_size
)
185 ERR("TOO MUCH AVAIL: %u/%u\n", avail
, buf
->buf_size
);
186 avail
= buf
->buf_size
;
191 alcCaptureSamples(buf
->dev
, buf
->buf
+ buf
->pos
, avail
/buf
->format
->nBlockAlign
);
192 trigger_notifies(buf
, buf
->pos
, buf
->pos
+ avail
);
200 LeaveCriticalSection(&This
->crst
);
204 static void DSCBuffer_starttimer(DSCImpl
*prim
)
207 ALint refresh
= FAKE_REFRESH_COUNT
;
208 DWORD triggertime
, res
= DS_TIME_RES
;
213 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
214 triggertime
= 1000 / refresh
;
215 if (triggertime
< time
.wPeriodMin
)
216 triggertime
= time
.wPeriodMin
;
217 TRACE("Calling timer every %u ms for %i refreshes per second\n", triggertime
, refresh
);
218 if (res
< time
.wPeriodMin
)
219 res
= time
.wPeriodMin
;
220 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
221 WARN("Could not set minimum resolution, don't expect sound\n");
222 prim
->timer_res
= res
;
223 prim
->timer_id
= timeSetEvent(triggertime
, res
, DSCBuffer_timer
, (DWORD_PTR
)prim
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
226 static void DSCBuffer_Destroy(DSCBuffer
*This
)
231 alcCaptureStop(This
->dev
);
232 alcCaptureCloseDevice(This
->dev
);
235 This
->parent
->buf
= NULL
;
236 HeapFree(GetProcessHeap(), 0, This
->notify
);
237 HeapFree(GetProcessHeap(), 0, This
->format
);
238 HeapFree(GetProcessHeap(), 0, This
->buf
);
239 HeapFree(GetProcessHeap(), 0, This
);
242 static HRESULT WINAPI
DSCBuffer_QueryInterface(IDirectSoundCaptureBuffer8
*iface
, REFIID riid
, void **ppv
)
244 DSCBuffer
*This
= (DSCBuffer
*)iface
;
247 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
249 if (IsEqualIID(riid
, &IID_IDirectSoundNotify
))
250 *ppv
= &This
->lpNotVtbl
;
251 else if (IsEqualIID(riid
, &IID_IUnknown
)
252 || IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer
)
253 || IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer8
))
256 return E_NOINTERFACE
;
257 IUnknown_AddRef((IUnknown
*)*ppv
);
261 static ULONG WINAPI
DSCBuffer_AddRef(IDirectSoundCaptureBuffer8
*iface
)
263 DSCBuffer
*This
= (DSCBuffer
*)iface
;
265 ref
= InterlockedIncrement(&This
->ref
);
266 TRACE("Reference count incremented to %i\n", ref
);
270 static ULONG WINAPI
DSCBuffer_Release(IDirectSoundCaptureBuffer8
*iface
)
272 DSCBuffer
*This
= (DSCBuffer
*)iface
;
273 CRITICAL_SECTION
*crst
= &This
->parent
->crst
;
275 EnterCriticalSection(crst
);
276 ref
= InterlockedDecrement(&This
->ref
);
277 TRACE("Reference count decremented to %i\n", ref
);
278 if (!ref
&& !This
->not_ref
)
279 DSCBuffer_Destroy(This
);
280 LeaveCriticalSection(crst
);
284 static HRESULT WINAPI
DSCBuffer_GetCaps(IDirectSoundCaptureBuffer8
*iface
, DSCBCAPS
*caps
)
286 DSCBuffer
*This
= (DSCBuffer
*)iface
;
288 if (!caps
|| caps
->dwSize
< sizeof(*caps
))
289 return DSERR_INVALIDPARAM
;
290 caps
->dwSize
= sizeof(*caps
);
292 caps
->dwBufferBytes
= This
->buf_size
;
296 static HRESULT WINAPI
DSCBuffer_GetCurrentPosition(IDirectSoundCaptureBuffer8
*iface
, DWORD
*cappos
, DWORD
*readpos
)
298 DSCBuffer
*This
= (DSCBuffer
*)iface
;
301 EnterCriticalSection(&This
->parent
->crst
);
305 pos2
= This
->format
->nSamplesPerSec
/ 100;
306 pos2
*= This
->format
->nBlockAlign
;
308 if (!This
->looping
&& pos2
>= This
->buf_size
)
311 pos2
%= This
->buf_size
;
315 LeaveCriticalSection(&This
->parent
->crst
);
317 if(cappos
) *cappos
= pos1
;
318 if(readpos
) *readpos
= pos2
;
323 static HRESULT WINAPI
DSCBuffer_GetFormat(IDirectSoundCaptureBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD size
, DWORD
*written
)
325 DSCBuffer
*This
= (DSCBuffer
*)iface
;
326 TRACE("(%p,%p,%u,%p)\n", This
, wfx
, size
, written
);
328 if (size
> sizeof(WAVEFORMATEX
) + This
->format
->cbSize
)
329 size
= sizeof(WAVEFORMATEX
) + This
->format
->cbSize
;
333 CopyMemory(wfx
, This
->format
, size
);
337 *written
= sizeof(WAVEFORMATEX
) + This
->format
->cbSize
;
339 return DSERR_INVALIDPARAM
;
344 static HRESULT WINAPI
DSCBuffer_GetStatus(IDirectSoundCaptureBuffer8
*iface
, DWORD
*status
)
346 DSCBuffer
*This
= (DSCBuffer
*)iface
;
347 TRACE("(%p)->(%p)\n", This
, status
);
350 return DSERR_INVALIDPARAM
;
351 EnterCriticalSection(&This
->parent
->crst
);
355 *status
|= DSCBSTATUS_CAPTURING
;
357 *status
|= DSCBSTATUS_LOOPING
;
359 LeaveCriticalSection(&This
->parent
->crst
);
364 static HRESULT WINAPI
DSCBuffer_Initialize(IDirectSoundCaptureBuffer8
*iface
, IDirectSoundCapture
*parent
, const DSCBUFFERDESC
*desc
)
366 DSCBuffer
*This
= (DSCBuffer
*)iface
;
367 WAVEFORMATEX
*format
;
368 ALenum buf_format
= -1;
371 return DSERR_ALREADYINITIALIZED
;
372 This
->parent
= (DSCImpl
*)parent
;
373 if (!desc
->lpwfxFormat
)
374 return DSERR_INVALIDPARAM
;
376 format
= desc
->lpwfxFormat
;
377 if (format
->nChannels
> 2)
379 WARN("nChannels > 2 not supported for recording\n");
380 return DSERR_INVALIDPARAM
;
384 This
->format
= HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE
));
386 return DSERR_OUTOFMEMORY
;
388 if (format
->wFormatTag
== WAVE_FORMAT_PCM
389 || format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
391 if (format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
393 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)format
;
394 if (format
->cbSize
< sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
))
395 return DSERR_INVALIDPARAM
;
396 else if (format
->cbSize
> sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
)
397 && format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
398 return DSERR_CONTROLUNAVAIL
;
399 else if (!IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
400 return DSERR_BADFORMAT
;
403 if (format
->nChannels
== 1)
405 switch (format
->wBitsPerSample
)
407 case 8: buf_format
= AL_FORMAT_MONO8
; break;
408 case 16: buf_format
= AL_FORMAT_MONO16
; break;
410 WARN("Unsupported bpp %u\n", format
->wBitsPerSample
);
411 return DSERR_BADFORMAT
;
414 else if (format
->nChannels
== 2)
416 switch (format
->wBitsPerSample
)
418 case 8: buf_format
= AL_FORMAT_STEREO8
; break;
419 case 16: buf_format
= AL_FORMAT_STEREO16
; break;
421 WARN("Unsupported bpp %u\n", format
->wBitsPerSample
);
422 return DSERR_BADFORMAT
;
425 memcpy(This
->format
, format
, sizeof(*format
) + format
->cbSize
);
426 if (format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
427 This
->format
->cbSize
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
429 This
->format
->cbSize
= 0;
430 This
->format
->nBlockAlign
= This
->format
->wBitsPerSample
* This
->format
->nChannels
/ 8;
431 This
->format
->nAvgBytesPerSec
= This
->format
->nSamplesPerSec
* This
->format
->nBlockAlign
;
433 else if (format
->wFormatTag
)
434 WARN("Unhandled formattag %x\n", format
->wFormatTag
);
436 This
->buf_size
= desc
->dwBufferBytes
;
439 WARN("Could not get OpenAL format\n");
440 return DSERR_INVALIDPARAM
;
442 This
->dev
= alcCaptureOpenDevice(This
->parent
->device
, This
->format
->nSamplesPerSec
, buf_format
, This
->buf_size
/ This
->format
->nBlockAlign
);
445 ERR("couldn't open device %s %x@%u, reason: %04x\n", This
->parent
->device
, buf_format
, This
->format
->nSamplesPerSec
, alcGetError(NULL
));
446 return DSERR_INVALIDPARAM
;
448 This
->buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->buf_size
);
451 alcCaptureCloseDevice(This
->dev
);
452 WARN("Out of memory\n");
453 return DSERR_INVALIDPARAM
;
459 static HRESULT WINAPI
DSCBuffer_Lock(IDirectSoundCaptureBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
461 DSCBuffer
*This
= (DSCBuffer
*)iface
;
464 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, %#x)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
466 EnterCriticalSection(&This
->parent
->crst
);
467 hr
= DSERR_INVALIDPARAM
;
476 if (ofs
>= This
->buf_size
)
478 WARN("Invalid ofs %u\n", ofs
);
483 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
486 if (flags
& DSCBLOCK_ENTIREBUFFER
)
487 bytes
= This
->buf_size
;
488 if (bytes
> This
->buf_size
)
490 WARN("Invalid size %u\n", bytes
);
494 if (ofs
+ bytes
>= This
->buf_size
)
496 *len1
= This
->buf_size
- ofs
;
497 remain
= bytes
- *len1
;
504 *ptr1
= This
->buf
+ ofs
;
506 if (ptr2
&& len2
&& remain
)
514 LeaveCriticalSection(&This
->parent
->crst
);
518 static HRESULT WINAPI
DSCBuffer_Start(IDirectSoundCaptureBuffer8
*iface
, DWORD flags
)
520 DSCBuffer
*This
= (DSCBuffer
*)iface
;
521 TRACE("(%p)->(%08x)\n", This
, flags
);
523 EnterCriticalSection(&This
->parent
->crst
);
526 DSCBuffer_starttimer(This
->parent
);
528 alcCaptureStart(This
->dev
);
530 This
->looping
= !!(flags
& DSCBSTART_LOOPING
);
531 LeaveCriticalSection(&This
->parent
->crst
);
535 static HRESULT WINAPI
DSCBuffer_Stop(IDirectSoundCaptureBuffer8
*iface
)
537 DSCBuffer
*This
= (DSCBuffer
*)iface
;
538 TRACE("(%p)\n", This
);
540 EnterCriticalSection(&This
->parent
->crst
);
545 for (i
= 0; i
< This
->nnotify
; ++i
)
546 if (This
->notify
[i
].dwOffset
== DSCBPN_OFFSET_STOP
)
548 SetEvent(This
->notify
[i
].hEventNotify
);
551 This
->playing
= This
->looping
= 0;
552 alcCaptureStop(This
->dev
);
554 LeaveCriticalSection(&This
->parent
->crst
);
558 static HRESULT WINAPI
DSCBuffer_Unlock(IDirectSoundCaptureBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
560 DSCBuffer
*This
= (DSCBuffer
*)iface
;
561 TRACE("(%p)->(%p,%u,%p,%u)\n", This
, ptr1
, len1
, ptr2
, len2
);
564 return DSERR_INVALIDPARAM
;
568 static HRESULT WINAPI
DSCBuffer_GetObjectInPath(IDirectSoundCaptureBuffer8
*iface
, REFGUID guid
, DWORD num
, REFGUID riid
, void **ppv
)
570 DSCBuffer
*This
= (DSCBuffer
*)iface
;
571 FIXME("(%p)->(%s %u %s %p) stub\n", This
, debugstr_guid(guid
), num
, debugstr_guid(riid
), ppv
);
575 static HRESULT WINAPI
DSCBuffer_GetFXStatus(IDirectSoundCaptureBuffer8
*iface
, DWORD count
, DWORD
*status
)
577 DSCBuffer
*This
= (DSCBuffer
*)iface
;
578 FIXME("(%p)->(%u %p) stub\n", This
, count
, status
);
582 static const IDirectSoundCaptureBuffer8Vtbl DSCBuffer_Vtbl
=
584 DSCBuffer_QueryInterface
,
588 DSCBuffer_GetCurrentPosition
,
591 DSCBuffer_Initialize
,
596 DSCBuffer_GetObjectInPath
,
597 DSCBuffer_GetFXStatus
600 static DSCBuffer
*get_this_from_not(IDirectSoundNotify
*iface
)
602 return (DSCBuffer
*)((char*)iface
- offsetof(DSCBuffer
,lpNotVtbl
));
605 static HRESULT WINAPI
DSCBufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
607 DSCBuffer
*This
= get_this_from_not(iface
);
608 return IDirectSoundCaptureBuffer_QueryInterface((IDirectSoundCaptureBuffer
*)This
, riid
, ppv
);
611 static ULONG WINAPI
DSCBufferNot_AddRef(IDirectSoundNotify
*iface
)
613 DSCBuffer
*This
= get_this_from_not(iface
);
616 ret
= InterlockedIncrement(&This
->not_ref
);
617 TRACE("new refcount %d\n", ret
);
621 static ULONG WINAPI
DSCBufferNot_Release(IDirectSoundNotify
*iface
)
623 DSCBuffer
*This
= get_this_from_not(iface
);
624 CRITICAL_SECTION
*crst
= &This
->parent
->crst
;
627 EnterCriticalSection(crst
);
628 ret
= InterlockedDecrement(&This
->not_ref
);
629 TRACE("new refcount %d\n", ret
);
630 if (!ret
&& !This
->ref
)
631 DSCBuffer_Destroy(This
);
632 LeaveCriticalSection(crst
);
636 static HRESULT WINAPI
DSCBufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
638 DSCBuffer
*This
= get_this_from_not(iface
);
639 DSBPOSITIONNOTIFY
*nots
;
643 EnterCriticalSection(&This
->parent
->crst
);
644 hr
= DSERR_INVALIDPARAM
;
645 if (count
&& !notifications
)
648 hr
= DSCBuffer_GetStatus((IDirectSoundCaptureBuffer8
*)This
, &state
);
652 hr
= DSERR_INVALIDCALL
;
653 if (state
& DSCBSTATUS_CAPTURING
)
658 HeapFree(GetProcessHeap(), 0, This
->notify
);
665 hr
= DSERR_INVALIDPARAM
;
666 for (i
= 0; i
< count
; ++i
)
668 if (notifications
[i
].dwOffset
>= This
->buf_size
669 && notifications
[i
].dwOffset
!= DSCBPN_OFFSET_STOP
)
673 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
676 memcpy(nots
, notifications
, count
*sizeof(*nots
));
677 HeapFree(GetProcessHeap(), 0, This
->notify
);
679 This
->nnotify
= count
;
684 LeaveCriticalSection(&This
->parent
->crst
);
688 static const IDirectSoundNotifyVtbl DSCNot_Vtbl
=
690 DSCBufferNot_QueryInterface
,
692 DSCBufferNot_Release
,
693 DSCBufferNot_SetNotificationPositions
696 HRESULT
DSOUND_CaptureCreate8(REFIID riid
, IDirectSoundCapture8
**cap
)
698 DSCImpl
*This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
701 return DSERR_OUTOFMEMORY
;
702 This
->lpVtbl
= &DSC_Vtbl
;
704 InitializeCriticalSection(&This
->crst
);
705 This
->crst
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DSCImpl.crst");
706 if (FAILED(IUnknown_QueryInterface((IUnknown
*)This
, riid
, (void**)cap
)))
708 DSCImpl_Destroy(This
);
709 return E_NOINTERFACE
;
714 static void DSCImpl_Destroy(DSCImpl
*This
)
718 timeKillEvent(This
->timer_id
);
719 timeEndPeriod(This
->timer_res
);
721 EnterCriticalSection(&This
->crst
);
723 DSCBuffer_Destroy(This
->buf
);
724 LeaveCriticalSection(&This
->crst
);
725 HeapFree(GetProcessHeap(), 0, This
->device
);
726 This
->crst
.DebugInfo
->Spare
[0] = 0;
727 DeleteCriticalSection(&This
->crst
);
728 HeapFree(GetProcessHeap(), 0, This
);
731 static HRESULT WINAPI
DSCImpl_QueryInterface(IDirectSoundCapture
*iface
, REFIID riid
, void **ppv
)
734 if (IsEqualIID(riid
, &IID_IUnknown
)
735 || IsEqualIID(riid
, &IID_IDirectSoundCapture
))
740 return E_NOINTERFACE
;
741 IUnknown_AddRef((IUnknown
*)*ppv
);
745 static ULONG WINAPI
DSCImpl_AddRef(IDirectSoundCapture8
*iface
)
747 DSCImpl
*This
= (DSCImpl
*)iface
;
749 ref
= InterlockedIncrement(&This
->ref
);
750 TRACE("Reference count incremented to %i\n", ref
);
754 static ULONG WINAPI
DSCImpl_Release(IDirectSoundCapture8
*iface
)
756 DSCImpl
*This
= (DSCImpl
*)iface
;
758 ref
= InterlockedDecrement(&This
->ref
);
759 TRACE("Reference count decremented to %i\n", ref
);
761 DSCImpl_Destroy(This
);
765 static HRESULT WINAPI
DSCImpl_CreateCaptureBuffer(IDirectSoundCapture8
*iface
, const DSCBUFFERDESC
*desc
, IDirectSoundCaptureBuffer
**ppv
, IUnknown
*unk
)
767 DSCImpl
*This
= (DSCImpl
*)iface
;
769 TRACE("(%p)->(%p,%p,%p)\n", This
, desc
, ppv
, unk
);
773 WARN("Aggregation isn't supported\n");
774 return DSERR_NOAGGREGATION
;
777 if (!desc
|| desc
->dwSize
< sizeof(DSCBUFFERDESC1
))
779 WARN("Passed invalid description %p %u\n", desc
, desc
?desc
->dwSize
:0);
780 return DSERR_INVALIDPARAM
;
784 WARN("Passed null pointer\n");
785 return DSERR_INVALIDPARAM
;
789 EnterCriticalSection(&This
->crst
);
792 hr
= DSERR_UNINITIALIZED
;
793 WARN("Not initialized\n");
798 hr
= DSERR_ALLOCATED
;
799 WARN("Capture buffer already allocated\n");
803 hr
= DSCBuffer_Create(&This
->buf
);
806 hr
= IDirectSoundCaptureBuffer_Initialize((IDirectSoundCaptureBuffer
*)This
->buf
, iface
, desc
);
809 DSCBuffer_Destroy(This
->buf
);
813 *ppv
= (IDirectSoundCaptureBuffer
*)This
->buf
;
815 LeaveCriticalSection(&This
->crst
);
819 static HRESULT WINAPI
DSCImpl_GetCaps(IDirectSoundCapture8
*iface
, DSCCAPS
*caps
)
821 DSCImpl
*This
= (DSCImpl
*)iface
;
822 TRACE("(%p,%p)\n", This
, caps
);
825 WARN("Not initialized\n");
826 return DSERR_UNINITIALIZED
;
830 WARN("Caps is null\n");
831 return DSERR_INVALIDPARAM
;
834 if (caps
->dwSize
< sizeof(*caps
)) {
835 WARN("Invalid size %d\n", caps
->dwSize
);
836 return DSERR_INVALIDPARAM
;
840 /* Support all WAVE_FORMAT formats specified in mmsystem.h */
841 caps
->dwFormats
= 0x000fffff;
842 caps
->dwChannels
= 2;
847 static HRESULT WINAPI
DSCImpl_Initialize(IDirectSoundCapture8
*iface
, const GUID
*devguid
)
849 DSCImpl
*This
= (DSCImpl
*)iface
;
851 const ALCchar
*devs
, *drv_name
;
854 TRACE("(%p,%p)\n", This
, devguid
);
858 ERR("OpenAL not loaded!\n");
859 return DSERR_NODRIVER
;
863 WARN("Already initialized\n");
864 return DSERR_ALREADYINITIALIZED
;
868 devguid
= &DSDEVID_DefaultCapture
;
870 hr
= GetDeviceID(devguid
, &guid
);
872 return DSERR_INVALIDPARAM
;
875 EnterCriticalSection(&This
->crst
);
876 EnterCriticalSection(&openal_crst
);
877 devs
= DSOUND_getcapturedevicestrings();
881 if (memcmp(devguid
, &DSOUND_capture_guid
, sizeof(GUID
)-1)
884 WARN("No driver found\n");
890 const ALCchar
*str
= devs
;
893 str
+= strlen(str
) + 1;
896 WARN("No driver string found\n");
905 This
->device
= HeapAlloc(GetProcessHeap(), 0, strlen(drv_name
)+1);
908 WARN("Out of memory to allocate %s\n", drv_name
);
911 strcpy(This
->device
, drv_name
);
915 LeaveCriticalSection(&openal_crst
);
916 LeaveCriticalSection(&This
->crst
);
920 static const IDirectSoundCaptureVtbl DSC_Vtbl
=
922 DSCImpl_QueryInterface
,
925 DSCImpl_CreateCaptureBuffer
,