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 HeapFree(GetProcessHeap(), 0, This
->notifies
);
864 HeapFree( GetProcessHeap(), 0, This
);
865 TRACE("(%p) released\n", This
);
870 static HRESULT WINAPI
871 IDirectSoundCaptureBufferImpl_GetCaps(
872 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
873 LPDSCBCAPS lpDSCBCaps
)
875 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
876 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
878 if (lpDSCBCaps
== NULL
) {
879 WARN("invalid parameter: lpDSCBCaps == NULL\n");
880 return DSERR_INVALIDPARAM
;
883 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
884 WARN("invalid parameter: lpDSCBCaps->dwSize = %d\n", lpDSCBCaps
->dwSize
);
885 return DSERR_INVALIDPARAM
;
888 if (This
->device
== NULL
) {
889 WARN("invalid parameter: This->device == NULL\n");
890 return DSERR_INVALIDPARAM
;
893 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
894 lpDSCBCaps
->dwFlags
= This
->flags
;
895 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
896 lpDSCBCaps
->dwReserved
= 0;
898 TRACE("returning DS_OK\n");
902 static HRESULT WINAPI
903 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
904 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
905 LPDWORD lpdwCapturePosition
,
906 LPDWORD lpdwReadPosition
)
908 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
909 HRESULT hres
= DS_OK
;
910 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
912 if (This
->device
== NULL
) {
913 WARN("invalid parameter: This->device == NULL\n");
914 return DSERR_INVALIDPARAM
;
917 if (This
->device
->driver
) {
918 hres
= IDsCaptureDriverBuffer_GetPosition(This
->device
->hwbuf
, lpdwCapturePosition
, lpdwReadPosition
);
920 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
921 } else if (This
->device
->hwi
) {
924 EnterCriticalSection(&This
->device
->lock
);
925 pos
= (DWORD_PTR
)This
->device
->pwave
[This
->device
->index
].lpData
- (DWORD_PTR
)This
->device
->buffer
;
926 if (lpdwCapturePosition
)
927 *lpdwCapturePosition
= (This
->device
->pwave
[This
->device
->index
].dwBufferLength
+ pos
) % This
->device
->buflen
;
928 if (lpdwReadPosition
)
929 *lpdwReadPosition
= pos
;
930 LeaveCriticalSection(&This
->device
->lock
);
934 hres
= DSERR_NODRIVER
;
937 TRACE("cappos=%d readpos=%d\n", (lpdwCapturePosition
?*lpdwCapturePosition
:-1), (lpdwReadPosition
?*lpdwReadPosition
:-1));
938 TRACE("returning %08x\n", hres
);
942 static HRESULT WINAPI
943 IDirectSoundCaptureBufferImpl_GetFormat(
944 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
945 LPWAVEFORMATEX lpwfxFormat
,
946 DWORD dwSizeAllocated
,
947 LPDWORD lpdwSizeWritten
)
949 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
950 HRESULT hres
= DS_OK
;
951 TRACE( "(%p,%p,0x%08x,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
954 if (This
->device
== NULL
) {
955 WARN("invalid parameter: This->device == NULL\n");
956 return DSERR_INVALIDPARAM
;
959 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
))
960 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
962 if (lpwfxFormat
) { /* NULL is valid (just want size) */
963 CopyMemory(lpwfxFormat
, This
->device
->pwfx
, dwSizeAllocated
);
965 *lpdwSizeWritten
= dwSizeAllocated
;
968 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
970 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
971 hres
= DSERR_INVALIDPARAM
;
975 TRACE("returning %08x\n", hres
);
979 static HRESULT WINAPI
980 IDirectSoundCaptureBufferImpl_GetStatus(
981 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
984 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
985 TRACE( "(%p, %p), thread is %04x\n", This
, lpdwStatus
, GetCurrentThreadId() );
987 if (This
->device
== NULL
) {
988 WARN("invalid parameter: This->device == NULL\n");
989 return DSERR_INVALIDPARAM
;
992 if (lpdwStatus
== NULL
) {
993 WARN("invalid parameter: lpdwStatus == NULL\n");
994 return DSERR_INVALIDPARAM
;
998 EnterCriticalSection(&(This
->device
->lock
));
1000 TRACE("old This->device->state=%s, old lpdwStatus=%08x\n",
1001 captureStateString
[This
->device
->state
],*lpdwStatus
);
1002 if ((This
->device
->state
== STATE_STARTING
) ||
1003 (This
->device
->state
== STATE_CAPTURING
)) {
1004 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
1005 if (This
->flags
& DSCBSTART_LOOPING
)
1006 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
1008 TRACE("new This->device->state=%s, new lpdwStatus=%08x\n",
1009 captureStateString
[This
->device
->state
],*lpdwStatus
);
1010 LeaveCriticalSection(&(This
->device
->lock
));
1012 TRACE("status=%x\n", *lpdwStatus
);
1013 TRACE("returning DS_OK\n");
1017 static HRESULT WINAPI
1018 IDirectSoundCaptureBufferImpl_Initialize(
1019 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1020 LPDIRECTSOUNDCAPTURE lpDSC
,
1021 LPCDSCBUFFERDESC lpcDSCBDesc
)
1023 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1025 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
1030 static HRESULT WINAPI
1031 IDirectSoundCaptureBufferImpl_Lock(
1032 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1035 LPVOID
* lplpvAudioPtr1
,
1036 LPDWORD lpdwAudioBytes1
,
1037 LPVOID
* lplpvAudioPtr2
,
1038 LPDWORD lpdwAudioBytes2
,
1041 HRESULT hres
= DS_OK
;
1042 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1043 TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This
, dwReadCusor
,
1044 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
1045 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
1047 if (This
->device
== NULL
) {
1048 WARN("invalid parameter: This->device == NULL\n");
1049 return DSERR_INVALIDPARAM
;
1052 if (lplpvAudioPtr1
== NULL
) {
1053 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1054 return DSERR_INVALIDPARAM
;
1057 if (lpdwAudioBytes1
== NULL
) {
1058 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1059 return DSERR_INVALIDPARAM
;
1062 EnterCriticalSection(&(This
->device
->lock
));
1064 if (This
->device
->driver
) {
1065 hres
= IDsCaptureDriverBuffer_Lock(This
->device
->hwbuf
, lplpvAudioPtr1
,
1066 lpdwAudioBytes1
, lplpvAudioPtr2
,
1067 lpdwAudioBytes2
, dwReadCusor
,
1068 dwReadBytes
, dwFlags
);
1070 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1071 } else if (This
->device
->hwi
) {
1072 *lplpvAudioPtr1
= This
->device
->buffer
+ dwReadCusor
;
1073 if ( (dwReadCusor
+ dwReadBytes
) > This
->device
->buflen
) {
1074 *lpdwAudioBytes1
= This
->device
->buflen
- dwReadCusor
;
1076 *lplpvAudioPtr2
= This
->device
->buffer
;
1077 if (lpdwAudioBytes2
)
1078 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
1080 *lpdwAudioBytes1
= dwReadBytes
;
1082 *lplpvAudioPtr2
= 0;
1083 if (lpdwAudioBytes2
)
1084 *lpdwAudioBytes2
= 0;
1087 TRACE("invalid call\n");
1088 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
1091 LeaveCriticalSection(&(This
->device
->lock
));
1093 TRACE("returning %08x\n", hres
);
1097 static HRESULT WINAPI
1098 IDirectSoundCaptureBufferImpl_Start(
1099 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1102 HRESULT hres
= DS_OK
;
1103 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1104 TRACE( "(%p,0x%08x)\n", This
, dwFlags
);
1106 if (This
->device
== NULL
) {
1107 WARN("invalid parameter: This->device == NULL\n");
1108 return DSERR_INVALIDPARAM
;
1111 if ( (This
->device
->driver
== 0) && (This
->device
->hwi
== 0) ) {
1112 WARN("no driver\n");
1113 return DSERR_NODRIVER
;
1116 EnterCriticalSection(&(This
->device
->lock
));
1118 This
->flags
= dwFlags
;
1119 TRACE("old This->state=%s\n",captureStateString
[This
->device
->state
]);
1120 if (This
->device
->state
== STATE_STOPPED
)
1121 This
->device
->state
= STATE_STARTING
;
1122 else if (This
->device
->state
== STATE_STOPPING
)
1123 This
->device
->state
= STATE_CAPTURING
;
1124 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1126 LeaveCriticalSection(&(This
->device
->lock
));
1128 if (This
->device
->driver
) {
1129 hres
= IDsCaptureDriverBuffer_Start(This
->device
->hwbuf
, dwFlags
);
1131 WARN("IDsCaptureDriverBuffer_Start failed\n");
1132 } else if (This
->device
->hwi
) {
1133 DirectSoundCaptureDevice
*device
= This
->device
;
1135 if (device
->buffer
) {
1137 DWORD blocksize
= DSOUND_fraglen(device
->pwfx
->nSamplesPerSec
, device
->pwfx
->nBlockAlign
);
1138 device
->nrofpwaves
= device
->buflen
/ blocksize
+ !!(device
->buflen
% blocksize
);
1139 TRACE("nrofpwaves=%d\n", device
->nrofpwaves
);
1141 /* prepare headers */
1143 device
->pwave
= HeapReAlloc(GetProcessHeap(), 0,device
->pwave
, device
->nrofpwaves
*sizeof(WAVEHDR
));
1145 device
->pwave
= HeapAlloc(GetProcessHeap(), 0, device
->nrofpwaves
*sizeof(WAVEHDR
));
1147 for (c
= 0; c
< device
->nrofpwaves
; ++c
) {
1148 device
->pwave
[c
].lpData
= (char *)device
->buffer
+ c
* blocksize
;
1149 device
->pwave
[c
].dwBufferLength
= blocksize
;
1150 device
->pwave
[c
].dwBytesRecorded
= 0;
1151 device
->pwave
[c
].dwUser
= (DWORD
)device
;
1152 device
->pwave
[c
].dwFlags
= 0;
1153 device
->pwave
[c
].dwLoops
= 0;
1154 hres
= mmErr(waveInPrepareHeader(device
->hwi
, &(device
->pwave
[c
]),sizeof(WAVEHDR
)));
1155 if (hres
!= DS_OK
) {
1156 WARN("waveInPrepareHeader failed\n");
1158 waveInUnprepareHeader(device
->hwi
, &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1162 hres
= mmErr(waveInAddBuffer(device
->hwi
, &(device
->pwave
[c
]), sizeof(WAVEHDR
)));
1163 if (hres
!= DS_OK
) {
1164 WARN("waveInAddBuffer failed\n");
1166 waveInUnprepareHeader(device
->hwi
, &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1170 if (device
->buflen
% blocksize
)
1171 device
->pwave
[device
->nrofpwaves
- 1].dwBufferLength
= device
->buflen
% blocksize
;
1173 FillMemory(device
->buffer
, device
->buflen
, (device
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
1178 if (hres
== DS_OK
) {
1179 /* start filling the first buffer */
1180 hres
= mmErr(waveInStart(device
->hwi
));
1182 WARN("waveInStart failed\n");
1185 if (hres
!= DS_OK
) {
1186 WARN("calling waveInClose because of error\n");
1187 waveInClose(device
->hwi
);
1191 WARN("no driver\n");
1192 hres
= DSERR_NODRIVER
;
1195 TRACE("returning %08x\n", hres
);
1199 static HRESULT WINAPI
1200 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1202 HRESULT hres
= DS_OK
;
1203 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1204 TRACE( "(%p)\n", This
);
1206 if (This
->device
== NULL
) {
1207 WARN("invalid parameter: This->device == NULL\n");
1208 return DSERR_INVALIDPARAM
;
1211 EnterCriticalSection(&(This
->device
->lock
));
1213 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1214 if (This
->device
->state
== STATE_CAPTURING
)
1215 This
->device
->state
= STATE_STOPPING
;
1216 else if (This
->device
->state
== STATE_STARTING
)
1217 This
->device
->state
= STATE_STOPPED
;
1218 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1220 LeaveCriticalSection(&(This
->device
->lock
));
1222 if (This
->device
->driver
) {
1223 hres
= IDsCaptureDriverBuffer_Stop(This
->device
->hwbuf
);
1225 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1226 } else if (This
->device
->hwi
) {
1227 hres
= mmErr(waveInReset(This
->device
->hwi
));
1229 WARN("waveInReset() failed\n");
1231 WARN("no driver\n");
1232 hres
= DSERR_NODRIVER
;
1235 TRACE("returning %08x\n", hres
);
1239 static HRESULT WINAPI
1240 IDirectSoundCaptureBufferImpl_Unlock(
1241 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1242 LPVOID lpvAudioPtr1
,
1243 DWORD dwAudioBytes1
,
1244 LPVOID lpvAudioPtr2
,
1245 DWORD dwAudioBytes2
)
1247 HRESULT hres
= DS_OK
;
1248 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1249 TRACE( "(%p,%p,%08u,%p,%08u)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
1250 lpvAudioPtr2
, dwAudioBytes2
);
1252 if (lpvAudioPtr1
== NULL
) {
1253 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1254 return DSERR_INVALIDPARAM
;
1257 if (This
->device
->driver
) {
1258 hres
= IDsCaptureDriverBuffer_Unlock(This
->device
->hwbuf
, lpvAudioPtr1
,
1259 dwAudioBytes1
, lpvAudioPtr2
, dwAudioBytes2
);
1261 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1262 } else if (!This
->device
->hwi
) {
1263 WARN("invalid call\n");
1264 hres
= DSERR_INVALIDCALL
;
1267 TRACE("returning %08x\n", hres
);
1271 static HRESULT WINAPI
1272 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1273 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1274 REFGUID rguidObject
,
1276 REFGUID rguidInterface
,
1279 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1281 FIXME( "(%p,%s,%u,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
1282 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
1287 static HRESULT WINAPI
1288 IDirectSoundCaptureBufferImpl_GetFXStatus(
1289 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1291 LPDWORD pdwFXStatus
)
1293 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1295 FIXME( "(%p,%u,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
1300 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
=
1302 /* IUnknown methods */
1303 IDirectSoundCaptureBufferImpl_QueryInterface
,
1304 IDirectSoundCaptureBufferImpl_AddRef
,
1305 IDirectSoundCaptureBufferImpl_Release
,
1307 /* IDirectSoundCaptureBuffer methods */
1308 IDirectSoundCaptureBufferImpl_GetCaps
,
1309 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
1310 IDirectSoundCaptureBufferImpl_GetFormat
,
1311 IDirectSoundCaptureBufferImpl_GetStatus
,
1312 IDirectSoundCaptureBufferImpl_Initialize
,
1313 IDirectSoundCaptureBufferImpl_Lock
,
1314 IDirectSoundCaptureBufferImpl_Start
,
1315 IDirectSoundCaptureBufferImpl_Stop
,
1316 IDirectSoundCaptureBufferImpl_Unlock
,
1318 /* IDirectSoundCaptureBuffer methods */
1319 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
1320 IDirectSoundCaptureBufferImpl_GetFXStatus
1323 HRESULT
IDirectSoundCaptureBufferImpl_Create(
1324 DirectSoundCaptureDevice
*device
,
1325 IDirectSoundCaptureBufferImpl
** ppobj
,
1326 LPCDSCBUFFERDESC lpcDSCBufferDesc
)
1328 LPWAVEFORMATEX wfex
;
1329 TRACE( "(%p,%p,%p)\n", device
, ppobj
, lpcDSCBufferDesc
);
1331 if (ppobj
== NULL
) {
1332 WARN("invalid parameter: ppobj == NULL\n");
1333 return DSERR_INVALIDPARAM
;
1337 WARN("not initialized\n");
1339 return DSERR_UNINITIALIZED
;
1342 if (lpcDSCBufferDesc
== NULL
) {
1343 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
1345 return DSERR_INVALIDPARAM
;
1348 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
1349 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
1350 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
1351 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) {
1352 WARN("invalid lpcDSCBufferDesc\n");
1354 return DSERR_INVALIDPARAM
;
1357 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
1360 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1361 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1362 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
1363 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
1364 wfex
->wBitsPerSample
, wfex
->cbSize
);
1366 if (wfex
->wFormatTag
== WAVE_FORMAT_PCM
) {
1367 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
));
1368 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
));
1369 device
->pwfx
->cbSize
= 0;
1371 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1372 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1375 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
1377 return DSERR_INVALIDPARAM
; /* FIXME: DSERR_BADFORMAT ? */
1380 *ppobj
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1381 sizeof(IDirectSoundCaptureBufferImpl
));
1383 if ( *ppobj
== NULL
) {
1384 WARN("out of memory\n");
1386 return DSERR_OUTOFMEMORY
;
1388 HRESULT err
= DS_OK
;
1391 IDirectSoundCaptureBufferImpl
*This
= *ppobj
;
1394 This
->device
= device
;
1395 This
->device
->capture_buffer
= This
;
1396 This
->notify
= NULL
;
1397 This
->nrofnotifies
= 0;
1398 This
->hwnotify
= NULL
;
1400 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1401 lpcDSCBufferDesc
->dwSize
);
1403 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
1405 WARN("no memory\n");
1406 This
->device
->capture_buffer
= 0;
1407 HeapFree( GetProcessHeap(), 0, This
);
1409 return DSERR_OUTOFMEMORY
;
1412 This
->lpVtbl
= &dscbvt
;
1414 if (device
->driver
) {
1415 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1416 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
1418 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
1419 /* allocate buffer from system memory */
1420 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1421 TRACE("desired buflen=%d, old buffer=%p\n", buflen
, device
->buffer
);
1423 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1425 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1427 if (newbuf
== NULL
) {
1428 WARN("failed to allocate capture buffer\n");
1429 err
= DSERR_OUTOFMEMORY
;
1430 /* but the old buffer might still exist and must be re-prepared */
1432 device
->buffer
= newbuf
;
1433 device
->buflen
= buflen
;
1436 /* let driver allocate memory */
1437 device
->buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1439 HeapFree( GetProcessHeap(), 0, device
->buffer
);
1440 device
->buffer
= NULL
;
1443 err
= IDsCaptureDriver_CreateCaptureBuffer(device
->driver
,
1444 device
->pwfx
,0,0,&(device
->buflen
),&(device
->buffer
),(LPVOID
*)&(device
->hwbuf
));
1446 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1447 This
->device
->capture_buffer
= 0;
1448 HeapFree( GetProcessHeap(), 0, This
);
1453 DWORD flags
= CALLBACK_FUNCTION
;
1454 err
= mmErr(waveInOpen(&(device
->hwi
),
1455 device
->drvdesc
.dnDevNode
, device
->pwfx
,
1456 (DWORD_PTR
)DSOUND_capture_callback
, (DWORD
)device
, flags
));
1458 WARN("waveInOpen failed\n");
1459 This
->device
->capture_buffer
= 0;
1460 HeapFree( GetProcessHeap(), 0, This
);
1465 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1466 TRACE("desired buflen=%d, old buffer=%p\n", buflen
, device
->buffer
);
1468 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1470 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1471 if (newbuf
== NULL
) {
1472 WARN("failed to allocate capture buffer\n");
1473 err
= DSERR_OUTOFMEMORY
;
1474 /* but the old buffer might still exist and must be re-prepared */
1476 device
->buffer
= newbuf
;
1477 device
->buflen
= buflen
;
1482 TRACE("returning DS_OK\n");
1486 /*******************************************************************************
1487 * DirectSoundCaptureDevice
1489 HRESULT
DirectSoundCaptureDevice_Initialize(
1490 DirectSoundCaptureDevice
** ppDevice
,
1493 HRESULT err
= DSERR_INVALIDPARAM
;
1495 BOOLEAN found
= FALSE
;
1497 DirectSoundCaptureDevice
*device
= *ppDevice
;
1498 TRACE("(%p, %s)\n", ppDevice
, debugstr_guid(lpcGUID
));
1500 /* Default device? */
1501 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
1502 lpcGUID
= &DSDEVID_DefaultCapture
;
1504 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1505 WARN("invalid parameter: lpcGUID\n");
1506 return DSERR_INVALIDPARAM
;
1509 widn
= waveInGetNumDevs();
1511 WARN("no audio devices found\n");
1512 return DSERR_NODRIVER
;
1515 /* enumerate WINMM audio devices and find the one we want */
1516 for (wid
=0; wid
<widn
; wid
++) {
1517 if (IsEqualGUID( &devGUID
, &DSOUND_capture_guids
[wid
]) ) {
1523 if (found
== FALSE
) {
1524 WARN("No device found matching given ID!\n");
1525 return DSERR_NODRIVER
;
1528 if (DSOUND_capture
[wid
]) {
1529 WARN("already in use\n");
1530 return DSERR_ALLOCATED
;
1533 err
= DirectSoundCaptureDevice_Create(&(device
));
1535 WARN("DirectSoundCaptureDevice_Create failed\n");
1540 device
->guid
= devGUID
;
1542 /* Disable the direct sound driver to force emulation if requested. */
1543 device
->driver
= NULL
;
1544 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
1546 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDIFACE
,(DWORD_PTR
)&(device
->driver
),0));
1547 if ( (err
!= DS_OK
) && (err
!= DSERR_UNSUPPORTED
) ) {
1548 WARN("waveInMessage failed; err=%x\n",err
);
1554 /* Get driver description */
1555 if (device
->driver
) {
1556 TRACE("using DirectSound driver\n");
1557 err
= IDsCaptureDriver_GetDriverDesc(device
->driver
, &(device
->drvdesc
));
1559 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
1563 TRACE("using WINMM\n");
1564 /* if no DirectSound interface available, use WINMM API instead */
1565 device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
|
1566 DSDDESC_DOMMSYSTEMSETFORMAT
;
1569 device
->drvdesc
.dnDevNode
= wid
;
1571 /* open the DirectSound driver if available */
1572 if (device
->driver
&& (err
== DS_OK
))
1573 err
= IDsCaptureDriver_Open(device
->driver
);
1578 /* the driver is now open, so it's now allowed to call GetCaps */
1579 if (device
->driver
) {
1580 device
->drvcaps
.dwSize
= sizeof(device
->drvcaps
);
1581 err
= IDsCaptureDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1583 WARN("IDsCaptureDriver_GetCaps failed\n");
1586 } else /*if (device->hwi)*/ {
1588 err
= mmErr(waveInGetDevCapsA((UINT
)device
->drvdesc
.dnDevNode
, &wic
, sizeof(wic
)));
1591 device
->drvcaps
.dwFlags
= 0;
1592 lstrcpynA(device
->drvdesc
.szDrvname
, wic
.szPname
,
1593 sizeof(device
->drvdesc
.szDrvname
));
1595 device
->drvcaps
.dwFlags
|= DSCCAPS_EMULDRIVER
;
1596 device
->drvcaps
.dwFormats
= wic
.dwFormats
;
1597 device
->drvcaps
.dwChannels
= wic
.wChannels
;
1605 static HRESULT
DirectSoundCaptureDevice_Create(
1606 DirectSoundCaptureDevice
** ppDevice
)
1608 DirectSoundCaptureDevice
* device
;
1609 TRACE("(%p)\n", ppDevice
);
1611 /* Allocate memory */
1612 device
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DirectSoundCaptureDevice
));
1614 if (device
== NULL
) {
1615 WARN("out of memory\n");
1616 return DSERR_OUTOFMEMORY
;
1620 device
->state
= STATE_STOPPED
;
1622 InitializeCriticalSection( &(device
->lock
) );
1623 device
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundCaptureDevice.lock");
1630 ULONG
DirectSoundCaptureDevice_AddRef(
1631 DirectSoundCaptureDevice
* device
)
1633 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1634 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1638 ULONG
DirectSoundCaptureDevice_Release(
1639 DirectSoundCaptureDevice
* device
)
1641 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1642 TRACE("(%p) ref was %d\n", device
, ref
+ 1);
1645 TRACE("deleting object\n");
1646 if (device
->capture_buffer
)
1647 IDirectSoundCaptureBufferImpl_Release(
1648 (LPDIRECTSOUNDCAPTUREBUFFER8
) device
->capture_buffer
);
1650 if (device
->driver
) {
1651 IDsCaptureDriver_Close(device
->driver
);
1652 IDsCaptureDriver_Release(device
->driver
);
1655 HeapFree(GetProcessHeap(), 0, device
->pwfx
);
1656 device
->lock
.DebugInfo
->Spare
[0] = 0;
1657 DeleteCriticalSection( &(device
->lock
) );
1658 DSOUND_capture
[device
->drvdesc
.dnDevNode
] = NULL
;
1659 HeapFree(GetProcessHeap(), 0, device
);
1660 TRACE("(%p) released\n", device
);