Merge the MDI and common window creation code. Change the way MDI
[wine.git] / dlls / dsound / capture.c
blob4b3f9346337e7daac8e702180b09314a42aa2c08
1 /* DirectSoundCapture
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
22 * TODO:
23 * Implement DirectSoundFullDuplex support.
24 * Implement FX support.
27 #include "config.h"
28 #include <assert.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/fcntl.h>
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
36 #include <stdlib.h>
37 #include <string.h>
39 #include "windef.h"
40 #include "winbase.h"
41 #include "wingdi.h"
42 #include "winuser.h"
43 #include "winerror.h"
44 #include "mmsystem.h"
45 #include "mmddk.h"
46 #include "winreg.h"
47 #include "winternl.h"
48 #include "winnls.h"
49 #include "wine/debug.h"
50 #include "dsound.h"
51 #include "dsdriver.h"
52 #include "dsound_private.h"
54 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
56 static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(
57 LPDIRECTSOUNDCAPTURE iface,
58 LPCGUID lpcGUID );
59 static ULONG WINAPI IDirectSoundCaptureImpl_Release(
60 LPDIRECTSOUNDCAPTURE iface );
61 static ULONG WINAPI IDirectSoundCaptureBufferImpl_Release(
62 LPDIRECTSOUNDCAPTUREBUFFER8 iface );
63 static HRESULT DSOUND_CreateDirectSoundCaptureBuffer(
64 IDirectSoundCaptureImpl *ipDSC,
65 LPCDSCBUFFERDESC lpcDSCBufferDesc,
66 LPVOID* ppobj );
67 static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize(
68 LPDIRECTSOUNDFULLDUPLEX iface,
69 LPCGUID pCaptureGuid,
70 LPCGUID pRendererGuid,
71 LPCDSCBUFFERDESC lpDscBufferDesc,
72 LPCDSBUFFERDESC lpDsBufferDesc,
73 HWND hWnd,
74 DWORD dwLevel,
75 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
76 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 );
78 static ICOM_VTABLE(IDirectSoundCapture) dscvt;
79 static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt;
80 static ICOM_VTABLE(IDirectSoundFullDuplex) dsfdvt;
82 static IDirectSoundCaptureImpl* dsound_capture = NULL;
84 static const char * captureStateString[] = {
85 "STATE_STOPPED",
86 "STATE_STARTING",
87 "STATE_CAPTURING",
88 "STATE_STOPPING"
91 /***************************************************************************
92 * DirectSoundCaptureCreate [DSOUND.6]
94 * Create and initialize a DirectSoundCapture interface.
96 * PARAMS
97 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
98 * lplpDSC [O] Address of a variable to receive the interface pointer.
99 * pUnkOuter [I] Must be NULL.
101 * RETURNS
102 * Success: DS_OK
103 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
104 * DSERR_OUTOFMEMORY
106 * NOTES
107 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
108 * or NULL for the default device or DSDEVID_DefaultCapture or
109 * DSDEVID_DefaultVoiceCapture.
111 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
113 HRESULT WINAPI
114 DirectSoundCaptureCreate8(
115 LPCGUID lpcGUID,
116 LPDIRECTSOUNDCAPTURE* lplpDSC,
117 LPUNKNOWN pUnkOuter )
119 IDirectSoundCaptureImpl** ippDSC=(IDirectSoundCaptureImpl**)lplpDSC;
120 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter);
122 if ( pUnkOuter ) {
123 WARN("invalid parameter: pUnkOuter != NULL\n");
124 return DSERR_NOAGGREGATION;
127 if ( !lplpDSC ) {
128 WARN("invalid parameter: lplpDSC == NULL\n");
129 return DSERR_INVALIDPARAM;
132 /* Default device? */
133 if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
134 lpcGUID = &DSDEVID_DefaultCapture;
136 *ippDSC = (IDirectSoundCaptureImpl*)HeapAlloc(GetProcessHeap(),
137 HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureImpl));
139 if (*ippDSC == NULL) {
140 WARN("out of memory\n");
141 return DSERR_OUTOFMEMORY;
142 } else {
143 ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC);
145 This->ref = 1;
146 This->state = STATE_STOPPED;
148 InitializeCriticalSection( &(This->lock) );
150 This->lpVtbl = &dscvt;
151 dsound_capture = This;
153 if (GetDeviceID(lpcGUID, &This->guid) == DS_OK) {
154 HRESULT hres;
155 hres = IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE)This, &This->guid);
156 if (hres != DS_OK)
157 WARN("IDirectSoundCaptureImpl_Initialize failed\n");
158 return hres;
161 WARN("invalid GUID: %s\n", debugstr_guid(lpcGUID));
162 return DSERR_INVALIDPARAM;
165 /***************************************************************************
166 * DirectSoundCaptureEnumerateA [DSOUND.7]
168 * Enumerate all DirectSound drivers installed in the system.
170 * PARAMS
171 * lpDSEnumCallback [I] Address of callback function.
172 * lpContext [I] Address of user defined context passed to callback function.
174 * RETURNS
175 * Success: DS_OK
176 * Failure: DSERR_INVALIDPARAM
178 HRESULT WINAPI
179 DirectSoundCaptureEnumerateA(
180 LPDSENUMCALLBACKA lpDSEnumCallback,
181 LPVOID lpContext)
183 unsigned devs, wid;
184 DSDRIVERDESC desc;
185 GUID guid;
186 int err;
188 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
190 if (lpDSEnumCallback == NULL) {
191 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
192 return DSERR_INVALIDPARAM;
195 devs = waveInGetNumDevs();
196 if (devs > 0) {
197 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
198 GUID temp;
199 for (wid = 0; wid < devs; ++wid) {
200 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
201 if (err == DS_OK) {
202 if (IsEqualGUID( &guid, &temp ) ) {
203 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
204 if (err == DS_OK) {
205 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
206 "Primary Sound Capture Driver",desc.szDrvName,lpContext);
207 if (lpDSEnumCallback(NULL, "Primary Sound Capture Driver", desc.szDrvName, lpContext) == FALSE)
208 return DS_OK;
216 for (wid = 0; wid < devs; ++wid) {
217 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
218 if (err == DS_OK) {
219 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
220 if (err == DS_OK) {
221 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
222 debugstr_guid(&guid),desc.szDesc,desc.szDrvName,lpContext);
223 if (lpDSEnumCallback(&guid, desc.szDesc, desc.szDrvName, lpContext) == FALSE)
224 return DS_OK;
229 return DS_OK;
232 /***************************************************************************
233 * DirectSoundCaptureEnumerateW [DSOUND.8]
235 * Enumerate all DirectSound drivers installed in the system.
237 * PARAMS
238 * lpDSEnumCallback [I] Address of callback function.
239 * lpContext [I] Address of user defined context passed to callback function.
241 * RETURNS
242 * Success: DS_OK
243 * Failure: DSERR_INVALIDPARAM
245 HRESULT WINAPI
246 DirectSoundCaptureEnumerateW(
247 LPDSENUMCALLBACKW lpDSEnumCallback,
248 LPVOID lpContext)
250 unsigned devs, wid;
251 DSDRIVERDESC desc;
252 GUID guid;
253 int err;
254 WCHAR wDesc[MAXPNAMELEN];
255 WCHAR wName[MAXPNAMELEN];
257 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
259 if (lpDSEnumCallback == NULL) {
260 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
261 return DSERR_INVALIDPARAM;
264 devs = waveInGetNumDevs();
265 if (devs > 0) {
266 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
267 GUID temp;
268 for (wid = 0; wid < devs; ++wid) {
269 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
270 if (err == DS_OK) {
271 if (IsEqualGUID( &guid, &temp ) ) {
272 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
273 if (err == DS_OK) {
274 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
275 "Primary Sound Capture Driver",desc.szDrvName,lpContext);
276 MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
277 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
278 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
279 wName, sizeof(wName)/sizeof(WCHAR) );
280 if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
281 return DS_OK;
289 for (wid = 0; wid < devs; ++wid) {
290 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
291 if (err == DS_OK) {
292 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
293 if (err == DS_OK) {
294 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
295 debugstr_guid(&DSDEVID_DefaultCapture),desc.szDesc,desc.szDrvName,lpContext);
296 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
297 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
298 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
299 wName, sizeof(wName)/sizeof(WCHAR) );
300 if (lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, wDesc, wName, lpContext) == FALSE)
301 return DS_OK;
306 return DS_OK;
309 static void CALLBACK
310 DSOUND_capture_callback(
311 HWAVEIN hwi,
312 UINT msg,
313 DWORD dwUser,
314 DWORD dw1,
315 DWORD dw2 )
317 IDirectSoundCaptureImpl* This = (IDirectSoundCaptureImpl*)dwUser;
318 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi,msg,
319 msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
320 msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
322 if (msg == MM_WIM_DATA) {
323 EnterCriticalSection( &(This->lock) );
324 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
325 captureStateString[This->state],This->index);
326 if (This->state != STATE_STOPPED) {
327 int index = This->index;
328 if (This->state == STATE_STARTING) {
329 MMTIME mtime;
330 mtime.wType = TIME_BYTES;
331 waveInGetPosition(This->hwi, &mtime, sizeof(mtime));
332 TRACE("mtime.u.cb=%ld,This->buflen=%ld\n", mtime.u.cb, This->buflen);
333 mtime.u.cb = mtime.u.cb % This->buflen;
334 This->read_position = mtime.u.cb;
335 This->state = STATE_CAPTURING;
337 waveInUnprepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR));
338 if (This->capture_buffer->nrofnotifies)
339 SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
340 This->index = (This->index + 1) % This->nrofpwaves;
341 if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
342 TRACE("end of buffer\n");
343 This->state = STATE_STOPPED;
344 } else {
345 if (This->state == STATE_CAPTURING) {
346 waveInPrepareHeader(hwi,&(This->pwave[index]),sizeof(WAVEHDR));
347 waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
348 } else if (This->state == STATE_STOPPING) {
349 TRACE("stopping\n");
350 This->state = STATE_STOPPED;
354 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
355 captureStateString[This->state],This->index);
356 LeaveCriticalSection( &(This->lock) );
359 TRACE("completed\n");
362 static HRESULT WINAPI
363 IDirectSoundCaptureImpl_QueryInterface(
364 LPDIRECTSOUNDCAPTURE iface,
365 REFIID riid,
366 LPVOID* ppobj )
368 ICOM_THIS(IDirectSoundCaptureImpl,iface);
369 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
371 if (ppobj == NULL) {
372 WARN("invalid parameter\n");
373 return E_INVALIDARG;
376 *ppobj = NULL;
378 if (This->driver) {
379 HRESULT hres;
380 hres = IDsCaptureDriver_QueryInterface(This->driver, riid, ppobj);
381 if (hres != DS_OK)
382 WARN("IDsCaptureDriver_QueryInterface failed\n");
383 return hres;
386 WARN("unsupported riid: %s\n", debugstr_guid(riid));
387 return E_FAIL;
390 static ULONG WINAPI
391 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
393 ULONG uRef;
394 ICOM_THIS(IDirectSoundCaptureImpl,iface);
395 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
397 EnterCriticalSection( &(This->lock) );
398 uRef = ++(This->ref);
400 if (This->driver)
401 IDsCaptureDriver_AddRef(This->driver);
403 LeaveCriticalSection( &(This->lock) );
405 return uRef;
408 static ULONG WINAPI
409 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
411 ULONG uRef;
412 ICOM_THIS(IDirectSoundCaptureImpl,iface);
413 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
415 EnterCriticalSection( &(This->lock) );
417 uRef = --(This->ref);
419 LeaveCriticalSection( &(This->lock) );
421 if ( uRef == 0 ) {
422 TRACE("deleting object\n");
423 if (This->driver) {
424 IDsCaptureDriver_Close(This->driver);
425 IDsCaptureDriver_Release(This->driver);
428 if (This->capture_buffer)
429 IDirectSoundCaptureBufferImpl_Release(
430 (LPDIRECTSOUNDCAPTUREBUFFER8) This->capture_buffer);
432 if (This->pwfx)
433 HeapFree(GetProcessHeap(), 0, This->pwfx);
435 DeleteCriticalSection( &(This->lock) );
436 HeapFree( GetProcessHeap(), 0, This );
437 dsound_capture = NULL;
438 TRACE("(%p) released\n",This);
441 return uRef;
444 static HRESULT WINAPI
445 IDirectSoundCaptureImpl_CreateCaptureBuffer(
446 LPDIRECTSOUNDCAPTURE iface,
447 LPCDSCBUFFERDESC lpcDSCBufferDesc,
448 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
449 LPUNKNOWN pUnk )
451 HRESULT hr;
452 ICOM_THIS(IDirectSoundCaptureImpl,iface);
454 TRACE( "(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk );
456 if (This == NULL) {
457 WARN("invalid parameter: This == NULL\n");
458 return DSERR_INVALIDPARAM;
461 if (lpcDSCBufferDesc == NULL) {
462 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
463 return DSERR_INVALIDPARAM;
466 if (lplpDSCaptureBuffer == NULL) {
467 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
468 return DSERR_INVALIDPARAM;
471 if (pUnk != NULL) {
472 WARN("invalid parameter: pUnk != NULL\n");
473 return DSERR_INVALIDPARAM;
476 /* FIXME: We can only have one buffer so what do we do here? */
477 if (This->capture_buffer) {
478 WARN("lnvalid parameter: already has buffer\n");
479 return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */
482 hr = DSOUND_CreateDirectSoundCaptureBuffer( This, lpcDSCBufferDesc,
483 (LPVOID*)lplpDSCaptureBuffer );
485 if (hr != DS_OK)
486 WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n");
488 return hr;
491 static HRESULT WINAPI
492 IDirectSoundCaptureImpl_GetCaps(
493 LPDIRECTSOUNDCAPTURE iface,
494 LPDSCCAPS lpDSCCaps )
496 ICOM_THIS(IDirectSoundCaptureImpl,iface);
497 TRACE("(%p,%p)\n",This,lpDSCCaps);
499 if (lpDSCCaps== NULL) {
500 WARN("invalid parameter: lpDSCCaps== NULL\n");
501 return DSERR_INVALIDPARAM;
504 if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
505 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
506 lpDSCCaps->dwSize, sizeof(*lpDSCCaps));
507 return DSERR_INVALIDPARAM;
510 if ( !(This->initialized) ) {
511 WARN("not initialized\n");
512 return DSERR_UNINITIALIZED;
515 lpDSCCaps->dwFlags = This->drvcaps.dwFlags;
516 lpDSCCaps->dwFormats = This->drvcaps.dwFormats;
517 lpDSCCaps->dwChannels = This->drvcaps.dwChannels;
519 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps->dwFlags,
520 lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
522 return DS_OK;
525 static HRESULT WINAPI
526 IDirectSoundCaptureImpl_Initialize(
527 LPDIRECTSOUNDCAPTURE iface,
528 LPCGUID lpcGUID )
530 HRESULT err = DSERR_INVALIDPARAM;
531 unsigned wid, widn;
532 ICOM_THIS(IDirectSoundCaptureImpl,iface);
533 TRACE("(%p)\n", This);
535 if (!This) {
536 WARN("invalid parameter: This == NULL\n");
537 return DSERR_INVALIDPARAM;
540 if (This->initialized) {
541 WARN("already initialized\n");
542 return DSERR_ALREADYINITIALIZED;
545 widn = waveInGetNumDevs();
547 if (!widn) {
548 WARN("no audio devices found\n");
549 return DSERR_NODRIVER;
552 /* Get dsound configuration */
553 setup_dsound_options();
555 /* enumerate WINMM audio devices and find the one we want */
556 for (wid=0; wid<widn; wid++) {
557 GUID guid;
558 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
559 if (err != DS_OK) {
560 WARN("waveInMessage failed; err=%lx\n",err);
561 return err;
563 if (IsEqualGUID( lpcGUID, &guid) ) {
564 err = DS_OK;
565 break;
569 if (err != DS_OK) {
570 WARN("invalid parameter\n");
571 return DSERR_INVALIDPARAM;
574 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&(This->driver),0));
575 if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
576 WARN("waveInMessage failed; err=%lx\n",err);
577 return err;
579 err = DS_OK;
581 /* Disable the direct sound driver to force emulation if requested. */
582 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
583 This->driver = NULL;
585 /* Get driver description */
586 if (This->driver) {
587 TRACE("using DirectSound driver\n");
588 err = IDsCaptureDriver_GetDriverDesc(This->driver, &(This->drvdesc));
589 if (err != DS_OK) {
590 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
591 return err;
593 } else {
594 TRACE("using WINMM\n");
595 /* if no DirectSound interface available, use WINMM API instead */
596 This->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |
597 DSDDESC_DOMMSYSTEMSETFORMAT;
600 This->drvdesc.dnDevNode = wid;
602 /* open the DirectSound driver if available */
603 if (This->driver && (err == DS_OK))
604 err = IDsCaptureDriver_Open(This->driver);
606 if (err == DS_OK) {
607 This->initialized = TRUE;
609 /* the driver is now open, so it's now allowed to call GetCaps */
610 if (This->driver) {
611 This->drvcaps.dwSize = sizeof(This->drvcaps);
612 err = IDsCaptureDriver_GetCaps(This->driver,&(This->drvcaps));
613 if (err != DS_OK) {
614 WARN("IDsCaptureDriver_GetCaps failed\n");
615 return err;
617 } else /*if (This->hwi)*/ {
618 WAVEINCAPSA wic;
619 err = mmErr(waveInGetDevCapsA((UINT)This->drvdesc.dnDevNode, &wic, sizeof(wic)));
621 if (err == DS_OK) {
622 This->drvcaps.dwFlags = 0;
623 strncpy(This->drvdesc.szDrvName, wic.szPname,
624 sizeof(This->drvdesc.szDrvName));
626 This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
627 This->drvcaps.dwFormats = wic.dwFormats;
628 This->drvcaps.dwChannels = wic.wChannels;
633 return err;
636 static ICOM_VTABLE(IDirectSoundCapture) dscvt =
638 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
639 /* IUnknown methods */
640 IDirectSoundCaptureImpl_QueryInterface,
641 IDirectSoundCaptureImpl_AddRef,
642 IDirectSoundCaptureImpl_Release,
644 /* IDirectSoundCapture methods */
645 IDirectSoundCaptureImpl_CreateCaptureBuffer,
646 IDirectSoundCaptureImpl_GetCaps,
647 IDirectSoundCaptureImpl_Initialize
650 static HRESULT
651 DSOUND_CreateDirectSoundCaptureBuffer(
652 IDirectSoundCaptureImpl *ipDSC,
653 LPCDSCBUFFERDESC lpcDSCBufferDesc,
654 LPVOID* ppobj )
656 LPWAVEFORMATEX wfex;
657 TRACE( "(%p,%p)\n", lpcDSCBufferDesc, ppobj );
659 if (ipDSC == NULL) {
660 WARN("invalid parameter: ipDSC == NULL\n");
661 return DSERR_INVALIDPARAM;
664 if (lpcDSCBufferDesc == NULL) {
665 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
666 return DSERR_INVALIDPARAM;
669 if (ppobj == NULL) {
670 WARN("invalid parameter: ppobj == NULL\n");
671 return DSERR_INVALIDPARAM;
674 if ( (lpcDSCBufferDesc->dwSize < sizeof(DSCBUFFERDESC)) ||
675 (lpcDSCBufferDesc->dwBufferBytes == 0) ||
676 (lpcDSCBufferDesc->lpwfxFormat == NULL) ) {
677 WARN("invalid lpcDSCBufferDesc\n");
678 *ppobj = NULL;
679 return DSERR_INVALIDPARAM;
682 if ( !ipDSC->initialized ) {
683 WARN("not initialized\n");
684 *ppobj = NULL;
685 return DSERR_UNINITIALIZED;
688 wfex = lpcDSCBufferDesc->lpwfxFormat;
690 if (wfex) {
691 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
692 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
693 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
694 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
695 wfex->wBitsPerSample, wfex->cbSize);
697 if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
698 ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX));
699 memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX));
700 ipDSC->pwfx->cbSize = 0;
701 } else {
702 ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize);
703 memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize);
705 } else {
706 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
707 *ppobj = NULL;
708 return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */
711 *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
712 sizeof(IDirectSoundCaptureBufferImpl));
714 if ( *ppobj == NULL ) {
715 WARN("out of memory\n");
716 *ppobj = NULL;
717 return DSERR_OUTOFMEMORY;
718 } else {
719 HRESULT err = DS_OK;
720 ICOM_THIS(IDirectSoundCaptureBufferImpl,*ppobj);
722 This->ref = 1;
723 This->dsound = ipDSC;
724 This->dsound->capture_buffer = This;
725 This->notify = NULL;
726 This->nrofnotifies = 0;
727 This->hwnotify = NULL;
729 This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
730 lpcDSCBufferDesc->dwSize);
731 if (This->pdscbd)
732 memcpy(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
733 else {
734 WARN("no memory\n");
735 This->dsound->capture_buffer = 0;
736 HeapFree( GetProcessHeap(), 0, This );
737 *ppobj = NULL;
738 return DSERR_OUTOFMEMORY;
741 This->lpVtbl = &dscbvt;
743 if (ipDSC->driver) {
744 err = IDsCaptureDriver_CreateCaptureBuffer(ipDSC->driver,
745 ipDSC->pwfx,0,0,&(ipDSC->buflen),&(ipDSC->buffer),(LPVOID*)&(ipDSC->hwbuf));
746 if (err != DS_OK) {
747 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
748 This->dsound->capture_buffer = 0;
749 HeapFree( GetProcessHeap(), 0, This );
750 *ppobj = NULL;
751 return err;
753 } else {
754 LPBYTE newbuf;
755 DWORD buflen;
756 DWORD flags = CALLBACK_FUNCTION;
757 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
758 flags |= WAVE_DIRECTSOUND;
759 err = mmErr(waveInOpen(&(ipDSC->hwi),
760 ipDSC->drvdesc.dnDevNode, ipDSC->pwfx,
761 (DWORD)DSOUND_capture_callback, (DWORD)ipDSC, flags));
762 if (err != DS_OK) {
763 WARN("waveInOpen failed\n");
764 This->dsound->capture_buffer = 0;
765 HeapFree( GetProcessHeap(), 0, This );
766 *ppobj = NULL;
767 return err;
770 buflen = lpcDSCBufferDesc->dwBufferBytes;
771 TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->buffer);
772 if (ipDSC->buffer)
773 newbuf = (LPBYTE)HeapReAlloc(GetProcessHeap(),0,ipDSC->buffer,buflen);
774 else
775 newbuf = (LPBYTE)HeapAlloc(GetProcessHeap(),0,buflen);
776 if (newbuf == NULL) {
777 WARN("failed to allocate capture buffer\n");
778 err = DSERR_OUTOFMEMORY;
779 /* but the old buffer might still exist and must be re-prepared */
780 } else {
781 ipDSC->buffer = newbuf;
782 ipDSC->buflen = buflen;
787 TRACE("returning DS_OK\n");
788 return DS_OK;
791 /*******************************************************************************
792 * IDirectSoundCaptureNotify
794 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
795 LPDIRECTSOUNDNOTIFY iface,
796 REFIID riid,
797 LPVOID *ppobj)
799 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
800 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
802 if (This->dscb == NULL) {
803 WARN("invalid parameter\n");
804 return E_INVALIDARG;
807 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
810 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
812 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
813 DWORD ref;
815 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
817 ref = InterlockedIncrement(&(This->ref));
818 return ref;
821 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
823 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
824 DWORD ref;
826 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
828 ref = InterlockedDecrement(&(This->ref));
829 if (ref == 0) {
830 This->dscb->notify=NULL;
831 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
832 HeapFree(GetProcessHeap(),0,This);
833 TRACE("(%p) released\n",This);
835 return ref;
838 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
839 LPDIRECTSOUNDNOTIFY iface,
840 DWORD howmuch,
841 LPCDSBPOSITIONNOTIFY notify)
843 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
844 TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
846 if (notify == NULL) {
847 WARN("invalid parameter: notify == NULL\n");
848 return DSERR_INVALIDPARAM;
851 if (TRACE_ON(dsound)) {
852 int i;
853 for (i=0;i<howmuch;i++)
854 TRACE("notify at %ld to 0x%08lx\n",
855 notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
858 if (This->dscb->hwnotify) {
859 HRESULT hres;
860 hres = IDsDriverNotify_SetNotificationPositions(This->dscb->hwnotify, howmuch, notify);
861 if (hres != DS_OK)
862 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
863 return hres;
864 } else {
865 /* Make an internal copy of the caller-supplied array.
866 * Replace the existing copy if one is already present. */
867 if (This->dscb->notifies)
868 This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
869 This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
870 else
871 This->dscb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
872 howmuch * sizeof(DSBPOSITIONNOTIFY));
874 if (This->dscb->notifies == NULL) {
875 WARN("out of memory\n");
876 return DSERR_OUTOFMEMORY;
878 memcpy(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
879 This->dscb->nrofnotifies = howmuch;
882 return S_OK;
885 ICOM_VTABLE(IDirectSoundNotify) dscnvt =
887 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
888 IDirectSoundCaptureNotifyImpl_QueryInterface,
889 IDirectSoundCaptureNotifyImpl_AddRef,
890 IDirectSoundCaptureNotifyImpl_Release,
891 IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
894 HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create(
895 IDirectSoundCaptureBufferImpl *dscb,
896 IDirectSoundCaptureNotifyImpl **pdscn)
898 IDirectSoundCaptureNotifyImpl * dscn;
899 TRACE("(%p,%p)\n",dscb,pdscn);
901 dscn = (IDirectSoundCaptureNotifyImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dscn));
903 if (dscn == NULL) {
904 WARN("out of memory\n");
905 return DSERR_OUTOFMEMORY;
908 dscn->ref = 0;
909 dscn->lpVtbl = &dscnvt;
910 dscn->dscb = dscb;
911 dscb->notify = dscn;
912 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
914 *pdscn = dscn;
915 return DS_OK;
918 /*******************************************************************************
919 * IDirectSoundCaptureBuffer
921 static HRESULT WINAPI
922 IDirectSoundCaptureBufferImpl_QueryInterface(
923 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
924 REFIID riid,
925 LPVOID* ppobj )
927 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
928 HRESULT hres;
929 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
931 if (ppobj == NULL) {
932 WARN("invalid parameter\n");
933 return E_INVALIDARG;
936 *ppobj = NULL;
938 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ||
939 IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) {
940 if (!This->notify)
941 hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
942 if (This->notify) {
943 if (This->dsound->hwbuf) {
944 hres = IDsCaptureDriverBuffer_QueryInterface(This->dsound->hwbuf,
945 &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
946 if (hres != DS_OK) {
947 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
948 *ppobj = 0;
949 return hres;
953 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
954 *ppobj = (LPVOID)This->notify;
955 return DS_OK;
958 WARN("IID_IDirectSoundNotify\n");
959 return E_FAIL;
962 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
963 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
964 IDirectSoundCaptureBuffer8_AddRef(iface);
965 *ppobj = This;
966 return NO_ERROR;
969 FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
970 return E_NOINTERFACE;
973 static ULONG WINAPI
974 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
976 ULONG uRef;
977 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
978 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
980 assert(This->dsound);
982 EnterCriticalSection( &(This->dsound->lock) );
984 uRef = ++(This->ref);
986 LeaveCriticalSection( &(This->dsound->lock) );
988 return uRef;
991 static ULONG WINAPI
992 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
994 ULONG uRef;
995 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
996 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
998 assert(This->dsound);
1000 EnterCriticalSection( &(This->dsound->lock) );
1002 uRef = --(This->ref);
1004 LeaveCriticalSection( &(This->dsound->lock) );
1006 if ( uRef == 0 ) {
1007 TRACE("deleting object\n");
1008 if (This->pdscbd)
1009 HeapFree(GetProcessHeap(),0, This->pdscbd);
1011 if (This->dsound->hwi) {
1012 waveInReset(This->dsound->hwi);
1013 waveInClose(This->dsound->hwi);
1014 if (This->dsound->pwave) {
1015 HeapFree(GetProcessHeap(),0, This->dsound->pwave);
1016 This->dsound->pwave = 0;
1018 This->dsound->hwi = 0;
1021 if (This->dsound->hwbuf)
1022 IDsCaptureDriverBuffer_Release(This->dsound->hwbuf);
1024 /* remove from IDirectSoundCaptureImpl */
1025 if (This->dsound)
1026 This->dsound->capture_buffer = NULL;
1027 else
1028 ERR("does not reference dsound\n");
1030 if (This->notify)
1031 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
1033 if (This->notifies != NULL)
1034 HeapFree(GetProcessHeap(), 0, This->notifies);
1036 HeapFree( GetProcessHeap(), 0, This );
1037 TRACE("(%p) released\n",This);
1040 return uRef;
1043 static HRESULT WINAPI
1044 IDirectSoundCaptureBufferImpl_GetCaps(
1045 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1046 LPDSCBCAPS lpDSCBCaps )
1048 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1049 TRACE( "(%p,%p)\n", This, lpDSCBCaps );
1051 if (This == NULL) {
1052 WARN("invalid parameter: This == NULL\n");
1053 return DSERR_INVALIDPARAM;
1056 if (lpDSCBCaps == NULL) {
1057 WARN("invalid parameter: lpDSCBCaps == NULL\n");
1058 return DSERR_INVALIDPARAM;
1061 if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) {
1062 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
1063 lpDSCBCaps->dwSize, sizeof(DSCBCAPS));
1064 return DSERR_INVALIDPARAM;
1067 if (This->dsound == NULL) {
1068 WARN("invalid parameter: This->dsound == NULL\n");
1069 return DSERR_INVALIDPARAM;
1072 lpDSCBCaps->dwSize = sizeof(DSCBCAPS);
1073 lpDSCBCaps->dwFlags = This->flags;
1074 lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes;
1075 lpDSCBCaps->dwReserved = 0;
1077 TRACE("returning DS_OK\n");
1078 return DS_OK;
1081 static HRESULT WINAPI
1082 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
1083 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1084 LPDWORD lpdwCapturePosition,
1085 LPDWORD lpdwReadPosition )
1087 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1088 TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
1090 if (This == NULL) {
1091 WARN("invalid parameter: This == NULL\n");
1092 return DSERR_INVALIDPARAM;
1095 if (This->dsound == NULL) {
1096 WARN("invalid parameter: This->dsound == NULL\n");
1097 return DSERR_INVALIDPARAM;
1100 if (This->dsound->driver) {
1101 HRESULT hres;
1102 hres = IDsCaptureDriverBuffer_GetPosition(This->dsound->hwbuf, lpdwCapturePosition, lpdwReadPosition );
1103 if (hres != DS_OK) {
1104 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
1105 return hres;
1107 } else if (This->dsound->hwi) {
1108 EnterCriticalSection(&(This->dsound->lock));
1109 TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1110 if (lpdwCapturePosition) {
1111 MMTIME mtime;
1112 mtime.wType = TIME_BYTES;
1113 waveInGetPosition(This->dsound->hwi, &mtime, sizeof(mtime));
1114 TRACE("mtime.u.cb=%ld,This->dsound->buflen=%ld\n", mtime.u.cb,
1115 This->dsound->buflen);
1116 mtime.u.cb = mtime.u.cb % This->dsound->buflen;
1117 *lpdwCapturePosition = mtime.u.cb;
1120 if (lpdwReadPosition) {
1121 if (This->dsound->state == STATE_STARTING) {
1122 if (lpdwCapturePosition)
1123 This->dsound->read_position = *lpdwCapturePosition;
1124 This->dsound->state = STATE_CAPTURING;
1126 *lpdwReadPosition = This->dsound->read_position;
1128 TRACE("new This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1129 LeaveCriticalSection(&(This->dsound->lock));
1130 if (lpdwCapturePosition) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition);
1131 if (lpdwReadPosition) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition);
1132 } else {
1133 WARN("no driver\n");
1134 return DSERR_NODRIVER;
1137 TRACE("returning DS_OK\n");
1138 return DS_OK;
1141 static HRESULT WINAPI
1142 IDirectSoundCaptureBufferImpl_GetFormat(
1143 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1144 LPWAVEFORMATEX lpwfxFormat,
1145 DWORD dwSizeAllocated,
1146 LPDWORD lpdwSizeWritten )
1148 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1149 TRACE( "(%p,%p,0x%08lx,%p)\n", This, lpwfxFormat, dwSizeAllocated,
1150 lpdwSizeWritten );
1152 if (This == NULL) {
1153 WARN("invalid parameter: This == NULL\n");
1154 return DSERR_INVALIDPARAM;
1157 if (This->dsound == NULL) {
1158 WARN("invalid parameter: This->dsound == NULL\n");
1159 return DSERR_INVALIDPARAM;
1162 if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize))
1163 dwSizeAllocated = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
1165 if (lpwfxFormat) { /* NULL is valid (just want size) */
1166 memcpy(lpwfxFormat, This->dsound->pwfx, dwSizeAllocated);
1167 if (lpdwSizeWritten)
1168 *lpdwSizeWritten = dwSizeAllocated;
1169 } else {
1170 if (lpdwSizeWritten)
1171 *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
1172 else {
1173 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
1174 return DSERR_INVALIDPARAM;
1178 TRACE("returning DS_OK\n");
1179 return DS_OK;
1182 static HRESULT WINAPI
1183 IDirectSoundCaptureBufferImpl_GetStatus(
1184 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1185 LPDWORD lpdwStatus )
1187 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1188 TRACE( "(%p, %p), thread is %04lx\n", This, lpdwStatus, GetCurrentThreadId() );
1190 if (This == NULL) {
1191 WARN("invalid parameter: This == NULL\n");
1192 return DSERR_INVALIDPARAM;
1195 if (This->dsound == NULL) {
1196 WARN("invalid parameter: This->dsound == NULL\n");
1197 return DSERR_INVALIDPARAM;
1200 if (lpdwStatus == NULL) {
1201 WARN("invalid parameter: lpdwStatus == NULL\n");
1202 return DSERR_INVALIDPARAM;
1205 *lpdwStatus = 0;
1206 EnterCriticalSection(&(This->dsound->lock));
1208 TRACE("old This->dsound->state=%s, old lpdwStatus=%08lx\n",
1209 captureStateString[This->dsound->state],*lpdwStatus);
1210 if ((This->dsound->state == STATE_STARTING) ||
1211 (This->dsound->state == STATE_CAPTURING)) {
1212 *lpdwStatus |= DSCBSTATUS_CAPTURING;
1213 if (This->flags & DSCBSTART_LOOPING)
1214 *lpdwStatus |= DSCBSTATUS_LOOPING;
1216 TRACE("new This->dsound->state=%s, new lpdwStatus=%08lx\n",
1217 captureStateString[This->dsound->state],*lpdwStatus);
1218 LeaveCriticalSection(&(This->dsound->lock));
1220 TRACE("status=%lx\n", *lpdwStatus);
1221 TRACE("returning DS_OK\n");
1222 return DS_OK;
1225 static HRESULT WINAPI
1226 IDirectSoundCaptureBufferImpl_Initialize(
1227 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1228 LPDIRECTSOUNDCAPTURE lpDSC,
1229 LPCDSCBUFFERDESC lpcDSCBDesc )
1231 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1233 FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
1235 return DS_OK;
1238 static HRESULT WINAPI
1239 IDirectSoundCaptureBufferImpl_Lock(
1240 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1241 DWORD dwReadCusor,
1242 DWORD dwReadBytes,
1243 LPVOID* lplpvAudioPtr1,
1244 LPDWORD lpdwAudioBytes1,
1245 LPVOID* lplpvAudioPtr2,
1246 LPDWORD lpdwAudioBytes2,
1247 DWORD dwFlags )
1249 HRESULT err = DS_OK;
1250 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1251 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This, dwReadCusor,
1252 dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
1253 lpdwAudioBytes2, dwFlags, GetTickCount() );
1255 if (This == NULL) {
1256 WARN("invalid parameter: This == NULL\n");
1257 return DSERR_INVALIDPARAM;
1260 if (This->dsound == NULL) {
1261 WARN("invalid parameter: This->dsound == NULL\n");
1262 return DSERR_INVALIDPARAM;
1265 if (lplpvAudioPtr1 == NULL) {
1266 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1267 return DSERR_INVALIDPARAM;
1270 if (lpdwAudioBytes1 == NULL) {
1271 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1272 return DSERR_INVALIDPARAM;
1275 EnterCriticalSection(&(This->dsound->lock));
1277 if (This->dsound->driver) {
1278 err = IDsCaptureDriverBuffer_Lock(This->dsound->hwbuf, lplpvAudioPtr1,
1279 lpdwAudioBytes1, lplpvAudioPtr2, lpdwAudioBytes2,
1280 dwReadCusor, dwReadBytes, dwFlags);
1281 if (err != DS_OK)
1282 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1283 } else if (This->dsound->hwi) {
1284 *lplpvAudioPtr1 = This->dsound->buffer + dwReadCusor;
1285 if ( (dwReadCusor + dwReadBytes) > This->dsound->buflen) {
1286 *lpdwAudioBytes1 = This->dsound->buflen - dwReadCusor;
1287 if (lplpvAudioPtr2)
1288 *lplpvAudioPtr2 = This->dsound->buffer;
1289 if (lpdwAudioBytes2)
1290 *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
1291 } else {
1292 *lpdwAudioBytes1 = dwReadBytes;
1293 if (lplpvAudioPtr2)
1294 *lplpvAudioPtr2 = 0;
1295 if (lpdwAudioBytes2)
1296 *lpdwAudioBytes2 = 0;
1298 } else {
1299 TRACE("invalid call\n");
1300 err = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */
1303 LeaveCriticalSection(&(This->dsound->lock));
1305 return err;
1308 static HRESULT WINAPI
1309 IDirectSoundCaptureBufferImpl_Start(
1310 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1311 DWORD dwFlags )
1313 HRESULT err = DS_OK;
1314 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1315 TRACE( "(%p,0x%08lx)\n", This, dwFlags );
1317 if (This == NULL) {
1318 WARN("invalid parameter: This == NULL\n");
1319 return DSERR_INVALIDPARAM;
1322 if (This->dsound == NULL) {
1323 WARN("invalid parameter: This->dsound == NULL\n");
1324 return DSERR_INVALIDPARAM;
1327 if ( (This->dsound->driver == 0) && (This->dsound->hwi == 0) ) {
1328 WARN("no driver\n");
1329 return DSERR_NODRIVER;
1332 EnterCriticalSection(&(This->dsound->lock));
1334 This->flags = dwFlags;
1335 TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1336 if (This->dsound->state == STATE_STOPPED)
1337 This->dsound->state = STATE_STARTING;
1338 else if (This->dsound->state == STATE_STOPPING)
1339 This->dsound->state = STATE_CAPTURING;
1340 TRACE("new This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1342 LeaveCriticalSection(&(This->dsound->lock));
1344 if (This->dsound->driver) {
1345 err = IDsCaptureDriverBuffer_Start(This->dsound->hwbuf, dwFlags);
1346 if (err != DS_OK)
1347 WARN("IDsCaptureDriverBuffer_Start failed\n");
1348 return err;
1349 } else {
1350 IDirectSoundCaptureImpl* ipDSC = This->dsound;
1352 if (ipDSC->buffer) {
1353 if (This->nrofnotifies) {
1354 unsigned c;
1356 ipDSC->nrofpwaves = This->nrofnotifies;
1357 TRACE("nrofnotifies=%d\n", This->nrofnotifies);
1359 /* prepare headers */
1360 if (ipDSC->pwave)
1361 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,
1362 ipDSC->nrofpwaves*sizeof(WAVEHDR));
1363 else
1364 ipDSC->pwave = HeapAlloc(GetProcessHeap(),0,
1365 ipDSC->nrofpwaves*sizeof(WAVEHDR));
1367 for (c = 0; c < ipDSC->nrofpwaves; c++) {
1368 if (c == 0) {
1369 ipDSC->pwave[0].lpData = ipDSC->buffer;
1370 ipDSC->pwave[0].dwBufferLength =
1371 This->notifies[0].dwOffset + 1;
1372 } else {
1373 ipDSC->pwave[c].lpData = ipDSC->buffer +
1374 This->notifies[c-1].dwOffset + 1;
1375 ipDSC->pwave[c].dwBufferLength =
1376 This->notifies[c].dwOffset -
1377 This->notifies[c-1].dwOffset;
1379 ipDSC->pwave[c].dwUser = (DWORD)ipDSC;
1380 ipDSC->pwave[c].dwFlags = 0;
1381 ipDSC->pwave[c].dwLoops = 0;
1382 err = mmErr(waveInPrepareHeader(ipDSC->hwi,
1383 &(ipDSC->pwave[c]),sizeof(WAVEHDR)));
1384 if (err != DS_OK) {
1385 while (c--)
1386 waveInUnprepareHeader(ipDSC->hwi,
1387 &(ipDSC->pwave[c]),sizeof(WAVEHDR));
1388 break;
1391 err = mmErr(waveInAddBuffer(ipDSC->hwi,
1392 &(ipDSC->pwave[c]), sizeof(WAVEHDR)));
1393 if (err != DS_OK) {
1394 while (c--)
1395 waveInUnprepareHeader(ipDSC->hwi,
1396 &(ipDSC->pwave[c]),sizeof(WAVEHDR));
1397 break;
1401 memset(ipDSC->buffer,
1402 (ipDSC->pwfx->wBitsPerSample == 8) ? 128 : 0, ipDSC->buflen);
1403 } else {
1404 TRACE("no notifiers specified\n");
1405 /* no notifiers specified so just create a single default header */
1406 ipDSC->nrofpwaves = 1;
1407 if (ipDSC->pwave)
1408 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,sizeof(WAVEHDR));
1409 else
1410 ipDSC->pwave = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR));
1412 ipDSC->pwave[0].lpData = ipDSC->buffer;
1413 ipDSC->pwave[0].dwBufferLength = ipDSC->buflen;
1414 ipDSC->pwave[0].dwUser = (DWORD)ipDSC;
1415 ipDSC->pwave[0].dwFlags = 0;
1416 ipDSC->pwave[0].dwLoops = 0;
1418 err = mmErr(waveInPrepareHeader(ipDSC->hwi,
1419 &(ipDSC->pwave[0]),sizeof(WAVEHDR)));
1420 if (err != DS_OK) {
1421 WARN("waveInPrepareHeader failed\n");
1422 waveInUnprepareHeader(ipDSC->hwi,
1423 &(ipDSC->pwave[0]),sizeof(WAVEHDR));
1425 err = mmErr(waveInAddBuffer(ipDSC->hwi,
1426 &(ipDSC->pwave[0]), sizeof(WAVEHDR)));
1427 if (err != DS_OK) {
1428 waveInUnprepareHeader(ipDSC->hwi,
1429 &(ipDSC->pwave[0]),sizeof(WAVEHDR));
1434 ipDSC->index = 0;
1435 ipDSC->read_position = 0;
1437 if (err == DS_OK) {
1438 /* start filling the first buffer */
1439 err = mmErr(waveInStart(ipDSC->hwi));
1443 if (err != DS_OK) {
1444 WARN("calling waveInClose because of error\n");
1445 waveInClose(This->dsound->hwi);
1446 This->dsound->hwi = 0;
1449 TRACE("returning %ld\n", err);
1450 return err;
1453 static HRESULT WINAPI
1454 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
1456 HRESULT err = DS_OK;
1457 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1458 TRACE( "(%p)\n", This );
1460 if (This == NULL) {
1461 WARN("invalid parameter: This == NULL\n");
1462 return DSERR_INVALIDPARAM;
1465 if (This->dsound == NULL) {
1466 WARN("invalid parameter: This->dsound == NULL\n");
1467 return DSERR_INVALIDPARAM;
1470 EnterCriticalSection(&(This->dsound->lock));
1472 TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1473 if (This->dsound->state == STATE_CAPTURING)
1474 This->dsound->state = STATE_STOPPING;
1475 else if (This->dsound->state == STATE_STARTING)
1476 This->dsound->state = STATE_STOPPED;
1477 TRACE("new This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1479 LeaveCriticalSection(&(This->dsound->lock));
1481 if (This->dsound->driver) {
1482 err = IDsCaptureDriverBuffer_Stop(This->dsound->hwbuf);
1483 if (err == DSERR_BUFFERLOST) {
1484 /* Wine-only: the driver wants us to reopen the device */
1485 IDsCaptureDriverBuffer_Release(This->dsound->hwbuf);
1486 err = IDsCaptureDriver_CreateCaptureBuffer(This->dsound->driver,
1487 This->dsound->pwfx,0,0,&(This->dsound->buflen),&(This->dsound->buffer),
1488 (LPVOID*)&(This->dsound->hwbuf));
1489 if (err != DS_OK) {
1490 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1491 This->dsound->hwbuf = 0;
1493 } else if (err != DS_OK)
1494 WARN("IDsCaptureDriverBuffer_Stop failed\n");
1495 } else if (This->dsound->hwi) {
1496 err = waveInStop(This->dsound->hwi);
1497 } else {
1498 WARN("no driver\n");
1499 err = DSERR_NODRIVER;
1502 TRACE( "(%p) returning 0x%08lx\n", This,err);
1503 return err;
1506 static HRESULT WINAPI
1507 IDirectSoundCaptureBufferImpl_Unlock(
1508 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1509 LPVOID lpvAudioPtr1,
1510 DWORD dwAudioBytes1,
1511 LPVOID lpvAudioPtr2,
1512 DWORD dwAudioBytes2 )
1514 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1515 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This, lpvAudioPtr1, dwAudioBytes1,
1516 lpvAudioPtr2, dwAudioBytes2 );
1518 if (This == NULL) {
1519 WARN("invalid parameter: This == NULL\n");
1520 return DSERR_INVALIDPARAM;
1523 if (lpvAudioPtr1 == NULL) {
1524 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1525 return DSERR_INVALIDPARAM;
1528 if (This->dsound->driver) {
1529 HRESULT hres;
1530 hres = IDsCaptureDriverBuffer_Unlock(This->dsound->hwbuf, lpvAudioPtr1,
1531 dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
1532 if (hres != DS_OK)
1533 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1534 return hres;
1535 } else if (This->dsound->hwi) {
1536 This->dsound->read_position = (This->dsound->read_position +
1537 (dwAudioBytes1 + dwAudioBytes2)) % This->dsound->buflen;
1538 } else {
1539 WARN("invalid call\n");
1540 return DSERR_INVALIDCALL;
1543 return DS_OK;
1546 static HRESULT WINAPI
1547 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1548 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1549 REFGUID rguidObject,
1550 DWORD dwIndex,
1551 REFGUID rguidInterface,
1552 LPVOID* ppObject )
1554 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1556 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject),
1557 dwIndex, debugstr_guid(rguidInterface), ppObject );
1559 return DS_OK;
1562 static HRESULT WINAPI
1563 IDirectSoundCaptureBufferImpl_GetFXStatus(
1564 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1565 DWORD dwFXCount,
1566 LPDWORD pdwFXStatus )
1568 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1570 FIXME( "(%p,%lu,%p): stub\n", This, dwFXCount, pdwFXStatus );
1572 return DS_OK;
1575 static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt =
1577 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1578 /* IUnknown methods */
1579 IDirectSoundCaptureBufferImpl_QueryInterface,
1580 IDirectSoundCaptureBufferImpl_AddRef,
1581 IDirectSoundCaptureBufferImpl_Release,
1583 /* IDirectSoundCaptureBuffer methods */
1584 IDirectSoundCaptureBufferImpl_GetCaps,
1585 IDirectSoundCaptureBufferImpl_GetCurrentPosition,
1586 IDirectSoundCaptureBufferImpl_GetFormat,
1587 IDirectSoundCaptureBufferImpl_GetStatus,
1588 IDirectSoundCaptureBufferImpl_Initialize,
1589 IDirectSoundCaptureBufferImpl_Lock,
1590 IDirectSoundCaptureBufferImpl_Start,
1591 IDirectSoundCaptureBufferImpl_Stop,
1592 IDirectSoundCaptureBufferImpl_Unlock,
1594 /* IDirectSoundCaptureBuffer methods */
1595 IDirectSoundCaptureBufferImpl_GetObjectInPath,
1596 IDirectSoundCaptureBufferImpl_GetFXStatus
1599 /*******************************************************************************
1600 * DirectSoundCapture ClassFactory
1603 static HRESULT WINAPI
1604 DSCCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1606 ICOM_THIS(IClassFactoryImpl,iface);
1608 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1609 return E_NOINTERFACE;
1612 static ULONG WINAPI
1613 DSCCF_AddRef(LPCLASSFACTORY iface)
1615 ICOM_THIS(IClassFactoryImpl,iface);
1616 TRACE("(%p) ref was %ld\n", This, This->ref);
1617 return ++(This->ref);
1620 static ULONG WINAPI
1621 DSCCF_Release(LPCLASSFACTORY iface)
1623 ICOM_THIS(IClassFactoryImpl,iface);
1624 /* static class, won't be freed */
1625 TRACE("(%p) ref was %ld\n", This, This->ref);
1626 return --(This->ref);
1629 static HRESULT WINAPI
1630 DSCCF_CreateInstance(
1631 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1633 ICOM_THIS(IClassFactoryImpl,iface);
1634 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1636 if (ppobj == NULL) {
1637 WARN("invalid parameter\n");
1638 return E_INVALIDARG;
1641 *ppobj = NULL;
1643 if ( IsEqualGUID( &IID_IDirectSoundCapture, riid ) ||
1644 IsEqualGUID( &IID_IDirectSoundCapture8, riid ) ) {
1645 return DirectSoundCaptureCreate8(0,(LPDIRECTSOUNDCAPTURE8*)ppobj,pOuter);
1648 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1649 return E_NOINTERFACE;
1652 static HRESULT WINAPI
1653 DSCCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1655 ICOM_THIS(IClassFactoryImpl,iface);
1656 FIXME("(%p)->(%d),stub!\n",This,dolock);
1657 return S_OK;
1660 static ICOM_VTABLE(IClassFactory) DSCCF_Vtbl =
1662 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1663 DSCCF_QueryInterface,
1664 DSCCF_AddRef,
1665 DSCCF_Release,
1666 DSCCF_CreateInstance,
1667 DSCCF_LockServer
1670 IClassFactoryImpl DSOUND_CAPTURE_CF = { &DSCCF_Vtbl, 1 };
1672 /***************************************************************************
1673 * DirectSoundFullDuplexCreate8 [DSOUND.10]
1675 * Create and initialize a DirectSoundFullDuplex interface.
1677 * PARAMS
1678 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
1679 * pcGuidRenderDevice [I] Address of sound render device GUID.
1680 * pcDSCBufferDesc [I] Address of capture buffer description.
1681 * pcDSBufferDesc [I] Address of render buffer description.
1682 * hWnd [I] Handle to application window.
1683 * dwLevel [I] Cooperative level.
1684 * ppDSFD [O] Address where full duplex interface returned.
1685 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
1686 * ppDSBuffer8 [0] Address where render buffer interface returned.
1687 * pUnkOuter [I] Must be NULL.
1689 * RETURNS
1690 * Success: DS_OK
1691 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1692 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
1694 HRESULT WINAPI
1695 DirectSoundFullDuplexCreate8(
1696 LPCGUID pcGuidCaptureDevice,
1697 LPCGUID pcGuidRenderDevice,
1698 LPCDSCBUFFERDESC pcDSCBufferDesc,
1699 LPCDSBUFFERDESC pcDSBufferDesc,
1700 HWND hWnd,
1701 DWORD dwLevel,
1702 LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
1703 LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
1704 LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
1705 LPUNKNOWN pUnkOuter)
1707 IDirectSoundFullDuplexImpl** ippDSFD=(IDirectSoundFullDuplexImpl**)ppDSFD;
1708 TRACE("(%s,%s,%p,%p,%lx,%lx,%p,%p,%p,%p)\n", debugstr_guid(pcGuidCaptureDevice),
1709 debugstr_guid(pcGuidRenderDevice), pcDSCBufferDesc, pcDSBufferDesc,
1710 (DWORD)hWnd, dwLevel, ppDSFD, ppDSCBuffer8, ppDSBuffer8, pUnkOuter);
1712 if ( pUnkOuter ) {
1713 WARN("pUnkOuter != 0\n");
1714 return DSERR_NOAGGREGATION;
1717 *ippDSFD = (IDirectSoundFullDuplexImpl*)HeapAlloc(GetProcessHeap(),
1718 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
1720 if (*ippDSFD == NULL) {
1721 WARN("out of memory\n");
1722 return DSERR_OUTOFMEMORY;
1723 } else {
1724 HRESULT hres;
1725 ICOM_THIS(IDirectSoundFullDuplexImpl, *ippDSFD);
1727 This->ref = 1;
1728 This->lpVtbl = &dsfdvt;
1730 InitializeCriticalSection( &(This->lock) );
1732 hres = IDirectSoundFullDuplexImpl_Initialize( (LPDIRECTSOUNDFULLDUPLEX)This,
1733 pcGuidCaptureDevice, pcGuidRenderDevice,
1734 pcDSCBufferDesc, pcDSBufferDesc,
1735 hWnd, dwLevel, ppDSCBuffer8, ppDSBuffer8);
1736 if (hres != DS_OK)
1737 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
1738 return hres;
1741 return DSERR_GENERIC;
1744 static HRESULT WINAPI
1745 IDirectSoundFullDuplexImpl_QueryInterface(
1746 LPDIRECTSOUNDFULLDUPLEX iface,
1747 REFIID riid,
1748 LPVOID* ppobj )
1750 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1751 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
1753 if (ppobj == NULL) {
1754 WARN("invalid parameter\n");
1755 return E_INVALIDARG;
1758 *ppobj = NULL;
1759 return E_NOINTERFACE;
1762 static ULONG WINAPI
1763 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
1765 ULONG uRef;
1766 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1767 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1769 EnterCriticalSection( &(This->lock) );
1771 uRef = ++(This->ref);
1773 LeaveCriticalSection( &(This->lock) );
1775 return uRef;
1778 static ULONG WINAPI
1779 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
1781 ULONG uRef;
1782 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1783 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1785 EnterCriticalSection( &(This->lock) );
1787 uRef = --(This->ref);
1789 LeaveCriticalSection( &(This->lock) );
1791 if ( uRef == 0 ) {
1792 DeleteCriticalSection( &(This->lock) );
1793 HeapFree( GetProcessHeap(), 0, This );
1794 TRACE("(%p) released\n",This);
1797 return uRef;
1800 static HRESULT WINAPI
1801 IDirectSoundFullDuplexImpl_Initialize(
1802 LPDIRECTSOUNDFULLDUPLEX iface,
1803 LPCGUID pCaptureGuid,
1804 LPCGUID pRendererGuid,
1805 LPCDSCBUFFERDESC lpDscBufferDesc,
1806 LPCDSBUFFERDESC lpDsBufferDesc,
1807 HWND hWnd,
1808 DWORD dwLevel,
1809 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
1810 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
1812 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1813 IDirectSoundCaptureBufferImpl** ippdscb=(IDirectSoundCaptureBufferImpl**)lplpDirectSoundCaptureBuffer8;
1814 IDirectSoundBufferImpl** ippdsc=(IDirectSoundBufferImpl**)lplpDirectSoundBuffer8;
1816 FIXME( "(%p,%s,%s,%p,%p,%lx,%lx,%p,%p) stub!\n", This, debugstr_guid(pCaptureGuid),
1817 debugstr_guid(pRendererGuid), lpDscBufferDesc, lpDsBufferDesc, (DWORD)hWnd, dwLevel,
1818 ippdscb, ippdsc);
1820 return E_FAIL;
1823 static ICOM_VTABLE(IDirectSoundFullDuplex) dsfdvt =
1825 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1826 /* IUnknown methods */
1827 IDirectSoundFullDuplexImpl_QueryInterface,
1828 IDirectSoundFullDuplexImpl_AddRef,
1829 IDirectSoundFullDuplexImpl_Release,
1831 /* IDirectSoundFullDuplex methods */
1832 IDirectSoundFullDuplexImpl_Initialize
1835 /*******************************************************************************
1836 * DirectSoundFullDuplex ClassFactory
1839 static HRESULT WINAPI
1840 DSFDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1842 ICOM_THIS(IClassFactoryImpl,iface);
1844 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1845 return E_NOINTERFACE;
1848 static ULONG WINAPI
1849 DSFDCF_AddRef(LPCLASSFACTORY iface)
1851 ICOM_THIS(IClassFactoryImpl,iface);
1852 TRACE("(%p) ref was %ld\n", This, This->ref);
1853 return ++(This->ref);
1856 static ULONG WINAPI
1857 DSFDCF_Release(LPCLASSFACTORY iface)
1859 ICOM_THIS(IClassFactoryImpl,iface);
1860 /* static class, won't be freed */
1861 TRACE("(%p) ref was %ld\n", This, This->ref);
1862 return --(This->ref);
1865 static HRESULT WINAPI
1866 DSFDCF_CreateInstance(
1867 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1869 ICOM_THIS(IClassFactoryImpl,iface);
1871 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1873 if (ppobj == NULL) {
1874 WARN("invalid parameter\n");
1875 return E_INVALIDARG;
1878 *ppobj = NULL;
1880 if ( IsEqualGUID( &IID_IDirectSoundFullDuplex, riid ) ) {
1881 /* FIXME: how do we do this one ? */
1882 FIXME("not implemented\n");
1883 return E_NOINTERFACE;
1886 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1887 return E_NOINTERFACE;
1890 static HRESULT WINAPI
1891 DSFDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1893 ICOM_THIS(IClassFactoryImpl,iface);
1894 FIXME("(%p)->(%d),stub!\n",This,dolock);
1895 return S_OK;
1898 static ICOM_VTABLE(IClassFactory) DSFDCF_Vtbl =
1900 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1901 DSFDCF_QueryInterface,
1902 DSFDCF_AddRef,
1903 DSFDCF_Release,
1904 DSFDCF_CreateInstance,
1905 DSFDCF_LockServer
1908 IClassFactoryImpl DSOUND_FULLDUPLEX_CF = { &DSFDCF_Vtbl, 1 };