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.
24 * Implement both IDirectSoundCaptureBuffer and IDirectSoundCaptureBuffer8
25 * Make DirectSoundCaptureCreate and DirectSoundCaptureCreate8 behave differently
31 #define NONAMELESSSTRUCT
32 #define NONAMELESSUNION
40 #include "wine/debug.h"
42 #include "dsound_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
47 /*****************************************************************************
48 * IDirectSoundCaptureNotify implementation structure
50 struct IDirectSoundCaptureNotifyImpl
53 const IDirectSoundNotifyVtbl
*lpVtbl
;
55 IDirectSoundCaptureBufferImpl
* dscb
;
58 /*******************************************************************************
59 * IDirectSoundCaptureNotify
61 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_QueryInterface(
62 LPDIRECTSOUNDNOTIFY iface
,
66 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
67 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
69 if (This
->dscb
== NULL
) {
70 WARN("invalid parameter\n");
74 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
, riid
, ppobj
);
77 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface
)
79 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
80 ULONG ref
= InterlockedIncrement(&(This
->ref
));
81 TRACE("(%p) ref was %d\n", This
, ref
- 1);
85 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface
)
87 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
88 ULONG ref
= InterlockedDecrement(&(This
->ref
));
89 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
92 This
->dscb
->notify
=NULL
;
93 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
);
94 HeapFree(GetProcessHeap(),0,This
);
95 TRACE("(%p) released\n", This
);
100 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
101 LPDIRECTSOUNDNOTIFY iface
,
103 LPCDSBPOSITIONNOTIFY notify
)
105 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
106 TRACE("(%p,0x%08x,%p)\n",This
,howmuch
,notify
);
108 if (howmuch
> 0 && notify
== NULL
) {
109 WARN("invalid parameter: notify == NULL\n");
110 return DSERR_INVALIDPARAM
;
113 if (TRACE_ON(dsound
)) {
115 for (i
=0;i
<howmuch
;i
++)
116 TRACE("notify at %d to %p\n",
117 notify
[i
].dwOffset
,notify
[i
].hEventNotify
);
121 /* Make an internal copy of the caller-supplied array.
122 * Replace the existing copy if one is already present. */
123 if (This
->dscb
->notifies
)
124 This
->dscb
->notifies
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
125 This
->dscb
->notifies
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
127 This
->dscb
->notifies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
128 howmuch
* sizeof(DSBPOSITIONNOTIFY
));
130 if (This
->dscb
->notifies
== NULL
) {
131 WARN("out of memory\n");
132 return DSERR_OUTOFMEMORY
;
134 CopyMemory(This
->dscb
->notifies
, notify
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
135 This
->dscb
->nrofnotifies
= howmuch
;
137 HeapFree(GetProcessHeap(), 0, This
->dscb
->notifies
);
138 This
->dscb
->notifies
= NULL
;
139 This
->dscb
->nrofnotifies
= 0;
145 static const IDirectSoundNotifyVtbl dscnvt
=
147 IDirectSoundCaptureNotifyImpl_QueryInterface
,
148 IDirectSoundCaptureNotifyImpl_AddRef
,
149 IDirectSoundCaptureNotifyImpl_Release
,
150 IDirectSoundCaptureNotifyImpl_SetNotificationPositions
,
153 static HRESULT
IDirectSoundCaptureNotifyImpl_Create(
154 IDirectSoundCaptureBufferImpl
*dscb
,
155 IDirectSoundCaptureNotifyImpl
**pdscn
)
157 IDirectSoundCaptureNotifyImpl
* dscn
;
158 TRACE("(%p,%p)\n",dscb
,pdscn
);
160 dscn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*dscn
));
163 WARN("out of memory\n");
164 return DSERR_OUTOFMEMORY
;
168 dscn
->lpVtbl
= &dscnvt
;
171 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER
)dscb
);
178 static const char * const captureStateString
[] = {
186 /*******************************************************************************
187 * IDirectSoundCaptureBuffer
189 static HRESULT WINAPI
190 IDirectSoundCaptureBufferImpl_QueryInterface(
191 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
195 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
198 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
201 WARN("invalid parameter\n");
207 if ( IsEqualGUID( &IID_IDirectSoundNotify
, riid
) ) {
209 hres
= IDirectSoundCaptureNotifyImpl_Create(This
, &This
->notify
);
214 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY
)This
->notify
);
215 *ppobj
= This
->notify
;
219 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer
, riid
) ||
220 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8
, riid
) ) {
221 IDirectSoundCaptureBuffer8_AddRef(iface
);
226 FIXME("(%p,%s,%p) unsupported GUID\n", This
, debugstr_guid(riid
), ppobj
);
227 return E_NOINTERFACE
;
231 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
233 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
234 ULONG ref
= InterlockedIncrement(&(This
->ref
));
235 TRACE("(%p) ref was %d\n", This
, ref
- 1);
240 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
242 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
243 ULONG ref
= InterlockedDecrement(&(This
->ref
));
244 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
247 TRACE("deleting object\n");
248 if (This
->device
->state
== STATE_CAPTURING
)
249 This
->device
->state
= STATE_STOPPING
;
251 HeapFree(GetProcessHeap(),0, This
->pdscbd
);
253 if (This
->device
->client
) {
254 IAudioClient_Release(This
->device
->client
);
255 This
->device
->client
= NULL
;
258 if (This
->device
->capture
) {
259 IAudioCaptureClient_Release(This
->device
->capture
);
260 This
->device
->capture
= NULL
;
263 /* remove from DirectSoundCaptureDevice */
264 This
->device
->capture_buffer
= NULL
;
267 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
269 HeapFree(GetProcessHeap(), 0, This
->notifies
);
270 HeapFree( GetProcessHeap(), 0, This
);
271 TRACE("(%p) released\n", This
);
276 static HRESULT WINAPI
277 IDirectSoundCaptureBufferImpl_GetCaps(
278 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
279 LPDSCBCAPS lpDSCBCaps
)
281 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
282 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
284 if (lpDSCBCaps
== NULL
) {
285 WARN("invalid parameter: lpDSCBCaps == NULL\n");
286 return DSERR_INVALIDPARAM
;
289 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
290 WARN("invalid parameter: lpDSCBCaps->dwSize = %d\n", lpDSCBCaps
->dwSize
);
291 return DSERR_INVALIDPARAM
;
294 if (This
->device
== NULL
) {
295 WARN("invalid parameter: This->device == NULL\n");
296 return DSERR_INVALIDPARAM
;
299 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
300 lpDSCBCaps
->dwFlags
= This
->flags
;
301 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
302 lpDSCBCaps
->dwReserved
= 0;
304 TRACE("returning DS_OK\n");
308 static HRESULT WINAPI
309 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
310 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
311 LPDWORD lpdwCapturePosition
,
312 LPDWORD lpdwReadPosition
)
314 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
315 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
317 if (This
->device
== NULL
) {
318 WARN("invalid parameter: This->device == NULL\n");
319 return DSERR_INVALIDPARAM
;
322 EnterCriticalSection(&This
->device
->lock
);
324 if (!This
->device
->client
) {
325 LeaveCriticalSection(&This
->device
->lock
);
327 return DSERR_NODRIVER
;
330 if(lpdwCapturePosition
)
331 *lpdwCapturePosition
= This
->device
->write_pos_bytes
;
334 *lpdwReadPosition
= This
->device
->write_pos_bytes
;
336 LeaveCriticalSection(&This
->device
->lock
);
338 TRACE("cappos=%d readpos=%d\n", (lpdwCapturePosition
?*lpdwCapturePosition
:-1), (lpdwReadPosition
?*lpdwReadPosition
:-1));
339 TRACE("returning DS_OK\n");
344 static HRESULT WINAPI
345 IDirectSoundCaptureBufferImpl_GetFormat(
346 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
347 LPWAVEFORMATEX lpwfxFormat
,
348 DWORD dwSizeAllocated
,
349 LPDWORD lpdwSizeWritten
)
351 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
352 HRESULT hres
= DS_OK
;
353 TRACE( "(%p,%p,0x%08x,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
356 if (This
->device
== NULL
) {
357 WARN("invalid parameter: This->device == NULL\n");
358 return DSERR_INVALIDPARAM
;
361 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
))
362 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
364 if (lpwfxFormat
) { /* NULL is valid (just want size) */
365 CopyMemory(lpwfxFormat
, This
->device
->pwfx
, dwSizeAllocated
);
367 *lpdwSizeWritten
= dwSizeAllocated
;
370 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
372 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
373 hres
= DSERR_INVALIDPARAM
;
377 TRACE("returning %08x\n", hres
);
381 static HRESULT WINAPI
382 IDirectSoundCaptureBufferImpl_GetStatus(
383 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
386 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
387 TRACE( "(%p, %p), thread is %04x\n", This
, lpdwStatus
, GetCurrentThreadId() );
389 if (This
->device
== NULL
) {
390 WARN("invalid parameter: This->device == NULL\n");
391 return DSERR_INVALIDPARAM
;
394 if (lpdwStatus
== NULL
) {
395 WARN("invalid parameter: lpdwStatus == NULL\n");
396 return DSERR_INVALIDPARAM
;
400 EnterCriticalSection(&(This
->device
->lock
));
402 TRACE("old This->device->state=%s, old lpdwStatus=%08x\n",
403 captureStateString
[This
->device
->state
],*lpdwStatus
);
404 if ((This
->device
->state
== STATE_STARTING
) ||
405 (This
->device
->state
== STATE_CAPTURING
)) {
406 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
407 if (This
->flags
& DSCBSTART_LOOPING
)
408 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
410 TRACE("new This->device->state=%s, new lpdwStatus=%08x\n",
411 captureStateString
[This
->device
->state
],*lpdwStatus
);
412 LeaveCriticalSection(&(This
->device
->lock
));
414 TRACE("status=%x\n", *lpdwStatus
);
415 TRACE("returning DS_OK\n");
419 static HRESULT WINAPI
420 IDirectSoundCaptureBufferImpl_Initialize(
421 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
422 LPDIRECTSOUNDCAPTURE lpDSC
,
423 LPCDSCBUFFERDESC lpcDSCBDesc
)
425 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
427 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
432 static HRESULT WINAPI
433 IDirectSoundCaptureBufferImpl_Lock(
434 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
437 LPVOID
* lplpvAudioPtr1
,
438 LPDWORD lpdwAudioBytes1
,
439 LPVOID
* lplpvAudioPtr2
,
440 LPDWORD lpdwAudioBytes2
,
443 HRESULT hres
= DS_OK
;
444 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
445 TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This
, dwReadCusor
,
446 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
447 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
449 if (This
->device
== NULL
) {
450 WARN("invalid parameter: This->device == NULL\n");
451 return DSERR_INVALIDPARAM
;
454 if (lplpvAudioPtr1
== NULL
) {
455 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
456 return DSERR_INVALIDPARAM
;
459 if (lpdwAudioBytes1
== NULL
) {
460 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
461 return DSERR_INVALIDPARAM
;
464 EnterCriticalSection(&(This
->device
->lock
));
466 if (This
->device
->client
) {
467 *lplpvAudioPtr1
= This
->device
->buffer
+ dwReadCusor
;
468 if ( (dwReadCusor
+ dwReadBytes
) > This
->device
->buflen
) {
469 *lpdwAudioBytes1
= This
->device
->buflen
- dwReadCusor
;
471 *lplpvAudioPtr2
= This
->device
->buffer
;
473 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
475 *lpdwAudioBytes1
= dwReadBytes
;
479 *lpdwAudioBytes2
= 0;
482 TRACE("invalid call\n");
483 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
486 LeaveCriticalSection(&(This
->device
->lock
));
488 TRACE("returning %08x\n", hres
);
492 static HRESULT WINAPI
493 IDirectSoundCaptureBufferImpl_Start(
494 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
498 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
500 TRACE( "(%p,0x%08x)\n", This
, dwFlags
);
502 if (This
->device
== NULL
) {
503 WARN("invalid parameter: This->device == NULL\n");
504 return DSERR_INVALIDPARAM
;
507 if ( !This
->device
->client
) {
509 return DSERR_NODRIVER
;
512 EnterCriticalSection(&(This
->device
->lock
));
514 This
->flags
= dwFlags
;
515 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
516 if (This
->device
->state
== STATE_STOPPED
)
517 This
->device
->state
= STATE_STARTING
;
518 else if (This
->device
->state
== STATE_STOPPING
)
519 This
->device
->state
= STATE_CAPTURING
;
520 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
522 if (This
->device
->buffer
)
523 FillMemory(This
->device
->buffer
, This
->device
->buflen
, (This
->device
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
525 hres
= IAudioClient_Start(This
->device
->client
);
527 WARN("Start failed: %08x\n", hres
);
528 LeaveCriticalSection(&This
->device
->lock
);
532 LeaveCriticalSection(&This
->device
->lock
);
534 TRACE("returning DS_OK\n");
538 static HRESULT WINAPI
539 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
542 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
543 TRACE( "(%p)\n", This
);
545 if (This
->device
== NULL
) {
546 WARN("invalid parameter: This->device == NULL\n");
547 return DSERR_INVALIDPARAM
;
550 EnterCriticalSection(&(This
->device
->lock
));
552 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
553 if (This
->device
->state
== STATE_CAPTURING
)
554 This
->device
->state
= STATE_STOPPING
;
555 else if (This
->device
->state
== STATE_STARTING
)
556 This
->device
->state
= STATE_STOPPED
;
557 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
559 if(This
->device
->client
){
560 hres
= IAudioClient_Stop(This
->device
->client
);
562 LeaveCriticalSection(&This
->device
->lock
);
567 LeaveCriticalSection(&(This
->device
->lock
));
569 TRACE("returning DS_OK\n");
573 static HRESULT WINAPI
574 IDirectSoundCaptureBufferImpl_Unlock(
575 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
579 DWORD dwAudioBytes2
)
581 HRESULT hres
= DS_OK
;
582 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
583 TRACE( "(%p,%p,%08u,%p,%08u)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
584 lpvAudioPtr2
, dwAudioBytes2
);
586 if (lpvAudioPtr1
== NULL
) {
587 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
588 return DSERR_INVALIDPARAM
;
591 if (!This
->device
->client
) {
592 WARN("invalid call\n");
593 hres
= DSERR_INVALIDCALL
;
596 TRACE("returning %08x\n", hres
);
600 static HRESULT WINAPI
601 IDirectSoundCaptureBufferImpl_GetObjectInPath(
602 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
605 REFGUID rguidInterface
,
608 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
610 FIXME( "(%p,%s,%u,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
611 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
616 static HRESULT WINAPI
617 IDirectSoundCaptureBufferImpl_GetFXStatus(
618 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
620 LPDWORD pdwFXStatus
)
622 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
624 FIXME( "(%p,%u,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
629 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
=
631 /* IUnknown methods */
632 IDirectSoundCaptureBufferImpl_QueryInterface
,
633 IDirectSoundCaptureBufferImpl_AddRef
,
634 IDirectSoundCaptureBufferImpl_Release
,
636 /* IDirectSoundCaptureBuffer methods */
637 IDirectSoundCaptureBufferImpl_GetCaps
,
638 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
639 IDirectSoundCaptureBufferImpl_GetFormat
,
640 IDirectSoundCaptureBufferImpl_GetStatus
,
641 IDirectSoundCaptureBufferImpl_Initialize
,
642 IDirectSoundCaptureBufferImpl_Lock
,
643 IDirectSoundCaptureBufferImpl_Start
,
644 IDirectSoundCaptureBufferImpl_Stop
,
645 IDirectSoundCaptureBufferImpl_Unlock
,
647 /* IDirectSoundCaptureBuffer methods */
648 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
649 IDirectSoundCaptureBufferImpl_GetFXStatus
652 static void capture_CheckNotify(IDirectSoundCaptureBufferImpl
*This
, DWORD from
, DWORD len
)
655 for (i
= 0; i
< This
->nrofnotifies
; ++i
) {
656 LPDSBPOSITIONNOTIFY event
= This
->notifies
+ i
;
657 DWORD offset
= event
->dwOffset
;
658 TRACE("checking %d, position %d, event = %p\n", i
, offset
, event
->hEventNotify
);
660 if (offset
== DSBPN_OFFSETSTOP
) {
662 SetEvent(event
->hEventNotify
);
663 TRACE("signalled event %p (%d)\n", event
->hEventNotify
, i
);
669 if (offset
>= from
&& offset
< (from
+ len
))
671 TRACE("signalled event %p (%d)\n", event
->hEventNotify
, i
);
672 SetEvent(event
->hEventNotify
);
677 static HRESULT
IDirectSoundCaptureBufferImpl_Create(
678 DirectSoundCaptureDevice
*device
,
679 IDirectSoundCaptureBufferImpl
** ppobj
,
680 LPCDSCBUFFERDESC lpcDSCBufferDesc
)
683 IDirectSoundCaptureBufferImpl
*This
;
684 TRACE( "(%p,%p,%p)\n", device
, ppobj
, lpcDSCBufferDesc
);
687 WARN("invalid parameter: ppobj == NULL\n");
688 return DSERR_INVALIDPARAM
;
694 WARN("not initialized\n");
695 return DSERR_UNINITIALIZED
;
698 if (lpcDSCBufferDesc
== NULL
) {
699 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
700 return DSERR_INVALIDPARAM
;
703 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
704 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
705 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
706 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) { /* FIXME: DSERR_BADFORMAT ? */
707 WARN("invalid lpcDSCBufferDesc\n");
708 return DSERR_INVALIDPARAM
;
711 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
713 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
714 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
715 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
716 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
717 wfex
->wBitsPerSample
, wfex
->cbSize
);
719 device
->pwfx
= DSOUND_CopyFormat(wfex
);
720 if ( device
->pwfx
== NULL
)
721 return DSERR_OUTOFMEMORY
;
723 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
724 sizeof(IDirectSoundCaptureBufferImpl
));
726 if ( This
== NULL
) {
727 WARN("out of memory\n");
728 return DSERR_OUTOFMEMORY
;
735 This
->device
= device
;
736 This
->device
->capture_buffer
= This
;
738 This
->nrofnotifies
= 0;
740 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
741 lpcDSCBufferDesc
->dwSize
);
743 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
746 This
->device
->capture_buffer
= 0;
747 HeapFree( GetProcessHeap(), 0, This
);
748 return DSERR_OUTOFMEMORY
;
751 This
->lpVtbl
= &dscbvt
;
753 err
= IMMDevice_Activate(device
->mmdevice
, &IID_IAudioClient
,
754 CLSCTX_INPROC_SERVER
, NULL
, (void**)&device
->client
);
756 WARN("Activate failed: %08x\n", err
);
757 HeapFree(GetProcessHeap(), 0, This
->pdscbd
);
758 This
->device
->capture_buffer
= 0;
759 HeapFree( GetProcessHeap(), 0, This
);
763 err
= IAudioClient_Initialize(device
->client
,
764 AUDCLNT_SHAREMODE_SHARED
, AUDCLNT_STREAMFLAGS_NOPERSIST
,
765 200 * 100000, 50000, device
->pwfx
, NULL
);
767 WARN("Initialize failed: %08x\n", err
);
768 IAudioClient_Release(device
->client
);
769 device
->client
= NULL
;
770 HeapFree(GetProcessHeap(), 0, This
->pdscbd
);
771 This
->device
->capture_buffer
= 0;
772 HeapFree( GetProcessHeap(), 0, This
);
776 err
= IAudioClient_GetService(device
->client
, &IID_IAudioCaptureClient
,
777 (void**)&device
->capture
);
779 WARN("GetService failed: %08x\n", err
);
780 IAudioClient_Release(device
->client
);
781 device
->client
= NULL
;
782 HeapFree(GetProcessHeap(), 0, This
->pdscbd
);
783 This
->device
->capture_buffer
= 0;
784 HeapFree( GetProcessHeap(), 0, This
);
788 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
789 TRACE("desired buflen=%d, old buffer=%p\n", buflen
, device
->buffer
);
791 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
793 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
794 if (newbuf
== NULL
) {
795 IAudioClient_Release(device
->client
);
796 device
->client
= NULL
;
797 IAudioCaptureClient_Release(device
->capture
);
798 device
->capture
= NULL
;
799 HeapFree(GetProcessHeap(), 0, This
->pdscbd
);
800 This
->device
->capture_buffer
= 0;
801 HeapFree( GetProcessHeap(), 0, This
);
802 return DSERR_OUTOFMEMORY
;
804 device
->buffer
= newbuf
;
805 device
->buflen
= buflen
;
810 TRACE("returning DS_OK\n");
815 /*******************************************************************************
816 * DirectSoundCaptureDevice
818 static HRESULT
DirectSoundCaptureDevice_Create(
819 DirectSoundCaptureDevice
** ppDevice
)
821 DirectSoundCaptureDevice
* device
;
822 TRACE("(%p)\n", ppDevice
);
824 /* Allocate memory */
825 device
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DirectSoundCaptureDevice
));
827 if (device
== NULL
) {
828 WARN("out of memory\n");
829 return DSERR_OUTOFMEMORY
;
833 device
->state
= STATE_STOPPED
;
835 InitializeCriticalSection( &(device
->lock
) );
836 device
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundCaptureDevice.lock");
843 static ULONG
DirectSoundCaptureDevice_Release(
844 DirectSoundCaptureDevice
* device
)
846 ULONG ref
= InterlockedDecrement(&(device
->ref
));
847 TRACE("(%p) ref was %d\n", device
, ref
+ 1);
850 TRACE("deleting object\n");
852 timeKillEvent(device
->timerID
);
853 timeEndPeriod(DS_TIME_RES
);
855 EnterCriticalSection(&DSOUND_capturers_lock
);
856 list_remove(&device
->entry
);
857 LeaveCriticalSection(&DSOUND_capturers_lock
);
859 if (device
->capture_buffer
)
860 IDirectSoundCaptureBufferImpl_Release(
861 (LPDIRECTSOUNDCAPTUREBUFFER8
) device
->capture_buffer
);
864 IMMDevice_Release(device
->mmdevice
);
865 HeapFree(GetProcessHeap(), 0, device
->pwfx
);
866 device
->lock
.DebugInfo
->Spare
[0] = 0;
867 DeleteCriticalSection( &(device
->lock
) );
868 HeapFree(GetProcessHeap(), 0, device
);
869 TRACE("(%p) released\n", device
);
874 static void CALLBACK
DSOUND_capture_timer(UINT timerID
, UINT msg
, DWORD_PTR user
,
875 DWORD_PTR dw1
, DWORD_PTR dw2
)
877 DirectSoundCaptureDevice
*device
= (DirectSoundCaptureDevice
*)user
;
878 UINT32 packet_frames
, packet_bytes
, avail_bytes
;
886 EnterCriticalSection(&device
->lock
);
888 if(!device
->capture_buffer
|| device
->state
== STATE_STOPPED
){
889 LeaveCriticalSection(&device
->lock
);
893 if(device
->state
== STATE_STOPPING
){
894 device
->state
= STATE_STOPPED
;
895 LeaveCriticalSection(&device
->lock
);
899 if(device
->state
== STATE_STARTING
)
900 device
->state
= STATE_CAPTURING
;
902 hr
= IAudioCaptureClient_GetBuffer(device
->capture
, &buf
, &packet_frames
,
905 LeaveCriticalSection(&device
->lock
);
906 WARN("GetBuffer failed: %08x\n", hr
);
910 packet_bytes
= packet_frames
* device
->pwfx
->nBlockAlign
;
912 avail_bytes
= device
->buflen
- device
->write_pos_bytes
;
913 if(avail_bytes
> packet_bytes
)
914 avail_bytes
= packet_bytes
;
916 memcpy(device
->buffer
+ device
->write_pos_bytes
, buf
, avail_bytes
);
917 capture_CheckNotify(device
->capture_buffer
, device
->write_pos_bytes
, avail_bytes
);
919 packet_bytes
-= avail_bytes
;
920 if(packet_bytes
> 0){
921 if(device
->capture_buffer
->flags
& DSCBSTART_LOOPING
){
922 memcpy(device
->buffer
, buf
+ avail_bytes
, packet_bytes
);
923 capture_CheckNotify(device
->capture_buffer
, 0, packet_bytes
);
925 device
->state
= STATE_STOPPED
;
926 capture_CheckNotify(device
->capture_buffer
, 0, 0);
930 device
->write_pos_bytes
+= avail_bytes
+ packet_bytes
;
931 device
->write_pos_bytes
%= device
->buflen
;
933 hr
= IAudioCaptureClient_ReleaseBuffer(device
->capture
, packet_frames
);
935 LeaveCriticalSection(&device
->lock
);
936 WARN("ReleaseBuffer failed: %08x\n", hr
);
940 LeaveCriticalSection(&device
->lock
);
943 static struct _TestFormat
{
948 } formats_to_test
[] = {
949 { WAVE_FORMAT_1M08
, 11025, 8, 1 },
950 { WAVE_FORMAT_1M16
, 11025, 16, 1 },
951 { WAVE_FORMAT_1S08
, 11025, 8, 2 },
952 { WAVE_FORMAT_1S16
, 11025, 16, 2 },
953 { WAVE_FORMAT_2M08
, 22050, 8, 1 },
954 { WAVE_FORMAT_2M16
, 22050, 16, 1 },
955 { WAVE_FORMAT_2S08
, 22050, 8, 2 },
956 { WAVE_FORMAT_2S16
, 22050, 16, 2 },
957 { WAVE_FORMAT_4M08
, 44100, 8, 1 },
958 { WAVE_FORMAT_4M16
, 44100, 16, 1 },
959 { WAVE_FORMAT_4S08
, 44100, 8, 2 },
960 { WAVE_FORMAT_4S16
, 44100, 16, 2 },
961 { WAVE_FORMAT_48M08
, 48000, 8, 1 },
962 { WAVE_FORMAT_48M16
, 48000, 16, 1 },
963 { WAVE_FORMAT_48S08
, 48000, 8, 2 },
964 { WAVE_FORMAT_48S16
, 48000, 16, 2 },
965 { WAVE_FORMAT_96M08
, 96000, 8, 1 },
966 { WAVE_FORMAT_96M16
, 96000, 16, 1 },
967 { WAVE_FORMAT_96S08
, 96000, 8, 2 },
968 { WAVE_FORMAT_96S16
, 96000, 16, 2 },
972 static HRESULT
DirectSoundCaptureDevice_Initialize(
973 DirectSoundCaptureDevice
** ppDevice
,
979 struct _TestFormat
*fmt
;
980 DirectSoundCaptureDevice
*device
;
981 IAudioClient
*client
;
983 TRACE("(%p, %s)\n", ppDevice
, debugstr_guid(lpcGUID
));
985 /* Default device? */
986 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
987 lpcGUID
= &DSDEVID_DefaultCapture
;
989 if(IsEqualGUID(lpcGUID
, &DSDEVID_DefaultPlayback
) ||
990 IsEqualGUID(lpcGUID
, &DSDEVID_DefaultVoicePlayback
))
991 return DSERR_NODRIVER
;
993 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
994 WARN("invalid parameter: lpcGUID\n");
995 return DSERR_INVALIDPARAM
;
998 hr
= get_mmdevice(eCapture
, &devGUID
, &mmdevice
);
1002 EnterCriticalSection(&DSOUND_capturers_lock
);
1004 LIST_FOR_EACH_ENTRY(device
, &DSOUND_capturers
, DirectSoundCaptureDevice
, entry
){
1005 if(IsEqualGUID(&device
->guid
, &devGUID
)){
1006 IMMDevice_Release(mmdevice
);
1007 LeaveCriticalSection(&DSOUND_capturers_lock
);
1008 return DSERR_ALLOCATED
;
1012 hr
= DirectSoundCaptureDevice_Create(&device
);
1014 WARN("DirectSoundCaptureDevice_Create failed\n");
1015 LeaveCriticalSection(&DSOUND_capturers_lock
);
1019 device
->guid
= devGUID
;
1021 device
->mmdevice
= mmdevice
;
1023 device
->drvcaps
.dwFlags
= 0;
1025 device
->drvcaps
.dwFormats
= 0;
1026 device
->drvcaps
.dwChannels
= 0;
1027 hr
= IMMDevice_Activate(mmdevice
, &IID_IAudioClient
,
1028 CLSCTX_INPROC_SERVER
, NULL
, (void**)&client
);
1030 device
->lock
.DebugInfo
->Spare
[0] = 0;
1031 DeleteCriticalSection(&device
->lock
);
1032 HeapFree(GetProcessHeap(), 0, device
);
1033 LeaveCriticalSection(&DSOUND_capturers_lock
);
1034 return DSERR_NODRIVER
;
1037 for(fmt
= formats_to_test
; fmt
->flag
; ++fmt
){
1038 if(DSOUND_check_supported(client
, fmt
->rate
, fmt
->depth
, fmt
->channels
)){
1039 device
->drvcaps
.dwFormats
|= fmt
->flag
;
1040 if(fmt
->channels
> device
->drvcaps
.dwChannels
)
1041 device
->drvcaps
.dwChannels
= fmt
->channels
;
1044 IAudioClient_Release(client
);
1046 device
->timerID
= DSOUND_create_timer(DSOUND_capture_timer
, (DWORD_PTR
)device
);
1048 list_add_tail(&DSOUND_capturers
, &device
->entry
);
1052 LeaveCriticalSection(&DSOUND_capturers_lock
);
1058 /*****************************************************************************
1059 * IDirectSoundCapture implementation structure
1061 struct IDirectSoundCaptureImpl
1063 IDirectSoundCapture IDirectSoundCapture_iface
;
1065 DirectSoundCaptureDevice
*device
;
1068 static inline struct IDirectSoundCaptureImpl
*impl_from_IDirectSoundCapture(IDirectSoundCapture
*iface
)
1070 return CONTAINING_RECORD(iface
, struct IDirectSoundCaptureImpl
, IDirectSoundCapture_iface
);
1073 /***************************************************************************
1074 * IDirectSoundCaptureImpl
1076 static HRESULT WINAPI
IDirectSoundCaptureImpl_QueryInterface(IDirectSoundCapture
*iface
,
1077 REFIID riid
, void **ppobj
)
1079 TRACE( "(%p,%s,%p)\n", iface
, debugstr_guid(riid
), ppobj
);
1081 if (ppobj
== NULL
) {
1082 WARN("invalid parameter\n");
1083 return E_INVALIDARG
;
1088 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
1089 IDirectSoundCapture_AddRef(iface
);
1094 WARN("unsupported riid: %s\n", debugstr_guid(riid
));
1095 return E_NOINTERFACE
;
1098 static ULONG WINAPI
IDirectSoundCaptureImpl_AddRef(IDirectSoundCapture
*iface
)
1100 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
1101 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1103 TRACE("(%p) ref was %d\n", This
, ref
- 1);
1107 static ULONG WINAPI
IDirectSoundCaptureImpl_Release(IDirectSoundCapture
*iface
)
1109 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
1110 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1112 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
1116 DirectSoundCaptureDevice_Release(This
->device
);
1118 HeapFree( GetProcessHeap(), 0, This
);
1119 TRACE("(%p) released\n", This
);
1124 static HRESULT WINAPI
IDirectSoundCaptureImpl_CreateCaptureBuffer(IDirectSoundCapture
*iface
,
1125 LPCDSCBUFFERDESC lpcDSCBufferDesc
, IDirectSoundCaptureBuffer
**lplpDSCaptureBuffer
,
1128 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
1131 TRACE( "(%p,%p,%p,%p)\n",iface
,lpcDSCBufferDesc
,lplpDSCaptureBuffer
,pUnk
);
1133 if (lpcDSCBufferDesc
== NULL
) {
1134 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
1135 return DSERR_INVALIDPARAM
;
1138 if (lplpDSCaptureBuffer
== NULL
) {
1139 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
1140 return DSERR_INVALIDPARAM
;
1144 WARN("invalid parameter: pUnk != NULL\n");
1145 return DSERR_INVALIDPARAM
;
1148 /* FIXME: We can only have one buffer so what do we do here? */
1149 if (This
->device
->capture_buffer
) {
1150 WARN("invalid parameter: already has buffer\n");
1151 return DSERR_INVALIDPARAM
; /* DSERR_GENERIC ? */
1154 hr
= IDirectSoundCaptureBufferImpl_Create(This
->device
,
1155 (IDirectSoundCaptureBufferImpl
**)lplpDSCaptureBuffer
, lpcDSCBufferDesc
);
1158 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
1163 static HRESULT WINAPI
IDirectSoundCaptureImpl_GetCaps(IDirectSoundCapture
*iface
,
1164 LPDSCCAPS lpDSCCaps
)
1166 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
1168 TRACE("(%p,%p)\n",This
,lpDSCCaps
);
1170 if (This
->device
== NULL
) {
1171 WARN("not initialized\n");
1172 return DSERR_UNINITIALIZED
;
1175 if (lpDSCCaps
== NULL
) {
1176 WARN("invalid parameter: lpDSCCaps== NULL\n");
1177 return DSERR_INVALIDPARAM
;
1180 if (lpDSCCaps
->dwSize
< sizeof(*lpDSCCaps
)) {
1181 WARN("invalid parameter: lpDSCCaps->dwSize = %d\n", lpDSCCaps
->dwSize
);
1182 return DSERR_INVALIDPARAM
;
1185 lpDSCCaps
->dwFlags
= This
->device
->drvcaps
.dwFlags
;
1186 lpDSCCaps
->dwFormats
= This
->device
->drvcaps
.dwFormats
;
1187 lpDSCCaps
->dwChannels
= This
->device
->drvcaps
.dwChannels
;
1189 TRACE("(flags=0x%08x,format=0x%08x,channels=%d)\n",lpDSCCaps
->dwFlags
,
1190 lpDSCCaps
->dwFormats
, lpDSCCaps
->dwChannels
);
1195 static HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(IDirectSoundCapture
*iface
,
1198 IDirectSoundCaptureImpl
*This
= impl_from_IDirectSoundCapture(iface
);
1200 TRACE("(%p,%s)\n", This
, debugstr_guid(lpcGUID
));
1202 if (This
->device
!= NULL
) {
1203 WARN("already initialized\n");
1204 return DSERR_ALREADYINITIALIZED
;
1206 return DirectSoundCaptureDevice_Initialize(&This
->device
, lpcGUID
);
1209 static const IDirectSoundCaptureVtbl dscvt
=
1211 /* IUnknown methods */
1212 IDirectSoundCaptureImpl_QueryInterface
,
1213 IDirectSoundCaptureImpl_AddRef
,
1214 IDirectSoundCaptureImpl_Release
,
1216 /* IDirectSoundCapture methods */
1217 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
1218 IDirectSoundCaptureImpl_GetCaps
,
1219 IDirectSoundCaptureImpl_Initialize
1222 static HRESULT
IDirectSoundCaptureImpl_Create(
1223 LPDIRECTSOUNDCAPTURE8
* ppDSC
)
1225 IDirectSoundCaptureImpl
*pDSC
;
1226 TRACE("(%p)\n", ppDSC
);
1228 /* Allocate memory */
1229 pDSC
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundCaptureImpl
));
1231 WARN("out of memory\n");
1233 return DSERR_OUTOFMEMORY
;
1236 pDSC
->IDirectSoundCapture_iface
.lpVtbl
= &dscvt
;
1238 pDSC
->device
= NULL
;
1240 *ppDSC
= (LPDIRECTSOUNDCAPTURE8
)pDSC
;
1245 HRESULT
DSOUND_CaptureCreate(REFIID riid
, IDirectSoundCapture
**ppDSC
)
1247 IDirectSoundCapture
*pDSC
;
1249 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDSC
);
1251 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
1252 !IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
1254 return E_NOINTERFACE
;
1257 /* Get dsound configuration */
1258 setup_dsound_options();
1260 hr
= IDirectSoundCaptureImpl_Create(&pDSC
);
1262 IDirectSoundCapture_AddRef(pDSC
);
1265 WARN("IDirectSoundCaptureImpl_Create failed\n");
1272 HRESULT
DSOUND_CaptureCreate8(
1274 LPDIRECTSOUNDCAPTURE8
*ppDSC8
)
1276 LPDIRECTSOUNDCAPTURE8 pDSC8
;
1278 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDSC8
);
1280 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
1281 !IsEqualIID(riid
, &IID_IDirectSoundCapture8
)) {
1283 return E_NOINTERFACE
;
1286 /* Get dsound configuration */
1287 setup_dsound_options();
1289 hr
= IDirectSoundCaptureImpl_Create(&pDSC8
);
1291 IDirectSoundCapture_AddRef(pDSC8
);
1294 WARN("IDirectSoundCaptureImpl_Create failed\n");
1301 /***************************************************************************
1302 * DirectSoundCaptureCreate [DSOUND.6]
1304 * Create and initialize a DirectSoundCapture interface.
1307 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
1308 * lplpDSC [O] Address of a variable to receive the interface pointer.
1309 * pUnkOuter [I] Must be NULL.
1313 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1317 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
1318 * or NULL for the default device or DSDEVID_DefaultCapture or
1319 * DSDEVID_DefaultVoiceCapture.
1321 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
1323 HRESULT WINAPI
DirectSoundCaptureCreate(LPCGUID lpcGUID
, IDirectSoundCapture
**ppDSC
,
1324 IUnknown
*pUnkOuter
)
1327 IDirectSoundCapture
*pDSC
;
1329 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC
, pUnkOuter
);
1331 if (ppDSC
== NULL
) {
1332 WARN("invalid parameter: ppDSC == NULL\n");
1333 return DSERR_INVALIDPARAM
;
1337 WARN("invalid parameter: pUnkOuter != NULL\n");
1339 return DSERR_NOAGGREGATION
;
1342 hr
= DSOUND_CaptureCreate(&IID_IDirectSoundCapture
, &pDSC
);
1344 hr
= IDirectSoundCapture_Initialize(pDSC
, lpcGUID
);
1346 IDirectSoundCapture_Release(pDSC
);
1356 /***************************************************************************
1357 * DirectSoundCaptureCreate8 [DSOUND.12]
1359 * Create and initialize a DirectSoundCapture interface.
1362 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
1363 * lplpDSC [O] Address of a variable to receive the interface pointer.
1364 * pUnkOuter [I] Must be NULL.
1368 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1372 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
1373 * or NULL for the default device or DSDEVID_DefaultCapture or
1374 * DSDEVID_DefaultVoiceCapture.
1376 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
1378 HRESULT WINAPI
DirectSoundCaptureCreate8(
1380 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
1381 LPUNKNOWN pUnkOuter
)
1384 LPDIRECTSOUNDCAPTURE8 pDSC8
;
1385 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC8
, pUnkOuter
);
1387 if (ppDSC8
== NULL
) {
1388 WARN("invalid parameter: ppDSC8 == NULL\n");
1389 return DSERR_INVALIDPARAM
;
1393 WARN("invalid parameter: pUnkOuter != NULL\n");
1395 return DSERR_NOAGGREGATION
;
1398 hr
= DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8
, &pDSC8
);
1400 hr
= IDirectSoundCapture_Initialize(pDSC8
, lpcGUID
);
1402 IDirectSoundCapture_Release(pDSC8
);