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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * Implement FX support.
24 * Implement both IDirectSoundCaptureBuffer and IDirectSoundCaptureBuffer8
25 * Make DirectSoundCaptureCreate and DirectSoundCaptureCreate8 behave differently
30 #define NONAMELESSSTRUCT
31 #define NONAMELESSUNION
40 #include "wine/debug.h"
43 #include "dsound_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
47 /*****************************************************************************
48 * IDirectSoundCapture implementation structure
50 struct IDirectSoundCaptureImpl
53 const IDirectSoundCaptureVtbl *lpVtbl;
56 DirectSoundCaptureDevice *device;
59 static HRESULT IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8 * ppds);
62 /*****************************************************************************
63 * IDirectSoundCaptureNotify implementation structure
65 struct IDirectSoundCaptureNotifyImpl
68 const IDirectSoundNotifyVtbl *lpVtbl;
70 IDirectSoundCaptureBufferImpl* dscb;
73 static HRESULT IDirectSoundCaptureNotifyImpl_Create(IDirectSoundCaptureBufferImpl *dscb,
74 IDirectSoundCaptureNotifyImpl ** pdscn);
77 DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS];
79 static HRESULT DirectSoundCaptureDevice_Create(DirectSoundCaptureDevice ** ppDevice);
81 static const char * captureStateString[] = {
88 static HRESULT DSOUND_CaptureCreate(
89 LPDIRECTSOUNDCAPTURE *ppDSC,
92 LPDIRECTSOUNDCAPTURE pDSC;
94 TRACE("(%p,%p)\n",ppDSC,pUnkOuter);
96 /* Get dsound configuration */
97 setup_dsound_options();
99 hr = IDirectSoundCaptureImpl_Create(&pDSC);
101 IDirectSoundCapture_AddRef(pDSC);
104 WARN("IDirectSoundCaptureImpl_Create failed\n");
111 static HRESULT DSOUND_CaptureCreate8(
112 LPDIRECTSOUNDCAPTURE8 *ppDSC8,
115 LPDIRECTSOUNDCAPTURE8 pDSC8;
117 TRACE("(%p,%p)\n",ppDSC8,pUnkOuter);
119 /* Get dsound configuration */
120 setup_dsound_options();
122 hr = IDirectSoundCaptureImpl_Create(&pDSC8);
124 IDirectSoundCapture_AddRef(pDSC8);
127 WARN("IDirectSoundCaptureImpl_Create failed\n");
134 /***************************************************************************
135 * DirectSoundCaptureCreate [DSOUND.6]
137 * Create and initialize a DirectSoundCapture interface.
140 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
141 * lplpDSC [O] Address of a variable to receive the interface pointer.
142 * pUnkOuter [I] Must be NULL.
146 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
150 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
151 * or NULL for the default device or DSDEVID_DefaultCapture or
152 * DSDEVID_DefaultVoiceCapture.
154 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
156 HRESULT WINAPI DirectSoundCaptureCreate(
158 LPDIRECTSOUNDCAPTURE *ppDSC,
162 LPDIRECTSOUNDCAPTURE pDSC;
163 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC, pUnkOuter);
166 WARN("invalid parameter: ppDSC == NULL\n");
167 return DSERR_INVALIDPARAM;
171 WARN("invalid parameter: pUnkOuter != NULL\n");
173 return DSERR_NOAGGREGATION;
176 hr = DSOUND_CaptureCreate(&pDSC, (IUnknown *)pUnkOuter);
178 hr = IDirectSoundCapture_Initialize(pDSC, lpcGUID);
180 IDirectSoundCapture_Release(pDSC);
190 /***************************************************************************
191 * DirectSoundCaptureCreate8 [DSOUND.12]
193 * Create and initialize a DirectSoundCapture interface.
196 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
197 * lplpDSC [O] Address of a variable to receive the interface pointer.
198 * pUnkOuter [I] Must be NULL.
202 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
206 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
207 * or NULL for the default device or DSDEVID_DefaultCapture or
208 * DSDEVID_DefaultVoiceCapture.
210 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
212 HRESULT WINAPI DirectSoundCaptureCreate8(
214 LPDIRECTSOUNDCAPTURE8 *ppDSC8,
218 LPDIRECTSOUNDCAPTURE8 pDSC8;
219 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC8, pUnkOuter);
221 if (ppDSC8 == NULL) {
222 WARN("invalid parameter: ppDSC8 == NULL\n");
223 return DSERR_INVALIDPARAM;
227 WARN("invalid parameter: pUnkOuter != NULL\n");
229 return DSERR_NOAGGREGATION;
232 hr = DSOUND_CaptureCreate8(&pDSC8, (IUnknown *)pUnkOuter);
234 hr = IDirectSoundCapture_Initialize(pDSC8, lpcGUID);
236 IDirectSoundCapture_Release(pDSC8);
246 /***************************************************************************
247 * DirectSoundCaptureEnumerateA [DSOUND.7]
249 * Enumerate all DirectSound drivers installed in the system.
252 * lpDSEnumCallback [I] Address of callback function.
253 * lpContext [I] Address of user defined context passed to callback function.
257 * Failure: DSERR_INVALIDPARAM
260 DirectSoundCaptureEnumerateA(
261 LPDSENUMCALLBACKA lpDSEnumCallback,
269 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
271 if (lpDSEnumCallback == NULL) {
272 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
273 return DSERR_INVALIDPARAM;
276 devs = waveInGetNumDevs();
278 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
279 for (wid = 0; wid < devs; ++wid) {
280 if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
281 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
283 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
284 "Primary Sound Capture Driver",desc.szDrvname,lpContext);
285 if (lpDSEnumCallback(NULL, "Primary Sound Capture Driver", desc.szDrvname, lpContext) == FALSE)
293 for (wid = 0; wid < devs; ++wid) {
294 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
296 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
297 debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
298 if (lpDSEnumCallback(&DSOUND_capture_guids[wid], desc.szDesc, desc.szDrvname, lpContext) == FALSE)
306 /***************************************************************************
307 * DirectSoundCaptureEnumerateW [DSOUND.8]
309 * Enumerate all DirectSound drivers installed in the system.
312 * lpDSEnumCallback [I] Address of callback function.
313 * lpContext [I] Address of user defined context passed to callback function.
317 * Failure: DSERR_INVALIDPARAM
320 DirectSoundCaptureEnumerateW(
321 LPDSENUMCALLBACKW lpDSEnumCallback,
328 WCHAR wDesc[MAXPNAMELEN];
329 WCHAR wName[MAXPNAMELEN];
331 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
333 if (lpDSEnumCallback == NULL) {
334 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
335 return DSERR_INVALIDPARAM;
338 devs = waveInGetNumDevs();
340 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
341 for (wid = 0; wid < devs; ++wid) {
342 if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
343 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
345 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
346 "Primary Sound Capture Driver",desc.szDrvname,lpContext);
347 MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
348 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
349 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
350 wName, sizeof(wName)/sizeof(WCHAR) );
351 if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
359 for (wid = 0; wid < devs; ++wid) {
360 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
362 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
363 debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
364 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
365 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
366 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
367 wName, sizeof(wName)/sizeof(WCHAR) );
368 if (lpDSEnumCallback((LPGUID)&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE)
377 DSOUND_capture_callback(
384 DirectSoundCaptureDevice * This = (DirectSoundCaptureDevice*)dwUser;
385 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi,msg,
386 msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
387 msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
389 if (msg == MM_WIM_DATA) {
390 LPWAVEHDR pHdr = (LPWAVEHDR)dw1;
391 EnterCriticalSection( &(This->lock) );
392 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
393 captureStateString[This->state],This->index);
394 if (This->state != STATE_STOPPED) {
395 int index = This->index;
396 if (This->state == STATE_STARTING) {
397 This->read_position = pHdr->dwBytesRecorded;
398 This->state = STATE_CAPTURING;
400 if (This->capture_buffer->nrofnotifies)
401 SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
402 This->index = (This->index + 1) % This->nrofpwaves;
403 if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
404 TRACE("end of buffer\n");
405 This->state = STATE_STOPPED;
407 if (This->state == STATE_CAPTURING) {
408 waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
409 } else if (This->state == STATE_STOPPING) {
411 This->state = STATE_STOPPED;
415 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
416 captureStateString[This->state],This->index);
417 LeaveCriticalSection( &(This->lock) );
420 TRACE("completed\n");
423 /***************************************************************************
424 * IDirectSoundCaptureImpl
426 static HRESULT WINAPI
427 IDirectSoundCaptureImpl_QueryInterface(
428 LPDIRECTSOUNDCAPTURE iface,
432 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
433 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
436 WARN("invalid parameter\n");
442 if (IsEqualIID(riid, &IID_IUnknown)) {
443 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
446 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
447 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
452 WARN("unsupported riid: %s\n", debugstr_guid(riid));
453 return E_NOINTERFACE;
457 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
459 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
460 ULONG ref = InterlockedIncrement(&(This->ref));
461 TRACE("(%p) ref was %ld\n", This, ref - 1);
466 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
468 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
469 ULONG ref = InterlockedDecrement(&(This->ref));
470 TRACE("(%p) ref was %ld\n", This, ref + 1);
474 DirectSoundCaptureDevice_Release(This->device);
476 HeapFree( GetProcessHeap(), 0, This );
477 TRACE("(%p) released\n", This);
482 HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer(
483 LPDIRECTSOUNDCAPTURE iface,
484 LPCDSCBUFFERDESC lpcDSCBufferDesc,
485 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
489 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
491 TRACE( "(%p,%p,%p,%p)\n",iface,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
493 if (lpcDSCBufferDesc == NULL) {
494 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
495 return DSERR_INVALIDPARAM;
498 if (lplpDSCaptureBuffer == NULL) {
499 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
500 return DSERR_INVALIDPARAM;
504 WARN("invalid parameter: pUnk != NULL\n");
505 return DSERR_INVALIDPARAM;
508 /* FIXME: We can only have one buffer so what do we do here? */
509 if (This->device->capture_buffer) {
510 WARN("lnvalid parameter: already has buffer\n");
511 return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */
514 hr = IDirectSoundCaptureBufferImpl_Create(This->device,
515 (IDirectSoundCaptureBufferImpl **)lplpDSCaptureBuffer, lpcDSCBufferDesc);
518 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
523 HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps(
524 LPDIRECTSOUNDCAPTURE iface,
525 LPDSCCAPS lpDSCCaps )
527 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
528 TRACE("(%p,%p)\n",This,lpDSCCaps);
530 if (This->device == NULL) {
531 WARN("not initialized\n");
532 return DSERR_UNINITIALIZED;
535 if (lpDSCCaps== NULL) {
536 WARN("invalid parameter: lpDSCCaps== NULL\n");
537 return DSERR_INVALIDPARAM;
540 if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
541 WARN("invalid parameter: lpDSCCaps->dwSize = %ld\n", lpDSCCaps->dwSize);
542 return DSERR_INVALIDPARAM;
545 lpDSCCaps->dwFlags = This->device->drvcaps.dwFlags;
546 lpDSCCaps->dwFormats = This->device->drvcaps.dwFormats;
547 lpDSCCaps->dwChannels = This->device->drvcaps.dwChannels;
549 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps->dwFlags,
550 lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
555 HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(
556 LPDIRECTSOUNDCAPTURE iface,
559 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
560 TRACE("(%p,%s)\n", This, debugstr_guid(lpcGUID));
562 if (This->device != NULL) {
563 WARN("already initialized\n");
564 return DSERR_ALREADYINITIALIZED;
567 return DirectSoundCaptureDevice_Initialize(&This->device, lpcGUID);
570 static const IDirectSoundCaptureVtbl dscvt =
572 /* IUnknown methods */
573 IDirectSoundCaptureImpl_QueryInterface,
574 IDirectSoundCaptureImpl_AddRef,
575 IDirectSoundCaptureImpl_Release,
577 /* IDirectSoundCapture methods */
578 IDirectSoundCaptureImpl_CreateCaptureBuffer,
579 IDirectSoundCaptureImpl_GetCaps,
580 IDirectSoundCaptureImpl_Initialize
583 static HRESULT IDirectSoundCaptureImpl_Create(
584 LPDIRECTSOUNDCAPTURE8 * ppDSC)
586 IDirectSoundCaptureImpl *pDSC;
587 TRACE("(%p)\n", ppDSC);
589 /* Allocate memory */
590 pDSC = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundCaptureImpl));
592 WARN("out of memory\n");
594 return DSERR_OUTOFMEMORY;
597 pDSC->lpVtbl = &dscvt;
601 *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC;
606 /*******************************************************************************
607 * IDirectSoundCaptureNotify
609 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
610 LPDIRECTSOUNDNOTIFY iface,
614 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
615 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
617 if (This->dscb == NULL) {
618 WARN("invalid parameter\n");
622 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
625 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
627 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
628 ULONG ref = InterlockedIncrement(&(This->ref));
629 TRACE("(%p) ref was %ld\n", This, ref - 1);
633 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
635 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
636 ULONG ref = InterlockedDecrement(&(This->ref));
637 TRACE("(%p) ref was %ld\n", This, ref + 1);
640 if (This->dscb->hwnotify)
641 IDsDriverNotify_Release(This->dscb->hwnotify);
642 This->dscb->notify=NULL;
643 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
644 HeapFree(GetProcessHeap(),0,This);
645 TRACE("(%p) released\n", This);
650 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
651 LPDIRECTSOUNDNOTIFY iface,
653 LPCDSBPOSITIONNOTIFY notify)
655 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
656 TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
658 if (howmuch > 0 && notify == NULL) {
659 WARN("invalid parameter: notify == NULL\n");
660 return DSERR_INVALIDPARAM;
663 if (TRACE_ON(dsound)) {
665 for (i=0;i<howmuch;i++)
666 TRACE("notify at %ld to %p\n",
667 notify[i].dwOffset,notify[i].hEventNotify);
670 if (This->dscb->hwnotify) {
672 hres = IDsDriverNotify_SetNotificationPositions(This->dscb->hwnotify, howmuch, notify);
674 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
676 } else if (howmuch > 0) {
677 /* Make an internal copy of the caller-supplied array.
678 * Replace the existing copy if one is already present. */
679 if (This->dscb->notifies)
680 This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
681 This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
683 This->dscb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
684 howmuch * sizeof(DSBPOSITIONNOTIFY));
686 if (This->dscb->notifies == NULL) {
687 WARN("out of memory\n");
688 return DSERR_OUTOFMEMORY;
690 CopyMemory(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
691 This->dscb->nrofnotifies = howmuch;
693 HeapFree(GetProcessHeap(), 0, This->dscb->notifies);
694 This->dscb->notifies = NULL;
695 This->dscb->nrofnotifies = 0;
701 static const IDirectSoundNotifyVtbl dscnvt =
703 IDirectSoundCaptureNotifyImpl_QueryInterface,
704 IDirectSoundCaptureNotifyImpl_AddRef,
705 IDirectSoundCaptureNotifyImpl_Release,
706 IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
709 static HRESULT IDirectSoundCaptureNotifyImpl_Create(
710 IDirectSoundCaptureBufferImpl *dscb,
711 IDirectSoundCaptureNotifyImpl **pdscn)
713 IDirectSoundCaptureNotifyImpl * dscn;
714 TRACE("(%p,%p)\n",dscb,pdscn);
716 dscn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dscn));
719 WARN("out of memory\n");
720 return DSERR_OUTOFMEMORY;
724 dscn->lpVtbl = &dscnvt;
727 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
733 /*******************************************************************************
734 * IDirectSoundCaptureBuffer
736 static HRESULT WINAPI
737 IDirectSoundCaptureBufferImpl_QueryInterface(
738 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
742 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
744 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
747 WARN("invalid parameter\n");
753 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
755 hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
757 if (This->device->hwbuf) {
758 hres = IDsCaptureDriverBuffer_QueryInterface(This->device->hwbuf,
759 &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
761 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
767 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
768 *ppobj = (LPVOID)This->notify;
772 WARN("IID_IDirectSoundNotify\n");
776 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
777 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
778 IDirectSoundCaptureBuffer8_AddRef(iface);
783 FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
784 return E_NOINTERFACE;
788 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
790 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
791 ULONG ref = InterlockedIncrement(&(This->ref));
792 TRACE("(%p) ref was %ld\n", This, ref - 1);
797 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
799 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
800 ULONG ref = InterlockedDecrement(&(This->ref));
801 TRACE("(%p) ref was %ld\n", This, ref + 1);
804 TRACE("deleting object\n");
805 if (This->device->state == STATE_CAPTURING)
806 This->device->state = STATE_STOPPING;
808 HeapFree(GetProcessHeap(),0, This->pdscbd);
810 if (This->device->hwi) {
811 waveInReset(This->device->hwi);
812 waveInClose(This->device->hwi);
813 HeapFree(GetProcessHeap(),0, This->device->pwave);
814 This->device->pwave = 0;
815 This->device->hwi = 0;
818 if (This->device->hwbuf)
819 IDsCaptureDriverBuffer_Release(This->device->hwbuf);
821 /* remove from DirectSoundCaptureDevice */
822 This->device->capture_buffer = NULL;
825 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
827 HeapFree(GetProcessHeap(), 0, This->notifies);
828 HeapFree( GetProcessHeap(), 0, This );
829 TRACE("(%p) released\n", This);
834 static HRESULT WINAPI
835 IDirectSoundCaptureBufferImpl_GetCaps(
836 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
837 LPDSCBCAPS lpDSCBCaps )
839 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
840 TRACE( "(%p,%p)\n", This, lpDSCBCaps );
842 if (lpDSCBCaps == NULL) {
843 WARN("invalid parameter: lpDSCBCaps == NULL\n");
844 return DSERR_INVALIDPARAM;
847 if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) {
848 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld\n", lpDSCBCaps->dwSize);
849 return DSERR_INVALIDPARAM;
852 if (This->device == NULL) {
853 WARN("invalid parameter: This->device == NULL\n");
854 return DSERR_INVALIDPARAM;
857 lpDSCBCaps->dwSize = sizeof(DSCBCAPS);
858 lpDSCBCaps->dwFlags = This->flags;
859 lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes;
860 lpDSCBCaps->dwReserved = 0;
862 TRACE("returning DS_OK\n");
866 static HRESULT WINAPI
867 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
868 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
869 LPDWORD lpdwCapturePosition,
870 LPDWORD lpdwReadPosition )
872 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
873 HRESULT hres = DS_OK;
874 TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
876 if (This->device == NULL) {
877 WARN("invalid parameter: This->device == NULL\n");
878 return DSERR_INVALIDPARAM;
881 if (This->device->driver) {
882 hres = IDsCaptureDriverBuffer_GetPosition(This->device->hwbuf, lpdwCapturePosition, lpdwReadPosition );
884 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
885 } else if (This->device->hwi) {
886 EnterCriticalSection(&(This->device->lock));
887 TRACE("old This->device->state=%s\n",captureStateString[This->device->state]);
888 if (lpdwCapturePosition) {
890 mtime.wType = TIME_BYTES;
891 waveInGetPosition(This->device->hwi, &mtime, sizeof(mtime));
892 TRACE("mtime.u.cb=%ld,This->device->buflen=%ld\n", mtime.u.cb,
893 This->device->buflen);
894 mtime.u.cb = mtime.u.cb % This->device->buflen;
895 *lpdwCapturePosition = mtime.u.cb;
898 if (lpdwReadPosition) {
899 if (This->device->state == STATE_STARTING) {
900 if (lpdwCapturePosition)
901 This->device->read_position = *lpdwCapturePosition;
902 This->device->state = STATE_CAPTURING;
904 *lpdwReadPosition = This->device->read_position;
906 TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
907 LeaveCriticalSection(&(This->device->lock));
908 if (lpdwCapturePosition) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition);
909 if (lpdwReadPosition) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition);
912 hres = DSERR_NODRIVER;
915 TRACE("returning %08lx\n", hres);
919 static HRESULT WINAPI
920 IDirectSoundCaptureBufferImpl_GetFormat(
921 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
922 LPWAVEFORMATEX lpwfxFormat,
923 DWORD dwSizeAllocated,
924 LPDWORD lpdwSizeWritten )
926 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
927 HRESULT hres = DS_OK;
928 TRACE( "(%p,%p,0x%08lx,%p)\n", This, lpwfxFormat, dwSizeAllocated,
931 if (This->device == NULL) {
932 WARN("invalid parameter: This->device == NULL\n");
933 return DSERR_INVALIDPARAM;
936 if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize))
937 dwSizeAllocated = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
939 if (lpwfxFormat) { /* NULL is valid (just want size) */
940 CopyMemory(lpwfxFormat, This->device->pwfx, dwSizeAllocated);
942 *lpdwSizeWritten = dwSizeAllocated;
945 *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
947 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
948 hres = DSERR_INVALIDPARAM;
952 TRACE("returning %08lx\n", hres);
956 static HRESULT WINAPI
957 IDirectSoundCaptureBufferImpl_GetStatus(
958 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
961 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
962 TRACE( "(%p, %p), thread is %04lx\n", This, lpdwStatus, GetCurrentThreadId() );
964 if (This->device == NULL) {
965 WARN("invalid parameter: This->device == NULL\n");
966 return DSERR_INVALIDPARAM;
969 if (lpdwStatus == NULL) {
970 WARN("invalid parameter: lpdwStatus == NULL\n");
971 return DSERR_INVALIDPARAM;
975 EnterCriticalSection(&(This->device->lock));
977 TRACE("old This->device->state=%s, old lpdwStatus=%08lx\n",
978 captureStateString[This->device->state],*lpdwStatus);
979 if ((This->device->state == STATE_STARTING) ||
980 (This->device->state == STATE_CAPTURING)) {
981 *lpdwStatus |= DSCBSTATUS_CAPTURING;
982 if (This->flags & DSCBSTART_LOOPING)
983 *lpdwStatus |= DSCBSTATUS_LOOPING;
985 TRACE("new This->device->state=%s, new lpdwStatus=%08lx\n",
986 captureStateString[This->device->state],*lpdwStatus);
987 LeaveCriticalSection(&(This->device->lock));
989 TRACE("status=%lx\n", *lpdwStatus);
990 TRACE("returning DS_OK\n");
994 static HRESULT WINAPI
995 IDirectSoundCaptureBufferImpl_Initialize(
996 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
997 LPDIRECTSOUNDCAPTURE lpDSC,
998 LPCDSCBUFFERDESC lpcDSCBDesc )
1000 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1002 FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
1007 static HRESULT WINAPI
1008 IDirectSoundCaptureBufferImpl_Lock(
1009 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1012 LPVOID* lplpvAudioPtr1,
1013 LPDWORD lpdwAudioBytes1,
1014 LPVOID* lplpvAudioPtr2,
1015 LPDWORD lpdwAudioBytes2,
1018 HRESULT hres = DS_OK;
1019 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1020 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This, dwReadCusor,
1021 dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
1022 lpdwAudioBytes2, dwFlags, GetTickCount() );
1024 if (This->device == NULL) {
1025 WARN("invalid parameter: This->device == NULL\n");
1026 return DSERR_INVALIDPARAM;
1029 if (lplpvAudioPtr1 == NULL) {
1030 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1031 return DSERR_INVALIDPARAM;
1034 if (lpdwAudioBytes1 == NULL) {
1035 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1036 return DSERR_INVALIDPARAM;
1039 EnterCriticalSection(&(This->device->lock));
1041 if (This->device->driver) {
1042 hres = IDsCaptureDriverBuffer_Lock(This->device->hwbuf, lplpvAudioPtr1,
1043 lpdwAudioBytes1, lplpvAudioPtr2,
1044 lpdwAudioBytes2, dwReadCusor,
1045 dwReadBytes, dwFlags);
1047 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1048 } else if (This->device->hwi) {
1049 *lplpvAudioPtr1 = This->device->buffer + dwReadCusor;
1050 if ( (dwReadCusor + dwReadBytes) > This->device->buflen) {
1051 *lpdwAudioBytes1 = This->device->buflen - dwReadCusor;
1053 *lplpvAudioPtr2 = This->device->buffer;
1054 if (lpdwAudioBytes2)
1055 *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
1057 *lpdwAudioBytes1 = dwReadBytes;
1059 *lplpvAudioPtr2 = 0;
1060 if (lpdwAudioBytes2)
1061 *lpdwAudioBytes2 = 0;
1064 TRACE("invalid call\n");
1065 hres = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */
1068 LeaveCriticalSection(&(This->device->lock));
1070 TRACE("returning %08lx\n", hres);
1074 static HRESULT WINAPI
1075 IDirectSoundCaptureBufferImpl_Start(
1076 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1079 HRESULT hres = DS_OK;
1080 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1081 TRACE( "(%p,0x%08lx)\n", This, dwFlags );
1083 if (This->device == NULL) {
1084 WARN("invalid parameter: This->device == NULL\n");
1085 return DSERR_INVALIDPARAM;
1088 if ( (This->device->driver == 0) && (This->device->hwi == 0) ) {
1089 WARN("no driver\n");
1090 return DSERR_NODRIVER;
1093 EnterCriticalSection(&(This->device->lock));
1095 This->flags = dwFlags;
1096 TRACE("old This->state=%s\n",captureStateString[This->device->state]);
1097 if (This->device->state == STATE_STOPPED)
1098 This->device->state = STATE_STARTING;
1099 else if (This->device->state == STATE_STOPPING)
1100 This->device->state = STATE_CAPTURING;
1101 TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
1103 LeaveCriticalSection(&(This->device->lock));
1105 if (This->device->driver) {
1106 hres = IDsCaptureDriverBuffer_Start(This->device->hwbuf, dwFlags);
1108 WARN("IDsCaptureDriverBuffer_Start failed\n");
1109 } else if (This->device->hwi) {
1110 DirectSoundCaptureDevice *device = This->device;
1112 if (device->buffer) {
1113 if (This->nrofnotifies) {
1116 device->nrofpwaves = This->nrofnotifies;
1117 TRACE("nrofnotifies=%d\n", This->nrofnotifies);
1119 /* prepare headers */
1121 device->pwave = HeapReAlloc(GetProcessHeap(),0,device->pwave,
1122 device->nrofpwaves*sizeof(WAVEHDR));
1124 device->pwave = HeapAlloc(GetProcessHeap(),0,
1125 device->nrofpwaves*sizeof(WAVEHDR));
1127 for (c = 0; c < device->nrofpwaves; c++) {
1128 if (This->notifies[c].dwOffset == DSBPN_OFFSETSTOP) {
1129 TRACE("got DSBPN_OFFSETSTOP\n");
1130 device->nrofpwaves = c;
1134 device->pwave[0].lpData = (LPSTR)device->buffer;
1135 device->pwave[0].dwBufferLength =
1136 This->notifies[0].dwOffset + 1;
1138 device->pwave[c].lpData = (LPSTR)device->buffer +
1139 This->notifies[c-1].dwOffset + 1;
1140 device->pwave[c].dwBufferLength =
1141 This->notifies[c].dwOffset -
1142 This->notifies[c-1].dwOffset;
1144 device->pwave[c].dwBytesRecorded = 0;
1145 device->pwave[c].dwUser = (DWORD)device;
1146 device->pwave[c].dwFlags = 0;
1147 device->pwave[c].dwLoops = 0;
1148 hres = mmErr(waveInPrepareHeader(device->hwi,
1149 &(device->pwave[c]),sizeof(WAVEHDR)));
1150 if (hres != DS_OK) {
1151 WARN("waveInPrepareHeader failed\n");
1153 waveInUnprepareHeader(device->hwi,
1154 &(device->pwave[c]),sizeof(WAVEHDR));
1158 hres = mmErr(waveInAddBuffer(device->hwi,
1159 &(device->pwave[c]), sizeof(WAVEHDR)));
1160 if (hres != DS_OK) {
1161 WARN("waveInAddBuffer failed\n");
1163 waveInUnprepareHeader(device->hwi,
1164 &(device->pwave[c]),sizeof(WAVEHDR));
1169 FillMemory(device->buffer, device->buflen,
1170 (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
1172 TRACE("no notifiers specified\n");
1173 /* no notifiers specified so just create a single default header */
1174 device->nrofpwaves = 1;
1176 device->pwave = HeapReAlloc(GetProcessHeap(),0,device->pwave,sizeof(WAVEHDR));
1178 device->pwave = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR));
1180 device->pwave[0].lpData = (LPSTR)device->buffer;
1181 device->pwave[0].dwBufferLength = device->buflen;
1182 device->pwave[0].dwBytesRecorded = 0;
1183 device->pwave[0].dwUser = (DWORD)device;
1184 device->pwave[0].dwFlags = 0;
1185 device->pwave[0].dwLoops = 0;
1187 hres = mmErr(waveInPrepareHeader(device->hwi,
1188 &(device->pwave[0]),sizeof(WAVEHDR)));
1189 if (hres != DS_OK) {
1190 WARN("waveInPrepareHeader failed\n");
1191 waveInUnprepareHeader(device->hwi,
1192 &(device->pwave[0]),sizeof(WAVEHDR));
1194 hres = mmErr(waveInAddBuffer(device->hwi,
1195 &(device->pwave[0]), sizeof(WAVEHDR)));
1196 if (hres != DS_OK) {
1197 WARN("waveInAddBuffer failed\n");
1198 waveInUnprepareHeader(device->hwi,
1199 &(device->pwave[0]),sizeof(WAVEHDR));
1205 device->read_position = 0;
1207 if (hres == DS_OK) {
1208 /* start filling the first buffer */
1209 hres = mmErr(waveInStart(device->hwi));
1211 WARN("waveInStart failed\n");
1214 if (hres != DS_OK) {
1215 WARN("calling waveInClose because of error\n");
1216 waveInClose(device->hwi);
1220 WARN("no driver\n");
1221 hres = DSERR_NODRIVER;
1224 TRACE("returning %08lx\n", hres);
1228 static HRESULT WINAPI
1229 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
1231 HRESULT hres = DS_OK;
1232 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1233 TRACE( "(%p)\n", This );
1235 if (This->device == NULL) {
1236 WARN("invalid parameter: This->device == NULL\n");
1237 return DSERR_INVALIDPARAM;
1240 EnterCriticalSection(&(This->device->lock));
1242 TRACE("old This->device->state=%s\n",captureStateString[This->device->state]);
1243 if (This->device->state == STATE_CAPTURING)
1244 This->device->state = STATE_STOPPING;
1245 else if (This->device->state == STATE_STARTING)
1246 This->device->state = STATE_STOPPED;
1247 TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
1249 LeaveCriticalSection(&(This->device->lock));
1251 if (This->device->driver) {
1252 hres = IDsCaptureDriverBuffer_Stop(This->device->hwbuf);
1254 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1255 } else if (This->device->hwi) {
1256 hres = mmErr(waveInReset(This->device->hwi));
1258 WARN("waveInReset() failed\n");
1260 WARN("no driver\n");
1261 hres = DSERR_NODRIVER;
1264 TRACE("returning %08lx\n", hres);
1268 static HRESULT WINAPI
1269 IDirectSoundCaptureBufferImpl_Unlock(
1270 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1271 LPVOID lpvAudioPtr1,
1272 DWORD dwAudioBytes1,
1273 LPVOID lpvAudioPtr2,
1274 DWORD dwAudioBytes2 )
1276 HRESULT hres = DS_OK;
1277 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1278 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This, lpvAudioPtr1, dwAudioBytes1,
1279 lpvAudioPtr2, dwAudioBytes2 );
1281 if (lpvAudioPtr1 == NULL) {
1282 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1283 return DSERR_INVALIDPARAM;
1286 if (This->device->driver) {
1287 hres = IDsCaptureDriverBuffer_Unlock(This->device->hwbuf, lpvAudioPtr1,
1288 dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
1290 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1291 } else if (This->device->hwi) {
1292 This->device->read_position = (This->device->read_position +
1293 (dwAudioBytes1 + dwAudioBytes2)) % This->device->buflen;
1295 WARN("invalid call\n");
1296 hres = DSERR_INVALIDCALL;
1299 TRACE("returning %08lx\n", hres);
1303 static HRESULT WINAPI
1304 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1305 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1306 REFGUID rguidObject,
1308 REFGUID rguidInterface,
1311 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1313 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject),
1314 dwIndex, debugstr_guid(rguidInterface), ppObject );
1319 static HRESULT WINAPI
1320 IDirectSoundCaptureBufferImpl_GetFXStatus(
1321 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1323 LPDWORD pdwFXStatus )
1325 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1327 FIXME( "(%p,%lu,%p): stub\n", This, dwFXCount, pdwFXStatus );
1332 static const IDirectSoundCaptureBuffer8Vtbl dscbvt =
1334 /* IUnknown methods */
1335 IDirectSoundCaptureBufferImpl_QueryInterface,
1336 IDirectSoundCaptureBufferImpl_AddRef,
1337 IDirectSoundCaptureBufferImpl_Release,
1339 /* IDirectSoundCaptureBuffer methods */
1340 IDirectSoundCaptureBufferImpl_GetCaps,
1341 IDirectSoundCaptureBufferImpl_GetCurrentPosition,
1342 IDirectSoundCaptureBufferImpl_GetFormat,
1343 IDirectSoundCaptureBufferImpl_GetStatus,
1344 IDirectSoundCaptureBufferImpl_Initialize,
1345 IDirectSoundCaptureBufferImpl_Lock,
1346 IDirectSoundCaptureBufferImpl_Start,
1347 IDirectSoundCaptureBufferImpl_Stop,
1348 IDirectSoundCaptureBufferImpl_Unlock,
1350 /* IDirectSoundCaptureBuffer methods */
1351 IDirectSoundCaptureBufferImpl_GetObjectInPath,
1352 IDirectSoundCaptureBufferImpl_GetFXStatus
1355 HRESULT IDirectSoundCaptureBufferImpl_Create(
1356 DirectSoundCaptureDevice *device,
1357 IDirectSoundCaptureBufferImpl ** ppobj,
1358 LPCDSCBUFFERDESC lpcDSCBufferDesc)
1360 LPWAVEFORMATEX wfex;
1361 TRACE( "(%p,%p,%p)\n", device, ppobj, lpcDSCBufferDesc);
1363 if (ppobj == NULL) {
1364 WARN("invalid parameter: ppobj == NULL\n");
1365 return DSERR_INVALIDPARAM;
1369 WARN("not initialized\n");
1371 return DSERR_UNINITIALIZED;
1374 if (lpcDSCBufferDesc == NULL) {
1375 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
1377 return DSERR_INVALIDPARAM;
1380 if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) &&
1381 (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) ||
1382 (lpcDSCBufferDesc->dwBufferBytes == 0) ||
1383 (lpcDSCBufferDesc->lpwfxFormat == NULL) ) {
1384 WARN("invalid lpcDSCBufferDesc\n");
1386 return DSERR_INVALIDPARAM;
1389 wfex = lpcDSCBufferDesc->lpwfxFormat;
1392 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
1393 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
1394 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
1395 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
1396 wfex->wBitsPerSample, wfex->cbSize);
1398 if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
1399 device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX));
1400 CopyMemory(device->pwfx, wfex, sizeof(WAVEFORMATEX));
1401 device->pwfx->cbSize = 0;
1403 device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize);
1404 CopyMemory(device->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize);
1407 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
1409 return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */
1412 *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1413 sizeof(IDirectSoundCaptureBufferImpl));
1415 if ( *ppobj == NULL ) {
1416 WARN("out of memory\n");
1418 return DSERR_OUTOFMEMORY;
1420 HRESULT err = DS_OK;
1423 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)*ppobj;
1426 This->device = device;
1427 This->device->capture_buffer = This;
1428 This->notify = NULL;
1429 This->nrofnotifies = 0;
1430 This->hwnotify = NULL;
1432 This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
1433 lpcDSCBufferDesc->dwSize);
1435 CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
1437 WARN("no memory\n");
1438 This->device->capture_buffer = 0;
1439 HeapFree( GetProcessHeap(), 0, This );
1441 return DSERR_OUTOFMEMORY;
1444 This->lpVtbl = &dscbvt;
1446 if (device->driver) {
1447 if (This->device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
1448 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
1450 if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
1451 /* allocate buffer from system memory */
1452 buflen = lpcDSCBufferDesc->dwBufferBytes;
1453 TRACE("desired buflen=%ld, old buffer=%p\n", buflen, device->buffer);
1455 newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
1457 newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
1459 if (newbuf == NULL) {
1460 WARN("failed to allocate capture buffer\n");
1461 err = DSERR_OUTOFMEMORY;
1462 /* but the old buffer might still exist and must be re-prepared */
1464 device->buffer = newbuf;
1465 device->buflen = buflen;
1468 /* let driver allocate memory */
1469 device->buflen = lpcDSCBufferDesc->dwBufferBytes;
1471 HeapFree( GetProcessHeap(), 0, device->buffer);
1472 device->buffer = NULL;
1475 err = IDsCaptureDriver_CreateCaptureBuffer(device->driver,
1476 device->pwfx,0,0,&(device->buflen),&(device->buffer),(LPVOID*)&(device->hwbuf));
1478 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
1479 This->device->capture_buffer = 0;
1480 HeapFree( GetProcessHeap(), 0, This );
1485 DWORD flags = CALLBACK_FUNCTION;
1486 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
1487 flags |= WAVE_DIRECTSOUND;
1488 err = mmErr(waveInOpen(&(device->hwi),
1489 device->drvdesc.dnDevNode, device->pwfx,
1490 (DWORD_PTR)DSOUND_capture_callback, (DWORD)device, flags));
1492 WARN("waveInOpen failed\n");
1493 This->device->capture_buffer = 0;
1494 HeapFree( GetProcessHeap(), 0, This );
1499 buflen = lpcDSCBufferDesc->dwBufferBytes;
1500 TRACE("desired buflen=%ld, old buffer=%p\n", buflen, device->buffer);
1502 newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
1504 newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
1505 if (newbuf == NULL) {
1506 WARN("failed to allocate capture buffer\n");
1507 err = DSERR_OUTOFMEMORY;
1508 /* but the old buffer might still exist and must be re-prepared */
1510 device->buffer = newbuf;
1511 device->buflen = buflen;
1516 TRACE("returning DS_OK\n");
1520 /*******************************************************************************
1521 * DirectSoundCaptureDevice
1523 HRESULT DirectSoundCaptureDevice_Initialize(
1524 DirectSoundCaptureDevice ** ppDevice,
1527 HRESULT err = DSERR_INVALIDPARAM;
1529 BOOLEAN found = FALSE;
1531 DirectSoundCaptureDevice *device = *ppDevice;
1532 TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID));
1534 /* Default device? */
1535 if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
1536 lpcGUID = &DSDEVID_DefaultCapture;
1538 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
1539 WARN("invalid parameter: lpcGUID\n");
1540 return DSERR_INVALIDPARAM;
1543 widn = waveInGetNumDevs();
1545 WARN("no audio devices found\n");
1546 return DSERR_NODRIVER;
1549 /* enumerate WINMM audio devices and find the one we want */
1550 for (wid=0; wid<widn; wid++) {
1551 if (IsEqualGUID( &devGUID, &DSOUND_capture_guids[wid]) ) {
1557 if (found == FALSE) {
1558 WARN("No device found matching given ID!\n");
1559 return DSERR_NODRIVER;
1562 if (DSOUND_capture[wid]) {
1563 WARN("already in use\n");
1564 return DSERR_ALLOCATED;
1567 err = DirectSoundCaptureDevice_Create(&(device));
1569 WARN("DirectSoundCaptureDevice_Create failed\n");
1574 device->guid = devGUID;
1576 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&(device->driver),0));
1577 if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
1578 WARN("waveInMessage failed; err=%lx\n",err);
1583 /* Disable the direct sound driver to force emulation if requested. */
1584 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
1585 device->driver = NULL;
1587 /* Get driver description */
1588 if (device->driver) {
1589 TRACE("using DirectSound driver\n");
1590 err = IDsCaptureDriver_GetDriverDesc(device->driver, &(device->drvdesc));
1592 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
1596 TRACE("using WINMM\n");
1597 /* if no DirectSound interface available, use WINMM API instead */
1598 device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |
1599 DSDDESC_DOMMSYSTEMSETFORMAT;
1602 device->drvdesc.dnDevNode = wid;
1604 /* open the DirectSound driver if available */
1605 if (device->driver && (err == DS_OK))
1606 err = IDsCaptureDriver_Open(device->driver);
1611 /* the driver is now open, so it's now allowed to call GetCaps */
1612 if (device->driver) {
1613 device->drvcaps.dwSize = sizeof(device->drvcaps);
1614 err = IDsCaptureDriver_GetCaps(device->driver,&(device->drvcaps));
1616 WARN("IDsCaptureDriver_GetCaps failed\n");
1619 } else /*if (device->hwi)*/ {
1621 err = mmErr(waveInGetDevCapsA((UINT)device->drvdesc.dnDevNode, &wic, sizeof(wic)));
1624 device->drvcaps.dwFlags = 0;
1625 lstrcpynA(device->drvdesc.szDrvname, wic.szPname,
1626 sizeof(device->drvdesc.szDrvname));
1628 device->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
1629 device->drvcaps.dwFormats = wic.dwFormats;
1630 device->drvcaps.dwChannels = wic.wChannels;
1638 static HRESULT DirectSoundCaptureDevice_Create(
1639 DirectSoundCaptureDevice ** ppDevice)
1641 DirectSoundCaptureDevice * device;
1642 TRACE("(%p)\n", ppDevice);
1644 /* Allocate memory */
1645 device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectSoundCaptureDevice));
1647 if (device == NULL) {
1648 WARN("out of memory\n");
1649 return DSERR_OUTOFMEMORY;
1653 device->state = STATE_STOPPED;
1655 InitializeCriticalSection( &(device->lock) );
1656 device->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSCAPTURE_lock";
1663 ULONG DirectSoundCaptureDevice_AddRef(
1664 DirectSoundCaptureDevice * device)
1666 ULONG ref = InterlockedIncrement(&(device->ref));
1667 TRACE("(%p) ref was %ld\n", device, ref - 1);
1671 ULONG DirectSoundCaptureDevice_Release(
1672 DirectSoundCaptureDevice * device)
1674 ULONG ref = InterlockedDecrement(&(device->ref));
1675 TRACE("(%p) ref was %ld\n", device, ref + 1);
1678 TRACE("deleting object\n");
1679 if (device->capture_buffer)
1680 IDirectSoundCaptureBufferImpl_Release(
1681 (LPDIRECTSOUNDCAPTUREBUFFER8) device->capture_buffer);
1683 if (device->driver) {
1684 IDsCaptureDriver_Close(device->driver);
1685 IDsCaptureDriver_Release(device->driver);
1688 HeapFree(GetProcessHeap(), 0, device->pwfx);
1689 device->lock.DebugInfo->Spare[0] = 0;
1690 DeleteCriticalSection( &(device->lock) );
1691 DSOUND_capture[device->drvdesc.dnDevNode] = NULL;
1692 HeapFree(GetProcessHeap(), 0, device);
1693 TRACE("(%p) released\n", device);
1698 /*******************************************************************************
1699 * DirectSoundCapture ClassFactory
1702 static HRESULT WINAPI
1703 DSCCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1705 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1707 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1708 return E_NOINTERFACE;
1712 DSCCF_AddRef(LPCLASSFACTORY iface)
1714 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1715 ULONG ref = InterlockedIncrement(&(This->ref));
1716 TRACE("(%p) ref was %ld\n", This, ref - 1);
1721 DSCCF_Release(LPCLASSFACTORY iface)
1723 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1724 ULONG ref = InterlockedDecrement(&(This->ref));
1725 TRACE("(%p) ref was %ld\n", This, ref + 1);
1726 /* static class, won't be freed */
1730 static HRESULT WINAPI
1731 DSCCF_CreateInstance(
1732 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1734 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1735 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1738 WARN("aggregation not supported\n");
1739 return CLASS_E_NOAGGREGATION;
1742 if (ppobj == NULL) {
1743 WARN("invalid parameter\n");
1744 return E_INVALIDARG;
1749 if ( IsEqualGUID( &IID_IDirectSoundCapture, riid ) )
1750 return DSOUND_CaptureCreate8((LPDIRECTSOUNDCAPTURE*)ppobj,pOuter);
1752 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1753 return E_NOINTERFACE;
1756 static HRESULT WINAPI
1757 DSCCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1759 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1760 FIXME("(%p)->(%d),stub!\n",This,dolock);
1764 static const IClassFactoryVtbl DSCCF_Vtbl =
1766 DSCCF_QueryInterface,
1769 DSCCF_CreateInstance,
1773 IClassFactoryImpl DSOUND_CAPTURE_CF = { &DSCCF_Vtbl, 1 };