3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * Implement FX support.
29 #define NONAMELESSSTRUCT
30 #define NONAMELESSUNION
39 #include "wine/debug.h"
41 #include "dsound_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
46 typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl
;
48 typedef struct IDirectSoundCaptureImpl
50 IDirectSoundCapture IDirectSoundCapture_iface
;
53 IDirectSoundCaptureBufferImpl
*buf
;
54 CRITICAL_SECTION crst
;
58 } IDirectSoundCaptureImpl
;
60 static void IDirectSoundCaptureImpl_Destroy(IDirectSoundCaptureImpl
*This
);
62 struct IDirectSoundCaptureBufferImpl
64 IDirectSoundCaptureBuffer8 IDirectSoundCaptureBuffer8_iface
;
66 IDirectSoundCaptureImpl
*parent
;
68 IAudioCaptureClient
*cap_dev
;
72 DSBPOSITIONNOTIFY
*notify
;
76 BOOL playing
, looping
;
79 static void IDirectSoundCaptureBufferImpl_Destroy(IDirectSoundCaptureBufferImpl
*This
);
81 static IDirectSoundCaptureBufferImpl
*impl_from_IDirectSoundCaptureBuffer8(IDirectSoundCaptureBuffer8
*iface
)
83 return CONTAINING_RECORD(iface
, IDirectSoundCaptureBufferImpl
, IDirectSoundCaptureBuffer8_iface
);
86 static IDirectSoundCaptureImpl
*impl_from_IDirectSoundCapture(IDirectSoundCapture
*iface
)
88 return CONTAINING_RECORD(iface
, IDirectSoundCaptureImpl
, IDirectSoundCapture_iface
);
91 static void trigger_notifies(IDirectSoundCaptureBufferImpl
*buf
, DWORD lastpos
, DWORD curpos
)
96 static void CALLBACK
IDirectSoundCaptureBufferImpl_timer(UINT timerID
, UINT msg
, DWORD_PTR dwUser
, DWORD_PTR dw1
, DWORD_PTR dw2
)
98 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)dwUser
;
99 IDirectSoundCaptureBufferImpl
*buf
;
102 EnterCriticalSection(&This
->crst
);
104 if (!buf
|| !buf
->dev
|| !buf
->playing
)
107 IAudioCaptureClient_GetNextPacketSize(buf
->cap_dev
, &avail
);
114 DWORD block
= buf
->format
->nBlockAlign
;
116 IAudioCaptureClient_GetBuffer(buf
->cap_dev
, &data
, &read
, &flags
, &pos
, 0);
117 if (read
* block
+ buf
->pos
>= buf
->buf_size
)
121 trigger_notifies(buf
, buf
->pos
, 0);
122 memcpy(buf
->buf
+ buf
->pos
, data
, buf
->buf_size
- buf
->pos
);
124 IAudioCaptureClient_ReleaseBuffer(buf
->cap_dev
, read
);
125 IDirectSoundCaptureBuffer8_Stop(&buf
->IDirectSoundCaptureBuffer8_iface
);
129 DWORD firstpart
= buf
->buf_size
- buf
->pos
, oldpos
= buf
->pos
;
130 memcpy(buf
->buf
+ buf
->pos
, data
, firstpart
);
131 buf
->pos
= read
* block
- firstpart
;
132 memcpy(buf
->buf
, data
+ firstpart
, buf
->pos
);
133 trigger_notifies(buf
, oldpos
, buf
->pos
);
134 IAudioCaptureClient_ReleaseBuffer(buf
->cap_dev
, read
);
137 memcpy(buf
->buf
+ buf
->pos
, data
, read
* block
);
138 trigger_notifies(buf
, buf
->pos
, buf
->pos
+ read
* block
);
139 buf
->pos
+= read
* block
;
140 IAudioCaptureClient_ReleaseBuffer(buf
->cap_dev
, read
);
145 LeaveCriticalSection(&This
->crst
);
149 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_QueryInterface(IDirectSoundCaptureBuffer8
*iface
, REFIID riid
, void **ppv
)
151 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
154 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), ppv
);
156 if (IsEqualIID(riid
, &IID_IUnknown
) ||
157 IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer
) ||
158 (This
->parent
->is_8
&& IsEqualIID(riid
, &IID_IDirectSoundCaptureBuffer8
)))
159 *ppv
= &This
->IDirectSoundCaptureBuffer8_iface
;
161 return E_NOINTERFACE
;
162 IUnknown_AddRef((IUnknown
*)*ppv
);
166 static ULONG WINAPI
IDirectSoundCaptureBufferImpl_AddRef(IDirectSoundCaptureBuffer8
*iface
)
168 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
170 ref
= InterlockedIncrement(&This
->ref
);
171 TRACE("Reference count incremented to %i\n", ref
);
175 static ULONG WINAPI
IDirectSoundCaptureBufferImpl_Release(IDirectSoundCaptureBuffer8
*iface
)
177 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
179 ref
= InterlockedDecrement(&This
->ref
);
180 TRACE("Reference count decremented to %i\n", ref
);
182 IDirectSoundCaptureBufferImpl_Destroy(This
);
186 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetCaps(IDirectSoundCaptureBuffer8
*iface
, DSCBCAPS
*caps
)
188 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
190 if (!caps
|| caps
->dwSize
< sizeof(*caps
))
191 return DSERR_INVALIDPARAM
;
192 caps
->dwSize
= sizeof(*caps
);
194 caps
->dwBufferBytes
= This
->buf_size
;
198 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetCurrentPosition(IDirectSoundCaptureBuffer8
*iface
, DWORD
*cappos
, DWORD
*readpos
)
200 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
202 TRACE("(%p)->(%p, %p)\n", This
, cappos
, readpos
);
203 EnterCriticalSection(&This
->parent
->crst
);
207 pos2
= This
->format
->nSamplesPerSec
/ 100;
208 pos2
*= This
->format
->nBlockAlign
;
210 if (!This
->looping
&& pos2
> This
->buf_size
)
213 pos2
%= This
->buf_size
;
217 pos2
%= This
->buf_size
;
218 LeaveCriticalSection(&This
->parent
->crst
);
219 TRACE("Reporting %u %u\n", pos1
, pos2
);
227 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetFormat(IDirectSoundCaptureBuffer8
*iface
, WAVEFORMATEX
*wfx
, DWORD size
, DWORD
*written
)
229 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
230 TRACE("(%p,%p,%u,%p)\n", This
, wfx
, size
, written
);
232 if (size
> sizeof(WAVEFORMATEX
) + This
->format
->cbSize
)
233 size
= sizeof(WAVEFORMATEX
) + This
->format
->cbSize
;
237 CopyMemory(wfx
, This
->format
, size
);
241 *written
= sizeof(WAVEFORMATEX
) + This
->format
->cbSize
;
243 return DSERR_INVALIDPARAM
;
248 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetStatus(IDirectSoundCaptureBuffer8
*iface
, DWORD
*status
)
250 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
251 TRACE("(%p)->(%p)\n", This
, status
);
254 return DSERR_INVALIDPARAM
;
255 EnterCriticalSection(&This
->parent
->crst
);
259 *status
|= DSCBSTATUS_CAPTURING
;
261 *status
|= DSCBSTATUS_LOOPING
;
263 LeaveCriticalSection(&This
->parent
->crst
);
268 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Initialize(IDirectSoundCaptureBuffer8
*iface
, IDirectSoundCapture
*parent
, const DSCBUFFERDESC
*desc
)
270 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
271 WAVEFORMATEX
*format
;
273 IMMDevice
*dev
= NULL
;
276 return DSERR_ALREADYINITIALIZED
;
277 This
->parent
= impl_from_IDirectSoundCapture(parent
);
278 if (!desc
->lpwfxFormat
|| !desc
->dwBufferBytes
)
279 return DSERR_INVALIDPARAM
;
281 format
= desc
->lpwfxFormat
;
282 if (format
->nChannels
> 2)
284 WARN("nChannels > 2 not supported for recording\n");
285 return DSERR_INVALIDPARAM
;
289 This
->format
= HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE
));
291 return DSERR_OUTOFMEMORY
;
293 if (format
->wFormatTag
== WAVE_FORMAT_PCM
294 || format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
296 if (format
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
)
298 if (format
->cbSize
< sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
))
299 return DSERR_INVALIDPARAM
;
300 else if (format
->cbSize
> sizeof(WAVEFORMATEXTENSIBLE
)-sizeof(WAVEFORMATEX
)
301 && format
->cbSize
!= sizeof(WAVEFORMATEXTENSIBLE
))
302 return DSERR_CONTROLUNAVAIL
;
304 memcpy(This
->format
, format
, sizeof(WAVEFORMATEXTENSIBLE
));
305 This
->format
->cbSize
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
309 memcpy(This
->format
, format
, sizeof(WAVEFORMATEX
));
310 This
->format
->cbSize
= 0;
313 This
->format
->nBlockAlign
= This
->format
->wBitsPerSample
* This
->format
->nChannels
/ 8;
314 This
->format
->nAvgBytesPerSec
= This
->format
->nSamplesPerSec
* This
->format
->nBlockAlign
;
316 else if (format
->wFormatTag
)
317 WARN("Unhandled formattag %x\n", format
->wFormatTag
);
319 This
->buf_size
= desc
->dwBufferBytes
;
320 hr
= get_mmdevice(eCapture
, &This
->parent
->device
, &dev
);
322 hr
= IMMDevice_Activate(dev
, &IID_IAudioClient
, CLSCTX_ALL
, NULL
, (void**)&This
->dev
);
324 hr
= IAudioClient_Initialize(This
->dev
, AUDCLNT_SHAREMODE_SHARED
, 0, 5000000, 0, This
->format
, NULL
);
326 hr
= IAudioClient_GetService(This
->dev
, &IID_IAudioCaptureClient
, (void**)&This
->cap_dev
);
330 IUnknown_Release(This
->dev
);
333 IUnknown_Release(dev
);
334 if (hr
== AUDCLNT_E_UNSUPPORTED_FORMAT
)
336 WARN("Couldn't open device: bad format\n");
337 return DSERR_BADFORMAT
;
339 ERR("couldn't open device %s %i: %08x\n", debugstr_guid(&This
->parent
->device
), This
->format
->nSamplesPerSec
, hr
);
340 return hr
== DSERR_INVALIDPARAM
;
342 This
->buf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->buf_size
);
345 IAudioCaptureClient_Release(This
->cap_dev
);
346 IAudioClient_Release(This
->dev
);
347 WARN("Out of memory\n");
348 return DSERR_INVALIDPARAM
;
354 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Lock(IDirectSoundCaptureBuffer8
*iface
, DWORD ofs
, DWORD bytes
, void **ptr1
, DWORD
*len1
, void **ptr2
, DWORD
*len2
, DWORD flags
)
356 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
359 TRACE("(%p)->(%u, %u, %p, %p, %p, %p, %#x)\n", This
, ofs
, bytes
, ptr1
, len1
, ptr2
, len2
, flags
);
361 EnterCriticalSection(&This
->parent
->crst
);
362 hr
= DSERR_INVALIDPARAM
;
371 if (ofs
>= This
->buf_size
)
373 WARN("Invalid ofs %u\n", ofs
);
378 WARN("Invalid pointer/len %p %p\n", ptr1
, len1
);
381 if (flags
& DSCBLOCK_ENTIREBUFFER
)
382 bytes
= This
->buf_size
;
383 if (bytes
> This
->buf_size
)
385 WARN("Invalid size %u\n", bytes
);
389 if (ofs
+ bytes
>= This
->buf_size
)
391 *len1
= This
->buf_size
- ofs
;
392 remain
= bytes
- *len1
;
399 *ptr1
= This
->buf
+ ofs
;
401 if (ptr2
&& len2
&& remain
)
409 LeaveCriticalSection(&This
->parent
->crst
);
413 static void IDirectSoundCaptureBufferImpl_starttimer(IDirectSoundCaptureBufferImpl
*This
)
416 REFERENCE_TIME min_period
, default_period
;
417 DWORD triggertime
, res
= DS_TIME_RES
;
419 if (This
->parent
->timer_id
)
422 timeGetDevCaps(&time
, sizeof(TIMECAPS
));
423 IAudioClient_GetDevicePeriod(This
->dev
, &default_period
, &min_period
);
424 triggertime
= default_period
/ 10000;
425 if (triggertime
< time
.wPeriodMin
)
426 triggertime
= time
.wPeriodMin
;
427 TRACE("Calling timer every %u ms\n", triggertime
);
428 if (res
< time
.wPeriodMin
)
429 res
= time
.wPeriodMin
;
430 if (timeBeginPeriod(res
) == TIMERR_NOCANDO
)
431 WARN("Could not set minimum resolution, don't expect sound\n");
432 This
->parent
->timer_res
= res
;
433 This
->parent
->timer_id
= timeSetEvent(triggertime
, res
, IDirectSoundCaptureBufferImpl_timer
, (DWORD_PTR
)This
->parent
, TIME_PERIODIC
| TIME_KILL_SYNCHRONOUS
);
436 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Start(IDirectSoundCaptureBuffer8
*iface
, DWORD flags
)
438 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
439 TRACE("(%p)->(%08x)\n", This
, flags
);
441 EnterCriticalSection(&This
->parent
->crst
);
444 IDirectSoundCaptureBufferImpl_starttimer(This
);
446 IAudioClient_Start(This
->dev
);
448 This
->looping
= !!(flags
& DSCBSTART_LOOPING
);
449 LeaveCriticalSection(&This
->parent
->crst
);
453 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Stop(IDirectSoundCaptureBuffer8
*iface
)
455 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
456 TRACE("(%p)\n", This
);
458 EnterCriticalSection(&This
->parent
->crst
);
463 for (i
= 0; i
< This
->nnotify
; ++i
)
464 if (This
->notify
[i
].dwOffset
== DSCBPN_OFFSET_STOP
)
466 SetEvent(This
->notify
[i
].hEventNotify
);
469 This
->playing
= This
->looping
= 0;
470 IAudioClient_Stop(This
->dev
);
471 IAudioClient_Reset(This
->dev
);
473 LeaveCriticalSection(&This
->parent
->crst
);
477 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_Unlock(IDirectSoundCaptureBuffer8
*iface
, void *ptr1
, DWORD len1
, void *ptr2
, DWORD len2
)
479 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
480 TRACE("(%p)->(%p,%u,%p,%u)\n", This
, ptr1
, len2
, ptr2
, len2
);
483 return DSERR_INVALIDPARAM
;
487 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetObjectInPath(IDirectSoundCaptureBuffer8
*iface
, REFGUID guid
, DWORD num
, REFGUID riid
, void **ppv
)
489 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
490 FIXME("(%p)->(%s %u %s %p) stub\n", This
, debugstr_guid(guid
), num
, debugstr_guid(riid
), ppv
);
494 static HRESULT WINAPI
IDirectSoundCaptureBufferImpl_GetFXStatus(IDirectSoundCaptureBuffer8
*iface
, DWORD count
, DWORD
*status
)
496 IDirectSoundCaptureBufferImpl
*This
= impl_from_IDirectSoundCaptureBuffer8(iface
);
497 FIXME("(%p)->(%u %p) stub\n", This
, count
, status
);
501 static const IDirectSoundCaptureBuffer8Vtbl IDirectSoundCaptureBufferImpl_Vtbl
= {
502 IDirectSoundCaptureBufferImpl_QueryInterface
,
503 IDirectSoundCaptureBufferImpl_AddRef
,
504 IDirectSoundCaptureBufferImpl_Release
,
505 IDirectSoundCaptureBufferImpl_GetCaps
,
506 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
507 IDirectSoundCaptureBufferImpl_GetFormat
,
508 IDirectSoundCaptureBufferImpl_GetStatus
,
509 IDirectSoundCaptureBufferImpl_Initialize
,
510 IDirectSoundCaptureBufferImpl_Lock
,
511 IDirectSoundCaptureBufferImpl_Start
,
512 IDirectSoundCaptureBufferImpl_Stop
,
513 IDirectSoundCaptureBufferImpl_Unlock
,
514 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
515 IDirectSoundCaptureBufferImpl_GetFXStatus
518 static HRESULT
IDirectSoundCaptureBufferImpl_Create(IDirectSoundCaptureBufferImpl
**buf
)
520 IDirectSoundCaptureBufferImpl
*This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
522 return E_OUTOFMEMORY
;
523 This
->IDirectSoundCaptureBuffer8_iface
.lpVtbl
= &IDirectSoundCaptureBufferImpl_Vtbl
;
529 static void IDirectSoundCaptureBufferImpl_Destroy(IDirectSoundCaptureBufferImpl
*This
)
534 IAudioClient_Stop(This
->dev
);
535 IAudioCaptureClient_Release(This
->cap_dev
);
536 IAudioClient_Release(This
->dev
);
539 This
->parent
->buf
= NULL
;
540 HeapFree(GetProcessHeap(), 0, This
->notify
);
541 HeapFree(GetProcessHeap(), 0, This
->format
);
542 HeapFree(GetProcessHeap(), 0, This
->buf
);
543 HeapFree(GetProcessHeap(), 0, This
);
547 static HRESULT WINAPI
IDirectSoundCaptureImpl_QueryInterface(IDirectSoundCapture
*iface
, REFIID riid
, void **ppobj
)
549 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
550 TRACE("(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
553 WARN("invalid parameter\n");
559 if (IsEqualIID(riid
, &IID_IUnknown
)) {
560 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
563 } else if (IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
564 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
569 WARN("unsupported riid: %s\n", debugstr_guid(riid
));
570 return E_NOINTERFACE
;
573 static ULONG WINAPI
IDirectSoundCaptureImpl_AddRef(IDirectSoundCapture
*iface
)
575 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
576 ULONG ref
= InterlockedIncrement(&(This
->ref
));
577 TRACE("(%p) ref was %d\n", This
, ref
- 1);
581 static ULONG WINAPI
IDirectSoundCaptureImpl_Release(IDirectSoundCapture
*iface
)
583 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
584 ULONG ref
= InterlockedDecrement(&(This
->ref
));
585 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
588 IDirectSoundCaptureImpl_Destroy(This
);
589 TRACE("(%p) released\n", This
);
594 static HRESULT WINAPI
IDirectSoundCaptureImpl_CreateCaptureBuffer(IDirectSoundCapture
*iface
, const DSCBUFFERDESC
*desc
, IDirectSoundCaptureBuffer
**ppv
, IUnknown
*unk
)
596 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
598 TRACE("(%p)->(%p,%p,%p)\n", This
, desc
, ppv
, unk
);
602 WARN("Aggregation isn't supported\n");
603 return DSERR_NOAGGREGATION
;
606 if (!desc
|| desc
->dwSize
< sizeof(DSCBUFFERDESC1
))
608 WARN("Passed invalid description %p %u\n", desc
, desc
?desc
->dwSize
:0);
609 return DSERR_INVALIDPARAM
;
613 WARN("Passed null pointer\n");
614 return DSERR_INVALIDPARAM
;
618 EnterCriticalSection(&This
->crst
);
619 if (IsEqualIID(&This
->device
, &GUID_NULL
))
621 hr
= DSERR_UNINITIALIZED
;
622 WARN("Not initialized\n");
626 hr
= IDirectSoundCaptureBufferImpl_Create(&This
->buf
);
629 hr
= IDirectSoundCaptureBuffer_Initialize((IDirectSoundCaptureBuffer
*)This
->buf
, iface
, desc
);
632 IDirectSoundCaptureBufferImpl_Destroy(This
->buf
);
636 *ppv
= (IDirectSoundCaptureBuffer
*)&This
->buf
->IDirectSoundCaptureBuffer8_iface
;
638 LeaveCriticalSection(&This
->crst
);
642 static HRESULT WINAPI
IDirectSoundCaptureImpl_GetCaps(IDirectSoundCapture
*iface
, DSCCAPS
*caps
)
644 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
645 TRACE("(%p,%p)\n", This
, caps
);
647 if (IsEqualIID(&This
->device
, &GUID_NULL
)) {
648 WARN("Not initialized\n");
649 return DSERR_UNINITIALIZED
;
653 WARN("Caps is null\n");
654 return DSERR_INVALIDPARAM
;
657 if (caps
->dwSize
< sizeof(*caps
)) {
658 WARN("Invalid size %d\n", caps
->dwSize
);
659 return DSERR_INVALIDPARAM
;
663 /* Support all WAVE_FORMAT formats specified in mmsystem.h */
664 caps
->dwFormats
= 0x000fffff;
665 caps
->dwChannels
= 2;
670 static HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(IDirectSoundCapture
*iface
, const GUID
*devguid
)
672 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
675 BOOL voice
= devguid
&& IsEqualIID(devguid
, &DSDEVID_DefaultVoiceCapture
);
678 TRACE("(%p,%p)\n", This
, devguid
);
680 if (!IsEqualIID(&This
->device
, &GUID_NULL
)) {
681 WARN("Already initialized\n");
682 return DSERR_ALREADYINITIALIZED
;
686 devguid
= &DSDEVID_DefaultCapture
;
689 EnterCriticalSection(&This
->crst
);
690 hr
= get_mmdevice(eCapture
, &guid
, &dev
);
693 WARN("Failed to create device for %s: %08x\n", debugstr_guid(&guid
), hr
);
697 IMMDevice_Release(dev
);
702 LeaveCriticalSection(&This
->crst
);
706 static const IDirectSoundCaptureVtbl dscvt
=
708 IDirectSoundCaptureImpl_QueryInterface
,
709 IDirectSoundCaptureImpl_AddRef
,
710 IDirectSoundCaptureImpl_Release
,
711 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
712 IDirectSoundCaptureImpl_GetCaps
,
713 IDirectSoundCaptureImpl_Initialize
716 HRESULT
DSOUND_CaptureCreate(REFIID riid
, LPDIRECTSOUNDCAPTURE
*ppDSC
)
719 hr
= DSOUND_CaptureCreate8(riid
, ppDSC
);
721 impl_from_IDirectSoundCapture(*ppDSC
)->is_8
= 0;
725 HRESULT
DSOUND_CaptureCreate8(REFIID riid
, LPDIRECTSOUNDCAPTURE8
*cap
)
727 IDirectSoundCaptureImpl
*This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*This
));
730 return DSERR_OUTOFMEMORY
;
731 This
->IDirectSoundCapture_iface
.lpVtbl
= &dscvt
;
734 InitializeCriticalSection(&This
->crst
);
735 This
->crst
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DSCImpl.crst");
736 if (FAILED(IUnknown_QueryInterface((IUnknown
*)This
, riid
, (void**)cap
)))
738 IDirectSoundCaptureImpl_Destroy(This
);
739 return E_NOINTERFACE
;
744 static void IDirectSoundCaptureImpl_Destroy(IDirectSoundCaptureImpl
*This
)
748 timeKillEvent(This
->timer_id
);
749 timeEndPeriod(This
->timer_res
);
751 EnterCriticalSection(&This
->crst
);
753 IDirectSoundCaptureBufferImpl_Destroy(This
->buf
);
754 LeaveCriticalSection(&This
->crst
);
755 This
->crst
.DebugInfo
->Spare
[0] = 0;
756 DeleteCriticalSection(&This
->crst
);
757 HeapFree(GetProcessHeap(), 0, This
);
760 /***************************************************************************
761 * DirectSoundCaptureCreate [DSOUND.6]
763 * Create and initialize a DirectSoundCapture interface.
766 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
767 * lplpDSC [O] Address of a variable to receive the interface pointer.
768 * pUnkOuter [I] Must be NULL.
772 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
776 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
777 * or NULL for the default device or DSDEVID_DefaultCapture or
778 * DSDEVID_DefaultVoiceCapture.
780 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
782 HRESULT WINAPI
DirectSoundCaptureCreate(
784 LPDIRECTSOUNDCAPTURE
*ppDSC
,
788 LPDIRECTSOUNDCAPTURE pDSC
;
789 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC
, pUnkOuter
);
792 WARN("invalid parameter: ppDSC == NULL\n");
793 return DSERR_INVALIDPARAM
;
797 WARN("invalid parameter: pUnkOuter != NULL\n");
799 return DSERR_NOAGGREGATION
;
802 hr
= DSOUND_CaptureCreate(&IID_IDirectSoundCapture
, &pDSC
);
804 hr
= IDirectSoundCapture_Initialize(pDSC
, lpcGUID
);
806 IDirectSoundCapture_Release(pDSC
);
816 /***************************************************************************
817 * DirectSoundCaptureCreate8 [DSOUND.12]
819 * Create and initialize a DirectSoundCapture interface.
822 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
823 * lplpDSC [O] Address of a variable to receive the interface pointer.
824 * pUnkOuter [I] Must be NULL.
828 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
832 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
833 * or NULL for the default device or DSDEVID_DefaultCapture or
834 * DSDEVID_DefaultVoiceCapture.
836 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
838 HRESULT WINAPI
DirectSoundCaptureCreate8(
840 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
844 LPDIRECTSOUNDCAPTURE8 pDSC8
;
845 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC8
, pUnkOuter
);
847 if (ppDSC8
== NULL
) {
848 WARN("invalid parameter: ppDSC8 == NULL\n");
849 return DSERR_INVALIDPARAM
;
853 WARN("invalid parameter: pUnkOuter != NULL\n");
855 return DSERR_NOAGGREGATION
;
858 hr
= DSOUND_CaptureCreate8(&IID_IDirectSoundCapture
, &pDSC8
);
860 hr
= IDirectSoundCapture_Initialize(pDSC8
, lpcGUID
);
862 IDirectSoundCapture_Release(pDSC8
);