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
30 #define NONAMELESSSTRUCT
31 #define NONAMELESSUNION
39 #include "wine/debug.h"
42 #include "dsound_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
46 /*****************************************************************************
47 * IDirectSoundCapture implementation structure
49 struct IDirectSoundCaptureImpl
52 const IDirectSoundCaptureVtbl
*lpVtbl
;
55 DirectSoundCaptureDevice
*device
;
58 static HRESULT
IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8
* ppds
);
61 /*****************************************************************************
62 * IDirectSoundCaptureNotify implementation structure
64 struct IDirectSoundCaptureNotifyImpl
67 const IDirectSoundNotifyVtbl
*lpVtbl
;
69 IDirectSoundCaptureBufferImpl
* dscb
;
72 static HRESULT
IDirectSoundCaptureNotifyImpl_Create(IDirectSoundCaptureBufferImpl
*dscb
,
73 IDirectSoundCaptureNotifyImpl
** pdscn
);
76 DirectSoundCaptureDevice
* DSOUND_capture
[MAXWAVEDRIVERS
];
78 static HRESULT
DirectSoundCaptureDevice_Create(DirectSoundCaptureDevice
** ppDevice
);
80 static const char * const captureStateString
[] = {
87 HRESULT
DSOUND_CaptureCreate(
89 LPDIRECTSOUNDCAPTURE
*ppDSC
)
91 LPDIRECTSOUNDCAPTURE pDSC
;
93 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDSC
);
95 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
96 !IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
101 /* Get dsound configuration */
102 setup_dsound_options();
104 hr
= IDirectSoundCaptureImpl_Create(&pDSC
);
106 IDirectSoundCapture_AddRef(pDSC
);
109 WARN("IDirectSoundCaptureImpl_Create failed\n");
116 HRESULT
DSOUND_CaptureCreate8(
118 LPDIRECTSOUNDCAPTURE8
*ppDSC8
)
120 LPDIRECTSOUNDCAPTURE8 pDSC8
;
122 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDSC8
);
124 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
125 !IsEqualIID(riid
, &IID_IDirectSoundCapture8
)) {
127 return E_NOINTERFACE
;
130 /* Get dsound configuration */
131 setup_dsound_options();
133 hr
= IDirectSoundCaptureImpl_Create(&pDSC8
);
135 IDirectSoundCapture_AddRef(pDSC8
);
138 WARN("IDirectSoundCaptureImpl_Create failed\n");
145 /***************************************************************************
146 * DirectSoundCaptureCreate [DSOUND.6]
148 * Create and initialize a DirectSoundCapture interface.
151 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
152 * lplpDSC [O] Address of a variable to receive the interface pointer.
153 * pUnkOuter [I] Must be NULL.
157 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
161 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
162 * or NULL for the default device or DSDEVID_DefaultCapture or
163 * DSDEVID_DefaultVoiceCapture.
165 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
167 HRESULT WINAPI
DirectSoundCaptureCreate(
169 LPDIRECTSOUNDCAPTURE
*ppDSC
,
173 LPDIRECTSOUNDCAPTURE pDSC
;
174 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC
, pUnkOuter
);
177 WARN("invalid parameter: ppDSC == NULL\n");
178 return DSERR_INVALIDPARAM
;
182 WARN("invalid parameter: pUnkOuter != NULL\n");
184 return DSERR_NOAGGREGATION
;
187 hr
= DSOUND_CaptureCreate(&IID_IDirectSoundCapture
, &pDSC
);
189 hr
= IDirectSoundCapture_Initialize(pDSC
, lpcGUID
);
191 IDirectSoundCapture_Release(pDSC
);
201 /***************************************************************************
202 * DirectSoundCaptureCreate8 [DSOUND.12]
204 * Create and initialize a DirectSoundCapture interface.
207 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
208 * lplpDSC [O] Address of a variable to receive the interface pointer.
209 * pUnkOuter [I] Must be NULL.
213 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
217 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
218 * or NULL for the default device or DSDEVID_DefaultCapture or
219 * DSDEVID_DefaultVoiceCapture.
221 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
223 HRESULT WINAPI
DirectSoundCaptureCreate8(
225 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
229 LPDIRECTSOUNDCAPTURE8 pDSC8
;
230 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC8
, pUnkOuter
);
232 if (ppDSC8
== NULL
) {
233 WARN("invalid parameter: ppDSC8 == NULL\n");
234 return DSERR_INVALIDPARAM
;
238 WARN("invalid parameter: pUnkOuter != NULL\n");
240 return DSERR_NOAGGREGATION
;
243 hr
= DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8
, &pDSC8
);
245 hr
= IDirectSoundCapture_Initialize(pDSC8
, lpcGUID
);
247 IDirectSoundCapture_Release(pDSC8
);
257 /***************************************************************************
258 * DirectSoundCaptureEnumerateA [DSOUND.7]
260 * Enumerate all DirectSound drivers installed in the system.
263 * lpDSEnumCallback [I] Address of callback function.
264 * lpContext [I] Address of user defined context passed to callback function.
268 * Failure: DSERR_INVALIDPARAM
271 DirectSoundCaptureEnumerateA(
272 LPDSENUMCALLBACKA lpDSEnumCallback
,
280 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
282 if (lpDSEnumCallback
== NULL
) {
283 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
284 return DSERR_INVALIDPARAM
;
287 devs
= waveInGetNumDevs();
289 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
290 for (wid
= 0; wid
< devs
; ++wid
) {
291 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
292 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
294 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
295 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
296 if (lpDSEnumCallback(NULL
, "Primary Sound Capture Driver", desc
.szDrvname
, lpContext
) == FALSE
)
304 for (wid
= 0; wid
< devs
; ++wid
) {
305 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
307 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
308 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
309 if (lpDSEnumCallback(&DSOUND_capture_guids
[wid
], desc
.szDesc
, desc
.szDrvname
, lpContext
) == FALSE
)
317 /***************************************************************************
318 * DirectSoundCaptureEnumerateW [DSOUND.8]
320 * Enumerate all DirectSound drivers installed in the system.
323 * lpDSEnumCallback [I] Address of callback function.
324 * lpContext [I] Address of user defined context passed to callback function.
328 * Failure: DSERR_INVALIDPARAM
331 DirectSoundCaptureEnumerateW(
332 LPDSENUMCALLBACKW lpDSEnumCallback
,
339 WCHAR wDesc
[MAXPNAMELEN
];
340 WCHAR wName
[MAXPNAMELEN
];
342 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
344 if (lpDSEnumCallback
== NULL
) {
345 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
346 return DSERR_INVALIDPARAM
;
349 devs
= waveInGetNumDevs();
351 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
352 for (wid
= 0; wid
< devs
; ++wid
) {
353 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
354 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
356 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
357 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
358 MultiByteToWideChar( CP_ACP
, 0, "Primary Sound Capture Driver", -1,
359 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
360 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
361 wName
, sizeof(wName
)/sizeof(WCHAR
) );
362 if (lpDSEnumCallback(NULL
, wDesc
, wName
, lpContext
) == FALSE
)
370 for (wid
= 0; wid
< devs
; ++wid
) {
371 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
373 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
374 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
375 MultiByteToWideChar( CP_ACP
, 0, desc
.szDesc
, -1,
376 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
377 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
378 wName
, sizeof(wName
)/sizeof(WCHAR
) );
379 if (lpDSEnumCallback(&DSOUND_capture_guids
[wid
], wDesc
, wName
, lpContext
) == FALSE
)
387 static void capture_CheckNotify(IDirectSoundCaptureBufferImpl
*This
, DWORD from
, DWORD len
)
390 for (i
= 0; i
< This
->nrofnotifies
; ++i
) {
391 LPDSBPOSITIONNOTIFY event
= This
->notifies
+ i
;
392 DWORD offset
= event
->dwOffset
;
393 TRACE("checking %d, position %d, event = %p\n", i
, offset
, event
->hEventNotify
);
395 if (offset
== DSBPN_OFFSETSTOP
) {
397 SetEvent(event
->hEventNotify
);
398 TRACE("signalled event %p (%d)\n", event
->hEventNotify
, i
);
404 if (offset
>= from
&& offset
< (from
+ len
))
406 TRACE("signalled event %p (%d)\n", event
->hEventNotify
, i
);
407 SetEvent(event
->hEventNotify
);
413 DSOUND_capture_callback(
420 DirectSoundCaptureDevice
* This
= (DirectSoundCaptureDevice
*)dwUser
;
421 IDirectSoundCaptureBufferImpl
* Moi
= This
->capture_buffer
;
422 TRACE("(%p,%08x(%s),%08x,%08x,%08x) entering at %d\n",hwi
,msg
,
423 msg
== MM_WIM_OPEN
? "MM_WIM_OPEN" : msg
== MM_WIM_CLOSE
? "MM_WIM_CLOSE" :
424 msg
== MM_WIM_DATA
? "MM_WIM_DATA" : "UNKNOWN",dwUser
,dw1
,dw2
,GetTickCount());
426 if (msg
== MM_WIM_DATA
) {
427 EnterCriticalSection( &(This
->lock
) );
428 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
429 captureStateString
[This
->state
],This
->index
);
430 if (This
->state
!= STATE_STOPPED
) {
431 int index
= This
->index
;
432 if (This
->state
== STATE_STARTING
)
433 This
->state
= STATE_CAPTURING
;
434 capture_CheckNotify(Moi
, (DWORD_PTR
)This
->pwave
[index
].lpData
- (DWORD_PTR
)This
->buffer
, This
->pwave
[index
].dwBufferLength
);
435 This
->index
= (++This
->index
) % This
->nrofpwaves
;
436 if ( (This
->index
== 0) && !(This
->capture_buffer
->flags
& DSCBSTART_LOOPING
) ) {
437 TRACE("end of buffer\n");
438 This
->state
= STATE_STOPPED
;
439 capture_CheckNotify(Moi
, 0, 0);
441 if (This
->state
== STATE_CAPTURING
) {
442 waveInUnprepareHeader(hwi
, &(This
->pwave
[index
]), sizeof(WAVEHDR
));
443 waveInPrepareHeader(hwi
, &(This
->pwave
[index
]), sizeof(WAVEHDR
));
444 waveInAddBuffer(hwi
, &(This
->pwave
[index
]), sizeof(WAVEHDR
));
445 } else if (This
->state
== STATE_STOPPING
) {
447 This
->state
= STATE_STOPPED
;
451 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
452 captureStateString
[This
->state
],This
->index
);
453 LeaveCriticalSection( &(This
->lock
) );
456 TRACE("completed\n");
459 /***************************************************************************
460 * IDirectSoundCaptureImpl
462 static HRESULT WINAPI
463 IDirectSoundCaptureImpl_QueryInterface(
464 LPDIRECTSOUNDCAPTURE iface
,
468 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
469 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
472 WARN("invalid parameter\n");
478 if (IsEqualIID(riid
, &IID_IUnknown
)) {
479 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
482 } else if (IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
483 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
488 WARN("unsupported riid: %s\n", debugstr_guid(riid
));
489 return E_NOINTERFACE
;
493 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface
)
495 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
496 ULONG ref
= InterlockedIncrement(&(This
->ref
));
497 TRACE("(%p) ref was %d\n", This
, ref
- 1);
502 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface
)
504 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
505 ULONG ref
= InterlockedDecrement(&(This
->ref
));
506 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
510 DirectSoundCaptureDevice_Release(This
->device
);
512 HeapFree( GetProcessHeap(), 0, This
);
513 TRACE("(%p) released\n", This
);
518 HRESULT WINAPI
IDirectSoundCaptureImpl_CreateCaptureBuffer(
519 LPDIRECTSOUNDCAPTURE iface
,
520 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
521 LPDIRECTSOUNDCAPTUREBUFFER
* lplpDSCaptureBuffer
,
525 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
527 TRACE( "(%p,%p,%p,%p)\n",iface
,lpcDSCBufferDesc
,lplpDSCaptureBuffer
,pUnk
);
529 if (lpcDSCBufferDesc
== NULL
) {
530 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
531 return DSERR_INVALIDPARAM
;
534 if (lplpDSCaptureBuffer
== NULL
) {
535 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
536 return DSERR_INVALIDPARAM
;
540 WARN("invalid parameter: pUnk != NULL\n");
541 return DSERR_INVALIDPARAM
;
544 /* FIXME: We can only have one buffer so what do we do here? */
545 if (This
->device
->capture_buffer
) {
546 WARN("lnvalid parameter: already has buffer\n");
547 return DSERR_INVALIDPARAM
; /* DSERR_GENERIC ? */
550 hr
= IDirectSoundCaptureBufferImpl_Create(This
->device
,
551 (IDirectSoundCaptureBufferImpl
**)lplpDSCaptureBuffer
, lpcDSCBufferDesc
);
554 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
559 HRESULT WINAPI
IDirectSoundCaptureImpl_GetCaps(
560 LPDIRECTSOUNDCAPTURE iface
,
561 LPDSCCAPS lpDSCCaps
)
563 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
564 TRACE("(%p,%p)\n",This
,lpDSCCaps
);
566 if (This
->device
== NULL
) {
567 WARN("not initialized\n");
568 return DSERR_UNINITIALIZED
;
571 if (lpDSCCaps
== NULL
) {
572 WARN("invalid parameter: lpDSCCaps== NULL\n");
573 return DSERR_INVALIDPARAM
;
576 if (lpDSCCaps
->dwSize
< sizeof(*lpDSCCaps
)) {
577 WARN("invalid parameter: lpDSCCaps->dwSize = %d\n", lpDSCCaps
->dwSize
);
578 return DSERR_INVALIDPARAM
;
581 lpDSCCaps
->dwFlags
= This
->device
->drvcaps
.dwFlags
;
582 lpDSCCaps
->dwFormats
= This
->device
->drvcaps
.dwFormats
;
583 lpDSCCaps
->dwChannels
= This
->device
->drvcaps
.dwChannels
;
585 TRACE("(flags=0x%08x,format=0x%08x,channels=%d)\n",lpDSCCaps
->dwFlags
,
586 lpDSCCaps
->dwFormats
, lpDSCCaps
->dwChannels
);
591 HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(
592 LPDIRECTSOUNDCAPTURE iface
,
595 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
596 TRACE("(%p,%s)\n", This
, debugstr_guid(lpcGUID
));
598 if (This
->device
!= NULL
) {
599 WARN("already initialized\n");
600 return DSERR_ALREADYINITIALIZED
;
602 return DirectSoundCaptureDevice_Initialize(&This
->device
, lpcGUID
);
605 static const IDirectSoundCaptureVtbl dscvt
=
607 /* IUnknown methods */
608 IDirectSoundCaptureImpl_QueryInterface
,
609 IDirectSoundCaptureImpl_AddRef
,
610 IDirectSoundCaptureImpl_Release
,
612 /* IDirectSoundCapture methods */
613 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
614 IDirectSoundCaptureImpl_GetCaps
,
615 IDirectSoundCaptureImpl_Initialize
618 static HRESULT
IDirectSoundCaptureImpl_Create(
619 LPDIRECTSOUNDCAPTURE8
* ppDSC
)
621 IDirectSoundCaptureImpl
*pDSC
;
622 TRACE("(%p)\n", ppDSC
);
624 /* Allocate memory */
625 pDSC
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundCaptureImpl
));
627 WARN("out of memory\n");
629 return DSERR_OUTOFMEMORY
;
632 pDSC
->lpVtbl
= &dscvt
;
636 *ppDSC
= (LPDIRECTSOUNDCAPTURE8
)pDSC
;
641 /*******************************************************************************
642 * IDirectSoundCaptureNotify
644 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_QueryInterface(
645 LPDIRECTSOUNDNOTIFY iface
,
649 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
650 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
652 if (This
->dscb
== NULL
) {
653 WARN("invalid parameter\n");
657 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
, riid
, ppobj
);
660 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface
)
662 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
663 ULONG ref
= InterlockedIncrement(&(This
->ref
));
664 TRACE("(%p) ref was %d\n", This
, ref
- 1);
668 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface
)
670 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
671 ULONG ref
= InterlockedDecrement(&(This
->ref
));
672 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
675 if (This
->dscb
->hwnotify
)
676 IDsDriverNotify_Release(This
->dscb
->hwnotify
);
677 This
->dscb
->notify
=NULL
;
678 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
);
679 HeapFree(GetProcessHeap(),0,This
);
680 TRACE("(%p) released\n", This
);
685 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
686 LPDIRECTSOUNDNOTIFY iface
,
688 LPCDSBPOSITIONNOTIFY notify
)
690 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
691 TRACE("(%p,0x%08x,%p)\n",This
,howmuch
,notify
);
693 if (howmuch
> 0 && notify
== NULL
) {
694 WARN("invalid parameter: notify == NULL\n");
695 return DSERR_INVALIDPARAM
;
698 if (TRACE_ON(dsound
)) {
700 for (i
=0;i
<howmuch
;i
++)
701 TRACE("notify at %d to %p\n",
702 notify
[i
].dwOffset
,notify
[i
].hEventNotify
);
705 if (This
->dscb
->hwnotify
) {
707 hres
= IDsDriverNotify_SetNotificationPositions(This
->dscb
->hwnotify
, howmuch
, notify
);
709 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
711 } else if (howmuch
> 0) {
712 /* Make an internal copy of the caller-supplied array.
713 * Replace the existing copy if one is already present. */
714 if (This
->dscb
->notifies
)
715 This
->dscb
->notifies
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
716 This
->dscb
->notifies
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
718 This
->dscb
->notifies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
719 howmuch
* sizeof(DSBPOSITIONNOTIFY
));
721 if (This
->dscb
->notifies
== NULL
) {
722 WARN("out of memory\n");
723 return DSERR_OUTOFMEMORY
;
725 CopyMemory(This
->dscb
->notifies
, notify
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
726 This
->dscb
->nrofnotifies
= howmuch
;
728 HeapFree(GetProcessHeap(), 0, This
->dscb
->notifies
);
729 This
->dscb
->notifies
= NULL
;
730 This
->dscb
->nrofnotifies
= 0;
736 static const IDirectSoundNotifyVtbl dscnvt
=
738 IDirectSoundCaptureNotifyImpl_QueryInterface
,
739 IDirectSoundCaptureNotifyImpl_AddRef
,
740 IDirectSoundCaptureNotifyImpl_Release
,
741 IDirectSoundCaptureNotifyImpl_SetNotificationPositions
,
744 static HRESULT
IDirectSoundCaptureNotifyImpl_Create(
745 IDirectSoundCaptureBufferImpl
*dscb
,
746 IDirectSoundCaptureNotifyImpl
**pdscn
)
748 IDirectSoundCaptureNotifyImpl
* dscn
;
749 TRACE("(%p,%p)\n",dscb
,pdscn
);
751 dscn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*dscn
));
754 WARN("out of memory\n");
755 return DSERR_OUTOFMEMORY
;
759 dscn
->lpVtbl
= &dscnvt
;
762 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER
)dscb
);
768 /*******************************************************************************
769 * IDirectSoundCaptureBuffer
771 static HRESULT WINAPI
772 IDirectSoundCaptureBufferImpl_QueryInterface(
773 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
777 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
779 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
782 WARN("invalid parameter\n");
788 if ( IsEqualGUID( &IID_IDirectSoundNotify
, riid
) ) {
790 hres
= IDirectSoundCaptureNotifyImpl_Create(This
, &This
->notify
);
792 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY
)This
->notify
);
793 if (This
->device
->hwbuf
&& !This
->hwnotify
) {
794 hres
= IDsCaptureDriverBuffer_QueryInterface(This
->device
->hwbuf
,
795 &IID_IDsDriverNotify
, (LPVOID
*)&(This
->hwnotify
));
797 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
798 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
804 *ppobj
= (LPVOID
)This
->notify
;
808 WARN("IID_IDirectSoundNotify\n");
812 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer
, riid
) ||
813 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8
, riid
) ) {
814 IDirectSoundCaptureBuffer8_AddRef(iface
);
819 FIXME("(%p,%s,%p) unsupported GUID\n", This
, debugstr_guid(riid
), ppobj
);
820 return E_NOINTERFACE
;
824 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
826 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
827 ULONG ref
= InterlockedIncrement(&(This
->ref
));
828 TRACE("(%p) ref was %d\n", This
, ref
- 1);
833 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
835 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
836 ULONG ref
= InterlockedDecrement(&(This
->ref
));
837 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
840 TRACE("deleting object\n");
841 if (This
->device
->state
== STATE_CAPTURING
)
842 This
->device
->state
= STATE_STOPPING
;
844 HeapFree(GetProcessHeap(),0, This
->pdscbd
);
846 if (This
->device
->hwi
) {
847 waveInReset(This
->device
->hwi
);
848 waveInClose(This
->device
->hwi
);
849 HeapFree(GetProcessHeap(),0, This
->device
->pwave
);
850 This
->device
->pwave
= 0;
851 This
->device
->hwi
= 0;
854 if (This
->device
->hwbuf
)
855 IDsCaptureDriverBuffer_Release(This
->device
->hwbuf
);
857 /* remove from DirectSoundCaptureDevice */
858 This
->device
->capture_buffer
= NULL
;
861 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
863 /* If driver manages its own buffer, IDsCaptureDriverBuffer_Release
864 should have freed the buffer. Prevent freeing it again in
865 IDirectSoundCaptureBufferImpl_Create */
866 if (!(This
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
))
867 This
->device
->buffer
= NULL
;
869 HeapFree(GetProcessHeap(), 0, This
->notifies
);
870 HeapFree( GetProcessHeap(), 0, This
);
871 TRACE("(%p) released\n", This
);
876 static HRESULT WINAPI
877 IDirectSoundCaptureBufferImpl_GetCaps(
878 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
879 LPDSCBCAPS lpDSCBCaps
)
881 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
882 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
884 if (lpDSCBCaps
== NULL
) {
885 WARN("invalid parameter: lpDSCBCaps == NULL\n");
886 return DSERR_INVALIDPARAM
;
889 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
890 WARN("invalid parameter: lpDSCBCaps->dwSize = %d\n", lpDSCBCaps
->dwSize
);
891 return DSERR_INVALIDPARAM
;
894 if (This
->device
== NULL
) {
895 WARN("invalid parameter: This->device == NULL\n");
896 return DSERR_INVALIDPARAM
;
899 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
900 lpDSCBCaps
->dwFlags
= This
->flags
;
901 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
902 lpDSCBCaps
->dwReserved
= 0;
904 TRACE("returning DS_OK\n");
908 static HRESULT WINAPI
909 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
910 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
911 LPDWORD lpdwCapturePosition
,
912 LPDWORD lpdwReadPosition
)
914 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
915 HRESULT hres
= DS_OK
;
916 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
918 if (This
->device
== NULL
) {
919 WARN("invalid parameter: This->device == NULL\n");
920 return DSERR_INVALIDPARAM
;
923 if (This
->device
->driver
) {
924 hres
= IDsCaptureDriverBuffer_GetPosition(This
->device
->hwbuf
, lpdwCapturePosition
, lpdwReadPosition
);
926 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
927 } else if (This
->device
->hwi
) {
930 EnterCriticalSection(&This
->device
->lock
);
931 pos
= (DWORD_PTR
)This
->device
->pwave
[This
->device
->index
].lpData
- (DWORD_PTR
)This
->device
->buffer
;
932 if (lpdwCapturePosition
)
933 *lpdwCapturePosition
= (This
->device
->pwave
[This
->device
->index
].dwBufferLength
+ pos
) % This
->device
->buflen
;
934 if (lpdwReadPosition
)
935 *lpdwReadPosition
= pos
;
936 LeaveCriticalSection(&This
->device
->lock
);
940 hres
= DSERR_NODRIVER
;
943 TRACE("cappos=%d readpos=%d\n", (lpdwCapturePosition
?*lpdwCapturePosition
:-1), (lpdwReadPosition
?*lpdwReadPosition
:-1));
944 TRACE("returning %08x\n", hres
);
948 static HRESULT WINAPI
949 IDirectSoundCaptureBufferImpl_GetFormat(
950 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
951 LPWAVEFORMATEX lpwfxFormat
,
952 DWORD dwSizeAllocated
,
953 LPDWORD lpdwSizeWritten
)
955 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
956 HRESULT hres
= DS_OK
;
957 TRACE( "(%p,%p,0x%08x,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
960 if (This
->device
== NULL
) {
961 WARN("invalid parameter: This->device == NULL\n");
962 return DSERR_INVALIDPARAM
;
965 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
))
966 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
968 if (lpwfxFormat
) { /* NULL is valid (just want size) */
969 CopyMemory(lpwfxFormat
, This
->device
->pwfx
, dwSizeAllocated
);
971 *lpdwSizeWritten
= dwSizeAllocated
;
974 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
976 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
977 hres
= DSERR_INVALIDPARAM
;
981 TRACE("returning %08x\n", hres
);
985 static HRESULT WINAPI
986 IDirectSoundCaptureBufferImpl_GetStatus(
987 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
990 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
991 TRACE( "(%p, %p), thread is %04x\n", This
, lpdwStatus
, GetCurrentThreadId() );
993 if (This
->device
== NULL
) {
994 WARN("invalid parameter: This->device == NULL\n");
995 return DSERR_INVALIDPARAM
;
998 if (lpdwStatus
== NULL
) {
999 WARN("invalid parameter: lpdwStatus == NULL\n");
1000 return DSERR_INVALIDPARAM
;
1004 EnterCriticalSection(&(This
->device
->lock
));
1006 TRACE("old This->device->state=%s, old lpdwStatus=%08x\n",
1007 captureStateString
[This
->device
->state
],*lpdwStatus
);
1008 if ((This
->device
->state
== STATE_STARTING
) ||
1009 (This
->device
->state
== STATE_CAPTURING
)) {
1010 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
1011 if (This
->flags
& DSCBSTART_LOOPING
)
1012 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
1014 TRACE("new This->device->state=%s, new lpdwStatus=%08x\n",
1015 captureStateString
[This
->device
->state
],*lpdwStatus
);
1016 LeaveCriticalSection(&(This
->device
->lock
));
1018 TRACE("status=%x\n", *lpdwStatus
);
1019 TRACE("returning DS_OK\n");
1023 static HRESULT WINAPI
1024 IDirectSoundCaptureBufferImpl_Initialize(
1025 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1026 LPDIRECTSOUNDCAPTURE lpDSC
,
1027 LPCDSCBUFFERDESC lpcDSCBDesc
)
1029 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1031 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
1036 static HRESULT WINAPI
1037 IDirectSoundCaptureBufferImpl_Lock(
1038 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1041 LPVOID
* lplpvAudioPtr1
,
1042 LPDWORD lpdwAudioBytes1
,
1043 LPVOID
* lplpvAudioPtr2
,
1044 LPDWORD lpdwAudioBytes2
,
1047 HRESULT hres
= DS_OK
;
1048 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1049 TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This
, dwReadCusor
,
1050 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
1051 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
1053 if (This
->device
== NULL
) {
1054 WARN("invalid parameter: This->device == NULL\n");
1055 return DSERR_INVALIDPARAM
;
1058 if (lplpvAudioPtr1
== NULL
) {
1059 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1060 return DSERR_INVALIDPARAM
;
1063 if (lpdwAudioBytes1
== NULL
) {
1064 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1065 return DSERR_INVALIDPARAM
;
1068 EnterCriticalSection(&(This
->device
->lock
));
1070 if (This
->device
->driver
) {
1071 hres
= IDsCaptureDriverBuffer_Lock(This
->device
->hwbuf
, lplpvAudioPtr1
,
1072 lpdwAudioBytes1
, lplpvAudioPtr2
,
1073 lpdwAudioBytes2
, dwReadCusor
,
1074 dwReadBytes
, dwFlags
);
1076 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1077 } else if (This
->device
->hwi
) {
1078 *lplpvAudioPtr1
= This
->device
->buffer
+ dwReadCusor
;
1079 if ( (dwReadCusor
+ dwReadBytes
) > This
->device
->buflen
) {
1080 *lpdwAudioBytes1
= This
->device
->buflen
- dwReadCusor
;
1082 *lplpvAudioPtr2
= This
->device
->buffer
;
1083 if (lpdwAudioBytes2
)
1084 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
1086 *lpdwAudioBytes1
= dwReadBytes
;
1088 *lplpvAudioPtr2
= 0;
1089 if (lpdwAudioBytes2
)
1090 *lpdwAudioBytes2
= 0;
1093 TRACE("invalid call\n");
1094 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
1097 LeaveCriticalSection(&(This
->device
->lock
));
1099 TRACE("returning %08x\n", hres
);
1103 static HRESULT WINAPI
1104 IDirectSoundCaptureBufferImpl_Start(
1105 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1108 HRESULT hres
= DS_OK
;
1109 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1110 TRACE( "(%p,0x%08x)\n", This
, dwFlags
);
1112 if (This
->device
== NULL
) {
1113 WARN("invalid parameter: This->device == NULL\n");
1114 return DSERR_INVALIDPARAM
;
1117 if ( (This
->device
->driver
== 0) && (This
->device
->hwi
== 0) ) {
1118 WARN("no driver\n");
1119 return DSERR_NODRIVER
;
1122 EnterCriticalSection(&(This
->device
->lock
));
1124 This
->flags
= dwFlags
;
1125 TRACE("old This->state=%s\n",captureStateString
[This
->device
->state
]);
1126 if (This
->device
->state
== STATE_STOPPED
)
1127 This
->device
->state
= STATE_STARTING
;
1128 else if (This
->device
->state
== STATE_STOPPING
)
1129 This
->device
->state
= STATE_CAPTURING
;
1130 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1132 LeaveCriticalSection(&(This
->device
->lock
));
1134 if (This
->device
->driver
) {
1135 hres
= IDsCaptureDriverBuffer_Start(This
->device
->hwbuf
, dwFlags
);
1137 WARN("IDsCaptureDriverBuffer_Start failed\n");
1138 } else if (This
->device
->hwi
) {
1139 DirectSoundCaptureDevice
*device
= This
->device
;
1141 if (device
->buffer
) {
1143 DWORD blocksize
= DSOUND_fraglen(device
->pwfx
->nSamplesPerSec
, device
->pwfx
->nBlockAlign
);
1144 device
->nrofpwaves
= device
->buflen
/ blocksize
+ !!(device
->buflen
% blocksize
);
1145 TRACE("nrofpwaves=%d\n", device
->nrofpwaves
);
1147 /* prepare headers */
1149 device
->pwave
= HeapReAlloc(GetProcessHeap(), 0,device
->pwave
, device
->nrofpwaves
*sizeof(WAVEHDR
));
1151 device
->pwave
= HeapAlloc(GetProcessHeap(), 0, device
->nrofpwaves
*sizeof(WAVEHDR
));
1153 for (c
= 0; c
< device
->nrofpwaves
; ++c
) {
1154 device
->pwave
[c
].lpData
= (char *)device
->buffer
+ c
* blocksize
;
1155 if (c
+ 1 == device
->nrofpwaves
)
1156 device
->pwave
[c
].dwBufferLength
= device
->buflen
- c
* blocksize
;
1158 device
->pwave
[c
].dwBufferLength
= blocksize
;
1159 device
->pwave
[c
].dwBytesRecorded
= 0;
1160 device
->pwave
[c
].dwUser
= (DWORD
)device
;
1161 device
->pwave
[c
].dwFlags
= 0;
1162 device
->pwave
[c
].dwLoops
= 0;
1163 hres
= mmErr(waveInPrepareHeader(device
->hwi
, &(device
->pwave
[c
]),sizeof(WAVEHDR
)));
1164 if (hres
!= DS_OK
) {
1165 WARN("waveInPrepareHeader failed\n");
1167 waveInUnprepareHeader(device
->hwi
, &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1171 hres
= mmErr(waveInAddBuffer(device
->hwi
, &(device
->pwave
[c
]), sizeof(WAVEHDR
)));
1172 if (hres
!= DS_OK
) {
1173 WARN("waveInAddBuffer failed\n");
1175 waveInUnprepareHeader(device
->hwi
, &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1180 FillMemory(device
->buffer
, device
->buflen
, (device
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
1185 if (hres
== DS_OK
) {
1186 /* start filling the first buffer */
1187 hres
= mmErr(waveInStart(device
->hwi
));
1189 WARN("waveInStart failed\n");
1192 if (hres
!= DS_OK
) {
1193 WARN("calling waveInClose because of error\n");
1194 waveInClose(device
->hwi
);
1198 WARN("no driver\n");
1199 hres
= DSERR_NODRIVER
;
1202 TRACE("returning %08x\n", hres
);
1206 static HRESULT WINAPI
1207 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1209 HRESULT hres
= DS_OK
;
1210 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1211 TRACE( "(%p)\n", This
);
1213 if (This
->device
== NULL
) {
1214 WARN("invalid parameter: This->device == NULL\n");
1215 return DSERR_INVALIDPARAM
;
1218 EnterCriticalSection(&(This
->device
->lock
));
1220 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1221 if (This
->device
->state
== STATE_CAPTURING
)
1222 This
->device
->state
= STATE_STOPPING
;
1223 else if (This
->device
->state
== STATE_STARTING
)
1224 This
->device
->state
= STATE_STOPPED
;
1225 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1227 LeaveCriticalSection(&(This
->device
->lock
));
1229 if (This
->device
->driver
) {
1230 hres
= IDsCaptureDriverBuffer_Stop(This
->device
->hwbuf
);
1232 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1233 } else if (This
->device
->hwi
) {
1234 hres
= mmErr(waveInReset(This
->device
->hwi
));
1236 WARN("waveInReset() failed\n");
1238 WARN("no driver\n");
1239 hres
= DSERR_NODRIVER
;
1242 TRACE("returning %08x\n", hres
);
1246 static HRESULT WINAPI
1247 IDirectSoundCaptureBufferImpl_Unlock(
1248 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1249 LPVOID lpvAudioPtr1
,
1250 DWORD dwAudioBytes1
,
1251 LPVOID lpvAudioPtr2
,
1252 DWORD dwAudioBytes2
)
1254 HRESULT hres
= DS_OK
;
1255 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1256 TRACE( "(%p,%p,%08u,%p,%08u)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
1257 lpvAudioPtr2
, dwAudioBytes2
);
1259 if (lpvAudioPtr1
== NULL
) {
1260 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1261 return DSERR_INVALIDPARAM
;
1264 if (This
->device
->driver
) {
1265 hres
= IDsCaptureDriverBuffer_Unlock(This
->device
->hwbuf
, lpvAudioPtr1
,
1266 dwAudioBytes1
, lpvAudioPtr2
, dwAudioBytes2
);
1268 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1269 } else if (!This
->device
->hwi
) {
1270 WARN("invalid call\n");
1271 hres
= DSERR_INVALIDCALL
;
1274 TRACE("returning %08x\n", hres
);
1278 static HRESULT WINAPI
1279 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1280 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1281 REFGUID rguidObject
,
1283 REFGUID rguidInterface
,
1286 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1288 FIXME( "(%p,%s,%u,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
1289 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
1294 static HRESULT WINAPI
1295 IDirectSoundCaptureBufferImpl_GetFXStatus(
1296 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1298 LPDWORD pdwFXStatus
)
1300 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1302 FIXME( "(%p,%u,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
1307 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
=
1309 /* IUnknown methods */
1310 IDirectSoundCaptureBufferImpl_QueryInterface
,
1311 IDirectSoundCaptureBufferImpl_AddRef
,
1312 IDirectSoundCaptureBufferImpl_Release
,
1314 /* IDirectSoundCaptureBuffer methods */
1315 IDirectSoundCaptureBufferImpl_GetCaps
,
1316 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
1317 IDirectSoundCaptureBufferImpl_GetFormat
,
1318 IDirectSoundCaptureBufferImpl_GetStatus
,
1319 IDirectSoundCaptureBufferImpl_Initialize
,
1320 IDirectSoundCaptureBufferImpl_Lock
,
1321 IDirectSoundCaptureBufferImpl_Start
,
1322 IDirectSoundCaptureBufferImpl_Stop
,
1323 IDirectSoundCaptureBufferImpl_Unlock
,
1325 /* IDirectSoundCaptureBuffer methods */
1326 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
1327 IDirectSoundCaptureBufferImpl_GetFXStatus
1330 HRESULT
IDirectSoundCaptureBufferImpl_Create(
1331 DirectSoundCaptureDevice
*device
,
1332 IDirectSoundCaptureBufferImpl
** ppobj
,
1333 LPCDSCBUFFERDESC lpcDSCBufferDesc
)
1335 LPWAVEFORMATEX wfex
;
1336 TRACE( "(%p,%p,%p)\n", device
, ppobj
, lpcDSCBufferDesc
);
1338 if (ppobj
== NULL
) {
1339 WARN("invalid parameter: ppobj == NULL\n");
1340 return DSERR_INVALIDPARAM
;
1344 WARN("not initialized\n");
1346 return DSERR_UNINITIALIZED
;
1349 if (lpcDSCBufferDesc
== NULL
) {
1350 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
1352 return DSERR_INVALIDPARAM
;
1355 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
1356 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
1357 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
1358 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) {
1359 WARN("invalid lpcDSCBufferDesc\n");
1361 return DSERR_INVALIDPARAM
;
1364 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
1367 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1368 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1369 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
1370 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
1371 wfex
->wBitsPerSample
, wfex
->cbSize
);
1373 if (wfex
->wFormatTag
== WAVE_FORMAT_PCM
) {
1374 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
));
1375 *device
->pwfx
= *wfex
;
1376 device
->pwfx
->cbSize
= 0;
1378 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1379 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1382 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
1384 return DSERR_INVALIDPARAM
; /* FIXME: DSERR_BADFORMAT ? */
1387 *ppobj
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1388 sizeof(IDirectSoundCaptureBufferImpl
));
1390 if ( *ppobj
== NULL
) {
1391 WARN("out of memory\n");
1393 return DSERR_OUTOFMEMORY
;
1395 HRESULT err
= DS_OK
;
1398 IDirectSoundCaptureBufferImpl
*This
= *ppobj
;
1401 This
->device
= device
;
1402 This
->device
->capture_buffer
= This
;
1403 This
->notify
= NULL
;
1404 This
->nrofnotifies
= 0;
1405 This
->hwnotify
= NULL
;
1407 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1408 lpcDSCBufferDesc
->dwSize
);
1410 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
1412 WARN("no memory\n");
1413 This
->device
->capture_buffer
= 0;
1414 HeapFree( GetProcessHeap(), 0, This
);
1416 return DSERR_OUTOFMEMORY
;
1419 This
->lpVtbl
= &dscbvt
;
1421 if (device
->driver
) {
1422 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1423 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
1425 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
1426 /* allocate buffer from system memory */
1427 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1428 TRACE("desired buflen=%d, old buffer=%p\n", buflen
, device
->buffer
);
1430 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1432 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1434 if (newbuf
== NULL
) {
1435 WARN("failed to allocate capture buffer\n");
1436 err
= DSERR_OUTOFMEMORY
;
1437 /* but the old buffer might still exist and must be re-prepared */
1439 device
->buffer
= newbuf
;
1440 device
->buflen
= buflen
;
1443 /* let driver allocate memory */
1444 device
->buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1446 HeapFree( GetProcessHeap(), 0, device
->buffer
);
1447 device
->buffer
= NULL
;
1450 err
= IDsCaptureDriver_CreateCaptureBuffer(device
->driver
,
1451 device
->pwfx
,0,0,&(device
->buflen
),&(device
->buffer
),(LPVOID
*)&(device
->hwbuf
));
1453 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1454 This
->device
->capture_buffer
= 0;
1455 HeapFree( GetProcessHeap(), 0, This
);
1460 DWORD flags
= CALLBACK_FUNCTION
;
1461 err
= mmErr(waveInOpen(&(device
->hwi
),
1462 device
->drvdesc
.dnDevNode
, device
->pwfx
,
1463 (DWORD_PTR
)DSOUND_capture_callback
, (DWORD
)device
, flags
));
1465 WARN("waveInOpen failed\n");
1466 This
->device
->capture_buffer
= 0;
1467 HeapFree( GetProcessHeap(), 0, This
);
1472 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1473 TRACE("desired buflen=%d, old buffer=%p\n", buflen
, device
->buffer
);
1475 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1477 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1478 if (newbuf
== NULL
) {
1479 WARN("failed to allocate capture buffer\n");
1480 err
= DSERR_OUTOFMEMORY
;
1481 /* but the old buffer might still exist and must be re-prepared */
1483 device
->buffer
= newbuf
;
1484 device
->buflen
= buflen
;
1489 TRACE("returning DS_OK\n");
1493 /*******************************************************************************
1494 * DirectSoundCaptureDevice
1496 HRESULT
DirectSoundCaptureDevice_Initialize(
1497 DirectSoundCaptureDevice
** ppDevice
,
1500 HRESULT err
= DSERR_INVALIDPARAM
;
1502 BOOLEAN found
= FALSE
;
1504 DirectSoundCaptureDevice
*device
= *ppDevice
;
1505 TRACE("(%p, %s)\n", ppDevice
, debugstr_guid(lpcGUID
));
1507 /* Default device? */
1508 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
1509 lpcGUID
= &DSDEVID_DefaultCapture
;
1511 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1512 WARN("invalid parameter: lpcGUID\n");
1513 return DSERR_INVALIDPARAM
;
1516 widn
= waveInGetNumDevs();
1518 WARN("no audio devices found\n");
1519 return DSERR_NODRIVER
;
1522 /* enumerate WINMM audio devices and find the one we want */
1523 for (wid
=0; wid
<widn
; wid
++) {
1524 if (IsEqualGUID( &devGUID
, &DSOUND_capture_guids
[wid
]) ) {
1530 if (found
== FALSE
) {
1531 WARN("No device found matching given ID!\n");
1532 return DSERR_NODRIVER
;
1535 if (DSOUND_capture
[wid
]) {
1536 WARN("already in use\n");
1537 return DSERR_ALLOCATED
;
1540 err
= DirectSoundCaptureDevice_Create(&(device
));
1542 WARN("DirectSoundCaptureDevice_Create failed\n");
1547 device
->guid
= devGUID
;
1549 /* Disable the direct sound driver to force emulation if requested. */
1550 device
->driver
= NULL
;
1551 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
1553 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDIFACE
,(DWORD_PTR
)&(device
->driver
),0));
1554 if ( (err
!= DS_OK
) && (err
!= DSERR_UNSUPPORTED
) ) {
1555 WARN("waveInMessage failed; err=%x\n",err
);
1561 /* Get driver description */
1562 if (device
->driver
) {
1563 TRACE("using DirectSound driver\n");
1564 err
= IDsCaptureDriver_GetDriverDesc(device
->driver
, &(device
->drvdesc
));
1566 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
1570 TRACE("using WINMM\n");
1571 /* if no DirectSound interface available, use WINMM API instead */
1572 device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
|
1573 DSDDESC_DOMMSYSTEMSETFORMAT
;
1576 device
->drvdesc
.dnDevNode
= wid
;
1578 /* open the DirectSound driver if available */
1579 if (device
->driver
&& (err
== DS_OK
))
1580 err
= IDsCaptureDriver_Open(device
->driver
);
1585 /* the driver is now open, so it's now allowed to call GetCaps */
1586 if (device
->driver
) {
1587 device
->drvcaps
.dwSize
= sizeof(device
->drvcaps
);
1588 err
= IDsCaptureDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1590 WARN("IDsCaptureDriver_GetCaps failed\n");
1593 } else /*if (device->hwi)*/ {
1595 err
= mmErr(waveInGetDevCapsA((UINT
)device
->drvdesc
.dnDevNode
, &wic
, sizeof(wic
)));
1598 device
->drvcaps
.dwFlags
= 0;
1599 lstrcpynA(device
->drvdesc
.szDrvname
, wic
.szPname
,
1600 sizeof(device
->drvdesc
.szDrvname
));
1602 device
->drvcaps
.dwFlags
|= DSCCAPS_EMULDRIVER
;
1603 device
->drvcaps
.dwFormats
= wic
.dwFormats
;
1604 device
->drvcaps
.dwChannels
= wic
.wChannels
;
1612 static HRESULT
DirectSoundCaptureDevice_Create(
1613 DirectSoundCaptureDevice
** ppDevice
)
1615 DirectSoundCaptureDevice
* device
;
1616 TRACE("(%p)\n", ppDevice
);
1618 /* Allocate memory */
1619 device
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DirectSoundCaptureDevice
));
1621 if (device
== NULL
) {
1622 WARN("out of memory\n");
1623 return DSERR_OUTOFMEMORY
;
1627 device
->state
= STATE_STOPPED
;
1629 InitializeCriticalSection( &(device
->lock
) );
1630 device
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundCaptureDevice.lock");
1637 ULONG
DirectSoundCaptureDevice_AddRef(
1638 DirectSoundCaptureDevice
* device
)
1640 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1641 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1645 ULONG
DirectSoundCaptureDevice_Release(
1646 DirectSoundCaptureDevice
* device
)
1648 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1649 TRACE("(%p) ref was %d\n", device
, ref
+ 1);
1652 TRACE("deleting object\n");
1653 if (device
->capture_buffer
)
1654 IDirectSoundCaptureBufferImpl_Release(
1655 (LPDIRECTSOUNDCAPTUREBUFFER8
) device
->capture_buffer
);
1657 if (device
->driver
) {
1658 IDsCaptureDriver_Close(device
->driver
);
1659 IDsCaptureDriver_Release(device
->driver
);
1662 HeapFree(GetProcessHeap(), 0, device
->pwfx
);
1663 device
->lock
.DebugInfo
->Spare
[0] = 0;
1664 DeleteCriticalSection( &(device
->lock
) );
1665 DSOUND_capture
[device
->drvdesc
.dnDevNode
] = NULL
;
1666 HeapFree(GetProcessHeap(), 0, device
);
1667 TRACE("(%p) released\n", device
);