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
;
153 EnterCriticalSection(&This
->crst
);
155 if (!buf
|| !buf
->dev
|| !buf
->playing
)
158 alcGetIntegerv(buf
->dev
, ALC_CAPTURE_SAMPLES
, 1, &avail
);
161 avail
*= buf
->format
->nBlockAlign
;
162 if (avail
+ buf
->pos
> buf
->buf_size
)
163 avail
= buf
->buf_size
- buf
->pos
;
165 alcCaptureSamples(buf
->dev
, buf
->buf
+ buf
->pos
, avail
/buf
->format
->nBlockAlign
);
166 trigger_notifies(buf
, buf
->pos
, buf
->pos
+ avail
);
169 if (buf
->pos
== buf
->buf_size
)
173 IDirectSoundCaptureBuffer_Stop((IDirectSoundCaptureBuffer
*)buf
);
177 alcGetIntegerv(buf
->dev
, ALC_CAPTURE_SAMPLES
, 1, &avail
);
178 avail
*= buf
->format
->nBlockAlign
;
179 if (avail
>= buf
->buf_size
)
181 ERR("TOO MUCH AVAIL: %u/%u\n", avail
, buf
->buf_size
);
182 avail
= buf
->buf_size
;
187 alcCaptureSamples(buf
->dev
, buf
->buf
+ buf
->pos
, avail
/buf
->format
->nBlockAlign
);
188 trigger_notifies(buf
, buf
->pos
, buf
->pos
+ avail
);
196 LeaveCriticalSection(&This
->crst
);
200 static void DSCBuffer_starttimer(DSCImpl
*prim
)
203 ALint refresh
= FAKE_REFRESH_COUNT
;
204 DWORD triggertime
, res
= DS_TIME_RES
;
209 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
210 triggertime
= 1000 / refresh
;
211 if (triggertime
< time
.wPeriodMin
)
212 triggertime
= time
.wPeriodMin
;
213 TRACE("Calling timer every %u ms for %i refreshes per second\n", triggertime
, refresh
);
214 if (res
< time
.wPeriodMin
)
215 res
= time
.wPeriodMin
;
216 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
217 WARN("Could not set minimum resolution, don't expect sound\n");
218 prim
->timer_res
= res
;
219 prim
->timer_id
= timeSetEvent(triggertime
, res
, DSCBuffer_timer
, (DWORD_PTR
)prim
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
222 static void DSCBuffer_Destroy(DSCBuffer
*This
)
227 alcCaptureStop(This
->dev
);
228 alcCaptureCloseDevice(This
->dev
);
231 This
->parent
->buf
= NULL
;
232 HeapFree(GetProcessHeap(), 0, This
->notify
);
233 HeapFree(GetProcessHeap(), 0, This
->format
);
234 HeapFree(GetProcessHeap(), 0, This
->buf
);
235 HeapFree(GetProcessHeap(), 0, This
);
238 static HRESULT WINAPI
DSCBuffer_QueryInterface(IDirectSoundCaptureBuffer8
*iface
, REFIID riid
, void **ppv
)
240 DSCBuffer
*This
= (DSCBuffer
*)iface
;
243 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
245 if (IsEqualIID(riid
, &IID_IDirectSoundNotify
))
246 *ppv
= &This
->lpNotVtbl
;
247 else if (IsEqualIID(riid
, &IID_IUnknown
)
248 || IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer
)
249 || IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer8
))
252 return E_NOINTERFACE
;
253 IUnknown_AddRef((IUnknown
*)*ppv
);
257 static ULONG WINAPI
DSCBuffer_AddRef(IDirectSoundCaptureBuffer8
*iface
)
259 DSCBuffer
*This
= (DSCBuffer
*)iface
;
261 ref
= InterlockedIncrement(&This
->ref
);
262 TRACE("Reference count incremented to %i\n", ref
);
266 static ULONG WINAPI
DSCBuffer_Release(IDirectSoundCaptureBuffer8
*iface
)
268 DSCBuffer
*This
= (DSCBuffer
*)iface
;
269 CRITICAL_SECTION
*crst
= &This
->parent
->crst
;
271 EnterCriticalSection(crst
);
272 ref
= InterlockedDecrement(&This
->ref
);
273 TRACE("Reference count decremented to %i\n", ref
);
274 if (!ref
&& !This
->not_ref
)
275 DSCBuffer_Destroy(This
);
276 LeaveCriticalSection(crst
);
280 static HRESULT WINAPI
DSCBuffer_GetCaps(IDirectSoundCaptureBuffer8
*iface
, DSCBCAPS
*caps
)
282 DSCBuffer
*This
= (DSCBuffer
*)iface
;
284 if (!caps
|| caps
->dwSize
< sizeof(*caps
))
285 return DSERR_INVALIDPARAM
;
286 caps
->dwSize
= sizeof(*caps
);
288 caps
->dwBufferBytes
= This
->buf_size
;
292 static HRESULT WINAPI
DSCBuffer_GetCurrentPosition(IDirectSoundCaptureBuffer8
*iface
, DWORD
*cappos
, DWORD
*readpos
)
294 DSCBuffer
*This
= (DSCBuffer
*)iface
;
296 EnterCriticalSection(&This
->parent
->crst
);
300 pos2
= This
->format
->nSamplesPerSec
/ 100;
301 pos2
*= This
->format
->nBlockAlign
;
303 if (!This
->looping
&& pos2
> This
->buf_size
)
306 pos2
%= This
->buf_size
;
310 pos2
%= This
->buf_size
;
311 LeaveCriticalSection(&This
->parent
->crst
);
315 static HRESULT WINAPI
DSCBuffer_GetFormat(IDirectSoundCaptureBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD size
, DWORD
*written
)
317 DSCBuffer
*This
= (DSCBuffer
*)iface
;
318 TRACE("(%p,%p,%u,%p)\n", This
, wfx
, size
, written
);
320 if (size
> sizeof(WAVEFORMATEX
) + This
->format
->cbSize
)
321 size
= sizeof(WAVEFORMATEX
) + This
->format
->cbSize
;
325 CopyMemory(wfx
, This
->format
, size
);
329 *written
= sizeof(WAVEFORMATEX
) + This
->format
->cbSize
;
331 return DSERR_INVALIDPARAM
;
336 static HRESULT WINAPI
DSCBuffer_GetStatus(IDirectSoundCaptureBuffer8
*iface
, DWORD
*status
)
338 DSCBuffer
*This
= (DSCBuffer
*)iface
;
339 TRACE("(%p)->(%p)\n", This
, status
);
342 return DSERR_INVALIDPARAM
;
343 EnterCriticalSection(&This
->parent
->crst
);
347 *status
|= DSCBSTATUS_CAPTURING
;
349 *status
|= DSCBSTATUS_LOOPING
;
351 LeaveCriticalSection(&This
->parent
->crst
);
356 static HRESULT WINAPI
DSCBuffer_Initialize(IDirectSoundCaptureBuffer8
*iface
, IDirectSoundCapture
*parent
, const DSCBUFFERDESC
*desc
)
358 DSCBuffer
*This
= (DSCBuffer
*)iface
;
359 WAVEFORMATEX
*format
;
360 ALenum buf_format
= -1;
363 return DSERR_ALREADYINITIALIZED
;
364 This
->parent
= (DSCImpl
*)parent
;
365 if (!desc
->lpwfxFormat
)
366 return DSERR_INVALIDPARAM
;
368 format
= desc
->lpwfxFormat
;
369 if (format
->nChannels
> 2)
371 WARN("nChannels > 2 not supported for recording\n");
372 return DSERR_INVALIDPARAM
;
376 This
->format
= HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE
));
378 return DSERR_OUTOFMEMORY
;
380 if (format
->wFormatTag
== WAVE_FORMAT_PCM
381 || format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
383 if (format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
385 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)format
;
386 if (format
->cbSize
< sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
))
387 return DSERR_INVALIDPARAM
;
388 else if (format
->cbSize
> sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
)
389 && format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
390 return DSERR_CONTROLUNAVAIL
;
391 else if (!IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
392 return DSERR_BADFORMAT
;
395 if (format
->nChannels
== 1)
397 switch (format
->wBitsPerSample
)
399 case 8: buf_format
= AL_FORMAT_MONO8
; break;
400 case 16: buf_format
= AL_FORMAT_MONO16
; break;
402 WARN("Unsupported bpp %u\n", format
->wBitsPerSample
);
403 return DSERR_BADFORMAT
;
406 else if (format
->nChannels
== 2)
408 switch (format
->wBitsPerSample
)
410 case 8: buf_format
= AL_FORMAT_STEREO8
; break;
411 case 16: buf_format
= AL_FORMAT_STEREO16
; break;
413 WARN("Unsupported bpp %u\n", format
->wBitsPerSample
);
414 return DSERR_BADFORMAT
;
417 memcpy(This
->format
, format
, sizeof(*format
) + format
->cbSize
);
418 if (format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
419 This
->format
->cbSize
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
421 This
->format
->cbSize
= 0;
422 This
->format
->nBlockAlign
= This
->format
->wBitsPerSample
* This
->format
->nChannels
/ 8;
423 This
->format
->nAvgBytesPerSec
= This
->format
->nSamplesPerSec
* This
->format
->nBlockAlign
;
425 else if (format
->wFormatTag
)
426 WARN("Unhandled formattag %x\n", format
->wFormatTag
);
428 This
->buf_size
= desc
->dwBufferBytes
;
431 WARN("Could not get OpenAL format\n");
432 return DSERR_INVALIDPARAM
;
434 This
->dev
= alcCaptureOpenDevice(This
->parent
->device
, This
->format
->nSamplesPerSec
, buf_format
, This
->buf_size
/ This
->format
->nBlockAlign
);
437 ERR("couldn't open device %s %x@%u, reason: %04x\n", This
->parent
->device
, buf_format
, This
->format
->nSamplesPerSec
, alcGetError(NULL
));
438 return DSERR_INVALIDPARAM
;
440 This
->buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->buf_size
);
443 alcCaptureCloseDevice(This
->dev
);
444 WARN("Out of memory\n");
445 return DSERR_INVALIDPARAM
;
451 static HRESULT WINAPI
DSCBuffer_Lock(IDirectSoundCaptureBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
453 DSCBuffer
*This
= (DSCBuffer
*)iface
;
456 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, %#x)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
458 EnterCriticalSection(&This
->parent
->crst
);
459 hr
= DSERR_INVALIDPARAM
;
468 if (ofs
>= This
->buf_size
)
470 WARN("Invalid ofs %u\n", ofs
);
475 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
478 if (flags
& DSCBLOCK_ENTIREBUFFER
)
479 bytes
= This
->buf_size
;
480 if (bytes
> This
->buf_size
)
482 WARN("Invalid size %u\n", bytes
);
486 if (ofs
+ bytes
>= This
->buf_size
)
488 *len1
= This
->buf_size
- ofs
;
489 remain
= bytes
- *len1
;
496 *ptr1
= This
->buf
+ ofs
;
498 if (ptr2
&& len2
&& remain
)
506 LeaveCriticalSection(&This
->parent
->crst
);
510 static HRESULT WINAPI
DSCBuffer_Start(IDirectSoundCaptureBuffer8
*iface
, DWORD flags
)
512 DSCBuffer
*This
= (DSCBuffer
*)iface
;
513 TRACE("(%p)->(%08x)\n", This
, flags
);
515 EnterCriticalSection(&This
->parent
->crst
);
518 DSCBuffer_starttimer(This
->parent
);
520 alcCaptureStart(This
->dev
);
522 This
->looping
= !!(flags
& DSCBSTART_LOOPING
);
523 LeaveCriticalSection(&This
->parent
->crst
);
527 static HRESULT WINAPI
DSCBuffer_Stop(IDirectSoundCaptureBuffer8
*iface
)
529 DSCBuffer
*This
= (DSCBuffer
*)iface
;
530 TRACE("(%p)\n", This
);
532 EnterCriticalSection(&This
->parent
->crst
);
537 for (i
= 0; i
< This
->nnotify
; ++i
)
538 if (This
->notify
[i
].dwOffset
== DSCBPN_OFFSET_STOP
)
540 SetEvent(This
->notify
[i
].hEventNotify
);
543 This
->playing
= This
->looping
= 0;
544 alcCaptureStop(This
->dev
);
546 LeaveCriticalSection(&This
->parent
->crst
);
550 static HRESULT WINAPI
DSCBuffer_Unlock(IDirectSoundCaptureBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
552 DSCBuffer
*This
= (DSCBuffer
*)iface
;
553 TRACE("(%p)->(%p,%u,%p,%u)\n", This
, ptr1
, len2
, ptr2
, len2
);
556 return DSERR_INVALIDPARAM
;
560 static HRESULT WINAPI
DSCBuffer_GetObjectInPath(IDirectSoundCaptureBuffer8
*iface
, REFGUID guid
, DWORD num
, REFGUID riid
, void **ppv
)
562 DSCBuffer
*This
= (DSCBuffer
*)iface
;
563 FIXME("(%p)->(%s %u %s %p) stub\n", This
, debugstr_guid(guid
), num
, debugstr_guid(riid
), ppv
);
567 static HRESULT WINAPI
DSCBuffer_GetFXStatus(IDirectSoundCaptureBuffer8
*iface
, DWORD count
, DWORD
*status
)
569 DSCBuffer
*This
= (DSCBuffer
*)iface
;
570 FIXME("(%p)->(%u %p) stub\n", This
, count
, status
);
574 static const IDirectSoundCaptureBuffer8Vtbl DSCBuffer_Vtbl
=
576 DSCBuffer_QueryInterface
,
580 DSCBuffer_GetCurrentPosition
,
583 DSCBuffer_Initialize
,
588 DSCBuffer_GetObjectInPath
,
589 DSCBuffer_GetFXStatus
592 static DSCBuffer
*get_this_from_not(IDirectSoundNotify
*iface
)
594 return (DSCBuffer
*)((char*)iface
- offsetof(DSCBuffer
,lpNotVtbl
));
597 static HRESULT WINAPI
DSCBufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
599 DSCBuffer
*This
= get_this_from_not(iface
);
600 return IDirectSoundCaptureBuffer_QueryInterface((IDirectSoundCaptureBuffer
*)This
, riid
, ppv
);
603 static ULONG WINAPI
DSCBufferNot_AddRef(IDirectSoundNotify
*iface
)
605 DSCBuffer
*This
= get_this_from_not(iface
);
608 ret
= InterlockedIncrement(&This
->not_ref
);
609 TRACE("new refcount %d\n", ret
);
613 static ULONG WINAPI
DSCBufferNot_Release(IDirectSoundNotify
*iface
)
615 DSCBuffer
*This
= get_this_from_not(iface
);
616 CRITICAL_SECTION
*crst
= &This
->parent
->crst
;
619 EnterCriticalSection(crst
);
620 ret
= InterlockedDecrement(&This
->not_ref
);
621 TRACE("new refcount %d\n", ret
);
622 if (!ret
&& !This
->ref
)
623 DSCBuffer_Destroy(This
);
624 LeaveCriticalSection(crst
);
628 static HRESULT WINAPI
DSCBufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
630 DSCBuffer
*This
= get_this_from_not(iface
);
631 DSBPOSITIONNOTIFY
*nots
;
635 EnterCriticalSection(&This
->parent
->crst
);
636 hr
= DSERR_INVALIDPARAM
;
637 if (count
&& !notifications
)
640 hr
= DSCBuffer_GetStatus((IDirectSoundCaptureBuffer8
*)This
, &state
);
644 hr
= DSERR_INVALIDCALL
;
645 if (state
& DSCBSTATUS_CAPTURING
)
650 HeapFree(GetProcessHeap(), 0, This
->notify
);
657 hr
= DSERR_INVALIDPARAM
;
658 for (i
= 0; i
< count
; ++i
)
660 if (notifications
[i
].dwOffset
>= This
->buf_size
661 && notifications
[i
].dwOffset
!= DSCBPN_OFFSET_STOP
)
665 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
668 memcpy(nots
, notifications
, count
*sizeof(*nots
));
669 HeapFree(GetProcessHeap(), 0, This
->notify
);
671 This
->nnotify
= count
;
676 LeaveCriticalSection(&This
->parent
->crst
);
680 static const IDirectSoundNotifyVtbl DSCNot_Vtbl
=
682 DSCBufferNot_QueryInterface
,
684 DSCBufferNot_Release
,
685 DSCBufferNot_SetNotificationPositions
688 HRESULT
DSOUND_CaptureCreate8(REFIID riid
, IDirectSoundCapture8
**cap
)
690 DSCImpl
*This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
693 return DSERR_OUTOFMEMORY
;
694 This
->lpVtbl
= &DSC_Vtbl
;
696 InitializeCriticalSection(&This
->crst
);
697 This
->crst
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DSCImpl.crst");
698 if (FAILED(IUnknown_QueryInterface((IUnknown
*)This
, riid
, (void**)cap
)))
700 DSCImpl_Destroy(This
);
701 return E_NOINTERFACE
;
706 static void DSCImpl_Destroy(DSCImpl
*This
)
710 timeKillEvent(This
->timer_id
);
711 timeEndPeriod(This
->timer_res
);
713 EnterCriticalSection(&This
->crst
);
715 DSCBuffer_Destroy(This
->buf
);
716 LeaveCriticalSection(&This
->crst
);
717 HeapFree(GetProcessHeap(), 0, This
->device
);
718 This
->crst
.DebugInfo
->Spare
[0] = 0;
719 DeleteCriticalSection(&This
->crst
);
720 HeapFree(GetProcessHeap(), 0, This
);
723 static HRESULT WINAPI
DSCImpl_QueryInterface(IDirectSoundCapture
*iface
, REFIID riid
, void **ppv
)
726 if (IsEqualIID(riid
, &IID_IUnknown
)
727 || IsEqualIID(riid
, &IID_IDirectSoundCapture
))
732 return E_NOINTERFACE
;
733 IUnknown_AddRef((IUnknown
*)*ppv
);
737 static ULONG WINAPI
DSCImpl_AddRef(IDirectSoundCapture8
*iface
)
739 DSCImpl
*This
= (DSCImpl
*)iface
;
741 ref
= InterlockedIncrement(&This
->ref
);
742 TRACE("Reference count incremented to %i\n", ref
);
746 static ULONG WINAPI
DSCImpl_Release(IDirectSoundCapture8
*iface
)
748 DSCImpl
*This
= (DSCImpl
*)iface
;
750 ref
= InterlockedDecrement(&This
->ref
);
751 TRACE("Reference count decremented to %i\n", ref
);
753 DSCImpl_Destroy(This
);
757 static HRESULT WINAPI
DSCImpl_CreateCaptureBuffer(IDirectSoundCapture8
*iface
, const DSCBUFFERDESC
*desc
, IDirectSoundCaptureBuffer
**ppv
, IUnknown
*unk
)
759 DSCImpl
*This
= (DSCImpl
*)iface
;
761 TRACE("(%p)->(%p,%p,%p)\n", This
, desc
, ppv
, unk
);
765 WARN("Aggregation isn't supported\n");
766 return DSERR_NOAGGREGATION
;
769 if (!desc
|| desc
->dwSize
< sizeof(DSCBUFFERDESC1
))
771 WARN("Passed invalid description %p %u\n", desc
, desc
?desc
->dwSize
:0);
772 return DSERR_INVALIDPARAM
;
776 WARN("Passed null pointer\n");
777 return DSERR_INVALIDPARAM
;
781 EnterCriticalSection(&This
->crst
);
784 hr
= DSERR_UNINITIALIZED
;
785 WARN("Not initialized\n");
790 hr
= DSERR_ALLOCATED
;
791 WARN("Capture buffer already allocated\n");
795 hr
= DSCBuffer_Create(&This
->buf
);
798 hr
= IDirectSoundCaptureBuffer_Initialize((IDirectSoundCaptureBuffer
*)This
->buf
, iface
, desc
);
801 DSCBuffer_Destroy(This
->buf
);
805 *ppv
= (IDirectSoundCaptureBuffer
*)This
->buf
;
807 LeaveCriticalSection(&This
->crst
);
811 static HRESULT WINAPI
DSCImpl_GetCaps(IDirectSoundCapture8
*iface
, DSCCAPS
*caps
)
813 DSCImpl
*This
= (DSCImpl
*)iface
;
814 TRACE("(%p,%p)\n", This
, caps
);
817 WARN("Not initialized\n");
818 return DSERR_UNINITIALIZED
;
822 WARN("Caps is null\n");
823 return DSERR_INVALIDPARAM
;
826 if (caps
->dwSize
< sizeof(*caps
)) {
827 WARN("Invalid size %d\n", caps
->dwSize
);
828 return DSERR_INVALIDPARAM
;
832 /* Support all WAVE_FORMAT formats specified in mmsystem.h */
833 caps
->dwFormats
= 0x000fffff;
834 caps
->dwChannels
= 2;
839 static HRESULT WINAPI
DSCImpl_Initialize(IDirectSoundCapture8
*iface
, const GUID
*devguid
)
841 DSCImpl
*This
= (DSCImpl
*)iface
;
843 const ALCchar
*devs
, *drv_name
;
846 TRACE("(%p,%p)\n", This
, devguid
);
850 ERR("OpenAL not loaded!\n");
851 return DSERR_NODRIVER
;
855 WARN("Already initialized\n");
856 return DSERR_ALREADYINITIALIZED
;
860 devguid
= &DSDEVID_DefaultCapture
;
862 hr
= GetDeviceID(devguid
, &guid
);
864 return DSERR_INVALIDPARAM
;
867 EnterCriticalSection(&This
->crst
);
868 EnterCriticalSection(&openal_crst
);
869 devs
= DSOUND_getcapturedevicestrings();
873 if (memcmp(devguid
, &DSOUND_capture_guid
, sizeof(GUID
)-1)
876 WARN("No driver found\n");
882 const ALCchar
*str
= devs
;
885 str
+= strlen(str
) + 1;
888 WARN("No driver string found\n");
897 This
->device
= HeapAlloc(GetProcessHeap(), 0, strlen(drv_name
)+1);
900 WARN("Out of memory to allocate %s\n", drv_name
);
903 strcpy(This
->device
, drv_name
);
907 LeaveCriticalSection(&openal_crst
);
908 LeaveCriticalSection(&This
->crst
);
912 static const IDirectSoundCaptureVtbl DSC_Vtbl
=
914 DSCImpl_QueryInterface
,
917 DSCImpl_CreateCaptureBuffer
,