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 const IDirectSoundCaptureVtbl dscvt
;
48 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
;
50 DirectSoundCaptureDevice
* DSOUND_capture
[MAXWAVEDRIVERS
];
52 static const char * captureStateString
[] = {
59 static HRESULT
DSOUND_CaptureCreate(
60 LPDIRECTSOUNDCAPTURE
*ppDSC
,
63 LPDIRECTSOUNDCAPTURE pDSC
;
65 TRACE("(%p,%p)\n",ppDSC
,pUnkOuter
);
67 /* Get dsound configuration */
68 setup_dsound_options();
70 hr
= IDirectSoundCaptureImpl_Create(&pDSC
);
72 IDirectSoundCapture_AddRef(pDSC
);
75 WARN("IDirectSoundCaptureImpl_Create failed\n");
82 static HRESULT
DSOUND_CaptureCreate8(
83 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
86 LPDIRECTSOUNDCAPTURE8 pDSC8
;
88 TRACE("(%p,%p)\n",ppDSC8
,pUnkOuter
);
90 /* Get dsound configuration */
91 setup_dsound_options();
93 hr
= IDirectSoundCaptureImpl_Create(&pDSC8
);
95 IDirectSoundCapture_AddRef(pDSC8
);
98 WARN("IDirectSoundCaptureImpl_Create failed\n");
105 /***************************************************************************
106 * DirectSoundCaptureCreate [DSOUND.6]
108 * Create and initialize a DirectSoundCapture interface.
111 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
112 * lplpDSC [O] Address of a variable to receive the interface pointer.
113 * pUnkOuter [I] Must be NULL.
117 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
121 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
122 * or NULL for the default device or DSDEVID_DefaultCapture or
123 * DSDEVID_DefaultVoiceCapture.
125 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
127 HRESULT WINAPI
DirectSoundCaptureCreate(
129 LPDIRECTSOUNDCAPTURE
*ppDSC
,
133 LPDIRECTSOUNDCAPTURE pDSC
;
134 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC
, pUnkOuter
);
137 WARN("invalid parameter: ppDSC == NULL\n");
138 return DSERR_INVALIDPARAM
;
142 WARN("invalid parameter: pUnkOuter != NULL\n");
144 return DSERR_NOAGGREGATION
;
147 hr
= DSOUND_CaptureCreate(&pDSC
, (IUnknown
*)pUnkOuter
);
149 hr
= IDirectSoundCapture_Initialize(pDSC
, lpcGUID
);
151 IDirectSoundCapture_Release(pDSC
);
161 /***************************************************************************
162 * DirectSoundCaptureCreate8 [DSOUND.12]
164 * Create and initialize a DirectSoundCapture interface.
167 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
168 * lplpDSC [O] Address of a variable to receive the interface pointer.
169 * pUnkOuter [I] Must be NULL.
173 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
177 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
178 * or NULL for the default device or DSDEVID_DefaultCapture or
179 * DSDEVID_DefaultVoiceCapture.
181 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
183 HRESULT WINAPI
DirectSoundCaptureCreate8(
185 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
189 LPDIRECTSOUNDCAPTURE8 pDSC8
;
190 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC8
, pUnkOuter
);
192 if (ppDSC8
== NULL
) {
193 WARN("invalid parameter: ppDSC8 == NULL\n");
194 return DSERR_INVALIDPARAM
;
198 WARN("invalid parameter: pUnkOuter != NULL\n");
200 return DSERR_NOAGGREGATION
;
203 hr
= DSOUND_CaptureCreate8(&pDSC8
, (IUnknown
*)pUnkOuter
);
205 hr
= IDirectSoundCapture_Initialize(pDSC8
, lpcGUID
);
207 IDirectSoundCapture_Release(pDSC8
);
217 /***************************************************************************
218 * DirectSoundCaptureEnumerateA [DSOUND.7]
220 * Enumerate all DirectSound drivers installed in the system.
223 * lpDSEnumCallback [I] Address of callback function.
224 * lpContext [I] Address of user defined context passed to callback function.
228 * Failure: DSERR_INVALIDPARAM
231 DirectSoundCaptureEnumerateA(
232 LPDSENUMCALLBACKA lpDSEnumCallback
,
240 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
242 if (lpDSEnumCallback
== NULL
) {
243 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
244 return DSERR_INVALIDPARAM
;
247 devs
= waveInGetNumDevs();
249 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
250 for (wid
= 0; wid
< devs
; ++wid
) {
251 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
252 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
254 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
255 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
256 if (lpDSEnumCallback(NULL
, "Primary Sound Capture Driver", desc
.szDrvname
, lpContext
) == FALSE
)
264 for (wid
= 0; wid
< devs
; ++wid
) {
265 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
267 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
268 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
269 if (lpDSEnumCallback(&DSOUND_capture_guids
[wid
], desc
.szDesc
, desc
.szDrvname
, lpContext
) == FALSE
)
277 /***************************************************************************
278 * DirectSoundCaptureEnumerateW [DSOUND.8]
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 DirectSoundCaptureEnumerateW(
292 LPDSENUMCALLBACKW lpDSEnumCallback
,
299 WCHAR wDesc
[MAXPNAMELEN
];
300 WCHAR wName
[MAXPNAMELEN
];
302 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
304 if (lpDSEnumCallback
== NULL
) {
305 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
306 return DSERR_INVALIDPARAM
;
309 devs
= waveInGetNumDevs();
311 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
312 for (wid
= 0; wid
< devs
; ++wid
) {
313 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
314 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
316 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
317 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
318 MultiByteToWideChar( CP_ACP
, 0, "Primary Sound Capture Driver", -1,
319 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
320 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
321 wName
, sizeof(wName
)/sizeof(WCHAR
) );
322 if (lpDSEnumCallback(NULL
, wDesc
, wName
, lpContext
) == FALSE
)
330 for (wid
= 0; wid
< devs
; ++wid
) {
331 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
333 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
334 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
335 MultiByteToWideChar( CP_ACP
, 0, desc
.szDesc
, -1,
336 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
337 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
338 wName
, sizeof(wName
)/sizeof(WCHAR
) );
339 if (lpDSEnumCallback((LPGUID
)&DSOUND_capture_guids
[wid
], wDesc
, wName
, lpContext
) == FALSE
)
348 DSOUND_capture_callback(
355 DirectSoundCaptureDevice
* This
= (DirectSoundCaptureDevice
*)dwUser
;
356 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi
,msg
,
357 msg
== MM_WIM_OPEN
? "MM_WIM_OPEN" : msg
== MM_WIM_CLOSE
? "MM_WIM_CLOSE" :
358 msg
== MM_WIM_DATA
? "MM_WIM_DATA" : "UNKNOWN",dwUser
,dw1
,dw2
,GetTickCount());
360 if (msg
== MM_WIM_DATA
) {
361 LPWAVEHDR pHdr
= (LPWAVEHDR
)dw1
;
362 EnterCriticalSection( &(This
->lock
) );
363 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
364 captureStateString
[This
->state
],This
->index
);
365 if (This
->state
!= STATE_STOPPED
) {
366 int index
= This
->index
;
367 if (This
->state
== STATE_STARTING
) {
368 This
->read_position
= pHdr
->dwBytesRecorded
;
369 This
->state
= STATE_CAPTURING
;
371 if (This
->capture_buffer
->nrofnotifies
)
372 SetEvent(This
->capture_buffer
->notifies
[This
->index
].hEventNotify
);
373 This
->index
= (This
->index
+ 1) % This
->nrofpwaves
;
374 if ( (This
->index
== 0) && !(This
->capture_buffer
->flags
& DSCBSTART_LOOPING
) ) {
375 TRACE("end of buffer\n");
376 This
->state
= STATE_STOPPED
;
378 if (This
->state
== STATE_CAPTURING
) {
379 waveInAddBuffer(hwi
, &(This
->pwave
[index
]), sizeof(WAVEHDR
));
380 } else if (This
->state
== STATE_STOPPING
) {
382 This
->state
= STATE_STOPPED
;
386 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
387 captureStateString
[This
->state
],This
->index
);
388 LeaveCriticalSection( &(This
->lock
) );
391 TRACE("completed\n");
394 /***************************************************************************
395 * IDirectSoundCaptureImpl
397 static HRESULT WINAPI
398 IDirectSoundCaptureImpl_QueryInterface(
399 LPDIRECTSOUNDCAPTURE iface
,
403 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
404 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
407 WARN("invalid parameter\n");
413 if (IsEqualIID(riid
, &IID_IUnknown
)) {
414 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
417 } else if (IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
418 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
423 WARN("unsupported riid: %s\n", debugstr_guid(riid
));
424 return E_NOINTERFACE
;
428 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface
)
430 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
431 ULONG ref
= InterlockedIncrement(&(This
->ref
));
432 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
437 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface
)
439 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
440 ULONG ref
= InterlockedDecrement(&(This
->ref
));
441 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
445 DirectSoundCaptureDevice_Release(This
->device
);
447 HeapFree( GetProcessHeap(), 0, This
);
448 TRACE("(%p) released\n", This
);
453 static HRESULT WINAPI
454 IDirectSoundCaptureImpl_CreateCaptureBuffer(
455 LPDIRECTSOUNDCAPTURE iface
,
456 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
457 LPDIRECTSOUNDCAPTUREBUFFER
* lplpDSCaptureBuffer
,
461 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
463 TRACE( "(%p,%p,%p,%p)\n",iface
,lpcDSCBufferDesc
,lplpDSCaptureBuffer
,pUnk
);
466 WARN("invalid parameter: This == NULL\n");
467 return DSERR_INVALIDPARAM
;
470 if (lpcDSCBufferDesc
== NULL
) {
471 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
472 return DSERR_INVALIDPARAM
;
475 if (lplpDSCaptureBuffer
== NULL
) {
476 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
477 return DSERR_INVALIDPARAM
;
481 WARN("invalid parameter: pUnk != NULL\n");
482 return DSERR_INVALIDPARAM
;
485 /* FIXME: We can only have one buffer so what do we do here? */
486 if (This
->device
->capture_buffer
) {
487 WARN("lnvalid parameter: already has buffer\n");
488 return DSERR_INVALIDPARAM
; /* DSERR_GENERIC ? */
491 hr
= DSOUND_CreateDirectSoundCaptureBuffer(This
, lpcDSCBufferDesc
,
492 (LPVOID
*)lplpDSCaptureBuffer
);
495 WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n");
500 static HRESULT WINAPI
501 IDirectSoundCaptureImpl_GetCaps(
502 LPDIRECTSOUNDCAPTURE iface
,
503 LPDSCCAPS lpDSCCaps
)
505 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
506 TRACE("(%p,%p)\n",This
,lpDSCCaps
);
508 if (This
->device
== NULL
) {
509 WARN("not initialized\n");
510 return DSERR_UNINITIALIZED
;
513 if (lpDSCCaps
== NULL
) {
514 WARN("invalid parameter: lpDSCCaps== NULL\n");
515 return DSERR_INVALIDPARAM
;
518 if (lpDSCCaps
->dwSize
< sizeof(*lpDSCCaps
)) {
519 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
520 lpDSCCaps
->dwSize
, sizeof(*lpDSCCaps
));
521 return DSERR_INVALIDPARAM
;
524 lpDSCCaps
->dwFlags
= This
->device
->drvcaps
.dwFlags
;
525 lpDSCCaps
->dwFormats
= This
->device
->drvcaps
.dwFormats
;
526 lpDSCCaps
->dwChannels
= This
->device
->drvcaps
.dwChannels
;
528 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps
->dwFlags
,
529 lpDSCCaps
->dwFormats
, lpDSCCaps
->dwChannels
);
534 static HRESULT WINAPI
535 IDirectSoundCaptureImpl_Initialize(
536 LPDIRECTSOUNDCAPTURE iface
,
539 HRESULT err
= DSERR_INVALIDPARAM
;
541 BOOLEAN found
= FALSE
;
543 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
544 DirectSoundCaptureDevice
*device
= This
->device
;
545 TRACE("(%p)\n", This
);
548 WARN("invalid parameter: This == NULL\n");
549 return DSERR_INVALIDPARAM
;
552 if (device
!= NULL
) {
553 WARN("already initialized\n");
554 return DSERR_ALREADYINITIALIZED
;
557 /* Default device? */
558 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
559 lpcGUID
= &DSDEVID_DefaultCapture
;
561 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
562 WARN("invalid parameter: lpcGUID\n");
563 return DSERR_INVALIDPARAM
;
566 widn
= waveInGetNumDevs();
568 WARN("no audio devices found\n");
569 return DSERR_NODRIVER
;
572 /* enumerate WINMM audio devices and find the one we want */
573 for (wid
=0; wid
<widn
; wid
++) {
574 if (IsEqualGUID( &devGUID
, &DSOUND_capture_guids
[wid
]) ) {
580 if (found
== FALSE
) {
581 WARN("No device found matching given ID!\n");
582 return DSERR_NODRIVER
;
585 if (DSOUND_capture
[wid
]) {
586 WARN("already in use\n");
587 return DSERR_ALLOCATED
;
590 err
= DirectSoundCaptureDevice_Create(&(device
));
592 WARN("DirectSoundCaptureDevice_Create failed\n");
596 This
->device
= device
;
597 device
->guid
= devGUID
;
599 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDIFACE
,(DWORD_PTR
)&(This
->device
->driver
),0));
600 if ( (err
!= DS_OK
) && (err
!= DSERR_UNSUPPORTED
) ) {
601 WARN("waveInMessage failed; err=%lx\n",err
);
606 /* Disable the direct sound driver to force emulation if requested. */
607 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
608 This
->device
->driver
= NULL
;
610 /* Get driver description */
611 if (This
->device
->driver
) {
612 TRACE("using DirectSound driver\n");
613 err
= IDsCaptureDriver_GetDriverDesc(This
->device
->driver
, &(This
->device
->drvdesc
));
615 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
619 TRACE("using WINMM\n");
620 /* if no DirectSound interface available, use WINMM API instead */
621 This
->device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
|
622 DSDDESC_DOMMSYSTEMSETFORMAT
;
625 This
->device
->drvdesc
.dnDevNode
= wid
;
627 /* open the DirectSound driver if available */
628 if (This
->device
->driver
&& (err
== DS_OK
))
629 err
= IDsCaptureDriver_Open(This
->device
->driver
);
632 This
->device
= device
;
634 /* the driver is now open, so it's now allowed to call GetCaps */
635 if (This
->device
->driver
) {
636 This
->device
->drvcaps
.dwSize
= sizeof(This
->device
->drvcaps
);
637 err
= IDsCaptureDriver_GetCaps(This
->device
->driver
,&(This
->device
->drvcaps
));
639 WARN("IDsCaptureDriver_GetCaps failed\n");
642 } else /*if (This->hwi)*/ {
644 err
= mmErr(waveInGetDevCapsA((UINT
)This
->device
->drvdesc
.dnDevNode
, &wic
, sizeof(wic
)));
647 This
->device
->drvcaps
.dwFlags
= 0;
648 lstrcpynA(This
->device
->drvdesc
.szDrvname
, wic
.szPname
,
649 sizeof(This
->device
->drvdesc
.szDrvname
));
651 This
->device
->drvcaps
.dwFlags
|= DSCCAPS_EMULDRIVER
;
652 This
->device
->drvcaps
.dwFormats
= wic
.dwFormats
;
653 This
->device
->drvcaps
.dwChannels
= wic
.wChannels
;
661 static const IDirectSoundCaptureVtbl dscvt
=
663 /* IUnknown methods */
664 IDirectSoundCaptureImpl_QueryInterface
,
665 IDirectSoundCaptureImpl_AddRef
,
666 IDirectSoundCaptureImpl_Release
,
668 /* IDirectSoundCapture methods */
669 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
670 IDirectSoundCaptureImpl_GetCaps
,
671 IDirectSoundCaptureImpl_Initialize
674 HRESULT
IDirectSoundCaptureImpl_Create(
675 LPDIRECTSOUNDCAPTURE8
* ppDSC
)
677 IDirectSoundCaptureImpl
*pDSC
;
678 TRACE("(%p)\n", ppDSC
);
680 /* Allocate memory */
681 pDSC
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundCaptureImpl
));
683 WARN("out of memory\n");
685 return DSERR_OUTOFMEMORY
;
688 pDSC
->lpVtbl
= &dscvt
;
692 *ppDSC
= (LPDIRECTSOUNDCAPTURE8
)pDSC
;
697 /*******************************************************************************
698 * IDirectSoundCaptureNotify
700 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_QueryInterface(
701 LPDIRECTSOUNDNOTIFY iface
,
705 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
706 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
708 if (This
->dscb
== NULL
) {
709 WARN("invalid parameter\n");
713 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
, riid
, ppobj
);
716 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface
)
718 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
719 ULONG ref
= InterlockedIncrement(&(This
->ref
));
720 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
724 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface
)
726 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
727 ULONG ref
= InterlockedDecrement(&(This
->ref
));
728 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
731 if (This
->dscb
->hwnotify
)
732 IDsDriverNotify_Release(This
->dscb
->hwnotify
);
733 This
->dscb
->notify
=NULL
;
734 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
);
735 HeapFree(GetProcessHeap(),0,This
);
736 TRACE("(%p) released\n", This
);
741 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
742 LPDIRECTSOUNDNOTIFY iface
,
744 LPCDSBPOSITIONNOTIFY notify
)
746 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
747 TRACE("(%p,0x%08lx,%p)\n",This
,howmuch
,notify
);
749 if (howmuch
> 0 && notify
== NULL
) {
750 WARN("invalid parameter: notify == NULL\n");
751 return DSERR_INVALIDPARAM
;
754 if (TRACE_ON(dsound
)) {
756 for (i
=0;i
<howmuch
;i
++)
757 TRACE("notify at %ld to %p\n",
758 notify
[i
].dwOffset
,notify
[i
].hEventNotify
);
761 if (This
->dscb
->hwnotify
) {
763 hres
= IDsDriverNotify_SetNotificationPositions(This
->dscb
->hwnotify
, howmuch
, notify
);
765 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
767 } else if (howmuch
> 0) {
768 /* Make an internal copy of the caller-supplied array.
769 * Replace the existing copy if one is already present. */
770 if (This
->dscb
->notifies
)
771 This
->dscb
->notifies
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
772 This
->dscb
->notifies
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
774 This
->dscb
->notifies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
775 howmuch
* sizeof(DSBPOSITIONNOTIFY
));
777 if (This
->dscb
->notifies
== NULL
) {
778 WARN("out of memory\n");
779 return DSERR_OUTOFMEMORY
;
781 CopyMemory(This
->dscb
->notifies
, notify
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
782 This
->dscb
->nrofnotifies
= howmuch
;
784 HeapFree(GetProcessHeap(), 0, This
->dscb
->notifies
);
785 This
->dscb
->notifies
= NULL
;
786 This
->dscb
->nrofnotifies
= 0;
792 static const IDirectSoundNotifyVtbl dscnvt
=
794 IDirectSoundCaptureNotifyImpl_QueryInterface
,
795 IDirectSoundCaptureNotifyImpl_AddRef
,
796 IDirectSoundCaptureNotifyImpl_Release
,
797 IDirectSoundCaptureNotifyImpl_SetNotificationPositions
,
800 HRESULT
IDirectSoundCaptureNotifyImpl_Create(
801 IDirectSoundCaptureBufferImpl
*dscb
,
802 IDirectSoundCaptureNotifyImpl
**pdscn
)
804 IDirectSoundCaptureNotifyImpl
* dscn
;
805 TRACE("(%p,%p)\n",dscb
,pdscn
);
807 dscn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(dscn
));
810 WARN("out of memory\n");
811 return DSERR_OUTOFMEMORY
;
815 dscn
->lpVtbl
= &dscnvt
;
818 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER
)dscb
);
824 /*******************************************************************************
825 * IDirectSoundCaptureBuffer
827 static HRESULT WINAPI
828 IDirectSoundCaptureBufferImpl_QueryInterface(
829 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
833 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
835 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
838 WARN("invalid parameter\n");
844 if ( IsEqualGUID( &IID_IDirectSoundNotify
, riid
) ) {
846 hres
= IDirectSoundCaptureNotifyImpl_Create(This
, &This
->notify
);
848 if (This
->dsound
->device
->hwbuf
) {
849 hres
= IDsCaptureDriverBuffer_QueryInterface(This
->dsound
->device
->hwbuf
,
850 &IID_IDsDriverNotify
, (LPVOID
*)&(This
->hwnotify
));
852 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
858 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY
)This
->notify
);
859 *ppobj
= (LPVOID
)This
->notify
;
863 WARN("IID_IDirectSoundNotify\n");
867 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer
, riid
) ||
868 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8
, riid
) ) {
869 IDirectSoundCaptureBuffer8_AddRef(iface
);
874 FIXME("(%p,%s,%p) unsupported GUID\n", This
, debugstr_guid(riid
), ppobj
);
875 return E_NOINTERFACE
;
879 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
881 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
882 ULONG ref
= InterlockedIncrement(&(This
->ref
));
883 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
888 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
890 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
891 ULONG ref
= InterlockedDecrement(&(This
->ref
));
892 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
895 TRACE("deleting object\n");
896 if (This
->dsound
->device
->state
== STATE_CAPTURING
)
897 This
->dsound
->device
->state
= STATE_STOPPING
;
899 HeapFree(GetProcessHeap(),0, This
->pdscbd
);
901 if (This
->dsound
->device
->hwi
) {
902 waveInReset(This
->dsound
->device
->hwi
);
903 waveInClose(This
->dsound
->device
->hwi
);
904 HeapFree(GetProcessHeap(),0, This
->dsound
->device
->pwave
);
905 This
->dsound
->device
->pwave
= 0;
906 This
->dsound
->device
->hwi
= 0;
909 if (This
->dsound
->device
->hwbuf
)
910 IDsCaptureDriverBuffer_Release(This
->dsound
->device
->hwbuf
);
912 /* remove from IDirectSoundCaptureImpl */
914 This
->dsound
->device
->capture_buffer
= NULL
;
916 ERR("does not reference dsound\n");
919 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
921 HeapFree(GetProcessHeap(), 0, This
->notifies
);
922 HeapFree( GetProcessHeap(), 0, This
);
923 TRACE("(%p) released\n", This
);
928 static HRESULT WINAPI
929 IDirectSoundCaptureBufferImpl_GetCaps(
930 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
931 LPDSCBCAPS lpDSCBCaps
)
933 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
934 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
937 WARN("invalid parameter: This == NULL\n");
938 return DSERR_INVALIDPARAM
;
941 if (lpDSCBCaps
== NULL
) {
942 WARN("invalid parameter: lpDSCBCaps == NULL\n");
943 return DSERR_INVALIDPARAM
;
946 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
947 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
948 lpDSCBCaps
->dwSize
, sizeof(DSCBCAPS
));
949 return DSERR_INVALIDPARAM
;
952 if (This
->dsound
== NULL
) {
953 WARN("invalid parameter: This->dsound == NULL\n");
954 return DSERR_INVALIDPARAM
;
957 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
958 lpDSCBCaps
->dwFlags
= This
->flags
;
959 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
960 lpDSCBCaps
->dwReserved
= 0;
962 TRACE("returning DS_OK\n");
966 static HRESULT WINAPI
967 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
968 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
969 LPDWORD lpdwCapturePosition
,
970 LPDWORD lpdwReadPosition
)
972 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
973 HRESULT hres
= DS_OK
;
974 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
977 WARN("invalid parameter: This == NULL\n");
978 return DSERR_INVALIDPARAM
;
981 if (This
->dsound
== NULL
) {
982 WARN("invalid parameter: This->dsound == NULL\n");
983 return DSERR_INVALIDPARAM
;
986 if (This
->dsound
->device
->driver
) {
987 hres
= IDsCaptureDriverBuffer_GetPosition(This
->dsound
->device
->hwbuf
, lpdwCapturePosition
, lpdwReadPosition
);
989 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
990 } else if (This
->dsound
->device
->hwi
) {
991 EnterCriticalSection(&(This
->dsound
->device
->lock
));
992 TRACE("old This->dsound->device->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
993 if (lpdwCapturePosition
) {
995 mtime
.wType
= TIME_BYTES
;
996 waveInGetPosition(This
->dsound
->device
->hwi
, &mtime
, sizeof(mtime
));
997 TRACE("mtime.u.cb=%ld,This->dsound->device->buflen=%ld\n", mtime
.u
.cb
,
998 This
->dsound
->device
->buflen
);
999 mtime
.u
.cb
= mtime
.u
.cb
% This
->dsound
->device
->buflen
;
1000 *lpdwCapturePosition
= mtime
.u
.cb
;
1003 if (lpdwReadPosition
) {
1004 if (This
->dsound
->device
->state
== STATE_STARTING
) {
1005 if (lpdwCapturePosition
)
1006 This
->dsound
->device
->read_position
= *lpdwCapturePosition
;
1007 This
->dsound
->device
->state
= STATE_CAPTURING
;
1009 *lpdwReadPosition
= This
->dsound
->device
->read_position
;
1011 TRACE("new This->dsound->device->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1012 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1013 if (lpdwCapturePosition
) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition
);
1014 if (lpdwReadPosition
) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition
);
1016 WARN("no driver\n");
1017 hres
= DSERR_NODRIVER
;
1020 TRACE("returning %08lx\n", hres
);
1024 static HRESULT WINAPI
1025 IDirectSoundCaptureBufferImpl_GetFormat(
1026 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1027 LPWAVEFORMATEX lpwfxFormat
,
1028 DWORD dwSizeAllocated
,
1029 LPDWORD lpdwSizeWritten
)
1031 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1032 HRESULT hres
= DS_OK
;
1033 TRACE( "(%p,%p,0x%08lx,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
1037 WARN("invalid parameter: This == NULL\n");
1038 return DSERR_INVALIDPARAM
;
1041 if (This
->dsound
== NULL
) {
1042 WARN("invalid parameter: This->dsound == NULL\n");
1043 return DSERR_INVALIDPARAM
;
1046 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->dsound
->device
->pwfx
->cbSize
))
1047 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->dsound
->device
->pwfx
->cbSize
;
1049 if (lpwfxFormat
) { /* NULL is valid (just want size) */
1050 CopyMemory(lpwfxFormat
, This
->dsound
->device
->pwfx
, dwSizeAllocated
);
1051 if (lpdwSizeWritten
)
1052 *lpdwSizeWritten
= dwSizeAllocated
;
1054 if (lpdwSizeWritten
)
1055 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->dsound
->device
->pwfx
->cbSize
;
1057 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
1058 hres
= DSERR_INVALIDPARAM
;
1062 TRACE("returning %08lx\n", hres
);
1066 static HRESULT WINAPI
1067 IDirectSoundCaptureBufferImpl_GetStatus(
1068 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1069 LPDWORD lpdwStatus
)
1071 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1072 TRACE( "(%p, %p), thread is %04lx\n", This
, lpdwStatus
, GetCurrentThreadId() );
1075 WARN("invalid parameter: This == NULL\n");
1076 return DSERR_INVALIDPARAM
;
1079 if (This
->dsound
== NULL
) {
1080 WARN("invalid parameter: This->dsound == NULL\n");
1081 return DSERR_INVALIDPARAM
;
1084 if (lpdwStatus
== NULL
) {
1085 WARN("invalid parameter: lpdwStatus == NULL\n");
1086 return DSERR_INVALIDPARAM
;
1090 EnterCriticalSection(&(This
->dsound
->device
->lock
));
1092 TRACE("old This->dsound->state=%s, old lpdwStatus=%08lx\n",
1093 captureStateString
[This
->dsound
->device
->state
],*lpdwStatus
);
1094 if ((This
->dsound
->device
->state
== STATE_STARTING
) ||
1095 (This
->dsound
->device
->state
== STATE_CAPTURING
)) {
1096 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
1097 if (This
->flags
& DSCBSTART_LOOPING
)
1098 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
1100 TRACE("new This->dsound->state=%s, new lpdwStatus=%08lx\n",
1101 captureStateString
[This
->dsound
->device
->state
],*lpdwStatus
);
1102 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1104 TRACE("status=%lx\n", *lpdwStatus
);
1105 TRACE("returning DS_OK\n");
1109 static HRESULT WINAPI
1110 IDirectSoundCaptureBufferImpl_Initialize(
1111 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1112 LPDIRECTSOUNDCAPTURE lpDSC
,
1113 LPCDSCBUFFERDESC lpcDSCBDesc
)
1115 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1117 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
1122 static HRESULT WINAPI
1123 IDirectSoundCaptureBufferImpl_Lock(
1124 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1127 LPVOID
* lplpvAudioPtr1
,
1128 LPDWORD lpdwAudioBytes1
,
1129 LPVOID
* lplpvAudioPtr2
,
1130 LPDWORD lpdwAudioBytes2
,
1133 HRESULT hres
= DS_OK
;
1134 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1135 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This
, dwReadCusor
,
1136 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
1137 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
1140 WARN("invalid parameter: This == NULL\n");
1141 return DSERR_INVALIDPARAM
;
1144 if (This
->dsound
== NULL
) {
1145 WARN("invalid parameter: This->dsound == NULL\n");
1146 return DSERR_INVALIDPARAM
;
1149 if (lplpvAudioPtr1
== NULL
) {
1150 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1151 return DSERR_INVALIDPARAM
;
1154 if (lpdwAudioBytes1
== NULL
) {
1155 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1156 return DSERR_INVALIDPARAM
;
1159 EnterCriticalSection(&(This
->dsound
->device
->lock
));
1161 if (This
->dsound
->device
->driver
) {
1162 hres
= IDsCaptureDriverBuffer_Lock(This
->dsound
->device
->hwbuf
, lplpvAudioPtr1
,
1163 lpdwAudioBytes1
, lplpvAudioPtr2
,
1164 lpdwAudioBytes2
, dwReadCusor
,
1165 dwReadBytes
, dwFlags
);
1167 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1168 } else if (This
->dsound
->device
->hwi
) {
1169 *lplpvAudioPtr1
= This
->dsound
->device
->buffer
+ dwReadCusor
;
1170 if ( (dwReadCusor
+ dwReadBytes
) > This
->dsound
->device
->buflen
) {
1171 *lpdwAudioBytes1
= This
->dsound
->device
->buflen
- dwReadCusor
;
1173 *lplpvAudioPtr2
= This
->dsound
->device
->buffer
;
1174 if (lpdwAudioBytes2
)
1175 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
1177 *lpdwAudioBytes1
= dwReadBytes
;
1179 *lplpvAudioPtr2
= 0;
1180 if (lpdwAudioBytes2
)
1181 *lpdwAudioBytes2
= 0;
1184 TRACE("invalid call\n");
1185 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
1188 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1190 TRACE("returning %08lx\n", hres
);
1194 static HRESULT WINAPI
1195 IDirectSoundCaptureBufferImpl_Start(
1196 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1199 HRESULT hres
= DS_OK
;
1200 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1201 TRACE( "(%p,0x%08lx)\n", This
, dwFlags
);
1204 WARN("invalid parameter: This == NULL\n");
1205 return DSERR_INVALIDPARAM
;
1208 if (This
->dsound
== NULL
) {
1209 WARN("invalid parameter: This->dsound == NULL\n");
1210 return DSERR_INVALIDPARAM
;
1213 if ( (This
->dsound
->device
->driver
== 0) && (This
->dsound
->device
->hwi
== 0) ) {
1214 WARN("no driver\n");
1215 return DSERR_NODRIVER
;
1218 EnterCriticalSection(&(This
->dsound
->device
->lock
));
1220 This
->flags
= dwFlags
;
1221 TRACE("old This->dsound->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1222 if (This
->dsound
->device
->state
== STATE_STOPPED
)
1223 This
->dsound
->device
->state
= STATE_STARTING
;
1224 else if (This
->dsound
->device
->state
== STATE_STOPPING
)
1225 This
->dsound
->device
->state
= STATE_CAPTURING
;
1226 TRACE("new This->dsound->device->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1228 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1230 if (This
->dsound
->device
->driver
) {
1231 hres
= IDsCaptureDriverBuffer_Start(This
->dsound
->device
->hwbuf
, dwFlags
);
1233 WARN("IDsCaptureDriverBuffer_Start failed\n");
1234 } else if (This
->dsound
->device
->hwi
) {
1235 IDirectSoundCaptureImpl
* ipDSC
= This
->dsound
;
1237 if (ipDSC
->device
->buffer
) {
1238 if (This
->nrofnotifies
) {
1241 ipDSC
->device
->nrofpwaves
= This
->nrofnotifies
;
1242 TRACE("nrofnotifies=%d\n", This
->nrofnotifies
);
1244 /* prepare headers */
1245 if (ipDSC
->device
->pwave
)
1246 ipDSC
->device
->pwave
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->device
->pwave
,
1247 ipDSC
->device
->nrofpwaves
*sizeof(WAVEHDR
));
1249 ipDSC
->device
->pwave
= HeapAlloc(GetProcessHeap(),0,
1250 ipDSC
->device
->nrofpwaves
*sizeof(WAVEHDR
));
1252 for (c
= 0; c
< ipDSC
->device
->nrofpwaves
; c
++) {
1253 if (This
->notifies
[c
].dwOffset
== DSBPN_OFFSETSTOP
) {
1254 TRACE("got DSBPN_OFFSETSTOP\n");
1255 ipDSC
->device
->nrofpwaves
= c
;
1259 ipDSC
->device
->pwave
[0].lpData
= (LPSTR
)ipDSC
->device
->buffer
;
1260 ipDSC
->device
->pwave
[0].dwBufferLength
=
1261 This
->notifies
[0].dwOffset
+ 1;
1263 ipDSC
->device
->pwave
[c
].lpData
= (LPSTR
)ipDSC
->device
->buffer
+
1264 This
->notifies
[c
-1].dwOffset
+ 1;
1265 ipDSC
->device
->pwave
[c
].dwBufferLength
=
1266 This
->notifies
[c
].dwOffset
-
1267 This
->notifies
[c
-1].dwOffset
;
1269 ipDSC
->device
->pwave
[c
].dwBytesRecorded
= 0;
1270 ipDSC
->device
->pwave
[c
].dwUser
= (DWORD
)ipDSC
;
1271 ipDSC
->device
->pwave
[c
].dwFlags
= 0;
1272 ipDSC
->device
->pwave
[c
].dwLoops
= 0;
1273 hres
= mmErr(waveInPrepareHeader(ipDSC
->device
->hwi
,
1274 &(ipDSC
->device
->pwave
[c
]),sizeof(WAVEHDR
)));
1275 if (hres
!= DS_OK
) {
1276 WARN("waveInPrepareHeader failed\n");
1278 waveInUnprepareHeader(ipDSC
->device
->hwi
,
1279 &(ipDSC
->device
->pwave
[c
]),sizeof(WAVEHDR
));
1283 hres
= mmErr(waveInAddBuffer(ipDSC
->device
->hwi
,
1284 &(ipDSC
->device
->pwave
[c
]), sizeof(WAVEHDR
)));
1285 if (hres
!= DS_OK
) {
1286 WARN("waveInAddBuffer failed\n");
1288 waveInUnprepareHeader(ipDSC
->device
->hwi
,
1289 &(ipDSC
->device
->pwave
[c
]),sizeof(WAVEHDR
));
1294 FillMemory(ipDSC
->device
->buffer
, ipDSC
->device
->buflen
,
1295 (ipDSC
->device
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
1297 TRACE("no notifiers specified\n");
1298 /* no notifiers specified so just create a single default header */
1299 ipDSC
->device
->nrofpwaves
= 1;
1300 if (ipDSC
->device
->pwave
)
1301 ipDSC
->device
->pwave
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->device
->pwave
,sizeof(WAVEHDR
));
1303 ipDSC
->device
->pwave
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR
));
1305 ipDSC
->device
->pwave
[0].lpData
= (LPSTR
)ipDSC
->device
->buffer
;
1306 ipDSC
->device
->pwave
[0].dwBufferLength
= ipDSC
->device
->buflen
;
1307 ipDSC
->device
->pwave
[0].dwBytesRecorded
= 0;
1308 ipDSC
->device
->pwave
[0].dwUser
= (DWORD
)ipDSC
;
1309 ipDSC
->device
->pwave
[0].dwFlags
= 0;
1310 ipDSC
->device
->pwave
[0].dwLoops
= 0;
1312 hres
= mmErr(waveInPrepareHeader(ipDSC
->device
->hwi
,
1313 &(ipDSC
->device
->pwave
[0]),sizeof(WAVEHDR
)));
1314 if (hres
!= DS_OK
) {
1315 WARN("waveInPrepareHeader failed\n");
1316 waveInUnprepareHeader(ipDSC
->device
->hwi
,
1317 &(ipDSC
->device
->pwave
[0]),sizeof(WAVEHDR
));
1319 hres
= mmErr(waveInAddBuffer(ipDSC
->device
->hwi
,
1320 &(ipDSC
->device
->pwave
[0]), sizeof(WAVEHDR
)));
1321 if (hres
!= DS_OK
) {
1322 WARN("waveInAddBuffer failed\n");
1323 waveInUnprepareHeader(ipDSC
->device
->hwi
,
1324 &(ipDSC
->device
->pwave
[0]),sizeof(WAVEHDR
));
1329 ipDSC
->device
->index
= 0;
1330 ipDSC
->device
->read_position
= 0;
1332 if (hres
== DS_OK
) {
1333 /* start filling the first buffer */
1334 hres
= mmErr(waveInStart(ipDSC
->device
->hwi
));
1336 WARN("waveInStart failed\n");
1339 if (hres
!= DS_OK
) {
1340 WARN("calling waveInClose because of error\n");
1341 waveInClose(This
->dsound
->device
->hwi
);
1342 This
->dsound
->device
->hwi
= 0;
1345 WARN("no driver\n");
1346 hres
= DSERR_NODRIVER
;
1349 TRACE("returning %08lx\n", hres
);
1353 static HRESULT WINAPI
1354 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1356 HRESULT hres
= DS_OK
;
1357 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1358 TRACE( "(%p)\n", This
);
1361 WARN("invalid parameter: This == NULL\n");
1362 return DSERR_INVALIDPARAM
;
1365 if (This
->dsound
== NULL
) {
1366 WARN("invalid parameter: This->dsound == NULL\n");
1367 return DSERR_INVALIDPARAM
;
1370 EnterCriticalSection(&(This
->dsound
->device
->lock
));
1372 TRACE("old This->dsound->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1373 if (This
->dsound
->device
->state
== STATE_CAPTURING
)
1374 This
->dsound
->device
->state
= STATE_STOPPING
;
1375 else if (This
->dsound
->device
->state
== STATE_STARTING
)
1376 This
->dsound
->device
->state
= STATE_STOPPED
;
1377 TRACE("new This->dsound->device->state=%s\n",captureStateString
[This
->dsound
->device
->state
]);
1379 LeaveCriticalSection(&(This
->dsound
->device
->lock
));
1381 if (This
->dsound
->device
->driver
) {
1382 hres
= IDsCaptureDriverBuffer_Stop(This
->dsound
->device
->hwbuf
);
1384 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1385 } else if (This
->dsound
->device
->hwi
) {
1386 hres
= mmErr(waveInReset(This
->dsound
->device
->hwi
));
1388 WARN("waveInReset() failed\n");
1390 WARN("no driver\n");
1391 hres
= DSERR_NODRIVER
;
1394 TRACE("returning %08lx\n", hres
);
1398 static HRESULT WINAPI
1399 IDirectSoundCaptureBufferImpl_Unlock(
1400 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1401 LPVOID lpvAudioPtr1
,
1402 DWORD dwAudioBytes1
,
1403 LPVOID lpvAudioPtr2
,
1404 DWORD dwAudioBytes2
)
1406 HRESULT hres
= DS_OK
;
1407 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1408 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
1409 lpvAudioPtr2
, dwAudioBytes2
);
1412 WARN("invalid parameter: This == NULL\n");
1413 return DSERR_INVALIDPARAM
;
1416 if (lpvAudioPtr1
== NULL
) {
1417 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1418 return DSERR_INVALIDPARAM
;
1421 if (This
->dsound
->device
->driver
) {
1422 hres
= IDsCaptureDriverBuffer_Unlock(This
->dsound
->device
->hwbuf
, lpvAudioPtr1
,
1423 dwAudioBytes1
, lpvAudioPtr2
, dwAudioBytes2
);
1425 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1426 } else if (This
->dsound
->device
->hwi
) {
1427 This
->dsound
->device
->read_position
= (This
->dsound
->device
->read_position
+
1428 (dwAudioBytes1
+ dwAudioBytes2
)) % This
->dsound
->device
->buflen
;
1430 WARN("invalid call\n");
1431 hres
= DSERR_INVALIDCALL
;
1434 TRACE("returning %08lx\n", hres
);
1438 static HRESULT WINAPI
1439 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1440 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1441 REFGUID rguidObject
,
1443 REFGUID rguidInterface
,
1446 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1448 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
1449 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
1454 static HRESULT WINAPI
1455 IDirectSoundCaptureBufferImpl_GetFXStatus(
1456 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1458 LPDWORD pdwFXStatus
)
1460 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1462 FIXME( "(%p,%lu,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
1467 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
=
1469 /* IUnknown methods */
1470 IDirectSoundCaptureBufferImpl_QueryInterface
,
1471 IDirectSoundCaptureBufferImpl_AddRef
,
1472 IDirectSoundCaptureBufferImpl_Release
,
1474 /* IDirectSoundCaptureBuffer methods */
1475 IDirectSoundCaptureBufferImpl_GetCaps
,
1476 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
1477 IDirectSoundCaptureBufferImpl_GetFormat
,
1478 IDirectSoundCaptureBufferImpl_GetStatus
,
1479 IDirectSoundCaptureBufferImpl_Initialize
,
1480 IDirectSoundCaptureBufferImpl_Lock
,
1481 IDirectSoundCaptureBufferImpl_Start
,
1482 IDirectSoundCaptureBufferImpl_Stop
,
1483 IDirectSoundCaptureBufferImpl_Unlock
,
1485 /* IDirectSoundCaptureBuffer methods */
1486 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
1487 IDirectSoundCaptureBufferImpl_GetFXStatus
1490 HRESULT
DSOUND_CreateDirectSoundCaptureBuffer(
1491 IDirectSoundCaptureImpl
*ipDSC
,
1492 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
1495 LPWAVEFORMATEX wfex
;
1496 TRACE( "(%p,%p)\n", lpcDSCBufferDesc
, ppobj
);
1498 if (ipDSC
== NULL
) {
1499 WARN("invalid parameter: ipDSC == NULL\n");
1500 return DSERR_INVALIDPARAM
;
1503 if (lpcDSCBufferDesc
== NULL
) {
1504 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
1505 return DSERR_INVALIDPARAM
;
1508 if (ppobj
== NULL
) {
1509 WARN("invalid parameter: ppobj == NULL\n");
1510 return DSERR_INVALIDPARAM
;
1513 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
1514 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
1515 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
1516 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) {
1517 WARN("invalid lpcDSCBufferDesc\n");
1519 return DSERR_INVALIDPARAM
;
1522 if ( !ipDSC
->device
) {
1523 WARN("not initialized\n");
1525 return DSERR_UNINITIALIZED
;
1528 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
1531 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
1532 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1533 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
1534 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
1535 wfex
->wBitsPerSample
, wfex
->cbSize
);
1537 if (wfex
->wFormatTag
== WAVE_FORMAT_PCM
) {
1538 ipDSC
->device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
));
1539 CopyMemory(ipDSC
->device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
));
1540 ipDSC
->device
->pwfx
->cbSize
= 0;
1542 ipDSC
->device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1543 CopyMemory(ipDSC
->device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1546 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
1548 return DSERR_INVALIDPARAM
; /* FIXME: DSERR_BADFORMAT ? */
1551 *ppobj
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1552 sizeof(IDirectSoundCaptureBufferImpl
));
1554 if ( *ppobj
== NULL
) {
1555 WARN("out of memory\n");
1557 return DSERR_OUTOFMEMORY
;
1559 HRESULT err
= DS_OK
;
1562 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)*ppobj
;
1565 This
->dsound
= ipDSC
;
1566 This
->dsound
->device
->capture_buffer
= This
;
1567 This
->notify
= NULL
;
1568 This
->nrofnotifies
= 0;
1569 This
->hwnotify
= NULL
;
1571 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1572 lpcDSCBufferDesc
->dwSize
);
1574 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
1576 WARN("no memory\n");
1577 This
->dsound
->device
->capture_buffer
= 0;
1578 HeapFree( GetProcessHeap(), 0, This
);
1580 return DSERR_OUTOFMEMORY
;
1583 This
->lpVtbl
= &dscbvt
;
1585 if (ipDSC
->device
->driver
) {
1586 if (This
->dsound
->device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1587 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
1589 if (This
->dsound
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
1590 /* allocate buffer from system memory */
1591 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1592 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, ipDSC
->device
->buffer
);
1593 if (ipDSC
->device
->buffer
)
1594 newbuf
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->device
->buffer
,buflen
);
1596 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1598 if (newbuf
== NULL
) {
1599 WARN("failed to allocate capture buffer\n");
1600 err
= DSERR_OUTOFMEMORY
;
1601 /* but the old buffer might still exist and must be re-prepared */
1603 ipDSC
->device
->buffer
= newbuf
;
1604 ipDSC
->device
->buflen
= buflen
;
1607 /* let driver allocate memory */
1608 ipDSC
->device
->buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1610 HeapFree( GetProcessHeap(), 0, ipDSC
->device
->buffer
);
1611 ipDSC
->device
->buffer
= NULL
;
1614 err
= IDsCaptureDriver_CreateCaptureBuffer(ipDSC
->device
->driver
,
1615 ipDSC
->device
->pwfx
,0,0,&(ipDSC
->device
->buflen
),&(ipDSC
->device
->buffer
),(LPVOID
*)&(ipDSC
->device
->hwbuf
));
1617 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1618 This
->dsound
->device
->capture_buffer
= 0;
1619 HeapFree( GetProcessHeap(), 0, This
);
1624 DWORD flags
= CALLBACK_FUNCTION
;
1625 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
1626 flags
|= WAVE_DIRECTSOUND
;
1627 err
= mmErr(waveInOpen(&(ipDSC
->device
->hwi
),
1628 ipDSC
->device
->drvdesc
.dnDevNode
, ipDSC
->device
->pwfx
,
1629 (DWORD_PTR
)DSOUND_capture_callback
, (DWORD
)ipDSC
->device
, flags
));
1631 WARN("waveInOpen failed\n");
1632 This
->dsound
->device
->capture_buffer
= 0;
1633 HeapFree( GetProcessHeap(), 0, This
);
1638 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1639 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, ipDSC
->device
->buffer
);
1640 if (ipDSC
->device
->buffer
)
1641 newbuf
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->device
->buffer
,buflen
);
1643 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1644 if (newbuf
== NULL
) {
1645 WARN("failed to allocate capture buffer\n");
1646 err
= DSERR_OUTOFMEMORY
;
1647 /* but the old buffer might still exist and must be re-prepared */
1649 ipDSC
->device
->buffer
= newbuf
;
1650 ipDSC
->device
->buflen
= buflen
;
1655 TRACE("returning DS_OK\n");
1659 /*******************************************************************************
1660 * DirectSoundCaptureDevice
1663 HRESULT
DirectSoundCaptureDevice_Create(
1664 DirectSoundCaptureDevice
** ppDevice
)
1666 DirectSoundCaptureDevice
* device
;
1667 TRACE("(%p)\n", ppDevice
);
1669 /* Allocate memory */
1670 device
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DirectSoundCaptureDevice
));
1672 if (device
== NULL
) {
1673 WARN("out of memory\n");
1674 return DSERR_OUTOFMEMORY
;
1678 device
->state
= STATE_STOPPED
;
1680 InitializeCriticalSection( &(device
->lock
) );
1681 device
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)"DSCAPTURE_lock";
1688 ULONG
DirectSoundCaptureDevice_Release(
1689 DirectSoundCaptureDevice
* device
)
1692 TRACE("(%p) ref was %lu\n", device
, device
->ref
);
1696 if (device
->ref
== 0) {
1697 TRACE("deleting object\n");
1698 if (device
->capture_buffer
)
1699 IDirectSoundCaptureBufferImpl_Release(
1700 (LPDIRECTSOUNDCAPTUREBUFFER8
) device
->capture_buffer
);
1702 if (device
->driver
) {
1703 IDsCaptureDriver_Close(device
->driver
);
1704 IDsCaptureDriver_Release(device
->driver
);
1707 HeapFree(GetProcessHeap(), 0, device
->pwfx
);
1708 device
->lock
.DebugInfo
->Spare
[0] = 0;
1709 DeleteCriticalSection( &(device
->lock
) );
1710 DSOUND_capture
[device
->drvdesc
.dnDevNode
] = NULL
;
1711 HeapFree(GetProcessHeap(), 0, device
);
1712 TRACE("(%p) released\n", device
);
1717 /*******************************************************************************
1718 * DirectSoundCapture ClassFactory
1721 static HRESULT WINAPI
1722 DSCCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
)
1724 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1726 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
1727 return E_NOINTERFACE
;
1731 DSCCF_AddRef(LPCLASSFACTORY iface
)
1733 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1734 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1735 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1740 DSCCF_Release(LPCLASSFACTORY iface
)
1742 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1743 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1744 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1745 /* static class, won't be freed */
1749 static HRESULT WINAPI
1750 DSCCF_CreateInstance(
1751 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
)
1753 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1754 TRACE("(%p)->(%p,%s,%p)\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1757 WARN("aggregation not supported\n");
1758 return CLASS_E_NOAGGREGATION
;
1761 if (ppobj
== NULL
) {
1762 WARN("invalid parameter\n");
1763 return E_INVALIDARG
;
1768 if ( IsEqualGUID( &IID_IDirectSoundCapture
, riid
) )
1769 return DSOUND_CaptureCreate8((LPDIRECTSOUNDCAPTURE
*)ppobj
,pOuter
);
1771 WARN("(%p,%p,%s,%p) Interface not found!\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1772 return E_NOINTERFACE
;
1775 static HRESULT WINAPI
1776 DSCCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
)
1778 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1779 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
1783 static const IClassFactoryVtbl DSCCF_Vtbl
=
1785 DSCCF_QueryInterface
,
1788 DSCCF_CreateInstance
,
1792 IClassFactoryImpl DSOUND_CAPTURE_CF
= { &DSCCF_Vtbl
, 1 };