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 DSCImpl DSCImpl
;
68 typedef struct DSCBuffer DSCBuffer
;
71 IDirectSoundCapture IDirectSoundCapture_iface
;
78 CRITICAL_SECTION crst
;
82 IDirectSoundCaptureBuffer8 IDirectSoundCaptureBuffer8_iface
;
83 IDirectSoundNotify IDirectSoundNotify_iface
;
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
));
107 if (!This
) return E_OUTOFMEMORY
;
109 This
->IDirectSoundCaptureBuffer8_iface
.lpVtbl
= &DSCBuffer_Vtbl
;
110 This
->IDirectSoundNotify_iface
.lpVtbl
= &DSCNot_Vtbl
;
117 static void trigger_notifies(DSCBuffer
*buf
, DWORD lastpos
, DWORD curpos
)
121 if (lastpos
== curpos
)
124 for (i
= 0; i
< buf
->nnotify
; ++i
)
126 DSBPOSITIONNOTIFY
*not = &buf
->notify
[i
];
127 HANDLE event
= not->hEventNotify
;
128 DWORD ofs
= not->dwOffset
;
130 if (ofs
== DSCBPN_OFFSET_STOP
)
133 /* Wraparound case */
134 if (curpos
< lastpos
)
136 if (ofs
< curpos
|| ofs
>= lastpos
)
142 if (ofs
>= lastpos
&& ofs
< curpos
)
147 static void CALLBACK
DSCBuffer_timer(UINT timerID
, UINT msg
, DWORD_PTR dwUser
,
148 DWORD_PTR dw1
, DWORD_PTR dw2
)
150 DSCImpl
*This
= (DSCImpl
*)dwUser
;
158 EnterCriticalSection(&This
->crst
);
160 if (!buf
|| !buf
->dev
|| !buf
->playing
)
163 alcGetIntegerv(buf
->dev
, ALC_CAPTURE_SAMPLES
, 1, &avail
);
166 avail
*= buf
->format
->nBlockAlign
;
167 if (avail
+ buf
->pos
> buf
->buf_size
)
168 avail
= buf
->buf_size
- buf
->pos
;
170 alcCaptureSamples(buf
->dev
, buf
->buf
+ buf
->pos
, avail
/buf
->format
->nBlockAlign
);
171 trigger_notifies(buf
, buf
->pos
, buf
->pos
+ avail
);
174 if (buf
->pos
== buf
->buf_size
)
178 IDirectSoundCaptureBuffer_Stop((IDirectSoundCaptureBuffer
*)buf
);
182 alcGetIntegerv(buf
->dev
, ALC_CAPTURE_SAMPLES
, 1, &avail
);
183 avail
*= buf
->format
->nBlockAlign
;
184 if ((ALCuint
)avail
>= buf
->buf_size
)
186 ERR("TOO MUCH AVAIL: %u/%u\n", avail
, buf
->buf_size
);
187 avail
= buf
->buf_size
;
192 alcCaptureSamples(buf
->dev
, buf
->buf
+ buf
->pos
, avail
/buf
->format
->nBlockAlign
);
193 trigger_notifies(buf
, buf
->pos
, buf
->pos
+ avail
);
201 LeaveCriticalSection(&This
->crst
);
205 static void DSCBuffer_starttimer(DSCImpl
*prim
)
208 ALint refresh
= FAKE_REFRESH_COUNT
;
209 DWORD triggertime
, res
= DS_TIME_RES
;
214 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
215 triggertime
= 1000 / refresh
;
216 if (triggertime
< time
.wPeriodMin
)
217 triggertime
= time
.wPeriodMin
;
218 TRACE("Calling timer every %u ms for %i refreshes per second\n", triggertime
, refresh
);
219 if (res
< time
.wPeriodMin
)
220 res
= time
.wPeriodMin
;
221 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
222 WARN("Could not set minimum resolution, don't expect sound\n");
223 prim
->timer_res
= res
;
224 prim
->timer_id
= timeSetEvent(triggertime
, res
, DSCBuffer_timer
, (DWORD_PTR
)prim
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
227 static void DSCBuffer_Destroy(DSCBuffer
*This
)
232 alcCaptureStop(This
->dev
);
233 alcCaptureCloseDevice(This
->dev
);
236 This
->parent
->buf
= NULL
;
237 HeapFree(GetProcessHeap(), 0, This
->notify
);
238 HeapFree(GetProcessHeap(), 0, This
->format
);
239 HeapFree(GetProcessHeap(), 0, This
->buf
);
240 HeapFree(GetProcessHeap(), 0, This
);
243 static inline DSCBuffer
*impl_from_IDirectSoundCaptureBuffer8(IDirectSoundCaptureBuffer8
*iface
)
245 return CONTAINING_RECORD(iface
, DSCBuffer
, IDirectSoundCaptureBuffer8_iface
);
248 static HRESULT WINAPI
DSCBuffer_QueryInterface(IDirectSoundCaptureBuffer8
*iface
, REFIID riid
, void **ppv
)
250 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
252 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
258 if (IsEqualIID(riid
, &IID_IDirectSoundNotify
))
259 *ppv
= &This
->IDirectSoundNotify_iface
;
260 else if (IsEqualIID(riid
, &IID_IUnknown
) ||
261 IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer
) ||
262 IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer8
))
263 *ppv
= &This
->IDirectSoundCaptureBuffer8_iface
;
266 return E_NOINTERFACE
;
267 IUnknown_AddRef((IUnknown
*)*ppv
);
271 static ULONG WINAPI
DSCBuffer_AddRef(IDirectSoundCaptureBuffer8
*iface
)
273 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
276 ref
= InterlockedIncrement(&This
->ref
);
277 TRACE("Reference count incremented to %i\n", ref
);
282 static ULONG WINAPI
DSCBuffer_Release(IDirectSoundCaptureBuffer8
*iface
)
284 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
285 CRITICAL_SECTION
*crst
= &This
->parent
->crst
;
288 EnterCriticalSection(crst
);
289 ref
= InterlockedDecrement(&This
->ref
);
290 TRACE("Reference count decremented to %i\n", ref
);
291 if (!ref
&& !This
->not_ref
)
292 DSCBuffer_Destroy(This
);
293 LeaveCriticalSection(crst
);
298 static HRESULT WINAPI
DSCBuffer_GetCaps(IDirectSoundCaptureBuffer8
*iface
, DSCBCAPS
*caps
)
300 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
302 if (!caps
|| caps
->dwSize
< sizeof(*caps
))
303 return DSERR_INVALIDPARAM
;
304 caps
->dwSize
= sizeof(*caps
);
306 caps
->dwBufferBytes
= This
->buf_size
;
310 static HRESULT WINAPI
DSCBuffer_GetCurrentPosition(IDirectSoundCaptureBuffer8
*iface
, DWORD
*cappos
, DWORD
*readpos
)
312 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
315 EnterCriticalSection(&This
->parent
->crst
);
319 pos2
= This
->format
->nSamplesPerSec
/ 100;
320 pos2
*= This
->format
->nBlockAlign
;
322 if (!This
->looping
&& pos2
>= This
->buf_size
)
325 pos2
%= This
->buf_size
;
329 LeaveCriticalSection(&This
->parent
->crst
);
331 if(cappos
) *cappos
= pos1
;
332 if(readpos
) *readpos
= pos2
;
337 static HRESULT WINAPI
DSCBuffer_GetFormat(IDirectSoundCaptureBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD size
, DWORD
*written
)
339 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
340 TRACE("(%p,%p,%u,%p)\n", This
, wfx
, size
, written
);
342 if (size
> sizeof(WAVEFORMATEX
) + This
->format
->cbSize
)
343 size
= sizeof(WAVEFORMATEX
) + This
->format
->cbSize
;
347 CopyMemory(wfx
, This
->format
, size
);
352 *written
= sizeof(WAVEFORMATEX
) + This
->format
->cbSize
;
354 return DSERR_INVALIDPARAM
;
359 static HRESULT WINAPI
DSCBuffer_GetStatus(IDirectSoundCaptureBuffer8
*iface
, DWORD
*status
)
361 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
362 TRACE("(%p)->(%p)\n", This
, status
);
365 return DSERR_INVALIDPARAM
;
366 EnterCriticalSection(&This
->parent
->crst
);
370 *status
|= DSCBSTATUS_CAPTURING
;
372 *status
|= DSCBSTATUS_LOOPING
;
374 LeaveCriticalSection(&This
->parent
->crst
);
379 static HRESULT WINAPI
DSCBuffer_Initialize(IDirectSoundCaptureBuffer8
*iface
, IDirectSoundCapture
*parent
, const DSCBUFFERDESC
*desc
)
381 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
382 WAVEFORMATEX
*format
;
383 ALenum buf_format
= -1;
386 return DSERR_ALREADYINITIALIZED
;
387 This
->parent
= (DSCImpl
*)parent
;
389 if (!desc
->lpwfxFormat
)
390 return DSERR_INVALIDPARAM
;
392 format
= desc
->lpwfxFormat
;
393 if (format
->nChannels
> 2)
395 WARN("nChannels > 2 not supported for recording\n");
396 return DSERR_INVALIDPARAM
;
400 This
->format
= HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE
));
402 return DSERR_OUTOFMEMORY
;
404 if (format
->wFormatTag
== WAVE_FORMAT_PCM
||
405 format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
407 if (format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
409 WAVEFORMATEXTENSIBLE
*wfe
= (WAVEFORMATEXTENSIBLE
*)format
;
410 if (format
->cbSize
< sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
))
411 return DSERR_INVALIDPARAM
;
412 else if (format
->cbSize
> sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
)
413 && format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
414 return DSERR_CONTROLUNAVAIL
;
415 else if (!IsEqualGUID(&wfe
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
))
416 return DSERR_BADFORMAT
;
419 if (format
->nChannels
== 1)
421 switch (format
->wBitsPerSample
)
423 case 8: buf_format
= AL_FORMAT_MONO8
; break;
424 case 16: buf_format
= AL_FORMAT_MONO16
; break;
426 WARN("Unsupported bpp %u\n", format
->wBitsPerSample
);
427 return DSERR_BADFORMAT
;
430 else if (format
->nChannels
== 2)
432 switch (format
->wBitsPerSample
)
434 case 8: buf_format
= AL_FORMAT_STEREO8
; break;
435 case 16: buf_format
= AL_FORMAT_STEREO16
; break;
437 WARN("Unsupported bpp %u\n", format
->wBitsPerSample
);
438 return DSERR_BADFORMAT
;
441 memcpy(This
->format
, format
, sizeof(*format
) + format
->cbSize
);
442 if (format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
443 This
->format
->cbSize
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
445 This
->format
->cbSize
= 0;
446 This
->format
->nBlockAlign
= This
->format
->wBitsPerSample
* This
->format
->nChannels
/ 8;
447 This
->format
->nAvgBytesPerSec
= This
->format
->nSamplesPerSec
* This
->format
->nBlockAlign
;
449 else if (format
->wFormatTag
)
450 WARN("Unhandled formattag %x\n", format
->wFormatTag
);
452 This
->buf_size
= desc
->dwBufferBytes
;
455 WARN("Could not get OpenAL format\n");
456 return DSERR_INVALIDPARAM
;
459 This
->dev
= alcCaptureOpenDevice(This
->parent
->device
, This
->format
->nSamplesPerSec
, buf_format
, This
->buf_size
/ This
->format
->nBlockAlign
);
462 ERR("couldn't open device %s %x@%u, reason: %04x\n", This
->parent
->device
, buf_format
, This
->format
->nSamplesPerSec
, alcGetError(NULL
));
463 return DSERR_INVALIDPARAM
;
466 This
->buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->buf_size
);
469 alcCaptureCloseDevice(This
->dev
);
470 WARN("Out of memory\n");
471 return DSERR_INVALIDPARAM
;
477 static HRESULT WINAPI
DSCBuffer_Lock(IDirectSoundCaptureBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
479 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
482 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, %#x)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
484 EnterCriticalSection(&This
->parent
->crst
);
485 hr
= DSERR_INVALIDPARAM
;
487 if(ptr1
) *ptr1
= NULL
;
489 if(ptr2
) *ptr2
= NULL
;
492 if (ofs
>= This
->buf_size
)
494 WARN("Invalid ofs %u\n", ofs
);
499 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
502 if((flags
&DSCBLOCK_ENTIREBUFFER
))
503 bytes
= This
->buf_size
;
504 else if(bytes
> This
->buf_size
)
506 WARN("Invalid size %u\n", bytes
);
510 if (ofs
+ bytes
>= This
->buf_size
)
512 *len1
= This
->buf_size
- ofs
;
513 remain
= bytes
- *len1
;
520 *ptr1
= This
->buf
+ ofs
;
522 if (ptr2
&& len2
&& remain
)
530 LeaveCriticalSection(&This
->parent
->crst
);
534 static HRESULT WINAPI
DSCBuffer_Start(IDirectSoundCaptureBuffer8
*iface
, DWORD flags
)
536 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
537 TRACE("(%p)->(%08x)\n", This
, flags
);
539 EnterCriticalSection(&This
->parent
->crst
);
542 DSCBuffer_starttimer(This
->parent
);
544 alcCaptureStart(This
->dev
);
546 This
->looping
= !!(flags
& DSCBSTART_LOOPING
);
547 LeaveCriticalSection(&This
->parent
->crst
);
551 static HRESULT WINAPI
DSCBuffer_Stop(IDirectSoundCaptureBuffer8
*iface
)
553 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
554 TRACE("(%p)\n", This
);
556 EnterCriticalSection(&This
->parent
->crst
);
561 for (i
= 0; i
< This
->nnotify
; ++i
)
562 if (This
->notify
[i
].dwOffset
== DSCBPN_OFFSET_STOP
)
564 SetEvent(This
->notify
[i
].hEventNotify
);
567 This
->playing
= This
->looping
= 0;
568 alcCaptureStop(This
->dev
);
570 LeaveCriticalSection(&This
->parent
->crst
);
574 static HRESULT WINAPI
DSCBuffer_Unlock(IDirectSoundCaptureBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
576 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
577 TRACE("(%p)->(%p,%u,%p,%u)\n", This
, ptr1
, len1
, ptr2
, len2
);
580 return DSERR_INVALIDPARAM
;
584 static HRESULT WINAPI
DSCBuffer_GetObjectInPath(IDirectSoundCaptureBuffer8
*iface
, REFGUID guid
, DWORD num
, REFGUID riid
, void **ppv
)
586 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
587 FIXME("(%p)->(%s %u %s %p) stub\n", This
, debugstr_guid(guid
), num
, debugstr_guid(riid
), ppv
);
591 static HRESULT WINAPI
DSCBuffer_GetFXStatus(IDirectSoundCaptureBuffer8
*iface
, DWORD count
, DWORD
*status
)
593 DSCBuffer
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
594 FIXME("(%p)->(%u %p) stub\n", This
, count
, status
);
598 static const IDirectSoundCaptureBuffer8Vtbl DSCBuffer_Vtbl
=
600 DSCBuffer_QueryInterface
,
604 DSCBuffer_GetCurrentPosition
,
607 DSCBuffer_Initialize
,
612 DSCBuffer_GetObjectInPath
,
613 DSCBuffer_GetFXStatus
616 static inline DSCBuffer
*impl_from_IDirectSoundNotify(IDirectSoundNotify
*iface
)
618 return CONTAINING_RECORD(iface
, DSCBuffer
, IDirectSoundNotify_iface
);
621 static HRESULT WINAPI
DSCBufferNot_QueryInterface(IDirectSoundNotify
*iface
, REFIID riid
, void **ppv
)
623 DSCBuffer
*This
= impl_from_IDirectSoundNotify(iface
);
624 return IDirectSoundCaptureBuffer_QueryInterface((IDirectSoundCaptureBuffer
*)This
, riid
, ppv
);
627 static ULONG WINAPI
DSCBufferNot_AddRef(IDirectSoundNotify
*iface
)
629 DSCBuffer
*This
= impl_from_IDirectSoundNotify(iface
);
632 ret
= InterlockedIncrement(&This
->not_ref
);
633 TRACE("new refcount %d\n", ret
);
637 static ULONG WINAPI
DSCBufferNot_Release(IDirectSoundNotify
*iface
)
639 DSCBuffer
*This
= impl_from_IDirectSoundNotify(iface
);
640 CRITICAL_SECTION
*crst
= &This
->parent
->crst
;
643 EnterCriticalSection(crst
);
644 ret
= InterlockedDecrement(&This
->not_ref
);
645 TRACE("new refcount %d\n", ret
);
646 if (!ret
&& !This
->ref
)
647 DSCBuffer_Destroy(This
);
648 LeaveCriticalSection(crst
);
653 static HRESULT WINAPI
DSCBufferNot_SetNotificationPositions(IDirectSoundNotify
*iface
, DWORD count
, const DSBPOSITIONNOTIFY
*notifications
)
655 DSCBuffer
*This
= impl_from_IDirectSoundNotify(iface
);
656 DSBPOSITIONNOTIFY
*nots
;
660 EnterCriticalSection(&This
->parent
->crst
);
661 hr
= DSERR_INVALIDPARAM
;
662 if (count
&& !notifications
)
665 hr
= DSCBuffer_GetStatus(&This
->IDirectSoundCaptureBuffer8_iface
, &state
);
669 hr
= DSERR_INVALIDCALL
;
670 if (state
& DSCBSTATUS_CAPTURING
)
675 HeapFree(GetProcessHeap(), 0, This
->notify
);
682 hr
= DSERR_INVALIDPARAM
;
683 for (i
= 0; i
< count
; ++i
)
685 if (notifications
[i
].dwOffset
>= This
->buf_size
686 && notifications
[i
].dwOffset
!= DSCBPN_OFFSET_STOP
)
690 nots
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(*nots
));
693 memcpy(nots
, notifications
, count
*sizeof(*nots
));
694 HeapFree(GetProcessHeap(), 0, This
->notify
);
696 This
->nnotify
= count
;
701 LeaveCriticalSection(&This
->parent
->crst
);
705 static const IDirectSoundNotifyVtbl DSCNot_Vtbl
=
707 DSCBufferNot_QueryInterface
,
709 DSCBufferNot_Release
,
710 DSCBufferNot_SetNotificationPositions
713 HRESULT
DSOUND_CaptureCreate8(REFIID riid
, IDirectSoundCapture8
**cap
)
719 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
720 if(!This
) return DSERR_OUTOFMEMORY
;
722 This
->IDirectSoundCapture_iface
.lpVtbl
= &DSC_Vtbl
;
724 InitializeCriticalSection(&This
->crst
);
725 This
->crst
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DSCImpl.crst");
727 if(FAILED(IDirectSoundCapture_QueryInterface(&This
->IDirectSoundCapture_iface
, riid
, (void**)cap
)))
729 DSCImpl_Destroy(This
);
730 return E_NOINTERFACE
;
735 static void DSCImpl_Destroy(DSCImpl
*This
)
739 timeKillEvent(This
->timer_id
);
740 timeEndPeriod(This
->timer_res
);
743 EnterCriticalSection(&This
->crst
);
745 DSCBuffer_Destroy(This
->buf
);
746 LeaveCriticalSection(&This
->crst
);
748 HeapFree(GetProcessHeap(), 0, This
->device
);
750 This
->crst
.DebugInfo
->Spare
[0] = 0;
751 DeleteCriticalSection(&This
->crst
);
753 HeapFree(GetProcessHeap(), 0, This
);
756 static HRESULT WINAPI
DSCImpl_QueryInterface(IDirectSoundCapture
*iface
, REFIID riid
, void **ppv
)
759 if(IsEqualIID(riid
, &IID_IUnknown
) ||
760 IsEqualIID(riid
, &IID_IDirectSoundCapture
))
764 return E_NOINTERFACE
;
765 IUnknown_AddRef((IUnknown
*)*ppv
);
769 static ULONG WINAPI
DSCImpl_AddRef(IDirectSoundCapture8
*iface
)
771 DSCImpl
*This
= (DSCImpl
*)iface
;
774 ref
= InterlockedIncrement(&This
->ref
);
775 TRACE("Reference count incremented to %i\n", ref
);
780 static ULONG WINAPI
DSCImpl_Release(IDirectSoundCapture8
*iface
)
782 DSCImpl
*This
= (DSCImpl
*)iface
;
785 ref
= InterlockedDecrement(&This
->ref
);
786 TRACE("Reference count decremented to %i\n", ref
);
788 DSCImpl_Destroy(This
);
793 static HRESULT WINAPI
DSCImpl_CreateCaptureBuffer(IDirectSoundCapture8
*iface
, const DSCBUFFERDESC
*desc
, IDirectSoundCaptureBuffer
**ppv
, IUnknown
*unk
)
795 DSCImpl
*This
= (DSCImpl
*)iface
;
797 TRACE("(%p)->(%p,%p,%p)\n", This
, desc
, ppv
, unk
);
801 WARN("Aggregation isn't supported\n");
802 return DSERR_NOAGGREGATION
;
805 if (!desc
|| desc
->dwSize
< sizeof(DSCBUFFERDESC1
))
807 WARN("Passed invalid description %p %u\n", desc
, desc
?desc
->dwSize
:0);
808 return DSERR_INVALIDPARAM
;
812 WARN("Passed null pointer\n");
813 return DSERR_INVALIDPARAM
;
817 EnterCriticalSection(&This
->crst
);
820 hr
= DSERR_UNINITIALIZED
;
821 WARN("Not initialized\n");
826 hr
= DSERR_ALLOCATED
;
827 WARN("Capture buffer already allocated\n");
831 hr
= DSCBuffer_Create(&This
->buf
);
834 hr
= IDirectSoundCaptureBuffer_Initialize((IDirectSoundCaptureBuffer
*)This
->buf
, iface
, desc
);
837 DSCBuffer_Destroy(This
->buf
);
841 *ppv
= (IDirectSoundCaptureBuffer
*)This
->buf
;
843 LeaveCriticalSection(&This
->crst
);
847 static HRESULT WINAPI
DSCImpl_GetCaps(IDirectSoundCapture8
*iface
, DSCCAPS
*caps
)
849 DSCImpl
*This
= (DSCImpl
*)iface
;
850 TRACE("(%p,%p)\n", This
, caps
);
853 WARN("Not initialized\n");
854 return DSERR_UNINITIALIZED
;
858 WARN("Caps is null\n");
859 return DSERR_INVALIDPARAM
;
862 if (caps
->dwSize
< sizeof(*caps
)) {
863 WARN("Invalid size %d\n", caps
->dwSize
);
864 return DSERR_INVALIDPARAM
;
868 /* Support all WAVE_FORMAT formats specified in mmsystem.h */
869 caps
->dwFormats
= 0x000fffff;
870 caps
->dwChannels
= 2;
875 static HRESULT WINAPI
DSCImpl_Initialize(IDirectSoundCapture8
*iface
, const GUID
*devguid
)
877 DSCImpl
*This
= (DSCImpl
*)iface
;
879 const ALCchar
*devs
, *drv_name
;
882 TRACE("(%p,%p)\n", This
, devguid
);
886 ERR("OpenAL not loaded!\n");
887 return DSERR_NODRIVER
;
891 WARN("Already initialized\n");
892 return DSERR_ALREADYINITIALIZED
;
896 devguid
= &DSDEVID_DefaultCapture
;
898 hr
= GetDeviceID(devguid
, &guid
);
900 return DSERR_INVALIDPARAM
;
903 EnterCriticalSection(&This
->crst
);
904 EnterCriticalSection(&openal_crst
);
905 devs
= DSOUND_getcapturedevicestrings();
909 if(memcmp(devguid
, &DSOUND_capture_guid
, sizeof(GUID
)-1) ||
912 WARN("No driver found\n");
918 const ALCchar
*str
= devs
;
921 str
+= strlen(str
) + 1;
924 WARN("No driver string found\n");
933 This
->device
= HeapAlloc(GetProcessHeap(), 0, strlen(drv_name
)+1);
936 WARN("Out of memory to allocate %s\n", drv_name
);
939 strcpy(This
->device
, drv_name
);
943 LeaveCriticalSection(&openal_crst
);
944 LeaveCriticalSection(&This
->crst
);
948 static const IDirectSoundCaptureVtbl DSC_Vtbl
=
950 DSCImpl_QueryInterface
,
953 DSCImpl_CreateCaptureBuffer
,