3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Implement FX support.
24 * Implement both IDirectSoundCaptureBuffer and IDirectSoundCaptureBuffer8
25 * Make DirectSoundCaptureCreate and DirectSoundCaptureCreate8 behave differently
30 #define NONAMELESSSTRUCT
31 #define NONAMELESSUNION
40 #include "wine/debug.h"
43 #include "dsound_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
47 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
);
462 WARN("invalid parameter: This == NULL\n");
463 return DSERR_INVALIDPARAM
;
466 if (lpcDSCBufferDesc
== NULL
) {
467 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
468 return DSERR_INVALIDPARAM
;
471 if (lplpDSCaptureBuffer
== NULL
) {
472 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
473 return DSERR_INVALIDPARAM
;
477 WARN("invalid parameter: pUnk != NULL\n");
478 return DSERR_INVALIDPARAM
;
481 /* FIXME: We can only have one buffer so what do we do here? */
482 if (This
->device
->capture_buffer
) {
483 WARN("lnvalid parameter: already has buffer\n");
484 return DSERR_INVALIDPARAM
; /* DSERR_GENERIC ? */
487 hr
= IDirectSoundCaptureBufferImpl_Create(This
->device
,
488 (IDirectSoundCaptureBufferImpl
**)lplpDSCaptureBuffer
, lpcDSCBufferDesc
);
491 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
496 HRESULT WINAPI
IDirectSoundCaptureImpl_GetCaps(
497 LPDIRECTSOUNDCAPTURE iface
,
498 LPDSCCAPS lpDSCCaps
)
500 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
501 TRACE("(%p,%p)\n",This
,lpDSCCaps
);
503 if (This
->device
== NULL
) {
504 WARN("not initialized\n");
505 return DSERR_UNINITIALIZED
;
508 if (lpDSCCaps
== NULL
) {
509 WARN("invalid parameter: lpDSCCaps== NULL\n");
510 return DSERR_INVALIDPARAM
;
513 if (lpDSCCaps
->dwSize
< sizeof(*lpDSCCaps
)) {
514 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
515 lpDSCCaps
->dwSize
, sizeof(*lpDSCCaps
));
516 return DSERR_INVALIDPARAM
;
519 lpDSCCaps
->dwFlags
= This
->device
->drvcaps
.dwFlags
;
520 lpDSCCaps
->dwFormats
= This
->device
->drvcaps
.dwFormats
;
521 lpDSCCaps
->dwChannels
= This
->device
->drvcaps
.dwChannels
;
523 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps
->dwFlags
,
524 lpDSCCaps
->dwFormats
, lpDSCCaps
->dwChannels
);
529 HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(
530 LPDIRECTSOUNDCAPTURE iface
,
533 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
534 TRACE("(%p,%s)\n", This
, debugstr_guid(lpcGUID
));
536 if (This
->device
!= NULL
) {
537 WARN("already initialized\n");
538 return DSERR_ALREADYINITIALIZED
;
541 return DirectSoundCaptureDevice_Initialize(&This
->device
, lpcGUID
);
544 static const IDirectSoundCaptureVtbl dscvt
=
546 /* IUnknown methods */
547 IDirectSoundCaptureImpl_QueryInterface
,
548 IDirectSoundCaptureImpl_AddRef
,
549 IDirectSoundCaptureImpl_Release
,
551 /* IDirectSoundCapture methods */
552 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
553 IDirectSoundCaptureImpl_GetCaps
,
554 IDirectSoundCaptureImpl_Initialize
557 HRESULT
IDirectSoundCaptureImpl_Create(
558 LPDIRECTSOUNDCAPTURE8
* ppDSC
)
560 IDirectSoundCaptureImpl
*pDSC
;
561 TRACE("(%p)\n", ppDSC
);
563 /* Allocate memory */
564 pDSC
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundCaptureImpl
));
566 WARN("out of memory\n");
568 return DSERR_OUTOFMEMORY
;
571 pDSC
->lpVtbl
= &dscvt
;
575 *ppDSC
= (LPDIRECTSOUNDCAPTURE8
)pDSC
;
580 /*******************************************************************************
581 * IDirectSoundCaptureNotify
583 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_QueryInterface(
584 LPDIRECTSOUNDNOTIFY iface
,
588 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
589 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
591 if (This
->dscb
== NULL
) {
592 WARN("invalid parameter\n");
596 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
, riid
, ppobj
);
599 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface
)
601 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
602 ULONG ref
= InterlockedIncrement(&(This
->ref
));
603 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
607 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface
)
609 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
610 ULONG ref
= InterlockedDecrement(&(This
->ref
));
611 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
614 if (This
->dscb
->hwnotify
)
615 IDsDriverNotify_Release(This
->dscb
->hwnotify
);
616 This
->dscb
->notify
=NULL
;
617 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
);
618 HeapFree(GetProcessHeap(),0,This
);
619 TRACE("(%p) released\n", This
);
624 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
625 LPDIRECTSOUNDNOTIFY iface
,
627 LPCDSBPOSITIONNOTIFY notify
)
629 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
630 TRACE("(%p,0x%08lx,%p)\n",This
,howmuch
,notify
);
632 if (howmuch
> 0 && notify
== NULL
) {
633 WARN("invalid parameter: notify == NULL\n");
634 return DSERR_INVALIDPARAM
;
637 if (TRACE_ON(dsound
)) {
639 for (i
=0;i
<howmuch
;i
++)
640 TRACE("notify at %ld to %p\n",
641 notify
[i
].dwOffset
,notify
[i
].hEventNotify
);
644 if (This
->dscb
->hwnotify
) {
646 hres
= IDsDriverNotify_SetNotificationPositions(This
->dscb
->hwnotify
, howmuch
, notify
);
648 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
650 } else if (howmuch
> 0) {
651 /* Make an internal copy of the caller-supplied array.
652 * Replace the existing copy if one is already present. */
653 if (This
->dscb
->notifies
)
654 This
->dscb
->notifies
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
655 This
->dscb
->notifies
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
657 This
->dscb
->notifies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
658 howmuch
* sizeof(DSBPOSITIONNOTIFY
));
660 if (This
->dscb
->notifies
== NULL
) {
661 WARN("out of memory\n");
662 return DSERR_OUTOFMEMORY
;
664 CopyMemory(This
->dscb
->notifies
, notify
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
665 This
->dscb
->nrofnotifies
= howmuch
;
667 HeapFree(GetProcessHeap(), 0, This
->dscb
->notifies
);
668 This
->dscb
->notifies
= NULL
;
669 This
->dscb
->nrofnotifies
= 0;
675 static const IDirectSoundNotifyVtbl dscnvt
=
677 IDirectSoundCaptureNotifyImpl_QueryInterface
,
678 IDirectSoundCaptureNotifyImpl_AddRef
,
679 IDirectSoundCaptureNotifyImpl_Release
,
680 IDirectSoundCaptureNotifyImpl_SetNotificationPositions
,
683 HRESULT
IDirectSoundCaptureNotifyImpl_Create(
684 IDirectSoundCaptureBufferImpl
*dscb
,
685 IDirectSoundCaptureNotifyImpl
**pdscn
)
687 IDirectSoundCaptureNotifyImpl
* dscn
;
688 TRACE("(%p,%p)\n",dscb
,pdscn
);
690 dscn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(dscn
));
693 WARN("out of memory\n");
694 return DSERR_OUTOFMEMORY
;
698 dscn
->lpVtbl
= &dscnvt
;
701 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER
)dscb
);
707 /*******************************************************************************
708 * IDirectSoundCaptureBuffer
710 static HRESULT WINAPI
711 IDirectSoundCaptureBufferImpl_QueryInterface(
712 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
716 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
718 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
721 WARN("invalid parameter\n");
727 if ( IsEqualGUID( &IID_IDirectSoundNotify
, riid
) ) {
729 hres
= IDirectSoundCaptureNotifyImpl_Create(This
, &This
->notify
);
731 if (This
->device
->hwbuf
) {
732 hres
= IDsCaptureDriverBuffer_QueryInterface(This
->device
->hwbuf
,
733 &IID_IDsDriverNotify
, (LPVOID
*)&(This
->hwnotify
));
735 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
741 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY
)This
->notify
);
742 *ppobj
= (LPVOID
)This
->notify
;
746 WARN("IID_IDirectSoundNotify\n");
750 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer
, riid
) ||
751 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8
, riid
) ) {
752 IDirectSoundCaptureBuffer8_AddRef(iface
);
757 FIXME("(%p,%s,%p) unsupported GUID\n", This
, debugstr_guid(riid
), ppobj
);
758 return E_NOINTERFACE
;
762 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
764 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
765 ULONG ref
= InterlockedIncrement(&(This
->ref
));
766 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
771 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
773 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
774 ULONG ref
= InterlockedDecrement(&(This
->ref
));
775 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
778 TRACE("deleting object\n");
779 if (This
->device
->state
== STATE_CAPTURING
)
780 This
->device
->state
= STATE_STOPPING
;
782 HeapFree(GetProcessHeap(),0, This
->pdscbd
);
784 if (This
->device
->hwi
) {
785 waveInReset(This
->device
->hwi
);
786 waveInClose(This
->device
->hwi
);
787 HeapFree(GetProcessHeap(),0, This
->device
->pwave
);
788 This
->device
->pwave
= 0;
789 This
->device
->hwi
= 0;
792 if (This
->device
->hwbuf
)
793 IDsCaptureDriverBuffer_Release(This
->device
->hwbuf
);
795 /* remove from DirectSoundCaptureDevice */
796 This
->device
->capture_buffer
= NULL
;
799 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
801 HeapFree(GetProcessHeap(), 0, This
->notifies
);
802 HeapFree( GetProcessHeap(), 0, This
);
803 TRACE("(%p) released\n", This
);
808 static HRESULT WINAPI
809 IDirectSoundCaptureBufferImpl_GetCaps(
810 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
811 LPDSCBCAPS lpDSCBCaps
)
813 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
814 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
817 WARN("invalid parameter: This == NULL\n");
818 return DSERR_INVALIDPARAM
;
821 if (lpDSCBCaps
== NULL
) {
822 WARN("invalid parameter: lpDSCBCaps == NULL\n");
823 return DSERR_INVALIDPARAM
;
826 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
827 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
828 lpDSCBCaps
->dwSize
, sizeof(DSCBCAPS
));
829 return DSERR_INVALIDPARAM
;
832 if (This
->device
== NULL
) {
833 WARN("invalid parameter: This->device == NULL\n");
834 return DSERR_INVALIDPARAM
;
837 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
838 lpDSCBCaps
->dwFlags
= This
->flags
;
839 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
840 lpDSCBCaps
->dwReserved
= 0;
842 TRACE("returning DS_OK\n");
846 static HRESULT WINAPI
847 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
848 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
849 LPDWORD lpdwCapturePosition
,
850 LPDWORD lpdwReadPosition
)
852 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
853 HRESULT hres
= DS_OK
;
854 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
857 WARN("invalid parameter: This == NULL\n");
858 return DSERR_INVALIDPARAM
;
861 if (This
->device
== NULL
) {
862 WARN("invalid parameter: This->device == NULL\n");
863 return DSERR_INVALIDPARAM
;
866 if (This
->device
->driver
) {
867 hres
= IDsCaptureDriverBuffer_GetPosition(This
->device
->hwbuf
, lpdwCapturePosition
, lpdwReadPosition
);
869 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
870 } else if (This
->device
->hwi
) {
871 EnterCriticalSection(&(This
->device
->lock
));
872 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
873 if (lpdwCapturePosition
) {
875 mtime
.wType
= TIME_BYTES
;
876 waveInGetPosition(This
->device
->hwi
, &mtime
, sizeof(mtime
));
877 TRACE("mtime.u.cb=%ld,This->device->buflen=%ld\n", mtime
.u
.cb
,
878 This
->device
->buflen
);
879 mtime
.u
.cb
= mtime
.u
.cb
% This
->device
->buflen
;
880 *lpdwCapturePosition
= mtime
.u
.cb
;
883 if (lpdwReadPosition
) {
884 if (This
->device
->state
== STATE_STARTING
) {
885 if (lpdwCapturePosition
)
886 This
->device
->read_position
= *lpdwCapturePosition
;
887 This
->device
->state
= STATE_CAPTURING
;
889 *lpdwReadPosition
= This
->device
->read_position
;
891 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
892 LeaveCriticalSection(&(This
->device
->lock
));
893 if (lpdwCapturePosition
) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition
);
894 if (lpdwReadPosition
) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition
);
897 hres
= DSERR_NODRIVER
;
900 TRACE("returning %08lx\n", hres
);
904 static HRESULT WINAPI
905 IDirectSoundCaptureBufferImpl_GetFormat(
906 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
907 LPWAVEFORMATEX lpwfxFormat
,
908 DWORD dwSizeAllocated
,
909 LPDWORD lpdwSizeWritten
)
911 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
912 HRESULT hres
= DS_OK
;
913 TRACE( "(%p,%p,0x%08lx,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
917 WARN("invalid parameter: This == NULL\n");
918 return DSERR_INVALIDPARAM
;
921 if (This
->device
== NULL
) {
922 WARN("invalid parameter: This->device == NULL\n");
923 return DSERR_INVALIDPARAM
;
926 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
))
927 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
929 if (lpwfxFormat
) { /* NULL is valid (just want size) */
930 CopyMemory(lpwfxFormat
, This
->device
->pwfx
, dwSizeAllocated
);
932 *lpdwSizeWritten
= dwSizeAllocated
;
935 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
937 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
938 hres
= DSERR_INVALIDPARAM
;
942 TRACE("returning %08lx\n", hres
);
946 static HRESULT WINAPI
947 IDirectSoundCaptureBufferImpl_GetStatus(
948 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
951 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
952 TRACE( "(%p, %p), thread is %04lx\n", This
, lpdwStatus
, GetCurrentThreadId() );
955 WARN("invalid parameter: This == NULL\n");
956 return DSERR_INVALIDPARAM
;
959 if (This
->device
== NULL
) {
960 WARN("invalid parameter: This->device == NULL\n");
961 return DSERR_INVALIDPARAM
;
964 if (lpdwStatus
== NULL
) {
965 WARN("invalid parameter: lpdwStatus == NULL\n");
966 return DSERR_INVALIDPARAM
;
970 EnterCriticalSection(&(This
->device
->lock
));
972 TRACE("old This->device->state=%s, old lpdwStatus=%08lx\n",
973 captureStateString
[This
->device
->state
],*lpdwStatus
);
974 if ((This
->device
->state
== STATE_STARTING
) ||
975 (This
->device
->state
== STATE_CAPTURING
)) {
976 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
977 if (This
->flags
& DSCBSTART_LOOPING
)
978 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
980 TRACE("new This->device->state=%s, new lpdwStatus=%08lx\n",
981 captureStateString
[This
->device
->state
],*lpdwStatus
);
982 LeaveCriticalSection(&(This
->device
->lock
));
984 TRACE("status=%lx\n", *lpdwStatus
);
985 TRACE("returning DS_OK\n");
989 static HRESULT WINAPI
990 IDirectSoundCaptureBufferImpl_Initialize(
991 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
992 LPDIRECTSOUNDCAPTURE lpDSC
,
993 LPCDSCBUFFERDESC lpcDSCBDesc
)
995 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
997 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
1002 static HRESULT WINAPI
1003 IDirectSoundCaptureBufferImpl_Lock(
1004 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1007 LPVOID
* lplpvAudioPtr1
,
1008 LPDWORD lpdwAudioBytes1
,
1009 LPVOID
* lplpvAudioPtr2
,
1010 LPDWORD lpdwAudioBytes2
,
1013 HRESULT hres
= DS_OK
;
1014 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1015 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This
, dwReadCusor
,
1016 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
1017 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
1020 WARN("invalid parameter: This == NULL\n");
1021 return DSERR_INVALIDPARAM
;
1024 if (This
->device
== NULL
) {
1025 WARN("invalid parameter: This->device == NULL\n");
1026 return DSERR_INVALIDPARAM
;
1029 if (lplpvAudioPtr1
== NULL
) {
1030 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1031 return DSERR_INVALIDPARAM
;
1034 if (lpdwAudioBytes1
== NULL
) {
1035 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1036 return DSERR_INVALIDPARAM
;
1039 EnterCriticalSection(&(This
->device
->lock
));
1041 if (This
->device
->driver
) {
1042 hres
= IDsCaptureDriverBuffer_Lock(This
->device
->hwbuf
, lplpvAudioPtr1
,
1043 lpdwAudioBytes1
, lplpvAudioPtr2
,
1044 lpdwAudioBytes2
, dwReadCusor
,
1045 dwReadBytes
, dwFlags
);
1047 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1048 } else if (This
->device
->hwi
) {
1049 *lplpvAudioPtr1
= This
->device
->buffer
+ dwReadCusor
;
1050 if ( (dwReadCusor
+ dwReadBytes
) > This
->device
->buflen
) {
1051 *lpdwAudioBytes1
= This
->device
->buflen
- dwReadCusor
;
1053 *lplpvAudioPtr2
= This
->device
->buffer
;
1054 if (lpdwAudioBytes2
)
1055 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
1057 *lpdwAudioBytes1
= dwReadBytes
;
1059 *lplpvAudioPtr2
= 0;
1060 if (lpdwAudioBytes2
)
1061 *lpdwAudioBytes2
= 0;
1064 TRACE("invalid call\n");
1065 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
1068 LeaveCriticalSection(&(This
->device
->lock
));
1070 TRACE("returning %08lx\n", hres
);
1074 static HRESULT WINAPI
1075 IDirectSoundCaptureBufferImpl_Start(
1076 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1079 HRESULT hres
= DS_OK
;
1080 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1081 TRACE( "(%p,0x%08lx)\n", This
, dwFlags
);
1084 WARN("invalid parameter: This == NULL\n");
1085 return DSERR_INVALIDPARAM
;
1088 if (This
->device
== NULL
) {
1089 WARN("invalid parameter: This->device == NULL\n");
1090 return DSERR_INVALIDPARAM
;
1093 if ( (This
->device
->driver
== 0) && (This
->device
->hwi
== 0) ) {
1094 WARN("no driver\n");
1095 return DSERR_NODRIVER
;
1098 EnterCriticalSection(&(This
->device
->lock
));
1100 This
->flags
= dwFlags
;
1101 TRACE("old This->state=%s\n",captureStateString
[This
->device
->state
]);
1102 if (This
->device
->state
== STATE_STOPPED
)
1103 This
->device
->state
= STATE_STARTING
;
1104 else if (This
->device
->state
== STATE_STOPPING
)
1105 This
->device
->state
= STATE_CAPTURING
;
1106 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1108 LeaveCriticalSection(&(This
->device
->lock
));
1110 if (This
->device
->driver
) {
1111 hres
= IDsCaptureDriverBuffer_Start(This
->device
->hwbuf
, dwFlags
);
1113 WARN("IDsCaptureDriverBuffer_Start failed\n");
1114 } else if (This
->device
->hwi
) {
1115 DirectSoundCaptureDevice
*device
= This
->device
;
1117 if (device
->buffer
) {
1118 if (This
->nrofnotifies
) {
1121 device
->nrofpwaves
= This
->nrofnotifies
;
1122 TRACE("nrofnotifies=%d\n", This
->nrofnotifies
);
1124 /* prepare headers */
1126 device
->pwave
= HeapReAlloc(GetProcessHeap(),0,device
->pwave
,
1127 device
->nrofpwaves
*sizeof(WAVEHDR
));
1129 device
->pwave
= HeapAlloc(GetProcessHeap(),0,
1130 device
->nrofpwaves
*sizeof(WAVEHDR
));
1132 for (c
= 0; c
< device
->nrofpwaves
; c
++) {
1133 if (This
->notifies
[c
].dwOffset
== DSBPN_OFFSETSTOP
) {
1134 TRACE("got DSBPN_OFFSETSTOP\n");
1135 device
->nrofpwaves
= c
;
1139 device
->pwave
[0].lpData
= (LPSTR
)device
->buffer
;
1140 device
->pwave
[0].dwBufferLength
=
1141 This
->notifies
[0].dwOffset
+ 1;
1143 device
->pwave
[c
].lpData
= (LPSTR
)device
->buffer
+
1144 This
->notifies
[c
-1].dwOffset
+ 1;
1145 device
->pwave
[c
].dwBufferLength
=
1146 This
->notifies
[c
].dwOffset
-
1147 This
->notifies
[c
-1].dwOffset
;
1149 device
->pwave
[c
].dwBytesRecorded
= 0;
1150 device
->pwave
[c
].dwUser
= (DWORD
)device
;
1151 device
->pwave
[c
].dwFlags
= 0;
1152 device
->pwave
[c
].dwLoops
= 0;
1153 hres
= mmErr(waveInPrepareHeader(device
->hwi
,
1154 &(device
->pwave
[c
]),sizeof(WAVEHDR
)));
1155 if (hres
!= DS_OK
) {
1156 WARN("waveInPrepareHeader failed\n");
1158 waveInUnprepareHeader(device
->hwi
,
1159 &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1163 hres
= mmErr(waveInAddBuffer(device
->hwi
,
1164 &(device
->pwave
[c
]), sizeof(WAVEHDR
)));
1165 if (hres
!= DS_OK
) {
1166 WARN("waveInAddBuffer failed\n");
1168 waveInUnprepareHeader(device
->hwi
,
1169 &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1174 FillMemory(device
->buffer
, device
->buflen
,
1175 (device
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
1177 TRACE("no notifiers specified\n");
1178 /* no notifiers specified so just create a single default header */
1179 device
->nrofpwaves
= 1;
1181 device
->pwave
= HeapReAlloc(GetProcessHeap(),0,device
->pwave
,sizeof(WAVEHDR
));
1183 device
->pwave
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR
));
1185 device
->pwave
[0].lpData
= (LPSTR
)device
->buffer
;
1186 device
->pwave
[0].dwBufferLength
= device
->buflen
;
1187 device
->pwave
[0].dwBytesRecorded
= 0;
1188 device
->pwave
[0].dwUser
= (DWORD
)device
;
1189 device
->pwave
[0].dwFlags
= 0;
1190 device
->pwave
[0].dwLoops
= 0;
1192 hres
= mmErr(waveInPrepareHeader(device
->hwi
,
1193 &(device
->pwave
[0]),sizeof(WAVEHDR
)));
1194 if (hres
!= DS_OK
) {
1195 WARN("waveInPrepareHeader failed\n");
1196 waveInUnprepareHeader(device
->hwi
,
1197 &(device
->pwave
[0]),sizeof(WAVEHDR
));
1199 hres
= mmErr(waveInAddBuffer(device
->hwi
,
1200 &(device
->pwave
[0]), sizeof(WAVEHDR
)));
1201 if (hres
!= DS_OK
) {
1202 WARN("waveInAddBuffer failed\n");
1203 waveInUnprepareHeader(device
->hwi
,
1204 &(device
->pwave
[0]),sizeof(WAVEHDR
));
1210 device
->read_position
= 0;
1212 if (hres
== DS_OK
) {
1213 /* start filling the first buffer */
1214 hres
= mmErr(waveInStart(device
->hwi
));
1216 WARN("waveInStart failed\n");
1219 if (hres
!= DS_OK
) {
1220 WARN("calling waveInClose because of error\n");
1221 waveInClose(device
->hwi
);
1225 WARN("no driver\n");
1226 hres
= DSERR_NODRIVER
;
1229 TRACE("returning %08lx\n", hres
);
1233 static HRESULT WINAPI
1234 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1236 HRESULT hres
= DS_OK
;
1237 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1238 TRACE( "(%p)\n", This
);
1241 WARN("invalid parameter: This == NULL\n");
1242 return DSERR_INVALIDPARAM
;
1245 if (This
->device
== NULL
) {
1246 WARN("invalid parameter: This->device == NULL\n");
1247 return DSERR_INVALIDPARAM
;
1250 EnterCriticalSection(&(This
->device
->lock
));
1252 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1253 if (This
->device
->state
== STATE_CAPTURING
)
1254 This
->device
->state
= STATE_STOPPING
;
1255 else if (This
->device
->state
== STATE_STARTING
)
1256 This
->device
->state
= STATE_STOPPED
;
1257 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1259 LeaveCriticalSection(&(This
->device
->lock
));
1261 if (This
->device
->driver
) {
1262 hres
= IDsCaptureDriverBuffer_Stop(This
->device
->hwbuf
);
1264 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1265 } else if (This
->device
->hwi
) {
1266 hres
= mmErr(waveInReset(This
->device
->hwi
));
1268 WARN("waveInReset() failed\n");
1270 WARN("no driver\n");
1271 hres
= DSERR_NODRIVER
;
1274 TRACE("returning %08lx\n", hres
);
1278 static HRESULT WINAPI
1279 IDirectSoundCaptureBufferImpl_Unlock(
1280 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1281 LPVOID lpvAudioPtr1
,
1282 DWORD dwAudioBytes1
,
1283 LPVOID lpvAudioPtr2
,
1284 DWORD dwAudioBytes2
)
1286 HRESULT hres
= DS_OK
;
1287 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1288 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
1289 lpvAudioPtr2
, dwAudioBytes2
);
1292 WARN("invalid parameter: This == NULL\n");
1293 return DSERR_INVALIDPARAM
;
1296 if (lpvAudioPtr1
== NULL
) {
1297 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1298 return DSERR_INVALIDPARAM
;
1301 if (This
->device
->driver
) {
1302 hres
= IDsCaptureDriverBuffer_Unlock(This
->device
->hwbuf
, lpvAudioPtr1
,
1303 dwAudioBytes1
, lpvAudioPtr2
, dwAudioBytes2
);
1305 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1306 } else if (This
->device
->hwi
) {
1307 This
->device
->read_position
= (This
->device
->read_position
+
1308 (dwAudioBytes1
+ dwAudioBytes2
)) % This
->device
->buflen
;
1310 WARN("invalid call\n");
1311 hres
= DSERR_INVALIDCALL
;
1314 TRACE("returning %08lx\n", hres
);
1318 static HRESULT WINAPI
1319 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1320 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1321 REFGUID rguidObject
,
1323 REFGUID rguidInterface
,
1326 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1328 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
1329 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
1334 static HRESULT WINAPI
1335 IDirectSoundCaptureBufferImpl_GetFXStatus(
1336 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1338 LPDWORD pdwFXStatus
)
1340 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1342 FIXME( "(%p,%lu,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
1347 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
=
1349 /* IUnknown methods */
1350 IDirectSoundCaptureBufferImpl_QueryInterface
,
1351 IDirectSoundCaptureBufferImpl_AddRef
,
1352 IDirectSoundCaptureBufferImpl_Release
,
1354 /* IDirectSoundCaptureBuffer methods */
1355 IDirectSoundCaptureBufferImpl_GetCaps
,
1356 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
1357 IDirectSoundCaptureBufferImpl_GetFormat
,
1358 IDirectSoundCaptureBufferImpl_GetStatus
,
1359 IDirectSoundCaptureBufferImpl_Initialize
,
1360 IDirectSoundCaptureBufferImpl_Lock
,
1361 IDirectSoundCaptureBufferImpl_Start
,
1362 IDirectSoundCaptureBufferImpl_Stop
,
1363 IDirectSoundCaptureBufferImpl_Unlock
,
1365 /* IDirectSoundCaptureBuffer methods */
1366 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
1367 IDirectSoundCaptureBufferImpl_GetFXStatus
1370 HRESULT
IDirectSoundCaptureBufferImpl_Create(
1371 DirectSoundCaptureDevice
*device
,
1372 IDirectSoundCaptureBufferImpl
** ppobj
,
1373 LPCDSCBUFFERDESC lpcDSCBufferDesc
)
1375 LPWAVEFORMATEX wfex
;
1376 TRACE( "(%p,%p,%p)\n", device
, ppobj
, lpcDSCBufferDesc
);
1378 if (ppobj
== NULL
) {
1379 WARN("invalid parameter: ppobj == NULL\n");
1380 return DSERR_INVALIDPARAM
;
1384 WARN("not initialized\n");
1386 return DSERR_UNINITIALIZED
;
1389 if (lpcDSCBufferDesc
== NULL
) {
1390 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
1392 return DSERR_INVALIDPARAM
;
1395 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
1396 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
1397 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
1398 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) {
1399 WARN("invalid lpcDSCBufferDesc\n");
1401 return DSERR_INVALIDPARAM
;
1404 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
1407 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
1408 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1409 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
1410 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
1411 wfex
->wBitsPerSample
, wfex
->cbSize
);
1413 if (wfex
->wFormatTag
== WAVE_FORMAT_PCM
) {
1414 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
));
1415 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
));
1416 device
->pwfx
->cbSize
= 0;
1418 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1419 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1422 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
1424 return DSERR_INVALIDPARAM
; /* FIXME: DSERR_BADFORMAT ? */
1427 *ppobj
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1428 sizeof(IDirectSoundCaptureBufferImpl
));
1430 if ( *ppobj
== NULL
) {
1431 WARN("out of memory\n");
1433 return DSERR_OUTOFMEMORY
;
1435 HRESULT err
= DS_OK
;
1438 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)*ppobj
;
1441 This
->device
= device
;
1442 This
->device
->capture_buffer
= This
;
1443 This
->notify
= NULL
;
1444 This
->nrofnotifies
= 0;
1445 This
->hwnotify
= NULL
;
1447 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1448 lpcDSCBufferDesc
->dwSize
);
1450 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
1452 WARN("no memory\n");
1453 This
->device
->capture_buffer
= 0;
1454 HeapFree( GetProcessHeap(), 0, This
);
1456 return DSERR_OUTOFMEMORY
;
1459 This
->lpVtbl
= &dscbvt
;
1461 if (device
->driver
) {
1462 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1463 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
1465 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
1466 /* allocate buffer from system memory */
1467 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1468 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, device
->buffer
);
1470 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1472 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1474 if (newbuf
== NULL
) {
1475 WARN("failed to allocate capture buffer\n");
1476 err
= DSERR_OUTOFMEMORY
;
1477 /* but the old buffer might still exist and must be re-prepared */
1479 device
->buffer
= newbuf
;
1480 device
->buflen
= buflen
;
1483 /* let driver allocate memory */
1484 device
->buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1486 HeapFree( GetProcessHeap(), 0, device
->buffer
);
1487 device
->buffer
= NULL
;
1490 err
= IDsCaptureDriver_CreateCaptureBuffer(device
->driver
,
1491 device
->pwfx
,0,0,&(device
->buflen
),&(device
->buffer
),(LPVOID
*)&(device
->hwbuf
));
1493 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1494 This
->device
->capture_buffer
= 0;
1495 HeapFree( GetProcessHeap(), 0, This
);
1500 DWORD flags
= CALLBACK_FUNCTION
;
1501 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
1502 flags
|= WAVE_DIRECTSOUND
;
1503 err
= mmErr(waveInOpen(&(device
->hwi
),
1504 device
->drvdesc
.dnDevNode
, device
->pwfx
,
1505 (DWORD_PTR
)DSOUND_capture_callback
, (DWORD
)device
, flags
));
1507 WARN("waveInOpen failed\n");
1508 This
->device
->capture_buffer
= 0;
1509 HeapFree( GetProcessHeap(), 0, This
);
1514 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1515 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, device
->buffer
);
1517 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1519 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1520 if (newbuf
== NULL
) {
1521 WARN("failed to allocate capture buffer\n");
1522 err
= DSERR_OUTOFMEMORY
;
1523 /* but the old buffer might still exist and must be re-prepared */
1525 device
->buffer
= newbuf
;
1526 device
->buflen
= buflen
;
1531 TRACE("returning DS_OK\n");
1535 /*******************************************************************************
1536 * DirectSoundCaptureDevice
1538 HRESULT
DirectSoundCaptureDevice_Initialize(
1539 DirectSoundCaptureDevice
** ppDevice
,
1542 HRESULT err
= DSERR_INVALIDPARAM
;
1544 BOOLEAN found
= FALSE
;
1546 DirectSoundCaptureDevice
*device
= *ppDevice
;
1547 TRACE("(%p, %s)\n", ppDevice
, debugstr_guid(lpcGUID
));
1549 /* Default device? */
1550 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
1551 lpcGUID
= &DSDEVID_DefaultCapture
;
1553 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1554 WARN("invalid parameter: lpcGUID\n");
1555 return DSERR_INVALIDPARAM
;
1558 widn
= waveInGetNumDevs();
1560 WARN("no audio devices found\n");
1561 return DSERR_NODRIVER
;
1564 /* enumerate WINMM audio devices and find the one we want */
1565 for (wid
=0; wid
<widn
; wid
++) {
1566 if (IsEqualGUID( &devGUID
, &DSOUND_capture_guids
[wid
]) ) {
1572 if (found
== FALSE
) {
1573 WARN("No device found matching given ID!\n");
1574 return DSERR_NODRIVER
;
1577 if (DSOUND_capture
[wid
]) {
1578 WARN("already in use\n");
1579 return DSERR_ALLOCATED
;
1582 err
= DirectSoundCaptureDevice_Create(&(device
));
1584 WARN("DirectSoundCaptureDevice_Create failed\n");
1589 device
->guid
= devGUID
;
1591 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDIFACE
,(DWORD_PTR
)&(device
->driver
),0));
1592 if ( (err
!= DS_OK
) && (err
!= DSERR_UNSUPPORTED
) ) {
1593 WARN("waveInMessage failed; err=%lx\n",err
);
1598 /* Disable the direct sound driver to force emulation if requested. */
1599 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
1600 device
->driver
= NULL
;
1602 /* Get driver description */
1603 if (device
->driver
) {
1604 TRACE("using DirectSound driver\n");
1605 err
= IDsCaptureDriver_GetDriverDesc(device
->driver
, &(device
->drvdesc
));
1607 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
1611 TRACE("using WINMM\n");
1612 /* if no DirectSound interface available, use WINMM API instead */
1613 device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
|
1614 DSDDESC_DOMMSYSTEMSETFORMAT
;
1617 device
->drvdesc
.dnDevNode
= wid
;
1619 /* open the DirectSound driver if available */
1620 if (device
->driver
&& (err
== DS_OK
))
1621 err
= IDsCaptureDriver_Open(device
->driver
);
1626 /* the driver is now open, so it's now allowed to call GetCaps */
1627 if (device
->driver
) {
1628 device
->drvcaps
.dwSize
= sizeof(device
->drvcaps
);
1629 err
= IDsCaptureDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1631 WARN("IDsCaptureDriver_GetCaps failed\n");
1634 } else /*if (device->hwi)*/ {
1636 err
= mmErr(waveInGetDevCapsA((UINT
)device
->drvdesc
.dnDevNode
, &wic
, sizeof(wic
)));
1639 device
->drvcaps
.dwFlags
= 0;
1640 lstrcpynA(device
->drvdesc
.szDrvname
, wic
.szPname
,
1641 sizeof(device
->drvdesc
.szDrvname
));
1643 device
->drvcaps
.dwFlags
|= DSCCAPS_EMULDRIVER
;
1644 device
->drvcaps
.dwFormats
= wic
.dwFormats
;
1645 device
->drvcaps
.dwChannels
= wic
.wChannels
;
1653 HRESULT
DirectSoundCaptureDevice_Create(
1654 DirectSoundCaptureDevice
** ppDevice
)
1656 DirectSoundCaptureDevice
* device
;
1657 TRACE("(%p)\n", ppDevice
);
1659 /* Allocate memory */
1660 device
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DirectSoundCaptureDevice
));
1662 if (device
== NULL
) {
1663 WARN("out of memory\n");
1664 return DSERR_OUTOFMEMORY
;
1668 device
->state
= STATE_STOPPED
;
1670 InitializeCriticalSection( &(device
->lock
) );
1671 device
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)"DSCAPTURE_lock";
1678 ULONG
DirectSoundCaptureDevice_AddRef(
1679 DirectSoundCaptureDevice
* device
)
1681 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1682 TRACE("(%p) ref was %ld\n", device
, ref
- 1);
1686 ULONG
DirectSoundCaptureDevice_Release(
1687 DirectSoundCaptureDevice
* device
)
1689 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1690 TRACE("(%p) ref was %ld\n", device
, ref
+ 1);
1693 TRACE("deleting object\n");
1694 if (device
->capture_buffer
)
1695 IDirectSoundCaptureBufferImpl_Release(
1696 (LPDIRECTSOUNDCAPTUREBUFFER8
) device
->capture_buffer
);
1698 if (device
->driver
) {
1699 IDsCaptureDriver_Close(device
->driver
);
1700 IDsCaptureDriver_Release(device
->driver
);
1703 HeapFree(GetProcessHeap(), 0, device
->pwfx
);
1704 device
->lock
.DebugInfo
->Spare
[0] = 0;
1705 DeleteCriticalSection( &(device
->lock
) );
1706 DSOUND_capture
[device
->drvdesc
.dnDevNode
] = NULL
;
1707 HeapFree(GetProcessHeap(), 0, device
);
1708 TRACE("(%p) released\n", device
);
1713 /*******************************************************************************
1714 * DirectSoundCapture ClassFactory
1717 static HRESULT WINAPI
1718 DSCCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
)
1720 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1722 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
1723 return E_NOINTERFACE
;
1727 DSCCF_AddRef(LPCLASSFACTORY iface
)
1729 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1730 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1731 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1736 DSCCF_Release(LPCLASSFACTORY iface
)
1738 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1739 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1740 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1741 /* static class, won't be freed */
1745 static HRESULT WINAPI
1746 DSCCF_CreateInstance(
1747 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
)
1749 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1750 TRACE("(%p)->(%p,%s,%p)\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1753 WARN("aggregation not supported\n");
1754 return CLASS_E_NOAGGREGATION
;
1757 if (ppobj
== NULL
) {
1758 WARN("invalid parameter\n");
1759 return E_INVALIDARG
;
1764 if ( IsEqualGUID( &IID_IDirectSoundCapture
, riid
) )
1765 return DSOUND_CaptureCreate8((LPDIRECTSOUNDCAPTURE
*)ppobj
,pOuter
);
1767 WARN("(%p,%p,%s,%p) Interface not found!\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1768 return E_NOINTERFACE
;
1771 static HRESULT WINAPI
1772 DSCCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
)
1774 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1775 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
1779 static const IClassFactoryVtbl DSCCF_Vtbl
=
1781 DSCCF_QueryInterface
,
1784 DSCCF_CreateInstance
,
1788 IClassFactoryImpl DSOUND_CAPTURE_CF
= { &DSCCF_Vtbl
, 1 };