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 /*****************************************************************************
48 * IDirectSoundCapture implementation structure
50 struct IDirectSoundCaptureImpl
53 const IDirectSoundCaptureVtbl
*lpVtbl
;
56 DirectSoundCaptureDevice
*device
;
59 static HRESULT
IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8
* ppds
);
62 /*****************************************************************************
63 * IDirectSoundCaptureNotify implementation structure
65 struct IDirectSoundCaptureNotifyImpl
68 const IDirectSoundNotifyVtbl
*lpVtbl
;
70 IDirectSoundCaptureBufferImpl
* dscb
;
73 static HRESULT
IDirectSoundCaptureNotifyImpl_Create(IDirectSoundCaptureBufferImpl
*dscb
,
74 IDirectSoundCaptureNotifyImpl
** pdscn
);
77 DirectSoundCaptureDevice
* DSOUND_capture
[MAXWAVEDRIVERS
];
79 static HRESULT
DirectSoundCaptureDevice_Create(DirectSoundCaptureDevice
** ppDevice
);
81 static const char * const captureStateString
[] = {
88 HRESULT
DSOUND_CaptureCreate(
90 LPDIRECTSOUNDCAPTURE
*ppDSC
)
92 LPDIRECTSOUNDCAPTURE pDSC
;
94 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDSC
);
96 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
97 !IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
102 /* Get dsound configuration */
103 setup_dsound_options();
105 hr
= IDirectSoundCaptureImpl_Create(&pDSC
);
107 IDirectSoundCapture_AddRef(pDSC
);
110 WARN("IDirectSoundCaptureImpl_Create failed\n");
117 HRESULT
DSOUND_CaptureCreate8(
119 LPDIRECTSOUNDCAPTURE8
*ppDSC8
)
121 LPDIRECTSOUNDCAPTURE8 pDSC8
;
123 TRACE("(%s, %p)\n", debugstr_guid(riid
), ppDSC8
);
125 if (!IsEqualIID(riid
, &IID_IUnknown
) &&
126 !IsEqualIID(riid
, &IID_IDirectSoundCapture8
)) {
128 return E_NOINTERFACE
;
131 /* Get dsound configuration */
132 setup_dsound_options();
134 hr
= IDirectSoundCaptureImpl_Create(&pDSC8
);
136 IDirectSoundCapture_AddRef(pDSC8
);
139 WARN("IDirectSoundCaptureImpl_Create failed\n");
146 /***************************************************************************
147 * DirectSoundCaptureCreate [DSOUND.6]
149 * Create and initialize a DirectSoundCapture interface.
152 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
153 * lplpDSC [O] Address of a variable to receive the interface pointer.
154 * pUnkOuter [I] Must be NULL.
158 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
162 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
163 * or NULL for the default device or DSDEVID_DefaultCapture or
164 * DSDEVID_DefaultVoiceCapture.
166 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
168 HRESULT WINAPI
DirectSoundCaptureCreate(
170 LPDIRECTSOUNDCAPTURE
*ppDSC
,
174 LPDIRECTSOUNDCAPTURE pDSC
;
175 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC
, pUnkOuter
);
178 WARN("invalid parameter: ppDSC == NULL\n");
179 return DSERR_INVALIDPARAM
;
183 WARN("invalid parameter: pUnkOuter != NULL\n");
185 return DSERR_NOAGGREGATION
;
188 hr
= DSOUND_CaptureCreate(&IID_IDirectSoundCapture
, &pDSC
);
190 hr
= IDirectSoundCapture_Initialize(pDSC
, lpcGUID
);
192 IDirectSoundCapture_Release(pDSC
);
202 /***************************************************************************
203 * DirectSoundCaptureCreate8 [DSOUND.12]
205 * Create and initialize a DirectSoundCapture interface.
208 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
209 * lplpDSC [O] Address of a variable to receive the interface pointer.
210 * pUnkOuter [I] Must be NULL.
214 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
218 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
219 * or NULL for the default device or DSDEVID_DefaultCapture or
220 * DSDEVID_DefaultVoiceCapture.
222 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
224 HRESULT WINAPI
DirectSoundCaptureCreate8(
226 LPDIRECTSOUNDCAPTURE8
*ppDSC8
,
230 LPDIRECTSOUNDCAPTURE8 pDSC8
;
231 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), ppDSC8
, pUnkOuter
);
233 if (ppDSC8
== NULL
) {
234 WARN("invalid parameter: ppDSC8 == NULL\n");
235 return DSERR_INVALIDPARAM
;
239 WARN("invalid parameter: pUnkOuter != NULL\n");
241 return DSERR_NOAGGREGATION
;
244 hr
= DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8
, &pDSC8
);
246 hr
= IDirectSoundCapture_Initialize(pDSC8
, lpcGUID
);
248 IDirectSoundCapture_Release(pDSC8
);
258 /***************************************************************************
259 * DirectSoundCaptureEnumerateA [DSOUND.7]
261 * Enumerate all DirectSound drivers installed in the system.
264 * lpDSEnumCallback [I] Address of callback function.
265 * lpContext [I] Address of user defined context passed to callback function.
269 * Failure: DSERR_INVALIDPARAM
272 DirectSoundCaptureEnumerateA(
273 LPDSENUMCALLBACKA lpDSEnumCallback
,
281 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
283 if (lpDSEnumCallback
== NULL
) {
284 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
285 return DSERR_INVALIDPARAM
;
288 devs
= waveInGetNumDevs();
290 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
291 for (wid
= 0; wid
< devs
; ++wid
) {
292 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
293 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
295 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
296 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
297 if (lpDSEnumCallback(NULL
, "Primary Sound Capture Driver", desc
.szDrvname
, lpContext
) == FALSE
)
305 for (wid
= 0; wid
< devs
; ++wid
) {
306 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
308 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
309 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
310 if (lpDSEnumCallback(&DSOUND_capture_guids
[wid
], desc
.szDesc
, desc
.szDrvname
, lpContext
) == FALSE
)
318 /***************************************************************************
319 * DirectSoundCaptureEnumerateW [DSOUND.8]
321 * Enumerate all DirectSound drivers installed in the system.
324 * lpDSEnumCallback [I] Address of callback function.
325 * lpContext [I] Address of user defined context passed to callback function.
329 * Failure: DSERR_INVALIDPARAM
332 DirectSoundCaptureEnumerateW(
333 LPDSENUMCALLBACKW lpDSEnumCallback
,
340 WCHAR wDesc
[MAXPNAMELEN
];
341 WCHAR wName
[MAXPNAMELEN
];
343 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
345 if (lpDSEnumCallback
== NULL
) {
346 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
347 return DSERR_INVALIDPARAM
;
350 devs
= waveInGetNumDevs();
352 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
353 for (wid
= 0; wid
< devs
; ++wid
) {
354 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
355 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
357 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
358 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
359 MultiByteToWideChar( CP_ACP
, 0, "Primary Sound Capture Driver", -1,
360 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
361 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
362 wName
, sizeof(wName
)/sizeof(WCHAR
) );
363 if (lpDSEnumCallback(NULL
, wDesc
, wName
, lpContext
) == FALSE
)
371 for (wid
= 0; wid
< devs
; ++wid
) {
372 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD_PTR
)&desc
,0));
374 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
375 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
376 MultiByteToWideChar( CP_ACP
, 0, desc
.szDesc
, -1,
377 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
378 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
379 wName
, sizeof(wName
)/sizeof(WCHAR
) );
380 if (lpDSEnumCallback((LPGUID
)&DSOUND_capture_guids
[wid
], wDesc
, wName
, lpContext
) == FALSE
)
389 DSOUND_capture_callback(
396 DirectSoundCaptureDevice
* This
= (DirectSoundCaptureDevice
*)dwUser
;
397 TRACE("(%p,%08x(%s),%08x,%08x,%08x) entering at %d\n",hwi
,msg
,
398 msg
== MM_WIM_OPEN
? "MM_WIM_OPEN" : msg
== MM_WIM_CLOSE
? "MM_WIM_CLOSE" :
399 msg
== MM_WIM_DATA
? "MM_WIM_DATA" : "UNKNOWN",dwUser
,dw1
,dw2
,GetTickCount());
401 if (msg
== MM_WIM_DATA
) {
402 LPWAVEHDR pHdr
= (LPWAVEHDR
)dw1
;
403 EnterCriticalSection( &(This
->lock
) );
404 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
405 captureStateString
[This
->state
],This
->index
);
406 if (This
->state
!= STATE_STOPPED
) {
407 int index
= This
->index
;
408 if (This
->state
== STATE_STARTING
) {
409 This
->read_position
= pHdr
->dwBytesRecorded
;
410 This
->state
= STATE_CAPTURING
;
412 if (This
->capture_buffer
->nrofnotifies
)
413 SetEvent(This
->capture_buffer
->notifies
[This
->index
].hEventNotify
);
414 This
->index
= (This
->index
+ 1) % This
->nrofpwaves
;
415 if ( (This
->index
== 0) && !(This
->capture_buffer
->flags
& DSCBSTART_LOOPING
) ) {
416 TRACE("end of buffer\n");
417 This
->state
= STATE_STOPPED
;
419 if (This
->state
== STATE_CAPTURING
) {
420 waveInAddBuffer(hwi
, &(This
->pwave
[index
]), sizeof(WAVEHDR
));
421 } else if (This
->state
== STATE_STOPPING
) {
423 This
->state
= STATE_STOPPED
;
427 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
428 captureStateString
[This
->state
],This
->index
);
429 LeaveCriticalSection( &(This
->lock
) );
432 TRACE("completed\n");
435 /***************************************************************************
436 * IDirectSoundCaptureImpl
438 static HRESULT WINAPI
439 IDirectSoundCaptureImpl_QueryInterface(
440 LPDIRECTSOUNDCAPTURE iface
,
444 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
445 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
448 WARN("invalid parameter\n");
454 if (IsEqualIID(riid
, &IID_IUnknown
)) {
455 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
458 } else if (IsEqualIID(riid
, &IID_IDirectSoundCapture
)) {
459 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE
)This
);
464 WARN("unsupported riid: %s\n", debugstr_guid(riid
));
465 return E_NOINTERFACE
;
469 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface
)
471 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
472 ULONG ref
= InterlockedIncrement(&(This
->ref
));
473 TRACE("(%p) ref was %d\n", This
, ref
- 1);
478 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface
)
480 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
481 ULONG ref
= InterlockedDecrement(&(This
->ref
));
482 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
486 DirectSoundCaptureDevice_Release(This
->device
);
488 HeapFree( GetProcessHeap(), 0, This
);
489 TRACE("(%p) released\n", This
);
494 HRESULT WINAPI
IDirectSoundCaptureImpl_CreateCaptureBuffer(
495 LPDIRECTSOUNDCAPTURE iface
,
496 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
497 LPDIRECTSOUNDCAPTUREBUFFER
* lplpDSCaptureBuffer
,
501 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
503 TRACE( "(%p,%p,%p,%p)\n",iface
,lpcDSCBufferDesc
,lplpDSCaptureBuffer
,pUnk
);
505 if (lpcDSCBufferDesc
== NULL
) {
506 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
507 return DSERR_INVALIDPARAM
;
510 if (lplpDSCaptureBuffer
== NULL
) {
511 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
512 return DSERR_INVALIDPARAM
;
516 WARN("invalid parameter: pUnk != NULL\n");
517 return DSERR_INVALIDPARAM
;
520 /* FIXME: We can only have one buffer so what do we do here? */
521 if (This
->device
->capture_buffer
) {
522 WARN("lnvalid parameter: already has buffer\n");
523 return DSERR_INVALIDPARAM
; /* DSERR_GENERIC ? */
526 hr
= IDirectSoundCaptureBufferImpl_Create(This
->device
,
527 (IDirectSoundCaptureBufferImpl
**)lplpDSCaptureBuffer
, lpcDSCBufferDesc
);
530 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
535 HRESULT WINAPI
IDirectSoundCaptureImpl_GetCaps(
536 LPDIRECTSOUNDCAPTURE iface
,
537 LPDSCCAPS lpDSCCaps
)
539 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
540 TRACE("(%p,%p)\n",This
,lpDSCCaps
);
542 if (This
->device
== NULL
) {
543 WARN("not initialized\n");
544 return DSERR_UNINITIALIZED
;
547 if (lpDSCCaps
== NULL
) {
548 WARN("invalid parameter: lpDSCCaps== NULL\n");
549 return DSERR_INVALIDPARAM
;
552 if (lpDSCCaps
->dwSize
< sizeof(*lpDSCCaps
)) {
553 WARN("invalid parameter: lpDSCCaps->dwSize = %d\n", lpDSCCaps
->dwSize
);
554 return DSERR_INVALIDPARAM
;
557 lpDSCCaps
->dwFlags
= This
->device
->drvcaps
.dwFlags
;
558 lpDSCCaps
->dwFormats
= This
->device
->drvcaps
.dwFormats
;
559 lpDSCCaps
->dwChannels
= This
->device
->drvcaps
.dwChannels
;
561 TRACE("(flags=0x%08x,format=0x%08x,channels=%d)\n",lpDSCCaps
->dwFlags
,
562 lpDSCCaps
->dwFormats
, lpDSCCaps
->dwChannels
);
567 HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(
568 LPDIRECTSOUNDCAPTURE iface
,
571 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
572 TRACE("(%p,%s)\n", This
, debugstr_guid(lpcGUID
));
574 if (This
->device
!= NULL
) {
575 WARN("already initialized\n");
576 return DSERR_ALREADYINITIALIZED
;
579 return DirectSoundCaptureDevice_Initialize(&This
->device
, lpcGUID
);
582 static const IDirectSoundCaptureVtbl dscvt
=
584 /* IUnknown methods */
585 IDirectSoundCaptureImpl_QueryInterface
,
586 IDirectSoundCaptureImpl_AddRef
,
587 IDirectSoundCaptureImpl_Release
,
589 /* IDirectSoundCapture methods */
590 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
591 IDirectSoundCaptureImpl_GetCaps
,
592 IDirectSoundCaptureImpl_Initialize
595 static HRESULT
IDirectSoundCaptureImpl_Create(
596 LPDIRECTSOUNDCAPTURE8
* ppDSC
)
598 IDirectSoundCaptureImpl
*pDSC
;
599 TRACE("(%p)\n", ppDSC
);
601 /* Allocate memory */
602 pDSC
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(IDirectSoundCaptureImpl
));
604 WARN("out of memory\n");
606 return DSERR_OUTOFMEMORY
;
609 pDSC
->lpVtbl
= &dscvt
;
613 *ppDSC
= (LPDIRECTSOUNDCAPTURE8
)pDSC
;
618 /*******************************************************************************
619 * IDirectSoundCaptureNotify
621 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_QueryInterface(
622 LPDIRECTSOUNDNOTIFY iface
,
626 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
627 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
629 if (This
->dscb
== NULL
) {
630 WARN("invalid parameter\n");
634 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
, riid
, ppobj
);
637 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface
)
639 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
640 ULONG ref
= InterlockedIncrement(&(This
->ref
));
641 TRACE("(%p) ref was %d\n", This
, ref
- 1);
645 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface
)
647 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
648 ULONG ref
= InterlockedDecrement(&(This
->ref
));
649 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
652 if (This
->dscb
->hwnotify
)
653 IDsDriverNotify_Release(This
->dscb
->hwnotify
);
654 This
->dscb
->notify
=NULL
;
655 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
);
656 HeapFree(GetProcessHeap(),0,This
);
657 TRACE("(%p) released\n", This
);
662 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
663 LPDIRECTSOUNDNOTIFY iface
,
665 LPCDSBPOSITIONNOTIFY notify
)
667 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
668 TRACE("(%p,0x%08x,%p)\n",This
,howmuch
,notify
);
670 if (howmuch
> 0 && notify
== NULL
) {
671 WARN("invalid parameter: notify == NULL\n");
672 return DSERR_INVALIDPARAM
;
675 if (TRACE_ON(dsound
)) {
677 for (i
=0;i
<howmuch
;i
++)
678 TRACE("notify at %d to %p\n",
679 notify
[i
].dwOffset
,notify
[i
].hEventNotify
);
682 if (This
->dscb
->hwnotify
) {
684 hres
= IDsDriverNotify_SetNotificationPositions(This
->dscb
->hwnotify
, howmuch
, notify
);
686 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
688 } else if (howmuch
> 0) {
689 /* Make an internal copy of the caller-supplied array.
690 * Replace the existing copy if one is already present. */
691 if (This
->dscb
->notifies
)
692 This
->dscb
->notifies
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
693 This
->dscb
->notifies
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
695 This
->dscb
->notifies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
696 howmuch
* sizeof(DSBPOSITIONNOTIFY
));
698 if (This
->dscb
->notifies
== NULL
) {
699 WARN("out of memory\n");
700 return DSERR_OUTOFMEMORY
;
702 CopyMemory(This
->dscb
->notifies
, notify
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
703 This
->dscb
->nrofnotifies
= howmuch
;
705 HeapFree(GetProcessHeap(), 0, This
->dscb
->notifies
);
706 This
->dscb
->notifies
= NULL
;
707 This
->dscb
->nrofnotifies
= 0;
713 static const IDirectSoundNotifyVtbl dscnvt
=
715 IDirectSoundCaptureNotifyImpl_QueryInterface
,
716 IDirectSoundCaptureNotifyImpl_AddRef
,
717 IDirectSoundCaptureNotifyImpl_Release
,
718 IDirectSoundCaptureNotifyImpl_SetNotificationPositions
,
721 static HRESULT
IDirectSoundCaptureNotifyImpl_Create(
722 IDirectSoundCaptureBufferImpl
*dscb
,
723 IDirectSoundCaptureNotifyImpl
**pdscn
)
725 IDirectSoundCaptureNotifyImpl
* dscn
;
726 TRACE("(%p,%p)\n",dscb
,pdscn
);
728 dscn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(dscn
));
731 WARN("out of memory\n");
732 return DSERR_OUTOFMEMORY
;
736 dscn
->lpVtbl
= &dscnvt
;
739 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER
)dscb
);
745 /*******************************************************************************
746 * IDirectSoundCaptureBuffer
748 static HRESULT WINAPI
749 IDirectSoundCaptureBufferImpl_QueryInterface(
750 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
754 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
756 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
759 WARN("invalid parameter\n");
765 if ( IsEqualGUID( &IID_IDirectSoundNotify
, riid
) ) {
767 hres
= IDirectSoundCaptureNotifyImpl_Create(This
, &This
->notify
);
769 if (This
->device
->hwbuf
) {
770 hres
= IDsCaptureDriverBuffer_QueryInterface(This
->device
->hwbuf
,
771 &IID_IDsDriverNotify
, (LPVOID
*)&(This
->hwnotify
));
773 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
779 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY
)This
->notify
);
780 *ppobj
= (LPVOID
)This
->notify
;
784 WARN("IID_IDirectSoundNotify\n");
788 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer
, riid
) ||
789 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8
, riid
) ) {
790 IDirectSoundCaptureBuffer8_AddRef(iface
);
795 FIXME("(%p,%s,%p) unsupported GUID\n", This
, debugstr_guid(riid
), ppobj
);
796 return E_NOINTERFACE
;
800 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
802 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
803 ULONG ref
= InterlockedIncrement(&(This
->ref
));
804 TRACE("(%p) ref was %d\n", This
, ref
- 1);
809 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
811 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
812 ULONG ref
= InterlockedDecrement(&(This
->ref
));
813 TRACE("(%p) ref was %d\n", This
, ref
+ 1);
816 TRACE("deleting object\n");
817 if (This
->device
->state
== STATE_CAPTURING
)
818 This
->device
->state
= STATE_STOPPING
;
820 HeapFree(GetProcessHeap(),0, This
->pdscbd
);
822 if (This
->device
->hwi
) {
823 waveInReset(This
->device
->hwi
);
824 waveInClose(This
->device
->hwi
);
825 HeapFree(GetProcessHeap(),0, This
->device
->pwave
);
826 This
->device
->pwave
= 0;
827 This
->device
->hwi
= 0;
830 if (This
->device
->hwbuf
)
831 IDsCaptureDriverBuffer_Release(This
->device
->hwbuf
);
833 /* remove from DirectSoundCaptureDevice */
834 This
->device
->capture_buffer
= NULL
;
837 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
839 HeapFree(GetProcessHeap(), 0, This
->notifies
);
840 HeapFree( GetProcessHeap(), 0, This
);
841 TRACE("(%p) released\n", This
);
846 static HRESULT WINAPI
847 IDirectSoundCaptureBufferImpl_GetCaps(
848 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
849 LPDSCBCAPS lpDSCBCaps
)
851 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
852 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
854 if (lpDSCBCaps
== NULL
) {
855 WARN("invalid parameter: lpDSCBCaps == NULL\n");
856 return DSERR_INVALIDPARAM
;
859 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
860 WARN("invalid parameter: lpDSCBCaps->dwSize = %d\n", lpDSCBCaps
->dwSize
);
861 return DSERR_INVALIDPARAM
;
864 if (This
->device
== NULL
) {
865 WARN("invalid parameter: This->device == NULL\n");
866 return DSERR_INVALIDPARAM
;
869 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
870 lpDSCBCaps
->dwFlags
= This
->flags
;
871 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
872 lpDSCBCaps
->dwReserved
= 0;
874 TRACE("returning DS_OK\n");
878 static HRESULT WINAPI
879 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
880 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
881 LPDWORD lpdwCapturePosition
,
882 LPDWORD lpdwReadPosition
)
884 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
885 HRESULT hres
= DS_OK
;
886 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
888 if (This
->device
== NULL
) {
889 WARN("invalid parameter: This->device == NULL\n");
890 return DSERR_INVALIDPARAM
;
893 if (This
->device
->driver
) {
894 hres
= IDsCaptureDriverBuffer_GetPosition(This
->device
->hwbuf
, lpdwCapturePosition
, lpdwReadPosition
);
896 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
897 } else if (This
->device
->hwi
) {
898 EnterCriticalSection(&(This
->device
->lock
));
899 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
900 if (lpdwCapturePosition
) {
902 mtime
.wType
= TIME_BYTES
;
903 waveInGetPosition(This
->device
->hwi
, &mtime
, sizeof(mtime
));
904 TRACE("mtime.u.cb=%d,This->device->buflen=%d\n", mtime
.u
.cb
,
905 This
->device
->buflen
);
906 mtime
.u
.cb
= mtime
.u
.cb
% This
->device
->buflen
;
907 *lpdwCapturePosition
= mtime
.u
.cb
;
910 if (lpdwReadPosition
) {
911 if (This
->device
->state
== STATE_STARTING
) {
912 if (lpdwCapturePosition
)
913 This
->device
->read_position
= *lpdwCapturePosition
;
914 This
->device
->state
= STATE_CAPTURING
;
916 *lpdwReadPosition
= This
->device
->read_position
;
918 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
919 LeaveCriticalSection(&(This
->device
->lock
));
920 if (lpdwCapturePosition
) TRACE("*lpdwCapturePosition=%d\n",*lpdwCapturePosition
);
921 if (lpdwReadPosition
) TRACE("*lpdwReadPosition=%d\n",*lpdwReadPosition
);
924 hres
= DSERR_NODRIVER
;
927 TRACE("returning %08x\n", hres
);
931 static HRESULT WINAPI
932 IDirectSoundCaptureBufferImpl_GetFormat(
933 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
934 LPWAVEFORMATEX lpwfxFormat
,
935 DWORD dwSizeAllocated
,
936 LPDWORD lpdwSizeWritten
)
938 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
939 HRESULT hres
= DS_OK
;
940 TRACE( "(%p,%p,0x%08x,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
943 if (This
->device
== NULL
) {
944 WARN("invalid parameter: This->device == NULL\n");
945 return DSERR_INVALIDPARAM
;
948 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
))
949 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
951 if (lpwfxFormat
) { /* NULL is valid (just want size) */
952 CopyMemory(lpwfxFormat
, This
->device
->pwfx
, dwSizeAllocated
);
954 *lpdwSizeWritten
= dwSizeAllocated
;
957 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->device
->pwfx
->cbSize
;
959 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
960 hres
= DSERR_INVALIDPARAM
;
964 TRACE("returning %08x\n", hres
);
968 static HRESULT WINAPI
969 IDirectSoundCaptureBufferImpl_GetStatus(
970 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
973 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
974 TRACE( "(%p, %p), thread is %04x\n", This
, lpdwStatus
, GetCurrentThreadId() );
976 if (This
->device
== NULL
) {
977 WARN("invalid parameter: This->device == NULL\n");
978 return DSERR_INVALIDPARAM
;
981 if (lpdwStatus
== NULL
) {
982 WARN("invalid parameter: lpdwStatus == NULL\n");
983 return DSERR_INVALIDPARAM
;
987 EnterCriticalSection(&(This
->device
->lock
));
989 TRACE("old This->device->state=%s, old lpdwStatus=%08x\n",
990 captureStateString
[This
->device
->state
],*lpdwStatus
);
991 if ((This
->device
->state
== STATE_STARTING
) ||
992 (This
->device
->state
== STATE_CAPTURING
)) {
993 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
994 if (This
->flags
& DSCBSTART_LOOPING
)
995 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
997 TRACE("new This->device->state=%s, new lpdwStatus=%08x\n",
998 captureStateString
[This
->device
->state
],*lpdwStatus
);
999 LeaveCriticalSection(&(This
->device
->lock
));
1001 TRACE("status=%x\n", *lpdwStatus
);
1002 TRACE("returning DS_OK\n");
1006 static HRESULT WINAPI
1007 IDirectSoundCaptureBufferImpl_Initialize(
1008 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1009 LPDIRECTSOUNDCAPTURE lpDSC
,
1010 LPCDSCBUFFERDESC lpcDSCBDesc
)
1012 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1014 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
1019 static HRESULT WINAPI
1020 IDirectSoundCaptureBufferImpl_Lock(
1021 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1024 LPVOID
* lplpvAudioPtr1
,
1025 LPDWORD lpdwAudioBytes1
,
1026 LPVOID
* lplpvAudioPtr2
,
1027 LPDWORD lpdwAudioBytes2
,
1030 HRESULT hres
= DS_OK
;
1031 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1032 TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This
, dwReadCusor
,
1033 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
1034 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
1036 if (This
->device
== NULL
) {
1037 WARN("invalid parameter: This->device == NULL\n");
1038 return DSERR_INVALIDPARAM
;
1041 if (lplpvAudioPtr1
== NULL
) {
1042 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1043 return DSERR_INVALIDPARAM
;
1046 if (lpdwAudioBytes1
== NULL
) {
1047 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1048 return DSERR_INVALIDPARAM
;
1051 EnterCriticalSection(&(This
->device
->lock
));
1053 if (This
->device
->driver
) {
1054 hres
= IDsCaptureDriverBuffer_Lock(This
->device
->hwbuf
, lplpvAudioPtr1
,
1055 lpdwAudioBytes1
, lplpvAudioPtr2
,
1056 lpdwAudioBytes2
, dwReadCusor
,
1057 dwReadBytes
, dwFlags
);
1059 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1060 } else if (This
->device
->hwi
) {
1061 *lplpvAudioPtr1
= This
->device
->buffer
+ dwReadCusor
;
1062 if ( (dwReadCusor
+ dwReadBytes
) > This
->device
->buflen
) {
1063 *lpdwAudioBytes1
= This
->device
->buflen
- dwReadCusor
;
1065 *lplpvAudioPtr2
= This
->device
->buffer
;
1066 if (lpdwAudioBytes2
)
1067 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
1069 *lpdwAudioBytes1
= dwReadBytes
;
1071 *lplpvAudioPtr2
= 0;
1072 if (lpdwAudioBytes2
)
1073 *lpdwAudioBytes2
= 0;
1076 TRACE("invalid call\n");
1077 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
1080 LeaveCriticalSection(&(This
->device
->lock
));
1082 TRACE("returning %08x\n", hres
);
1086 static HRESULT WINAPI
1087 IDirectSoundCaptureBufferImpl_Start(
1088 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1091 HRESULT hres
= DS_OK
;
1092 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1093 TRACE( "(%p,0x%08x)\n", This
, dwFlags
);
1095 if (This
->device
== NULL
) {
1096 WARN("invalid parameter: This->device == NULL\n");
1097 return DSERR_INVALIDPARAM
;
1100 if ( (This
->device
->driver
== 0) && (This
->device
->hwi
== 0) ) {
1101 WARN("no driver\n");
1102 return DSERR_NODRIVER
;
1105 EnterCriticalSection(&(This
->device
->lock
));
1107 This
->flags
= dwFlags
;
1108 TRACE("old This->state=%s\n",captureStateString
[This
->device
->state
]);
1109 if (This
->device
->state
== STATE_STOPPED
)
1110 This
->device
->state
= STATE_STARTING
;
1111 else if (This
->device
->state
== STATE_STOPPING
)
1112 This
->device
->state
= STATE_CAPTURING
;
1113 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1115 LeaveCriticalSection(&(This
->device
->lock
));
1117 if (This
->device
->driver
) {
1118 hres
= IDsCaptureDriverBuffer_Start(This
->device
->hwbuf
, dwFlags
);
1120 WARN("IDsCaptureDriverBuffer_Start failed\n");
1121 } else if (This
->device
->hwi
) {
1122 DirectSoundCaptureDevice
*device
= This
->device
;
1124 if (device
->buffer
) {
1125 if (This
->nrofnotifies
) {
1128 device
->nrofpwaves
= This
->nrofnotifies
;
1129 TRACE("nrofnotifies=%d\n", This
->nrofnotifies
);
1131 /* prepare headers */
1133 device
->pwave
= HeapReAlloc(GetProcessHeap(),0,device
->pwave
,
1134 device
->nrofpwaves
*sizeof(WAVEHDR
));
1136 device
->pwave
= HeapAlloc(GetProcessHeap(),0,
1137 device
->nrofpwaves
*sizeof(WAVEHDR
));
1139 for (c
= 0; c
< device
->nrofpwaves
; c
++) {
1140 if (This
->notifies
[c
].dwOffset
== DSBPN_OFFSETSTOP
) {
1141 TRACE("got DSBPN_OFFSETSTOP\n");
1142 device
->nrofpwaves
= c
;
1146 device
->pwave
[0].lpData
= (LPSTR
)device
->buffer
;
1147 device
->pwave
[0].dwBufferLength
=
1148 This
->notifies
[0].dwOffset
+ 1;
1150 device
->pwave
[c
].lpData
= (LPSTR
)device
->buffer
+
1151 This
->notifies
[c
-1].dwOffset
+ 1;
1152 device
->pwave
[c
].dwBufferLength
=
1153 This
->notifies
[c
].dwOffset
-
1154 This
->notifies
[c
-1].dwOffset
;
1156 device
->pwave
[c
].dwBytesRecorded
= 0;
1157 device
->pwave
[c
].dwUser
= (DWORD
)device
;
1158 device
->pwave
[c
].dwFlags
= 0;
1159 device
->pwave
[c
].dwLoops
= 0;
1160 hres
= mmErr(waveInPrepareHeader(device
->hwi
,
1161 &(device
->pwave
[c
]),sizeof(WAVEHDR
)));
1162 if (hres
!= DS_OK
) {
1163 WARN("waveInPrepareHeader failed\n");
1165 waveInUnprepareHeader(device
->hwi
,
1166 &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1170 hres
= mmErr(waveInAddBuffer(device
->hwi
,
1171 &(device
->pwave
[c
]), sizeof(WAVEHDR
)));
1172 if (hres
!= DS_OK
) {
1173 WARN("waveInAddBuffer failed\n");
1175 waveInUnprepareHeader(device
->hwi
,
1176 &(device
->pwave
[c
]),sizeof(WAVEHDR
));
1181 FillMemory(device
->buffer
, device
->buflen
,
1182 (device
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
1184 TRACE("no notifiers specified\n");
1185 /* no notifiers specified so just create a single default header */
1186 device
->nrofpwaves
= 1;
1188 device
->pwave
= HeapReAlloc(GetProcessHeap(),0,device
->pwave
,sizeof(WAVEHDR
));
1190 device
->pwave
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR
));
1192 device
->pwave
[0].lpData
= (LPSTR
)device
->buffer
;
1193 device
->pwave
[0].dwBufferLength
= device
->buflen
;
1194 device
->pwave
[0].dwBytesRecorded
= 0;
1195 device
->pwave
[0].dwUser
= (DWORD
)device
;
1196 device
->pwave
[0].dwFlags
= 0;
1197 device
->pwave
[0].dwLoops
= 0;
1199 hres
= mmErr(waveInPrepareHeader(device
->hwi
,
1200 &(device
->pwave
[0]),sizeof(WAVEHDR
)));
1201 if (hres
!= DS_OK
) {
1202 WARN("waveInPrepareHeader failed\n");
1203 waveInUnprepareHeader(device
->hwi
,
1204 &(device
->pwave
[0]),sizeof(WAVEHDR
));
1206 hres
= mmErr(waveInAddBuffer(device
->hwi
,
1207 &(device
->pwave
[0]), sizeof(WAVEHDR
)));
1208 if (hres
!= DS_OK
) {
1209 WARN("waveInAddBuffer failed\n");
1210 waveInUnprepareHeader(device
->hwi
,
1211 &(device
->pwave
[0]),sizeof(WAVEHDR
));
1217 device
->read_position
= 0;
1219 if (hres
== DS_OK
) {
1220 /* start filling the first buffer */
1221 hres
= mmErr(waveInStart(device
->hwi
));
1223 WARN("waveInStart failed\n");
1226 if (hres
!= DS_OK
) {
1227 WARN("calling waveInClose because of error\n");
1228 waveInClose(device
->hwi
);
1232 WARN("no driver\n");
1233 hres
= DSERR_NODRIVER
;
1236 TRACE("returning %08x\n", hres
);
1240 static HRESULT WINAPI
1241 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1243 HRESULT hres
= DS_OK
;
1244 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1245 TRACE( "(%p)\n", This
);
1247 if (This
->device
== NULL
) {
1248 WARN("invalid parameter: This->device == NULL\n");
1249 return DSERR_INVALIDPARAM
;
1252 EnterCriticalSection(&(This
->device
->lock
));
1254 TRACE("old This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1255 if (This
->device
->state
== STATE_CAPTURING
)
1256 This
->device
->state
= STATE_STOPPING
;
1257 else if (This
->device
->state
== STATE_STARTING
)
1258 This
->device
->state
= STATE_STOPPED
;
1259 TRACE("new This->device->state=%s\n",captureStateString
[This
->device
->state
]);
1261 LeaveCriticalSection(&(This
->device
->lock
));
1263 if (This
->device
->driver
) {
1264 hres
= IDsCaptureDriverBuffer_Stop(This
->device
->hwbuf
);
1266 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1267 } else if (This
->device
->hwi
) {
1268 hres
= mmErr(waveInReset(This
->device
->hwi
));
1270 WARN("waveInReset() failed\n");
1272 WARN("no driver\n");
1273 hres
= DSERR_NODRIVER
;
1276 TRACE("returning %08x\n", hres
);
1280 static HRESULT WINAPI
1281 IDirectSoundCaptureBufferImpl_Unlock(
1282 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1283 LPVOID lpvAudioPtr1
,
1284 DWORD dwAudioBytes1
,
1285 LPVOID lpvAudioPtr2
,
1286 DWORD dwAudioBytes2
)
1288 HRESULT hres
= DS_OK
;
1289 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1290 TRACE( "(%p,%p,%08u,%p,%08u)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
1291 lpvAudioPtr2
, dwAudioBytes2
);
1293 if (lpvAudioPtr1
== NULL
) {
1294 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1295 return DSERR_INVALIDPARAM
;
1298 if (This
->device
->driver
) {
1299 hres
= IDsCaptureDriverBuffer_Unlock(This
->device
->hwbuf
, lpvAudioPtr1
,
1300 dwAudioBytes1
, lpvAudioPtr2
, dwAudioBytes2
);
1302 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1303 } else if (This
->device
->hwi
) {
1304 This
->device
->read_position
= (This
->device
->read_position
+
1305 (dwAudioBytes1
+ dwAudioBytes2
)) % This
->device
->buflen
;
1307 WARN("invalid call\n");
1308 hres
= DSERR_INVALIDCALL
;
1311 TRACE("returning %08x\n", hres
);
1315 static HRESULT WINAPI
1316 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1317 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1318 REFGUID rguidObject
,
1320 REFGUID rguidInterface
,
1323 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1325 FIXME( "(%p,%s,%u,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
1326 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
1331 static HRESULT WINAPI
1332 IDirectSoundCaptureBufferImpl_GetFXStatus(
1333 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1335 LPDWORD pdwFXStatus
)
1337 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1339 FIXME( "(%p,%u,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
1344 static const IDirectSoundCaptureBuffer8Vtbl dscbvt
=
1346 /* IUnknown methods */
1347 IDirectSoundCaptureBufferImpl_QueryInterface
,
1348 IDirectSoundCaptureBufferImpl_AddRef
,
1349 IDirectSoundCaptureBufferImpl_Release
,
1351 /* IDirectSoundCaptureBuffer methods */
1352 IDirectSoundCaptureBufferImpl_GetCaps
,
1353 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
1354 IDirectSoundCaptureBufferImpl_GetFormat
,
1355 IDirectSoundCaptureBufferImpl_GetStatus
,
1356 IDirectSoundCaptureBufferImpl_Initialize
,
1357 IDirectSoundCaptureBufferImpl_Lock
,
1358 IDirectSoundCaptureBufferImpl_Start
,
1359 IDirectSoundCaptureBufferImpl_Stop
,
1360 IDirectSoundCaptureBufferImpl_Unlock
,
1362 /* IDirectSoundCaptureBuffer methods */
1363 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
1364 IDirectSoundCaptureBufferImpl_GetFXStatus
1367 HRESULT
IDirectSoundCaptureBufferImpl_Create(
1368 DirectSoundCaptureDevice
*device
,
1369 IDirectSoundCaptureBufferImpl
** ppobj
,
1370 LPCDSCBUFFERDESC lpcDSCBufferDesc
)
1372 LPWAVEFORMATEX wfex
;
1373 TRACE( "(%p,%p,%p)\n", device
, ppobj
, lpcDSCBufferDesc
);
1375 if (ppobj
== NULL
) {
1376 WARN("invalid parameter: ppobj == NULL\n");
1377 return DSERR_INVALIDPARAM
;
1381 WARN("not initialized\n");
1383 return DSERR_UNINITIALIZED
;
1386 if (lpcDSCBufferDesc
== NULL
) {
1387 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
1389 return DSERR_INVALIDPARAM
;
1392 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
1393 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
1394 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
1395 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) {
1396 WARN("invalid lpcDSCBufferDesc\n");
1398 return DSERR_INVALIDPARAM
;
1401 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
1404 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
1405 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1406 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
1407 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
1408 wfex
->wBitsPerSample
, wfex
->cbSize
);
1410 if (wfex
->wFormatTag
== WAVE_FORMAT_PCM
) {
1411 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
));
1412 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
));
1413 device
->pwfx
->cbSize
= 0;
1415 device
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1416 CopyMemory(device
->pwfx
, wfex
, sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
1419 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
1421 return DSERR_INVALIDPARAM
; /* FIXME: DSERR_BADFORMAT ? */
1424 *ppobj
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1425 sizeof(IDirectSoundCaptureBufferImpl
));
1427 if ( *ppobj
== NULL
) {
1428 WARN("out of memory\n");
1430 return DSERR_OUTOFMEMORY
;
1432 HRESULT err
= DS_OK
;
1435 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)*ppobj
;
1438 This
->device
= device
;
1439 This
->device
->capture_buffer
= This
;
1440 This
->notify
= NULL
;
1441 This
->nrofnotifies
= 0;
1442 This
->hwnotify
= NULL
;
1444 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
1445 lpcDSCBufferDesc
->dwSize
);
1447 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
1449 WARN("no memory\n");
1450 This
->device
->capture_buffer
= 0;
1451 HeapFree( GetProcessHeap(), 0, This
);
1453 return DSERR_OUTOFMEMORY
;
1456 This
->lpVtbl
= &dscbvt
;
1458 if (device
->driver
) {
1459 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
1460 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
1462 if (This
->device
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
1463 /* allocate buffer from system memory */
1464 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1465 TRACE("desired buflen=%d, old buffer=%p\n", buflen
, device
->buffer
);
1467 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1469 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1471 if (newbuf
== NULL
) {
1472 WARN("failed to allocate capture buffer\n");
1473 err
= DSERR_OUTOFMEMORY
;
1474 /* but the old buffer might still exist and must be re-prepared */
1476 device
->buffer
= newbuf
;
1477 device
->buflen
= buflen
;
1480 /* let driver allocate memory */
1481 device
->buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1483 HeapFree( GetProcessHeap(), 0, device
->buffer
);
1484 device
->buffer
= NULL
;
1487 err
= IDsCaptureDriver_CreateCaptureBuffer(device
->driver
,
1488 device
->pwfx
,0,0,&(device
->buflen
),&(device
->buffer
),(LPVOID
*)&(device
->hwbuf
));
1490 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1491 This
->device
->capture_buffer
= 0;
1492 HeapFree( GetProcessHeap(), 0, This
);
1497 DWORD flags
= CALLBACK_FUNCTION
;
1498 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
1499 flags
|= WAVE_DIRECTSOUND
;
1500 err
= mmErr(waveInOpen(&(device
->hwi
),
1501 device
->drvdesc
.dnDevNode
, device
->pwfx
,
1502 (DWORD_PTR
)DSOUND_capture_callback
, (DWORD
)device
, flags
));
1504 WARN("waveInOpen failed\n");
1505 This
->device
->capture_buffer
= 0;
1506 HeapFree( GetProcessHeap(), 0, This
);
1511 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
1512 TRACE("desired buflen=%d, old buffer=%p\n", buflen
, device
->buffer
);
1514 newbuf
= HeapReAlloc(GetProcessHeap(),0,device
->buffer
,buflen
);
1516 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
1517 if (newbuf
== NULL
) {
1518 WARN("failed to allocate capture buffer\n");
1519 err
= DSERR_OUTOFMEMORY
;
1520 /* but the old buffer might still exist and must be re-prepared */
1522 device
->buffer
= newbuf
;
1523 device
->buflen
= buflen
;
1528 TRACE("returning DS_OK\n");
1532 /*******************************************************************************
1533 * DirectSoundCaptureDevice
1535 HRESULT
DirectSoundCaptureDevice_Initialize(
1536 DirectSoundCaptureDevice
** ppDevice
,
1539 HRESULT err
= DSERR_INVALIDPARAM
;
1541 BOOLEAN found
= FALSE
;
1543 DirectSoundCaptureDevice
*device
= *ppDevice
;
1544 TRACE("(%p, %s)\n", ppDevice
, debugstr_guid(lpcGUID
));
1546 /* Default device? */
1547 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
1548 lpcGUID
= &DSDEVID_DefaultCapture
;
1550 if (GetDeviceID(lpcGUID
, &devGUID
) != DS_OK
) {
1551 WARN("invalid parameter: lpcGUID\n");
1552 return DSERR_INVALIDPARAM
;
1555 widn
= waveInGetNumDevs();
1557 WARN("no audio devices found\n");
1558 return DSERR_NODRIVER
;
1561 /* enumerate WINMM audio devices and find the one we want */
1562 for (wid
=0; wid
<widn
; wid
++) {
1563 if (IsEqualGUID( &devGUID
, &DSOUND_capture_guids
[wid
]) ) {
1569 if (found
== FALSE
) {
1570 WARN("No device found matching given ID!\n");
1571 return DSERR_NODRIVER
;
1574 if (DSOUND_capture
[wid
]) {
1575 WARN("already in use\n");
1576 return DSERR_ALLOCATED
;
1579 err
= DirectSoundCaptureDevice_Create(&(device
));
1581 WARN("DirectSoundCaptureDevice_Create failed\n");
1586 device
->guid
= devGUID
;
1588 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDIFACE
,(DWORD_PTR
)&(device
->driver
),0));
1589 if ( (err
!= DS_OK
) && (err
!= DSERR_UNSUPPORTED
) ) {
1590 WARN("waveInMessage failed; err=%x\n",err
);
1595 /* Disable the direct sound driver to force emulation if requested. */
1596 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
1597 device
->driver
= NULL
;
1599 /* Get driver description */
1600 if (device
->driver
) {
1601 TRACE("using DirectSound driver\n");
1602 err
= IDsCaptureDriver_GetDriverDesc(device
->driver
, &(device
->drvdesc
));
1604 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
1608 TRACE("using WINMM\n");
1609 /* if no DirectSound interface available, use WINMM API instead */
1610 device
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
|
1611 DSDDESC_DOMMSYSTEMSETFORMAT
;
1614 device
->drvdesc
.dnDevNode
= wid
;
1616 /* open the DirectSound driver if available */
1617 if (device
->driver
&& (err
== DS_OK
))
1618 err
= IDsCaptureDriver_Open(device
->driver
);
1623 /* the driver is now open, so it's now allowed to call GetCaps */
1624 if (device
->driver
) {
1625 device
->drvcaps
.dwSize
= sizeof(device
->drvcaps
);
1626 err
= IDsCaptureDriver_GetCaps(device
->driver
,&(device
->drvcaps
));
1628 WARN("IDsCaptureDriver_GetCaps failed\n");
1631 } else /*if (device->hwi)*/ {
1633 err
= mmErr(waveInGetDevCapsA((UINT
)device
->drvdesc
.dnDevNode
, &wic
, sizeof(wic
)));
1636 device
->drvcaps
.dwFlags
= 0;
1637 lstrcpynA(device
->drvdesc
.szDrvname
, wic
.szPname
,
1638 sizeof(device
->drvdesc
.szDrvname
));
1640 device
->drvcaps
.dwFlags
|= DSCCAPS_EMULDRIVER
;
1641 device
->drvcaps
.dwFormats
= wic
.dwFormats
;
1642 device
->drvcaps
.dwChannels
= wic
.wChannels
;
1650 static HRESULT
DirectSoundCaptureDevice_Create(
1651 DirectSoundCaptureDevice
** ppDevice
)
1653 DirectSoundCaptureDevice
* device
;
1654 TRACE("(%p)\n", ppDevice
);
1656 /* Allocate memory */
1657 device
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DirectSoundCaptureDevice
));
1659 if (device
== NULL
) {
1660 WARN("out of memory\n");
1661 return DSERR_OUTOFMEMORY
;
1665 device
->state
= STATE_STOPPED
;
1667 InitializeCriticalSection( &(device
->lock
) );
1668 device
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)"DSCAPTURE_lock";
1675 ULONG
DirectSoundCaptureDevice_AddRef(
1676 DirectSoundCaptureDevice
* device
)
1678 ULONG ref
= InterlockedIncrement(&(device
->ref
));
1679 TRACE("(%p) ref was %d\n", device
, ref
- 1);
1683 ULONG
DirectSoundCaptureDevice_Release(
1684 DirectSoundCaptureDevice
* device
)
1686 ULONG ref
= InterlockedDecrement(&(device
->ref
));
1687 TRACE("(%p) ref was %d\n", device
, ref
+ 1);
1690 TRACE("deleting object\n");
1691 if (device
->capture_buffer
)
1692 IDirectSoundCaptureBufferImpl_Release(
1693 (LPDIRECTSOUNDCAPTUREBUFFER8
) device
->capture_buffer
);
1695 if (device
->driver
) {
1696 IDsCaptureDriver_Close(device
->driver
);
1697 IDsCaptureDriver_Release(device
->driver
);
1700 HeapFree(GetProcessHeap(), 0, device
->pwfx
);
1701 device
->lock
.DebugInfo
->Spare
[0] = 0;
1702 DeleteCriticalSection( &(device
->lock
) );
1703 DSOUND_capture
[device
->drvdesc
.dnDevNode
] = NULL
;
1704 HeapFree(GetProcessHeap(), 0, device
);
1705 TRACE("(%p) released\n", device
);