Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / dsound / capture.c
blobe13b388c161069d7decd9560e22d4dc1e9b79dbe
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 IDirectSoundCaptureImpl* dsound_capture = NULL;
84 /***************************************************************************
85 * DirectSoundCaptureCreate [DSOUND.6]
87 * Create and initialize a DirectSoundCapture interface.
89 * PARAMS
90 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
91 * lplpDSC [O] Address of a variable to receive the interface pointer.
92 * pUnkOuter [I] Must be NULL.
94 * RETURNS
95 * Success: DS_OK
96 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
97 * DSERR_OUTOFMEMORY
99 * NOTES
100 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
101 * or NULL for the default device or DSDEVID_DefaultCapture or
102 * DSDEVID_DefaultVoiceCapture.
104 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
106 HRESULT WINAPI
107 DirectSoundCaptureCreate8(
108 LPCGUID lpcGUID,
109 LPDIRECTSOUNDCAPTURE* lplpDSC,
110 LPUNKNOWN pUnkOuter )
112 IDirectSoundCaptureImpl** ippDSC=(IDirectSoundCaptureImpl**)lplpDSC;
113 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter);
115 if ( pUnkOuter ) {
116 WARN("invalid parameter: pUnkOuter != NULL\n");
117 return DSERR_NOAGGREGATION;
120 if ( !lplpDSC ) {
121 WARN("invalid parameter: lplpDSC == NULL\n");
122 return DSERR_INVALIDPARAM;
125 /* Default device? */
126 if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
127 lpcGUID = &DSDEVID_DefaultCapture;
129 *ippDSC = (IDirectSoundCaptureImpl*)HeapAlloc(GetProcessHeap(),
130 HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureImpl));
132 if (*ippDSC == NULL) {
133 WARN("out of memory\n");
134 return DSERR_OUTOFMEMORY;
135 } else {
136 ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC);
138 This->ref = 1;
139 This->state = STATE_STOPPED;
141 InitializeCriticalSection( &(This->lock) );
143 This->lpVtbl = &dscvt;
144 dsound_capture = This;
146 if (GetDeviceID(lpcGUID, &This->guid) == DS_OK) {
147 HRESULT hres;
148 hres = IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE)This, &This->guid);
149 if (hres != DS_OK)
150 WARN("IDirectSoundCaptureImpl_Initialize failed\n");
151 return hres;
154 WARN("invalid GUID: %s\n", debugstr_guid(lpcGUID));
155 return DSERR_INVALIDPARAM;
158 /***************************************************************************
159 * DirectSoundCaptureEnumerateA [DSOUND.7]
161 * Enumerate all DirectSound drivers installed in the system.
163 * PARAMS
164 * lpDSEnumCallback [I] Address of callback function.
165 * lpContext [I] Address of user defined context passed to callback function.
167 * RETURNS
168 * Success: DS_OK
169 * Failure: DSERR_INVALIDPARAM
171 HRESULT WINAPI
172 DirectSoundCaptureEnumerateA(
173 LPDSENUMCALLBACKA lpDSEnumCallback,
174 LPVOID lpContext)
176 unsigned devs, wid;
177 DSDRIVERDESC desc;
178 GUID guid;
179 int err;
181 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
183 if (lpDSEnumCallback == NULL) {
184 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
185 return DSERR_INVALIDPARAM;
188 devs = waveInGetNumDevs();
189 if (devs > 0) {
190 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
191 GUID temp;
192 for (wid = 0; wid < devs; ++wid) {
193 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
194 if (err == DS_OK) {
195 if (IsEqualGUID( &guid, &temp ) ) {
196 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
197 if (err == DS_OK) {
198 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
199 debugstr_guid(&DSDEVID_DefaultCapture),"Primary Sound Capture Driver",desc.szDrvName,lpContext);
200 if (lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, "Primary Sound Capture Driver", desc.szDrvName, lpContext) == FALSE)
201 return DS_OK;
209 for (wid = 0; wid < devs; ++wid) {
210 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
211 if (err == DS_OK) {
212 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
213 if (err == DS_OK) {
214 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
215 debugstr_guid(&guid),desc.szDesc,desc.szDrvName,lpContext);
216 if (lpDSEnumCallback(&guid, desc.szDesc, desc.szDrvName, lpContext) == FALSE)
217 return DS_OK;
222 return DS_OK;
225 /***************************************************************************
226 * DirectSoundCaptureEnumerateW [DSOUND.8]
228 * Enumerate all DirectSound drivers installed in the system.
230 * PARAMS
231 * lpDSEnumCallback [I] Address of callback function.
232 * lpContext [I] Address of user defined context passed to callback function.
234 * RETURNS
235 * Success: DS_OK
236 * Failure: DSERR_INVALIDPARAM
238 HRESULT WINAPI
239 DirectSoundCaptureEnumerateW(
240 LPDSENUMCALLBACKW lpDSEnumCallback,
241 LPVOID lpContext)
243 unsigned devs, wid;
244 DSDRIVERDESC desc;
245 GUID guid;
246 int err;
247 WCHAR wDesc[MAXPNAMELEN];
248 WCHAR wName[MAXPNAMELEN];
250 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
252 if (lpDSEnumCallback == NULL) {
253 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
254 return DSERR_INVALIDPARAM;
257 devs = waveInGetNumDevs();
258 if (devs > 0) {
259 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
260 GUID temp;
261 for (wid = 0; wid < devs; ++wid) {
262 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
263 if (err == DS_OK) {
264 if (IsEqualGUID( &guid, &temp ) ) {
265 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
266 if (err == DS_OK) {
267 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
268 debugstr_guid(&DSDEVID_DefaultCapture),"Primary Sound Capture Driver",desc.szDrvName,lpContext);
269 MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
270 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
271 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
272 wName, sizeof(wName)/sizeof(WCHAR) );
273 if (lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, wDesc, wName, lpContext) == FALSE)
274 return DS_OK;
282 for (wid = 0; wid < devs; ++wid) {
283 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
284 if (err == DS_OK) {
285 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
286 if (err == DS_OK) {
287 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
288 debugstr_guid(&DSDEVID_DefaultCapture),desc.szDesc,desc.szDrvName,lpContext);
289 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
290 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
291 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
292 wName, sizeof(wName)/sizeof(WCHAR) );
293 if (lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, wDesc, wName, lpContext) == FALSE)
294 return DS_OK;
299 return DS_OK;
302 static void CALLBACK
303 DSOUND_capture_callback(
304 HWAVEIN hwi,
305 UINT msg,
306 DWORD dwUser,
307 DWORD dw1,
308 DWORD dw2 )
310 IDirectSoundCaptureImpl* This = (IDirectSoundCaptureImpl*)dwUser;
311 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi,msg,
312 msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
313 msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
315 if (msg == MM_WIM_DATA) {
316 EnterCriticalSection( &(This->lock) );
317 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%ld, old This->index=%d\n",This->state,This->index);
318 if (This->state != STATE_STOPPED) {
319 if (This->state == STATE_STARTING) {
320 MMTIME mtime;
321 mtime.wType = TIME_BYTES;
322 waveInGetPosition(This->hwi, &mtime, sizeof(mtime));
323 TRACE("mtime.u.cb=%ld,This->buflen=%ld\n", mtime.u.cb, This->buflen);
324 mtime.u.cb = mtime.u.cb % This->buflen;
325 This->read_position = mtime.u.cb;
326 This->state = STATE_CAPTURING;
328 This->index = (This->index + 1) % This->nrofpwaves;
329 waveInUnprepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR));
330 if (This->capture_buffer->nrofnotifies)
331 SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
332 if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
333 TRACE("end of buffer\n");
334 This->state = STATE_STOPPED;
335 } else {
336 if (This->state == STATE_CAPTURING) {
337 waveInPrepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR));
338 waveInAddBuffer(hwi, &(This->pwave[This->index]), sizeof(WAVEHDR));
342 TRACE("DirectSoundCapture new This->state=%ld, new This->index=%d\n",This->state,This->index);
343 LeaveCriticalSection( &(This->lock) );
346 TRACE("completed\n");
349 static HRESULT WINAPI
350 IDirectSoundCaptureImpl_QueryInterface(
351 LPDIRECTSOUNDCAPTURE iface,
352 REFIID riid,
353 LPVOID* ppobj )
355 ICOM_THIS(IDirectSoundCaptureImpl,iface);
356 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
358 if (ppobj == NULL) {
359 WARN("invalid parameter\n");
360 return E_INVALIDARG;
363 *ppobj = NULL;
365 if (This->driver) {
366 HRESULT hres;
367 hres = IDsCaptureDriver_QueryInterface(This->driver, riid, ppobj);
368 if (hres != DS_OK)
369 WARN("IDsCaptureDriver_QueryInterface failed\n");
370 return hres;
373 WARN("unsupported riid: %s\n", debugstr_guid(riid));
374 return E_FAIL;
377 static ULONG WINAPI
378 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
380 ULONG uRef;
381 ICOM_THIS(IDirectSoundCaptureImpl,iface);
382 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
384 EnterCriticalSection( &(This->lock) );
385 uRef = ++(This->ref);
387 if (This->driver)
388 IDsCaptureDriver_AddRef(This->driver);
390 LeaveCriticalSection( &(This->lock) );
392 return uRef;
395 static ULONG WINAPI
396 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
398 ULONG uRef;
399 ICOM_THIS(IDirectSoundCaptureImpl,iface);
400 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
402 EnterCriticalSection( &(This->lock) );
404 uRef = --(This->ref);
406 LeaveCriticalSection( &(This->lock) );
408 if ( uRef == 0 ) {
409 TRACE("deleting object\n");
410 if (This->capture_buffer)
411 IDirectSoundCaptureBufferImpl_Release(
412 (LPDIRECTSOUNDCAPTUREBUFFER8) This->capture_buffer);
414 if (This->driver) {
415 IDsCaptureDriver_Close(This->driver);
416 IDsCaptureDriver_Release(This->driver);
419 DeleteCriticalSection( &(This->lock) );
420 HeapFree( GetProcessHeap(), 0, This );
421 dsound_capture = NULL;
422 TRACE("(%p) released\n",This);
425 return uRef;
428 static HRESULT WINAPI
429 IDirectSoundCaptureImpl_CreateCaptureBuffer(
430 LPDIRECTSOUNDCAPTURE iface,
431 LPCDSCBUFFERDESC lpcDSCBufferDesc,
432 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
433 LPUNKNOWN pUnk )
435 HRESULT hr;
436 ICOM_THIS(IDirectSoundCaptureImpl,iface);
438 TRACE( "(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk );
440 if (This == NULL) {
441 WARN("invalid parameter: This == NULL\n");
442 return DSERR_INVALIDPARAM;
445 if (lpcDSCBufferDesc == NULL) {
446 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
447 return DSERR_INVALIDPARAM;
450 if (lplpDSCaptureBuffer == NULL) {
451 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
452 return DSERR_INVALIDPARAM;
455 if (pUnk != NULL) {
456 WARN("invalid parameter: pUnk != NULL\n");
457 return DSERR_INVALIDPARAM;
460 /* FIXME: We can only have one buffer so what do we do here? */
461 if (This->capture_buffer) {
462 WARN("lnvalid parameter: already has buffer\n");
463 return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */
466 hr = DSOUND_CreateDirectSoundCaptureBuffer( This, lpcDSCBufferDesc,
467 (LPVOID*)lplpDSCaptureBuffer );
469 if (hr != DS_OK)
470 WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n");
472 return hr;
475 static HRESULT WINAPI
476 IDirectSoundCaptureImpl_GetCaps(
477 LPDIRECTSOUNDCAPTURE iface,
478 LPDSCCAPS lpDSCCaps )
480 ICOM_THIS(IDirectSoundCaptureImpl,iface);
481 TRACE("(%p,%p)\n",This,lpDSCCaps);
483 if (lpDSCCaps== NULL) {
484 WARN("invalid parameter: lpDSCCaps== NULL\n");
485 return DSERR_INVALIDPARAM;
488 if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
489 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
490 lpDSCCaps->dwSize, sizeof(*lpDSCCaps));
491 return DSERR_INVALIDPARAM;
494 if ( !(This->initialized) ) {
495 WARN("not initialized\n");
496 return DSERR_UNINITIALIZED;
499 lpDSCCaps->dwFlags = This->drvcaps.dwFlags;
500 lpDSCCaps->dwFormats = This->drvcaps.dwFormats;
501 lpDSCCaps->dwChannels = This->drvcaps.dwChannels;
503 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps->dwFlags,
504 lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
506 return DS_OK;
509 static HRESULT WINAPI
510 IDirectSoundCaptureImpl_Initialize(
511 LPDIRECTSOUNDCAPTURE iface,
512 LPCGUID lpcGUID )
514 HRESULT err = DSERR_INVALIDPARAM;
515 unsigned wid, widn;
516 ICOM_THIS(IDirectSoundCaptureImpl,iface);
517 TRACE("(%p)\n", This);
519 if (!This) {
520 WARN("invalid parameter: This == NULL\n");
521 return DSERR_INVALIDPARAM;
524 if (This->initialized) {
525 WARN("already initialized\n");
526 return DSERR_ALREADYINITIALIZED;
529 widn = waveInGetNumDevs();
531 if (!widn) {
532 WARN("no audio devices found\n");
533 return DSERR_NODRIVER;
536 /* Get dsound configuration */
537 setup_dsound_options();
539 /* enumerate WINMM audio devices and find the one we want */
540 for (wid=0; wid<widn; wid++) {
541 GUID guid;
542 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
543 if (err != DS_OK) {
544 WARN("waveInMessage failed; err=%lx\n",err);
545 return err;
547 if (IsEqualGUID( lpcGUID, &guid) ) {
548 err = DS_OK;
549 break;
553 if (err != DS_OK) {
554 WARN("invalid parameter\n");
555 return DSERR_INVALIDPARAM;
558 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&(This->driver),0));
559 if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
560 WARN("waveInMessage failed; err=%lx\n",err);
561 return err;
563 err = DS_OK;
565 /* Disable the direct sound driver to force emulation if requested. */
566 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
567 This->driver = NULL;
569 /* Get driver description */
570 if (This->driver) {
571 TRACE("using DirectSound driver\n");
572 err = IDsCaptureDriver_GetDriverDesc(This->driver, &(This->drvdesc));
573 if (err != DS_OK) {
574 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
575 return err;
577 } else {
578 TRACE("using WINMM\n");
579 /* if no DirectSound interface available, use WINMM API instead */
580 This->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |
581 DSDDESC_DOMMSYSTEMSETFORMAT;
584 This->drvdesc.dnDevNode = wid;
586 /* open the DirectSound driver if available */
587 if (This->driver && (err == DS_OK))
588 err = IDsCaptureDriver_Open(This->driver);
590 if (err == DS_OK) {
591 This->initialized = TRUE;
593 /* the driver is now open, so it's now allowed to call GetCaps */
594 if (This->driver) {
595 This->drvcaps.dwSize = sizeof(This->drvcaps);
596 err = IDsCaptureDriver_GetCaps(This->driver,&(This->drvcaps));
597 if (err != DS_OK) {
598 WARN("IDsCaptureDriver_GetCaps failed\n");
599 return err;
601 } else /*if (This->hwi)*/ {
602 WAVEINCAPSA wic;
603 err = mmErr(waveInGetDevCapsA((UINT)This->drvdesc.dnDevNode, &wic, sizeof(wic)));
605 if (err == DS_OK) {
606 This->drvcaps.dwFlags = 0;
607 strncpy(This->drvdesc.szDrvName, wic.szPname,
608 sizeof(This->drvdesc.szDrvName));
610 This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
611 This->drvcaps.dwFormats = wic.dwFormats;
612 This->drvcaps.dwChannels = wic.wChannels;
617 return err;
620 static ICOM_VTABLE(IDirectSoundCapture) dscvt =
622 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
623 /* IUnknown methods */
624 IDirectSoundCaptureImpl_QueryInterface,
625 IDirectSoundCaptureImpl_AddRef,
626 IDirectSoundCaptureImpl_Release,
628 /* IDirectSoundCapture methods */
629 IDirectSoundCaptureImpl_CreateCaptureBuffer,
630 IDirectSoundCaptureImpl_GetCaps,
631 IDirectSoundCaptureImpl_Initialize
634 static HRESULT
635 DSOUND_CreateDirectSoundCaptureBuffer(
636 IDirectSoundCaptureImpl *ipDSC,
637 LPCDSCBUFFERDESC lpcDSCBufferDesc,
638 LPVOID* ppobj )
640 LPWAVEFORMATEX wfex;
641 TRACE( "(%p,%p)\n", lpcDSCBufferDesc, ppobj );
643 if (ipDSC == NULL) {
644 WARN("invalid parameter: ipDSC == NULL\n");
645 return DSERR_INVALIDPARAM;
648 if (lpcDSCBufferDesc == NULL) {
649 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
650 return DSERR_INVALIDPARAM;
653 if (ppobj == NULL) {
654 WARN("invalid parameter: ppobj == NULL\n");
655 return DSERR_INVALIDPARAM;
658 if ( (lpcDSCBufferDesc->dwSize < sizeof(DSCBUFFERDESC)) ||
659 (lpcDSCBufferDesc->dwBufferBytes == 0) ||
660 (lpcDSCBufferDesc->lpwfxFormat == NULL) ) {
661 WARN("invalid lpcDSCBufferDesc\n");
662 *ppobj = NULL;
663 return DSERR_INVALIDPARAM;
666 if ( !ipDSC->initialized ) {
667 WARN("not initialized\n");
668 *ppobj = NULL;
669 return DSERR_UNINITIALIZED;
672 wfex = lpcDSCBufferDesc->lpwfxFormat;
674 if (wfex) {
675 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
676 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
677 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
678 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
679 wfex->wBitsPerSample, wfex->cbSize);
681 if (wfex->wFormatTag == WAVE_FORMAT_PCM)
682 memcpy(&(ipDSC->wfx), wfex, sizeof(WAVEFORMATEX));
683 else {
684 WARN("non PCM formats not supported\n");
685 *ppobj = NULL;
686 return DSERR_BADFORMAT;
688 } else {
689 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
690 *ppobj = NULL;
691 return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */
694 *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
695 sizeof(IDirectSoundCaptureBufferImpl));
697 if ( *ppobj == NULL ) {
698 WARN("out of memory\n");
699 *ppobj = NULL;
700 return DSERR_OUTOFMEMORY;
701 } else {
702 HRESULT err = DS_OK;
703 ICOM_THIS(IDirectSoundCaptureBufferImpl,*ppobj);
705 This->ref = 1;
706 This->dsound = ipDSC;
707 This->dsound->capture_buffer = This;
708 This->notify = NULL;
709 This->nrofnotifies = 0;
710 This->hwnotify = NULL;
712 This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
713 lpcDSCBufferDesc->dwSize);
714 if (This->pdscbd)
715 memcpy(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
716 else {
717 WARN("no memory\n");
718 This->dsound->capture_buffer = 0;
719 HeapFree( GetProcessHeap(), 0, This );
720 *ppobj = NULL;
721 return DSERR_OUTOFMEMORY;
724 This->lpVtbl = &dscbvt;
726 if (ipDSC->driver) {
727 err = IDsCaptureDriver_CreateCaptureBuffer(ipDSC->driver,
728 &(ipDSC->wfx),0,0,&(ipDSC->buflen),&(ipDSC->buffer),(LPVOID*)&(ipDSC->hwbuf));
729 if (err != DS_OK) {
730 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
731 This->dsound->capture_buffer = 0;
732 HeapFree( GetProcessHeap(), 0, This );
733 *ppobj = NULL;
734 return err;
736 } else {
737 LPBYTE newbuf;
738 DWORD buflen;
739 DWORD flags = CALLBACK_FUNCTION;
740 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
741 flags |= WAVE_DIRECTSOUND;
742 err = mmErr(waveInOpen(&(ipDSC->hwi),
743 ipDSC->drvdesc.dnDevNode, &(ipDSC->wfx),
744 (DWORD)DSOUND_capture_callback, (DWORD)ipDSC, flags));
745 if (err != DS_OK) {
746 WARN("waveInOpen failed\n");
747 This->dsound->capture_buffer = 0;
748 HeapFree( GetProcessHeap(), 0, This );
749 *ppobj = NULL;
750 return err;
753 buflen = lpcDSCBufferDesc->dwBufferBytes;
754 TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->buffer);
755 newbuf = (LPBYTE)HeapReAlloc(GetProcessHeap(),0,ipDSC->buffer,buflen);
757 if (newbuf == NULL) {
758 WARN("failed to allocate capture buffer\n");
759 err = DSERR_OUTOFMEMORY;
760 /* but the old buffer might still exist and must be re-prepared */
761 } else {
762 ipDSC->buffer = newbuf;
763 ipDSC->buflen = buflen;
768 TRACE("returning DS_OK\n");
769 return DS_OK;
772 /*******************************************************************************
773 * IDirectSoundCaptureNotify
775 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
776 LPDIRECTSOUNDNOTIFY iface,
777 REFIID riid,
778 LPVOID *ppobj)
780 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
781 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
783 if (This->dscb == NULL) {
784 WARN("invalid parameter\n");
785 return E_INVALIDARG;
788 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
791 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
793 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
794 DWORD ref;
796 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
798 ref = InterlockedIncrement(&(This->ref));
799 return ref;
802 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
804 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
805 DWORD ref;
807 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
809 ref = InterlockedDecrement(&(This->ref));
810 if (ref == 0) {
811 This->dscb->notify=NULL;
812 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
813 HeapFree(GetProcessHeap(),0,This);
814 TRACE("(%p) released\n",This);
816 return ref;
819 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
820 LPDIRECTSOUNDNOTIFY iface,
821 DWORD howmuch,
822 LPCDSBPOSITIONNOTIFY notify)
824 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
825 TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
827 if (notify == NULL) {
828 WARN("invalid parameter: notify == NULL\n");
829 return DSERR_INVALIDPARAM;
832 if (TRACE_ON(dsound)) {
833 int i;
834 for (i=0;i<howmuch;i++)
835 TRACE("notify at %ld to 0x%08lx\n",
836 notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
839 if (This->dscb->hwnotify) {
840 HRESULT hres;
841 hres = IDsDriverNotify_SetNotificationPositions(This->dscb->hwnotify, howmuch, notify);
842 if (hres != DS_OK)
843 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
844 return hres;
845 } else {
846 /* Make an internal copy of the caller-supplied array.
847 * Replace the existing copy if one is already present. */
848 This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
849 This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
850 if (This->dscb->notifies == NULL) {
851 WARN("out of memory\n");
852 return DSERR_OUTOFMEMORY;
854 memcpy(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
855 This->dscb->nrofnotifies = howmuch;
858 return S_OK;
861 ICOM_VTABLE(IDirectSoundNotify) dscnvt =
863 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
864 IDirectSoundCaptureNotifyImpl_QueryInterface,
865 IDirectSoundCaptureNotifyImpl_AddRef,
866 IDirectSoundCaptureNotifyImpl_Release,
867 IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
870 HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create(
871 IDirectSoundCaptureBufferImpl *dscb,
872 IDirectSoundCaptureNotifyImpl **pdscn)
874 IDirectSoundCaptureNotifyImpl * dscn;
875 TRACE("(%p,%p)\n",dscb,pdscn);
877 dscn = (IDirectSoundCaptureNotifyImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dscn));
879 if (dscn == NULL) {
880 WARN("out of memory\n");
881 return DSERR_OUTOFMEMORY;
884 dscn->ref = 0;
885 dscn->lpVtbl = &dscnvt;
886 dscn->dscb = dscb;
887 dscb->notify = dscn;
888 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
890 *pdscn = dscn;
891 return DS_OK;
894 /*******************************************************************************
895 * IDirectSoundCaptureBuffer
897 static HRESULT WINAPI
898 IDirectSoundCaptureBufferImpl_QueryInterface(
899 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
900 REFIID riid,
901 LPVOID* ppobj )
903 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
904 HRESULT hres;
905 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
907 if (ppobj == NULL) {
908 WARN("invalid parameter\n");
909 return E_INVALIDARG;
912 *ppobj = NULL;
914 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ||
915 IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) {
916 if (!This->notify)
917 hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
918 if (This->notify) {
919 if (This->dsound->hwbuf) {
920 hres = IDsCaptureDriverBuffer_QueryInterface(This->dsound->hwbuf,
921 &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
922 if (hres != DS_OK) {
923 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
924 *ppobj = 0;
925 return hres;
929 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
930 *ppobj = (LPVOID)This->notify;
931 return DS_OK;
934 WARN("IID_IDirectSoundNotify\n");
935 return E_FAIL;
938 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
939 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
940 IDirectSoundCaptureBuffer8_AddRef(iface);
941 *ppobj = This;
942 return NO_ERROR;
945 FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
946 return E_NOINTERFACE;
949 static ULONG WINAPI
950 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
952 ULONG uRef;
953 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
954 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
956 assert(This->dsound);
958 EnterCriticalSection( &(This->dsound->lock) );
960 uRef = ++(This->ref);
962 LeaveCriticalSection( &(This->dsound->lock) );
964 return uRef;
967 static ULONG WINAPI
968 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
970 ULONG uRef;
971 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
972 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
974 assert(This->dsound);
976 EnterCriticalSection( &(This->dsound->lock) );
978 uRef = --(This->ref);
980 LeaveCriticalSection( &(This->dsound->lock) );
982 if ( uRef == 0 ) {
983 TRACE("deleting object\n");
984 if (This->pdscbd)
985 HeapFree(GetProcessHeap(),0, This->pdscbd);
987 if (This->dsound->hwi) {
988 waveInReset(This->dsound->hwi);
989 waveInClose(This->dsound->hwi);
990 if (This->dsound->pwave) {
991 HeapFree(GetProcessHeap(),0, This->dsound->pwave);
992 This->dsound->pwave = 0;
994 This->dsound->hwi = 0;
997 if (This->dsound->hwbuf)
998 IDsCaptureDriverBuffer_Release(This->dsound->hwbuf);
1000 /* remove from IDirectSoundCaptureImpl */
1001 if (This->dsound)
1002 This->dsound->capture_buffer = NULL;
1003 else
1004 ERR("does not reference dsound\n");
1006 if (This->notify)
1007 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
1009 if (This->notifies != NULL)
1010 HeapFree(GetProcessHeap(), 0, This->notifies);
1012 HeapFree( GetProcessHeap(), 0, This );
1013 TRACE("(%p) released\n",This);
1016 return uRef;
1019 static HRESULT WINAPI
1020 IDirectSoundCaptureBufferImpl_GetCaps(
1021 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1022 LPDSCBCAPS lpDSCBCaps )
1024 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1025 TRACE( "(%p,%p)\n", This, lpDSCBCaps );
1027 if (This == NULL) {
1028 WARN("invalid parameter: This == NULL\n");
1029 return DSERR_INVALIDPARAM;
1032 if (lpDSCBCaps == NULL) {
1033 WARN("invalid parameter: lpDSCBCaps == NULL\n");
1034 return DSERR_INVALIDPARAM;
1037 if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) {
1038 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
1039 lpDSCBCaps->dwSize, sizeof(DSCBCAPS));
1040 return DSERR_INVALIDPARAM;
1043 if (This->dsound == NULL) {
1044 WARN("invalid parameter: This->dsound == NULL\n");
1045 return DSERR_INVALIDPARAM;
1048 lpDSCBCaps->dwSize = sizeof(DSCBCAPS);
1049 lpDSCBCaps->dwFlags = This->flags;
1050 lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes;
1051 lpDSCBCaps->dwReserved = 0;
1053 TRACE("returning DS_OK\n");
1054 return DS_OK;
1057 static HRESULT WINAPI
1058 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
1059 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1060 LPDWORD lpdwCapturePosition,
1061 LPDWORD lpdwReadPosition )
1063 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1064 TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
1066 if (This == NULL) {
1067 WARN("invalid parameter: This == NULL\n");
1068 return DSERR_INVALIDPARAM;
1071 if (This->dsound == NULL) {
1072 WARN("invalid parameter: This->dsound == NULL\n");
1073 return DSERR_INVALIDPARAM;
1076 if (This->dsound->driver) {
1077 HRESULT hres;
1078 hres = IDsCaptureDriverBuffer_GetPosition(This->dsound->hwbuf, lpdwCapturePosition, lpdwReadPosition );
1079 if (hres != DS_OK) {
1080 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
1081 return hres;
1083 } else if (This->dsound->hwi) {
1084 EnterCriticalSection(&(This->dsound->lock));
1085 TRACE("old This->dsound->state=%ld\n",This->dsound->state);
1086 if (lpdwCapturePosition) {
1087 MMTIME mtime;
1088 mtime.wType = TIME_BYTES;
1089 waveInGetPosition(This->dsound->hwi, &mtime, sizeof(mtime));
1090 TRACE("mtime.u.cb=%ld,This->dsound->buflen=%ld\n", mtime.u.cb,
1091 This->dsound->buflen);
1092 mtime.u.cb = mtime.u.cb % This->dsound->buflen;
1093 *lpdwCapturePosition = mtime.u.cb;
1096 if (lpdwReadPosition) {
1097 if (This->dsound->state == STATE_STARTING) {
1098 if (lpdwCapturePosition)
1099 This->dsound->read_position = *lpdwCapturePosition;
1100 This->dsound->state = STATE_CAPTURING;
1102 *lpdwReadPosition = This->dsound->read_position;
1104 TRACE("new This->dsound->state=%ld\n",This->dsound->state);
1105 LeaveCriticalSection(&(This->dsound->lock));
1106 if (lpdwCapturePosition) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition);
1107 if (lpdwReadPosition) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition);
1108 } else {
1109 WARN("no driver\n");
1110 return DSERR_NODRIVER;
1113 TRACE("returning DS_OK\n");
1114 return DS_OK;
1117 static HRESULT WINAPI
1118 IDirectSoundCaptureBufferImpl_GetFormat(
1119 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1120 LPWAVEFORMATEX lpwfxFormat,
1121 DWORD dwSizeAllocated,
1122 LPDWORD lpdwSizeWritten )
1124 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1125 TRACE( "(%p,%p,0x%08lx,%p)\n", This, lpwfxFormat, dwSizeAllocated,
1126 lpdwSizeWritten );
1128 if (This == NULL) {
1129 WARN("invalid parameter: This == NULL\n");
1130 return DSERR_INVALIDPARAM;
1133 if (This->dsound == NULL) {
1134 WARN("invalid parameter: This->dsound == NULL\n");
1135 return DSERR_INVALIDPARAM;
1138 /* FIXME: use real size for extended formats someday */
1139 if (dwSizeAllocated > sizeof(This->dsound->wfx))
1140 dwSizeAllocated = sizeof(This->dsound->wfx);
1141 if (lpwfxFormat) { /* NULL is valid (just want size) */
1142 memcpy(lpwfxFormat,&(This->dsound->wfx),dwSizeAllocated);
1143 if (lpdwSizeWritten)
1144 *lpdwSizeWritten = dwSizeAllocated;
1145 } else {
1146 if (lpdwSizeWritten)
1147 *lpdwSizeWritten = sizeof(This->dsound->wfx);
1148 else {
1149 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
1150 return DSERR_INVALIDPARAM;
1154 TRACE("returning DS_OK\n");
1155 return DS_OK;
1158 static HRESULT WINAPI
1159 IDirectSoundCaptureBufferImpl_GetStatus(
1160 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1161 LPDWORD lpdwStatus )
1163 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1164 TRACE( "(%p, %p), thread is %04lx\n", This, lpdwStatus, GetCurrentThreadId() );
1166 if (This == NULL) {
1167 WARN("invalid parameter: This == NULL\n");
1168 return DSERR_INVALIDPARAM;
1171 if (This->dsound == NULL) {
1172 WARN("invalid parameter: This->dsound == NULL\n");
1173 return DSERR_INVALIDPARAM;
1176 if (lpdwStatus == NULL) {
1177 WARN("invalid parameter: lpdwStatus == NULL\n");
1178 return DSERR_INVALIDPARAM;
1181 *lpdwStatus = 0;
1182 EnterCriticalSection(&(This->dsound->lock));
1184 TRACE("old This->dsound->state=%ld, old lpdwStatus=%08lx\n",This->dsound->state,*lpdwStatus);
1185 if ((This->dsound->state == STATE_STARTING) ||
1186 (This->dsound->state == STATE_CAPTURING)) {
1187 *lpdwStatus |= DSCBSTATUS_CAPTURING;
1188 if (This->flags & DSCBSTART_LOOPING)
1189 *lpdwStatus |= DSCBSTATUS_LOOPING;
1191 TRACE("new This->dsound->state=%ld, new lpdwStatus=%08lx\n",This->dsound->state,*lpdwStatus);
1192 LeaveCriticalSection(&(This->dsound->lock));
1194 TRACE("status=%lx\n", *lpdwStatus);
1195 TRACE("returning DS_OK\n");
1196 return DS_OK;
1199 static HRESULT WINAPI
1200 IDirectSoundCaptureBufferImpl_Initialize(
1201 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1202 LPDIRECTSOUNDCAPTURE lpDSC,
1203 LPCDSCBUFFERDESC lpcDSCBDesc )
1205 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1207 FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
1209 return DS_OK;
1212 static HRESULT WINAPI
1213 IDirectSoundCaptureBufferImpl_Lock(
1214 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1215 DWORD dwReadCusor,
1216 DWORD dwReadBytes,
1217 LPVOID* lplpvAudioPtr1,
1218 LPDWORD lpdwAudioBytes1,
1219 LPVOID* lplpvAudioPtr2,
1220 LPDWORD lpdwAudioBytes2,
1221 DWORD dwFlags )
1223 HRESULT err = DS_OK;
1224 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1225 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This, dwReadCusor,
1226 dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
1227 lpdwAudioBytes2, dwFlags, GetTickCount() );
1229 if (This == NULL) {
1230 WARN("invalid parameter: This == NULL\n");
1231 return DSERR_INVALIDPARAM;
1234 if (This->dsound == NULL) {
1235 WARN("invalid parameter: This->dsound == NULL\n");
1236 return DSERR_INVALIDPARAM;
1239 if (lplpvAudioPtr1 == NULL) {
1240 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1241 return DSERR_INVALIDPARAM;
1244 if (lpdwAudioBytes1 == NULL) {
1245 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1246 return DSERR_INVALIDPARAM;
1249 EnterCriticalSection(&(This->dsound->lock));
1251 if (This->dsound->driver) {
1252 err = IDsCaptureDriverBuffer_Lock(This->dsound->hwbuf, lplpvAudioPtr1,
1253 lpdwAudioBytes1, lplpvAudioPtr2, lpdwAudioBytes2,
1254 dwReadCusor, dwReadBytes, dwFlags);
1255 if (err != DS_OK)
1256 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1257 } else if (This->dsound->hwi) {
1258 *lplpvAudioPtr1 = This->dsound->buffer + dwReadCusor;
1259 if ( (dwReadCusor + dwReadBytes) > This->dsound->buflen) {
1260 *lpdwAudioBytes1 = This->dsound->buflen - dwReadCusor;
1261 if (lplpvAudioPtr2)
1262 *lplpvAudioPtr2 = This->dsound->buffer;
1263 if (lpdwAudioBytes2)
1264 *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
1265 } else {
1266 *lpdwAudioBytes1 = dwReadBytes;
1267 if (lplpvAudioPtr2)
1268 *lplpvAudioPtr2 = 0;
1269 if (lpdwAudioBytes2)
1270 *lpdwAudioBytes2 = 0;
1272 } else {
1273 TRACE("invalid call\n");
1274 err = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */
1277 LeaveCriticalSection(&(This->dsound->lock));
1279 return err;
1282 static HRESULT WINAPI
1283 IDirectSoundCaptureBufferImpl_Start(
1284 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1285 DWORD dwFlags )
1287 HRESULT err = DS_OK;
1288 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1289 TRACE( "(%p,0x%08lx)\n", This, dwFlags );
1291 if (This == NULL) {
1292 WARN("invalid parameter: This == NULL\n");
1293 return DSERR_INVALIDPARAM;
1296 if (This->dsound == NULL) {
1297 WARN("invalid parameter: This->dsound == NULL\n");
1298 return DSERR_INVALIDPARAM;
1301 if ( (This->dsound->driver == 0) && (This->dsound->hwi == 0) ) {
1302 WARN("no driver\n");
1303 return DSERR_NODRIVER;
1306 EnterCriticalSection(&(This->dsound->lock));
1308 This->flags = dwFlags;
1309 TRACE("old This->dsound->state=%ld\n",This->dsound->state);
1310 if (This->dsound->state == STATE_STOPPED)
1311 This->dsound->state = STATE_STARTING;
1312 else if (This->dsound->state == STATE_STOPPING)
1313 This->dsound->state = STATE_CAPTURING;
1314 TRACE("new This->dsound->state=%ld\n",This->dsound->state);
1316 LeaveCriticalSection(&(This->dsound->lock));
1318 if (This->dsound->driver) {
1319 err = IDsCaptureDriverBuffer_Start(This->dsound->hwbuf, dwFlags);
1320 if (err != DS_OK)
1321 WARN("IDsCaptureDriverBuffer_Start failed\n");
1322 return err;
1323 } else {
1324 IDirectSoundCaptureImpl* ipDSC = This->dsound;
1326 if (ipDSC->buffer) {
1327 if (This->nrofnotifies) {
1328 unsigned c;
1330 ipDSC->nrofpwaves = This->nrofnotifies;
1332 /* prepare headers */
1333 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,
1334 ipDSC->nrofpwaves*sizeof(WAVEHDR));
1336 for (c = 0; c < ipDSC->nrofpwaves; c++) {
1337 if (c == 0) {
1338 ipDSC->pwave[0].lpData = ipDSC->buffer;
1339 ipDSC->pwave[0].dwBufferLength =
1340 This->notifies[0].dwOffset + 1;
1341 } else {
1342 ipDSC->pwave[c].lpData = ipDSC->buffer +
1343 This->notifies[c-1].dwOffset + 1;
1344 ipDSC->pwave[c].dwBufferLength =
1345 This->notifies[c].dwOffset -
1346 This->notifies[c-1].dwOffset;
1348 ipDSC->pwave[c].dwUser = (DWORD)ipDSC;
1349 ipDSC->pwave[c].dwFlags = 0;
1350 ipDSC->pwave[c].dwLoops = 0;
1351 err = mmErr(waveInPrepareHeader(ipDSC->hwi,
1352 &(ipDSC->pwave[c]),sizeof(WAVEHDR)));
1353 if (err != DS_OK) {
1354 while (c--)
1355 waveInUnprepareHeader(ipDSC->hwi,
1356 &(ipDSC->pwave[c]),sizeof(WAVEHDR));
1357 break;
1361 memset(ipDSC->buffer,
1362 (ipDSC->wfx.wBitsPerSample == 16) ? 0 : 128, ipDSC->buflen);
1363 } else {
1364 TRACE("no notifiers specified\n");
1365 /* no notifiers specified so just create a single default header */
1366 ipDSC->nrofpwaves = 1;
1367 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,sizeof(WAVEHDR));
1368 ipDSC->pwave[0].lpData = ipDSC->buffer;
1369 ipDSC->pwave[0].dwBufferLength = ipDSC->buflen;
1370 ipDSC->pwave[0].dwUser = (DWORD)ipDSC;
1371 ipDSC->pwave[0].dwFlags = 0;
1372 ipDSC->pwave[0].dwLoops = 0;
1374 err = mmErr(waveInPrepareHeader(ipDSC->hwi,
1375 &(ipDSC->pwave[0]),sizeof(WAVEHDR)));
1376 if (err != DS_OK) {
1377 WARN("waveInPrepareHeader failed\n");
1378 waveInUnprepareHeader(ipDSC->hwi,
1379 &(ipDSC->pwave[0]),sizeof(WAVEHDR));
1384 ipDSC->index = 0;
1385 ipDSC->read_position = 0;
1387 if (err == DS_OK) {
1388 err = mmErr(waveInReset(ipDSC->hwi));
1389 if (err == DS_OK) {
1390 /* add the first buffer to the queue */
1391 err = mmErr(waveInAddBuffer(ipDSC->hwi, &(ipDSC->pwave[0]), sizeof(WAVEHDR)));
1392 if (err == DS_OK) {
1393 /* start filling the first buffer */
1394 err = mmErr(waveInStart(ipDSC->hwi));
1395 } else
1396 WARN("waveInAddBuffer failed\n");
1397 } else
1398 WARN("waveInReset failed\n");
1402 if (err != DS_OK) {
1403 WARN("calling waveInClose because of error\n");
1404 waveInClose(This->dsound->hwi);
1405 This->dsound->hwi = 0;
1408 TRACE("returning %ld\n", err);
1409 return err;
1412 static HRESULT WINAPI
1413 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
1415 HRESULT err = DS_OK;
1416 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1417 TRACE( "(%p)\n", This );
1419 if (This == NULL) {
1420 WARN("invalid parameter: This == NULL\n");
1421 return DSERR_INVALIDPARAM;
1424 if (This->dsound == NULL) {
1425 WARN("invalid parameter: This->dsound == NULL\n");
1426 return DSERR_INVALIDPARAM;
1429 EnterCriticalSection(&(This->dsound->lock));
1431 TRACE("old This->dsound->state=%ld\n",This->dsound->state);
1432 if (This->dsound->state == STATE_CAPTURING)
1433 This->dsound->state = STATE_STOPPING;
1434 else if (This->dsound->state == STATE_STARTING)
1435 This->dsound->state = STATE_STOPPED;
1436 TRACE("new This->dsound->state=%ld\n",This->dsound->state);
1438 LeaveCriticalSection(&(This->dsound->lock));
1440 if (This->dsound->driver) {
1441 err = IDsCaptureDriverBuffer_Stop(This->dsound->hwbuf);
1442 if (err == DSERR_BUFFERLOST) {
1443 /* Wine-only: the driver wants us to reopen the device */
1444 IDsCaptureDriverBuffer_Release(This->dsound->hwbuf);
1445 err = IDsCaptureDriver_CreateCaptureBuffer(This->dsound->driver,
1446 &(This->dsound->wfx),0,0,&(This->dsound->buflen),&(This->dsound->buffer),
1447 (LPVOID*)&(This->dsound->hwbuf));
1448 if (err != DS_OK) {
1449 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1450 This->dsound->hwbuf = 0;
1452 } else if (err != DS_OK)
1453 WARN("IDsCaptureDriverBuffer_Stop failed\n");
1454 } else if (This->dsound->hwi) {
1455 err = waveInStop(This->dsound->hwi);
1456 } else {
1457 WARN("no driver\n");
1458 err = DSERR_NODRIVER;
1461 TRACE( "(%p) returning 0x%08lx\n", This,err);
1462 return err;
1465 static HRESULT WINAPI
1466 IDirectSoundCaptureBufferImpl_Unlock(
1467 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1468 LPVOID lpvAudioPtr1,
1469 DWORD dwAudioBytes1,
1470 LPVOID lpvAudioPtr2,
1471 DWORD dwAudioBytes2 )
1473 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1474 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This, lpvAudioPtr1, dwAudioBytes1,
1475 lpvAudioPtr2, dwAudioBytes2 );
1477 if (This == NULL) {
1478 WARN("invalid parameter: This == NULL\n");
1479 return DSERR_INVALIDPARAM;
1482 if (lpvAudioPtr1 == NULL) {
1483 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1484 return DSERR_INVALIDPARAM;
1487 if (This->dsound->driver) {
1488 HRESULT hres;
1489 hres = IDsCaptureDriverBuffer_Unlock(This->dsound->hwbuf, lpvAudioPtr1,
1490 dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
1491 if (hres != DS_OK)
1492 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1493 return hres;
1494 } else if (This->dsound->hwi) {
1495 This->dsound->read_position = (This->dsound->read_position +
1496 (dwAudioBytes1 + dwAudioBytes2)) % This->dsound->buflen;
1497 } else {
1498 WARN("invalid call\n");
1499 return DSERR_INVALIDCALL;
1502 return DS_OK;
1505 static HRESULT WINAPI
1506 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1507 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1508 REFGUID rguidObject,
1509 DWORD dwIndex,
1510 REFGUID rguidInterface,
1511 LPVOID* ppObject )
1513 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1515 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject),
1516 dwIndex, debugstr_guid(rguidInterface), ppObject );
1518 return DS_OK;
1521 static HRESULT WINAPI
1522 IDirectSoundCaptureBufferImpl_GetFXStatus(
1523 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1524 DWORD dwFXCount,
1525 LPDWORD pdwFXStatus )
1527 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1529 FIXME( "(%p,%lu,%p): stub\n", This, dwFXCount, pdwFXStatus );
1531 return DS_OK;
1534 static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt =
1536 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1537 /* IUnknown methods */
1538 IDirectSoundCaptureBufferImpl_QueryInterface,
1539 IDirectSoundCaptureBufferImpl_AddRef,
1540 IDirectSoundCaptureBufferImpl_Release,
1542 /* IDirectSoundCaptureBuffer methods */
1543 IDirectSoundCaptureBufferImpl_GetCaps,
1544 IDirectSoundCaptureBufferImpl_GetCurrentPosition,
1545 IDirectSoundCaptureBufferImpl_GetFormat,
1546 IDirectSoundCaptureBufferImpl_GetStatus,
1547 IDirectSoundCaptureBufferImpl_Initialize,
1548 IDirectSoundCaptureBufferImpl_Lock,
1549 IDirectSoundCaptureBufferImpl_Start,
1550 IDirectSoundCaptureBufferImpl_Stop,
1551 IDirectSoundCaptureBufferImpl_Unlock,
1553 /* IDirectSoundCaptureBuffer methods */
1554 IDirectSoundCaptureBufferImpl_GetObjectInPath,
1555 IDirectSoundCaptureBufferImpl_GetFXStatus
1558 /*******************************************************************************
1559 * DirectSoundCapture ClassFactory
1562 static HRESULT WINAPI
1563 DSCCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1565 ICOM_THIS(IClassFactoryImpl,iface);
1567 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1568 return E_NOINTERFACE;
1571 static ULONG WINAPI
1572 DSCCF_AddRef(LPCLASSFACTORY iface)
1574 ICOM_THIS(IClassFactoryImpl,iface);
1575 TRACE("(%p) ref was %ld\n", This, This->ref);
1576 return ++(This->ref);
1579 static ULONG WINAPI
1580 DSCCF_Release(LPCLASSFACTORY iface)
1582 ICOM_THIS(IClassFactoryImpl,iface);
1583 /* static class, won't be freed */
1584 TRACE("(%p) ref was %ld\n", This, This->ref);
1585 return --(This->ref);
1588 static HRESULT WINAPI
1589 DSCCF_CreateInstance(
1590 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1592 ICOM_THIS(IClassFactoryImpl,iface);
1593 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1595 if (ppobj == NULL) {
1596 WARN("invalid parameter\n");
1597 return E_INVALIDARG;
1600 *ppobj = NULL;
1602 if ( IsEqualGUID( &IID_IDirectSoundCapture, riid ) ||
1603 IsEqualGUID( &IID_IDirectSoundCapture8, riid ) ) {
1604 return DirectSoundCaptureCreate8(0,(LPDIRECTSOUNDCAPTURE8*)ppobj,pOuter);
1607 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1608 return E_NOINTERFACE;
1611 static HRESULT WINAPI
1612 DSCCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1614 ICOM_THIS(IClassFactoryImpl,iface);
1615 FIXME("(%p)->(%d),stub!\n",This,dolock);
1616 return S_OK;
1619 static ICOM_VTABLE(IClassFactory) DSCCF_Vtbl =
1621 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1622 DSCCF_QueryInterface,
1623 DSCCF_AddRef,
1624 DSCCF_Release,
1625 DSCCF_CreateInstance,
1626 DSCCF_LockServer
1629 IClassFactoryImpl DSOUND_CAPTURE_CF = { &DSCCF_Vtbl, 1 };
1631 /***************************************************************************
1632 * DirectSoundFullDuplexCreate8 [DSOUND.10]
1634 * Create and initialize a DirectSoundFullDuplex interface.
1636 * PARAMS
1637 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
1638 * pcGuidRenderDevice [I] Address of sound render device GUID.
1639 * pcDSCBufferDesc [I] Address of capture buffer description.
1640 * pcDSBufferDesc [I] Address of render buffer description.
1641 * hWnd [I] Handle to application window.
1642 * dwLevel [I] Cooperative level.
1643 * ppDSFD [O] Address where full duplex interface returned.
1644 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
1645 * ppDSBuffer8 [0] Address where render buffer interface returned.
1646 * pUnkOuter [I] Must be NULL.
1648 * RETURNS
1649 * Success: DS_OK
1650 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1651 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
1653 HRESULT WINAPI
1654 DirectSoundFullDuplexCreate8(
1655 LPCGUID pcGuidCaptureDevice,
1656 LPCGUID pcGuidRenderDevice,
1657 LPCDSCBUFFERDESC pcDSCBufferDesc,
1658 LPCDSBUFFERDESC pcDSBufferDesc,
1659 HWND hWnd,
1660 DWORD dwLevel,
1661 LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
1662 LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
1663 LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
1664 LPUNKNOWN pUnkOuter)
1666 IDirectSoundFullDuplexImpl** ippDSFD=(IDirectSoundFullDuplexImpl**)ppDSFD;
1667 TRACE("(%s,%s,%p,%p,%lx,%lx,%p,%p,%p,%p)\n", debugstr_guid(pcGuidCaptureDevice),
1668 debugstr_guid(pcGuidRenderDevice), pcDSCBufferDesc, pcDSBufferDesc,
1669 (DWORD)hWnd, dwLevel, ppDSFD, ppDSCBuffer8, ppDSBuffer8, pUnkOuter);
1671 if ( pUnkOuter ) {
1672 WARN("pUnkOuter != 0\n");
1673 return DSERR_NOAGGREGATION;
1676 *ippDSFD = (IDirectSoundFullDuplexImpl*)HeapAlloc(GetProcessHeap(),
1677 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
1679 if (*ippDSFD == NULL) {
1680 WARN("out of memory\n");
1681 return DSERR_OUTOFMEMORY;
1682 } else {
1683 HRESULT hres;
1684 ICOM_THIS(IDirectSoundFullDuplexImpl, *ippDSFD);
1686 This->ref = 1;
1687 This->lpVtbl = &dsfdvt;
1689 InitializeCriticalSection( &(This->lock) );
1691 hres = IDirectSoundFullDuplexImpl_Initialize( (LPDIRECTSOUNDFULLDUPLEX)This,
1692 pcGuidCaptureDevice, pcGuidRenderDevice,
1693 pcDSCBufferDesc, pcDSBufferDesc,
1694 hWnd, dwLevel, ppDSCBuffer8, ppDSBuffer8);
1695 if (hres != DS_OK)
1696 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
1697 return hres;
1700 return DSERR_GENERIC;
1703 static HRESULT WINAPI
1704 IDirectSoundFullDuplexImpl_QueryInterface(
1705 LPDIRECTSOUNDFULLDUPLEX iface,
1706 REFIID riid,
1707 LPVOID* ppobj )
1709 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1710 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
1712 if (ppobj == NULL) {
1713 WARN("invalid parameter\n");
1714 return E_INVALIDARG;
1717 *ppobj = NULL;
1718 return E_NOINTERFACE;
1721 static ULONG WINAPI
1722 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
1724 ULONG uRef;
1725 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1726 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1728 EnterCriticalSection( &(This->lock) );
1730 uRef = ++(This->ref);
1732 LeaveCriticalSection( &(This->lock) );
1734 return uRef;
1737 static ULONG WINAPI
1738 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
1740 ULONG uRef;
1741 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1742 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1744 EnterCriticalSection( &(This->lock) );
1746 uRef = --(This->ref);
1748 LeaveCriticalSection( &(This->lock) );
1750 if ( uRef == 0 ) {
1751 DeleteCriticalSection( &(This->lock) );
1752 HeapFree( GetProcessHeap(), 0, This );
1753 TRACE("(%p) released\n",This);
1756 return uRef;
1759 static HRESULT WINAPI
1760 IDirectSoundFullDuplexImpl_Initialize(
1761 LPDIRECTSOUNDFULLDUPLEX iface,
1762 LPCGUID pCaptureGuid,
1763 LPCGUID pRendererGuid,
1764 LPCDSCBUFFERDESC lpDscBufferDesc,
1765 LPCDSBUFFERDESC lpDsBufferDesc,
1766 HWND hWnd,
1767 DWORD dwLevel,
1768 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
1769 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
1771 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1772 IDirectSoundCaptureBufferImpl** ippdscb=(IDirectSoundCaptureBufferImpl**)lplpDirectSoundCaptureBuffer8;
1773 IDirectSoundBufferImpl** ippdsc=(IDirectSoundBufferImpl**)lplpDirectSoundBuffer8;
1775 FIXME( "(%p,%s,%s,%p,%p,%lx,%lx,%p,%p) stub!\n", This, debugstr_guid(pCaptureGuid),
1776 debugstr_guid(pRendererGuid), lpDscBufferDesc, lpDsBufferDesc, (DWORD)hWnd, dwLevel,
1777 ippdscb, ippdsc);
1779 return E_FAIL;
1782 static ICOM_VTABLE(IDirectSoundFullDuplex) dsfdvt =
1784 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1785 /* IUnknown methods */
1786 IDirectSoundFullDuplexImpl_QueryInterface,
1787 IDirectSoundFullDuplexImpl_AddRef,
1788 IDirectSoundFullDuplexImpl_Release,
1790 /* IDirectSoundFullDuplex methods */
1791 IDirectSoundFullDuplexImpl_Initialize
1794 /*******************************************************************************
1795 * DirectSoundFullDuplex ClassFactory
1798 static HRESULT WINAPI
1799 DSFDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1801 ICOM_THIS(IClassFactoryImpl,iface);
1803 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1804 return E_NOINTERFACE;
1807 static ULONG WINAPI
1808 DSFDCF_AddRef(LPCLASSFACTORY iface)
1810 ICOM_THIS(IClassFactoryImpl,iface);
1811 TRACE("(%p) ref was %ld\n", This, This->ref);
1812 return ++(This->ref);
1815 static ULONG WINAPI
1816 DSFDCF_Release(LPCLASSFACTORY iface)
1818 ICOM_THIS(IClassFactoryImpl,iface);
1819 /* static class, won't be freed */
1820 TRACE("(%p) ref was %ld\n", This, This->ref);
1821 return --(This->ref);
1824 static HRESULT WINAPI
1825 DSFDCF_CreateInstance(
1826 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1828 ICOM_THIS(IClassFactoryImpl,iface);
1830 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1832 if (ppobj == NULL) {
1833 WARN("invalid parameter\n");
1834 return E_INVALIDARG;
1837 *ppobj = NULL;
1839 if ( IsEqualGUID( &IID_IDirectSoundFullDuplex, riid ) ) {
1840 /* FIXME: how do we do this one ? */
1841 FIXME("not implemented\n");
1842 return E_NOINTERFACE;
1845 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1846 return E_NOINTERFACE;
1849 static HRESULT WINAPI
1850 DSFDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1852 ICOM_THIS(IClassFactoryImpl,iface);
1853 FIXME("(%p)->(%d),stub!\n",This,dolock);
1854 return S_OK;
1857 static ICOM_VTABLE(IClassFactory) DSFDCF_Vtbl =
1859 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1860 DSFDCF_QueryInterface,
1861 DSFDCF_AddRef,
1862 DSFDCF_Release,
1863 DSFDCF_CreateInstance,
1864 DSFDCF_LockServer
1867 IClassFactoryImpl DSOUND_FULLDUPLEX_CF = { &DSFDCF_Vtbl, 1 };