3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Implement DirectSoundFullDuplex support.
24 * Implement FX support.
31 #include <sys/types.h>
32 #include <sys/fcntl.h>
49 #include "wine/debug.h"
52 #include "dsound_private.h"
54 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
56 static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(
57 LPDIRECTSOUNDCAPTURE iface,
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,
67 static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize(
68 LPDIRECTSOUNDFULLDUPLEX iface,
70 LPCGUID pRendererGuid,
71 LPCDSCBUFFERDESC lpDscBufferDesc,
72 LPCDSBUFFERDESC lpDsBufferDesc,
75 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
76 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 );
78 static ICOM_VTABLE(IDirectSoundCapture) dscvt;
79 static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt;
80 static ICOM_VTABLE(IDirectSoundFullDuplex) dsfdvt;
82 static IDirectSoundCaptureImpl* dsound_capture = NULL;
84 /***************************************************************************
85 * DirectSoundCaptureCreate [DSOUND.6]
87 * Create and initialize a DirectSoundCapture interface.
90 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
91 * lplpDSC [O] Address of a variable to receive the interface pointer.
92 * pUnkOuter [I] Must be NULL.
96 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
100 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
101 * or NULL for the default device or DSDEVID_DefaultCapture or
102 * DSDEVID_DefaultVoiceCapture.
104 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
107 DirectSoundCaptureCreate8(
109 LPDIRECTSOUNDCAPTURE* lplpDSC,
110 LPUNKNOWN pUnkOuter )
112 IDirectSoundCaptureImpl** ippDSC=(IDirectSoundCaptureImpl**)lplpDSC;
113 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter);
116 WARN("invalid parameter: pUnkOuter != NULL\n");
117 return DSERR_NOAGGREGATION;
121 WARN("invalid parameter: lplpDSC == NULL\n");
122 return DSERR_INVALIDPARAM;
125 /* Default device? */
126 if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
127 lpcGUID = &DSDEVID_DefaultCapture;
129 *ippDSC = (IDirectSoundCaptureImpl*)HeapAlloc(GetProcessHeap(),
130 HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureImpl));
132 if (*ippDSC == NULL) {
133 WARN("out of memory\n");
134 return DSERR_OUTOFMEMORY;
136 ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC);
139 This->state = STATE_STOPPED;
141 InitializeCriticalSection( &(This->lock) );
143 This->lpVtbl = &dscvt;
144 dsound_capture = This;
146 if (GetDeviceID(lpcGUID, &This->guid) == DS_OK) {
148 hres = IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE)This, &This->guid);
150 WARN("IDirectSoundCaptureImpl_Initialize failed\n");
154 WARN("invalid GUID: %s\n", debugstr_guid(lpcGUID));
155 return DSERR_INVALIDPARAM;
158 /***************************************************************************
159 * DirectSoundCaptureEnumerateA [DSOUND.7]
161 * Enumerate all DirectSound drivers installed in the system.
164 * lpDSEnumCallback [I] Address of callback function.
165 * lpContext [I] Address of user defined context passed to callback function.
169 * Failure: DSERR_INVALIDPARAM
172 DirectSoundCaptureEnumerateA(
173 LPDSENUMCALLBACKA lpDSEnumCallback,
181 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
183 if (lpDSEnumCallback == NULL) {
184 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
185 return DSERR_INVALIDPARAM;
188 devs = waveInGetNumDevs();
190 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
192 for (wid = 0; wid < devs; ++wid) {
193 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
195 if (IsEqualGUID( &guid, &temp ) ) {
196 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
198 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
199 "Primary Sound Capture Driver",desc.szDrvName,lpContext);
200 if (lpDSEnumCallback(NULL, "Primary Sound Capture Driver", desc.szDrvName, lpContext) == FALSE)
209 for (wid = 0; wid < devs; ++wid) {
210 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
212 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
214 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
215 debugstr_guid(&guid),desc.szDesc,desc.szDrvName,lpContext);
216 if (lpDSEnumCallback(&guid, desc.szDesc, desc.szDrvName, lpContext) == FALSE)
225 /***************************************************************************
226 * DirectSoundCaptureEnumerateW [DSOUND.8]
228 * Enumerate all DirectSound drivers installed in the system.
231 * lpDSEnumCallback [I] Address of callback function.
232 * lpContext [I] Address of user defined context passed to callback function.
236 * Failure: DSERR_INVALIDPARAM
239 DirectSoundCaptureEnumerateW(
240 LPDSENUMCALLBACKW lpDSEnumCallback,
247 WCHAR wDesc[MAXPNAMELEN];
248 WCHAR wName[MAXPNAMELEN];
250 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
252 if (lpDSEnumCallback == NULL) {
253 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
254 return DSERR_INVALIDPARAM;
257 devs = waveInGetNumDevs();
259 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
261 for (wid = 0; wid < devs; ++wid) {
262 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&temp,0));
264 if (IsEqualGUID( &guid, &temp ) ) {
265 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
267 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
268 "Primary Sound Capture Driver",desc.szDrvName,lpContext);
269 MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
270 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
271 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
272 wName, sizeof(wName)/sizeof(WCHAR) );
273 if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
282 for (wid = 0; wid < devs; ++wid) {
283 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD)&desc,0));
285 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)&guid,0));
287 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
288 debugstr_guid(&DSDEVID_DefaultCapture),desc.szDesc,desc.szDrvName,lpContext);
289 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
290 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
291 MultiByteToWideChar( CP_ACP, 0, desc.szDrvName, -1,
292 wName, sizeof(wName)/sizeof(WCHAR) );
293 if (lpDSEnumCallback((LPGUID)&DSDEVID_DefaultCapture, wDesc, wName, lpContext) == FALSE)
303 DSOUND_capture_callback(
310 IDirectSoundCaptureImpl* This = (IDirectSoundCaptureImpl*)dwUser;
311 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi,msg,
312 msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
313 msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
315 if (msg == MM_WIM_DATA) {
316 EnterCriticalSection( &(This->lock) );
317 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%ld, old This->index=%d\n",This->state,This->index);
318 if (This->state != STATE_STOPPED) {
319 int index = This->index;
320 if (This->state == STATE_STARTING) {
322 mtime.wType = TIME_BYTES;
323 waveInGetPosition(This->hwi, &mtime, sizeof(mtime));
324 TRACE("mtime.u.cb=%ld,This->buflen=%ld\n", mtime.u.cb, This->buflen);
325 mtime.u.cb = mtime.u.cb % This->buflen;
326 This->read_position = mtime.u.cb;
327 This->state = STATE_CAPTURING;
329 waveInUnprepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR));
330 if (This->capture_buffer->nrofnotifies)
331 SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
332 This->index = (This->index + 1) % This->nrofpwaves;
333 if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
334 TRACE("end of buffer\n");
335 This->state = STATE_STOPPED;
337 if (This->state == STATE_CAPTURING) {
338 waveInPrepareHeader(hwi,&(This->pwave[index]),sizeof(WAVEHDR));
339 waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
343 TRACE("DirectSoundCapture new This->state=%ld, new This->index=%d\n",This->state,This->index);
344 LeaveCriticalSection( &(This->lock) );
347 TRACE("completed\n");
350 static HRESULT WINAPI
351 IDirectSoundCaptureImpl_QueryInterface(
352 LPDIRECTSOUNDCAPTURE iface,
356 ICOM_THIS(IDirectSoundCaptureImpl,iface);
357 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
360 WARN("invalid parameter\n");
368 hres = IDsCaptureDriver_QueryInterface(This->driver, riid, ppobj);
370 WARN("IDsCaptureDriver_QueryInterface failed\n");
374 WARN("unsupported riid: %s\n", debugstr_guid(riid));
379 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
382 ICOM_THIS(IDirectSoundCaptureImpl,iface);
383 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
385 EnterCriticalSection( &(This->lock) );
386 uRef = ++(This->ref);
389 IDsCaptureDriver_AddRef(This->driver);
391 LeaveCriticalSection( &(This->lock) );
397 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
400 ICOM_THIS(IDirectSoundCaptureImpl,iface);
401 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
403 EnterCriticalSection( &(This->lock) );
405 uRef = --(This->ref);
407 LeaveCriticalSection( &(This->lock) );
410 TRACE("deleting object\n");
411 if (This->capture_buffer)
412 IDirectSoundCaptureBufferImpl_Release(
413 (LPDIRECTSOUNDCAPTUREBUFFER8) This->capture_buffer);
416 IDsCaptureDriver_Close(This->driver);
417 IDsCaptureDriver_Release(This->driver);
421 HeapFree(GetProcessHeap(), 0, This->pwfx);
423 DeleteCriticalSection( &(This->lock) );
424 HeapFree( GetProcessHeap(), 0, This );
425 dsound_capture = NULL;
426 TRACE("(%p) released\n",This);
432 static HRESULT WINAPI
433 IDirectSoundCaptureImpl_CreateCaptureBuffer(
434 LPDIRECTSOUNDCAPTURE iface,
435 LPCDSCBUFFERDESC lpcDSCBufferDesc,
436 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
440 ICOM_THIS(IDirectSoundCaptureImpl,iface);
442 TRACE( "(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk );
445 WARN("invalid parameter: This == NULL\n");
446 return DSERR_INVALIDPARAM;
449 if (lpcDSCBufferDesc == NULL) {
450 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
451 return DSERR_INVALIDPARAM;
454 if (lplpDSCaptureBuffer == NULL) {
455 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
456 return DSERR_INVALIDPARAM;
460 WARN("invalid parameter: pUnk != NULL\n");
461 return DSERR_INVALIDPARAM;
464 /* FIXME: We can only have one buffer so what do we do here? */
465 if (This->capture_buffer) {
466 WARN("lnvalid parameter: already has buffer\n");
467 return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */
470 hr = DSOUND_CreateDirectSoundCaptureBuffer( This, lpcDSCBufferDesc,
471 (LPVOID*)lplpDSCaptureBuffer );
474 WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n");
479 static HRESULT WINAPI
480 IDirectSoundCaptureImpl_GetCaps(
481 LPDIRECTSOUNDCAPTURE iface,
482 LPDSCCAPS lpDSCCaps )
484 ICOM_THIS(IDirectSoundCaptureImpl,iface);
485 TRACE("(%p,%p)\n",This,lpDSCCaps);
487 if (lpDSCCaps== NULL) {
488 WARN("invalid parameter: lpDSCCaps== NULL\n");
489 return DSERR_INVALIDPARAM;
492 if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
493 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
494 lpDSCCaps->dwSize, sizeof(*lpDSCCaps));
495 return DSERR_INVALIDPARAM;
498 if ( !(This->initialized) ) {
499 WARN("not initialized\n");
500 return DSERR_UNINITIALIZED;
503 lpDSCCaps->dwFlags = This->drvcaps.dwFlags;
504 lpDSCCaps->dwFormats = This->drvcaps.dwFormats;
505 lpDSCCaps->dwChannels = This->drvcaps.dwChannels;
507 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps->dwFlags,
508 lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
513 static HRESULT WINAPI
514 IDirectSoundCaptureImpl_Initialize(
515 LPDIRECTSOUNDCAPTURE iface,
518 HRESULT err = DSERR_INVALIDPARAM;
520 ICOM_THIS(IDirectSoundCaptureImpl,iface);
521 TRACE("(%p)\n", This);
524 WARN("invalid parameter: This == NULL\n");
525 return DSERR_INVALIDPARAM;
528 if (This->initialized) {
529 WARN("already initialized\n");
530 return DSERR_ALREADYINITIALIZED;
533 widn = waveInGetNumDevs();
536 WARN("no audio devices found\n");
537 return DSERR_NODRIVER;
540 /* Get dsound configuration */
541 setup_dsound_options();
543 /* enumerate WINMM audio devices and find the one we want */
544 for (wid=0; wid<widn; wid++) {
546 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDGUID,(DWORD)(&guid),0));
548 WARN("waveInMessage failed; err=%lx\n",err);
551 if (IsEqualGUID( lpcGUID, &guid) ) {
558 WARN("invalid parameter\n");
559 return DSERR_INVALIDPARAM;
562 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&(This->driver),0));
563 if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
564 WARN("waveInMessage failed; err=%lx\n",err);
569 /* Disable the direct sound driver to force emulation if requested. */
570 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
573 /* Get driver description */
575 TRACE("using DirectSound driver\n");
576 err = IDsCaptureDriver_GetDriverDesc(This->driver, &(This->drvdesc));
578 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
582 TRACE("using WINMM\n");
583 /* if no DirectSound interface available, use WINMM API instead */
584 This->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |
585 DSDDESC_DOMMSYSTEMSETFORMAT;
588 This->drvdesc.dnDevNode = wid;
590 /* open the DirectSound driver if available */
591 if (This->driver && (err == DS_OK))
592 err = IDsCaptureDriver_Open(This->driver);
595 This->initialized = TRUE;
597 /* the driver is now open, so it's now allowed to call GetCaps */
599 This->drvcaps.dwSize = sizeof(This->drvcaps);
600 err = IDsCaptureDriver_GetCaps(This->driver,&(This->drvcaps));
602 WARN("IDsCaptureDriver_GetCaps failed\n");
605 } else /*if (This->hwi)*/ {
607 err = mmErr(waveInGetDevCapsA((UINT)This->drvdesc.dnDevNode, &wic, sizeof(wic)));
610 This->drvcaps.dwFlags = 0;
611 strncpy(This->drvdesc.szDrvName, wic.szPname,
612 sizeof(This->drvdesc.szDrvName));
614 This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
615 This->drvcaps.dwFormats = wic.dwFormats;
616 This->drvcaps.dwChannels = wic.wChannels;
624 static ICOM_VTABLE(IDirectSoundCapture) dscvt =
626 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
627 /* IUnknown methods */
628 IDirectSoundCaptureImpl_QueryInterface,
629 IDirectSoundCaptureImpl_AddRef,
630 IDirectSoundCaptureImpl_Release,
632 /* IDirectSoundCapture methods */
633 IDirectSoundCaptureImpl_CreateCaptureBuffer,
634 IDirectSoundCaptureImpl_GetCaps,
635 IDirectSoundCaptureImpl_Initialize
639 DSOUND_CreateDirectSoundCaptureBuffer(
640 IDirectSoundCaptureImpl *ipDSC,
641 LPCDSCBUFFERDESC lpcDSCBufferDesc,
645 TRACE( "(%p,%p)\n", lpcDSCBufferDesc, ppobj );
648 WARN("invalid parameter: ipDSC == NULL\n");
649 return DSERR_INVALIDPARAM;
652 if (lpcDSCBufferDesc == NULL) {
653 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
654 return DSERR_INVALIDPARAM;
658 WARN("invalid parameter: ppobj == NULL\n");
659 return DSERR_INVALIDPARAM;
662 if ( (lpcDSCBufferDesc->dwSize < sizeof(DSCBUFFERDESC)) ||
663 (lpcDSCBufferDesc->dwBufferBytes == 0) ||
664 (lpcDSCBufferDesc->lpwfxFormat == NULL) ) {
665 WARN("invalid lpcDSCBufferDesc\n");
667 return DSERR_INVALIDPARAM;
670 if ( !ipDSC->initialized ) {
671 WARN("not initialized\n");
673 return DSERR_UNINITIALIZED;
676 wfex = lpcDSCBufferDesc->lpwfxFormat;
679 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
680 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
681 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
682 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
683 wfex->wBitsPerSample, wfex->cbSize);
685 if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
686 ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX));
687 memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX));
688 ipDSC->pwfx->cbSize = 0;
690 ipDSC->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize);
691 memcpy(ipDSC->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize);
694 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
696 return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */
699 *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
700 sizeof(IDirectSoundCaptureBufferImpl));
702 if ( *ppobj == NULL ) {
703 WARN("out of memory\n");
705 return DSERR_OUTOFMEMORY;
708 ICOM_THIS(IDirectSoundCaptureBufferImpl,*ppobj);
711 This->dsound = ipDSC;
712 This->dsound->capture_buffer = This;
714 This->nrofnotifies = 0;
715 This->hwnotify = NULL;
717 This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
718 lpcDSCBufferDesc->dwSize);
720 memcpy(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
723 This->dsound->capture_buffer = 0;
724 HeapFree( GetProcessHeap(), 0, This );
726 return DSERR_OUTOFMEMORY;
729 This->lpVtbl = &dscbvt;
732 err = IDsCaptureDriver_CreateCaptureBuffer(ipDSC->driver,
733 ipDSC->pwfx,0,0,&(ipDSC->buflen),&(ipDSC->buffer),(LPVOID*)&(ipDSC->hwbuf));
735 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
736 This->dsound->capture_buffer = 0;
737 HeapFree( GetProcessHeap(), 0, This );
744 DWORD flags = CALLBACK_FUNCTION;
745 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
746 flags |= WAVE_DIRECTSOUND;
747 err = mmErr(waveInOpen(&(ipDSC->hwi),
748 ipDSC->drvdesc.dnDevNode, ipDSC->pwfx,
749 (DWORD)DSOUND_capture_callback, (DWORD)ipDSC, flags));
751 WARN("waveInOpen failed\n");
752 This->dsound->capture_buffer = 0;
753 HeapFree( GetProcessHeap(), 0, This );
758 buflen = lpcDSCBufferDesc->dwBufferBytes;
759 TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->buffer);
761 newbuf = (LPBYTE)HeapReAlloc(GetProcessHeap(),0,ipDSC->buffer,buflen);
763 newbuf = (LPBYTE)HeapAlloc(GetProcessHeap(),0,buflen);
764 if (newbuf == NULL) {
765 WARN("failed to allocate capture buffer\n");
766 err = DSERR_OUTOFMEMORY;
767 /* but the old buffer might still exist and must be re-prepared */
769 ipDSC->buffer = newbuf;
770 ipDSC->buflen = buflen;
775 TRACE("returning DS_OK\n");
779 /*******************************************************************************
780 * IDirectSoundCaptureNotify
782 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
783 LPDIRECTSOUNDNOTIFY iface,
787 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
788 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
790 if (This->dscb == NULL) {
791 WARN("invalid parameter\n");
795 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
798 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
800 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
803 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
805 ref = InterlockedIncrement(&(This->ref));
809 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
811 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
814 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
816 ref = InterlockedDecrement(&(This->ref));
818 This->dscb->notify=NULL;
819 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
820 HeapFree(GetProcessHeap(),0,This);
821 TRACE("(%p) released\n",This);
826 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
827 LPDIRECTSOUNDNOTIFY iface,
829 LPCDSBPOSITIONNOTIFY notify)
831 ICOM_THIS(IDirectSoundCaptureNotifyImpl,iface);
832 TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
834 if (notify == NULL) {
835 WARN("invalid parameter: notify == NULL\n");
836 return DSERR_INVALIDPARAM;
839 if (TRACE_ON(dsound)) {
841 for (i=0;i<howmuch;i++)
842 TRACE("notify at %ld to 0x%08lx\n",
843 notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
846 if (This->dscb->hwnotify) {
848 hres = IDsDriverNotify_SetNotificationPositions(This->dscb->hwnotify, howmuch, notify);
850 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
853 /* Make an internal copy of the caller-supplied array.
854 * Replace the existing copy if one is already present. */
855 if (This->dscb->notifies)
856 This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
857 This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
859 This->dscb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
860 howmuch * sizeof(DSBPOSITIONNOTIFY));
862 if (This->dscb->notifies == NULL) {
863 WARN("out of memory\n");
864 return DSERR_OUTOFMEMORY;
866 memcpy(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
867 This->dscb->nrofnotifies = howmuch;
873 ICOM_VTABLE(IDirectSoundNotify) dscnvt =
875 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
876 IDirectSoundCaptureNotifyImpl_QueryInterface,
877 IDirectSoundCaptureNotifyImpl_AddRef,
878 IDirectSoundCaptureNotifyImpl_Release,
879 IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
882 HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create(
883 IDirectSoundCaptureBufferImpl *dscb,
884 IDirectSoundCaptureNotifyImpl **pdscn)
886 IDirectSoundCaptureNotifyImpl * dscn;
887 TRACE("(%p,%p)\n",dscb,pdscn);
889 dscn = (IDirectSoundCaptureNotifyImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dscn));
892 WARN("out of memory\n");
893 return DSERR_OUTOFMEMORY;
897 dscn->lpVtbl = &dscnvt;
900 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
906 /*******************************************************************************
907 * IDirectSoundCaptureBuffer
909 static HRESULT WINAPI
910 IDirectSoundCaptureBufferImpl_QueryInterface(
911 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
915 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
917 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
920 WARN("invalid parameter\n");
926 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ||
927 IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) {
929 hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
931 if (This->dsound->hwbuf) {
932 hres = IDsCaptureDriverBuffer_QueryInterface(This->dsound->hwbuf,
933 &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
935 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
941 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
942 *ppobj = (LPVOID)This->notify;
946 WARN("IID_IDirectSoundNotify\n");
950 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
951 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
952 IDirectSoundCaptureBuffer8_AddRef(iface);
957 FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
958 return E_NOINTERFACE;
962 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
965 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
966 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
968 assert(This->dsound);
970 EnterCriticalSection( &(This->dsound->lock) );
972 uRef = ++(This->ref);
974 LeaveCriticalSection( &(This->dsound->lock) );
980 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
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) );
995 TRACE("deleting object\n");
997 HeapFree(GetProcessHeap(),0, This->pdscbd);
999 if (This->dsound->hwi) {
1000 waveInReset(This->dsound->hwi);
1001 waveInClose(This->dsound->hwi);
1002 if (This->dsound->pwave) {
1003 HeapFree(GetProcessHeap(),0, This->dsound->pwave);
1004 This->dsound->pwave = 0;
1006 This->dsound->hwi = 0;
1009 if (This->dsound->hwbuf)
1010 IDsCaptureDriverBuffer_Release(This->dsound->hwbuf);
1012 /* remove from IDirectSoundCaptureImpl */
1014 This->dsound->capture_buffer = NULL;
1016 ERR("does not reference dsound\n");
1019 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
1021 if (This->notifies != NULL)
1022 HeapFree(GetProcessHeap(), 0, This->notifies);
1024 HeapFree( GetProcessHeap(), 0, This );
1025 TRACE("(%p) released\n",This);
1031 static HRESULT WINAPI
1032 IDirectSoundCaptureBufferImpl_GetCaps(
1033 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1034 LPDSCBCAPS lpDSCBCaps )
1036 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1037 TRACE( "(%p,%p)\n", This, lpDSCBCaps );
1040 WARN("invalid parameter: This == NULL\n");
1041 return DSERR_INVALIDPARAM;
1044 if (lpDSCBCaps == NULL) {
1045 WARN("invalid parameter: lpDSCBCaps == NULL\n");
1046 return DSERR_INVALIDPARAM;
1049 if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) {
1050 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
1051 lpDSCBCaps->dwSize, sizeof(DSCBCAPS));
1052 return DSERR_INVALIDPARAM;
1055 if (This->dsound == NULL) {
1056 WARN("invalid parameter: This->dsound == NULL\n");
1057 return DSERR_INVALIDPARAM;
1060 lpDSCBCaps->dwSize = sizeof(DSCBCAPS);
1061 lpDSCBCaps->dwFlags = This->flags;
1062 lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes;
1063 lpDSCBCaps->dwReserved = 0;
1065 TRACE("returning DS_OK\n");
1069 static HRESULT WINAPI
1070 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
1071 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1072 LPDWORD lpdwCapturePosition,
1073 LPDWORD lpdwReadPosition )
1075 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1076 TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
1079 WARN("invalid parameter: This == NULL\n");
1080 return DSERR_INVALIDPARAM;
1083 if (This->dsound == NULL) {
1084 WARN("invalid parameter: This->dsound == NULL\n");
1085 return DSERR_INVALIDPARAM;
1088 if (This->dsound->driver) {
1090 hres = IDsCaptureDriverBuffer_GetPosition(This->dsound->hwbuf, lpdwCapturePosition, lpdwReadPosition );
1091 if (hres != DS_OK) {
1092 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
1095 } else if (This->dsound->hwi) {
1096 EnterCriticalSection(&(This->dsound->lock));
1097 TRACE("old This->dsound->state=%ld\n",This->dsound->state);
1098 if (lpdwCapturePosition) {
1100 mtime.wType = TIME_BYTES;
1101 waveInGetPosition(This->dsound->hwi, &mtime, sizeof(mtime));
1102 TRACE("mtime.u.cb=%ld,This->dsound->buflen=%ld\n", mtime.u.cb,
1103 This->dsound->buflen);
1104 mtime.u.cb = mtime.u.cb % This->dsound->buflen;
1105 *lpdwCapturePosition = mtime.u.cb;
1108 if (lpdwReadPosition) {
1109 if (This->dsound->state == STATE_STARTING) {
1110 if (lpdwCapturePosition)
1111 This->dsound->read_position = *lpdwCapturePosition;
1112 This->dsound->state = STATE_CAPTURING;
1114 *lpdwReadPosition = This->dsound->read_position;
1116 TRACE("new This->dsound->state=%ld\n",This->dsound->state);
1117 LeaveCriticalSection(&(This->dsound->lock));
1118 if (lpdwCapturePosition) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition);
1119 if (lpdwReadPosition) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition);
1121 WARN("no driver\n");
1122 return DSERR_NODRIVER;
1125 TRACE("returning DS_OK\n");
1129 static HRESULT WINAPI
1130 IDirectSoundCaptureBufferImpl_GetFormat(
1131 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1132 LPWAVEFORMATEX lpwfxFormat,
1133 DWORD dwSizeAllocated,
1134 LPDWORD lpdwSizeWritten )
1136 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1137 TRACE( "(%p,%p,0x%08lx,%p)\n", This, lpwfxFormat, dwSizeAllocated,
1141 WARN("invalid parameter: This == NULL\n");
1142 return DSERR_INVALIDPARAM;
1145 if (This->dsound == NULL) {
1146 WARN("invalid parameter: This->dsound == NULL\n");
1147 return DSERR_INVALIDPARAM;
1150 if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize))
1151 dwSizeAllocated = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
1153 if (lpwfxFormat) { /* NULL is valid (just want size) */
1154 memcpy(lpwfxFormat, This->dsound->pwfx, dwSizeAllocated);
1155 if (lpdwSizeWritten)
1156 *lpdwSizeWritten = dwSizeAllocated;
1158 if (lpdwSizeWritten)
1159 *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->dsound->pwfx->cbSize;
1161 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
1162 return DSERR_INVALIDPARAM;
1166 TRACE("returning DS_OK\n");
1170 static HRESULT WINAPI
1171 IDirectSoundCaptureBufferImpl_GetStatus(
1172 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1173 LPDWORD lpdwStatus )
1175 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1176 TRACE( "(%p, %p), thread is %04lx\n", This, lpdwStatus, GetCurrentThreadId() );
1179 WARN("invalid parameter: This == NULL\n");
1180 return DSERR_INVALIDPARAM;
1183 if (This->dsound == NULL) {
1184 WARN("invalid parameter: This->dsound == NULL\n");
1185 return DSERR_INVALIDPARAM;
1188 if (lpdwStatus == NULL) {
1189 WARN("invalid parameter: lpdwStatus == NULL\n");
1190 return DSERR_INVALIDPARAM;
1194 EnterCriticalSection(&(This->dsound->lock));
1196 TRACE("old This->dsound->state=%ld, old lpdwStatus=%08lx\n",This->dsound->state,*lpdwStatus);
1197 if ((This->dsound->state == STATE_STARTING) ||
1198 (This->dsound->state == STATE_CAPTURING)) {
1199 *lpdwStatus |= DSCBSTATUS_CAPTURING;
1200 if (This->flags & DSCBSTART_LOOPING)
1201 *lpdwStatus |= DSCBSTATUS_LOOPING;
1203 TRACE("new This->dsound->state=%ld, new lpdwStatus=%08lx\n",This->dsound->state,*lpdwStatus);
1204 LeaveCriticalSection(&(This->dsound->lock));
1206 TRACE("status=%lx\n", *lpdwStatus);
1207 TRACE("returning DS_OK\n");
1211 static HRESULT WINAPI
1212 IDirectSoundCaptureBufferImpl_Initialize(
1213 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1214 LPDIRECTSOUNDCAPTURE lpDSC,
1215 LPCDSCBUFFERDESC lpcDSCBDesc )
1217 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1219 FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
1224 static HRESULT WINAPI
1225 IDirectSoundCaptureBufferImpl_Lock(
1226 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1229 LPVOID* lplpvAudioPtr1,
1230 LPDWORD lpdwAudioBytes1,
1231 LPVOID* lplpvAudioPtr2,
1232 LPDWORD lpdwAudioBytes2,
1235 HRESULT err = DS_OK;
1236 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1237 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This, dwReadCusor,
1238 dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
1239 lpdwAudioBytes2, dwFlags, GetTickCount() );
1242 WARN("invalid parameter: This == NULL\n");
1243 return DSERR_INVALIDPARAM;
1246 if (This->dsound == NULL) {
1247 WARN("invalid parameter: This->dsound == NULL\n");
1248 return DSERR_INVALIDPARAM;
1251 if (lplpvAudioPtr1 == NULL) {
1252 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1253 return DSERR_INVALIDPARAM;
1256 if (lpdwAudioBytes1 == NULL) {
1257 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1258 return DSERR_INVALIDPARAM;
1261 EnterCriticalSection(&(This->dsound->lock));
1263 if (This->dsound->driver) {
1264 err = IDsCaptureDriverBuffer_Lock(This->dsound->hwbuf, lplpvAudioPtr1,
1265 lpdwAudioBytes1, lplpvAudioPtr2, lpdwAudioBytes2,
1266 dwReadCusor, dwReadBytes, dwFlags);
1268 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1269 } else if (This->dsound->hwi) {
1270 *lplpvAudioPtr1 = This->dsound->buffer + dwReadCusor;
1271 if ( (dwReadCusor + dwReadBytes) > This->dsound->buflen) {
1272 *lpdwAudioBytes1 = This->dsound->buflen - dwReadCusor;
1274 *lplpvAudioPtr2 = This->dsound->buffer;
1275 if (lpdwAudioBytes2)
1276 *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
1278 *lpdwAudioBytes1 = dwReadBytes;
1280 *lplpvAudioPtr2 = 0;
1281 if (lpdwAudioBytes2)
1282 *lpdwAudioBytes2 = 0;
1285 TRACE("invalid call\n");
1286 err = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */
1289 LeaveCriticalSection(&(This->dsound->lock));
1294 static HRESULT WINAPI
1295 IDirectSoundCaptureBufferImpl_Start(
1296 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1299 HRESULT err = DS_OK;
1300 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1301 TRACE( "(%p,0x%08lx)\n", This, dwFlags );
1304 WARN("invalid parameter: This == NULL\n");
1305 return DSERR_INVALIDPARAM;
1308 if (This->dsound == NULL) {
1309 WARN("invalid parameter: This->dsound == NULL\n");
1310 return DSERR_INVALIDPARAM;
1313 if ( (This->dsound->driver == 0) && (This->dsound->hwi == 0) ) {
1314 WARN("no driver\n");
1315 return DSERR_NODRIVER;
1318 EnterCriticalSection(&(This->dsound->lock));
1320 This->flags = dwFlags;
1321 TRACE("old This->dsound->state=%ld\n",This->dsound->state);
1322 if (This->dsound->state == STATE_STOPPED)
1323 This->dsound->state = STATE_STARTING;
1324 else if (This->dsound->state == STATE_STOPPING)
1325 This->dsound->state = STATE_CAPTURING;
1326 TRACE("new This->dsound->state=%ld\n",This->dsound->state);
1328 LeaveCriticalSection(&(This->dsound->lock));
1330 if (This->dsound->driver) {
1331 err = IDsCaptureDriverBuffer_Start(This->dsound->hwbuf, dwFlags);
1333 WARN("IDsCaptureDriverBuffer_Start failed\n");
1336 IDirectSoundCaptureImpl* ipDSC = This->dsound;
1338 if (ipDSC->buffer) {
1339 if (This->nrofnotifies) {
1342 ipDSC->nrofpwaves = This->nrofnotifies;
1343 TRACE("nrofnotifies=%d\n", This->nrofnotifies);
1345 /* prepare headers */
1347 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,
1348 ipDSC->nrofpwaves*sizeof(WAVEHDR));
1350 ipDSC->pwave = HeapAlloc(GetProcessHeap(),0,
1351 ipDSC->nrofpwaves*sizeof(WAVEHDR));
1353 for (c = 0; c < ipDSC->nrofpwaves; c++) {
1355 ipDSC->pwave[0].lpData = ipDSC->buffer;
1356 ipDSC->pwave[0].dwBufferLength =
1357 This->notifies[0].dwOffset + 1;
1359 ipDSC->pwave[c].lpData = ipDSC->buffer +
1360 This->notifies[c-1].dwOffset + 1;
1361 ipDSC->pwave[c].dwBufferLength =
1362 This->notifies[c].dwOffset -
1363 This->notifies[c-1].dwOffset;
1365 ipDSC->pwave[c].dwUser = (DWORD)ipDSC;
1366 ipDSC->pwave[c].dwFlags = 0;
1367 ipDSC->pwave[c].dwLoops = 0;
1368 err = mmErr(waveInPrepareHeader(ipDSC->hwi,
1369 &(ipDSC->pwave[c]),sizeof(WAVEHDR)));
1372 waveInUnprepareHeader(ipDSC->hwi,
1373 &(ipDSC->pwave[c]),sizeof(WAVEHDR));
1377 err = mmErr(waveInAddBuffer(ipDSC->hwi,
1378 &(ipDSC->pwave[c]), sizeof(WAVEHDR)));
1381 waveInUnprepareHeader(ipDSC->hwi,
1382 &(ipDSC->pwave[c]),sizeof(WAVEHDR));
1387 memset(ipDSC->buffer,
1388 (ipDSC->pwfx->wBitsPerSample == 8) ? 128 : 0, ipDSC->buflen);
1390 TRACE("no notifiers specified\n");
1391 /* no notifiers specified so just create a single default header */
1392 ipDSC->nrofpwaves = 1;
1394 ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave,sizeof(WAVEHDR));
1396 ipDSC->pwave = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR));
1398 ipDSC->pwave[0].lpData = ipDSC->buffer;
1399 ipDSC->pwave[0].dwBufferLength = ipDSC->buflen;
1400 ipDSC->pwave[0].dwUser = (DWORD)ipDSC;
1401 ipDSC->pwave[0].dwFlags = 0;
1402 ipDSC->pwave[0].dwLoops = 0;
1404 err = mmErr(waveInPrepareHeader(ipDSC->hwi,
1405 &(ipDSC->pwave[0]),sizeof(WAVEHDR)));
1407 WARN("waveInPrepareHeader failed\n");
1408 waveInUnprepareHeader(ipDSC->hwi,
1409 &(ipDSC->pwave[0]),sizeof(WAVEHDR));
1411 err = mmErr(waveInAddBuffer(ipDSC->hwi,
1412 &(ipDSC->pwave[0]), sizeof(WAVEHDR)));
1414 waveInUnprepareHeader(ipDSC->hwi,
1415 &(ipDSC->pwave[0]),sizeof(WAVEHDR));
1421 ipDSC->read_position = 0;
1424 /* start filling the first buffer */
1425 err = mmErr(waveInStart(ipDSC->hwi));
1430 WARN("calling waveInClose because of error\n");
1431 waveInClose(This->dsound->hwi);
1432 This->dsound->hwi = 0;
1435 TRACE("returning %ld\n", err);
1439 static HRESULT WINAPI
1440 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
1442 HRESULT err = DS_OK;
1443 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1444 TRACE( "(%p)\n", This );
1447 WARN("invalid parameter: This == NULL\n");
1448 return DSERR_INVALIDPARAM;
1451 if (This->dsound == NULL) {
1452 WARN("invalid parameter: This->dsound == NULL\n");
1453 return DSERR_INVALIDPARAM;
1456 EnterCriticalSection(&(This->dsound->lock));
1458 TRACE("old This->dsound->state=%ld\n",This->dsound->state);
1459 if (This->dsound->state == STATE_CAPTURING)
1460 This->dsound->state = STATE_STOPPING;
1461 else if (This->dsound->state == STATE_STARTING)
1462 This->dsound->state = STATE_STOPPED;
1463 TRACE("new This->dsound->state=%ld\n",This->dsound->state);
1465 LeaveCriticalSection(&(This->dsound->lock));
1467 if (This->dsound->driver) {
1468 err = IDsCaptureDriverBuffer_Stop(This->dsound->hwbuf);
1469 if (err == DSERR_BUFFERLOST) {
1470 /* Wine-only: the driver wants us to reopen the device */
1471 IDsCaptureDriverBuffer_Release(This->dsound->hwbuf);
1472 err = IDsCaptureDriver_CreateCaptureBuffer(This->dsound->driver,
1473 This->dsound->pwfx,0,0,&(This->dsound->buflen),&(This->dsound->buffer),
1474 (LPVOID*)&(This->dsound->hwbuf));
1476 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1477 This->dsound->hwbuf = 0;
1479 } else if (err != DS_OK)
1480 WARN("IDsCaptureDriverBuffer_Stop failed\n");
1481 } else if (This->dsound->hwi) {
1482 err = waveInStop(This->dsound->hwi);
1484 WARN("no driver\n");
1485 err = DSERR_NODRIVER;
1488 TRACE( "(%p) returning 0x%08lx\n", This,err);
1492 static HRESULT WINAPI
1493 IDirectSoundCaptureBufferImpl_Unlock(
1494 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1495 LPVOID lpvAudioPtr1,
1496 DWORD dwAudioBytes1,
1497 LPVOID lpvAudioPtr2,
1498 DWORD dwAudioBytes2 )
1500 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1501 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This, lpvAudioPtr1, dwAudioBytes1,
1502 lpvAudioPtr2, dwAudioBytes2 );
1505 WARN("invalid parameter: This == NULL\n");
1506 return DSERR_INVALIDPARAM;
1509 if (lpvAudioPtr1 == NULL) {
1510 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1511 return DSERR_INVALIDPARAM;
1514 if (This->dsound->driver) {
1516 hres = IDsCaptureDriverBuffer_Unlock(This->dsound->hwbuf, lpvAudioPtr1,
1517 dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
1519 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1521 } else if (This->dsound->hwi) {
1522 This->dsound->read_position = (This->dsound->read_position +
1523 (dwAudioBytes1 + dwAudioBytes2)) % This->dsound->buflen;
1525 WARN("invalid call\n");
1526 return DSERR_INVALIDCALL;
1532 static HRESULT WINAPI
1533 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1534 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1535 REFGUID rguidObject,
1537 REFGUID rguidInterface,
1540 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1542 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject),
1543 dwIndex, debugstr_guid(rguidInterface), ppObject );
1548 static HRESULT WINAPI
1549 IDirectSoundCaptureBufferImpl_GetFXStatus(
1550 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1552 LPDWORD pdwFXStatus )
1554 ICOM_THIS(IDirectSoundCaptureBufferImpl,iface);
1556 FIXME( "(%p,%lu,%p): stub\n", This, dwFXCount, pdwFXStatus );
1561 static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt =
1563 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1564 /* IUnknown methods */
1565 IDirectSoundCaptureBufferImpl_QueryInterface,
1566 IDirectSoundCaptureBufferImpl_AddRef,
1567 IDirectSoundCaptureBufferImpl_Release,
1569 /* IDirectSoundCaptureBuffer methods */
1570 IDirectSoundCaptureBufferImpl_GetCaps,
1571 IDirectSoundCaptureBufferImpl_GetCurrentPosition,
1572 IDirectSoundCaptureBufferImpl_GetFormat,
1573 IDirectSoundCaptureBufferImpl_GetStatus,
1574 IDirectSoundCaptureBufferImpl_Initialize,
1575 IDirectSoundCaptureBufferImpl_Lock,
1576 IDirectSoundCaptureBufferImpl_Start,
1577 IDirectSoundCaptureBufferImpl_Stop,
1578 IDirectSoundCaptureBufferImpl_Unlock,
1580 /* IDirectSoundCaptureBuffer methods */
1581 IDirectSoundCaptureBufferImpl_GetObjectInPath,
1582 IDirectSoundCaptureBufferImpl_GetFXStatus
1585 /*******************************************************************************
1586 * DirectSoundCapture ClassFactory
1589 static HRESULT WINAPI
1590 DSCCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1592 ICOM_THIS(IClassFactoryImpl,iface);
1594 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1595 return E_NOINTERFACE;
1599 DSCCF_AddRef(LPCLASSFACTORY iface)
1601 ICOM_THIS(IClassFactoryImpl,iface);
1602 TRACE("(%p) ref was %ld\n", This, This->ref);
1603 return ++(This->ref);
1607 DSCCF_Release(LPCLASSFACTORY iface)
1609 ICOM_THIS(IClassFactoryImpl,iface);
1610 /* static class, won't be freed */
1611 TRACE("(%p) ref was %ld\n", This, This->ref);
1612 return --(This->ref);
1615 static HRESULT WINAPI
1616 DSCCF_CreateInstance(
1617 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1619 ICOM_THIS(IClassFactoryImpl,iface);
1620 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1622 if (ppobj == NULL) {
1623 WARN("invalid parameter\n");
1624 return E_INVALIDARG;
1629 if ( IsEqualGUID( &IID_IDirectSoundCapture, riid ) ||
1630 IsEqualGUID( &IID_IDirectSoundCapture8, riid ) ) {
1631 return DirectSoundCaptureCreate8(0,(LPDIRECTSOUNDCAPTURE8*)ppobj,pOuter);
1634 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1635 return E_NOINTERFACE;
1638 static HRESULT WINAPI
1639 DSCCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1641 ICOM_THIS(IClassFactoryImpl,iface);
1642 FIXME("(%p)->(%d),stub!\n",This,dolock);
1646 static ICOM_VTABLE(IClassFactory) DSCCF_Vtbl =
1648 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1649 DSCCF_QueryInterface,
1652 DSCCF_CreateInstance,
1656 IClassFactoryImpl DSOUND_CAPTURE_CF = { &DSCCF_Vtbl, 1 };
1658 /***************************************************************************
1659 * DirectSoundFullDuplexCreate8 [DSOUND.10]
1661 * Create and initialize a DirectSoundFullDuplex interface.
1664 * pcGuidCaptureDevice [I] Address of sound capture device GUID.
1665 * pcGuidRenderDevice [I] Address of sound render device GUID.
1666 * pcDSCBufferDesc [I] Address of capture buffer description.
1667 * pcDSBufferDesc [I] Address of render buffer description.
1668 * hWnd [I] Handle to application window.
1669 * dwLevel [I] Cooperative level.
1670 * ppDSFD [O] Address where full duplex interface returned.
1671 * ppDSCBuffer8 [0] Address where capture buffer interface returned.
1672 * ppDSBuffer8 [0] Address where render buffer interface returned.
1673 * pUnkOuter [I] Must be NULL.
1677 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1678 * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
1681 DirectSoundFullDuplexCreate8(
1682 LPCGUID pcGuidCaptureDevice,
1683 LPCGUID pcGuidRenderDevice,
1684 LPCDSCBUFFERDESC pcDSCBufferDesc,
1685 LPCDSBUFFERDESC pcDSBufferDesc,
1688 LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
1689 LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
1690 LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
1691 LPUNKNOWN pUnkOuter)
1693 IDirectSoundFullDuplexImpl** ippDSFD=(IDirectSoundFullDuplexImpl**)ppDSFD;
1694 TRACE("(%s,%s,%p,%p,%lx,%lx,%p,%p,%p,%p)\n", debugstr_guid(pcGuidCaptureDevice),
1695 debugstr_guid(pcGuidRenderDevice), pcDSCBufferDesc, pcDSBufferDesc,
1696 (DWORD)hWnd, dwLevel, ppDSFD, ppDSCBuffer8, ppDSBuffer8, pUnkOuter);
1699 WARN("pUnkOuter != 0\n");
1700 return DSERR_NOAGGREGATION;
1703 *ippDSFD = (IDirectSoundFullDuplexImpl*)HeapAlloc(GetProcessHeap(),
1704 HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
1706 if (*ippDSFD == NULL) {
1707 WARN("out of memory\n");
1708 return DSERR_OUTOFMEMORY;
1711 ICOM_THIS(IDirectSoundFullDuplexImpl, *ippDSFD);
1714 This->lpVtbl = &dsfdvt;
1716 InitializeCriticalSection( &(This->lock) );
1718 hres = IDirectSoundFullDuplexImpl_Initialize( (LPDIRECTSOUNDFULLDUPLEX)This,
1719 pcGuidCaptureDevice, pcGuidRenderDevice,
1720 pcDSCBufferDesc, pcDSBufferDesc,
1721 hWnd, dwLevel, ppDSCBuffer8, ppDSBuffer8);
1723 WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
1727 return DSERR_GENERIC;
1730 static HRESULT WINAPI
1731 IDirectSoundFullDuplexImpl_QueryInterface(
1732 LPDIRECTSOUNDFULLDUPLEX iface,
1736 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1737 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
1739 if (ppobj == NULL) {
1740 WARN("invalid parameter\n");
1741 return E_INVALIDARG;
1745 return E_NOINTERFACE;
1749 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
1752 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1753 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1755 EnterCriticalSection( &(This->lock) );
1757 uRef = ++(This->ref);
1759 LeaveCriticalSection( &(This->lock) );
1765 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
1768 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1769 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1771 EnterCriticalSection( &(This->lock) );
1773 uRef = --(This->ref);
1775 LeaveCriticalSection( &(This->lock) );
1778 DeleteCriticalSection( &(This->lock) );
1779 HeapFree( GetProcessHeap(), 0, This );
1780 TRACE("(%p) released\n",This);
1786 static HRESULT WINAPI
1787 IDirectSoundFullDuplexImpl_Initialize(
1788 LPDIRECTSOUNDFULLDUPLEX iface,
1789 LPCGUID pCaptureGuid,
1790 LPCGUID pRendererGuid,
1791 LPCDSCBUFFERDESC lpDscBufferDesc,
1792 LPCDSBUFFERDESC lpDsBufferDesc,
1795 LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
1796 LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
1798 ICOM_THIS(IDirectSoundFullDuplexImpl,iface);
1799 IDirectSoundCaptureBufferImpl** ippdscb=(IDirectSoundCaptureBufferImpl**)lplpDirectSoundCaptureBuffer8;
1800 IDirectSoundBufferImpl** ippdsc=(IDirectSoundBufferImpl**)lplpDirectSoundBuffer8;
1802 FIXME( "(%p,%s,%s,%p,%p,%lx,%lx,%p,%p) stub!\n", This, debugstr_guid(pCaptureGuid),
1803 debugstr_guid(pRendererGuid), lpDscBufferDesc, lpDsBufferDesc, (DWORD)hWnd, dwLevel,
1809 static ICOM_VTABLE(IDirectSoundFullDuplex) dsfdvt =
1811 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1812 /* IUnknown methods */
1813 IDirectSoundFullDuplexImpl_QueryInterface,
1814 IDirectSoundFullDuplexImpl_AddRef,
1815 IDirectSoundFullDuplexImpl_Release,
1817 /* IDirectSoundFullDuplex methods */
1818 IDirectSoundFullDuplexImpl_Initialize
1821 /*******************************************************************************
1822 * DirectSoundFullDuplex ClassFactory
1825 static HRESULT WINAPI
1826 DSFDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1828 ICOM_THIS(IClassFactoryImpl,iface);
1830 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1831 return E_NOINTERFACE;
1835 DSFDCF_AddRef(LPCLASSFACTORY iface)
1837 ICOM_THIS(IClassFactoryImpl,iface);
1838 TRACE("(%p) ref was %ld\n", This, This->ref);
1839 return ++(This->ref);
1843 DSFDCF_Release(LPCLASSFACTORY iface)
1845 ICOM_THIS(IClassFactoryImpl,iface);
1846 /* static class, won't be freed */
1847 TRACE("(%p) ref was %ld\n", This, This->ref);
1848 return --(This->ref);
1851 static HRESULT WINAPI
1852 DSFDCF_CreateInstance(
1853 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1855 ICOM_THIS(IClassFactoryImpl,iface);
1857 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1859 if (ppobj == NULL) {
1860 WARN("invalid parameter\n");
1861 return E_INVALIDARG;
1866 if ( IsEqualGUID( &IID_IDirectSoundFullDuplex, riid ) ) {
1867 /* FIXME: how do we do this one ? */
1868 FIXME("not implemented\n");
1869 return E_NOINTERFACE;
1872 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1873 return E_NOINTERFACE;
1876 static HRESULT WINAPI
1877 DSFDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1879 ICOM_THIS(IClassFactoryImpl,iface);
1880 FIXME("(%p)->(%d),stub!\n",This,dolock);
1884 static ICOM_VTABLE(IClassFactory) DSFDCF_Vtbl =
1886 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1887 DSFDCF_QueryInterface,
1890 DSFDCF_CreateInstance,
1894 IClassFactoryImpl DSOUND_FULLDUPLEX_CF = { &DSFDCF_Vtbl, 1 };