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