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 DirectSoundFullDuplex support.
24 * Implement FX support.
29 #define NONAMELESSSTRUCT
30 #define NONAMELESSUNION
38 #include "wine/debug.h"
41 #include "dsound_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(dsound
);
45 static HRESULT WINAPI
IDirectSoundCaptureImpl_Initialize(
46 LPDIRECTSOUNDCAPTURE iface
,
48 static ULONG WINAPI
IDirectSoundCaptureImpl_Release(
49 LPDIRECTSOUNDCAPTURE iface
);
50 static ULONG WINAPI
IDirectSoundCaptureBufferImpl_Release(
51 LPDIRECTSOUNDCAPTUREBUFFER8 iface
);
52 static HRESULT
DSOUND_CreateDirectSoundCaptureBuffer(
53 IDirectSoundCaptureImpl
*ipDSC
,
54 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
56 static HRESULT WINAPI
IDirectSoundFullDuplexImpl_Initialize(
57 LPDIRECTSOUNDFULLDUPLEX iface
,
59 LPCGUID pRendererGuid
,
60 LPCDSCBUFFERDESC lpDscBufferDesc
,
61 LPCDSBUFFERDESC lpDsBufferDesc
,
64 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8
,
65 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8
);
67 static IDirectSoundCaptureVtbl dscvt
;
68 static IDirectSoundCaptureBuffer8Vtbl dscbvt
;
69 static IDirectSoundFullDuplexVtbl dsfdvt
;
71 static IDirectSoundCaptureImpl
* dsound_capture
= NULL
;
73 static const char * captureStateString
[] = {
80 /***************************************************************************
81 * DirectSoundCaptureCreate [DSOUND.6]
83 * Create and initialize a DirectSoundCapture interface.
86 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
87 * lplpDSC [O] Address of a variable to receive the interface pointer.
88 * pUnkOuter [I] Must be NULL.
92 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
96 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
97 * or NULL for the default device or DSDEVID_DefaultCapture or
98 * DSDEVID_DefaultVoiceCapture.
100 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
103 DirectSoundCaptureCreate8(
105 LPDIRECTSOUNDCAPTURE
* lplpDSC
,
106 LPUNKNOWN pUnkOuter
)
108 IDirectSoundCaptureImpl
** ippDSC
=(IDirectSoundCaptureImpl
**)lplpDSC
;
109 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID
), lplpDSC
, pUnkOuter
);
112 WARN("invalid parameter: pUnkOuter != NULL\n");
113 return DSERR_NOAGGREGATION
;
117 WARN("invalid parameter: lplpDSC == NULL\n");
118 return DSERR_INVALIDPARAM
;
121 /* Default device? */
122 if ( !lpcGUID
|| IsEqualGUID(lpcGUID
, &GUID_NULL
) )
123 lpcGUID
= &DSDEVID_DefaultCapture
;
125 *ippDSC
= HeapAlloc(GetProcessHeap(),
126 HEAP_ZERO_MEMORY
, sizeof(IDirectSoundCaptureImpl
));
128 if (*ippDSC
== NULL
) {
129 WARN("out of memory\n");
130 return DSERR_OUTOFMEMORY
;
132 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)*ippDSC
;
135 This
->state
= STATE_STOPPED
;
137 InitializeCriticalSection( &(This
->lock
) );
138 This
->lock
.DebugInfo
->Spare
[1] = (DWORD
)"DSCAPTURE_lock";
140 This
->lpVtbl
= &dscvt
;
141 dsound_capture
= This
;
143 if (GetDeviceID(lpcGUID
, &This
->guid
) == DS_OK
) {
145 hres
= IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE
)This
, &This
->guid
);
147 WARN("IDirectSoundCaptureImpl_Initialize failed\n");
151 WARN("invalid GUID: %s\n", debugstr_guid(lpcGUID
));
152 return DSERR_INVALIDPARAM
;
155 /***************************************************************************
156 * DirectSoundCaptureEnumerateA [DSOUND.7]
158 * Enumerate all DirectSound drivers installed in the system.
161 * lpDSEnumCallback [I] Address of callback function.
162 * lpContext [I] Address of user defined context passed to callback function.
166 * Failure: DSERR_INVALIDPARAM
169 DirectSoundCaptureEnumerateA(
170 LPDSENUMCALLBACKA lpDSEnumCallback
,
178 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
180 if (lpDSEnumCallback
== NULL
) {
181 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
182 return DSERR_INVALIDPARAM
;
185 devs
= waveInGetNumDevs();
187 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
188 for (wid
= 0; wid
< devs
; ++wid
) {
189 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
190 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD
)&desc
,0));
192 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
193 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
194 if (lpDSEnumCallback(NULL
, "Primary Sound Capture Driver", desc
.szDrvname
, lpContext
) == FALSE
)
202 for (wid
= 0; wid
< devs
; ++wid
) {
203 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD
)&desc
,0));
205 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
206 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
207 if (lpDSEnumCallback(&DSOUND_capture_guids
[wid
], desc
.szDesc
, desc
.szDrvname
, lpContext
) == FALSE
)
215 /***************************************************************************
216 * DirectSoundCaptureEnumerateW [DSOUND.8]
218 * Enumerate all DirectSound drivers installed in the system.
221 * lpDSEnumCallback [I] Address of callback function.
222 * lpContext [I] Address of user defined context passed to callback function.
226 * Failure: DSERR_INVALIDPARAM
229 DirectSoundCaptureEnumerateW(
230 LPDSENUMCALLBACKW lpDSEnumCallback
,
237 WCHAR wDesc
[MAXPNAMELEN
];
238 WCHAR wName
[MAXPNAMELEN
];
240 TRACE("(%p,%p)\n", lpDSEnumCallback
, lpContext
);
242 if (lpDSEnumCallback
== NULL
) {
243 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
244 return DSERR_INVALIDPARAM
;
247 devs
= waveInGetNumDevs();
249 if (GetDeviceID(&DSDEVID_DefaultCapture
, &guid
) == DS_OK
) {
250 for (wid
= 0; wid
< devs
; ++wid
) {
251 if (IsEqualGUID( &guid
, &DSOUND_capture_guids
[wid
] ) ) {
252 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD
)&desc
,0));
254 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
255 "Primary Sound Capture Driver",desc
.szDrvname
,lpContext
);
256 MultiByteToWideChar( CP_ACP
, 0, "Primary Sound Capture Driver", -1,
257 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
258 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
259 wName
, sizeof(wName
)/sizeof(WCHAR
) );
260 if (lpDSEnumCallback(NULL
, wDesc
, wName
, lpContext
) == FALSE
)
268 for (wid
= 0; wid
< devs
; ++wid
) {
269 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDDESC
,(DWORD
)&desc
,0));
271 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
272 debugstr_guid(&DSOUND_capture_guids
[wid
]),desc
.szDesc
,desc
.szDrvname
,lpContext
);
273 MultiByteToWideChar( CP_ACP
, 0, desc
.szDesc
, -1,
274 wDesc
, sizeof(wDesc
)/sizeof(WCHAR
) );
275 MultiByteToWideChar( CP_ACP
, 0, desc
.szDrvname
, -1,
276 wName
, sizeof(wName
)/sizeof(WCHAR
) );
277 if (lpDSEnumCallback((LPGUID
)&DSOUND_capture_guids
[wid
], wDesc
, wName
, lpContext
) == FALSE
)
286 DSOUND_capture_callback(
293 IDirectSoundCaptureImpl
* This
= (IDirectSoundCaptureImpl
*)dwUser
;
294 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi
,msg
,
295 msg
== MM_WIM_OPEN
? "MM_WIM_OPEN" : msg
== MM_WIM_CLOSE
? "MM_WIM_CLOSE" :
296 msg
== MM_WIM_DATA
? "MM_WIM_DATA" : "UNKNOWN",dwUser
,dw1
,dw2
,GetTickCount());
298 if (msg
== MM_WIM_DATA
) {
299 LPWAVEHDR pHdr
= (LPWAVEHDR
)dw1
;
300 EnterCriticalSection( &(This
->lock
) );
301 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
302 captureStateString
[This
->state
],This
->index
);
303 if (This
->state
!= STATE_STOPPED
) {
304 int index
= This
->index
;
305 if (This
->state
== STATE_STARTING
) {
306 This
->read_position
= pHdr
->dwBytesRecorded
;
307 This
->state
= STATE_CAPTURING
;
309 if (This
->capture_buffer
->nrofnotifies
)
310 SetEvent(This
->capture_buffer
->notifies
[This
->index
].hEventNotify
);
311 This
->index
= (This
->index
+ 1) % This
->nrofpwaves
;
312 if ( (This
->index
== 0) && !(This
->capture_buffer
->flags
& DSCBSTART_LOOPING
) ) {
313 TRACE("end of buffer\n");
314 This
->state
= STATE_STOPPED
;
316 if (This
->state
== STATE_CAPTURING
) {
317 waveInAddBuffer(hwi
, &(This
->pwave
[index
]), sizeof(WAVEHDR
));
318 } else if (This
->state
== STATE_STOPPING
) {
320 This
->state
= STATE_STOPPED
;
324 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
325 captureStateString
[This
->state
],This
->index
);
326 LeaveCriticalSection( &(This
->lock
) );
329 TRACE("completed\n");
332 static HRESULT WINAPI
333 IDirectSoundCaptureImpl_QueryInterface(
334 LPDIRECTSOUNDCAPTURE iface
,
338 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
339 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
342 WARN("invalid parameter\n");
350 hres
= IDsCaptureDriver_QueryInterface(This
->driver
, riid
, ppobj
);
352 WARN("IDsCaptureDriver_QueryInterface failed\n");
356 WARN("unsupported riid: %s\n", debugstr_guid(riid
));
361 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface
)
363 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
364 ULONG ref
= InterlockedIncrement(&(This
->ref
));
365 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
370 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface
)
372 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
373 ULONG ref
= InterlockedDecrement(&(This
->ref
));
374 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
377 TRACE("deleting object\n");
378 if (This
->capture_buffer
)
379 IDirectSoundCaptureBufferImpl_Release(
380 (LPDIRECTSOUNDCAPTUREBUFFER8
) This
->capture_buffer
);
383 IDsCaptureDriver_Close(This
->driver
);
384 IDsCaptureDriver_Release(This
->driver
);
387 HeapFree(GetProcessHeap(), 0, This
->pwfx
);
388 This
->lock
.DebugInfo
->Spare
[1] = 0;
389 DeleteCriticalSection( &(This
->lock
) );
390 HeapFree( GetProcessHeap(), 0, This
);
391 dsound_capture
= NULL
;
392 TRACE("(%p) released\n", This
);
397 static HRESULT WINAPI
398 IDirectSoundCaptureImpl_CreateCaptureBuffer(
399 LPDIRECTSOUNDCAPTURE iface
,
400 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
401 LPDIRECTSOUNDCAPTUREBUFFER
* lplpDSCaptureBuffer
,
405 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
407 TRACE( "(%p,%p,%p,%p)\n",This
,lpcDSCBufferDesc
,lplpDSCaptureBuffer
,pUnk
);
410 WARN("invalid parameter: This == NULL\n");
411 return DSERR_INVALIDPARAM
;
414 if (lpcDSCBufferDesc
== NULL
) {
415 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
416 return DSERR_INVALIDPARAM
;
419 if (lplpDSCaptureBuffer
== NULL
) {
420 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
421 return DSERR_INVALIDPARAM
;
425 WARN("invalid parameter: pUnk != NULL\n");
426 return DSERR_INVALIDPARAM
;
429 /* FIXME: We can only have one buffer so what do we do here? */
430 if (This
->capture_buffer
) {
431 WARN("lnvalid parameter: already has buffer\n");
432 return DSERR_INVALIDPARAM
; /* DSERR_GENERIC ? */
435 hr
= DSOUND_CreateDirectSoundCaptureBuffer( This
, lpcDSCBufferDesc
,
436 (LPVOID
*)lplpDSCaptureBuffer
);
439 WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n");
444 static HRESULT WINAPI
445 IDirectSoundCaptureImpl_GetCaps(
446 LPDIRECTSOUNDCAPTURE iface
,
447 LPDSCCAPS lpDSCCaps
)
449 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
450 TRACE("(%p,%p)\n",This
,lpDSCCaps
);
452 if (lpDSCCaps
== NULL
) {
453 WARN("invalid parameter: lpDSCCaps== NULL\n");
454 return DSERR_INVALIDPARAM
;
457 if (lpDSCCaps
->dwSize
< sizeof(*lpDSCCaps
)) {
458 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
459 lpDSCCaps
->dwSize
, sizeof(*lpDSCCaps
));
460 return DSERR_INVALIDPARAM
;
463 if ( !(This
->initialized
) ) {
464 WARN("not initialized\n");
465 return DSERR_UNINITIALIZED
;
468 lpDSCCaps
->dwFlags
= This
->drvcaps
.dwFlags
;
469 lpDSCCaps
->dwFormats
= This
->drvcaps
.dwFormats
;
470 lpDSCCaps
->dwChannels
= This
->drvcaps
.dwChannels
;
472 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps
->dwFlags
,
473 lpDSCCaps
->dwFormats
, lpDSCCaps
->dwChannels
);
478 static HRESULT WINAPI
479 IDirectSoundCaptureImpl_Initialize(
480 LPDIRECTSOUNDCAPTURE iface
,
483 HRESULT err
= DSERR_INVALIDPARAM
;
485 IDirectSoundCaptureImpl
*This
= (IDirectSoundCaptureImpl
*)iface
;
486 TRACE("(%p)\n", This
);
489 WARN("invalid parameter: This == NULL\n");
490 return DSERR_INVALIDPARAM
;
493 if (This
->initialized
) {
494 WARN("already initialized\n");
495 return DSERR_ALREADYINITIALIZED
;
498 widn
= waveInGetNumDevs();
501 WARN("no audio devices found\n");
502 return DSERR_NODRIVER
;
505 /* Get dsound configuration */
506 setup_dsound_options();
508 /* enumerate WINMM audio devices and find the one we want */
509 for (wid
=0; wid
<widn
; wid
++) {
510 if (IsEqualGUID( lpcGUID
, &DSOUND_capture_guids
[wid
]) ) {
517 WARN("invalid parameter\n");
518 return DSERR_INVALIDPARAM
;
521 err
= mmErr(waveInMessage((HWAVEIN
)wid
,DRV_QUERYDSOUNDIFACE
,(DWORD
)&(This
->driver
),0));
522 if ( (err
!= DS_OK
) && (err
!= DSERR_UNSUPPORTED
) ) {
523 WARN("waveInMessage failed; err=%lx\n",err
);
528 /* Disable the direct sound driver to force emulation if requested. */
529 if (ds_hw_accel
== DS_HW_ACCEL_EMULATION
)
532 /* Get driver description */
534 TRACE("using DirectSound driver\n");
535 err
= IDsCaptureDriver_GetDriverDesc(This
->driver
, &(This
->drvdesc
));
537 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
541 TRACE("using WINMM\n");
542 /* if no DirectSound interface available, use WINMM API instead */
543 This
->drvdesc
.dwFlags
= DSDDESC_DOMMSYSTEMOPEN
|
544 DSDDESC_DOMMSYSTEMSETFORMAT
;
547 This
->drvdesc
.dnDevNode
= wid
;
549 /* open the DirectSound driver if available */
550 if (This
->driver
&& (err
== DS_OK
))
551 err
= IDsCaptureDriver_Open(This
->driver
);
554 This
->initialized
= TRUE
;
556 /* the driver is now open, so it's now allowed to call GetCaps */
558 This
->drvcaps
.dwSize
= sizeof(This
->drvcaps
);
559 err
= IDsCaptureDriver_GetCaps(This
->driver
,&(This
->drvcaps
));
561 WARN("IDsCaptureDriver_GetCaps failed\n");
564 } else /*if (This->hwi)*/ {
566 err
= mmErr(waveInGetDevCapsA((UINT
)This
->drvdesc
.dnDevNode
, &wic
, sizeof(wic
)));
569 This
->drvcaps
.dwFlags
= 0;
570 lstrcpynA(This
->drvdesc
.szDrvname
, wic
.szPname
,
571 sizeof(This
->drvdesc
.szDrvname
));
573 This
->drvcaps
.dwFlags
|= DSCCAPS_EMULDRIVER
;
574 This
->drvcaps
.dwFormats
= wic
.dwFormats
;
575 This
->drvcaps
.dwChannels
= wic
.wChannels
;
583 static IDirectSoundCaptureVtbl dscvt
=
585 /* IUnknown methods */
586 IDirectSoundCaptureImpl_QueryInterface
,
587 IDirectSoundCaptureImpl_AddRef
,
588 IDirectSoundCaptureImpl_Release
,
590 /* IDirectSoundCapture methods */
591 IDirectSoundCaptureImpl_CreateCaptureBuffer
,
592 IDirectSoundCaptureImpl_GetCaps
,
593 IDirectSoundCaptureImpl_Initialize
597 DSOUND_CreateDirectSoundCaptureBuffer(
598 IDirectSoundCaptureImpl
*ipDSC
,
599 LPCDSCBUFFERDESC lpcDSCBufferDesc
,
603 TRACE( "(%p,%p)\n", lpcDSCBufferDesc
, ppobj
);
606 WARN("invalid parameter: ipDSC == NULL\n");
607 return DSERR_INVALIDPARAM
;
610 if (lpcDSCBufferDesc
== NULL
) {
611 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
612 return DSERR_INVALIDPARAM
;
616 WARN("invalid parameter: ppobj == NULL\n");
617 return DSERR_INVALIDPARAM
;
620 if ( ((lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC
)) &&
621 (lpcDSCBufferDesc
->dwSize
!= sizeof(DSCBUFFERDESC1
))) ||
622 (lpcDSCBufferDesc
->dwBufferBytes
== 0) ||
623 (lpcDSCBufferDesc
->lpwfxFormat
== NULL
) ) {
624 WARN("invalid lpcDSCBufferDesc\n");
626 return DSERR_INVALIDPARAM
;
629 if ( !ipDSC
->initialized
) {
630 WARN("not initialized\n");
632 return DSERR_UNINITIALIZED
;
635 wfex
= lpcDSCBufferDesc
->lpwfxFormat
;
638 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
639 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
640 wfex
->wFormatTag
, wfex
->nChannels
, wfex
->nSamplesPerSec
,
641 wfex
->nAvgBytesPerSec
, wfex
->nBlockAlign
,
642 wfex
->wBitsPerSample
, wfex
->cbSize
);
644 if (wfex
->wFormatTag
== WAVE_FORMAT_PCM
) {
645 ipDSC
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
));
646 CopyMemory(ipDSC
->pwfx
, wfex
, sizeof(WAVEFORMATEX
));
647 ipDSC
->pwfx
->cbSize
= 0;
649 ipDSC
->pwfx
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
650 CopyMemory(ipDSC
->pwfx
, wfex
, sizeof(WAVEFORMATEX
)+wfex
->cbSize
);
653 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
655 return DSERR_INVALIDPARAM
; /* FIXME: DSERR_BADFORMAT ? */
658 *ppobj
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
659 sizeof(IDirectSoundCaptureBufferImpl
));
661 if ( *ppobj
== NULL
) {
662 WARN("out of memory\n");
664 return DSERR_OUTOFMEMORY
;
669 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)*ppobj
;
672 This
->dsound
= ipDSC
;
673 This
->dsound
->capture_buffer
= This
;
675 This
->nrofnotifies
= 0;
676 This
->hwnotify
= NULL
;
678 This
->pdscbd
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
679 lpcDSCBufferDesc
->dwSize
);
681 CopyMemory(This
->pdscbd
, lpcDSCBufferDesc
, lpcDSCBufferDesc
->dwSize
);
684 This
->dsound
->capture_buffer
= 0;
685 HeapFree( GetProcessHeap(), 0, This
);
687 return DSERR_OUTOFMEMORY
;
690 This
->lpVtbl
= &dscbvt
;
693 if (This
->dsound
->drvdesc
.dwFlags
& DSDDESC_DOMMSYSTEMOPEN
)
694 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
696 if (This
->dsound
->drvdesc
.dwFlags
& DSDDESC_USESYSTEMMEMORY
) {
697 /* allocate buffer from system memory */
698 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
699 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, ipDSC
->buffer
);
701 newbuf
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->buffer
,buflen
);
703 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
705 if (newbuf
== NULL
) {
706 WARN("failed to allocate capture buffer\n");
707 err
= DSERR_OUTOFMEMORY
;
708 /* but the old buffer might still exist and must be re-prepared */
710 ipDSC
->buffer
= newbuf
;
711 ipDSC
->buflen
= buflen
;
714 /* let driver allocate memory */
715 ipDSC
->buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
717 HeapFree( GetProcessHeap(), 0, ipDSC
->buffer
);
718 ipDSC
->buffer
= NULL
;
721 err
= IDsCaptureDriver_CreateCaptureBuffer(ipDSC
->driver
,
722 ipDSC
->pwfx
,0,0,&(ipDSC
->buflen
),&(ipDSC
->buffer
),(LPVOID
*)&(ipDSC
->hwbuf
));
724 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
725 This
->dsound
->capture_buffer
= 0;
726 HeapFree( GetProcessHeap(), 0, This
);
731 DWORD flags
= CALLBACK_FUNCTION
;
732 if (ds_hw_accel
!= DS_HW_ACCEL_EMULATION
)
733 flags
|= WAVE_DIRECTSOUND
;
734 err
= mmErr(waveInOpen(&(ipDSC
->hwi
),
735 ipDSC
->drvdesc
.dnDevNode
, ipDSC
->pwfx
,
736 (DWORD
)DSOUND_capture_callback
, (DWORD
)ipDSC
, flags
));
738 WARN("waveInOpen failed\n");
739 This
->dsound
->capture_buffer
= 0;
740 HeapFree( GetProcessHeap(), 0, This
);
745 buflen
= lpcDSCBufferDesc
->dwBufferBytes
;
746 TRACE("desired buflen=%ld, old buffer=%p\n", buflen
, ipDSC
->buffer
);
748 newbuf
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->buffer
,buflen
);
750 newbuf
= HeapAlloc(GetProcessHeap(),0,buflen
);
751 if (newbuf
== NULL
) {
752 WARN("failed to allocate capture buffer\n");
753 err
= DSERR_OUTOFMEMORY
;
754 /* but the old buffer might still exist and must be re-prepared */
756 ipDSC
->buffer
= newbuf
;
757 ipDSC
->buflen
= buflen
;
762 TRACE("returning DS_OK\n");
766 /*******************************************************************************
767 * IDirectSoundCaptureNotify
769 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_QueryInterface(
770 LPDIRECTSOUNDNOTIFY iface
,
774 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
775 TRACE("(%p,%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
777 if (This
->dscb
== NULL
) {
778 WARN("invalid parameter\n");
782 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
, riid
, ppobj
);
785 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface
)
787 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
788 ULONG ref
= InterlockedIncrement(&(This
->ref
));
789 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
793 static ULONG WINAPI
IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface
)
795 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
796 ULONG ref
= InterlockedDecrement(&(This
->ref
));
797 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
800 if (This
->dscb
->hwnotify
)
801 IDsDriverNotify_Release(This
->dscb
->hwnotify
);
802 This
->dscb
->notify
=NULL
;
803 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER
)This
->dscb
);
804 HeapFree(GetProcessHeap(),0,This
);
805 TRACE("(%p) released\n", This
);
810 static HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
811 LPDIRECTSOUNDNOTIFY iface
,
813 LPCDSBPOSITIONNOTIFY notify
)
815 IDirectSoundCaptureNotifyImpl
*This
= (IDirectSoundCaptureNotifyImpl
*)iface
;
816 TRACE("(%p,0x%08lx,%p)\n",This
,howmuch
,notify
);
818 if (howmuch
> 0 && notify
== NULL
) {
819 WARN("invalid parameter: notify == NULL\n");
820 return DSERR_INVALIDPARAM
;
823 if (TRACE_ON(dsound
)) {
825 for (i
=0;i
<howmuch
;i
++)
826 TRACE("notify at %ld to 0x%08lx\n",
827 notify
[i
].dwOffset
,(DWORD
)notify
[i
].hEventNotify
);
830 if (This
->dscb
->hwnotify
) {
832 hres
= IDsDriverNotify_SetNotificationPositions(This
->dscb
->hwnotify
, howmuch
, notify
);
834 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
836 } else if (howmuch
> 0) {
837 /* Make an internal copy of the caller-supplied array.
838 * Replace the existing copy if one is already present. */
839 if (This
->dscb
->notifies
)
840 This
->dscb
->notifies
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
841 This
->dscb
->notifies
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
843 This
->dscb
->notifies
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
844 howmuch
* sizeof(DSBPOSITIONNOTIFY
));
846 if (This
->dscb
->notifies
== NULL
) {
847 WARN("out of memory\n");
848 return DSERR_OUTOFMEMORY
;
850 CopyMemory(This
->dscb
->notifies
, notify
, howmuch
* sizeof(DSBPOSITIONNOTIFY
));
851 This
->dscb
->nrofnotifies
= howmuch
;
853 HeapFree(GetProcessHeap(), 0, This
->dscb
->notifies
);
854 This
->dscb
->notifies
= NULL
;
855 This
->dscb
->nrofnotifies
= 0;
861 IDirectSoundNotifyVtbl dscnvt
=
863 IDirectSoundCaptureNotifyImpl_QueryInterface
,
864 IDirectSoundCaptureNotifyImpl_AddRef
,
865 IDirectSoundCaptureNotifyImpl_Release
,
866 IDirectSoundCaptureNotifyImpl_SetNotificationPositions
,
869 HRESULT WINAPI
IDirectSoundCaptureNotifyImpl_Create(
870 IDirectSoundCaptureBufferImpl
*dscb
,
871 IDirectSoundCaptureNotifyImpl
**pdscn
)
873 IDirectSoundCaptureNotifyImpl
* dscn
;
874 TRACE("(%p,%p)\n",dscb
,pdscn
);
876 dscn
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(dscn
));
879 WARN("out of memory\n");
880 return DSERR_OUTOFMEMORY
;
884 dscn
->lpVtbl
= &dscnvt
;
887 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER
)dscb
);
893 /*******************************************************************************
894 * IDirectSoundCaptureBuffer
896 static HRESULT WINAPI
897 IDirectSoundCaptureBufferImpl_QueryInterface(
898 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
902 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
904 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
907 WARN("invalid parameter\n");
913 if ( IsEqualGUID( &IID_IDirectSoundNotify
, riid
) ) {
915 hres
= IDirectSoundCaptureNotifyImpl_Create(This
, &This
->notify
);
917 if (This
->dsound
->hwbuf
) {
918 hres
= IDsCaptureDriverBuffer_QueryInterface(This
->dsound
->hwbuf
,
919 &IID_IDsDriverNotify
, (LPVOID
*)&(This
->hwnotify
));
921 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
927 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY
)This
->notify
);
928 *ppobj
= (LPVOID
)This
->notify
;
932 WARN("IID_IDirectSoundNotify\n");
936 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer
, riid
) ||
937 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8
, riid
) ) {
938 IDirectSoundCaptureBuffer8_AddRef(iface
);
943 FIXME("(%p,%s,%p) unsupported GUID\n", This
, debugstr_guid(riid
), ppobj
);
944 return E_NOINTERFACE
;
948 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
950 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
951 ULONG ref
= InterlockedIncrement(&(This
->ref
));
952 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
957 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
959 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
960 ULONG ref
= InterlockedDecrement(&(This
->ref
));
961 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
964 TRACE("deleting object\n");
965 if (This
->dsound
->state
== STATE_CAPTURING
)
966 This
->dsound
->state
= STATE_STOPPING
;
968 HeapFree(GetProcessHeap(),0, This
->pdscbd
);
970 if (This
->dsound
->hwi
) {
971 waveInReset(This
->dsound
->hwi
);
972 waveInClose(This
->dsound
->hwi
);
973 HeapFree(GetProcessHeap(),0, This
->dsound
->pwave
);
974 This
->dsound
->pwave
= 0;
975 This
->dsound
->hwi
= 0;
978 if (This
->dsound
->hwbuf
)
979 IDsCaptureDriverBuffer_Release(This
->dsound
->hwbuf
);
981 /* remove from IDirectSoundCaptureImpl */
983 This
->dsound
->capture_buffer
= NULL
;
985 ERR("does not reference dsound\n");
988 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY
)This
->notify
);
990 HeapFree(GetProcessHeap(), 0, This
->notifies
);
991 HeapFree( GetProcessHeap(), 0, This
);
992 TRACE("(%p) released\n", This
);
997 static HRESULT WINAPI
998 IDirectSoundCaptureBufferImpl_GetCaps(
999 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1000 LPDSCBCAPS lpDSCBCaps
)
1002 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1003 TRACE( "(%p,%p)\n", This
, lpDSCBCaps
);
1006 WARN("invalid parameter: This == NULL\n");
1007 return DSERR_INVALIDPARAM
;
1010 if (lpDSCBCaps
== NULL
) {
1011 WARN("invalid parameter: lpDSCBCaps == NULL\n");
1012 return DSERR_INVALIDPARAM
;
1015 if (lpDSCBCaps
->dwSize
< sizeof(DSCBCAPS
)) {
1016 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
1017 lpDSCBCaps
->dwSize
, sizeof(DSCBCAPS
));
1018 return DSERR_INVALIDPARAM
;
1021 if (This
->dsound
== NULL
) {
1022 WARN("invalid parameter: This->dsound == NULL\n");
1023 return DSERR_INVALIDPARAM
;
1026 lpDSCBCaps
->dwSize
= sizeof(DSCBCAPS
);
1027 lpDSCBCaps
->dwFlags
= This
->flags
;
1028 lpDSCBCaps
->dwBufferBytes
= This
->pdscbd
->dwBufferBytes
;
1029 lpDSCBCaps
->dwReserved
= 0;
1031 TRACE("returning DS_OK\n");
1035 static HRESULT WINAPI
1036 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
1037 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1038 LPDWORD lpdwCapturePosition
,
1039 LPDWORD lpdwReadPosition
)
1041 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1042 HRESULT hres
= DS_OK
;
1043 TRACE( "(%p,%p,%p)\n", This
, lpdwCapturePosition
, lpdwReadPosition
);
1046 WARN("invalid parameter: This == NULL\n");
1047 return DSERR_INVALIDPARAM
;
1050 if (This
->dsound
== NULL
) {
1051 WARN("invalid parameter: This->dsound == NULL\n");
1052 return DSERR_INVALIDPARAM
;
1055 if (This
->dsound
->driver
) {
1056 hres
= IDsCaptureDriverBuffer_GetPosition(This
->dsound
->hwbuf
, lpdwCapturePosition
, lpdwReadPosition
);
1058 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
1059 } else if (This
->dsound
->hwi
) {
1060 EnterCriticalSection(&(This
->dsound
->lock
));
1061 TRACE("old This->dsound->state=%s\n",captureStateString
[This
->dsound
->state
]);
1062 if (lpdwCapturePosition
) {
1064 mtime
.wType
= TIME_BYTES
;
1065 waveInGetPosition(This
->dsound
->hwi
, &mtime
, sizeof(mtime
));
1066 TRACE("mtime.u.cb=%ld,This->dsound->buflen=%ld\n", mtime
.u
.cb
,
1067 This
->dsound
->buflen
);
1068 mtime
.u
.cb
= mtime
.u
.cb
% This
->dsound
->buflen
;
1069 *lpdwCapturePosition
= mtime
.u
.cb
;
1072 if (lpdwReadPosition
) {
1073 if (This
->dsound
->state
== STATE_STARTING
) {
1074 if (lpdwCapturePosition
)
1075 This
->dsound
->read_position
= *lpdwCapturePosition
;
1076 This
->dsound
->state
= STATE_CAPTURING
;
1078 *lpdwReadPosition
= This
->dsound
->read_position
;
1080 TRACE("new This->dsound->state=%s\n",captureStateString
[This
->dsound
->state
]);
1081 LeaveCriticalSection(&(This
->dsound
->lock
));
1082 if (lpdwCapturePosition
) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition
);
1083 if (lpdwReadPosition
) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition
);
1085 WARN("no driver\n");
1086 hres
= DSERR_NODRIVER
;
1089 TRACE("returning %08lx\n", hres
);
1093 static HRESULT WINAPI
1094 IDirectSoundCaptureBufferImpl_GetFormat(
1095 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1096 LPWAVEFORMATEX lpwfxFormat
,
1097 DWORD dwSizeAllocated
,
1098 LPDWORD lpdwSizeWritten
)
1100 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1101 HRESULT hres
= DS_OK
;
1102 TRACE( "(%p,%p,0x%08lx,%p)\n", This
, lpwfxFormat
, dwSizeAllocated
,
1106 WARN("invalid parameter: This == NULL\n");
1107 return DSERR_INVALIDPARAM
;
1110 if (This
->dsound
== NULL
) {
1111 WARN("invalid parameter: This->dsound == NULL\n");
1112 return DSERR_INVALIDPARAM
;
1115 if (dwSizeAllocated
> (sizeof(WAVEFORMATEX
) + This
->dsound
->pwfx
->cbSize
))
1116 dwSizeAllocated
= sizeof(WAVEFORMATEX
) + This
->dsound
->pwfx
->cbSize
;
1118 if (lpwfxFormat
) { /* NULL is valid (just want size) */
1119 CopyMemory(lpwfxFormat
, This
->dsound
->pwfx
, dwSizeAllocated
);
1120 if (lpdwSizeWritten
)
1121 *lpdwSizeWritten
= dwSizeAllocated
;
1123 if (lpdwSizeWritten
)
1124 *lpdwSizeWritten
= sizeof(WAVEFORMATEX
) + This
->dsound
->pwfx
->cbSize
;
1126 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
1127 hres
= DSERR_INVALIDPARAM
;
1131 TRACE("returning %08lx\n", hres
);
1135 static HRESULT WINAPI
1136 IDirectSoundCaptureBufferImpl_GetStatus(
1137 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1138 LPDWORD lpdwStatus
)
1140 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1141 TRACE( "(%p, %p), thread is %04lx\n", This
, lpdwStatus
, GetCurrentThreadId() );
1144 WARN("invalid parameter: This == NULL\n");
1145 return DSERR_INVALIDPARAM
;
1148 if (This
->dsound
== NULL
) {
1149 WARN("invalid parameter: This->dsound == NULL\n");
1150 return DSERR_INVALIDPARAM
;
1153 if (lpdwStatus
== NULL
) {
1154 WARN("invalid parameter: lpdwStatus == NULL\n");
1155 return DSERR_INVALIDPARAM
;
1159 EnterCriticalSection(&(This
->dsound
->lock
));
1161 TRACE("old This->dsound->state=%s, old lpdwStatus=%08lx\n",
1162 captureStateString
[This
->dsound
->state
],*lpdwStatus
);
1163 if ((This
->dsound
->state
== STATE_STARTING
) ||
1164 (This
->dsound
->state
== STATE_CAPTURING
)) {
1165 *lpdwStatus
|= DSCBSTATUS_CAPTURING
;
1166 if (This
->flags
& DSCBSTART_LOOPING
)
1167 *lpdwStatus
|= DSCBSTATUS_LOOPING
;
1169 TRACE("new This->dsound->state=%s, new lpdwStatus=%08lx\n",
1170 captureStateString
[This
->dsound
->state
],*lpdwStatus
);
1171 LeaveCriticalSection(&(This
->dsound
->lock
));
1173 TRACE("status=%lx\n", *lpdwStatus
);
1174 TRACE("returning DS_OK\n");
1178 static HRESULT WINAPI
1179 IDirectSoundCaptureBufferImpl_Initialize(
1180 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1181 LPDIRECTSOUNDCAPTURE lpDSC
,
1182 LPCDSCBUFFERDESC lpcDSCBDesc
)
1184 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1186 FIXME( "(%p,%p,%p): stub\n", This
, lpDSC
, lpcDSCBDesc
);
1191 static HRESULT WINAPI
1192 IDirectSoundCaptureBufferImpl_Lock(
1193 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1196 LPVOID
* lplpvAudioPtr1
,
1197 LPDWORD lpdwAudioBytes1
,
1198 LPVOID
* lplpvAudioPtr2
,
1199 LPDWORD lpdwAudioBytes2
,
1202 HRESULT hres
= DS_OK
;
1203 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1204 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This
, dwReadCusor
,
1205 dwReadBytes
, lplpvAudioPtr1
, lpdwAudioBytes1
, lplpvAudioPtr2
,
1206 lpdwAudioBytes2
, dwFlags
, GetTickCount() );
1209 WARN("invalid parameter: This == NULL\n");
1210 return DSERR_INVALIDPARAM
;
1213 if (This
->dsound
== NULL
) {
1214 WARN("invalid parameter: This->dsound == NULL\n");
1215 return DSERR_INVALIDPARAM
;
1218 if (lplpvAudioPtr1
== NULL
) {
1219 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1220 return DSERR_INVALIDPARAM
;
1223 if (lpdwAudioBytes1
== NULL
) {
1224 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1225 return DSERR_INVALIDPARAM
;
1228 EnterCriticalSection(&(This
->dsound
->lock
));
1230 if (This
->dsound
->driver
) {
1231 hres
= IDsCaptureDriverBuffer_Lock(This
->dsound
->hwbuf
, lplpvAudioPtr1
,
1232 lpdwAudioBytes1
, lplpvAudioPtr2
,
1233 lpdwAudioBytes2
, dwReadCusor
,
1234 dwReadBytes
, dwFlags
);
1236 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1237 } else if (This
->dsound
->hwi
) {
1238 *lplpvAudioPtr1
= This
->dsound
->buffer
+ dwReadCusor
;
1239 if ( (dwReadCusor
+ dwReadBytes
) > This
->dsound
->buflen
) {
1240 *lpdwAudioBytes1
= This
->dsound
->buflen
- dwReadCusor
;
1242 *lplpvAudioPtr2
= This
->dsound
->buffer
;
1243 if (lpdwAudioBytes2
)
1244 *lpdwAudioBytes2
= dwReadBytes
- *lpdwAudioBytes1
;
1246 *lpdwAudioBytes1
= dwReadBytes
;
1248 *lplpvAudioPtr2
= 0;
1249 if (lpdwAudioBytes2
)
1250 *lpdwAudioBytes2
= 0;
1253 TRACE("invalid call\n");
1254 hres
= DSERR_INVALIDCALL
; /* DSERR_NODRIVER ? */
1257 LeaveCriticalSection(&(This
->dsound
->lock
));
1259 TRACE("returning %08lx\n", hres
);
1263 static HRESULT WINAPI
1264 IDirectSoundCaptureBufferImpl_Start(
1265 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1268 HRESULT hres
= DS_OK
;
1269 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1270 TRACE( "(%p,0x%08lx)\n", This
, dwFlags
);
1273 WARN("invalid parameter: This == NULL\n");
1274 return DSERR_INVALIDPARAM
;
1277 if (This
->dsound
== NULL
) {
1278 WARN("invalid parameter: This->dsound == NULL\n");
1279 return DSERR_INVALIDPARAM
;
1282 if ( (This
->dsound
->driver
== 0) && (This
->dsound
->hwi
== 0) ) {
1283 WARN("no driver\n");
1284 return DSERR_NODRIVER
;
1287 EnterCriticalSection(&(This
->dsound
->lock
));
1289 This
->flags
= dwFlags
;
1290 TRACE("old This->dsound->state=%s\n",captureStateString
[This
->dsound
->state
]);
1291 if (This
->dsound
->state
== STATE_STOPPED
)
1292 This
->dsound
->state
= STATE_STARTING
;
1293 else if (This
->dsound
->state
== STATE_STOPPING
)
1294 This
->dsound
->state
= STATE_CAPTURING
;
1295 TRACE("new This->dsound->state=%s\n",captureStateString
[This
->dsound
->state
]);
1297 LeaveCriticalSection(&(This
->dsound
->lock
));
1299 if (This
->dsound
->driver
) {
1300 hres
= IDsCaptureDriverBuffer_Start(This
->dsound
->hwbuf
, dwFlags
);
1302 WARN("IDsCaptureDriverBuffer_Start failed\n");
1303 } else if (This
->dsound
->hwi
) {
1304 IDirectSoundCaptureImpl
* ipDSC
= This
->dsound
;
1306 if (ipDSC
->buffer
) {
1307 if (This
->nrofnotifies
) {
1310 ipDSC
->nrofpwaves
= This
->nrofnotifies
;
1311 TRACE("nrofnotifies=%d\n", This
->nrofnotifies
);
1313 /* prepare headers */
1315 ipDSC
->pwave
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->pwave
,
1316 ipDSC
->nrofpwaves
*sizeof(WAVEHDR
));
1318 ipDSC
->pwave
= HeapAlloc(GetProcessHeap(),0,
1319 ipDSC
->nrofpwaves
*sizeof(WAVEHDR
));
1321 for (c
= 0; c
< ipDSC
->nrofpwaves
; c
++) {
1322 if (This
->notifies
[c
].dwOffset
== DSBPN_OFFSETSTOP
) {
1323 TRACE("got DSBPN_OFFSETSTOP\n");
1324 ipDSC
->nrofpwaves
= c
;
1328 ipDSC
->pwave
[0].lpData
= ipDSC
->buffer
;
1329 ipDSC
->pwave
[0].dwBufferLength
=
1330 This
->notifies
[0].dwOffset
+ 1;
1332 ipDSC
->pwave
[c
].lpData
= ipDSC
->buffer
+
1333 This
->notifies
[c
-1].dwOffset
+ 1;
1334 ipDSC
->pwave
[c
].dwBufferLength
=
1335 This
->notifies
[c
].dwOffset
-
1336 This
->notifies
[c
-1].dwOffset
;
1338 ipDSC
->pwave
[c
].dwBytesRecorded
= 0;
1339 ipDSC
->pwave
[c
].dwUser
= (DWORD
)ipDSC
;
1340 ipDSC
->pwave
[c
].dwFlags
= 0;
1341 ipDSC
->pwave
[c
].dwLoops
= 0;
1342 hres
= mmErr(waveInPrepareHeader(ipDSC
->hwi
,
1343 &(ipDSC
->pwave
[c
]),sizeof(WAVEHDR
)));
1344 if (hres
!= DS_OK
) {
1345 WARN("waveInPrepareHeader failed\n");
1347 waveInUnprepareHeader(ipDSC
->hwi
,
1348 &(ipDSC
->pwave
[c
]),sizeof(WAVEHDR
));
1352 hres
= mmErr(waveInAddBuffer(ipDSC
->hwi
,
1353 &(ipDSC
->pwave
[c
]), sizeof(WAVEHDR
)));
1354 if (hres
!= DS_OK
) {
1355 WARN("waveInAddBuffer failed\n");
1357 waveInUnprepareHeader(ipDSC
->hwi
,
1358 &(ipDSC
->pwave
[c
]),sizeof(WAVEHDR
));
1363 FillMemory(ipDSC
->buffer
, ipDSC
->buflen
,
1364 (ipDSC
->pwfx
->wBitsPerSample
== 8) ? 128 : 0);
1366 TRACE("no notifiers specified\n");
1367 /* no notifiers specified so just create a single default header */
1368 ipDSC
->nrofpwaves
= 1;
1370 ipDSC
->pwave
= HeapReAlloc(GetProcessHeap(),0,ipDSC
->pwave
,sizeof(WAVEHDR
));
1372 ipDSC
->pwave
= HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR
));
1374 ipDSC
->pwave
[0].lpData
= ipDSC
->buffer
;
1375 ipDSC
->pwave
[0].dwBufferLength
= ipDSC
->buflen
;
1376 ipDSC
->pwave
[0].dwBytesRecorded
= 0;
1377 ipDSC
->pwave
[0].dwUser
= (DWORD
)ipDSC
;
1378 ipDSC
->pwave
[0].dwFlags
= 0;
1379 ipDSC
->pwave
[0].dwLoops
= 0;
1381 hres
= mmErr(waveInPrepareHeader(ipDSC
->hwi
,
1382 &(ipDSC
->pwave
[0]),sizeof(WAVEHDR
)));
1383 if (hres
!= DS_OK
) {
1384 WARN("waveInPrepareHeader failed\n");
1385 waveInUnprepareHeader(ipDSC
->hwi
,
1386 &(ipDSC
->pwave
[0]),sizeof(WAVEHDR
));
1388 hres
= mmErr(waveInAddBuffer(ipDSC
->hwi
,
1389 &(ipDSC
->pwave
[0]), sizeof(WAVEHDR
)));
1390 if (hres
!= DS_OK
) {
1391 WARN("waveInAddBuffer failed\n");
1392 waveInUnprepareHeader(ipDSC
->hwi
,
1393 &(ipDSC
->pwave
[0]),sizeof(WAVEHDR
));
1399 ipDSC
->read_position
= 0;
1401 if (hres
== DS_OK
) {
1402 /* start filling the first buffer */
1403 hres
= mmErr(waveInStart(ipDSC
->hwi
));
1405 WARN("waveInStart failed\n");
1408 if (hres
!= DS_OK
) {
1409 WARN("calling waveInClose because of error\n");
1410 waveInClose(This
->dsound
->hwi
);
1411 This
->dsound
->hwi
= 0;
1414 WARN("no driver\n");
1415 hres
= DSERR_NODRIVER
;
1418 TRACE("returning %08lx\n", hres
);
1422 static HRESULT WINAPI
1423 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface
)
1425 HRESULT hres
= DS_OK
;
1426 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1427 TRACE( "(%p)\n", This
);
1430 WARN("invalid parameter: This == NULL\n");
1431 return DSERR_INVALIDPARAM
;
1434 if (This
->dsound
== NULL
) {
1435 WARN("invalid parameter: This->dsound == NULL\n");
1436 return DSERR_INVALIDPARAM
;
1439 EnterCriticalSection(&(This
->dsound
->lock
));
1441 TRACE("old This->dsound->state=%s\n",captureStateString
[This
->dsound
->state
]);
1442 if (This
->dsound
->state
== STATE_CAPTURING
)
1443 This
->dsound
->state
= STATE_STOPPING
;
1444 else if (This
->dsound
->state
== STATE_STARTING
)
1445 This
->dsound
->state
= STATE_STOPPED
;
1446 TRACE("new This->dsound->state=%s\n",captureStateString
[This
->dsound
->state
]);
1448 LeaveCriticalSection(&(This
->dsound
->lock
));
1450 if (This
->dsound
->driver
) {
1451 hres
= IDsCaptureDriverBuffer_Stop(This
->dsound
->hwbuf
);
1453 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1454 } else if (This
->dsound
->hwi
) {
1455 hres
= mmErr(waveInReset(This
->dsound
->hwi
));
1457 WARN("waveInReset() failed\n");
1459 WARN("no driver\n");
1460 hres
= DSERR_NODRIVER
;
1463 TRACE("returning %08lx\n", hres
);
1467 static HRESULT WINAPI
1468 IDirectSoundCaptureBufferImpl_Unlock(
1469 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1470 LPVOID lpvAudioPtr1
,
1471 DWORD dwAudioBytes1
,
1472 LPVOID lpvAudioPtr2
,
1473 DWORD dwAudioBytes2
)
1475 HRESULT hres
= DS_OK
;
1476 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1477 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This
, lpvAudioPtr1
, dwAudioBytes1
,
1478 lpvAudioPtr2
, dwAudioBytes2
);
1481 WARN("invalid parameter: This == NULL\n");
1482 return DSERR_INVALIDPARAM
;
1485 if (lpvAudioPtr1
== NULL
) {
1486 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1487 return DSERR_INVALIDPARAM
;
1490 if (This
->dsound
->driver
) {
1491 hres
= IDsCaptureDriverBuffer_Unlock(This
->dsound
->hwbuf
, lpvAudioPtr1
,
1492 dwAudioBytes1
, lpvAudioPtr2
, dwAudioBytes2
);
1494 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1495 } else if (This
->dsound
->hwi
) {
1496 This
->dsound
->read_position
= (This
->dsound
->read_position
+
1497 (dwAudioBytes1
+ dwAudioBytes2
)) % This
->dsound
->buflen
;
1499 WARN("invalid call\n");
1500 hres
= DSERR_INVALIDCALL
;
1503 TRACE("returning %08lx\n", hres
);
1507 static HRESULT WINAPI
1508 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1509 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1510 REFGUID rguidObject
,
1512 REFGUID rguidInterface
,
1515 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1517 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This
, debugstr_guid(rguidObject
),
1518 dwIndex
, debugstr_guid(rguidInterface
), ppObject
);
1523 static HRESULT WINAPI
1524 IDirectSoundCaptureBufferImpl_GetFXStatus(
1525 LPDIRECTSOUNDCAPTUREBUFFER8 iface
,
1527 LPDWORD pdwFXStatus
)
1529 IDirectSoundCaptureBufferImpl
*This
= (IDirectSoundCaptureBufferImpl
*)iface
;
1531 FIXME( "(%p,%lu,%p): stub\n", This
, dwFXCount
, pdwFXStatus
);
1536 static IDirectSoundCaptureBuffer8Vtbl dscbvt
=
1538 /* IUnknown methods */
1539 IDirectSoundCaptureBufferImpl_QueryInterface
,
1540 IDirectSoundCaptureBufferImpl_AddRef
,
1541 IDirectSoundCaptureBufferImpl_Release
,
1543 /* IDirectSoundCaptureBuffer methods */
1544 IDirectSoundCaptureBufferImpl_GetCaps
,
1545 IDirectSoundCaptureBufferImpl_GetCurrentPosition
,
1546 IDirectSoundCaptureBufferImpl_GetFormat
,
1547 IDirectSoundCaptureBufferImpl_GetStatus
,
1548 IDirectSoundCaptureBufferImpl_Initialize
,
1549 IDirectSoundCaptureBufferImpl_Lock
,
1550 IDirectSoundCaptureBufferImpl_Start
,
1551 IDirectSoundCaptureBufferImpl_Stop
,
1552 IDirectSoundCaptureBufferImpl_Unlock
,
1554 /* IDirectSoundCaptureBuffer methods */
1555 IDirectSoundCaptureBufferImpl_GetObjectInPath
,
1556 IDirectSoundCaptureBufferImpl_GetFXStatus
1559 /*******************************************************************************
1560 * DirectSoundCapture ClassFactory
1563 static HRESULT WINAPI
1564 DSCCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
)
1566 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1568 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
1569 return E_NOINTERFACE
;
1573 DSCCF_AddRef(LPCLASSFACTORY iface
)
1575 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1576 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1577 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1582 DSCCF_Release(LPCLASSFACTORY iface
)
1584 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1585 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1586 TRACE("(%p) ref was %ld\n", This
, ref
+ 1);
1587 /* static class, won't be freed */
1591 static HRESULT WINAPI
1592 DSCCF_CreateInstance(
1593 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
)
1595 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1596 TRACE("(%p)->(%p,%s,%p)\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1599 WARN("aggregation not supported\n");
1600 return CLASS_E_NOAGGREGATION
;
1603 if (ppobj
== NULL
) {
1604 WARN("invalid parameter\n");
1605 return E_INVALIDARG
;
1610 if ( IsEqualGUID( &IID_IDirectSoundCapture8
, riid
) )
1611 return DirectSoundCaptureCreate8(0,(LPDIRECTSOUNDCAPTURE8
*)ppobj
,pOuter
);
1613 WARN("(%p,%p,%s,%p) Interface not found!\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1614 return E_NOINTERFACE
;
1617 static HRESULT WINAPI
1618 DSCCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
)
1620 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1621 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
1625 static IClassFactoryVtbl DSCCF_Vtbl
=
1627 DSCCF_QueryInterface
,
1630 DSCCF_CreateInstance
,
1634 IClassFactoryImpl DSOUND_CAPTURE_CF
= { &DSCCF_Vtbl
, 1 };
1636 /***************************************************************************
1637 * DirectSoundFullDuplexCreate [DSOUND.10]
1639 * Create and initialize a DirectSoundFullDuplex interface.
1642 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
1643 * pcGuidRenderDevice [I] Address of sound render device GUID.
1644 * pcDSCBufferDesc [I] Address of capture buffer description.
1645 * pcDSBufferDesc [I] Address of render buffer description.
1646 * hWnd [I] Handle to application window.
1647 * dwLevel [I] Cooperative level.
1648 * ppDSFD [O] Address where full duplex interface returned.
1649 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
1650 * ppDSBuffer8 [0] Address where render buffer interface returned.
1651 * pUnkOuter [I] Must be NULL.
1655 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1656 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
1659 DirectSoundFullDuplexCreate(
1660 LPCGUID pcGuidCaptureDevice
,
1661 LPCGUID pcGuidRenderDevice
,
1662 LPCDSCBUFFERDESC pcDSCBufferDesc
,
1663 LPCDSBUFFERDESC pcDSBufferDesc
,
1666 LPDIRECTSOUNDFULLDUPLEX
*ppDSFD
,
1667 LPDIRECTSOUNDCAPTUREBUFFER8
*ppDSCBuffer8
,
1668 LPDIRECTSOUNDBUFFER8
*ppDSBuffer8
,
1669 LPUNKNOWN pUnkOuter
)
1671 IDirectSoundFullDuplexImpl
** ippDSFD
=(IDirectSoundFullDuplexImpl
**)ppDSFD
;
1672 TRACE("(%s,%s,%p,%p,%lx,%lx,%p,%p,%p,%p)\n", debugstr_guid(pcGuidCaptureDevice
),
1673 debugstr_guid(pcGuidRenderDevice
), pcDSCBufferDesc
, pcDSBufferDesc
,
1674 (DWORD
)hWnd
, dwLevel
, ppDSFD
, ppDSCBuffer8
, ppDSBuffer8
, pUnkOuter
);
1677 WARN("pUnkOuter != 0\n");
1678 return DSERR_NOAGGREGATION
;
1681 *ippDSFD
= HeapAlloc(GetProcessHeap(),
1682 HEAP_ZERO_MEMORY
, sizeof(IDirectSoundFullDuplexImpl
));
1684 if (*ippDSFD
== NULL
) {
1685 WARN("out of memory\n");
1686 return DSERR_OUTOFMEMORY
;
1689 IDirectSoundFullDuplexImpl
*This
= (IDirectSoundFullDuplexImpl
*)*ippDSFD
;
1692 This
->lpVtbl
= &dsfdvt
;
1694 InitializeCriticalSection( &(This
->lock
) );
1695 This
->lock
.DebugInfo
->Spare
[1] = (DWORD
)"DSDUPLEX_lock";
1697 hres
= IDirectSoundFullDuplexImpl_Initialize( (LPDIRECTSOUNDFULLDUPLEX
)This
,
1698 pcGuidCaptureDevice
, pcGuidRenderDevice
,
1699 pcDSCBufferDesc
, pcDSBufferDesc
,
1700 hWnd
, dwLevel
, ppDSCBuffer8
, ppDSBuffer8
);
1702 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
1707 static HRESULT WINAPI
1708 IDirectSoundFullDuplexImpl_QueryInterface(
1709 LPDIRECTSOUNDFULLDUPLEX iface
,
1713 IDirectSoundFullDuplexImpl
*This
= (IDirectSoundFullDuplexImpl
*)iface
;
1714 TRACE( "(%p,%s,%p)\n", This
, debugstr_guid(riid
), ppobj
);
1716 if (ppobj
== NULL
) {
1717 WARN("invalid parameter\n");
1718 return E_INVALIDARG
;
1722 return E_NOINTERFACE
;
1726 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface
)
1728 IDirectSoundFullDuplexImpl
*This
= (IDirectSoundFullDuplexImpl
*)iface
;
1729 ULONG ref
= InterlockedIncrement(&(This
->ref
));
1730 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1735 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface
)
1737 IDirectSoundFullDuplexImpl
*This
= (IDirectSoundFullDuplexImpl
*)iface
;
1738 ULONG ref
= InterlockedDecrement(&(This
->ref
));
1739 TRACE("(%p) ref was %ld\n", This
, ref
- 1);
1742 This
->lock
.DebugInfo
->Spare
[1] = 0;
1743 DeleteCriticalSection( &(This
->lock
) );
1744 HeapFree( GetProcessHeap(), 0, This
);
1745 TRACE("(%p) released\n", This
);
1750 static HRESULT WINAPI
1751 IDirectSoundFullDuplexImpl_Initialize(
1752 LPDIRECTSOUNDFULLDUPLEX iface
,
1753 LPCGUID pCaptureGuid
,
1754 LPCGUID pRendererGuid
,
1755 LPCDSCBUFFERDESC lpDscBufferDesc
,
1756 LPCDSBUFFERDESC lpDsBufferDesc
,
1759 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8
,
1760 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8
)
1762 IDirectSoundFullDuplexImpl
*This
= (IDirectSoundFullDuplexImpl
*)iface
;
1763 IDirectSoundCaptureBufferImpl
** ippdscb
=(IDirectSoundCaptureBufferImpl
**)lplpDirectSoundCaptureBuffer8
;
1764 IDirectSoundBufferImpl
** ippdsc
=(IDirectSoundBufferImpl
**)lplpDirectSoundBuffer8
;
1766 FIXME( "(%p,%s,%s,%p,%p,%lx,%lx,%p,%p) stub!\n", This
, debugstr_guid(pCaptureGuid
),
1767 debugstr_guid(pRendererGuid
), lpDscBufferDesc
, lpDsBufferDesc
, (DWORD
)hWnd
, dwLevel
,
1773 static IDirectSoundFullDuplexVtbl dsfdvt
=
1775 /* IUnknown methods */
1776 IDirectSoundFullDuplexImpl_QueryInterface
,
1777 IDirectSoundFullDuplexImpl_AddRef
,
1778 IDirectSoundFullDuplexImpl_Release
,
1780 /* IDirectSoundFullDuplex methods */
1781 IDirectSoundFullDuplexImpl_Initialize
1784 /*******************************************************************************
1785 * DirectSoundFullDuplex ClassFactory
1788 static HRESULT WINAPI
1789 DSFDCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
)
1791 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1793 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
1794 return E_NOINTERFACE
;
1798 DSFDCF_AddRef(LPCLASSFACTORY iface
)
1800 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1801 TRACE("(%p) ref was %ld\n", This
, This
->ref
);
1802 return InterlockedIncrement(&(This
->ref
));
1806 DSFDCF_Release(LPCLASSFACTORY iface
)
1808 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1809 /* static class, won't be freed */
1810 TRACE("(%p) ref was %ld\n", This
, This
->ref
);
1811 return InterlockedDecrement(&(This
->ref
));
1814 static HRESULT WINAPI
1815 DSFDCF_CreateInstance(
1816 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
)
1818 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1820 TRACE("(%p)->(%p,%s,%p)\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1823 WARN("aggregation not supported\n");
1824 return CLASS_E_NOAGGREGATION
;
1827 if (ppobj
== NULL
) {
1828 WARN("invalid parameter\n");
1829 return E_INVALIDARG
;
1834 if ( IsEqualGUID( &IID_IDirectSoundFullDuplex
, riid
) ) {
1835 /* FIXME: how do we do this one ? */
1836 FIXME("not implemented\n");
1837 return E_NOINTERFACE
;
1840 WARN("(%p,%p,%s,%p) Interface not found!\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
1841 return E_NOINTERFACE
;
1844 static HRESULT WINAPI
1845 DSFDCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
)
1847 IClassFactoryImpl
*This
= (IClassFactoryImpl
*)iface
;
1848 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
1852 static IClassFactoryVtbl DSFDCF_Vtbl
=
1854 DSFDCF_QueryInterface
,
1857 DSFDCF_CreateInstance
,
1861 IClassFactoryImpl DSOUND_FULLDUPLEX_CF
= { &DSFDCF_Vtbl
, 1 };