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
40 #include "wine/debug.h"
43 #include "dsound_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
47 DirectSoundCaptureDevice
* DSOUND_capture
[MAXWAVEDRIVERS
];
49 static const char * captureStateString
[] = {
56 static HRESULT
DSOUND_CaptureCreate(
57 LPDIRECTSOUNDCAPTURE
*ppDSC
,
60 LPDIRECTSOUNDCAPTURE pDSC
;
62 TRACE("(%p,%p)\n",ppDSC
,pUnkOuter
);
64 /* Get dsound configuration */
65 setup_dsound_options();
67 hr
= IDirectSoundCaptureImpl_Create(&pDSC
);
69 IDirectSoundCapture_AddRef(pDSC
);
72 WARN("IDirectSoundCaptureImpl_Create failed\n");
79 static HRESULT
DSOUND_CaptureCreate8(
80 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
83 LPDIRECTSOUNDCAPTURE8 pDSC8
;
85 TRACE("(%p,%p)\n",ppDSC8
,pUnkOuter
);
87 /* Get dsound configuration */
88 setup_dsound_options();
90 hr
= IDirectSoundCaptureImpl_Create(&pDSC8
);
92 IDirectSoundCapture_AddRef(pDSC8
);
95 WARN("IDirectSoundCaptureImpl_Create failed\n");
102 /***************************************************************************
103 * DirectSoundCaptureCreate [DSOUND.6]
105 * Create and initialize a DirectSoundCapture interface.
108 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
109 * lplpDSC [O] Address of a variable to receive the interface pointer.
110 * pUnkOuter [I] Must be NULL.
114 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
118 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
119 * or NULL for the default device or DSDEVID_DefaultCapture or
120 * DSDEVID_DefaultVoiceCapture.
122 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
124 HRESULT WINAPI
DirectSoundCaptureCreate(
126 LPDIRECTSOUNDCAPTURE
*ppDSC
,
130 LPDIRECTSOUNDCAPTURE pDSC
;
131 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC
, pUnkOuter
);
134 WARN("invalid parameter: ppDSC == NULL\n");
135 return DSERR_INVALIDPARAM
;
139 WARN("invalid parameter: pUnkOuter != NULL\n");
141 return DSERR_NOAGGREGATION
;
144 hr
= DSOUND_CaptureCreate(&pDSC
, (IUnknown
*)pUnkOuter
);
146 hr
= IDirectSoundCapture_Initialize(pDSC
, lpcGUID
);
148 IDirectSoundCapture_Release(pDSC
);
158 /***************************************************************************
159 * DirectSoundCaptureCreate8 [DSOUND.12]
161 * Create and initialize a DirectSoundCapture interface.
164 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
165 * lplpDSC [O] Address of a variable to receive the interface pointer.
166 * pUnkOuter [I] Must be NULL.
170 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
174 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
175 * or NULL for the default device or DSDEVID_DefaultCapture or
176 * DSDEVID_DefaultVoiceCapture.
178 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
180 HRESULT WINAPI
DirectSoundCaptureCreate8(
182 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
186 LPDIRECTSOUNDCAPTURE8 pDSC8
;
187 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC8
, pUnkOuter
);
189 if (ppDSC8
== NULL
) {
190 WARN("invalid parameter: ppDSC8 == NULL\n");
191 return DSERR_INVALIDPARAM
;
195 WARN("invalid parameter: pUnkOuter != NULL\n");
197 return DSERR_NOAGGREGATION
;
200 hr
= DSOUND_CaptureCreate8(&pDSC8
, (IUnknown
*)pUnkOuter
);
202 hr
= IDirectSoundCapture_Initialize(pDSC8
, lpcGUID
);
204 IDirectSoundCapture_Release(pDSC8
);
214 /***************************************************************************
215 * DirectSoundCaptureEnumerateA [DSOUND.7]
217 * Enumerate all DirectSound drivers installed in the system.
220 * lpDSEnumCallback [I] Address of callback function.
221 * lpContext [I] Address of user defined context passed to callback function.
225 * Failure: DSERR_INVALIDPARAM
228 DirectSoundCaptureEnumerateA(
229 LPDSENUMCALLBACKA lpDSEnumCallback
,
237 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
239 if (lpDSEnumCallback
== NULL
) {
240 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
241 return DSERR_INVALIDPARAM
;
244 devs
= waveInGetNumDevs();
246 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
247 for (wid
= 0; wid
< devs
; ++wid
) {
248 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
249 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
251 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
252 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
253 if (lpDSEnumCallback(NULL
, "Primary Sound Capture Driver", desc
.szDrvname
, lpContext
) == FALSE
)
261 for (wid
= 0; wid
< devs
; ++wid
) {
262 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
264 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
265 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
266 if (lpDSEnumCallback(&DSOUND_capture_guids
[wid
], desc
.szDesc
, desc
.szDrvname
, lpContext
) == FALSE
)
274 /***************************************************************************
275 * DirectSoundCaptureEnumerateW [DSOUND.8]
277 * Enumerate all DirectSound drivers installed in the system.
280 * lpDSEnumCallback [I] Address of callback function.
281 * lpContext [I] Address of user defined context passed to callback function.
285 * Failure: DSERR_INVALIDPARAM
288 DirectSoundCaptureEnumerateW(
289 LPDSENUMCALLBACKW lpDSEnumCallback
,
296 WCHAR wDesc
[MAXPNAMELEN
];
297 WCHAR wName
[MAXPNAMELEN
];
299 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
301 if (lpDSEnumCallback
== NULL
) {
302 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
303 return DSERR_INVALIDPARAM
;
306 devs
= waveInGetNumDevs();
308 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
309 for (wid
= 0; wid
< devs
; ++wid
) {
310 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
311 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
313 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
314 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
315 MultiByteToWideChar( CP_ACP
, 0, "Primary Sound Capture Driver", -1,
316 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
317 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
318 wName
, sizeof(wName
)/sizeof(WCHAR
) );
319 if (lpDSEnumCallback(NULL
, wDesc
, wName
, lpContext
) == FALSE
)
327 for (wid
= 0; wid
< devs
; ++wid
) {
328 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
330 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
331 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
332 MultiByteToWideChar( CP_ACP
, 0, desc
.szDesc
, -1,
333 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
334 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
335 wName
, sizeof(wName
)/sizeof(WCHAR
) );
336 if (lpDSEnumCallback((LPGUID
)&DSOUND_capture_guids
[wid
], wDesc
, wName
, lpContext
) == FALSE
)
345 DSOUND_capture_callback(
352 DirectSoundCaptureDevice
* This
= (DirectSoundCaptureDevice
*)dwUser
;
353 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi
,msg
,
354 msg
== MM_WIM_OPEN
? "MM_WIM_OPEN" : msg
== MM_WIM_CLOSE
? "MM_WIM_CLOSE" :
355 msg
== MM_WIM_DATA
? "MM_WIM_DATA" : "UNKNOWN",dwUser
,dw1
,dw2
,GetTickCount());
357 if (msg
== MM_WIM_DATA
) {
358 LPWAVEHDR pHdr
= (LPWAVEHDR
)dw1
;
359 EnterCriticalSection( &(This
->lock
) );
360 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
361 captureStateString
[This
->state
],This
->index
);
362 if (This
->state
!= STATE_STOPPED
) {
363 int index
= This
->index
;
364 if (This
->state
== STATE_STARTING
) {
365 This
->read_position
= pHdr
->dwBytesRecorded
;
366 This
->state
= STATE_CAPTURING
;
368 if (This
->capture_buffer
->nrofnotifies
)
369 SetEvent(This
->capture_buffer
->notifies
[This
->index
].hEventNotify
);
370 This
->index
= (This
->index
+ 1) % This
->nrofpwaves
;
371 if ( (This
->index
== 0) && !(This
->capture_buffer
->flags
& DSCBSTART_LOOPING
) ) {
372 TRACE("end of buffer\n");
373 This
->state
= STATE_STOPPED
;
375 if (This
->state
== STATE_CAPTURING
) {
376 waveInAddBuffer(hwi
, &(This
->pwave
[index
]), sizeof(WAVEHDR
));
377 } else if (This
->state
== STATE_STOPPING
) {
379 This
->state
= STATE_STOPPED
;
383 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
384 captureStateString
[This
->state
],This
->index
);
385 LeaveCriticalSection( &(This
->lock
) );
388 TRACE("completed\n");
391 /***************************************************************************
392 * IDirectSoundCaptureImpl
394 static HRESULT WINAPI
395 IDirectSoundCaptureImpl_QueryInterface(
396 LPDIRECTSOUNDCAPTURE iface
,
400 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
401 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
404 WARN("invalid parameter\n");
410 if (IsEqualIID(riid
, &IID_IUnknown
)) {
411 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
414 } else if (IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
415 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
420 WARN("unsupported riid: %s\n", debugstr_guid(riid
));
421 return E_NOINTERFACE
;
425 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface
)
427 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
428 ULONG ref
= InterlockedIncrement(&(This
->ref
));
429 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
434 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface
)
436 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
437 ULONG ref
= InterlockedDecrement(&(This
->ref
));
438 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
442 DirectSoundCaptureDevice_Release(This
->device
);
444 HeapFree( GetProcessHeap(), 0, This
);
445 TRACE("(%p) released\n", This
);
450 HRESULT WINAPI
IDirectSoundCaptureImpl_CreateCaptureBuffer(
451 LPDIRECTSOUNDCAPTURE iface
,
452 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
453 LPDIRECTSOUNDCAPTUREBUFFER
* lplpDSCaptureBuffer
,
457 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
459 TRACE( "(%p,%p,%p,%p)\n",iface
,lpcDSCBufferDesc
,lplpDSCaptureBuffer
,pUnk
);
461 if (lpcDSCBufferDesc
== NULL
) {
462 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
463 return DSERR_INVALIDPARAM
;
466 if (lplpDSCaptureBuffer
== NULL
) {
467 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
468 return DSERR_INVALIDPARAM
;
472 WARN("invalid parameter: pUnk != NULL\n");
473 return DSERR_INVALIDPARAM
;
476 /* FIXME: We can only have one buffer so what do we do here? */
477 if (This
->device
->capture_buffer
) {
478 WARN("lnvalid parameter: already has buffer\n");
479 return DSERR_INVALIDPARAM
; /* DSERR_GENERIC ? */
482 hr
= IDirectSoundCaptureBufferImpl_Create(This
->device
,
483 (IDirectSoundCaptureBufferImpl
**)lplpDSCaptureBuffer
, lpcDSCBufferDesc
);
486 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
491 HRESULT WINAPI
IDirectSoundCaptureImpl_GetCaps(
492 LPDIRECTSOUNDCAPTURE iface
,
493 LPDSCCAPS lpDSCCaps
)
495 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
496 TRACE("(%p,%p)\n",This
,lpDSCCaps
);
498 if (This
->device
== NULL
) {
499 WARN("not initialized\n");
500 return DSERR_UNINITIALIZED
;
503 if (lpDSCCaps
== NULL
) {
504 WARN("invalid parameter: lpDSCCaps== NULL\n");
505 return DSERR_INVALIDPARAM
;
508 if (lpDSCCaps
->dwSize
< sizeof(*lpDSCCaps
)) {
509 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
510 lpDSCCaps
->dwSize
, sizeof(*lpDSCCaps
));
511 return DSERR_INVALIDPARAM
;
514 lpDSCCaps
->dwFlags
= This
->device
->drvcaps
.dwFlags
;
515 lpDSCCaps
->dwFormats
= This
->device
->drvcaps
.dwFormats
;
516 lpDSCCaps
->dwChannels
= This
->device
->drvcaps
.dwChannels
;
518 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps
->dwFlags
,
519 lpDSCCaps
->dwFormats
, lpDSCCaps
->dwChannels
);
524 HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(
525 LPDIRECTSOUNDCAPTURE iface
,
528 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
529 TRACE("(%p,%s)\n", This
, debugstr_guid(lpcGUID
));
531 if (This
->device
!= NULL
) {
532 WARN("already initialized\n");
533 return DSERR_ALREADYINITIALIZED
;
536 return DirectSoundCaptureDevice_Initialize(&This
->device
, lpcGUID
);
539 static const IDirectSoundCaptureVtbl dscvt
=
541 /* IUnknown methods */
542 IDirectSoundCaptureImpl_QueryInterface
,
543 IDirectSoundCaptureImpl_AddRef
,
544 IDirectSoundCaptureImpl_Release
,
546 /* IDirectSoundCapture methods */
547 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
548 IDirectSoundCaptureImpl_GetCaps
,
549 IDirectSoundCaptureImpl_Initialize
552 HRESULT
IDirectSoundCaptureImpl_Create(
553 LPDIRECTSOUNDCAPTURE8
* ppDSC
)
555 IDirectSoundCaptureImpl
*pDSC
;
556 TRACE("(%p)\n", ppDSC
);
558 /* Allocate memory */
559 pDSC
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundCaptureImpl
));
561 WARN("out of memory\n");
563 return DSERR_OUTOFMEMORY
;
566 pDSC
->lpVtbl
= &dscvt
;
570 *ppDSC
= (LPDIRECTSOUNDCAPTURE8
)pDSC
;
575 /*******************************************************************************
576 * IDirectSoundCaptureNotify
578 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_QueryInterface(
579 LPDIRECTSOUNDNOTIFY iface
,
583 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
584 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
586 if (This
->dscb
== NULL
) {
587 WARN("invalid parameter\n");
591 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
, riid
, ppobj
);
594 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface
)
596 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
597 ULONG ref
= InterlockedIncrement(&(This
->ref
));
598 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
602 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface
)
604 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
605 ULONG ref
= InterlockedDecrement(&(This
->ref
));
606 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
609 if (This
->dscb
->hwnotify
)
610 IDsDriverNotify_Release(This
->dscb
->hwnotify
);
611 This
->dscb
->notify
=NULL
;
612 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
);
613 HeapFree(GetProcessHeap(),0,This
);
614 TRACE("(%p) released\n", This
);
619 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
620 LPDIRECTSOUNDNOTIFY iface
,
622 LPCDSBPOSITIONNOTIFY notify
)
624 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
625 TRACE("(%p,0x%08lx,%p)\n",This
,howmuch
,notify
);
627 if (howmuch
> 0 && notify
== NULL
) {
628 WARN("invalid parameter: notify == NULL\n");
629 return DSERR_INVALIDPARAM
;
632 if (TRACE_ON(dsound
)) {
634 for (i
=0;i
<howmuch
;i
++)
635 TRACE("notify at %ld to %p\n",
636 notify
[i
].dwOffset
,notify
[i
].hEventNotify
);
639 if (This
->dscb
->hwnotify
) {
641 hres
= IDsDriverNotify_SetNotificationPositions(This
->dscb
->hwnotify
, howmuch
, notify
);
643 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
645 } else if (howmuch
> 0) {
646 /* Make an internal copy of the caller-supplied array.
647 * Replace the existing copy if one is already present. */
648 if (This
->dscb
->notifies
)
649 This
->dscb
->notifies
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
650 This
->dscb
->notifies
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
652 This
->dscb
->notifies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
653 howmuch
* sizeof(DSBPOSITIONNOTIFY
));
655 if (This
->dscb
->notifies
== NULL
) {
656 WARN("out of memory\n");
657 return DSERR_OUTOFMEMORY
;
659 CopyMemory(This
->dscb
->notifies
, notify
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
660 This
->dscb
->nrofnotifies
= howmuch
;
662 HeapFree(GetProcessHeap(), 0, This
->dscb
->notifies
);
663 This
->dscb
->notifies
= NULL
;
664 This
->dscb
->nrofnotifies
= 0;
670 static const IDirectSoundNotifyVtbl dscnvt
=
672 IDirectSoundCaptureNotifyImpl_QueryInterface
,
673 IDirectSoundCaptureNotifyImpl_AddRef
,
674 IDirectSoundCaptureNotifyImpl_Release
,
675 IDirectSoundCaptureNotifyImpl_SetNotificationPositions
,
678 HRESULT
IDirectSoundCaptureNotifyImpl_Create(
679 IDirectSoundCaptureBufferImpl
*dscb
,
680 IDirectSoundCaptureNotifyImpl
**pdscn
)
682 IDirectSoundCaptureNotifyImpl
* dscn
;
683 TRACE("(%p,%p)\n",dscb
,pdscn
);
685 dscn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(dscn
));
688 WARN("out of memory\n");
689 return DSERR_OUTOFMEMORY
;
693 dscn
->lpVtbl
= &dscnvt
;
696 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER
)dscb
);
702 /*******************************************************************************
703 * IDirectSoundCaptureBuffer
705 static HRESULT WINAPI
706 IDirectSoundCaptureBufferImpl_QueryInterface(
707 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
711 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
713 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
716 WARN("invalid parameter\n");
722 if ( IsEqualGUID( &IID_IDirectSoundNotify
, riid
) ) {
724 hres
= IDirectSoundCaptureNotifyImpl_Create(This
, &This
->notify
);
726 if (This
->device
->hwbuf
) {
727 hres
= IDsCaptureDriverBuffer_QueryInterface(This
->device
->hwbuf
,
728 &IID_IDsDriverNotify
, (LPVOID
*)&(This
->hwnotify
));
730 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
736 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY
)This
->notify
);
737 *ppobj
= (LPVOID
)This
->notify
;
741 WARN("IID_IDirectSoundNotify\n");
745 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer
, riid
) ||
746 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8
, riid
) ) {
747 IDirectSoundCaptureBuffer8_AddRef(iface
);
752 FIXME("(%p,%s,%p) unsupported GUID\n", This
, debugstr_guid(riid
), ppobj
);
753 return E_NOINTERFACE
;
757 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
759 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
760 ULONG ref
= InterlockedIncrement(&(This
->ref
));
761 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
766 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
768 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
769 ULONG ref
= InterlockedDecrement(&(This
->ref
));
770 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
773 TRACE("deleting object\n");
774 if (This
->device
->state
== STATE_CAPTURING
)
775 This
->device
->state
= STATE_STOPPING
;
777 HeapFree(GetProcessHeap(),0, This
->pdscbd
);
779 if (This
->device
->hwi
) {
780 waveInReset(This
->device
->hwi
);
781 waveInClose(This
->device
->hwi
);
782 HeapFree(GetProcessHeap(),0, This
->device
->pwave
);
783 This
->device
->pwave
= 0;
784 This
->device
->hwi
= 0;
787 if (This
->device
->hwbuf
)
788 IDsCaptureDriverBuffer_Release(This
->device
->hwbuf
);
790 /* remove from DirectSoundCaptureDevice */
791 This
->device
->capture_buffer
= NULL
;
794 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
796 HeapFree(GetProcessHeap(), 0, This
->notifies
);
797 HeapFree( GetProcessHeap(), 0, This
);
798 TRACE("(%p) released\n", This
);
803 static HRESULT WINAPI
804 IDirectSoundCaptureBufferImpl_GetCaps(
805 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
806 LPDSCBCAPS lpDSCBCaps
)
808 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
809 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
811 if (lpDSCBCaps
== NULL
) {
812 WARN("invalid parameter: lpDSCBCaps == NULL\n");
813 return DSERR_INVALIDPARAM
;
816 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
817 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
818 lpDSCBCaps
->dwSize
, sizeof(DSCBCAPS
));
819 return DSERR_INVALIDPARAM
;
822 if (This
->device
== NULL
) {
823 WARN("invalid parameter: This->device == NULL\n");
824 return DSERR_INVALIDPARAM
;
827 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
828 lpDSCBCaps
->dwFlags
= This
->flags
;
829 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
830 lpDSCBCaps
->dwReserved
= 0;
832 TRACE("returning DS_OK\n");
836 static HRESULT WINAPI
837 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
838 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
839 LPDWORD lpdwCapturePosition
,
840 LPDWORD lpdwReadPosition
)
842 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
843 HRESULT hres
= DS_OK
;
844 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
846 if (This
->device
== NULL
) {
847 WARN("invalid parameter: This->device == NULL\n");
848 return DSERR_INVALIDPARAM
;
851 if (This
->device
->driver
) {
852 hres
= IDsCaptureDriverBuffer_GetPosition(This
->device
->hwbuf
, lpdwCapturePosition
, lpdwReadPosition
);
854 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
855 } else if (This
->device
->hwi
) {
856 EnterCriticalSection(&(This
->device
->lock
));
857 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
858 if (lpdwCapturePosition
) {
860 mtime
.wType
= TIME_BYTES
;
861 waveInGetPosition(This
->device
->hwi
, &mtime
, sizeof(mtime
));
862 TRACE("mtime.u.cb=%ld,This->device->buflen=%ld\n", mtime
.u
.cb
,
863 This
->device
->buflen
);
864 mtime
.u
.cb
= mtime
.u
.cb
% This
->device
->buflen
;
865 *lpdwCapturePosition
= mtime
.u
.cb
;
868 if (lpdwReadPosition
) {
869 if (This
->device
->state
== STATE_STARTING
) {
870 if (lpdwCapturePosition
)
871 This
->device
->read_position
= *lpdwCapturePosition
;
872 This
->device
->state
= STATE_CAPTURING
;
874 *lpdwReadPosition
= This
->device
->read_position
;
876 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
877 LeaveCriticalSection(&(This
->device
->lock
));
878 if (lpdwCapturePosition
) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition
);
879 if (lpdwReadPosition
) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition
);
882 hres
= DSERR_NODRIVER
;
885 TRACE("returning %08lx\n", hres
);
889 static HRESULT WINAPI
890 IDirectSoundCaptureBufferImpl_GetFormat(
891 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
892 LPWAVEFORMATEX lpwfxFormat
,
893 DWORD dwSizeAllocated
,
894 LPDWORD lpdwSizeWritten
)
896 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
897 HRESULT hres
= DS_OK
;
898 TRACE( "(%p,%p,0x%08lx,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
901 if (This
->device
== NULL
) {
902 WARN("invalid parameter: This->device == NULL\n");
903 return DSERR_INVALIDPARAM
;
906 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
))
907 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
909 if (lpwfxFormat
) { /* NULL is valid (just want size) */
910 CopyMemory(lpwfxFormat
, This
->device
->pwfx
, dwSizeAllocated
);
912 *lpdwSizeWritten
= dwSizeAllocated
;
915 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
917 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
918 hres
= DSERR_INVALIDPARAM
;
922 TRACE("returning %08lx\n", hres
);
926 static HRESULT WINAPI
927 IDirectSoundCaptureBufferImpl_GetStatus(
928 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
931 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
932 TRACE( "(%p, %p), thread is %04lx\n", This
, lpdwStatus
, GetCurrentThreadId() );
934 if (This
->device
== NULL
) {
935 WARN("invalid parameter: This->device == NULL\n");
936 return DSERR_INVALIDPARAM
;
939 if (lpdwStatus
== NULL
) {
940 WARN("invalid parameter: lpdwStatus == NULL\n");
941 return DSERR_INVALIDPARAM
;
945 EnterCriticalSection(&(This
->device
->lock
));
947 TRACE("old This->device->state=%s, old lpdwStatus=%08lx\n",
948 captureStateString
[This
->device
->state
],*lpdwStatus
);
949 if ((This
->device
->state
== STATE_STARTING
) ||
950 (This
->device
->state
== STATE_CAPTURING
)) {
951 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
952 if (This
->flags
& DSCBSTART_LOOPING
)
953 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
955 TRACE("new This->device->state=%s, new lpdwStatus=%08lx\n",
956 captureStateString
[This
->device
->state
],*lpdwStatus
);
957 LeaveCriticalSection(&(This
->device
->lock
));
959 TRACE("status=%lx\n", *lpdwStatus
);
960 TRACE("returning DS_OK\n");
964 static HRESULT WINAPI
965 IDirectSoundCaptureBufferImpl_Initialize(
966 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
967 LPDIRECTSOUNDCAPTURE lpDSC
,
968 LPCDSCBUFFERDESC lpcDSCBDesc
)
970 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
972 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
977 static HRESULT WINAPI
978 IDirectSoundCaptureBufferImpl_Lock(
979 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
982 LPVOID
* lplpvAudioPtr1
,
983 LPDWORD lpdwAudioBytes1
,
984 LPVOID
* lplpvAudioPtr2
,
985 LPDWORD lpdwAudioBytes2
,
988 HRESULT hres
= DS_OK
;
989 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
990 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This
, dwReadCusor
,
991 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
992 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
994 if (This
->device
== NULL
) {
995 WARN("invalid parameter: This->device == NULL\n");
996 return DSERR_INVALIDPARAM
;
999 if (lplpvAudioPtr1
== NULL
) {
1000 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1001 return DSERR_INVALIDPARAM
;
1004 if (lpdwAudioBytes1
== NULL
) {
1005 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1006 return DSERR_INVALIDPARAM
;
1009 EnterCriticalSection(&(This
->device
->lock
));
1011 if (This
->device
->driver
) {
1012 hres
= IDsCaptureDriverBuffer_Lock(This
->device
->hwbuf
, lplpvAudioPtr1
,
1013 lpdwAudioBytes1
, lplpvAudioPtr2
,
1014 lpdwAudioBytes2
, dwReadCusor
,
1015 dwReadBytes
, dwFlags
);
1017 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1018 } else if (This
->device
->hwi
) {
1019 *lplpvAudioPtr1
= This
->device
->buffer
+ dwReadCusor
;
1020 if ( (dwReadCusor
+ dwReadBytes
) > This
->device
->buflen
) {
1021 *lpdwAudioBytes1
= This
->device
->buflen
- dwReadCusor
;
1023 *lplpvAudioPtr2
= This
->device
->buffer
;
1024 if (lpdwAudioBytes2
)
1025 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
1027 *lpdwAudioBytes1
= dwReadBytes
;
1029 *lplpvAudioPtr2
= 0;
1030 if (lpdwAudioBytes2
)
1031 *lpdwAudioBytes2
= 0;
1034 TRACE("invalid call\n");
1035 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
1038 LeaveCriticalSection(&(This
->device
->lock
));
1040 TRACE("returning %08lx\n", hres
);
1044 static HRESULT WINAPI
1045 IDirectSoundCaptureBufferImpl_Start(
1046 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1049 HRESULT hres
= DS_OK
;
1050 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1051 TRACE( "(%p,0x%08lx)\n", This
, dwFlags
);
1053 if (This
->device
== NULL
) {
1054 WARN("invalid parameter: This->device == NULL\n");
1055 return DSERR_INVALIDPARAM
;
1058 if ( (This
->device
->driver
== 0) && (This
->device
->hwi
== 0) ) {
1059 WARN("no driver\n");
1060 return DSERR_NODRIVER
;
1063 EnterCriticalSection(&(This
->device
->lock
));
1065 This
->flags
= dwFlags
;
1066 TRACE("old This->state=%s\n",captureStateString
[This
->device
->state
]);
1067 if (This
->device
->state
== STATE_STOPPED
)
1068 This
->device
->state
= STATE_STARTING
;
1069 else if (This
->device
->state
== STATE_STOPPING
)
1070 This
->device
->state
= STATE_CAPTURING
;
1071 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1073 LeaveCriticalSection(&(This
->device
->lock
));
1075 if (This
->device
->driver
) {
1076 hres
= IDsCaptureDriverBuffer_Start(This
->device
->hwbuf
, dwFlags
);
1078 WARN("IDsCaptureDriverBuffer_Start failed\n");
1079 } else if (This
->device
->hwi
) {
1080 DirectSoundCaptureDevice
*device
= This
->device
;
1082 if (device
->buffer
) {
1083 if (This
->nrofnotifies
) {
1086 device
->nrofpwaves
= This
->nrofnotifies
;
1087 TRACE("nrofnotifies=%d\n", This
->nrofnotifies
);
1089 /* prepare headers */
1091 device
->pwave
= HeapReAlloc(GetProcessHeap(),0,device
->pwave
,
1092 device
->nrofpwaves
*sizeof(WAVEHDR
));
1094 device
->pwave
= HeapAlloc(GetProcessHeap(),0,
1095 device
->nrofpwaves
*sizeof(WAVEHDR
));
1097 for (c
= 0; c
< device
->nrofpwaves
; c
++) {
1098 if (This
->notifies
[c
].dwOffset
== DSBPN_OFFSETSTOP
) {
1099 TRACE("got DSBPN_OFFSETSTOP\n");
1100 device
->nrofpwaves
= c
;
1104 device
->pwave
[0].lpData
= (LPSTR
)device
->buffer
;
1105 device
->pwave
[0].dwBufferLength
=
1106 This
->notifies
[0].dwOffset
+ 1;
1108 device
->pwave
[c
].lpData
= (LPSTR
)device
->buffer
+
1109 This
->notifies
[c
-1].dwOffset
+ 1;
1110 device
->pwave
[c
].dwBufferLength
=
1111 This
->notifies
[c
].dwOffset
-
1112 This
->notifies
[c
-1].dwOffset
;
1114 device
->pwave
[c
].dwBytesRecorded
= 0;
1115 device
->pwave
[c
].dwUser
= (DWORD
)device
;
1116 device
->pwave
[c
].dwFlags
= 0;
1117 device
->pwave
[c
].dwLoops
= 0;
1118 hres
= mmErr(waveInPrepareHeader(device
->hwi
,
1119 &(device
->pwave
[c
]),sizeof(WAVEHDR
)));
1120 if (hres
!= DS_OK
) {
1121 WARN("waveInPrepareHeader failed\n");
1123 waveInUnprepareHeader(device
->hwi
,
1124 &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1128 hres
= mmErr(waveInAddBuffer(device
->hwi
,
1129 &(device
->pwave
[c
]), sizeof(WAVEHDR
)));
1130 if (hres
!= DS_OK
) {
1131 WARN("waveInAddBuffer failed\n");
1133 waveInUnprepareHeader(device
->hwi
,
1134 &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1139 FillMemory(device
->buffer
, device
->buflen
,
1140 (device
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
1142 TRACE("no notifiers specified\n");
1143 /* no notifiers specified so just create a single default header */
1144 device
->nrofpwaves
= 1;
1146 device
->pwave
= HeapReAlloc(GetProcessHeap(),0,device
->pwave
,sizeof(WAVEHDR
));
1148 device
->pwave
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR
));
1150 device
->pwave
[0].lpData
= (LPSTR
)device
->buffer
;
1151 device
->pwave
[0].dwBufferLength
= device
->buflen
;
1152 device
->pwave
[0].dwBytesRecorded
= 0;
1153 device
->pwave
[0].dwUser
= (DWORD
)device
;
1154 device
->pwave
[0].dwFlags
= 0;
1155 device
->pwave
[0].dwLoops
= 0;
1157 hres
= mmErr(waveInPrepareHeader(device
->hwi
,
1158 &(device
->pwave
[0]),sizeof(WAVEHDR
)));
1159 if (hres
!= DS_OK
) {
1160 WARN("waveInPrepareHeader failed\n");
1161 waveInUnprepareHeader(device
->hwi
,
1162 &(device
->pwave
[0]),sizeof(WAVEHDR
));
1164 hres
= mmErr(waveInAddBuffer(device
->hwi
,
1165 &(device
->pwave
[0]), sizeof(WAVEHDR
)));
1166 if (hres
!= DS_OK
) {
1167 WARN("waveInAddBuffer failed\n");
1168 waveInUnprepareHeader(device
->hwi
,
1169 &(device
->pwave
[0]),sizeof(WAVEHDR
));
1175 device
->read_position
= 0;
1177 if (hres
== DS_OK
) {
1178 /* start filling the first buffer */
1179 hres
= mmErr(waveInStart(device
->hwi
));
1181 WARN("waveInStart failed\n");
1184 if (hres
!= DS_OK
) {
1185 WARN("calling waveInClose because of error\n");
1186 waveInClose(device
->hwi
);
1190 WARN("no driver\n");
1191 hres
= DSERR_NODRIVER
;
1194 TRACE("returning %08lx\n", hres
);
1198 static HRESULT WINAPI
1199 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1201 HRESULT hres
= DS_OK
;
1202 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1203 TRACE( "(%p)\n", This
);
1205 if (This
->device
== NULL
) {
1206 WARN("invalid parameter: This->device == NULL\n");
1207 return DSERR_INVALIDPARAM
;
1210 EnterCriticalSection(&(This
->device
->lock
));
1212 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1213 if (This
->device
->state
== STATE_CAPTURING
)
1214 This
->device
->state
= STATE_STOPPING
;
1215 else if (This
->device
->state
== STATE_STARTING
)
1216 This
->device
->state
= STATE_STOPPED
;
1217 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1219 LeaveCriticalSection(&(This
->device
->lock
));
1221 if (This
->device
->driver
) {
1222 hres
= IDsCaptureDriverBuffer_Stop(This
->device
->hwbuf
);
1224 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1225 } else if (This
->device
->hwi
) {
1226 hres
= mmErr(waveInReset(This
->device
->hwi
));
1228 WARN("waveInReset() failed\n");
1230 WARN("no driver\n");
1231 hres
= DSERR_NODRIVER
;
1234 TRACE("returning %08lx\n", hres
);
1238 static HRESULT WINAPI
1239 IDirectSoundCaptureBufferImpl_Unlock(
1240 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1241 LPVOID lpvAudioPtr1
,
1242 DWORD dwAudioBytes1
,
1243 LPVOID lpvAudioPtr2
,
1244 DWORD dwAudioBytes2
)
1246 HRESULT hres
= DS_OK
;
1247 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1248 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
1249 lpvAudioPtr2
, dwAudioBytes2
);
1251 if (lpvAudioPtr1
== NULL
) {
1252 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1253 return DSERR_INVALIDPARAM
;
1256 if (This
->device
->driver
) {
1257 hres
= IDsCaptureDriverBuffer_Unlock(This
->device
->hwbuf
, lpvAudioPtr1
,
1258 dwAudioBytes1
, lpvAudioPtr2
, dwAudioBytes2
);
1260 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1261 } else if (This
->device
->hwi
) {
1262 This
->device
->read_position
= (This
->device
->read_position
+
1263 (dwAudioBytes1
+ dwAudioBytes2
)) % This
->device
->buflen
;
1265 WARN("invalid call\n");
1266 hres
= DSERR_INVALIDCALL
;
1269 TRACE("returning %08lx\n", hres
);
1273 static HRESULT WINAPI
1274 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1275 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1276 REFGUID rguidObject
,
1278 REFGUID rguidInterface
,
1281 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1283 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
1284 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
1289 static HRESULT WINAPI
1290 IDirectSoundCaptureBufferImpl_GetFXStatus(
1291 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1293 LPDWORD pdwFXStatus
)
1295 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1297 FIXME( "(%p,%lu,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
1302 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
=
1304 /* IUnknown methods */
1305 IDirectSoundCaptureBufferImpl_QueryInterface
,
1306 IDirectSoundCaptureBufferImpl_AddRef
,
1307 IDirectSoundCaptureBufferImpl_Release
,
1309 /* IDirectSoundCaptureBuffer methods */
1310 IDirectSoundCaptureBufferImpl_GetCaps
,
1311 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
1312 IDirectSoundCaptureBufferImpl_GetFormat
,
1313 IDirectSoundCaptureBufferImpl_GetStatus
,
1314 IDirectSoundCaptureBufferImpl_Initialize
,
1315 IDirectSoundCaptureBufferImpl_Lock
,
1316 IDirectSoundCaptureBufferImpl_Start
,
1317 IDirectSoundCaptureBufferImpl_Stop
,
1318 IDirectSoundCaptureBufferImpl_Unlock
,
1320 /* IDirectSoundCaptureBuffer methods */
1321 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
1322 IDirectSoundCaptureBufferImpl_GetFXStatus
1325 HRESULT
IDirectSoundCaptureBufferImpl_Create(
1326 DirectSoundCaptureDevice
*device
,
1327 IDirectSoundCaptureBufferImpl
** ppobj
,
1328 LPCDSCBUFFERDESC lpcDSCBufferDesc
)
1330 LPWAVEFORMATEX wfex
;
1331 TRACE( "(%p,%p,%p)\n", device
, ppobj
, lpcDSCBufferDesc
);
1333 if (ppobj
== NULL
) {
1334 WARN("invalid parameter: ppobj == NULL\n");
1335 return DSERR_INVALIDPARAM
;
1339 WARN("not initialized\n");
1341 return DSERR_UNINITIALIZED
;
1344 if (lpcDSCBufferDesc
== NULL
) {
1345 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
1347 return DSERR_INVALIDPARAM
;
1350 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
1351 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
1352 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
1353 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) {
1354 WARN("invalid lpcDSCBufferDesc\n");
1356 return DSERR_INVALIDPARAM
;
1359 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
1362 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
1363 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1364 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
1365 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
1366 wfex
->wBitsPerSample
, wfex
->cbSize
);
1368 if (wfex
->wFormatTag
== WAVE_FORMAT_PCM
) {
1369 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
));
1370 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
));
1371 device
->pwfx
->cbSize
= 0;
1373 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1374 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1377 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
1379 return DSERR_INVALIDPARAM
; /* FIXME: DSERR_BADFORMAT ? */
1382 *ppobj
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1383 sizeof(IDirectSoundCaptureBufferImpl
));
1385 if ( *ppobj
== NULL
) {
1386 WARN("out of memory\n");
1388 return DSERR_OUTOFMEMORY
;
1390 HRESULT err
= DS_OK
;
1393 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)*ppobj
;
1396 This
->device
= device
;
1397 This
->device
->capture_buffer
= This
;
1398 This
->notify
= NULL
;
1399 This
->nrofnotifies
= 0;
1400 This
->hwnotify
= NULL
;
1402 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1403 lpcDSCBufferDesc
->dwSize
);
1405 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
1407 WARN("no memory\n");
1408 This
->device
->capture_buffer
= 0;
1409 HeapFree( GetProcessHeap(), 0, This
);
1411 return DSERR_OUTOFMEMORY
;
1414 This
->lpVtbl
= &dscbvt
;
1416 if (device
->driver
) {
1417 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1418 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
1420 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
1421 /* allocate buffer from system memory */
1422 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1423 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, device
->buffer
);
1425 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1427 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1429 if (newbuf
== NULL
) {
1430 WARN("failed to allocate capture buffer\n");
1431 err
= DSERR_OUTOFMEMORY
;
1432 /* but the old buffer might still exist and must be re-prepared */
1434 device
->buffer
= newbuf
;
1435 device
->buflen
= buflen
;
1438 /* let driver allocate memory */
1439 device
->buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1441 HeapFree( GetProcessHeap(), 0, device
->buffer
);
1442 device
->buffer
= NULL
;
1445 err
= IDsCaptureDriver_CreateCaptureBuffer(device
->driver
,
1446 device
->pwfx
,0,0,&(device
->buflen
),&(device
->buffer
),(LPVOID
*)&(device
->hwbuf
));
1448 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1449 This
->device
->capture_buffer
= 0;
1450 HeapFree( GetProcessHeap(), 0, This
);
1455 DWORD flags
= CALLBACK_FUNCTION
;
1456 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
1457 flags
|= WAVE_DIRECTSOUND
;
1458 err
= mmErr(waveInOpen(&(device
->hwi
),
1459 device
->drvdesc
.dnDevNode
, device
->pwfx
,
1460 (DWORD_PTR
)DSOUND_capture_callback
, (DWORD
)device
, flags
));
1462 WARN("waveInOpen failed\n");
1463 This
->device
->capture_buffer
= 0;
1464 HeapFree( GetProcessHeap(), 0, This
);
1469 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1470 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, device
->buffer
);
1472 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1474 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1475 if (newbuf
== NULL
) {
1476 WARN("failed to allocate capture buffer\n");
1477 err
= DSERR_OUTOFMEMORY
;
1478 /* but the old buffer might still exist and must be re-prepared */
1480 device
->buffer
= newbuf
;
1481 device
->buflen
= buflen
;
1486 TRACE("returning DS_OK\n");
1490 /*******************************************************************************
1491 * DirectSoundCaptureDevice
1493 HRESULT
DirectSoundCaptureDevice_Initialize(
1494 DirectSoundCaptureDevice
** ppDevice
,
1497 HRESULT err
= DSERR_INVALIDPARAM
;
1499 BOOLEAN found
= FALSE
;
1501 DirectSoundCaptureDevice
*device
= *ppDevice
;
1502 TRACE("(%p, %s)\n", ppDevice
, debugstr_guid(lpcGUID
));
1504 /* Default device? */
1505 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
1506 lpcGUID
= &DSDEVID_DefaultCapture
;
1508 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1509 WARN("invalid parameter: lpcGUID\n");
1510 return DSERR_INVALIDPARAM
;
1513 widn
= waveInGetNumDevs();
1515 WARN("no audio devices found\n");
1516 return DSERR_NODRIVER
;
1519 /* enumerate WINMM audio devices and find the one we want */
1520 for (wid
=0; wid
<widn
; wid
++) {
1521 if (IsEqualGUID( &devGUID
, &DSOUND_capture_guids
[wid
]) ) {
1527 if (found
== FALSE
) {
1528 WARN("No device found matching given ID!\n");
1529 return DSERR_NODRIVER
;
1532 if (DSOUND_capture
[wid
]) {
1533 WARN("already in use\n");
1534 return DSERR_ALLOCATED
;
1537 err
= DirectSoundCaptureDevice_Create(&(device
));
1539 WARN("DirectSoundCaptureDevice_Create failed\n");
1544 device
->guid
= devGUID
;
1546 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDIFACE
,(DWORD_PTR
)&(device
->driver
),0));
1547 if ( (err
!= DS_OK
) && (err
!= DSERR_UNSUPPORTED
) ) {
1548 WARN("waveInMessage failed; err=%lx\n",err
);
1553 /* Disable the direct sound driver to force emulation if requested. */
1554 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
1555 device
->driver
= NULL
;
1557 /* Get driver description */
1558 if (device
->driver
) {
1559 TRACE("using DirectSound driver\n");
1560 err
= IDsCaptureDriver_GetDriverDesc(device
->driver
, &(device
->drvdesc
));
1562 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
1566 TRACE("using WINMM\n");
1567 /* if no DirectSound interface available, use WINMM API instead */
1568 device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
|
1569 DSDDESC_DOMMSYSTEMSETFORMAT
;
1572 device
->drvdesc
.dnDevNode
= wid
;
1574 /* open the DirectSound driver if available */
1575 if (device
->driver
&& (err
== DS_OK
))
1576 err
= IDsCaptureDriver_Open(device
->driver
);
1581 /* the driver is now open, so it's now allowed to call GetCaps */
1582 if (device
->driver
) {
1583 device
->drvcaps
.dwSize
= sizeof(device
->drvcaps
);
1584 err
= IDsCaptureDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1586 WARN("IDsCaptureDriver_GetCaps failed\n");
1589 } else /*if (device->hwi)*/ {
1591 err
= mmErr(waveInGetDevCapsA((UINT
)device
->drvdesc
.dnDevNode
, &wic
, sizeof(wic
)));
1594 device
->drvcaps
.dwFlags
= 0;
1595 lstrcpynA(device
->drvdesc
.szDrvname
, wic
.szPname
,
1596 sizeof(device
->drvdesc
.szDrvname
));
1598 device
->drvcaps
.dwFlags
|= DSCCAPS_EMULDRIVER
;
1599 device
->drvcaps
.dwFormats
= wic
.dwFormats
;
1600 device
->drvcaps
.dwChannels
= wic
.wChannels
;
1608 HRESULT
DirectSoundCaptureDevice_Create(
1609 DirectSoundCaptureDevice
** ppDevice
)
1611 DirectSoundCaptureDevice
* device
;
1612 TRACE("(%p)\n", ppDevice
);
1614 /* Allocate memory */
1615 device
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DirectSoundCaptureDevice
));
1617 if (device
== NULL
) {
1618 WARN("out of memory\n");
1619 return DSERR_OUTOFMEMORY
;
1623 device
->state
= STATE_STOPPED
;
1625 InitializeCriticalSection( &(device
->lock
) );
1626 device
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)"DSCAPTURE_lock";
1633 ULONG
DirectSoundCaptureDevice_AddRef(
1634 DirectSoundCaptureDevice
* device
)
1636 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1637 TRACE("(%p) ref was %ld\n", device
, ref
- 1);
1641 ULONG
DirectSoundCaptureDevice_Release(
1642 DirectSoundCaptureDevice
* device
)
1644 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1645 TRACE("(%p) ref was %ld\n", device
, ref
+ 1);
1648 TRACE("deleting object\n");
1649 if (device
->capture_buffer
)
1650 IDirectSoundCaptureBufferImpl_Release(
1651 (LPDIRECTSOUNDCAPTUREBUFFER8
) device
->capture_buffer
);
1653 if (device
->driver
) {
1654 IDsCaptureDriver_Close(device
->driver
);
1655 IDsCaptureDriver_Release(device
->driver
);
1658 HeapFree(GetProcessHeap(), 0, device
->pwfx
);
1659 device
->lock
.DebugInfo
->Spare
[0] = 0;
1660 DeleteCriticalSection( &(device
->lock
) );
1661 DSOUND_capture
[device
->drvdesc
.dnDevNode
] = NULL
;
1662 HeapFree(GetProcessHeap(), 0, device
);
1663 TRACE("(%p) released\n", device
);
1668 /*******************************************************************************
1669 * DirectSoundCapture ClassFactory
1672 static HRESULT WINAPI
1673 DSCCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
)
1675 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1677 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
1678 return E_NOINTERFACE
;
1682 DSCCF_AddRef(LPCLASSFACTORY iface
)
1684 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1685 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1686 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1691 DSCCF_Release(LPCLASSFACTORY iface
)
1693 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1694 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1695 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1696 /* static class, won't be freed */
1700 static HRESULT WINAPI
1701 DSCCF_CreateInstance(
1702 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
)
1704 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1705 TRACE("(%p)->(%p,%s,%p)\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1708 WARN("aggregation not supported\n");
1709 return CLASS_E_NOAGGREGATION
;
1712 if (ppobj
== NULL
) {
1713 WARN("invalid parameter\n");
1714 return E_INVALIDARG
;
1719 if ( IsEqualGUID( &IID_IDirectSoundCapture
, riid
) )
1720 return DSOUND_CaptureCreate8((LPDIRECTSOUNDCAPTURE
*)ppobj
,pOuter
);
1722 WARN("(%p,%p,%s,%p) Interface not found!\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1723 return E_NOINTERFACE
;
1726 static HRESULT WINAPI
1727 DSCCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
)
1729 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1730 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
1734 static const IClassFactoryVtbl DSCCF_Vtbl
=
1736 DSCCF_QueryInterface
,
1739 DSCCF_CreateInstance
,
1743 IClassFactoryImpl DSOUND_CAPTURE_CF
= { &DSCCF_Vtbl
, 1 };