Save enumerated GUIDs in a global array so they persist after
[wine/hacks.git] / dlls / dsound / capture.c
blobb8c526c19e135a033a7b299310b95cd6474c472b
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;
83 static GUID capture_guids[MAXWAVEDRIVERS];
85 static const char * captureStateString[] = {
86 "STATE_STOPPED",
87 "STATE_STARTING",
88 "STATE_CAPTURING",
89 "STATE_STOPPING"
92 /***************************************************************************
93 * DirectSoundCaptureCreate [DSOUND.6]
95 * Create and initialize a DirectSoundCapture interface.
97 * PARAMS
98 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
99 * lplpDSC [O] Address of a variable to receive the interface pointer.
100 * pUnkOuter [I] Must be NULL.
102 * RETURNS
103 * Success: DS_OK
104 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
105 * DSERR_OUTOFMEMORY
107 * NOTES
108 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
109 * or NULL for the default device or DSDEVID_DefaultCapture or
110 * DSDEVID_DefaultVoiceCapture.
112 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
114 HRESULT WINAPI
115 DirectSoundCaptureCreate8(
116 LPCGUID lpcGUID,
117 LPDIRECTSOUNDCAPTURE* lplpDSC,
118 LPUNKNOWN pUnkOuter )
120 IDirectSoundCaptureImpl** ippDSC=(IDirectSoundCaptureImpl**)lplpDSC;
121 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter);
123 if ( pUnkOuter ) {
124 WARN("invalid parameter: pUnkOuter != NULL\n");
125 return DSERR_NOAGGREGATION;
128 if ( !lplpDSC ) {
129 WARN("invalid parameter: lplpDSC == NULL\n");
130 return DSERR_INVALIDPARAM;
133 /* Default device? */
134 if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
135 lpcGUID = &DSDEVID_DefaultCapture;
137 *ippDSC = (IDirectSoundCaptureImpl*)HeapAlloc(GetProcessHeap(),
138 HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureImpl));
140 if (*ippDSC == NULL) {
141 WARN("out of memory\n");
142 return DSERR_OUTOFMEMORY;
143 } else {
144 ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC);
146 This->ref = 1;
147 This->state = STATE_STOPPED;
149 InitializeCriticalSection( &(This->lock) );
151 This->lpVtbl = &dscvt;
152 dsound_capture = This;
154 if (GetDeviceID(lpcGUID, &This->guid) == DS_OK) {
155 HRESULT hres;
156 hres = IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE)This, &This->guid);
157 if (hres != DS_OK)
158 WARN("IDirectSoundCaptureImpl_Initialize failed\n");
159 return hres;
162 WARN("invalid GUID: %s\n", debugstr_guid(lpcGUID));
163 return DSERR_INVALIDPARAM;
166 /***************************************************************************
167 * DirectSoundCaptureEnumerateA [DSOUND.7]
169 * Enumerate all DirectSound drivers installed in the system.
171 * PARAMS
172 * lpDSEnumCallback [I] Address of callback function.
173 * lpContext [I] Address of user defined context passed to callback function.
175 * RETURNS
176 * Success: DS_OK
177 * Failure: DSERR_INVALIDPARAM
179 HRESULT WINAPI
180 DirectSoundCaptureEnumerateA(
181 LPDSENUMCALLBACKA lpDSEnumCallback,
182 LPVOID lpContext)
184 unsigned devs, wid;
185 DSDRIVERDESC desc;
186 GUID guid;
187 int err;
189 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
191 if (lpDSEnumCallback == NULL) {
192 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
193 return DSERR_INVALIDPARAM;
196 devs = waveInGetNumDevs();
197 if (devs > 0) {
198 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
199 GUID temp;
200 for (wid = 0; wid < devs; ++wid) {
201 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
202 if (err == DS_OK) {
203 if (IsEqualGUID( &guid, &temp ) ) {
204 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
205 if (err == DS_OK) {
206 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
207 "Primary Sound Capture Driver",desc.szDrvName,lpContext);
208 if (lpDSEnumCallback(NULL, "Primary Sound Capture Driver", desc.szDrvName, lpContext) == FALSE)
209 return DS_OK;
217 for (wid = 0; wid < devs; ++wid) {
218 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
219 if (err == DS_OK) {
220 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&capture_guids[wid],0));
221 if (err == DS_OK) {
222 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
223 debugstr_guid(&capture_guids[wid]),desc.szDesc,desc.szDrvName,lpContext);
224 if (lpDSEnumCallback(&capture_guids[wid], desc.szDesc, desc.szDrvName, lpContext) == FALSE)
225 return DS_OK;
230 return DS_OK;
233 /***************************************************************************
234 * DirectSoundCaptureEnumerateW [DSOUND.8]
236 * Enumerate all DirectSound drivers installed in the system.
238 * PARAMS
239 * lpDSEnumCallback [I] Address of callback function.
240 * lpContext [I] Address of user defined context passed to callback function.
242 * RETURNS
243 * Success: DS_OK
244 * Failure: DSERR_INVALIDPARAM
246 HRESULT WINAPI
247 DirectSoundCaptureEnumerateW(
248 LPDSENUMCALLBACKW lpDSEnumCallback,
249 LPVOID lpContext)
251 unsigned devs, wid;
252 DSDRIVERDESC desc;
253 GUID guid;
254 int err;
255 WCHAR wDesc[MAXPNAMELEN];
256 WCHAR wName[MAXPNAMELEN];
258 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
260 if (lpDSEnumCallback == NULL) {
261 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
262 return DSERR_INVALIDPARAM;
265 devs = waveInGetNumDevs();
266 if (devs > 0) {
267 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
268 GUID temp;
269 for (wid = 0; wid < devs; ++wid) {
270 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
271 if (err == DS_OK) {
272 if (IsEqualGUID( &guid, &temp ) ) {
273 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
274 if (err == DS_OK) {
275 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
276 "Primary Sound Capture Driver",desc.szDrvName,lpContext);
277 MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
278 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
279 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
280 wName, sizeof(wName)/sizeof(WCHAR) );
281 if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
282 return DS_OK;
290 for (wid = 0; wid < devs; ++wid) {
291 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
292 if (err == DS_OK) {
293 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&capture_guids[wid],0));
294 if (err == DS_OK) {
295 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
296 debugstr_guid(&capture_guids[wid]),desc.szDesc,desc.szDrvName,lpContext);
297 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
298 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
299 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
300 wName, sizeof(wName)/sizeof(WCHAR) );
301 if (lpDSEnumCallback((LPGUID)&capture_guids[wid], wDesc, wName, lpContext) == FALSE)
302 return DS_OK;
307 return DS_OK;
310 static void CALLBACK
311 DSOUND_capture_callback(
312 HWAVEIN hwi,
313 UINT msg,
314 DWORD dwUser,
315 DWORD dw1,
316 DWORD dw2 )
318 IDirectSoundCaptureImpl* This = (IDirectSoundCaptureImpl*)dwUser;
319 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi,msg,
320 msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
321 msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
323 if (msg == MM_WIM_DATA) {
324 LPWAVEHDR pHdr = (LPWAVEHDR)dw1;
325 EnterCriticalSection( &(This->lock) );
326 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
327 captureStateString[This->state],This->index);
328 if (This->state != STATE_STOPPED) {
329 int index = This->index;
330 if (This->state == STATE_STARTING) {
331 This->read_position = pHdr->dwBytesRecorded;
332 This->state = STATE_CAPTURING;
334 waveInUnprepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR));
335 if (This->capture_buffer->nrofnotifies)
336 SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
337 This->index = (This->index + 1) % This->nrofpwaves;
338 if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
339 TRACE("end of buffer\n");
340 This->state = STATE_STOPPED;
341 } else {
342 if (This->state == STATE_CAPTURING) {
343 waveInPrepareHeader(hwi,&(This->pwave[index]),sizeof(WAVEHDR));
344 waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
345 } else if (This->state == STATE_STOPPING) {
346 TRACE("stopping\n");
347 This->state = STATE_STOPPED;
351 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
352 captureStateString[This->state],This->index);
353 LeaveCriticalSection( &(This->lock) );
356 TRACE("completed\n");
359 static HRESULT WINAPI
360 IDirectSoundCaptureImpl_QueryInterface(
361 LPDIRECTSOUNDCAPTURE iface,
362 REFIID riid,
363 LPVOID* ppobj )
365 ICOM_THIS(IDirectSoundCaptureImpl,iface);
366 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
368 if (ppobj == NULL) {
369 WARN("invalid parameter\n");
370 return E_INVALIDARG;
373 *ppobj = NULL;
375 if (This->driver) {
376 HRESULT hres;
377 hres = IDsCaptureDriver_QueryInterface(This->driver, riid, ppobj);
378 if (hres != DS_OK)
379 WARN("IDsCaptureDriver_QueryInterface failed\n");
380 return hres;
383 WARN("unsupported riid: %s\n", debugstr_guid(riid));
384 return E_FAIL;
387 static ULONG WINAPI
388 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
390 ULONG uRef;
391 ICOM_THIS(IDirectSoundCaptureImpl,iface);
392 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
394 EnterCriticalSection( &(This->lock) );
395 uRef = ++(This->ref);
397 if (This->driver)
398 IDsCaptureDriver_AddRef(This->driver);
400 LeaveCriticalSection( &(This->lock) );
402 return uRef;
405 static ULONG WINAPI
406 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
408 ULONG uRef;
409 ICOM_THIS(IDirectSoundCaptureImpl,iface);
410 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
412 EnterCriticalSection( &(This->lock) );
414 uRef = --(This->ref);
416 LeaveCriticalSection( &(This->lock) );
418 if ( uRef == 0 ) {
419 TRACE("deleting object\n");
420 if (This->driver) {
421 IDsCaptureDriver_Close(This->driver);
422 IDsCaptureDriver_Release(This->driver);
425 if (This->capture_buffer)
426 IDirectSoundCaptureBufferImpl_Release(
427 (LPDIRECTSOUNDCAPTUREBUFFER8) This->capture_buffer);
429 if (This->pwfx)
430 HeapFree(GetProcessHeap(), 0, This->pwfx);
432 DeleteCriticalSection( &(This->lock) );
433 HeapFree( GetProcessHeap(), 0, This );
434 dsound_capture = NULL;
435 TRACE("(%p) released\n",This);
438 return uRef;
441 static HRESULT WINAPI
442 IDirectSoundCaptureImpl_CreateCaptureBuffer(
443 LPDIRECTSOUNDCAPTURE iface,
444 LPCDSCBUFFERDESC lpcDSCBufferDesc,
445 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
446 LPUNKNOWN pUnk )
448 HRESULT hr;
449 ICOM_THIS(IDirectSoundCaptureImpl,iface);
451 TRACE( "(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk );
453 if (This == NULL) {
454 WARN("invalid parameter: This == NULL\n");
455 return DSERR_INVALIDPARAM;
458 if (lpcDSCBufferDesc == NULL) {
459 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
460 return DSERR_INVALIDPARAM;
463 if (lplpDSCaptureBuffer == NULL) {
464 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
465 return DSERR_INVALIDPARAM;
468 if (pUnk != NULL) {
469 WARN("invalid parameter: pUnk != NULL\n");
470 return DSERR_INVALIDPARAM;
473 /* FIXME: We can only have one buffer so what do we do here? */
474 if (This->capture_buffer) {
475 WARN("lnvalid parameter: already has buffer\n");
476 return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */
479 hr = DSOUND_CreateDirectSoundCaptureBuffer( This, lpcDSCBufferDesc,
480 (LPVOID*)lplpDSCaptureBuffer );
482 if (hr != DS_OK)
483 WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n");
485 return hr;
488 static HRESULT WINAPI
489 IDirectSoundCaptureImpl_GetCaps(
490 LPDIRECTSOUNDCAPTURE iface,
491 LPDSCCAPS lpDSCCaps )
493 ICOM_THIS(IDirectSoundCaptureImpl,iface);
494 TRACE("(%p,%p)\n",This,lpDSCCaps);
496 if (lpDSCCaps== NULL) {
497 WARN("invalid parameter: lpDSCCaps== NULL\n");
498 return DSERR_INVALIDPARAM;
501 if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
502 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
503 lpDSCCaps->dwSize, sizeof(*lpDSCCaps));
504 return DSERR_INVALIDPARAM;
507 if ( !(This->initialized) ) {
508 WARN("not initialized\n");
509 return DSERR_UNINITIALIZED;
512 lpDSCCaps->dwFlags = This->drvcaps.dwFlags;
513 lpDSCCaps->dwFormats = This->drvcaps.dwFormats;
514 lpDSCCaps->dwChannels = This->drvcaps.dwChannels;
516 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps->dwFlags,
517 lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
519 return DS_OK;
522 static HRESULT WINAPI
523 IDirectSoundCaptureImpl_Initialize(
524 LPDIRECTSOUNDCAPTURE iface,
525 LPCGUID lpcGUID )
527 HRESULT err = DSERR_INVALIDPARAM;
528 unsigned wid, widn;
529 ICOM_THIS(IDirectSoundCaptureImpl,iface);
530 TRACE("(%p)\n", This);
532 if (!This) {
533 WARN("invalid parameter: This == NULL\n");
534 return DSERR_INVALIDPARAM;
537 if (This->initialized) {
538 WARN("already initialized\n");
539 return DSERR_ALREADYINITIALIZED;
542 widn = waveInGetNumDevs();
544 if (!widn) {
545 WARN("no audio devices found\n");
546 return DSERR_NODRIVER;
549 /* Get dsound configuration */
550 setup_dsound_options();
552 /* enumerate WINMM audio devices and find the one we want */
553 for (wid=0; wid<widn; wid++) {
554 GUID guid;
555 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
556 if (err != DS_OK) {
557 WARN("waveInMessage failed; err=%lx\n",err);
558 return err;
560 if (IsEqualGUID( lpcGUID, &guid) ) {
561 err = DS_OK;
562 break;
566 if (err != DS_OK) {
567 WARN("invalid parameter\n");
568 return DSERR_INVALIDPARAM;
571 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&(This->driver),0));
572 if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
573 WARN("waveInMessage failed; err=%lx\n",err);
574 return err;
576 err = DS_OK;
578 /* Disable the direct sound driver to force emulation if requested. */
579 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
580 This->driver = NULL;
582 /* Get driver description */
583 if (This->driver) {
584 TRACE("using DirectSound driver\n");
585 err = IDsCaptureDriver_GetDriverDesc(This->driver, &(This->drvdesc));
586 if (err != DS_OK) {
587 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
588 return err;
590 } else {
591 TRACE("using WINMM\n");
592 /* if no DirectSound interface available, use WINMM API instead */
593 This->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |
594 DSDDESC_DOMMSYSTEMSETFORMAT;
597 This->drvdesc.dnDevNode = wid;
599 /* open the DirectSound driver if available */
600 if (This->driver && (err == DS_OK))
601 err = IDsCaptureDriver_Open(This->driver);
603 if (err == DS_OK) {
604 This->initialized = TRUE;
606 /* the driver is now open, so it's now allowed to call GetCaps */
607 if (This->driver) {
608 This->drvcaps.dwSize = sizeof(This->drvcaps);
609 err = IDsCaptureDriver_GetCaps(This->driver,&(This->drvcaps));
610 if (err != DS_OK) {
611 WARN("IDsCaptureDriver_GetCaps failed\n");
612 return err;
614 } else /*if (This->hwi)*/ {
615 WAVEINCAPSA wic;
616 err = mmErr(waveInGetDevCapsA((UINT)This->drvdesc.dnDevNode, &wic, sizeof(wic)));
618 if (err == DS_OK) {
619 This->drvcaps.dwFlags = 0;
620 strncpy(This->drvdesc.szDrvName, wic.szPname,
621 sizeof(This->drvdesc.szDrvName));
623 This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
624 This->drvcaps.dwFormats = wic.dwFormats;
625 This->drvcaps.dwChannels = wic.wChannels;
630 return err;
633 static ICOM_VTABLE(IDirectSoundCapture) dscvt =
635 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
636 /* IUnknown methods */
637 IDirectSoundCaptureImpl_QueryInterface,
638 IDirectSoundCaptureImpl_AddRef,
639 IDirectSoundCaptureImpl_Release,
641 /* IDirectSoundCapture methods */
642 IDirectSoundCaptureImpl_CreateCaptureBuffer,
643 IDirectSoundCaptureImpl_GetCaps,
644 IDirectSoundCaptureImpl_Initialize
647 static HRESULT
648 DSOUND_CreateDirectSoundCaptureBuffer(
649 IDirectSoundCaptureImpl *ipDSC,
650 LPCDSCBUFFERDESC lpcDSCBufferDesc,
651 LPVOID* ppobj )
653 LPWAVEFORMATEX wfex;
654 TRACE( "(%p,%p)\n", lpcDSCBufferDesc, ppobj );
656 if (ipDSC == NULL) {
657 WARN("invalid parameter: ipDSC == NULL\n");
658 return DSERR_INVALIDPARAM;
661 if (lpcDSCBufferDesc == NULL) {
662 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
663 return DSERR_INVALIDPARAM;
666 if (ppobj == NULL) {
667 WARN("invalid parameter: ppobj == NULL\n");
668 return DSERR_INVALIDPARAM;
671 if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) &&
672 (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) ||
673 (lpcDSCBufferDesc->dwBufferBytes == 0) ||
674 (lpcDSCBufferDesc->lpwfxFormat == NULL) ) {
675 WARN("invalid lpcDSCBufferDesc\n");
676 *ppobj = NULL;
677 return DSERR_INVALIDPARAM;
680 if ( !ipDSC->initialized ) {
681 WARN("not initialized\n");
682 *ppobj = NULL;
683 return DSERR_UNINITIALIZED;
686 wfex = lpcDSCBufferDesc->lpwfxFormat;
688 if (wfex) {
689 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
690 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
691 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
692 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
693 wfex->wBitsPerSample, wfex->cbSize);
695 if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
696 ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX));
697 memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX));
698 ipDSC->pwfx->cbSize = 0;
699 } else {
700 ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize);
701 memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize);
703 } else {
704 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
705 *ppobj = NULL;
706 return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */
709 *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
710 sizeof(IDirectSoundCaptureBufferImpl));
712 if ( *ppobj == NULL ) {
713 WARN("out of memory\n");
714 *ppobj = NULL;
715 return DSERR_OUTOFMEMORY;
716 } else {
717 HRESULT err = DS_OK;
718 ICOM_THIS(IDirectSoundCaptureBufferImpl,*ppobj);
720 This->ref = 1;
721 This->dsound = ipDSC;
722 This->dsound->capture_buffer = This;
723 This->notify = NULL;
724 This->nrofnotifies = 0;
725 This->hwnotify = NULL;
727 This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
728 lpcDSCBufferDesc->dwSize);
729 if (This->pdscbd)
730 memcpy(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
731 else {
732 WARN("no memory\n");
733 This->dsound->capture_buffer = 0;
734 HeapFree( GetProcessHeap(), 0, This );
735 *ppobj = NULL;
736 return DSERR_OUTOFMEMORY;
739 This->lpVtbl = &dscbvt;
741 if (ipDSC->driver) {
742 err = IDsCaptureDriver_CreateCaptureBuffer(ipDSC->driver,
743 ipDSC->pwfx,0,0,&(ipDSC->buflen),&(ipDSC->buffer),(LPVOID*)&(ipDSC->hwbuf));
744 if (err != DS_OK) {
745 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
746 This->dsound->capture_buffer = 0;
747 HeapFree( GetProcessHeap(), 0, This );
748 *ppobj = NULL;
749 return err;
751 } else {
752 LPBYTE newbuf;
753 DWORD buflen;
754 DWORD flags = CALLBACK_FUNCTION;
755 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
756 flags |= WAVE_DIRECTSOUND;
757 err = mmErr(waveInOpen(&(ipDSC->hwi),
758 ipDSC->drvdesc.dnDevNode, ipDSC->pwfx,
759 (DWORD)DSOUND_capture_callback, (DWORD)ipDSC, flags));
760 if (err != DS_OK) {
761 WARN("waveInOpen failed\n");
762 This->dsound->capture_buffer = 0;
763 HeapFree( GetProcessHeap(), 0, This );
764 *ppobj = NULL;
765 return err;
768 buflen = lpcDSCBufferDesc->dwBufferBytes;
769 TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->buffer);
770 if (ipDSC->buffer)
771 newbuf = (LPBYTE)HeapReAlloc(GetProcessHeap(),0,ipDSC->buffer,buflen);
772 else
773 newbuf = (LPBYTE)HeapAlloc(GetProcessHeap(),0,buflen);
774 if (newbuf == NULL) {
775 WARN("failed to allocate capture buffer\n");
776 err = DSERR_OUTOFMEMORY;
777 /* but the old buffer might still exist and must be re-prepared */
778 } else {
779 ipDSC->buffer = newbuf;
780 ipDSC->buflen = buflen;
785 TRACE("returning DS_OK\n");
786 return DS_OK;
789 /*******************************************************************************
790 * IDirectSoundCaptureNotify
792 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
793 LPDIRECTSOUNDNOTIFY iface,
794 REFIID riid,
795 LPVOID *ppobj)
797 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
798 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
800 if (This->dscb == NULL) {
801 WARN("invalid parameter\n");
802 return E_INVALIDARG;
805 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
808 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
810 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
811 DWORD ref;
813 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
815 ref = InterlockedIncrement(&(This->ref));
816 return ref;
819 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
821 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
822 DWORD ref;
824 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
826 ref = InterlockedDecrement(&(This->ref));
827 if (ref == 0) {
828 if (This->dscb->hwnotify)
829 IDsDriverNotify_Release(This->dscb->hwnotify);
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 (howmuch > 0 && 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 if (howmuch > 0) {
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;
880 } else {
881 if (This->dscb->notifies) {
882 HeapFree(GetProcessHeap(), 0, This->dscb->notifies);
883 This->dscb->notifies = NULL;
885 This->dscb->nrofnotifies = 0;
888 return S_OK;
891 ICOM_VTABLE(IDirectSoundNotify) dscnvt =
893 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
894 IDirectSoundCaptureNotifyImpl_QueryInterface,
895 IDirectSoundCaptureNotifyImpl_AddRef,
896 IDirectSoundCaptureNotifyImpl_Release,
897 IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
900 HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create(
901 IDirectSoundCaptureBufferImpl *dscb,
902 IDirectSoundCaptureNotifyImpl **pdscn)
904 IDirectSoundCaptureNotifyImpl * dscn;
905 TRACE("(%p,%p)\n",dscb,pdscn);
907 dscn = (IDirectSoundCaptureNotifyImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dscn));
909 if (dscn == NULL) {
910 WARN("out of memory\n");
911 return DSERR_OUTOFMEMORY;
914 dscn->ref = 0;
915 dscn->lpVtbl = &dscnvt;
916 dscn->dscb = dscb;
917 dscb->notify = dscn;
918 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
920 *pdscn = dscn;
921 return DS_OK;
924 /*******************************************************************************
925 * IDirectSoundCaptureBuffer
927 static HRESULT WINAPI
928 IDirectSoundCaptureBufferImpl_QueryInterface(
929 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
930 REFIID riid,
931 LPVOID* ppobj )
933 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
934 HRESULT hres;
935 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
937 if (ppobj == NULL) {
938 WARN("invalid parameter\n");
939 return E_INVALIDARG;
942 *ppobj = NULL;
944 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ||
945 IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) {
946 if (!This->notify)
947 hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
948 if (This->notify) {
949 if (This->dsound->hwbuf) {
950 hres = IDsCaptureDriverBuffer_QueryInterface(This->dsound->hwbuf,
951 &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
952 if (hres != DS_OK) {
953 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
954 *ppobj = 0;
955 return hres;
959 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
960 *ppobj = (LPVOID)This->notify;
961 return DS_OK;
964 WARN("IID_IDirectSoundNotify\n");
965 return E_FAIL;
968 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
969 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
970 IDirectSoundCaptureBuffer8_AddRef(iface);
971 *ppobj = This;
972 return NO_ERROR;
975 FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
976 return E_NOINTERFACE;
979 static ULONG WINAPI
980 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
982 ULONG uRef;
983 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
984 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
986 assert(This->dsound);
988 EnterCriticalSection( &(This->dsound->lock) );
990 uRef = ++(This->ref);
992 LeaveCriticalSection( &(This->dsound->lock) );
994 return uRef;
997 static ULONG WINAPI
998 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
1000 ULONG uRef;
1001 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1002 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1004 assert(This->dsound);
1006 EnterCriticalSection( &(This->dsound->lock) );
1008 uRef = --(This->ref);
1010 LeaveCriticalSection( &(This->dsound->lock) );
1012 if ( uRef == 0 ) {
1013 TRACE("deleting object\n");
1014 if (This->pdscbd)
1015 HeapFree(GetProcessHeap(),0, This->pdscbd);
1017 if (This->dsound->hwi) {
1018 waveInReset(This->dsound->hwi);
1019 waveInClose(This->dsound->hwi);
1020 if (This->dsound->pwave) {
1021 HeapFree(GetProcessHeap(),0, This->dsound->pwave);
1022 This->dsound->pwave = 0;
1024 This->dsound->hwi = 0;
1027 if (This->dsound->hwbuf)
1028 IDsCaptureDriverBuffer_Release(This->dsound->hwbuf);
1030 /* remove from IDirectSoundCaptureImpl */
1031 if (This->dsound)
1032 This->dsound->capture_buffer = NULL;
1033 else
1034 ERR("does not reference dsound\n");
1036 if (This->notify)
1037 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
1039 if (This->notifies != NULL)
1040 HeapFree(GetProcessHeap(), 0, This->notifies);
1042 HeapFree( GetProcessHeap(), 0, This );
1043 TRACE("(%p) released\n",This);
1046 return uRef;
1049 static HRESULT WINAPI
1050 IDirectSoundCaptureBufferImpl_GetCaps(
1051 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1052 LPDSCBCAPS lpDSCBCaps )
1054 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1055 TRACE( "(%p,%p)\n", This, lpDSCBCaps );
1057 if (This == NULL) {
1058 WARN("invalid parameter: This == NULL\n");
1059 return DSERR_INVALIDPARAM;
1062 if (lpDSCBCaps == NULL) {
1063 WARN("invalid parameter: lpDSCBCaps == NULL\n");
1064 return DSERR_INVALIDPARAM;
1067 if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) {
1068 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
1069 lpDSCBCaps->dwSize, sizeof(DSCBCAPS));
1070 return DSERR_INVALIDPARAM;
1073 if (This->dsound == NULL) {
1074 WARN("invalid parameter: This->dsound == NULL\n");
1075 return DSERR_INVALIDPARAM;
1078 lpDSCBCaps->dwSize = sizeof(DSCBCAPS);
1079 lpDSCBCaps->dwFlags = This->flags;
1080 lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes;
1081 lpDSCBCaps->dwReserved = 0;
1083 TRACE("returning DS_OK\n");
1084 return DS_OK;
1087 static HRESULT WINAPI
1088 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
1089 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1090 LPDWORD lpdwCapturePosition,
1091 LPDWORD lpdwReadPosition )
1093 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1094 TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
1096 if (This == NULL) {
1097 WARN("invalid parameter: This == NULL\n");
1098 return DSERR_INVALIDPARAM;
1101 if (This->dsound == NULL) {
1102 WARN("invalid parameter: This->dsound == NULL\n");
1103 return DSERR_INVALIDPARAM;
1106 if (This->dsound->driver) {
1107 HRESULT hres;
1108 hres = IDsCaptureDriverBuffer_GetPosition(This->dsound->hwbuf, lpdwCapturePosition, lpdwReadPosition );
1109 if (hres != DS_OK) {
1110 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
1111 return hres;
1113 } else if (This->dsound->hwi) {
1114 EnterCriticalSection(&(This->dsound->lock));
1115 TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1116 if (lpdwCapturePosition) {
1117 MMTIME mtime;
1118 mtime.wType = TIME_BYTES;
1119 waveInGetPosition(This->dsound->hwi, &mtime, sizeof(mtime));
1120 TRACE("mtime.u.cb=%ld,This->dsound->buflen=%ld\n", mtime.u.cb,
1121 This->dsound->buflen);
1122 mtime.u.cb = mtime.u.cb % This->dsound->buflen;
1123 *lpdwCapturePosition = mtime.u.cb;
1126 if (lpdwReadPosition) {
1127 if (This->dsound->state == STATE_STARTING) {
1128 if (lpdwCapturePosition)
1129 This->dsound->read_position = *lpdwCapturePosition;
1130 This->dsound->state = STATE_CAPTURING;
1132 *lpdwReadPosition = This->dsound->read_position;
1134 TRACE("new This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1135 LeaveCriticalSection(&(This->dsound->lock));
1136 if (lpdwCapturePosition) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition);
1137 if (lpdwReadPosition) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition);
1138 } else {
1139 WARN("no driver\n");
1140 return DSERR_NODRIVER;
1143 TRACE("returning DS_OK\n");
1144 return DS_OK;
1147 static HRESULT WINAPI
1148 IDirectSoundCaptureBufferImpl_GetFormat(
1149 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1150 LPWAVEFORMATEX lpwfxFormat,
1151 DWORD dwSizeAllocated,
1152 LPDWORD lpdwSizeWritten )
1154 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1155 TRACE( "(%p,%p,0x%08lx,%p)\n", This, lpwfxFormat, dwSizeAllocated,
1156 lpdwSizeWritten );
1158 if (This == NULL) {
1159 WARN("invalid parameter: This == NULL\n");
1160 return DSERR_INVALIDPARAM;
1163 if (This->dsound == NULL) {
1164 WARN("invalid parameter: This->dsound == NULL\n");
1165 return DSERR_INVALIDPARAM;
1168 if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize))
1169 dwSizeAllocated = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
1171 if (lpwfxFormat) { /* NULL is valid (just want size) */
1172 memcpy(lpwfxFormat, This->dsound->pwfx, dwSizeAllocated);
1173 if (lpdwSizeWritten)
1174 *lpdwSizeWritten = dwSizeAllocated;
1175 } else {
1176 if (lpdwSizeWritten)
1177 *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
1178 else {
1179 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
1180 return DSERR_INVALIDPARAM;
1184 TRACE("returning DS_OK\n");
1185 return DS_OK;
1188 static HRESULT WINAPI
1189 IDirectSoundCaptureBufferImpl_GetStatus(
1190 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1191 LPDWORD lpdwStatus )
1193 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1194 TRACE( "(%p, %p), thread is %04lx\n", This, lpdwStatus, GetCurrentThreadId() );
1196 if (This == NULL) {
1197 WARN("invalid parameter: This == NULL\n");
1198 return DSERR_INVALIDPARAM;
1201 if (This->dsound == NULL) {
1202 WARN("invalid parameter: This->dsound == NULL\n");
1203 return DSERR_INVALIDPARAM;
1206 if (lpdwStatus == NULL) {
1207 WARN("invalid parameter: lpdwStatus == NULL\n");
1208 return DSERR_INVALIDPARAM;
1211 *lpdwStatus = 0;
1212 EnterCriticalSection(&(This->dsound->lock));
1214 TRACE("old This->dsound->state=%s, old lpdwStatus=%08lx\n",
1215 captureStateString[This->dsound->state],*lpdwStatus);
1216 if ((This->dsound->state == STATE_STARTING) ||
1217 (This->dsound->state == STATE_CAPTURING)) {
1218 *lpdwStatus |= DSCBSTATUS_CAPTURING;
1219 if (This->flags & DSCBSTART_LOOPING)
1220 *lpdwStatus |= DSCBSTATUS_LOOPING;
1222 TRACE("new This->dsound->state=%s, new lpdwStatus=%08lx\n",
1223 captureStateString[This->dsound->state],*lpdwStatus);
1224 LeaveCriticalSection(&(This->dsound->lock));
1226 TRACE("status=%lx\n", *lpdwStatus);
1227 TRACE("returning DS_OK\n");
1228 return DS_OK;
1231 static HRESULT WINAPI
1232 IDirectSoundCaptureBufferImpl_Initialize(
1233 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1234 LPDIRECTSOUNDCAPTURE lpDSC,
1235 LPCDSCBUFFERDESC lpcDSCBDesc )
1237 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1239 FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
1241 return DS_OK;
1244 static HRESULT WINAPI
1245 IDirectSoundCaptureBufferImpl_Lock(
1246 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1247 DWORD dwReadCusor,
1248 DWORD dwReadBytes,
1249 LPVOID* lplpvAudioPtr1,
1250 LPDWORD lpdwAudioBytes1,
1251 LPVOID* lplpvAudioPtr2,
1252 LPDWORD lpdwAudioBytes2,
1253 DWORD dwFlags )
1255 HRESULT err = DS_OK;
1256 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1257 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This, dwReadCusor,
1258 dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
1259 lpdwAudioBytes2, dwFlags, GetTickCount() );
1261 if (This == NULL) {
1262 WARN("invalid parameter: This == NULL\n");
1263 return DSERR_INVALIDPARAM;
1266 if (This->dsound == NULL) {
1267 WARN("invalid parameter: This->dsound == NULL\n");
1268 return DSERR_INVALIDPARAM;
1271 if (lplpvAudioPtr1 == NULL) {
1272 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1273 return DSERR_INVALIDPARAM;
1276 if (lpdwAudioBytes1 == NULL) {
1277 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1278 return DSERR_INVALIDPARAM;
1281 EnterCriticalSection(&(This->dsound->lock));
1283 if (This->dsound->driver) {
1284 err = IDsCaptureDriverBuffer_Lock(This->dsound->hwbuf, lplpvAudioPtr1,
1285 lpdwAudioBytes1, lplpvAudioPtr2, lpdwAudioBytes2,
1286 dwReadCusor, dwReadBytes, dwFlags);
1287 if (err != DS_OK)
1288 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1289 } else if (This->dsound->hwi) {
1290 *lplpvAudioPtr1 = This->dsound->buffer + dwReadCusor;
1291 if ( (dwReadCusor + dwReadBytes) > This->dsound->buflen) {
1292 *lpdwAudioBytes1 = This->dsound->buflen - dwReadCusor;
1293 if (lplpvAudioPtr2)
1294 *lplpvAudioPtr2 = This->dsound->buffer;
1295 if (lpdwAudioBytes2)
1296 *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
1297 } else {
1298 *lpdwAudioBytes1 = dwReadBytes;
1299 if (lplpvAudioPtr2)
1300 *lplpvAudioPtr2 = 0;
1301 if (lpdwAudioBytes2)
1302 *lpdwAudioBytes2 = 0;
1304 } else {
1305 TRACE("invalid call\n");
1306 err = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */
1309 LeaveCriticalSection(&(This->dsound->lock));
1311 return err;
1314 static HRESULT WINAPI
1315 IDirectSoundCaptureBufferImpl_Start(
1316 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1317 DWORD dwFlags )
1319 HRESULT err = DS_OK;
1320 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1321 TRACE( "(%p,0x%08lx)\n", This, dwFlags );
1323 if (This == NULL) {
1324 WARN("invalid parameter: This == NULL\n");
1325 return DSERR_INVALIDPARAM;
1328 if (This->dsound == NULL) {
1329 WARN("invalid parameter: This->dsound == NULL\n");
1330 return DSERR_INVALIDPARAM;
1333 if ( (This->dsound->driver == 0) && (This->dsound->hwi == 0) ) {
1334 WARN("no driver\n");
1335 return DSERR_NODRIVER;
1338 EnterCriticalSection(&(This->dsound->lock));
1340 This->flags = dwFlags;
1341 TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1342 if (This->dsound->state == STATE_STOPPED)
1343 This->dsound->state = STATE_STARTING;
1344 else if (This->dsound->state == STATE_STOPPING)
1345 This->dsound->state = STATE_CAPTURING;
1346 TRACE("new This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1348 LeaveCriticalSection(&(This->dsound->lock));
1350 if (This->dsound->driver) {
1351 err = IDsCaptureDriverBuffer_Start(This->dsound->hwbuf, dwFlags);
1352 if (err != DS_OK)
1353 WARN("IDsCaptureDriverBuffer_Start failed\n");
1354 return err;
1355 } else {
1356 IDirectSoundCaptureImpl* ipDSC = This->dsound;
1358 if (ipDSC->buffer) {
1359 if (This->nrofnotifies) {
1360 unsigned c;
1362 ipDSC->nrofpwaves = This->nrofnotifies;
1363 TRACE("nrofnotifies=%d\n", This->nrofnotifies);
1365 /* prepare headers */
1366 if (ipDSC->pwave)
1367 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,
1368 ipDSC->nrofpwaves*sizeof(WAVEHDR));
1369 else
1370 ipDSC->pwave = HeapAlloc(GetProcessHeap(),0,
1371 ipDSC->nrofpwaves*sizeof(WAVEHDR));
1373 for (c = 0; c < ipDSC->nrofpwaves; c++) {
1374 if (This->notifies[c].dwOffset == DSBPN_OFFSETSTOP) {
1375 TRACE("got DSBPN_OFFSETSTOP\n");
1376 ipDSC->nrofpwaves = c;
1377 break;
1379 if (c == 0) {
1380 ipDSC->pwave[0].lpData = ipDSC->buffer;
1381 ipDSC->pwave[0].dwBufferLength =
1382 This->notifies[0].dwOffset + 1;
1383 } else {
1384 ipDSC->pwave[c].lpData = ipDSC->buffer +
1385 This->notifies[c-1].dwOffset + 1;
1386 ipDSC->pwave[c].dwBufferLength =
1387 This->notifies[c].dwOffset -
1388 This->notifies[c-1].dwOffset;
1390 ipDSC->pwave[c].dwBytesRecorded = 0;
1391 ipDSC->pwave[c].dwUser = (DWORD)ipDSC;
1392 ipDSC->pwave[c].dwFlags = 0;
1393 ipDSC->pwave[c].dwLoops = 0;
1394 err = mmErr(waveInPrepareHeader(ipDSC->hwi,
1395 &(ipDSC->pwave[c]),sizeof(WAVEHDR)));
1396 if (err != DS_OK) {
1397 WARN("waveInPrepareHeader failed\n");
1398 while (c--)
1399 waveInUnprepareHeader(ipDSC->hwi,
1400 &(ipDSC->pwave[c]),sizeof(WAVEHDR));
1401 break;
1404 err = mmErr(waveInAddBuffer(ipDSC->hwi,
1405 &(ipDSC->pwave[c]), sizeof(WAVEHDR)));
1406 if (err != DS_OK) {
1407 WARN("waveInAddBuffer failed\n");
1408 while (c--)
1409 waveInUnprepareHeader(ipDSC->hwi,
1410 &(ipDSC->pwave[c]),sizeof(WAVEHDR));
1411 break;
1415 memset(ipDSC->buffer,
1416 (ipDSC->pwfx->wBitsPerSample == 8) ? 128 : 0, ipDSC->buflen);
1417 } else {
1418 TRACE("no notifiers specified\n");
1419 /* no notifiers specified so just create a single default header */
1420 ipDSC->nrofpwaves = 1;
1421 if (ipDSC->pwave)
1422 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,sizeof(WAVEHDR));
1423 else
1424 ipDSC->pwave = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR));
1426 ipDSC->pwave[0].lpData = ipDSC->buffer;
1427 ipDSC->pwave[0].dwBufferLength = ipDSC->buflen;
1428 ipDSC->pwave[0].dwBytesRecorded = 0;
1429 ipDSC->pwave[0].dwUser = (DWORD)ipDSC;
1430 ipDSC->pwave[0].dwFlags = 0;
1431 ipDSC->pwave[0].dwLoops = 0;
1433 err = mmErr(waveInPrepareHeader(ipDSC->hwi,
1434 &(ipDSC->pwave[0]),sizeof(WAVEHDR)));
1435 if (err != DS_OK) {
1436 WARN("waveInPrepareHeader failed\n");
1437 waveInUnprepareHeader(ipDSC->hwi,
1438 &(ipDSC->pwave[0]),sizeof(WAVEHDR));
1440 err = mmErr(waveInAddBuffer(ipDSC->hwi,
1441 &(ipDSC->pwave[0]), sizeof(WAVEHDR)));
1442 if (err != DS_OK) {
1443 WARN("waveInAddBuffer failed\n");
1444 waveInUnprepareHeader(ipDSC->hwi,
1445 &(ipDSC->pwave[0]),sizeof(WAVEHDR));
1450 ipDSC->index = 0;
1451 ipDSC->read_position = 0;
1453 if (err == DS_OK) {
1454 /* start filling the first buffer */
1455 err = mmErr(waveInStart(ipDSC->hwi));
1456 if (err != DS_OK)
1457 WARN("waveInStart failed\n");
1461 if (err != DS_OK) {
1462 WARN("calling waveInClose because of error\n");
1463 waveInClose(This->dsound->hwi);
1464 This->dsound->hwi = 0;
1467 TRACE("returning %ld\n", err);
1468 return err;
1471 static HRESULT WINAPI
1472 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
1474 HRESULT err = DS_OK;
1475 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1476 TRACE( "(%p)\n", This );
1478 if (This == NULL) {
1479 WARN("invalid parameter: This == NULL\n");
1480 return DSERR_INVALIDPARAM;
1483 if (This->dsound == NULL) {
1484 WARN("invalid parameter: This->dsound == NULL\n");
1485 return DSERR_INVALIDPARAM;
1488 EnterCriticalSection(&(This->dsound->lock));
1490 TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1491 if (This->dsound->state == STATE_CAPTURING)
1492 This->dsound->state = STATE_STOPPING;
1493 else if (This->dsound->state == STATE_STARTING)
1494 This->dsound->state = STATE_STOPPED;
1495 TRACE("new This->dsound->state=%s\n",captureStateString[This->dsound->state]);
1497 LeaveCriticalSection(&(This->dsound->lock));
1499 if (This->dsound->driver) {
1500 err = IDsCaptureDriverBuffer_Stop(This->dsound->hwbuf);
1501 if (err == DSERR_BUFFERLOST) {
1502 /* Wine-only: the driver wants us to reopen the device */
1503 IDsCaptureDriverBuffer_Release(This->dsound->hwbuf);
1504 err = IDsCaptureDriver_CreateCaptureBuffer(This->dsound->driver,
1505 This->dsound->pwfx,0,0,&(This->dsound->buflen),&(This->dsound->buffer),
1506 (LPVOID*)&(This->dsound->hwbuf));
1507 if (err != DS_OK) {
1508 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1509 This->dsound->hwbuf = 0;
1511 } else if (err != DS_OK)
1512 WARN("IDsCaptureDriverBuffer_Stop failed\n");
1513 } else if (This->dsound->hwi) {
1514 err = waveInStop(This->dsound->hwi);
1515 } else {
1516 WARN("no driver\n");
1517 err = DSERR_NODRIVER;
1520 TRACE( "(%p) returning 0x%08lx\n", This,err);
1521 return err;
1524 static HRESULT WINAPI
1525 IDirectSoundCaptureBufferImpl_Unlock(
1526 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1527 LPVOID lpvAudioPtr1,
1528 DWORD dwAudioBytes1,
1529 LPVOID lpvAudioPtr2,
1530 DWORD dwAudioBytes2 )
1532 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1533 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This, lpvAudioPtr1, dwAudioBytes1,
1534 lpvAudioPtr2, dwAudioBytes2 );
1536 if (This == NULL) {
1537 WARN("invalid parameter: This == NULL\n");
1538 return DSERR_INVALIDPARAM;
1541 if (lpvAudioPtr1 == NULL) {
1542 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1543 return DSERR_INVALIDPARAM;
1546 if (This->dsound->driver) {
1547 HRESULT hres;
1548 hres = IDsCaptureDriverBuffer_Unlock(This->dsound->hwbuf, lpvAudioPtr1,
1549 dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
1550 if (hres != DS_OK)
1551 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1552 return hres;
1553 } else if (This->dsound->hwi) {
1554 This->dsound->read_position = (This->dsound->read_position +
1555 (dwAudioBytes1 + dwAudioBytes2)) % This->dsound->buflen;
1556 } else {
1557 WARN("invalid call\n");
1558 return DSERR_INVALIDCALL;
1561 return DS_OK;
1564 static HRESULT WINAPI
1565 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1566 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1567 REFGUID rguidObject,
1568 DWORD dwIndex,
1569 REFGUID rguidInterface,
1570 LPVOID* ppObject )
1572 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1574 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject),
1575 dwIndex, debugstr_guid(rguidInterface), ppObject );
1577 return DS_OK;
1580 static HRESULT WINAPI
1581 IDirectSoundCaptureBufferImpl_GetFXStatus(
1582 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1583 DWORD dwFXCount,
1584 LPDWORD pdwFXStatus )
1586 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1588 FIXME( "(%p,%lu,%p): stub\n", This, dwFXCount, pdwFXStatus );
1590 return DS_OK;
1593 static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt =
1595 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1596 /* IUnknown methods */
1597 IDirectSoundCaptureBufferImpl_QueryInterface,
1598 IDirectSoundCaptureBufferImpl_AddRef,
1599 IDirectSoundCaptureBufferImpl_Release,
1601 /* IDirectSoundCaptureBuffer methods */
1602 IDirectSoundCaptureBufferImpl_GetCaps,
1603 IDirectSoundCaptureBufferImpl_GetCurrentPosition,
1604 IDirectSoundCaptureBufferImpl_GetFormat,
1605 IDirectSoundCaptureBufferImpl_GetStatus,
1606 IDirectSoundCaptureBufferImpl_Initialize,
1607 IDirectSoundCaptureBufferImpl_Lock,
1608 IDirectSoundCaptureBufferImpl_Start,
1609 IDirectSoundCaptureBufferImpl_Stop,
1610 IDirectSoundCaptureBufferImpl_Unlock,
1612 /* IDirectSoundCaptureBuffer methods */
1613 IDirectSoundCaptureBufferImpl_GetObjectInPath,
1614 IDirectSoundCaptureBufferImpl_GetFXStatus
1617 /*******************************************************************************
1618 * DirectSoundCapture ClassFactory
1621 static HRESULT WINAPI
1622 DSCCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1624 ICOM_THIS(IClassFactoryImpl,iface);
1626 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1627 return E_NOINTERFACE;
1630 static ULONG WINAPI
1631 DSCCF_AddRef(LPCLASSFACTORY iface)
1633 ICOM_THIS(IClassFactoryImpl,iface);
1634 TRACE("(%p) ref was %ld\n", This, This->ref);
1635 return ++(This->ref);
1638 static ULONG WINAPI
1639 DSCCF_Release(LPCLASSFACTORY iface)
1641 ICOM_THIS(IClassFactoryImpl,iface);
1642 /* static class, won't be freed */
1643 TRACE("(%p) ref was %ld\n", This, This->ref);
1644 return --(This->ref);
1647 static HRESULT WINAPI
1648 DSCCF_CreateInstance(
1649 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1651 ICOM_THIS(IClassFactoryImpl,iface);
1652 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1654 if (ppobj == NULL) {
1655 WARN("invalid parameter\n");
1656 return E_INVALIDARG;
1659 *ppobj = NULL;
1661 if ( IsEqualGUID( &IID_IDirectSoundCapture, riid ) ||
1662 IsEqualGUID( &IID_IDirectSoundCapture8, riid ) ) {
1663 return DirectSoundCaptureCreate8(0,(LPDIRECTSOUNDCAPTURE8*)ppobj,pOuter);
1666 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1667 return E_NOINTERFACE;
1670 static HRESULT WINAPI
1671 DSCCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1673 ICOM_THIS(IClassFactoryImpl,iface);
1674 FIXME("(%p)->(%d),stub!\n",This,dolock);
1675 return S_OK;
1678 static ICOM_VTABLE(IClassFactory) DSCCF_Vtbl =
1680 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1681 DSCCF_QueryInterface,
1682 DSCCF_AddRef,
1683 DSCCF_Release,
1684 DSCCF_CreateInstance,
1685 DSCCF_LockServer
1688 IClassFactoryImpl DSOUND_CAPTURE_CF = { &DSCCF_Vtbl, 1 };
1690 /***************************************************************************
1691 * DirectSoundFullDuplexCreate [DSOUND.10]
1693 * Create and initialize a DirectSoundFullDuplex interface.
1695 * PARAMS
1696 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
1697 * pcGuidRenderDevice [I] Address of sound render device GUID.
1698 * pcDSCBufferDesc [I] Address of capture buffer description.
1699 * pcDSBufferDesc [I] Address of render buffer description.
1700 * hWnd [I] Handle to application window.
1701 * dwLevel [I] Cooperative level.
1702 * ppDSFD [O] Address where full duplex interface returned.
1703 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
1704 * ppDSBuffer8 [0] Address where render buffer interface returned.
1705 * pUnkOuter [I] Must be NULL.
1707 * RETURNS
1708 * Success: DS_OK
1709 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1710 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
1712 HRESULT WINAPI
1713 DirectSoundFullDuplexCreate(
1714 LPCGUID pcGuidCaptureDevice,
1715 LPCGUID pcGuidRenderDevice,
1716 LPCDSCBUFFERDESC pcDSCBufferDesc,
1717 LPCDSBUFFERDESC pcDSBufferDesc,
1718 HWND hWnd,
1719 DWORD dwLevel,
1720 LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
1721 LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
1722 LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
1723 LPUNKNOWN pUnkOuter)
1725 IDirectSoundFullDuplexImpl** ippDSFD=(IDirectSoundFullDuplexImpl**)ppDSFD;
1726 TRACE("(%s,%s,%p,%p,%lx,%lx,%p,%p,%p,%p)\n", debugstr_guid(pcGuidCaptureDevice),
1727 debugstr_guid(pcGuidRenderDevice), pcDSCBufferDesc, pcDSBufferDesc,
1728 (DWORD)hWnd, dwLevel, ppDSFD, ppDSCBuffer8, ppDSBuffer8, pUnkOuter);
1730 if ( pUnkOuter ) {
1731 WARN("pUnkOuter != 0\n");
1732 return DSERR_NOAGGREGATION;
1735 *ippDSFD = (IDirectSoundFullDuplexImpl*)HeapAlloc(GetProcessHeap(),
1736 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
1738 if (*ippDSFD == NULL) {
1739 WARN("out of memory\n");
1740 return DSERR_OUTOFMEMORY;
1741 } else {
1742 HRESULT hres;
1743 ICOM_THIS(IDirectSoundFullDuplexImpl, *ippDSFD);
1745 This->ref = 1;
1746 This->lpVtbl = &dsfdvt;
1748 InitializeCriticalSection( &(This->lock) );
1750 hres = IDirectSoundFullDuplexImpl_Initialize( (LPDIRECTSOUNDFULLDUPLEX)This,
1751 pcGuidCaptureDevice, pcGuidRenderDevice,
1752 pcDSCBufferDesc, pcDSBufferDesc,
1753 hWnd, dwLevel, ppDSCBuffer8, ppDSBuffer8);
1754 if (hres != DS_OK)
1755 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
1756 return hres;
1759 return DSERR_GENERIC;
1762 static HRESULT WINAPI
1763 IDirectSoundFullDuplexImpl_QueryInterface(
1764 LPDIRECTSOUNDFULLDUPLEX iface,
1765 REFIID riid,
1766 LPVOID* ppobj )
1768 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1769 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
1771 if (ppobj == NULL) {
1772 WARN("invalid parameter\n");
1773 return E_INVALIDARG;
1776 *ppobj = NULL;
1777 return E_NOINTERFACE;
1780 static ULONG WINAPI
1781 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
1783 ULONG uRef;
1784 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1785 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1787 EnterCriticalSection( &(This->lock) );
1789 uRef = ++(This->ref);
1791 LeaveCriticalSection( &(This->lock) );
1793 return uRef;
1796 static ULONG WINAPI
1797 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
1799 ULONG uRef;
1800 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1801 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1803 EnterCriticalSection( &(This->lock) );
1805 uRef = --(This->ref);
1807 LeaveCriticalSection( &(This->lock) );
1809 if ( uRef == 0 ) {
1810 DeleteCriticalSection( &(This->lock) );
1811 HeapFree( GetProcessHeap(), 0, This );
1812 TRACE("(%p) released\n",This);
1815 return uRef;
1818 static HRESULT WINAPI
1819 IDirectSoundFullDuplexImpl_Initialize(
1820 LPDIRECTSOUNDFULLDUPLEX iface,
1821 LPCGUID pCaptureGuid,
1822 LPCGUID pRendererGuid,
1823 LPCDSCBUFFERDESC lpDscBufferDesc,
1824 LPCDSBUFFERDESC lpDsBufferDesc,
1825 HWND hWnd,
1826 DWORD dwLevel,
1827 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
1828 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
1830 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1831 IDirectSoundCaptureBufferImpl** ippdscb=(IDirectSoundCaptureBufferImpl**)lplpDirectSoundCaptureBuffer8;
1832 IDirectSoundBufferImpl** ippdsc=(IDirectSoundBufferImpl**)lplpDirectSoundBuffer8;
1834 FIXME( "(%p,%s,%s,%p,%p,%lx,%lx,%p,%p) stub!\n", This, debugstr_guid(pCaptureGuid),
1835 debugstr_guid(pRendererGuid), lpDscBufferDesc, lpDsBufferDesc, (DWORD)hWnd, dwLevel,
1836 ippdscb, ippdsc);
1838 return E_FAIL;
1841 static ICOM_VTABLE(IDirectSoundFullDuplex) dsfdvt =
1843 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1844 /* IUnknown methods */
1845 IDirectSoundFullDuplexImpl_QueryInterface,
1846 IDirectSoundFullDuplexImpl_AddRef,
1847 IDirectSoundFullDuplexImpl_Release,
1849 /* IDirectSoundFullDuplex methods */
1850 IDirectSoundFullDuplexImpl_Initialize
1853 /*******************************************************************************
1854 * DirectSoundFullDuplex ClassFactory
1857 static HRESULT WINAPI
1858 DSFDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1860 ICOM_THIS(IClassFactoryImpl,iface);
1862 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1863 return E_NOINTERFACE;
1866 static ULONG WINAPI
1867 DSFDCF_AddRef(LPCLASSFACTORY iface)
1869 ICOM_THIS(IClassFactoryImpl,iface);
1870 TRACE("(%p) ref was %ld\n", This, This->ref);
1871 return ++(This->ref);
1874 static ULONG WINAPI
1875 DSFDCF_Release(LPCLASSFACTORY iface)
1877 ICOM_THIS(IClassFactoryImpl,iface);
1878 /* static class, won't be freed */
1879 TRACE("(%p) ref was %ld\n", This, This->ref);
1880 return --(This->ref);
1883 static HRESULT WINAPI
1884 DSFDCF_CreateInstance(
1885 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1887 ICOM_THIS(IClassFactoryImpl,iface);
1889 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1891 if (ppobj == NULL) {
1892 WARN("invalid parameter\n");
1893 return E_INVALIDARG;
1896 *ppobj = NULL;
1898 if ( IsEqualGUID( &IID_IDirectSoundFullDuplex, riid ) ) {
1899 /* FIXME: how do we do this one ? */
1900 FIXME("not implemented\n");
1901 return E_NOINTERFACE;
1904 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1905 return E_NOINTERFACE;
1908 static HRESULT WINAPI
1909 DSFDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1911 ICOM_THIS(IClassFactoryImpl,iface);
1912 FIXME("(%p)->(%d),stub!\n",This,dolock);
1913 return S_OK;
1916 static ICOM_VTABLE(IClassFactory) DSFDCF_Vtbl =
1918 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1919 DSFDCF_QueryInterface,
1920 DSFDCF_AddRef,
1921 DSFDCF_Release,
1922 DSFDCF_CreateInstance,
1923 DSFDCF_LockServer
1926 IClassFactoryImpl DSOUND_FULLDUPLEX_CF = { &DSFDCF_Vtbl, 1 };