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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Implement FX support.
24 * Implement both IDirectSoundCaptureBuffer and IDirectSoundCaptureBuffer8
25 * Make DirectSoundCaptureCreate and DirectSoundCaptureCreate8 behave differently
30 #define NONAMELESSSTRUCT
31 #define NONAMELESSUNION
40 #include "wine/debug.h"
43 #include "dsound_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
47 static HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(
48 LPDIRECTSOUNDCAPTURE iface
,
50 static ULONG WINAPI
IDirectSoundCaptureImpl_Release(
51 LPDIRECTSOUNDCAPTURE iface
);
52 static ULONG WINAPI
IDirectSoundCaptureBufferImpl_Release(
53 LPDIRECTSOUNDCAPTUREBUFFER8 iface
);
54 static HRESULT
DSOUND_CreateDirectSoundCaptureBuffer(
55 IDirectSoundCaptureImpl
*ipDSC
,
56 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
59 static const IDirectSoundCaptureVtbl dscvt
;
60 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
;
62 DirectSoundCaptureDevice
* DSOUND_capture
[MAXWAVEDRIVERS
];
64 static const char * captureStateString
[] = {
71 HRESULT WINAPI
IDirectSoundCaptureImpl_Create(
72 LPDIRECTSOUNDCAPTURE8
* ppDSC
)
74 IDirectSoundCaptureImpl
*pDSC
;
75 TRACE("(%p)\n", ppDSC
);
78 pDSC
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundCaptureImpl
));
80 WARN("out of memory\n");
82 return DSERR_OUTOFMEMORY
;
85 pDSC
->lpVtbl
= &dscvt
;
89 *ppDSC
= (LPDIRECTSOUNDCAPTURE8
)pDSC
;
94 HRESULT WINAPI
DSOUND_CaptureCreate(
95 LPDIRECTSOUNDCAPTURE
*ppDSC
,
98 LPDIRECTSOUNDCAPTURE pDSC
;
100 TRACE("(%p,%p)\n",ppDSC
,pUnkOuter
);
102 /* Get dsound configuration */
103 setup_dsound_options();
105 hr
= IDirectSoundCaptureImpl_Create(&pDSC
);
107 IDirectSoundCapture_AddRef(pDSC
);
110 WARN("IDirectSoundCaptureImpl_Create failed\n");
117 HRESULT WINAPI
DSOUND_CaptureCreate8(
118 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
121 LPDIRECTSOUNDCAPTURE8 pDSC8
;
123 TRACE("(%p,%p)\n",ppDSC8
,pUnkOuter
);
125 /* Get dsound configuration */
126 setup_dsound_options();
128 hr
= IDirectSoundCaptureImpl_Create(&pDSC8
);
130 IDirectSoundCapture_AddRef(pDSC8
);
133 WARN("IDirectSoundCaptureImpl_Create failed\n");
140 /***************************************************************************
141 * DirectSoundCaptureCreate [DSOUND.6]
143 * Create and initialize a DirectSoundCapture interface.
146 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
147 * lplpDSC [O] Address of a variable to receive the interface pointer.
148 * pUnkOuter [I] Must be NULL.
152 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
156 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
157 * or NULL for the default device or DSDEVID_DefaultCapture or
158 * DSDEVID_DefaultVoiceCapture.
160 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
162 HRESULT WINAPI
DirectSoundCaptureCreate(
164 LPDIRECTSOUNDCAPTURE
*ppDSC
,
168 LPDIRECTSOUNDCAPTURE pDSC
;
169 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC
, pUnkOuter
);
172 WARN("invalid parameter: ppDSC == NULL\n");
173 return DSERR_INVALIDPARAM
;
177 WARN("invalid parameter: pUnkOuter != NULL\n");
179 return DSERR_NOAGGREGATION
;
182 hr
= DSOUND_CaptureCreate(&pDSC
, (IUnknown
*)pUnkOuter
);
184 hr
= IDirectSoundCapture_Initialize(pDSC
, lpcGUID
);
186 IDirectSoundCapture_Release(pDSC
);
196 /***************************************************************************
197 * DirectSoundCaptureCreate8 [DSOUND.12]
199 * Create and initialize a DirectSoundCapture interface.
202 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
203 * lplpDSC [O] Address of a variable to receive the interface pointer.
204 * pUnkOuter [I] Must be NULL.
208 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
212 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
213 * or NULL for the default device or DSDEVID_DefaultCapture or
214 * DSDEVID_DefaultVoiceCapture.
216 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
218 HRESULT WINAPI
DirectSoundCaptureCreate8(
220 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
224 LPDIRECTSOUNDCAPTURE8 pDSC8
;
225 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC8
, pUnkOuter
);
227 if (ppDSC8
== NULL
) {
228 WARN("invalid parameter: ppDSC8 == NULL\n");
229 return DSERR_INVALIDPARAM
;
233 WARN("invalid parameter: pUnkOuter != NULL\n");
235 return DSERR_NOAGGREGATION
;
238 hr
= DSOUND_CaptureCreate8(&pDSC8
, (IUnknown
*)pUnkOuter
);
240 hr
= IDirectSoundCapture_Initialize(pDSC8
, lpcGUID
);
242 IDirectSoundCapture_Release(pDSC8
);
252 static HRESULT
DirectSoundCaptureDevice_Create(
253 DirectSoundCaptureDevice
** ppDevice
)
255 DirectSoundCaptureDevice
* device
;
256 TRACE("(%p)\n", ppDevice
);
258 /* Allocate memory */
259 device
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DirectSoundCaptureDevice
));
261 if (device
== NULL
) {
262 WARN("out of memory\n");
263 return DSERR_OUTOFMEMORY
;
267 device
->state
= STATE_STOPPED
;
269 InitializeCriticalSection( &(device
->lock
) );
270 device
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)"DSCAPTURE_lock";
277 /***************************************************************************
278 * DirectSoundCaptureEnumerateA [DSOUND.7]
280 * Enumerate all DirectSound drivers installed in the system.
283 * lpDSEnumCallback [I] Address of callback function.
284 * lpContext [I] Address of user defined context passed to callback function.
288 * Failure: DSERR_INVALIDPARAM
291 DirectSoundCaptureEnumerateA(
292 LPDSENUMCALLBACKA lpDSEnumCallback
,
300 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
302 if (lpDSEnumCallback
== NULL
) {
303 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
304 return DSERR_INVALIDPARAM
;
307 devs
= waveInGetNumDevs();
309 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
310 for (wid
= 0; wid
< devs
; ++wid
) {
311 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
312 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
314 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
315 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
316 if (lpDSEnumCallback(NULL
, "Primary Sound Capture Driver", desc
.szDrvname
, lpContext
) == FALSE
)
324 for (wid
= 0; wid
< devs
; ++wid
) {
325 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
327 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
328 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
329 if (lpDSEnumCallback(&DSOUND_capture_guids
[wid
], desc
.szDesc
, desc
.szDrvname
, lpContext
) == FALSE
)
337 /***************************************************************************
338 * DirectSoundCaptureEnumerateW [DSOUND.8]
340 * Enumerate all DirectSound drivers installed in the system.
343 * lpDSEnumCallback [I] Address of callback function.
344 * lpContext [I] Address of user defined context passed to callback function.
348 * Failure: DSERR_INVALIDPARAM
351 DirectSoundCaptureEnumerateW(
352 LPDSENUMCALLBACKW lpDSEnumCallback
,
359 WCHAR wDesc
[MAXPNAMELEN
];
360 WCHAR wName
[MAXPNAMELEN
];
362 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
364 if (lpDSEnumCallback
== NULL
) {
365 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
366 return DSERR_INVALIDPARAM
;
369 devs
= waveInGetNumDevs();
371 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
372 for (wid
= 0; wid
< devs
; ++wid
) {
373 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
374 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
376 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
377 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
378 MultiByteToWideChar( CP_ACP
, 0, "Primary Sound Capture Driver", -1,
379 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
380 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
381 wName
, sizeof(wName
)/sizeof(WCHAR
) );
382 if (lpDSEnumCallback(NULL
, wDesc
, wName
, lpContext
) == FALSE
)
390 for (wid
= 0; wid
< devs
; ++wid
) {
391 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
393 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
394 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
395 MultiByteToWideChar( CP_ACP
, 0, desc
.szDesc
, -1,
396 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
397 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
398 wName
, sizeof(wName
)/sizeof(WCHAR
) );
399 if (lpDSEnumCallback((LPGUID
)&DSOUND_capture_guids
[wid
], wDesc
, wName
, lpContext
) == FALSE
)
408 DSOUND_capture_callback(
415 DirectSoundCaptureDevice
* This
= (DirectSoundCaptureDevice
*)dwUser
;
416 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi
,msg
,
417 msg
== MM_WIM_OPEN
? "MM_WIM_OPEN" : msg
== MM_WIM_CLOSE
? "MM_WIM_CLOSE" :
418 msg
== MM_WIM_DATA
? "MM_WIM_DATA" : "UNKNOWN",dwUser
,dw1
,dw2
,GetTickCount());
420 if (msg
== MM_WIM_DATA
) {
421 LPWAVEHDR pHdr
= (LPWAVEHDR
)dw1
;
422 EnterCriticalSection( &(This
->lock
) );
423 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
424 captureStateString
[This
->state
],This
->index
);
425 if (This
->state
!= STATE_STOPPED
) {
426 int index
= This
->index
;
427 if (This
->state
== STATE_STARTING
) {
428 This
->read_position
= pHdr
->dwBytesRecorded
;
429 This
->state
= STATE_CAPTURING
;
431 if (This
->capture_buffer
->nrofnotifies
)
432 SetEvent(This
->capture_buffer
->notifies
[This
->index
].hEventNotify
);
433 This
->index
= (This
->index
+ 1) % This
->nrofpwaves
;
434 if ( (This
->index
== 0) && !(This
->capture_buffer
->flags
& DSCBSTART_LOOPING
) ) {
435 TRACE("end of buffer\n");
436 This
->state
= STATE_STOPPED
;
438 if (This
->state
== STATE_CAPTURING
) {
439 waveInAddBuffer(hwi
, &(This
->pwave
[index
]), sizeof(WAVEHDR
));
440 } else if (This
->state
== STATE_STOPPING
) {
442 This
->state
= STATE_STOPPED
;
446 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
447 captureStateString
[This
->state
],This
->index
);
448 LeaveCriticalSection( &(This
->lock
) );
451 TRACE("completed\n");
454 static HRESULT WINAPI
455 IDirectSoundCaptureImpl_QueryInterface(
456 LPDIRECTSOUNDCAPTURE iface
,
460 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
461 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
464 WARN("invalid parameter\n");
470 if (IsEqualIID(riid
, &IID_IUnknown
)) {
471 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
474 } else if (IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
475 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
480 WARN("unsupported riid: %s\n", debugstr_guid(riid
));
481 return E_NOINTERFACE
;
485 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface
)
487 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
488 ULONG ref
= InterlockedIncrement(&(This
->ref
));
489 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
493 static ULONG
DirectSoundCaptureDevice_Release(
494 DirectSoundCaptureDevice
* device
)
497 TRACE("(%p) ref was %lu\n", device
, device
->ref
);
501 if (device
->ref
== 0) {
502 TRACE("deleting object\n");
503 if (device
->capture_buffer
)
504 IDirectSoundCaptureBufferImpl_Release(
505 (LPDIRECTSOUNDCAPTUREBUFFER8
) device
->capture_buffer
);
507 if (device
->driver
) {
508 IDsCaptureDriver_Close(device
->driver
);
509 IDsCaptureDriver_Release(device
->driver
);
512 HeapFree(GetProcessHeap(), 0, device
->pwfx
);
513 device
->lock
.DebugInfo
->Spare
[0] = 0;
514 DeleteCriticalSection( &(device
->lock
) );
515 DSOUND_capture
[device
->drvdesc
.dnDevNode
] = NULL
;
516 HeapFree(GetProcessHeap(), 0, device
);
517 TRACE("(%p) released\n", device
);
523 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface
)
525 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
526 ULONG ref
= InterlockedDecrement(&(This
->ref
));
527 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
531 DirectSoundCaptureDevice_Release(This
->device
);
533 HeapFree( GetProcessHeap(), 0, This
);
534 TRACE("(%p) released\n", This
);
539 static HRESULT WINAPI
540 IDirectSoundCaptureImpl_CreateCaptureBuffer(
541 LPDIRECTSOUNDCAPTURE iface
,
542 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
543 LPDIRECTSOUNDCAPTUREBUFFER
* lplpDSCaptureBuffer
,
547 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
549 TRACE( "(%p,%p,%p,%p)\n",iface
,lpcDSCBufferDesc
,lplpDSCaptureBuffer
,pUnk
);
552 WARN("invalid parameter: This == NULL\n");
553 return DSERR_INVALIDPARAM
;
556 if (lpcDSCBufferDesc
== NULL
) {
557 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
558 return DSERR_INVALIDPARAM
;
561 if (lplpDSCaptureBuffer
== NULL
) {
562 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
563 return DSERR_INVALIDPARAM
;
567 WARN("invalid parameter: pUnk != NULL\n");
568 return DSERR_INVALIDPARAM
;
571 /* FIXME: We can only have one buffer so what do we do here? */
572 if (This
->device
->capture_buffer
) {
573 WARN("lnvalid parameter: already has buffer\n");
574 return DSERR_INVALIDPARAM
; /* DSERR_GENERIC ? */
577 hr
= DSOUND_CreateDirectSoundCaptureBuffer(This
, lpcDSCBufferDesc
,
578 (LPVOID
*)lplpDSCaptureBuffer
);
581 WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n");
586 static HRESULT WINAPI
587 IDirectSoundCaptureImpl_GetCaps(
588 LPDIRECTSOUNDCAPTURE iface
,
589 LPDSCCAPS lpDSCCaps
)
591 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
592 TRACE("(%p,%p)\n",This
,lpDSCCaps
);
594 if (This
->device
== NULL
) {
595 WARN("not initialized\n");
596 return DSERR_UNINITIALIZED
;
599 if (lpDSCCaps
== NULL
) {
600 WARN("invalid parameter: lpDSCCaps== NULL\n");
601 return DSERR_INVALIDPARAM
;
604 if (lpDSCCaps
->dwSize
< sizeof(*lpDSCCaps
)) {
605 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
606 lpDSCCaps
->dwSize
, sizeof(*lpDSCCaps
));
607 return DSERR_INVALIDPARAM
;
610 lpDSCCaps
->dwFlags
= This
->device
->drvcaps
.dwFlags
;
611 lpDSCCaps
->dwFormats
= This
->device
->drvcaps
.dwFormats
;
612 lpDSCCaps
->dwChannels
= This
->device
->drvcaps
.dwChannels
;
614 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps
->dwFlags
,
615 lpDSCCaps
->dwFormats
, lpDSCCaps
->dwChannels
);
620 static HRESULT WINAPI
621 IDirectSoundCaptureImpl_Initialize(
622 LPDIRECTSOUNDCAPTURE iface
,
625 HRESULT err
= DSERR_INVALIDPARAM
;
627 BOOLEAN found
= FALSE
;
629 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
630 DirectSoundCaptureDevice
*device
= This
->device
;
631 TRACE("(%p)\n", This
);
634 WARN("invalid parameter: This == NULL\n");
635 return DSERR_INVALIDPARAM
;
638 if (device
!= NULL
) {
639 WARN("already initialized\n");
640 return DSERR_ALREADYINITIALIZED
;
643 /* Default device? */
644 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
645 lpcGUID
= &DSDEVID_DefaultCapture
;
647 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
648 WARN("invalid parameter: lpcGUID\n");
649 return DSERR_INVALIDPARAM
;
652 widn
= waveInGetNumDevs();
654 WARN("no audio devices found\n");
655 return DSERR_NODRIVER
;
658 /* enumerate WINMM audio devices and find the one we want */
659 for (wid
=0; wid
<widn
; wid
++) {
660 if (IsEqualGUID( &devGUID
, &DSOUND_capture_guids
[wid
]) ) {
666 if (found
== FALSE
) {
667 WARN("No device found matching given ID!\n");
668 return DSERR_NODRIVER
;
671 if (DSOUND_capture
[wid
]) {
672 WARN("already in use\n");
673 return DSERR_ALLOCATED
;
676 err
= DirectSoundCaptureDevice_Create(&(device
));
678 WARN("DirectSoundCaptureDevice_Create failed\n");
682 This
->device
= device
;
683 device
->guid
= devGUID
;
685 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDIFACE
,(DWORD_PTR
)&(This
->device
->driver
),0));
686 if ( (err
!= DS_OK
) && (err
!= DSERR_UNSUPPORTED
) ) {
687 WARN("waveInMessage failed; err=%lx\n",err
);
692 /* Disable the direct sound driver to force emulation if requested. */
693 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
694 This
->device
->driver
= NULL
;
696 /* Get driver description */
697 if (This
->device
->driver
) {
698 TRACE("using DirectSound driver\n");
699 err
= IDsCaptureDriver_GetDriverDesc(This
->device
->driver
, &(This
->device
->drvdesc
));
701 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
705 TRACE("using WINMM\n");
706 /* if no DirectSound interface available, use WINMM API instead */
707 This
->device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
|
708 DSDDESC_DOMMSYSTEMSETFORMAT
;
711 This
->device
->drvdesc
.dnDevNode
= wid
;
713 /* open the DirectSound driver if available */
714 if (This
->device
->driver
&& (err
== DS_OK
))
715 err
= IDsCaptureDriver_Open(This
->device
->driver
);
718 This
->device
= device
;
720 /* the driver is now open, so it's now allowed to call GetCaps */
721 if (This
->device
->driver
) {
722 This
->device
->drvcaps
.dwSize
= sizeof(This
->device
->drvcaps
);
723 err
= IDsCaptureDriver_GetCaps(This
->device
->driver
,&(This
->device
->drvcaps
));
725 WARN("IDsCaptureDriver_GetCaps failed\n");
728 } else /*if (This->hwi)*/ {
730 err
= mmErr(waveInGetDevCapsA((UINT
)This
->device
->drvdesc
.dnDevNode
, &wic
, sizeof(wic
)));
733 This
->device
->drvcaps
.dwFlags
= 0;
734 lstrcpynA(This
->device
->drvdesc
.szDrvname
, wic
.szPname
,
735 sizeof(This
->device
->drvdesc
.szDrvname
));
737 This
->device
->drvcaps
.dwFlags
|= DSCCAPS_EMULDRIVER
;
738 This
->device
->drvcaps
.dwFormats
= wic
.dwFormats
;
739 This
->device
->drvcaps
.dwChannels
= wic
.wChannels
;
747 static const IDirectSoundCaptureVtbl dscvt
=
749 /* IUnknown methods */
750 IDirectSoundCaptureImpl_QueryInterface
,
751 IDirectSoundCaptureImpl_AddRef
,
752 IDirectSoundCaptureImpl_Release
,
754 /* IDirectSoundCapture methods */
755 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
756 IDirectSoundCaptureImpl_GetCaps
,
757 IDirectSoundCaptureImpl_Initialize
761 DSOUND_CreateDirectSoundCaptureBuffer(
762 IDirectSoundCaptureImpl
*ipDSC
,
763 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
767 TRACE( "(%p,%p)\n", lpcDSCBufferDesc
, ppobj
);
770 WARN("invalid parameter: ipDSC == NULL\n");
771 return DSERR_INVALIDPARAM
;
774 if (lpcDSCBufferDesc
== NULL
) {
775 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
776 return DSERR_INVALIDPARAM
;
780 WARN("invalid parameter: ppobj == NULL\n");
781 return DSERR_INVALIDPARAM
;
784 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
785 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
786 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
787 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) {
788 WARN("invalid lpcDSCBufferDesc\n");
790 return DSERR_INVALIDPARAM
;
793 if ( !ipDSC
->device
) {
794 WARN("not initialized\n");
796 return DSERR_UNINITIALIZED
;
799 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
802 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
803 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
804 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
805 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
806 wfex
->wBitsPerSample
, wfex
->cbSize
);
808 if (wfex
->wFormatTag
== WAVE_FORMAT_PCM
) {
809 ipDSC
->device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
));
810 CopyMemory(ipDSC
->device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
));
811 ipDSC
->device
->pwfx
->cbSize
= 0;
813 ipDSC
->device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
814 CopyMemory(ipDSC
->device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
817 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
819 return DSERR_INVALIDPARAM
; /* FIXME: DSERR_BADFORMAT ? */
822 *ppobj
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
823 sizeof(IDirectSoundCaptureBufferImpl
));
825 if ( *ppobj
== NULL
) {
826 WARN("out of memory\n");
828 return DSERR_OUTOFMEMORY
;
833 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)*ppobj
;
836 This
->dsound
= ipDSC
;
837 This
->dsound
->device
->capture_buffer
= This
;
839 This
->nrofnotifies
= 0;
840 This
->hwnotify
= NULL
;
842 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
843 lpcDSCBufferDesc
->dwSize
);
845 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
848 This
->dsound
->device
->capture_buffer
= 0;
849 HeapFree( GetProcessHeap(), 0, This
);
851 return DSERR_OUTOFMEMORY
;
854 This
->lpVtbl
= &dscbvt
;
856 if (ipDSC
->device
->driver
) {
857 if (This
->dsound
->device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
858 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
860 if (This
->dsound
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
861 /* allocate buffer from system memory */
862 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
863 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, ipDSC
->device
->buffer
);
864 if (ipDSC
->device
->buffer
)
865 newbuf
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->device
->buffer
,buflen
);
867 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
869 if (newbuf
== NULL
) {
870 WARN("failed to allocate capture buffer\n");
871 err
= DSERR_OUTOFMEMORY
;
872 /* but the old buffer might still exist and must be re-prepared */
874 ipDSC
->device
->buffer
= newbuf
;
875 ipDSC
->device
->buflen
= buflen
;
878 /* let driver allocate memory */
879 ipDSC
->device
->buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
881 HeapFree( GetProcessHeap(), 0, ipDSC
->device
->buffer
);
882 ipDSC
->device
->buffer
= NULL
;
885 err
= IDsCaptureDriver_CreateCaptureBuffer(ipDSC
->device
->driver
,
886 ipDSC
->device
->pwfx
,0,0,&(ipDSC
->device
->buflen
),&(ipDSC
->device
->buffer
),(LPVOID
*)&(ipDSC
->device
->hwbuf
));
888 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
889 This
->dsound
->device
->capture_buffer
= 0;
890 HeapFree( GetProcessHeap(), 0, This
);
895 DWORD flags
= CALLBACK_FUNCTION
;
896 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
897 flags
|= WAVE_DIRECTSOUND
;
898 err
= mmErr(waveInOpen(&(ipDSC
->device
->hwi
),
899 ipDSC
->device
->drvdesc
.dnDevNode
, ipDSC
->device
->pwfx
,
900 (DWORD_PTR
)DSOUND_capture_callback
, (DWORD
)ipDSC
->device
, flags
));
902 WARN("waveInOpen failed\n");
903 This
->dsound
->device
->capture_buffer
= 0;
904 HeapFree( GetProcessHeap(), 0, This
);
909 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
910 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, ipDSC
->device
->buffer
);
911 if (ipDSC
->device
->buffer
)
912 newbuf
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->device
->buffer
,buflen
);
914 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
915 if (newbuf
== NULL
) {
916 WARN("failed to allocate capture buffer\n");
917 err
= DSERR_OUTOFMEMORY
;
918 /* but the old buffer might still exist and must be re-prepared */
920 ipDSC
->device
->buffer
= newbuf
;
921 ipDSC
->device
->buflen
= buflen
;
926 TRACE("returning DS_OK\n");
930 /*******************************************************************************
931 * IDirectSoundCaptureNotify
933 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_QueryInterface(
934 LPDIRECTSOUNDNOTIFY iface
,
938 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
939 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
941 if (This
->dscb
== NULL
) {
942 WARN("invalid parameter\n");
946 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
, riid
, ppobj
);
949 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface
)
951 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
952 ULONG ref
= InterlockedIncrement(&(This
->ref
));
953 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
957 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface
)
959 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
960 ULONG ref
= InterlockedDecrement(&(This
->ref
));
961 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
964 if (This
->dscb
->hwnotify
)
965 IDsDriverNotify_Release(This
->dscb
->hwnotify
);
966 This
->dscb
->notify
=NULL
;
967 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
);
968 HeapFree(GetProcessHeap(),0,This
);
969 TRACE("(%p) released\n", This
);
974 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
975 LPDIRECTSOUNDNOTIFY iface
,
977 LPCDSBPOSITIONNOTIFY notify
)
979 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
980 TRACE("(%p,0x%08lx,%p)\n",This
,howmuch
,notify
);
982 if (howmuch
> 0 && notify
== NULL
) {
983 WARN("invalid parameter: notify == NULL\n");
984 return DSERR_INVALIDPARAM
;
987 if (TRACE_ON(dsound
)) {
989 for (i
=0;i
<howmuch
;i
++)
990 TRACE("notify at %ld to %p\n",
991 notify
[i
].dwOffset
,notify
[i
].hEventNotify
);
994 if (This
->dscb
->hwnotify
) {
996 hres
= IDsDriverNotify_SetNotificationPositions(This
->dscb
->hwnotify
, howmuch
, notify
);
998 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
1000 } else if (howmuch
> 0) {
1001 /* Make an internal copy of the caller-supplied array.
1002 * Replace the existing copy if one is already present. */
1003 if (This
->dscb
->notifies
)
1004 This
->dscb
->notifies
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1005 This
->dscb
->notifies
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
1007 This
->dscb
->notifies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1008 howmuch
* sizeof(DSBPOSITIONNOTIFY
));
1010 if (This
->dscb
->notifies
== NULL
) {
1011 WARN("out of memory\n");
1012 return DSERR_OUTOFMEMORY
;
1014 CopyMemory(This
->dscb
->notifies
, notify
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
1015 This
->dscb
->nrofnotifies
= howmuch
;
1017 HeapFree(GetProcessHeap(), 0, This
->dscb
->notifies
);
1018 This
->dscb
->notifies
= NULL
;
1019 This
->dscb
->nrofnotifies
= 0;
1025 static const IDirectSoundNotifyVtbl dscnvt
=
1027 IDirectSoundCaptureNotifyImpl_QueryInterface
,
1028 IDirectSoundCaptureNotifyImpl_AddRef
,
1029 IDirectSoundCaptureNotifyImpl_Release
,
1030 IDirectSoundCaptureNotifyImpl_SetNotificationPositions
,
1033 HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_Create(
1034 IDirectSoundCaptureBufferImpl
*dscb
,
1035 IDirectSoundCaptureNotifyImpl
**pdscn
)
1037 IDirectSoundCaptureNotifyImpl
* dscn
;
1038 TRACE("(%p,%p)\n",dscb
,pdscn
);
1040 dscn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(dscn
));
1043 WARN("out of memory\n");
1044 return DSERR_OUTOFMEMORY
;
1048 dscn
->lpVtbl
= &dscnvt
;
1050 dscb
->notify
= dscn
;
1051 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER
)dscb
);
1057 /*******************************************************************************
1058 * IDirectSoundCaptureBuffer
1060 static HRESULT WINAPI
1061 IDirectSoundCaptureBufferImpl_QueryInterface(
1062 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1066 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1068 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
1070 if (ppobj
== NULL
) {
1071 WARN("invalid parameter\n");
1072 return E_INVALIDARG
;
1077 if ( IsEqualGUID( &IID_IDirectSoundNotify
, riid
) ) {
1079 hres
= IDirectSoundCaptureNotifyImpl_Create(This
, &This
->notify
);
1081 if (This
->dsound
->device
->hwbuf
) {
1082 hres
= IDsCaptureDriverBuffer_QueryInterface(This
->dsound
->device
->hwbuf
,
1083 &IID_IDsDriverNotify
, (LPVOID
*)&(This
->hwnotify
));
1084 if (hres
!= DS_OK
) {
1085 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
1091 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY
)This
->notify
);
1092 *ppobj
= (LPVOID
)This
->notify
;
1096 WARN("IID_IDirectSoundNotify\n");
1100 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer
, riid
) ||
1101 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8
, riid
) ) {
1102 IDirectSoundCaptureBuffer8_AddRef(iface
);
1107 FIXME("(%p,%s,%p) unsupported GUID\n", This
, debugstr_guid(riid
), ppobj
);
1108 return E_NOINTERFACE
;
1112 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1114 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1115 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1116 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1121 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1123 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1124 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1125 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1128 TRACE("deleting object\n");
1129 if (This
->dsound
->device
->state
== STATE_CAPTURING
)
1130 This
->dsound
->device
->state
= STATE_STOPPING
;
1132 HeapFree(GetProcessHeap(),0, This
->pdscbd
);
1134 if (This
->dsound
->device
->hwi
) {
1135 waveInReset(This
->dsound
->device
->hwi
);
1136 waveInClose(This
->dsound
->device
->hwi
);
1137 HeapFree(GetProcessHeap(),0, This
->dsound
->device
->pwave
);
1138 This
->dsound
->device
->pwave
= 0;
1139 This
->dsound
->device
->hwi
= 0;
1142 if (This
->dsound
->device
->hwbuf
)
1143 IDsCaptureDriverBuffer_Release(This
->dsound
->device
->hwbuf
);
1145 /* remove from IDirectSoundCaptureImpl */
1147 This
->dsound
->device
->capture_buffer
= NULL
;
1149 ERR("does not reference dsound\n");
1152 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
1154 HeapFree(GetProcessHeap(), 0, This
->notifies
);
1155 HeapFree( GetProcessHeap(), 0, This
);
1156 TRACE("(%p) released\n", This
);
1161 static HRESULT WINAPI
1162 IDirectSoundCaptureBufferImpl_GetCaps(
1163 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1164 LPDSCBCAPS lpDSCBCaps
)
1166 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1167 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
1170 WARN("invalid parameter: This == NULL\n");
1171 return DSERR_INVALIDPARAM
;
1174 if (lpDSCBCaps
== NULL
) {
1175 WARN("invalid parameter: lpDSCBCaps == NULL\n");
1176 return DSERR_INVALIDPARAM
;
1179 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
1180 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
1181 lpDSCBCaps
->dwSize
, sizeof(DSCBCAPS
));
1182 return DSERR_INVALIDPARAM
;
1185 if (This
->dsound
== NULL
) {
1186 WARN("invalid parameter: This->dsound == NULL\n");
1187 return DSERR_INVALIDPARAM
;
1190 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
1191 lpDSCBCaps
->dwFlags
= This
->flags
;
1192 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
1193 lpDSCBCaps
->dwReserved
= 0;
1195 TRACE("returning DS_OK\n");
1199 static HRESULT WINAPI
1200 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
1201 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1202 LPDWORD lpdwCapturePosition
,
1203 LPDWORD lpdwReadPosition
)
1205 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1206 HRESULT hres
= DS_OK
;
1207 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
1210 WARN("invalid parameter: This == NULL\n");
1211 return DSERR_INVALIDPARAM
;
1214 if (This
->dsound
== NULL
) {
1215 WARN("invalid parameter: This->dsound == NULL\n");
1216 return DSERR_INVALIDPARAM
;
1219 if (This
->dsound
->device
->driver
) {
1220 hres
= IDsCaptureDriverBuffer_GetPosition(This
->dsound
->device
->hwbuf
, lpdwCapturePosition
, lpdwReadPosition
);
1222 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
1223 } else if (This
->dsound
->device
->hwi
) {
1224 EnterCriticalSection(&(This
->dsound
->device
->lock
));
1225 TRACE("old This->dsound->device->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1226 if (lpdwCapturePosition
) {
1228 mtime
.wType
= TIME_BYTES
;
1229 waveInGetPosition(This
->dsound
->device
->hwi
, &mtime
, sizeof(mtime
));
1230 TRACE("mtime.u.cb=%ld,This->dsound->device->buflen=%ld\n", mtime
.u
.cb
,
1231 This
->dsound
->device
->buflen
);
1232 mtime
.u
.cb
= mtime
.u
.cb
% This
->dsound
->device
->buflen
;
1233 *lpdwCapturePosition
= mtime
.u
.cb
;
1236 if (lpdwReadPosition
) {
1237 if (This
->dsound
->device
->state
== STATE_STARTING
) {
1238 if (lpdwCapturePosition
)
1239 This
->dsound
->device
->read_position
= *lpdwCapturePosition
;
1240 This
->dsound
->device
->state
= STATE_CAPTURING
;
1242 *lpdwReadPosition
= This
->dsound
->device
->read_position
;
1244 TRACE("new This->dsound->device->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1245 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1246 if (lpdwCapturePosition
) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition
);
1247 if (lpdwReadPosition
) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition
);
1249 WARN("no driver\n");
1250 hres
= DSERR_NODRIVER
;
1253 TRACE("returning %08lx\n", hres
);
1257 static HRESULT WINAPI
1258 IDirectSoundCaptureBufferImpl_GetFormat(
1259 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1260 LPWAVEFORMATEX lpwfxFormat
,
1261 DWORD dwSizeAllocated
,
1262 LPDWORD lpdwSizeWritten
)
1264 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1265 HRESULT hres
= DS_OK
;
1266 TRACE( "(%p,%p,0x%08lx,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
1270 WARN("invalid parameter: This == NULL\n");
1271 return DSERR_INVALIDPARAM
;
1274 if (This
->dsound
== NULL
) {
1275 WARN("invalid parameter: This->dsound == NULL\n");
1276 return DSERR_INVALIDPARAM
;
1279 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->dsound
->device
->pwfx
->cbSize
))
1280 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->dsound
->device
->pwfx
->cbSize
;
1282 if (lpwfxFormat
) { /* NULL is valid (just want size) */
1283 CopyMemory(lpwfxFormat
, This
->dsound
->device
->pwfx
, dwSizeAllocated
);
1284 if (lpdwSizeWritten
)
1285 *lpdwSizeWritten
= dwSizeAllocated
;
1287 if (lpdwSizeWritten
)
1288 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->dsound
->device
->pwfx
->cbSize
;
1290 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
1291 hres
= DSERR_INVALIDPARAM
;
1295 TRACE("returning %08lx\n", hres
);
1299 static HRESULT WINAPI
1300 IDirectSoundCaptureBufferImpl_GetStatus(
1301 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1302 LPDWORD lpdwStatus
)
1304 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1305 TRACE( "(%p, %p), thread is %04lx\n", This
, lpdwStatus
, GetCurrentThreadId() );
1308 WARN("invalid parameter: This == NULL\n");
1309 return DSERR_INVALIDPARAM
;
1312 if (This
->dsound
== NULL
) {
1313 WARN("invalid parameter: This->dsound == NULL\n");
1314 return DSERR_INVALIDPARAM
;
1317 if (lpdwStatus
== NULL
) {
1318 WARN("invalid parameter: lpdwStatus == NULL\n");
1319 return DSERR_INVALIDPARAM
;
1323 EnterCriticalSection(&(This
->dsound
->device
->lock
));
1325 TRACE("old This->dsound->state=%s, old lpdwStatus=%08lx\n",
1326 captureStateString
[This
->dsound
->device
->state
],*lpdwStatus
);
1327 if ((This
->dsound
->device
->state
== STATE_STARTING
) ||
1328 (This
->dsound
->device
->state
== STATE_CAPTURING
)) {
1329 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
1330 if (This
->flags
& DSCBSTART_LOOPING
)
1331 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
1333 TRACE("new This->dsound->state=%s, new lpdwStatus=%08lx\n",
1334 captureStateString
[This
->dsound
->device
->state
],*lpdwStatus
);
1335 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1337 TRACE("status=%lx\n", *lpdwStatus
);
1338 TRACE("returning DS_OK\n");
1342 static HRESULT WINAPI
1343 IDirectSoundCaptureBufferImpl_Initialize(
1344 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1345 LPDIRECTSOUNDCAPTURE lpDSC
,
1346 LPCDSCBUFFERDESC lpcDSCBDesc
)
1348 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1350 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
1355 static HRESULT WINAPI
1356 IDirectSoundCaptureBufferImpl_Lock(
1357 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1360 LPVOID
* lplpvAudioPtr1
,
1361 LPDWORD lpdwAudioBytes1
,
1362 LPVOID
* lplpvAudioPtr2
,
1363 LPDWORD lpdwAudioBytes2
,
1366 HRESULT hres
= DS_OK
;
1367 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1368 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This
, dwReadCusor
,
1369 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
1370 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
1373 WARN("invalid parameter: This == NULL\n");
1374 return DSERR_INVALIDPARAM
;
1377 if (This
->dsound
== NULL
) {
1378 WARN("invalid parameter: This->dsound == NULL\n");
1379 return DSERR_INVALIDPARAM
;
1382 if (lplpvAudioPtr1
== NULL
) {
1383 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1384 return DSERR_INVALIDPARAM
;
1387 if (lpdwAudioBytes1
== NULL
) {
1388 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1389 return DSERR_INVALIDPARAM
;
1392 EnterCriticalSection(&(This
->dsound
->device
->lock
));
1394 if (This
->dsound
->device
->driver
) {
1395 hres
= IDsCaptureDriverBuffer_Lock(This
->dsound
->device
->hwbuf
, lplpvAudioPtr1
,
1396 lpdwAudioBytes1
, lplpvAudioPtr2
,
1397 lpdwAudioBytes2
, dwReadCusor
,
1398 dwReadBytes
, dwFlags
);
1400 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1401 } else if (This
->dsound
->device
->hwi
) {
1402 *lplpvAudioPtr1
= This
->dsound
->device
->buffer
+ dwReadCusor
;
1403 if ( (dwReadCusor
+ dwReadBytes
) > This
->dsound
->device
->buflen
) {
1404 *lpdwAudioBytes1
= This
->dsound
->device
->buflen
- dwReadCusor
;
1406 *lplpvAudioPtr2
= This
->dsound
->device
->buffer
;
1407 if (lpdwAudioBytes2
)
1408 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
1410 *lpdwAudioBytes1
= dwReadBytes
;
1412 *lplpvAudioPtr2
= 0;
1413 if (lpdwAudioBytes2
)
1414 *lpdwAudioBytes2
= 0;
1417 TRACE("invalid call\n");
1418 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
1421 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1423 TRACE("returning %08lx\n", hres
);
1427 static HRESULT WINAPI
1428 IDirectSoundCaptureBufferImpl_Start(
1429 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1432 HRESULT hres
= DS_OK
;
1433 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1434 TRACE( "(%p,0x%08lx)\n", This
, dwFlags
);
1437 WARN("invalid parameter: This == NULL\n");
1438 return DSERR_INVALIDPARAM
;
1441 if (This
->dsound
== NULL
) {
1442 WARN("invalid parameter: This->dsound == NULL\n");
1443 return DSERR_INVALIDPARAM
;
1446 if ( (This
->dsound
->device
->driver
== 0) && (This
->dsound
->device
->hwi
== 0) ) {
1447 WARN("no driver\n");
1448 return DSERR_NODRIVER
;
1451 EnterCriticalSection(&(This
->dsound
->device
->lock
));
1453 This
->flags
= dwFlags
;
1454 TRACE("old This->dsound->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1455 if (This
->dsound
->device
->state
== STATE_STOPPED
)
1456 This
->dsound
->device
->state
= STATE_STARTING
;
1457 else if (This
->dsound
->device
->state
== STATE_STOPPING
)
1458 This
->dsound
->device
->state
= STATE_CAPTURING
;
1459 TRACE("new This->dsound->device->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1461 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1463 if (This
->dsound
->device
->driver
) {
1464 hres
= IDsCaptureDriverBuffer_Start(This
->dsound
->device
->hwbuf
, dwFlags
);
1466 WARN("IDsCaptureDriverBuffer_Start failed\n");
1467 } else if (This
->dsound
->device
->hwi
) {
1468 IDirectSoundCaptureImpl
* ipDSC
= This
->dsound
;
1470 if (ipDSC
->device
->buffer
) {
1471 if (This
->nrofnotifies
) {
1474 ipDSC
->device
->nrofpwaves
= This
->nrofnotifies
;
1475 TRACE("nrofnotifies=%d\n", This
->nrofnotifies
);
1477 /* prepare headers */
1478 if (ipDSC
->device
->pwave
)
1479 ipDSC
->device
->pwave
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->device
->pwave
,
1480 ipDSC
->device
->nrofpwaves
*sizeof(WAVEHDR
));
1482 ipDSC
->device
->pwave
= HeapAlloc(GetProcessHeap(),0,
1483 ipDSC
->device
->nrofpwaves
*sizeof(WAVEHDR
));
1485 for (c
= 0; c
< ipDSC
->device
->nrofpwaves
; c
++) {
1486 if (This
->notifies
[c
].dwOffset
== DSBPN_OFFSETSTOP
) {
1487 TRACE("got DSBPN_OFFSETSTOP\n");
1488 ipDSC
->device
->nrofpwaves
= c
;
1492 ipDSC
->device
->pwave
[0].lpData
= (LPSTR
)ipDSC
->device
->buffer
;
1493 ipDSC
->device
->pwave
[0].dwBufferLength
=
1494 This
->notifies
[0].dwOffset
+ 1;
1496 ipDSC
->device
->pwave
[c
].lpData
= (LPSTR
)ipDSC
->device
->buffer
+
1497 This
->notifies
[c
-1].dwOffset
+ 1;
1498 ipDSC
->device
->pwave
[c
].dwBufferLength
=
1499 This
->notifies
[c
].dwOffset
-
1500 This
->notifies
[c
-1].dwOffset
;
1502 ipDSC
->device
->pwave
[c
].dwBytesRecorded
= 0;
1503 ipDSC
->device
->pwave
[c
].dwUser
= (DWORD
)ipDSC
;
1504 ipDSC
->device
->pwave
[c
].dwFlags
= 0;
1505 ipDSC
->device
->pwave
[c
].dwLoops
= 0;
1506 hres
= mmErr(waveInPrepareHeader(ipDSC
->device
->hwi
,
1507 &(ipDSC
->device
->pwave
[c
]),sizeof(WAVEHDR
)));
1508 if (hres
!= DS_OK
) {
1509 WARN("waveInPrepareHeader failed\n");
1511 waveInUnprepareHeader(ipDSC
->device
->hwi
,
1512 &(ipDSC
->device
->pwave
[c
]),sizeof(WAVEHDR
));
1516 hres
= mmErr(waveInAddBuffer(ipDSC
->device
->hwi
,
1517 &(ipDSC
->device
->pwave
[c
]), sizeof(WAVEHDR
)));
1518 if (hres
!= DS_OK
) {
1519 WARN("waveInAddBuffer failed\n");
1521 waveInUnprepareHeader(ipDSC
->device
->hwi
,
1522 &(ipDSC
->device
->pwave
[c
]),sizeof(WAVEHDR
));
1527 FillMemory(ipDSC
->device
->buffer
, ipDSC
->device
->buflen
,
1528 (ipDSC
->device
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
1530 TRACE("no notifiers specified\n");
1531 /* no notifiers specified so just create a single default header */
1532 ipDSC
->device
->nrofpwaves
= 1;
1533 if (ipDSC
->device
->pwave
)
1534 ipDSC
->device
->pwave
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->device
->pwave
,sizeof(WAVEHDR
));
1536 ipDSC
->device
->pwave
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR
));
1538 ipDSC
->device
->pwave
[0].lpData
= (LPSTR
)ipDSC
->device
->buffer
;
1539 ipDSC
->device
->pwave
[0].dwBufferLength
= ipDSC
->device
->buflen
;
1540 ipDSC
->device
->pwave
[0].dwBytesRecorded
= 0;
1541 ipDSC
->device
->pwave
[0].dwUser
= (DWORD
)ipDSC
;
1542 ipDSC
->device
->pwave
[0].dwFlags
= 0;
1543 ipDSC
->device
->pwave
[0].dwLoops
= 0;
1545 hres
= mmErr(waveInPrepareHeader(ipDSC
->device
->hwi
,
1546 &(ipDSC
->device
->pwave
[0]),sizeof(WAVEHDR
)));
1547 if (hres
!= DS_OK
) {
1548 WARN("waveInPrepareHeader failed\n");
1549 waveInUnprepareHeader(ipDSC
->device
->hwi
,
1550 &(ipDSC
->device
->pwave
[0]),sizeof(WAVEHDR
));
1552 hres
= mmErr(waveInAddBuffer(ipDSC
->device
->hwi
,
1553 &(ipDSC
->device
->pwave
[0]), sizeof(WAVEHDR
)));
1554 if (hres
!= DS_OK
) {
1555 WARN("waveInAddBuffer failed\n");
1556 waveInUnprepareHeader(ipDSC
->device
->hwi
,
1557 &(ipDSC
->device
->pwave
[0]),sizeof(WAVEHDR
));
1562 ipDSC
->device
->index
= 0;
1563 ipDSC
->device
->read_position
= 0;
1565 if (hres
== DS_OK
) {
1566 /* start filling the first buffer */
1567 hres
= mmErr(waveInStart(ipDSC
->device
->hwi
));
1569 WARN("waveInStart failed\n");
1572 if (hres
!= DS_OK
) {
1573 WARN("calling waveInClose because of error\n");
1574 waveInClose(This
->dsound
->device
->hwi
);
1575 This
->dsound
->device
->hwi
= 0;
1578 WARN("no driver\n");
1579 hres
= DSERR_NODRIVER
;
1582 TRACE("returning %08lx\n", hres
);
1586 static HRESULT WINAPI
1587 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1589 HRESULT hres
= DS_OK
;
1590 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1591 TRACE( "(%p)\n", This
);
1594 WARN("invalid parameter: This == NULL\n");
1595 return DSERR_INVALIDPARAM
;
1598 if (This
->dsound
== NULL
) {
1599 WARN("invalid parameter: This->dsound == NULL\n");
1600 return DSERR_INVALIDPARAM
;
1603 EnterCriticalSection(&(This
->dsound
->device
->lock
));
1605 TRACE("old This->dsound->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1606 if (This
->dsound
->device
->state
== STATE_CAPTURING
)
1607 This
->dsound
->device
->state
= STATE_STOPPING
;
1608 else if (This
->dsound
->device
->state
== STATE_STARTING
)
1609 This
->dsound
->device
->state
= STATE_STOPPED
;
1610 TRACE("new This->dsound->device->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1612 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1614 if (This
->dsound
->device
->driver
) {
1615 hres
= IDsCaptureDriverBuffer_Stop(This
->dsound
->device
->hwbuf
);
1617 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1618 } else if (This
->dsound
->device
->hwi
) {
1619 hres
= mmErr(waveInReset(This
->dsound
->device
->hwi
));
1621 WARN("waveInReset() failed\n");
1623 WARN("no driver\n");
1624 hres
= DSERR_NODRIVER
;
1627 TRACE("returning %08lx\n", hres
);
1631 static HRESULT WINAPI
1632 IDirectSoundCaptureBufferImpl_Unlock(
1633 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1634 LPVOID lpvAudioPtr1
,
1635 DWORD dwAudioBytes1
,
1636 LPVOID lpvAudioPtr2
,
1637 DWORD dwAudioBytes2
)
1639 HRESULT hres
= DS_OK
;
1640 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1641 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
1642 lpvAudioPtr2
, dwAudioBytes2
);
1645 WARN("invalid parameter: This == NULL\n");
1646 return DSERR_INVALIDPARAM
;
1649 if (lpvAudioPtr1
== NULL
) {
1650 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1651 return DSERR_INVALIDPARAM
;
1654 if (This
->dsound
->device
->driver
) {
1655 hres
= IDsCaptureDriverBuffer_Unlock(This
->dsound
->device
->hwbuf
, lpvAudioPtr1
,
1656 dwAudioBytes1
, lpvAudioPtr2
, dwAudioBytes2
);
1658 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1659 } else if (This
->dsound
->device
->hwi
) {
1660 This
->dsound
->device
->read_position
= (This
->dsound
->device
->read_position
+
1661 (dwAudioBytes1
+ dwAudioBytes2
)) % This
->dsound
->device
->buflen
;
1663 WARN("invalid call\n");
1664 hres
= DSERR_INVALIDCALL
;
1667 TRACE("returning %08lx\n", hres
);
1671 static HRESULT WINAPI
1672 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1673 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1674 REFGUID rguidObject
,
1676 REFGUID rguidInterface
,
1679 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1681 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
1682 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
1687 static HRESULT WINAPI
1688 IDirectSoundCaptureBufferImpl_GetFXStatus(
1689 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1691 LPDWORD pdwFXStatus
)
1693 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1695 FIXME( "(%p,%lu,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
1700 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
=
1702 /* IUnknown methods */
1703 IDirectSoundCaptureBufferImpl_QueryInterface
,
1704 IDirectSoundCaptureBufferImpl_AddRef
,
1705 IDirectSoundCaptureBufferImpl_Release
,
1707 /* IDirectSoundCaptureBuffer methods */
1708 IDirectSoundCaptureBufferImpl_GetCaps
,
1709 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
1710 IDirectSoundCaptureBufferImpl_GetFormat
,
1711 IDirectSoundCaptureBufferImpl_GetStatus
,
1712 IDirectSoundCaptureBufferImpl_Initialize
,
1713 IDirectSoundCaptureBufferImpl_Lock
,
1714 IDirectSoundCaptureBufferImpl_Start
,
1715 IDirectSoundCaptureBufferImpl_Stop
,
1716 IDirectSoundCaptureBufferImpl_Unlock
,
1718 /* IDirectSoundCaptureBuffer methods */
1719 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
1720 IDirectSoundCaptureBufferImpl_GetFXStatus
1723 /*******************************************************************************
1724 * DirectSoundCapture ClassFactory
1727 static HRESULT WINAPI
1728 DSCCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
)
1730 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1732 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
1733 return E_NOINTERFACE
;
1737 DSCCF_AddRef(LPCLASSFACTORY iface
)
1739 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1740 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1741 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1746 DSCCF_Release(LPCLASSFACTORY iface
)
1748 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1749 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1750 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1751 /* static class, won't be freed */
1755 static HRESULT WINAPI
1756 DSCCF_CreateInstance(
1757 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
)
1759 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1760 TRACE("(%p)->(%p,%s,%p)\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1763 WARN("aggregation not supported\n");
1764 return CLASS_E_NOAGGREGATION
;
1767 if (ppobj
== NULL
) {
1768 WARN("invalid parameter\n");
1769 return E_INVALIDARG
;
1774 if ( IsEqualGUID( &IID_IDirectSoundCapture
, riid
) )
1775 return DSOUND_CaptureCreate8((LPDIRECTSOUNDCAPTURE
*)ppobj
,pOuter
);
1777 WARN("(%p,%p,%s,%p) Interface not found!\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1778 return E_NOINTERFACE
;
1781 static HRESULT WINAPI
1782 DSCCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
)
1784 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1785 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
1789 static const IClassFactoryVtbl DSCCF_Vtbl
=
1791 DSCCF_QueryInterface
,
1794 DSCCF_CreateInstance
,
1798 IClassFactoryImpl DSOUND_CAPTURE_CF
= { &DSCCF_Vtbl
, 1 };