3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * Implement FX support.
24 * Implement both IDirectSoundCaptureBuffer and IDirectSoundCaptureBuffer8
25 * Make DirectSoundCaptureCreate and DirectSoundCaptureCreate8 behave differently
30 #define NONAMELESSSTRUCT
31 #define NONAMELESSUNION
39 #include "wine/debug.h"
42 #include "dsound_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
46 /*****************************************************************************
47 * IDirectSoundCapture implementation structure
49 struct IDirectSoundCaptureImpl
52 const IDirectSoundCaptureVtbl
*lpVtbl
;
55 DirectSoundCaptureDevice
*device
;
58 static HRESULT
IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8
* ppds
);
61 /*****************************************************************************
62 * IDirectSoundCaptureNotify implementation structure
64 struct IDirectSoundCaptureNotifyImpl
67 const IDirectSoundNotifyVtbl
*lpVtbl
;
69 IDirectSoundCaptureBufferImpl
* dscb
;
72 static HRESULT
IDirectSoundCaptureNotifyImpl_Create(IDirectSoundCaptureBufferImpl
*dscb
,
73 IDirectSoundCaptureNotifyImpl
** pdscn
);
76 DirectSoundCaptureDevice
* DSOUND_capture
[MAXWAVEDRIVERS
];
78 static HRESULT
DirectSoundCaptureDevice_Create(DirectSoundCaptureDevice
** ppDevice
);
80 static const char * const captureStateString
[] = {
87 HRESULT
DSOUND_CaptureCreate(
89 LPDIRECTSOUNDCAPTURE
*ppDSC
)
91 LPDIRECTSOUNDCAPTURE pDSC
;
93 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDSC
);
95 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
96 !IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
101 /* Get dsound configuration */
102 setup_dsound_options();
104 hr
= IDirectSoundCaptureImpl_Create(&pDSC
);
106 IDirectSoundCapture_AddRef(pDSC
);
109 WARN("IDirectSoundCaptureImpl_Create failed\n");
116 HRESULT
DSOUND_CaptureCreate8(
118 LPDIRECTSOUNDCAPTURE8
*ppDSC8
)
120 LPDIRECTSOUNDCAPTURE8 pDSC8
;
122 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDSC8
);
124 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
125 !IsEqualIID(riid
, &IID_IDirectSoundCapture8
)) {
127 return E_NOINTERFACE
;
130 /* Get dsound configuration */
131 setup_dsound_options();
133 hr
= IDirectSoundCaptureImpl_Create(&pDSC8
);
135 IDirectSoundCapture_AddRef(pDSC8
);
138 WARN("IDirectSoundCaptureImpl_Create failed\n");
145 /***************************************************************************
146 * DirectSoundCaptureCreate [DSOUND.6]
148 * Create and initialize a DirectSoundCapture interface.
151 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
152 * lplpDSC [O] Address of a variable to receive the interface pointer.
153 * pUnkOuter [I] Must be NULL.
157 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
161 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
162 * or NULL for the default device or DSDEVID_DefaultCapture or
163 * DSDEVID_DefaultVoiceCapture.
165 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
167 HRESULT WINAPI
DirectSoundCaptureCreate(
169 LPDIRECTSOUNDCAPTURE
*ppDSC
,
173 LPDIRECTSOUNDCAPTURE pDSC
;
174 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC
, pUnkOuter
);
177 WARN("invalid parameter: ppDSC == NULL\n");
178 return DSERR_INVALIDPARAM
;
182 WARN("invalid parameter: pUnkOuter != NULL\n");
184 return DSERR_NOAGGREGATION
;
187 hr
= DSOUND_CaptureCreate(&IID_IDirectSoundCapture
, &pDSC
);
189 hr
= IDirectSoundCapture_Initialize(pDSC
, lpcGUID
);
191 IDirectSoundCapture_Release(pDSC
);
201 /***************************************************************************
202 * DirectSoundCaptureCreate8 [DSOUND.12]
204 * Create and initialize a DirectSoundCapture interface.
207 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
208 * lplpDSC [O] Address of a variable to receive the interface pointer.
209 * pUnkOuter [I] Must be NULL.
213 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
217 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
218 * or NULL for the default device or DSDEVID_DefaultCapture or
219 * DSDEVID_DefaultVoiceCapture.
221 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
223 HRESULT WINAPI
DirectSoundCaptureCreate8(
225 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
229 LPDIRECTSOUNDCAPTURE8 pDSC8
;
230 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC8
, pUnkOuter
);
232 if (ppDSC8
== NULL
) {
233 WARN("invalid parameter: ppDSC8 == NULL\n");
234 return DSERR_INVALIDPARAM
;
238 WARN("invalid parameter: pUnkOuter != NULL\n");
240 return DSERR_NOAGGREGATION
;
243 hr
= DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8
, &pDSC8
);
245 hr
= IDirectSoundCapture_Initialize(pDSC8
, lpcGUID
);
247 IDirectSoundCapture_Release(pDSC8
);
257 /***************************************************************************
258 * DirectSoundCaptureEnumerateA [DSOUND.7]
260 * Enumerate all DirectSound drivers installed in the system.
263 * lpDSEnumCallback [I] Address of callback function.
264 * lpContext [I] Address of user defined context passed to callback function.
268 * Failure: DSERR_INVALIDPARAM
271 DirectSoundCaptureEnumerateA(
272 LPDSENUMCALLBACKA lpDSEnumCallback
,
280 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
282 if (lpDSEnumCallback
== NULL
) {
283 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
284 return DSERR_INVALIDPARAM
;
287 devs
= waveInGetNumDevs();
289 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
290 for (wid
= 0; wid
< devs
; ++wid
) {
291 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
292 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
294 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
295 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
296 if (lpDSEnumCallback(NULL
, "Primary Sound Capture Driver", desc
.szDrvname
, lpContext
) == FALSE
)
304 for (wid
= 0; wid
< devs
; ++wid
) {
305 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
307 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
308 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
309 if (lpDSEnumCallback(&DSOUND_capture_guids
[wid
], desc
.szDesc
, desc
.szDrvname
, lpContext
) == FALSE
)
317 /***************************************************************************
318 * DirectSoundCaptureEnumerateW [DSOUND.8]
320 * Enumerate all DirectSound drivers installed in the system.
323 * lpDSEnumCallback [I] Address of callback function.
324 * lpContext [I] Address of user defined context passed to callback function.
328 * Failure: DSERR_INVALIDPARAM
331 DirectSoundCaptureEnumerateW(
332 LPDSENUMCALLBACKW lpDSEnumCallback
,
339 WCHAR wDesc
[MAXPNAMELEN
];
340 WCHAR wName
[MAXPNAMELEN
];
342 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
344 if (lpDSEnumCallback
== NULL
) {
345 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
346 return DSERR_INVALIDPARAM
;
349 devs
= waveInGetNumDevs();
351 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
352 for (wid
= 0; wid
< devs
; ++wid
) {
353 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
354 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
356 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
357 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
358 MultiByteToWideChar( CP_ACP
, 0, "Primary Sound Capture Driver", -1,
359 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
360 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
361 wName
, sizeof(wName
)/sizeof(WCHAR
) );
362 if (lpDSEnumCallback(NULL
, wDesc
, wName
, lpContext
) == FALSE
)
370 for (wid
= 0; wid
< devs
; ++wid
) {
371 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
373 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
374 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
375 MultiByteToWideChar( CP_ACP
, 0, desc
.szDesc
, -1,
376 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
377 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
378 wName
, sizeof(wName
)/sizeof(WCHAR
) );
379 if (lpDSEnumCallback((LPGUID
)&DSOUND_capture_guids
[wid
], wDesc
, wName
, lpContext
) == FALSE
)
388 DSOUND_capture_callback(
395 DirectSoundCaptureDevice
* This
= (DirectSoundCaptureDevice
*)dwUser
;
396 TRACE("(%p,%08x(%s),%08x,%08x,%08x) entering at %d\n",hwi
,msg
,
397 msg
== MM_WIM_OPEN
? "MM_WIM_OPEN" : msg
== MM_WIM_CLOSE
? "MM_WIM_CLOSE" :
398 msg
== MM_WIM_DATA
? "MM_WIM_DATA" : "UNKNOWN",dwUser
,dw1
,dw2
,GetTickCount());
400 if (msg
== MM_WIM_DATA
) {
401 LPWAVEHDR pHdr
= (LPWAVEHDR
)dw1
;
402 EnterCriticalSection( &(This
->lock
) );
403 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
404 captureStateString
[This
->state
],This
->index
);
405 if (This
->state
!= STATE_STOPPED
) {
406 int index
= This
->index
;
407 if (This
->state
== STATE_STARTING
) {
408 This
->read_position
= pHdr
->dwBytesRecorded
;
409 This
->state
= STATE_CAPTURING
;
411 if (This
->capture_buffer
->nrofnotifies
)
412 SetEvent(This
->capture_buffer
->notifies
[This
->index
].hEventNotify
);
413 This
->index
= (This
->index
+ 1) % This
->nrofpwaves
;
414 if ( (This
->index
== 0) && !(This
->capture_buffer
->flags
& DSCBSTART_LOOPING
) ) {
415 TRACE("end of buffer\n");
416 This
->state
= STATE_STOPPED
;
418 if (This
->state
== STATE_CAPTURING
) {
419 waveInAddBuffer(hwi
, &(This
->pwave
[index
]), sizeof(WAVEHDR
));
420 } else if (This
->state
== STATE_STOPPING
) {
422 This
->state
= STATE_STOPPED
;
426 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
427 captureStateString
[This
->state
],This
->index
);
428 LeaveCriticalSection( &(This
->lock
) );
431 TRACE("completed\n");
434 /***************************************************************************
435 * IDirectSoundCaptureImpl
437 static HRESULT WINAPI
438 IDirectSoundCaptureImpl_QueryInterface(
439 LPDIRECTSOUNDCAPTURE iface
,
443 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
444 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
447 WARN("invalid parameter\n");
453 if (IsEqualIID(riid
, &IID_IUnknown
)) {
454 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
457 } else if (IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
458 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
463 WARN("unsupported riid: %s\n", debugstr_guid(riid
));
464 return E_NOINTERFACE
;
468 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface
)
470 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
471 ULONG ref
= InterlockedIncrement(&(This
->ref
));
472 TRACE("(%p) ref was %d\n", This
, ref
- 1);
477 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface
)
479 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
480 ULONG ref
= InterlockedDecrement(&(This
->ref
));
481 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
485 DirectSoundCaptureDevice_Release(This
->device
);
487 HeapFree( GetProcessHeap(), 0, This
);
488 TRACE("(%p) released\n", This
);
493 HRESULT WINAPI
IDirectSoundCaptureImpl_CreateCaptureBuffer(
494 LPDIRECTSOUNDCAPTURE iface
,
495 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
496 LPDIRECTSOUNDCAPTUREBUFFER
* lplpDSCaptureBuffer
,
500 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
502 TRACE( "(%p,%p,%p,%p)\n",iface
,lpcDSCBufferDesc
,lplpDSCaptureBuffer
,pUnk
);
504 if (lpcDSCBufferDesc
== NULL
) {
505 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
506 return DSERR_INVALIDPARAM
;
509 if (lplpDSCaptureBuffer
== NULL
) {
510 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
511 return DSERR_INVALIDPARAM
;
515 WARN("invalid parameter: pUnk != NULL\n");
516 return DSERR_INVALIDPARAM
;
519 /* FIXME: We can only have one buffer so what do we do here? */
520 if (This
->device
->capture_buffer
) {
521 WARN("lnvalid parameter: already has buffer\n");
522 return DSERR_INVALIDPARAM
; /* DSERR_GENERIC ? */
525 hr
= IDirectSoundCaptureBufferImpl_Create(This
->device
,
526 (IDirectSoundCaptureBufferImpl
**)lplpDSCaptureBuffer
, lpcDSCBufferDesc
);
529 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
534 HRESULT WINAPI
IDirectSoundCaptureImpl_GetCaps(
535 LPDIRECTSOUNDCAPTURE iface
,
536 LPDSCCAPS lpDSCCaps
)
538 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
539 TRACE("(%p,%p)\n",This
,lpDSCCaps
);
541 if (This
->device
== NULL
) {
542 WARN("not initialized\n");
543 return DSERR_UNINITIALIZED
;
546 if (lpDSCCaps
== NULL
) {
547 WARN("invalid parameter: lpDSCCaps== NULL\n");
548 return DSERR_INVALIDPARAM
;
551 if (lpDSCCaps
->dwSize
< sizeof(*lpDSCCaps
)) {
552 WARN("invalid parameter: lpDSCCaps->dwSize = %d\n", lpDSCCaps
->dwSize
);
553 return DSERR_INVALIDPARAM
;
556 lpDSCCaps
->dwFlags
= This
->device
->drvcaps
.dwFlags
;
557 lpDSCCaps
->dwFormats
= This
->device
->drvcaps
.dwFormats
;
558 lpDSCCaps
->dwChannels
= This
->device
->drvcaps
.dwChannels
;
560 TRACE("(flags=0x%08x,format=0x%08x,channels=%d)\n",lpDSCCaps
->dwFlags
,
561 lpDSCCaps
->dwFormats
, lpDSCCaps
->dwChannels
);
566 HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(
567 LPDIRECTSOUNDCAPTURE iface
,
570 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
571 TRACE("(%p,%s)\n", This
, debugstr_guid(lpcGUID
));
573 if (This
->device
!= NULL
) {
574 WARN("already initialized\n");
575 return DSERR_ALREADYINITIALIZED
;
578 return DirectSoundCaptureDevice_Initialize(&This
->device
, lpcGUID
);
581 static const IDirectSoundCaptureVtbl dscvt
=
583 /* IUnknown methods */
584 IDirectSoundCaptureImpl_QueryInterface
,
585 IDirectSoundCaptureImpl_AddRef
,
586 IDirectSoundCaptureImpl_Release
,
588 /* IDirectSoundCapture methods */
589 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
590 IDirectSoundCaptureImpl_GetCaps
,
591 IDirectSoundCaptureImpl_Initialize
594 static HRESULT
IDirectSoundCaptureImpl_Create(
595 LPDIRECTSOUNDCAPTURE8
* ppDSC
)
597 IDirectSoundCaptureImpl
*pDSC
;
598 TRACE("(%p)\n", ppDSC
);
600 /* Allocate memory */
601 pDSC
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundCaptureImpl
));
603 WARN("out of memory\n");
605 return DSERR_OUTOFMEMORY
;
608 pDSC
->lpVtbl
= &dscvt
;
612 *ppDSC
= (LPDIRECTSOUNDCAPTURE8
)pDSC
;
617 /*******************************************************************************
618 * IDirectSoundCaptureNotify
620 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_QueryInterface(
621 LPDIRECTSOUNDNOTIFY iface
,
625 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
626 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
628 if (This
->dscb
== NULL
) {
629 WARN("invalid parameter\n");
633 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
, riid
, ppobj
);
636 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface
)
638 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
639 ULONG ref
= InterlockedIncrement(&(This
->ref
));
640 TRACE("(%p) ref was %d\n", This
, ref
- 1);
644 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface
)
646 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
647 ULONG ref
= InterlockedDecrement(&(This
->ref
));
648 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
651 if (This
->dscb
->hwnotify
)
652 IDsDriverNotify_Release(This
->dscb
->hwnotify
);
653 This
->dscb
->notify
=NULL
;
654 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
);
655 HeapFree(GetProcessHeap(),0,This
);
656 TRACE("(%p) released\n", This
);
661 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
662 LPDIRECTSOUNDNOTIFY iface
,
664 LPCDSBPOSITIONNOTIFY notify
)
666 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
667 TRACE("(%p,0x%08x,%p)\n",This
,howmuch
,notify
);
669 if (howmuch
> 0 && notify
== NULL
) {
670 WARN("invalid parameter: notify == NULL\n");
671 return DSERR_INVALIDPARAM
;
674 if (TRACE_ON(dsound
)) {
676 for (i
=0;i
<howmuch
;i
++)
677 TRACE("notify at %d to %p\n",
678 notify
[i
].dwOffset
,notify
[i
].hEventNotify
);
681 if (This
->dscb
->hwnotify
) {
683 hres
= IDsDriverNotify_SetNotificationPositions(This
->dscb
->hwnotify
, howmuch
, notify
);
685 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
687 } else if (howmuch
> 0) {
688 /* Make an internal copy of the caller-supplied array.
689 * Replace the existing copy if one is already present. */
690 if (This
->dscb
->notifies
)
691 This
->dscb
->notifies
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
692 This
->dscb
->notifies
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
694 This
->dscb
->notifies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
695 howmuch
* sizeof(DSBPOSITIONNOTIFY
));
697 if (This
->dscb
->notifies
== NULL
) {
698 WARN("out of memory\n");
699 return DSERR_OUTOFMEMORY
;
701 CopyMemory(This
->dscb
->notifies
, notify
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
702 This
->dscb
->nrofnotifies
= howmuch
;
704 HeapFree(GetProcessHeap(), 0, This
->dscb
->notifies
);
705 This
->dscb
->notifies
= NULL
;
706 This
->dscb
->nrofnotifies
= 0;
712 static const IDirectSoundNotifyVtbl dscnvt
=
714 IDirectSoundCaptureNotifyImpl_QueryInterface
,
715 IDirectSoundCaptureNotifyImpl_AddRef
,
716 IDirectSoundCaptureNotifyImpl_Release
,
717 IDirectSoundCaptureNotifyImpl_SetNotificationPositions
,
720 static HRESULT
IDirectSoundCaptureNotifyImpl_Create(
721 IDirectSoundCaptureBufferImpl
*dscb
,
722 IDirectSoundCaptureNotifyImpl
**pdscn
)
724 IDirectSoundCaptureNotifyImpl
* dscn
;
725 TRACE("(%p,%p)\n",dscb
,pdscn
);
727 dscn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(dscn
));
730 WARN("out of memory\n");
731 return DSERR_OUTOFMEMORY
;
735 dscn
->lpVtbl
= &dscnvt
;
738 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER
)dscb
);
744 /*******************************************************************************
745 * IDirectSoundCaptureBuffer
747 static HRESULT WINAPI
748 IDirectSoundCaptureBufferImpl_QueryInterface(
749 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
753 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
755 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
758 WARN("invalid parameter\n");
764 if ( IsEqualGUID( &IID_IDirectSoundNotify
, riid
) ) {
766 hres
= IDirectSoundCaptureNotifyImpl_Create(This
, &This
->notify
);
768 if (This
->device
->hwbuf
) {
769 hres
= IDsCaptureDriverBuffer_QueryInterface(This
->device
->hwbuf
,
770 &IID_IDsDriverNotify
, (LPVOID
*)&(This
->hwnotify
));
772 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
778 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY
)This
->notify
);
779 *ppobj
= (LPVOID
)This
->notify
;
783 WARN("IID_IDirectSoundNotify\n");
787 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer
, riid
) ||
788 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8
, riid
) ) {
789 IDirectSoundCaptureBuffer8_AddRef(iface
);
794 FIXME("(%p,%s,%p) unsupported GUID\n", This
, debugstr_guid(riid
), ppobj
);
795 return E_NOINTERFACE
;
799 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
801 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
802 ULONG ref
= InterlockedIncrement(&(This
->ref
));
803 TRACE("(%p) ref was %d\n", This
, ref
- 1);
808 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
810 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
811 ULONG ref
= InterlockedDecrement(&(This
->ref
));
812 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
815 TRACE("deleting object\n");
816 if (This
->device
->state
== STATE_CAPTURING
)
817 This
->device
->state
= STATE_STOPPING
;
819 HeapFree(GetProcessHeap(),0, This
->pdscbd
);
821 if (This
->device
->hwi
) {
822 waveInReset(This
->device
->hwi
);
823 waveInClose(This
->device
->hwi
);
824 HeapFree(GetProcessHeap(),0, This
->device
->pwave
);
825 This
->device
->pwave
= 0;
826 This
->device
->hwi
= 0;
829 if (This
->device
->hwbuf
)
830 IDsCaptureDriverBuffer_Release(This
->device
->hwbuf
);
832 /* remove from DirectSoundCaptureDevice */
833 This
->device
->capture_buffer
= NULL
;
836 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
838 HeapFree(GetProcessHeap(), 0, This
->notifies
);
839 HeapFree( GetProcessHeap(), 0, This
);
840 TRACE("(%p) released\n", This
);
845 static HRESULT WINAPI
846 IDirectSoundCaptureBufferImpl_GetCaps(
847 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
848 LPDSCBCAPS lpDSCBCaps
)
850 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
851 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
853 if (lpDSCBCaps
== NULL
) {
854 WARN("invalid parameter: lpDSCBCaps == NULL\n");
855 return DSERR_INVALIDPARAM
;
858 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
859 WARN("invalid parameter: lpDSCBCaps->dwSize = %d\n", lpDSCBCaps
->dwSize
);
860 return DSERR_INVALIDPARAM
;
863 if (This
->device
== NULL
) {
864 WARN("invalid parameter: This->device == NULL\n");
865 return DSERR_INVALIDPARAM
;
868 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
869 lpDSCBCaps
->dwFlags
= This
->flags
;
870 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
871 lpDSCBCaps
->dwReserved
= 0;
873 TRACE("returning DS_OK\n");
877 static HRESULT WINAPI
878 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
879 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
880 LPDWORD lpdwCapturePosition
,
881 LPDWORD lpdwReadPosition
)
883 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
884 HRESULT hres
= DS_OK
;
885 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
887 if (This
->device
== NULL
) {
888 WARN("invalid parameter: This->device == NULL\n");
889 return DSERR_INVALIDPARAM
;
892 if (This
->device
->driver
) {
893 hres
= IDsCaptureDriverBuffer_GetPosition(This
->device
->hwbuf
, lpdwCapturePosition
, lpdwReadPosition
);
895 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
896 } else if (This
->device
->hwi
) {
897 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
898 if (lpdwCapturePosition
) {
900 mtime
.wType
= TIME_BYTES
;
901 waveInGetPosition(This
->device
->hwi
, &mtime
, sizeof(mtime
));
902 TRACE("mtime.u.cb=%d,This->device->buflen=%d\n", mtime
.u
.cb
,
903 This
->device
->buflen
);
904 mtime
.u
.cb
= mtime
.u
.cb
% This
->device
->buflen
;
905 *lpdwCapturePosition
= mtime
.u
.cb
;
908 EnterCriticalSection(&(This
->device
->lock
));
909 if (lpdwReadPosition
) {
910 if (This
->device
->state
== STATE_STARTING
) {
911 if (lpdwCapturePosition
)
912 This
->device
->read_position
= *lpdwCapturePosition
;
913 This
->device
->state
= STATE_CAPTURING
;
915 *lpdwReadPosition
= This
->device
->read_position
;
917 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
918 LeaveCriticalSection(&(This
->device
->lock
));
919 if (lpdwCapturePosition
) TRACE("*lpdwCapturePosition=%d\n",*lpdwCapturePosition
);
920 if (lpdwReadPosition
) TRACE("*lpdwReadPosition=%d\n",*lpdwReadPosition
);
923 hres
= DSERR_NODRIVER
;
926 TRACE("returning %08x\n", hres
);
930 static HRESULT WINAPI
931 IDirectSoundCaptureBufferImpl_GetFormat(
932 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
933 LPWAVEFORMATEX lpwfxFormat
,
934 DWORD dwSizeAllocated
,
935 LPDWORD lpdwSizeWritten
)
937 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
938 HRESULT hres
= DS_OK
;
939 TRACE( "(%p,%p,0x%08x,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
942 if (This
->device
== NULL
) {
943 WARN("invalid parameter: This->device == NULL\n");
944 return DSERR_INVALIDPARAM
;
947 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
))
948 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
950 if (lpwfxFormat
) { /* NULL is valid (just want size) */
951 CopyMemory(lpwfxFormat
, This
->device
->pwfx
, dwSizeAllocated
);
953 *lpdwSizeWritten
= dwSizeAllocated
;
956 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
958 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
959 hres
= DSERR_INVALIDPARAM
;
963 TRACE("returning %08x\n", hres
);
967 static HRESULT WINAPI
968 IDirectSoundCaptureBufferImpl_GetStatus(
969 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
972 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
973 TRACE( "(%p, %p), thread is %04x\n", This
, lpdwStatus
, GetCurrentThreadId() );
975 if (This
->device
== NULL
) {
976 WARN("invalid parameter: This->device == NULL\n");
977 return DSERR_INVALIDPARAM
;
980 if (lpdwStatus
== NULL
) {
981 WARN("invalid parameter: lpdwStatus == NULL\n");
982 return DSERR_INVALIDPARAM
;
986 EnterCriticalSection(&(This
->device
->lock
));
988 TRACE("old This->device->state=%s, old lpdwStatus=%08x\n",
989 captureStateString
[This
->device
->state
],*lpdwStatus
);
990 if ((This
->device
->state
== STATE_STARTING
) ||
991 (This
->device
->state
== STATE_CAPTURING
)) {
992 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
993 if (This
->flags
& DSCBSTART_LOOPING
)
994 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
996 TRACE("new This->device->state=%s, new lpdwStatus=%08x\n",
997 captureStateString
[This
->device
->state
],*lpdwStatus
);
998 LeaveCriticalSection(&(This
->device
->lock
));
1000 TRACE("status=%x\n", *lpdwStatus
);
1001 TRACE("returning DS_OK\n");
1005 static HRESULT WINAPI
1006 IDirectSoundCaptureBufferImpl_Initialize(
1007 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1008 LPDIRECTSOUNDCAPTURE lpDSC
,
1009 LPCDSCBUFFERDESC lpcDSCBDesc
)
1011 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1013 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
1018 static HRESULT WINAPI
1019 IDirectSoundCaptureBufferImpl_Lock(
1020 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1023 LPVOID
* lplpvAudioPtr1
,
1024 LPDWORD lpdwAudioBytes1
,
1025 LPVOID
* lplpvAudioPtr2
,
1026 LPDWORD lpdwAudioBytes2
,
1029 HRESULT hres
= DS_OK
;
1030 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1031 TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This
, dwReadCusor
,
1032 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
1033 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
1035 if (This
->device
== NULL
) {
1036 WARN("invalid parameter: This->device == NULL\n");
1037 return DSERR_INVALIDPARAM
;
1040 if (lplpvAudioPtr1
== NULL
) {
1041 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1042 return DSERR_INVALIDPARAM
;
1045 if (lpdwAudioBytes1
== NULL
) {
1046 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1047 return DSERR_INVALIDPARAM
;
1050 EnterCriticalSection(&(This
->device
->lock
));
1052 if (This
->device
->driver
) {
1053 hres
= IDsCaptureDriverBuffer_Lock(This
->device
->hwbuf
, lplpvAudioPtr1
,
1054 lpdwAudioBytes1
, lplpvAudioPtr2
,
1055 lpdwAudioBytes2
, dwReadCusor
,
1056 dwReadBytes
, dwFlags
);
1058 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1059 } else if (This
->device
->hwi
) {
1060 *lplpvAudioPtr1
= This
->device
->buffer
+ dwReadCusor
;
1061 if ( (dwReadCusor
+ dwReadBytes
) > This
->device
->buflen
) {
1062 *lpdwAudioBytes1
= This
->device
->buflen
- dwReadCusor
;
1064 *lplpvAudioPtr2
= This
->device
->buffer
;
1065 if (lpdwAudioBytes2
)
1066 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
1068 *lpdwAudioBytes1
= dwReadBytes
;
1070 *lplpvAudioPtr2
= 0;
1071 if (lpdwAudioBytes2
)
1072 *lpdwAudioBytes2
= 0;
1075 TRACE("invalid call\n");
1076 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
1079 LeaveCriticalSection(&(This
->device
->lock
));
1081 TRACE("returning %08x\n", hres
);
1085 static HRESULT WINAPI
1086 IDirectSoundCaptureBufferImpl_Start(
1087 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1090 HRESULT hres
= DS_OK
;
1091 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1092 TRACE( "(%p,0x%08x)\n", This
, dwFlags
);
1094 if (This
->device
== NULL
) {
1095 WARN("invalid parameter: This->device == NULL\n");
1096 return DSERR_INVALIDPARAM
;
1099 if ( (This
->device
->driver
== 0) && (This
->device
->hwi
== 0) ) {
1100 WARN("no driver\n");
1101 return DSERR_NODRIVER
;
1104 EnterCriticalSection(&(This
->device
->lock
));
1106 This
->flags
= dwFlags
;
1107 TRACE("old This->state=%s\n",captureStateString
[This
->device
->state
]);
1108 if (This
->device
->state
== STATE_STOPPED
)
1109 This
->device
->state
= STATE_STARTING
;
1110 else if (This
->device
->state
== STATE_STOPPING
)
1111 This
->device
->state
= STATE_CAPTURING
;
1112 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1114 LeaveCriticalSection(&(This
->device
->lock
));
1116 if (This
->device
->driver
) {
1117 hres
= IDsCaptureDriverBuffer_Start(This
->device
->hwbuf
, dwFlags
);
1119 WARN("IDsCaptureDriverBuffer_Start failed\n");
1120 } else if (This
->device
->hwi
) {
1121 DirectSoundCaptureDevice
*device
= This
->device
;
1123 if (device
->buffer
) {
1124 if (This
->nrofnotifies
) {
1127 device
->nrofpwaves
= This
->nrofnotifies
;
1128 TRACE("nrofnotifies=%d\n", This
->nrofnotifies
);
1130 /* prepare headers */
1132 device
->pwave
= HeapReAlloc(GetProcessHeap(),0,device
->pwave
,
1133 device
->nrofpwaves
*sizeof(WAVEHDR
));
1135 device
->pwave
= HeapAlloc(GetProcessHeap(),0,
1136 device
->nrofpwaves
*sizeof(WAVEHDR
));
1138 for (c
= 0; c
< device
->nrofpwaves
; c
++) {
1139 if (This
->notifies
[c
].dwOffset
== DSBPN_OFFSETSTOP
) {
1140 TRACE("got DSBPN_OFFSETSTOP\n");
1141 device
->nrofpwaves
= c
;
1145 device
->pwave
[0].lpData
= (LPSTR
)device
->buffer
;
1146 device
->pwave
[0].dwBufferLength
=
1147 This
->notifies
[0].dwOffset
+ 1;
1149 device
->pwave
[c
].lpData
= (LPSTR
)device
->buffer
+
1150 This
->notifies
[c
-1].dwOffset
+ 1;
1151 device
->pwave
[c
].dwBufferLength
=
1152 This
->notifies
[c
].dwOffset
-
1153 This
->notifies
[c
-1].dwOffset
;
1155 device
->pwave
[c
].dwBytesRecorded
= 0;
1156 device
->pwave
[c
].dwUser
= (DWORD
)device
;
1157 device
->pwave
[c
].dwFlags
= 0;
1158 device
->pwave
[c
].dwLoops
= 0;
1159 hres
= mmErr(waveInPrepareHeader(device
->hwi
,
1160 &(device
->pwave
[c
]),sizeof(WAVEHDR
)));
1161 if (hres
!= DS_OK
) {
1162 WARN("waveInPrepareHeader failed\n");
1164 waveInUnprepareHeader(device
->hwi
,
1165 &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1169 hres
= mmErr(waveInAddBuffer(device
->hwi
,
1170 &(device
->pwave
[c
]), sizeof(WAVEHDR
)));
1171 if (hres
!= DS_OK
) {
1172 WARN("waveInAddBuffer failed\n");
1174 waveInUnprepareHeader(device
->hwi
,
1175 &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1180 FillMemory(device
->buffer
, device
->buflen
,
1181 (device
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
1183 TRACE("no notifiers specified\n");
1184 /* no notifiers specified so just create a single default header */
1185 device
->nrofpwaves
= 1;
1187 device
->pwave
= HeapReAlloc(GetProcessHeap(),0,device
->pwave
,sizeof(WAVEHDR
));
1189 device
->pwave
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR
));
1191 device
->pwave
[0].lpData
= (LPSTR
)device
->buffer
;
1192 device
->pwave
[0].dwBufferLength
= device
->buflen
;
1193 device
->pwave
[0].dwBytesRecorded
= 0;
1194 device
->pwave
[0].dwUser
= (DWORD
)device
;
1195 device
->pwave
[0].dwFlags
= 0;
1196 device
->pwave
[0].dwLoops
= 0;
1198 hres
= mmErr(waveInPrepareHeader(device
->hwi
,
1199 &(device
->pwave
[0]),sizeof(WAVEHDR
)));
1200 if (hres
!= DS_OK
) {
1201 WARN("waveInPrepareHeader failed\n");
1202 waveInUnprepareHeader(device
->hwi
,
1203 &(device
->pwave
[0]),sizeof(WAVEHDR
));
1205 hres
= mmErr(waveInAddBuffer(device
->hwi
,
1206 &(device
->pwave
[0]), sizeof(WAVEHDR
)));
1207 if (hres
!= DS_OK
) {
1208 WARN("waveInAddBuffer failed\n");
1209 waveInUnprepareHeader(device
->hwi
,
1210 &(device
->pwave
[0]),sizeof(WAVEHDR
));
1216 device
->read_position
= 0;
1218 if (hres
== DS_OK
) {
1219 /* start filling the first buffer */
1220 hres
= mmErr(waveInStart(device
->hwi
));
1222 WARN("waveInStart failed\n");
1225 if (hres
!= DS_OK
) {
1226 WARN("calling waveInClose because of error\n");
1227 waveInClose(device
->hwi
);
1231 WARN("no driver\n");
1232 hres
= DSERR_NODRIVER
;
1235 TRACE("returning %08x\n", hres
);
1239 static HRESULT WINAPI
1240 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1242 HRESULT hres
= DS_OK
;
1243 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1244 TRACE( "(%p)\n", This
);
1246 if (This
->device
== NULL
) {
1247 WARN("invalid parameter: This->device == NULL\n");
1248 return DSERR_INVALIDPARAM
;
1251 EnterCriticalSection(&(This
->device
->lock
));
1253 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1254 if (This
->device
->state
== STATE_CAPTURING
)
1255 This
->device
->state
= STATE_STOPPING
;
1256 else if (This
->device
->state
== STATE_STARTING
)
1257 This
->device
->state
= STATE_STOPPED
;
1258 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1260 LeaveCriticalSection(&(This
->device
->lock
));
1262 if (This
->device
->driver
) {
1263 hres
= IDsCaptureDriverBuffer_Stop(This
->device
->hwbuf
);
1265 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1266 } else if (This
->device
->hwi
) {
1267 hres
= mmErr(waveInReset(This
->device
->hwi
));
1269 WARN("waveInReset() failed\n");
1271 WARN("no driver\n");
1272 hres
= DSERR_NODRIVER
;
1275 TRACE("returning %08x\n", hres
);
1279 static HRESULT WINAPI
1280 IDirectSoundCaptureBufferImpl_Unlock(
1281 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1282 LPVOID lpvAudioPtr1
,
1283 DWORD dwAudioBytes1
,
1284 LPVOID lpvAudioPtr2
,
1285 DWORD dwAudioBytes2
)
1287 HRESULT hres
= DS_OK
;
1288 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1289 TRACE( "(%p,%p,%08u,%p,%08u)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
1290 lpvAudioPtr2
, dwAudioBytes2
);
1292 if (lpvAudioPtr1
== NULL
) {
1293 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1294 return DSERR_INVALIDPARAM
;
1297 if (This
->device
->driver
) {
1298 hres
= IDsCaptureDriverBuffer_Unlock(This
->device
->hwbuf
, lpvAudioPtr1
,
1299 dwAudioBytes1
, lpvAudioPtr2
, dwAudioBytes2
);
1301 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1302 } else if (This
->device
->hwi
) {
1303 This
->device
->read_position
= (This
->device
->read_position
+
1304 (dwAudioBytes1
+ dwAudioBytes2
)) % This
->device
->buflen
;
1306 WARN("invalid call\n");
1307 hres
= DSERR_INVALIDCALL
;
1310 TRACE("returning %08x\n", hres
);
1314 static HRESULT WINAPI
1315 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1316 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1317 REFGUID rguidObject
,
1319 REFGUID rguidInterface
,
1322 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1324 FIXME( "(%p,%s,%u,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
1325 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
1330 static HRESULT WINAPI
1331 IDirectSoundCaptureBufferImpl_GetFXStatus(
1332 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1334 LPDWORD pdwFXStatus
)
1336 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1338 FIXME( "(%p,%u,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
1343 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
=
1345 /* IUnknown methods */
1346 IDirectSoundCaptureBufferImpl_QueryInterface
,
1347 IDirectSoundCaptureBufferImpl_AddRef
,
1348 IDirectSoundCaptureBufferImpl_Release
,
1350 /* IDirectSoundCaptureBuffer methods */
1351 IDirectSoundCaptureBufferImpl_GetCaps
,
1352 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
1353 IDirectSoundCaptureBufferImpl_GetFormat
,
1354 IDirectSoundCaptureBufferImpl_GetStatus
,
1355 IDirectSoundCaptureBufferImpl_Initialize
,
1356 IDirectSoundCaptureBufferImpl_Lock
,
1357 IDirectSoundCaptureBufferImpl_Start
,
1358 IDirectSoundCaptureBufferImpl_Stop
,
1359 IDirectSoundCaptureBufferImpl_Unlock
,
1361 /* IDirectSoundCaptureBuffer methods */
1362 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
1363 IDirectSoundCaptureBufferImpl_GetFXStatus
1366 HRESULT
IDirectSoundCaptureBufferImpl_Create(
1367 DirectSoundCaptureDevice
*device
,
1368 IDirectSoundCaptureBufferImpl
** ppobj
,
1369 LPCDSCBUFFERDESC lpcDSCBufferDesc
)
1371 LPWAVEFORMATEX wfex
;
1372 TRACE( "(%p,%p,%p)\n", device
, ppobj
, lpcDSCBufferDesc
);
1374 if (ppobj
== NULL
) {
1375 WARN("invalid parameter: ppobj == NULL\n");
1376 return DSERR_INVALIDPARAM
;
1380 WARN("not initialized\n");
1382 return DSERR_UNINITIALIZED
;
1385 if (lpcDSCBufferDesc
== NULL
) {
1386 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
1388 return DSERR_INVALIDPARAM
;
1391 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
1392 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
1393 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
1394 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) {
1395 WARN("invalid lpcDSCBufferDesc\n");
1397 return DSERR_INVALIDPARAM
;
1400 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
1403 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1404 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1405 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
1406 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
1407 wfex
->wBitsPerSample
, wfex
->cbSize
);
1409 if (wfex
->wFormatTag
== WAVE_FORMAT_PCM
) {
1410 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
));
1411 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
));
1412 device
->pwfx
->cbSize
= 0;
1414 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1415 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1418 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
1420 return DSERR_INVALIDPARAM
; /* FIXME: DSERR_BADFORMAT ? */
1423 *ppobj
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1424 sizeof(IDirectSoundCaptureBufferImpl
));
1426 if ( *ppobj
== NULL
) {
1427 WARN("out of memory\n");
1429 return DSERR_OUTOFMEMORY
;
1431 HRESULT err
= DS_OK
;
1434 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)*ppobj
;
1437 This
->device
= device
;
1438 This
->device
->capture_buffer
= This
;
1439 This
->notify
= NULL
;
1440 This
->nrofnotifies
= 0;
1441 This
->hwnotify
= NULL
;
1443 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1444 lpcDSCBufferDesc
->dwSize
);
1446 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
1448 WARN("no memory\n");
1449 This
->device
->capture_buffer
= 0;
1450 HeapFree( GetProcessHeap(), 0, This
);
1452 return DSERR_OUTOFMEMORY
;
1455 This
->lpVtbl
= &dscbvt
;
1457 if (device
->driver
) {
1458 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1459 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
1461 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
1462 /* allocate buffer from system memory */
1463 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1464 TRACE("desired buflen=%d, old buffer=%p\n", buflen
, device
->buffer
);
1466 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1468 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1470 if (newbuf
== NULL
) {
1471 WARN("failed to allocate capture buffer\n");
1472 err
= DSERR_OUTOFMEMORY
;
1473 /* but the old buffer might still exist and must be re-prepared */
1475 device
->buffer
= newbuf
;
1476 device
->buflen
= buflen
;
1479 /* let driver allocate memory */
1480 device
->buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1482 HeapFree( GetProcessHeap(), 0, device
->buffer
);
1483 device
->buffer
= NULL
;
1486 err
= IDsCaptureDriver_CreateCaptureBuffer(device
->driver
,
1487 device
->pwfx
,0,0,&(device
->buflen
),&(device
->buffer
),(LPVOID
*)&(device
->hwbuf
));
1489 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1490 This
->device
->capture_buffer
= 0;
1491 HeapFree( GetProcessHeap(), 0, This
);
1496 DWORD flags
= CALLBACK_FUNCTION
;
1497 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
1498 flags
|= WAVE_DIRECTSOUND
;
1499 err
= mmErr(waveInOpen(&(device
->hwi
),
1500 device
->drvdesc
.dnDevNode
, device
->pwfx
,
1501 (DWORD_PTR
)DSOUND_capture_callback
, (DWORD
)device
, flags
));
1503 WARN("waveInOpen failed\n");
1504 This
->device
->capture_buffer
= 0;
1505 HeapFree( GetProcessHeap(), 0, This
);
1510 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1511 TRACE("desired buflen=%d, old buffer=%p\n", buflen
, device
->buffer
);
1513 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1515 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1516 if (newbuf
== NULL
) {
1517 WARN("failed to allocate capture buffer\n");
1518 err
= DSERR_OUTOFMEMORY
;
1519 /* but the old buffer might still exist and must be re-prepared */
1521 device
->buffer
= newbuf
;
1522 device
->buflen
= buflen
;
1527 TRACE("returning DS_OK\n");
1531 /*******************************************************************************
1532 * DirectSoundCaptureDevice
1534 HRESULT
DirectSoundCaptureDevice_Initialize(
1535 DirectSoundCaptureDevice
** ppDevice
,
1538 HRESULT err
= DSERR_INVALIDPARAM
;
1540 BOOLEAN found
= FALSE
;
1542 DirectSoundCaptureDevice
*device
= *ppDevice
;
1543 TRACE("(%p, %s)\n", ppDevice
, debugstr_guid(lpcGUID
));
1545 /* Default device? */
1546 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
1547 lpcGUID
= &DSDEVID_DefaultCapture
;
1549 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1550 WARN("invalid parameter: lpcGUID\n");
1551 return DSERR_INVALIDPARAM
;
1554 widn
= waveInGetNumDevs();
1556 WARN("no audio devices found\n");
1557 return DSERR_NODRIVER
;
1560 /* enumerate WINMM audio devices and find the one we want */
1561 for (wid
=0; wid
<widn
; wid
++) {
1562 if (IsEqualGUID( &devGUID
, &DSOUND_capture_guids
[wid
]) ) {
1568 if (found
== FALSE
) {
1569 WARN("No device found matching given ID!\n");
1570 return DSERR_NODRIVER
;
1573 if (DSOUND_capture
[wid
]) {
1574 WARN("already in use\n");
1575 return DSERR_ALLOCATED
;
1578 err
= DirectSoundCaptureDevice_Create(&(device
));
1580 WARN("DirectSoundCaptureDevice_Create failed\n");
1585 device
->guid
= devGUID
;
1587 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDIFACE
,(DWORD_PTR
)&(device
->driver
),0));
1588 if ( (err
!= DS_OK
) && (err
!= DSERR_UNSUPPORTED
) ) {
1589 WARN("waveInMessage failed; err=%x\n",err
);
1594 /* Disable the direct sound driver to force emulation if requested. */
1595 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
1596 device
->driver
= NULL
;
1598 /* Get driver description */
1599 if (device
->driver
) {
1600 TRACE("using DirectSound driver\n");
1601 err
= IDsCaptureDriver_GetDriverDesc(device
->driver
, &(device
->drvdesc
));
1603 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
1607 TRACE("using WINMM\n");
1608 /* if no DirectSound interface available, use WINMM API instead */
1609 device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
|
1610 DSDDESC_DOMMSYSTEMSETFORMAT
;
1613 device
->drvdesc
.dnDevNode
= wid
;
1615 /* open the DirectSound driver if available */
1616 if (device
->driver
&& (err
== DS_OK
))
1617 err
= IDsCaptureDriver_Open(device
->driver
);
1622 /* the driver is now open, so it's now allowed to call GetCaps */
1623 if (device
->driver
) {
1624 device
->drvcaps
.dwSize
= sizeof(device
->drvcaps
);
1625 err
= IDsCaptureDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1627 WARN("IDsCaptureDriver_GetCaps failed\n");
1630 } else /*if (device->hwi)*/ {
1632 err
= mmErr(waveInGetDevCapsA((UINT
)device
->drvdesc
.dnDevNode
, &wic
, sizeof(wic
)));
1635 device
->drvcaps
.dwFlags
= 0;
1636 lstrcpynA(device
->drvdesc
.szDrvname
, wic
.szPname
,
1637 sizeof(device
->drvdesc
.szDrvname
));
1639 device
->drvcaps
.dwFlags
|= DSCCAPS_EMULDRIVER
;
1640 device
->drvcaps
.dwFormats
= wic
.dwFormats
;
1641 device
->drvcaps
.dwChannels
= wic
.wChannels
;
1649 static HRESULT
DirectSoundCaptureDevice_Create(
1650 DirectSoundCaptureDevice
** ppDevice
)
1652 DirectSoundCaptureDevice
* device
;
1653 TRACE("(%p)\n", ppDevice
);
1655 /* Allocate memory */
1656 device
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DirectSoundCaptureDevice
));
1658 if (device
== NULL
) {
1659 WARN("out of memory\n");
1660 return DSERR_OUTOFMEMORY
;
1664 device
->state
= STATE_STOPPED
;
1666 InitializeCriticalSection( &(device
->lock
) );
1667 device
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": DirectSoundCaptureDevice.lock");
1674 ULONG
DirectSoundCaptureDevice_AddRef(
1675 DirectSoundCaptureDevice
* device
)
1677 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1678 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1682 ULONG
DirectSoundCaptureDevice_Release(
1683 DirectSoundCaptureDevice
* device
)
1685 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1686 TRACE("(%p) ref was %d\n", device
, ref
+ 1);
1689 TRACE("deleting object\n");
1690 if (device
->capture_buffer
)
1691 IDirectSoundCaptureBufferImpl_Release(
1692 (LPDIRECTSOUNDCAPTUREBUFFER8
) device
->capture_buffer
);
1694 if (device
->driver
) {
1695 IDsCaptureDriver_Close(device
->driver
);
1696 IDsCaptureDriver_Release(device
->driver
);
1699 HeapFree(GetProcessHeap(), 0, device
->pwfx
);
1700 device
->lock
.DebugInfo
->Spare
[0] = 0;
1701 DeleteCriticalSection( &(device
->lock
) );
1702 DSOUND_capture
[device
->drvdesc
.dnDevNode
] = NULL
;
1703 HeapFree(GetProcessHeap(), 0, device
);
1704 TRACE("(%p) released\n", device
);