Include winuser.h so the code compiles cleanly on windows using
[wine.git] / dlls / dsound / capture.c
blob33328c015be3c524b0aa52085f0c3928d17ba762
1 /* DirectSoundCapture
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2001 TransGaming Technologies, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * TODO:
23 * Implement FX support.
24 * Implement both IDirectSoundCaptureBuffer and IDirectSoundCaptureBuffer8
25 * Make DirectSoundCaptureCreate and DirectSoundCaptureCreate8 behave differently
28 #include <stdarg.h>
30 #define NONAMELESSSTRUCT
31 #define NONAMELESSUNION
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winuser.h"
35 #include "mmsystem.h"
36 #include "mmddk.h"
37 #include "winreg.h"
38 #include "winternl.h"
39 #include "winnls.h"
40 #include "wine/debug.h"
41 #include "dsound.h"
42 #include "dsdriver.h"
43 #include "dsound_private.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
47 static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(
48 LPDIRECTSOUNDCAPTURE iface,
49 LPCGUID lpcGUID );
50 static ULONG WINAPI IDirectSoundCaptureImpl_Release(
51 LPDIRECTSOUNDCAPTURE iface );
52 static ULONG WINAPI IDirectSoundCaptureBufferImpl_Release(
53 LPDIRECTSOUNDCAPTUREBUFFER8 iface );
54 static HRESULT DSOUND_CreateDirectSoundCaptureBuffer(
55 IDirectSoundCaptureImpl *ipDSC,
56 LPCDSCBUFFERDESC lpcDSCBufferDesc,
57 LPVOID* ppobj );
59 static const IDirectSoundCaptureVtbl dscvt;
60 static const IDirectSoundCaptureBuffer8Vtbl dscbvt;
62 DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS];
64 static const char * captureStateString[] = {
65 "STATE_STOPPED",
66 "STATE_STARTING",
67 "STATE_CAPTURING",
68 "STATE_STOPPING"
71 HRESULT WINAPI IDirectSoundCaptureImpl_Create(
72 LPDIRECTSOUNDCAPTURE8 * ppDSC)
74 IDirectSoundCaptureImpl *pDSC;
75 TRACE("(%p)\n", ppDSC);
77 /* Allocate memory */
78 pDSC = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundCaptureImpl));
79 if (pDSC == NULL) {
80 WARN("out of memory\n");
81 *ppDSC = NULL;
82 return DSERR_OUTOFMEMORY;
85 pDSC->lpVtbl = &dscvt;
86 pDSC->ref = 0;
87 pDSC->device = NULL;
89 *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC;
91 return DS_OK;
94 HRESULT WINAPI DSOUND_CaptureCreate(
95 LPDIRECTSOUNDCAPTURE *ppDSC,
96 IUnknown *pUnkOuter)
98 LPDIRECTSOUNDCAPTURE pDSC;
99 HRESULT hr;
100 TRACE("(%p,%p)\n",ppDSC,pUnkOuter);
102 /* Get dsound configuration */
103 setup_dsound_options();
105 hr = IDirectSoundCaptureImpl_Create(&pDSC);
106 if (hr == DS_OK) {
107 IDirectSoundCapture_AddRef(pDSC);
108 *ppDSC = pDSC;
109 } else {
110 WARN("IDirectSoundCaptureImpl_Create failed\n");
111 *ppDSC = 0;
114 return hr;
117 HRESULT WINAPI DSOUND_CaptureCreate8(
118 LPDIRECTSOUNDCAPTURE8 *ppDSC8,
119 IUnknown *pUnkOuter)
121 LPDIRECTSOUNDCAPTURE8 pDSC8;
122 HRESULT hr;
123 TRACE("(%p,%p)\n",ppDSC8,pUnkOuter);
125 /* Get dsound configuration */
126 setup_dsound_options();
128 hr = IDirectSoundCaptureImpl_Create(&pDSC8);
129 if (hr == DS_OK) {
130 IDirectSoundCapture_AddRef(pDSC8);
131 *ppDSC8 = pDSC8;
132 } else {
133 WARN("IDirectSoundCaptureImpl_Create failed\n");
134 *ppDSC8 = 0;
137 return hr;
140 /***************************************************************************
141 * DirectSoundCaptureCreate [DSOUND.6]
143 * Create and initialize a DirectSoundCapture interface.
145 * PARAMS
146 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
147 * lplpDSC [O] Address of a variable to receive the interface pointer.
148 * pUnkOuter [I] Must be NULL.
150 * RETURNS
151 * Success: DS_OK
152 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
153 * DSERR_OUTOFMEMORY
155 * NOTES
156 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
157 * or NULL for the default device or DSDEVID_DefaultCapture or
158 * DSDEVID_DefaultVoiceCapture.
160 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
162 HRESULT WINAPI DirectSoundCaptureCreate(
163 LPCGUID lpcGUID,
164 LPDIRECTSOUNDCAPTURE *ppDSC,
165 LPUNKNOWN pUnkOuter)
167 HRESULT hr;
168 LPDIRECTSOUNDCAPTURE pDSC;
169 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC, pUnkOuter);
171 if (ppDSC == NULL) {
172 WARN("invalid parameter: ppDSC == NULL\n");
173 return DSERR_INVALIDPARAM;
176 if (pUnkOuter) {
177 WARN("invalid parameter: pUnkOuter != NULL\n");
178 *ppDSC = NULL;
179 return DSERR_NOAGGREGATION;
182 hr = DSOUND_CaptureCreate(&pDSC, (IUnknown *)pUnkOuter);
183 if (hr == DS_OK) {
184 hr = IDirectSoundCapture_Initialize(pDSC, lpcGUID);
185 if (hr != DS_OK) {
186 IDirectSoundCapture_Release(pDSC);
187 pDSC = 0;
191 *ppDSC = pDSC;
193 return hr;
196 /***************************************************************************
197 * DirectSoundCaptureCreate8 [DSOUND.12]
199 * Create and initialize a DirectSoundCapture interface.
201 * PARAMS
202 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
203 * lplpDSC [O] Address of a variable to receive the interface pointer.
204 * pUnkOuter [I] Must be NULL.
206 * RETURNS
207 * Success: DS_OK
208 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
209 * DSERR_OUTOFMEMORY
211 * NOTES
212 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
213 * or NULL for the default device or DSDEVID_DefaultCapture or
214 * DSDEVID_DefaultVoiceCapture.
216 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
218 HRESULT WINAPI DirectSoundCaptureCreate8(
219 LPCGUID lpcGUID,
220 LPDIRECTSOUNDCAPTURE8 *ppDSC8,
221 LPUNKNOWN pUnkOuter)
223 HRESULT hr;
224 LPDIRECTSOUNDCAPTURE8 pDSC8;
225 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC8, pUnkOuter);
227 if (ppDSC8 == NULL) {
228 WARN("invalid parameter: ppDSC8 == NULL\n");
229 return DSERR_INVALIDPARAM;
232 if (pUnkOuter) {
233 WARN("invalid parameter: pUnkOuter != NULL\n");
234 *ppDSC8 = NULL;
235 return DSERR_NOAGGREGATION;
238 hr = DSOUND_CaptureCreate8(&pDSC8, (IUnknown *)pUnkOuter);
239 if (hr == DS_OK) {
240 hr = IDirectSoundCapture_Initialize(pDSC8, lpcGUID);
241 if (hr != DS_OK) {
242 IDirectSoundCapture_Release(pDSC8);
243 pDSC8 = 0;
247 *ppDSC8 = pDSC8;
249 return hr;
252 static HRESULT DirectSoundCaptureDevice_Create(
253 DirectSoundCaptureDevice ** ppDevice)
255 DirectSoundCaptureDevice * device;
256 TRACE("(%p)\n", ppDevice);
258 /* Allocate memory */
259 device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectSoundCaptureDevice));
261 if (device == NULL) {
262 WARN("out of memory\n");
263 return DSERR_OUTOFMEMORY;
266 device->ref = 1;
267 device->state = STATE_STOPPED;
269 InitializeCriticalSection( &(device->lock) );
270 device->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSCAPTURE_lock";
272 *ppDevice = device;
274 return DS_OK;
277 /***************************************************************************
278 * DirectSoundCaptureEnumerateA [DSOUND.7]
280 * Enumerate all DirectSound drivers installed in the system.
282 * PARAMS
283 * lpDSEnumCallback [I] Address of callback function.
284 * lpContext [I] Address of user defined context passed to callback function.
286 * RETURNS
287 * Success: DS_OK
288 * Failure: DSERR_INVALIDPARAM
290 HRESULT WINAPI
291 DirectSoundCaptureEnumerateA(
292 LPDSENUMCALLBACKA lpDSEnumCallback,
293 LPVOID lpContext)
295 unsigned devs, wid;
296 DSDRIVERDESC desc;
297 GUID guid;
298 int err;
300 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
302 if (lpDSEnumCallback == NULL) {
303 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
304 return DSERR_INVALIDPARAM;
307 devs = waveInGetNumDevs();
308 if (devs > 0) {
309 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
310 for (wid = 0; wid < devs; ++wid) {
311 if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
312 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
313 if (err == DS_OK) {
314 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
315 "Primary Sound Capture Driver",desc.szDrvname,lpContext);
316 if (lpDSEnumCallback(NULL, "Primary Sound Capture Driver", desc.szDrvname, lpContext) == FALSE)
317 return DS_OK;
324 for (wid = 0; wid < devs; ++wid) {
325 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
326 if (err == DS_OK) {
327 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
328 debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
329 if (lpDSEnumCallback(&DSOUND_capture_guids[wid], desc.szDesc, desc.szDrvname, lpContext) == FALSE)
330 return DS_OK;
334 return DS_OK;
337 /***************************************************************************
338 * DirectSoundCaptureEnumerateW [DSOUND.8]
340 * Enumerate all DirectSound drivers installed in the system.
342 * PARAMS
343 * lpDSEnumCallback [I] Address of callback function.
344 * lpContext [I] Address of user defined context passed to callback function.
346 * RETURNS
347 * Success: DS_OK
348 * Failure: DSERR_INVALIDPARAM
350 HRESULT WINAPI
351 DirectSoundCaptureEnumerateW(
352 LPDSENUMCALLBACKW lpDSEnumCallback,
353 LPVOID lpContext)
355 unsigned devs, wid;
356 DSDRIVERDESC desc;
357 GUID guid;
358 int err;
359 WCHAR wDesc[MAXPNAMELEN];
360 WCHAR wName[MAXPNAMELEN];
362 TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
364 if (lpDSEnumCallback == NULL) {
365 WARN("invalid parameter: lpDSEnumCallback == NULL\n");
366 return DSERR_INVALIDPARAM;
369 devs = waveInGetNumDevs();
370 if (devs > 0) {
371 if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
372 for (wid = 0; wid < devs; ++wid) {
373 if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
374 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
375 if (err == DS_OK) {
376 TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
377 "Primary Sound Capture Driver",desc.szDrvname,lpContext);
378 MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
379 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
380 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
381 wName, sizeof(wName)/sizeof(WCHAR) );
382 if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
383 return DS_OK;
390 for (wid = 0; wid < devs; ++wid) {
391 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
392 if (err == DS_OK) {
393 TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
394 debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
395 MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
396 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
397 MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
398 wName, sizeof(wName)/sizeof(WCHAR) );
399 if (lpDSEnumCallback((LPGUID)&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE)
400 return DS_OK;
404 return DS_OK;
407 static void CALLBACK
408 DSOUND_capture_callback(
409 HWAVEIN hwi,
410 UINT msg,
411 DWORD dwUser,
412 DWORD dw1,
413 DWORD dw2 )
415 DirectSoundCaptureDevice * This = (DirectSoundCaptureDevice*)dwUser;
416 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi,msg,
417 msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
418 msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
420 if (msg == MM_WIM_DATA) {
421 LPWAVEHDR pHdr = (LPWAVEHDR)dw1;
422 EnterCriticalSection( &(This->lock) );
423 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
424 captureStateString[This->state],This->index);
425 if (This->state != STATE_STOPPED) {
426 int index = This->index;
427 if (This->state == STATE_STARTING) {
428 This->read_position = pHdr->dwBytesRecorded;
429 This->state = STATE_CAPTURING;
431 if (This->capture_buffer->nrofnotifies)
432 SetEvent(This->capture_buffer->notifies[This->index].hEventNotify);
433 This->index = (This->index + 1) % This->nrofpwaves;
434 if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
435 TRACE("end of buffer\n");
436 This->state = STATE_STOPPED;
437 } else {
438 if (This->state == STATE_CAPTURING) {
439 waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
440 } else if (This->state == STATE_STOPPING) {
441 TRACE("stopping\n");
442 This->state = STATE_STOPPED;
446 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
447 captureStateString[This->state],This->index);
448 LeaveCriticalSection( &(This->lock) );
451 TRACE("completed\n");
454 static HRESULT WINAPI
455 IDirectSoundCaptureImpl_QueryInterface(
456 LPDIRECTSOUNDCAPTURE iface,
457 REFIID riid,
458 LPVOID* ppobj )
460 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
461 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
463 if (ppobj == NULL) {
464 WARN("invalid parameter\n");
465 return E_INVALIDARG;
468 *ppobj = NULL;
470 if (IsEqualIID(riid, &IID_IUnknown)) {
471 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
472 *ppobj = This;
473 return DS_OK;
474 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
475 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
476 *ppobj = This;
477 return DS_OK;
480 WARN("unsupported riid: %s\n", debugstr_guid(riid));
481 return E_NOINTERFACE;
484 static ULONG WINAPI
485 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
487 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
488 ULONG ref = InterlockedIncrement(&(This->ref));
489 TRACE("(%p) ref was %ld\n", This, ref - 1);
490 return ref;
493 static ULONG DirectSoundCaptureDevice_Release(
494 DirectSoundCaptureDevice * device)
496 ULONG ref;
497 TRACE("(%p) ref was %lu\n", device, device->ref);
499 device->ref--;
500 ref=device->ref;
501 if (device->ref == 0) {
502 TRACE("deleting object\n");
503 if (device->capture_buffer)
504 IDirectSoundCaptureBufferImpl_Release(
505 (LPDIRECTSOUNDCAPTUREBUFFER8) device->capture_buffer);
507 if (device->driver) {
508 IDsCaptureDriver_Close(device->driver);
509 IDsCaptureDriver_Release(device->driver);
512 HeapFree(GetProcessHeap(), 0, device->pwfx);
513 device->lock.DebugInfo->Spare[0] = 0;
514 DeleteCriticalSection( &(device->lock) );
515 DSOUND_capture[device->drvdesc.dnDevNode] = NULL;
516 HeapFree(GetProcessHeap(), 0, device);
517 TRACE("(%p) released\n", device);
519 return ref;
522 static ULONG WINAPI
523 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
525 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
526 ULONG ref = InterlockedDecrement(&(This->ref));
527 TRACE("(%p) ref was %ld\n", This, ref + 1);
529 if (!ref) {
530 if (This->device)
531 DirectSoundCaptureDevice_Release(This->device);
533 HeapFree( GetProcessHeap(), 0, This );
534 TRACE("(%p) released\n", This);
536 return ref;
539 static HRESULT WINAPI
540 IDirectSoundCaptureImpl_CreateCaptureBuffer(
541 LPDIRECTSOUNDCAPTURE iface,
542 LPCDSCBUFFERDESC lpcDSCBufferDesc,
543 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
544 LPUNKNOWN pUnk )
546 HRESULT hr;
547 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
549 TRACE( "(%p,%p,%p,%p)\n",iface,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
551 if (This == NULL) {
552 WARN("invalid parameter: This == NULL\n");
553 return DSERR_INVALIDPARAM;
556 if (lpcDSCBufferDesc == NULL) {
557 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
558 return DSERR_INVALIDPARAM;
561 if (lplpDSCaptureBuffer == NULL) {
562 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
563 return DSERR_INVALIDPARAM;
566 if (pUnk != NULL) {
567 WARN("invalid parameter: pUnk != NULL\n");
568 return DSERR_INVALIDPARAM;
571 /* FIXME: We can only have one buffer so what do we do here? */
572 if (This->device->capture_buffer) {
573 WARN("lnvalid parameter: already has buffer\n");
574 return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */
577 hr = DSOUND_CreateDirectSoundCaptureBuffer(This, lpcDSCBufferDesc,
578 (LPVOID*)lplpDSCaptureBuffer );
580 if (hr != DS_OK)
581 WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n");
583 return hr;
586 static HRESULT WINAPI
587 IDirectSoundCaptureImpl_GetCaps(
588 LPDIRECTSOUNDCAPTURE iface,
589 LPDSCCAPS lpDSCCaps )
591 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
592 TRACE("(%p,%p)\n",This,lpDSCCaps);
594 if (This->device == NULL) {
595 WARN("not initialized\n");
596 return DSERR_UNINITIALIZED;
599 if (lpDSCCaps== NULL) {
600 WARN("invalid parameter: lpDSCCaps== NULL\n");
601 return DSERR_INVALIDPARAM;
604 if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
605 WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n",
606 lpDSCCaps->dwSize, sizeof(*lpDSCCaps));
607 return DSERR_INVALIDPARAM;
610 lpDSCCaps->dwFlags = This->device->drvcaps.dwFlags;
611 lpDSCCaps->dwFormats = This->device->drvcaps.dwFormats;
612 lpDSCCaps->dwChannels = This->device->drvcaps.dwChannels;
614 TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps->dwFlags,
615 lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
617 return DS_OK;
620 static HRESULT WINAPI
621 IDirectSoundCaptureImpl_Initialize(
622 LPDIRECTSOUNDCAPTURE iface,
623 LPCGUID lpcGUID )
625 HRESULT err = DSERR_INVALIDPARAM;
626 unsigned wid, widn;
627 BOOLEAN found = FALSE;
628 GUID devGUID;
629 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
630 DirectSoundCaptureDevice *device = This->device;
631 TRACE("(%p)\n", This);
633 if (!This) {
634 WARN("invalid parameter: This == NULL\n");
635 return DSERR_INVALIDPARAM;
638 if (device != NULL) {
639 WARN("already initialized\n");
640 return DSERR_ALREADYINITIALIZED;
643 /* Default device? */
644 if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
645 lpcGUID = &DSDEVID_DefaultCapture;
647 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
648 WARN("invalid parameter: lpcGUID\n");
649 return DSERR_INVALIDPARAM;
652 widn = waveInGetNumDevs();
653 if (!widn) {
654 WARN("no audio devices found\n");
655 return DSERR_NODRIVER;
658 /* enumerate WINMM audio devices and find the one we want */
659 for (wid=0; wid<widn; wid++) {
660 if (IsEqualGUID( &devGUID, &DSOUND_capture_guids[wid]) ) {
661 found = TRUE;
662 break;
666 if (found == FALSE) {
667 WARN("No device found matching given ID!\n");
668 return DSERR_NODRIVER;
671 if (DSOUND_capture[wid]) {
672 WARN("already in use\n");
673 return DSERR_ALLOCATED;
676 err = DirectSoundCaptureDevice_Create(&(device));
677 if (err != DS_OK) {
678 WARN("DirectSoundCaptureDevice_Create failed\n");
679 return err;
682 This->device = device;
683 device->guid = devGUID;
685 err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&(This->device->driver),0));
686 if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
687 WARN("waveInMessage failed; err=%lx\n",err);
688 return err;
690 err = DS_OK;
692 /* Disable the direct sound driver to force emulation if requested. */
693 if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
694 This->device->driver = NULL;
696 /* Get driver description */
697 if (This->device->driver) {
698 TRACE("using DirectSound driver\n");
699 err = IDsCaptureDriver_GetDriverDesc(This->device->driver, &(This->device->drvdesc));
700 if (err != DS_OK) {
701 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
702 return err;
704 } else {
705 TRACE("using WINMM\n");
706 /* if no DirectSound interface available, use WINMM API instead */
707 This->device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |
708 DSDDESC_DOMMSYSTEMSETFORMAT;
711 This->device->drvdesc.dnDevNode = wid;
713 /* open the DirectSound driver if available */
714 if (This->device->driver && (err == DS_OK))
715 err = IDsCaptureDriver_Open(This->device->driver);
717 if (err == DS_OK) {
718 This->device = device;
720 /* the driver is now open, so it's now allowed to call GetCaps */
721 if (This->device->driver) {
722 This->device->drvcaps.dwSize = sizeof(This->device->drvcaps);
723 err = IDsCaptureDriver_GetCaps(This->device->driver,&(This->device->drvcaps));
724 if (err != DS_OK) {
725 WARN("IDsCaptureDriver_GetCaps failed\n");
726 return err;
728 } else /*if (This->hwi)*/ {
729 WAVEINCAPSA wic;
730 err = mmErr(waveInGetDevCapsA((UINT)This->device->drvdesc.dnDevNode, &wic, sizeof(wic)));
732 if (err == DS_OK) {
733 This->device->drvcaps.dwFlags = 0;
734 lstrcpynA(This->device->drvdesc.szDrvname, wic.szPname,
735 sizeof(This->device->drvdesc.szDrvname));
737 This->device->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
738 This->device->drvcaps.dwFormats = wic.dwFormats;
739 This->device->drvcaps.dwChannels = wic.wChannels;
744 return err;
747 static const IDirectSoundCaptureVtbl dscvt =
749 /* IUnknown methods */
750 IDirectSoundCaptureImpl_QueryInterface,
751 IDirectSoundCaptureImpl_AddRef,
752 IDirectSoundCaptureImpl_Release,
754 /* IDirectSoundCapture methods */
755 IDirectSoundCaptureImpl_CreateCaptureBuffer,
756 IDirectSoundCaptureImpl_GetCaps,
757 IDirectSoundCaptureImpl_Initialize
760 static HRESULT
761 DSOUND_CreateDirectSoundCaptureBuffer(
762 IDirectSoundCaptureImpl *ipDSC,
763 LPCDSCBUFFERDESC lpcDSCBufferDesc,
764 LPVOID* ppobj )
766 LPWAVEFORMATEX wfex;
767 TRACE( "(%p,%p)\n", lpcDSCBufferDesc, ppobj );
769 if (ipDSC == NULL) {
770 WARN("invalid parameter: ipDSC == NULL\n");
771 return DSERR_INVALIDPARAM;
774 if (lpcDSCBufferDesc == NULL) {
775 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
776 return DSERR_INVALIDPARAM;
779 if (ppobj == NULL) {
780 WARN("invalid parameter: ppobj == NULL\n");
781 return DSERR_INVALIDPARAM;
784 if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) &&
785 (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) ||
786 (lpcDSCBufferDesc->dwBufferBytes == 0) ||
787 (lpcDSCBufferDesc->lpwfxFormat == NULL) ) {
788 WARN("invalid lpcDSCBufferDesc\n");
789 *ppobj = NULL;
790 return DSERR_INVALIDPARAM;
793 if ( !ipDSC->device) {
794 WARN("not initialized\n");
795 *ppobj = NULL;
796 return DSERR_UNINITIALIZED;
799 wfex = lpcDSCBufferDesc->lpwfxFormat;
801 if (wfex) {
802 TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
803 "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
804 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
805 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
806 wfex->wBitsPerSample, wfex->cbSize);
808 if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
809 ipDSC->device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX));
810 CopyMemory(ipDSC->device->pwfx, wfex, sizeof(WAVEFORMATEX));
811 ipDSC->device->pwfx->cbSize = 0;
812 } else {
813 ipDSC->device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize);
814 CopyMemory(ipDSC->device->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize);
816 } else {
817 WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
818 *ppobj = NULL;
819 return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */
822 *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
823 sizeof(IDirectSoundCaptureBufferImpl));
825 if ( *ppobj == NULL ) {
826 WARN("out of memory\n");
827 *ppobj = NULL;
828 return DSERR_OUTOFMEMORY;
829 } else {
830 HRESULT err = DS_OK;
831 LPBYTE newbuf;
832 DWORD buflen;
833 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)*ppobj;
835 This->ref = 1;
836 This->dsound = ipDSC;
837 This->dsound->device->capture_buffer = This;
838 This->notify = NULL;
839 This->nrofnotifies = 0;
840 This->hwnotify = NULL;
842 This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
843 lpcDSCBufferDesc->dwSize);
844 if (This->pdscbd)
845 CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
846 else {
847 WARN("no memory\n");
848 This->dsound->device->capture_buffer = 0;
849 HeapFree( GetProcessHeap(), 0, This );
850 *ppobj = NULL;
851 return DSERR_OUTOFMEMORY;
854 This->lpVtbl = &dscbvt;
856 if (ipDSC->device->driver) {
857 if (This->dsound->device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
858 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
860 if (This->dsound->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
861 /* allocate buffer from system memory */
862 buflen = lpcDSCBufferDesc->dwBufferBytes;
863 TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->device->buffer);
864 if (ipDSC->device->buffer)
865 newbuf = HeapReAlloc(GetProcessHeap(),0,ipDSC->device->buffer,buflen);
866 else
867 newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
869 if (newbuf == NULL) {
870 WARN("failed to allocate capture buffer\n");
871 err = DSERR_OUTOFMEMORY;
872 /* but the old buffer might still exist and must be re-prepared */
873 } else {
874 ipDSC->device->buffer = newbuf;
875 ipDSC->device->buflen = buflen;
877 } else {
878 /* let driver allocate memory */
879 ipDSC->device->buflen = lpcDSCBufferDesc->dwBufferBytes;
880 /* FIXME: */
881 HeapFree( GetProcessHeap(), 0, ipDSC->device->buffer);
882 ipDSC->device->buffer = NULL;
885 err = IDsCaptureDriver_CreateCaptureBuffer(ipDSC->device->driver,
886 ipDSC->device->pwfx,0,0,&(ipDSC->device->buflen),&(ipDSC->device->buffer),(LPVOID*)&(ipDSC->device->hwbuf));
887 if (err != DS_OK) {
888 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
889 This->dsound->device->capture_buffer = 0;
890 HeapFree( GetProcessHeap(), 0, This );
891 *ppobj = NULL;
892 return err;
894 } else {
895 DWORD flags = CALLBACK_FUNCTION;
896 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
897 flags |= WAVE_DIRECTSOUND;
898 err = mmErr(waveInOpen(&(ipDSC->device->hwi),
899 ipDSC->device->drvdesc.dnDevNode, ipDSC->device->pwfx,
900 (DWORD_PTR)DSOUND_capture_callback, (DWORD)ipDSC->device, flags));
901 if (err != DS_OK) {
902 WARN("waveInOpen failed\n");
903 This->dsound->device->capture_buffer = 0;
904 HeapFree( GetProcessHeap(), 0, This );
905 *ppobj = NULL;
906 return err;
909 buflen = lpcDSCBufferDesc->dwBufferBytes;
910 TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->device->buffer);
911 if (ipDSC->device->buffer)
912 newbuf = HeapReAlloc(GetProcessHeap(),0,ipDSC->device->buffer,buflen);
913 else
914 newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
915 if (newbuf == NULL) {
916 WARN("failed to allocate capture buffer\n");
917 err = DSERR_OUTOFMEMORY;
918 /* but the old buffer might still exist and must be re-prepared */
919 } else {
920 ipDSC->device->buffer = newbuf;
921 ipDSC->device->buflen = buflen;
926 TRACE("returning DS_OK\n");
927 return DS_OK;
930 /*******************************************************************************
931 * IDirectSoundCaptureNotify
933 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
934 LPDIRECTSOUNDNOTIFY iface,
935 REFIID riid,
936 LPVOID *ppobj)
938 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
939 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
941 if (This->dscb == NULL) {
942 WARN("invalid parameter\n");
943 return E_INVALIDARG;
946 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
949 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
951 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
952 ULONG ref = InterlockedIncrement(&(This->ref));
953 TRACE("(%p) ref was %ld\n", This, ref - 1);
954 return ref;
957 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
959 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
960 ULONG ref = InterlockedDecrement(&(This->ref));
961 TRACE("(%p) ref was %ld\n", This, ref + 1);
963 if (!ref) {
964 if (This->dscb->hwnotify)
965 IDsDriverNotify_Release(This->dscb->hwnotify);
966 This->dscb->notify=NULL;
967 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
968 HeapFree(GetProcessHeap(),0,This);
969 TRACE("(%p) released\n", This);
971 return ref;
974 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
975 LPDIRECTSOUNDNOTIFY iface,
976 DWORD howmuch,
977 LPCDSBPOSITIONNOTIFY notify)
979 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
980 TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
982 if (howmuch > 0 && notify == NULL) {
983 WARN("invalid parameter: notify == NULL\n");
984 return DSERR_INVALIDPARAM;
987 if (TRACE_ON(dsound)) {
988 unsigned int i;
989 for (i=0;i<howmuch;i++)
990 TRACE("notify at %ld to %p\n",
991 notify[i].dwOffset,notify[i].hEventNotify);
994 if (This->dscb->hwnotify) {
995 HRESULT hres;
996 hres = IDsDriverNotify_SetNotificationPositions(This->dscb->hwnotify, howmuch, notify);
997 if (hres != DS_OK)
998 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
999 return hres;
1000 } else if (howmuch > 0) {
1001 /* Make an internal copy of the caller-supplied array.
1002 * Replace the existing copy if one is already present. */
1003 if (This->dscb->notifies)
1004 This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1005 This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
1006 else
1007 This->dscb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1008 howmuch * sizeof(DSBPOSITIONNOTIFY));
1010 if (This->dscb->notifies == NULL) {
1011 WARN("out of memory\n");
1012 return DSERR_OUTOFMEMORY;
1014 CopyMemory(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
1015 This->dscb->nrofnotifies = howmuch;
1016 } else {
1017 HeapFree(GetProcessHeap(), 0, This->dscb->notifies);
1018 This->dscb->notifies = NULL;
1019 This->dscb->nrofnotifies = 0;
1022 return S_OK;
1025 static const IDirectSoundNotifyVtbl dscnvt =
1027 IDirectSoundCaptureNotifyImpl_QueryInterface,
1028 IDirectSoundCaptureNotifyImpl_AddRef,
1029 IDirectSoundCaptureNotifyImpl_Release,
1030 IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
1033 HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create(
1034 IDirectSoundCaptureBufferImpl *dscb,
1035 IDirectSoundCaptureNotifyImpl **pdscn)
1037 IDirectSoundCaptureNotifyImpl * dscn;
1038 TRACE("(%p,%p)\n",dscb,pdscn);
1040 dscn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dscn));
1042 if (dscn == NULL) {
1043 WARN("out of memory\n");
1044 return DSERR_OUTOFMEMORY;
1047 dscn->ref = 0;
1048 dscn->lpVtbl = &dscnvt;
1049 dscn->dscb = dscb;
1050 dscb->notify = dscn;
1051 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
1053 *pdscn = dscn;
1054 return DS_OK;
1057 /*******************************************************************************
1058 * IDirectSoundCaptureBuffer
1060 static HRESULT WINAPI
1061 IDirectSoundCaptureBufferImpl_QueryInterface(
1062 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1063 REFIID riid,
1064 LPVOID* ppobj )
1066 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1067 HRESULT hres;
1068 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
1070 if (ppobj == NULL) {
1071 WARN("invalid parameter\n");
1072 return E_INVALIDARG;
1075 *ppobj = NULL;
1077 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
1078 if (!This->notify)
1079 hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
1080 if (This->notify) {
1081 if (This->dsound->device->hwbuf) {
1082 hres = IDsCaptureDriverBuffer_QueryInterface(This->dsound->device->hwbuf,
1083 &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
1084 if (hres != DS_OK) {
1085 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
1086 *ppobj = 0;
1087 return hres;
1091 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
1092 *ppobj = (LPVOID)This->notify;
1093 return DS_OK;
1096 WARN("IID_IDirectSoundNotify\n");
1097 return E_FAIL;
1100 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
1101 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
1102 IDirectSoundCaptureBuffer8_AddRef(iface);
1103 *ppobj = This;
1104 return NO_ERROR;
1107 FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
1108 return E_NOINTERFACE;
1111 static ULONG WINAPI
1112 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
1114 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1115 ULONG ref = InterlockedIncrement(&(This->ref));
1116 TRACE("(%p) ref was %ld\n", This, ref - 1);
1117 return ref;
1120 static ULONG WINAPI
1121 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
1123 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1124 ULONG ref = InterlockedDecrement(&(This->ref));
1125 TRACE("(%p) ref was %ld\n", This, ref + 1);
1127 if (!ref) {
1128 TRACE("deleting object\n");
1129 if (This->dsound->device->state == STATE_CAPTURING)
1130 This->dsound->device->state = STATE_STOPPING;
1132 HeapFree(GetProcessHeap(),0, This->pdscbd);
1134 if (This->dsound->device->hwi) {
1135 waveInReset(This->dsound->device->hwi);
1136 waveInClose(This->dsound->device->hwi);
1137 HeapFree(GetProcessHeap(),0, This->dsound->device->pwave);
1138 This->dsound->device->pwave = 0;
1139 This->dsound->device->hwi = 0;
1142 if (This->dsound->device->hwbuf)
1143 IDsCaptureDriverBuffer_Release(This->dsound->device->hwbuf);
1145 /* remove from IDirectSoundCaptureImpl */
1146 if (This->dsound)
1147 This->dsound->device->capture_buffer = NULL;
1148 else
1149 ERR("does not reference dsound\n");
1151 if (This->notify)
1152 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
1154 HeapFree(GetProcessHeap(), 0, This->notifies);
1155 HeapFree( GetProcessHeap(), 0, This );
1156 TRACE("(%p) released\n", This);
1158 return ref;
1161 static HRESULT WINAPI
1162 IDirectSoundCaptureBufferImpl_GetCaps(
1163 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1164 LPDSCBCAPS lpDSCBCaps )
1166 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1167 TRACE( "(%p,%p)\n", This, lpDSCBCaps );
1169 if (This == NULL) {
1170 WARN("invalid parameter: This == NULL\n");
1171 return DSERR_INVALIDPARAM;
1174 if (lpDSCBCaps == NULL) {
1175 WARN("invalid parameter: lpDSCBCaps == NULL\n");
1176 return DSERR_INVALIDPARAM;
1179 if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) {
1180 WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n",
1181 lpDSCBCaps->dwSize, sizeof(DSCBCAPS));
1182 return DSERR_INVALIDPARAM;
1185 if (This->dsound == NULL) {
1186 WARN("invalid parameter: This->dsound == NULL\n");
1187 return DSERR_INVALIDPARAM;
1190 lpDSCBCaps->dwSize = sizeof(DSCBCAPS);
1191 lpDSCBCaps->dwFlags = This->flags;
1192 lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes;
1193 lpDSCBCaps->dwReserved = 0;
1195 TRACE("returning DS_OK\n");
1196 return DS_OK;
1199 static HRESULT WINAPI
1200 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
1201 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1202 LPDWORD lpdwCapturePosition,
1203 LPDWORD lpdwReadPosition )
1205 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1206 HRESULT hres = DS_OK;
1207 TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
1209 if (This == NULL) {
1210 WARN("invalid parameter: This == NULL\n");
1211 return DSERR_INVALIDPARAM;
1214 if (This->dsound == NULL) {
1215 WARN("invalid parameter: This->dsound == NULL\n");
1216 return DSERR_INVALIDPARAM;
1219 if (This->dsound->device->driver) {
1220 hres = IDsCaptureDriverBuffer_GetPosition(This->dsound->device->hwbuf, lpdwCapturePosition, lpdwReadPosition );
1221 if (hres != DS_OK)
1222 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
1223 } else if (This->dsound->device->hwi) {
1224 EnterCriticalSection(&(This->dsound->device->lock));
1225 TRACE("old This->dsound->device->state=%s\n",captureStateString[This->dsound->device->state]);
1226 if (lpdwCapturePosition) {
1227 MMTIME mtime;
1228 mtime.wType = TIME_BYTES;
1229 waveInGetPosition(This->dsound->device->hwi, &mtime, sizeof(mtime));
1230 TRACE("mtime.u.cb=%ld,This->dsound->device->buflen=%ld\n", mtime.u.cb,
1231 This->dsound->device->buflen);
1232 mtime.u.cb = mtime.u.cb % This->dsound->device->buflen;
1233 *lpdwCapturePosition = mtime.u.cb;
1236 if (lpdwReadPosition) {
1237 if (This->dsound->device->state == STATE_STARTING) {
1238 if (lpdwCapturePosition)
1239 This->dsound->device->read_position = *lpdwCapturePosition;
1240 This->dsound->device->state = STATE_CAPTURING;
1242 *lpdwReadPosition = This->dsound->device->read_position;
1244 TRACE("new This->dsound->device->state=%s\n",captureStateString[This->dsound->device->state]);
1245 LeaveCriticalSection(&(This->dsound->device->lock));
1246 if (lpdwCapturePosition) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition);
1247 if (lpdwReadPosition) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition);
1248 } else {
1249 WARN("no driver\n");
1250 hres = DSERR_NODRIVER;
1253 TRACE("returning %08lx\n", hres);
1254 return hres;
1257 static HRESULT WINAPI
1258 IDirectSoundCaptureBufferImpl_GetFormat(
1259 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1260 LPWAVEFORMATEX lpwfxFormat,
1261 DWORD dwSizeAllocated,
1262 LPDWORD lpdwSizeWritten )
1264 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1265 HRESULT hres = DS_OK;
1266 TRACE( "(%p,%p,0x%08lx,%p)\n", This, lpwfxFormat, dwSizeAllocated,
1267 lpdwSizeWritten );
1269 if (This == NULL) {
1270 WARN("invalid parameter: This == NULL\n");
1271 return DSERR_INVALIDPARAM;
1274 if (This->dsound == NULL) {
1275 WARN("invalid parameter: This->dsound == NULL\n");
1276 return DSERR_INVALIDPARAM;
1279 if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->dsound->device->pwfx->cbSize))
1280 dwSizeAllocated = sizeof(WAVEFORMATEX) + This->dsound->device->pwfx->cbSize;
1282 if (lpwfxFormat) { /* NULL is valid (just want size) */
1283 CopyMemory(lpwfxFormat, This->dsound->device->pwfx, dwSizeAllocated);
1284 if (lpdwSizeWritten)
1285 *lpdwSizeWritten = dwSizeAllocated;
1286 } else {
1287 if (lpdwSizeWritten)
1288 *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->dsound->device->pwfx->cbSize;
1289 else {
1290 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
1291 hres = DSERR_INVALIDPARAM;
1295 TRACE("returning %08lx\n", hres);
1296 return hres;
1299 static HRESULT WINAPI
1300 IDirectSoundCaptureBufferImpl_GetStatus(
1301 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1302 LPDWORD lpdwStatus )
1304 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1305 TRACE( "(%p, %p), thread is %04lx\n", This, lpdwStatus, GetCurrentThreadId() );
1307 if (This == NULL) {
1308 WARN("invalid parameter: This == NULL\n");
1309 return DSERR_INVALIDPARAM;
1312 if (This->dsound == NULL) {
1313 WARN("invalid parameter: This->dsound == NULL\n");
1314 return DSERR_INVALIDPARAM;
1317 if (lpdwStatus == NULL) {
1318 WARN("invalid parameter: lpdwStatus == NULL\n");
1319 return DSERR_INVALIDPARAM;
1322 *lpdwStatus = 0;
1323 EnterCriticalSection(&(This->dsound->device->lock));
1325 TRACE("old This->dsound->state=%s, old lpdwStatus=%08lx\n",
1326 captureStateString[This->dsound->device->state],*lpdwStatus);
1327 if ((This->dsound->device->state == STATE_STARTING) ||
1328 (This->dsound->device->state == STATE_CAPTURING)) {
1329 *lpdwStatus |= DSCBSTATUS_CAPTURING;
1330 if (This->flags & DSCBSTART_LOOPING)
1331 *lpdwStatus |= DSCBSTATUS_LOOPING;
1333 TRACE("new This->dsound->state=%s, new lpdwStatus=%08lx\n",
1334 captureStateString[This->dsound->device->state],*lpdwStatus);
1335 LeaveCriticalSection(&(This->dsound->device->lock));
1337 TRACE("status=%lx\n", *lpdwStatus);
1338 TRACE("returning DS_OK\n");
1339 return DS_OK;
1342 static HRESULT WINAPI
1343 IDirectSoundCaptureBufferImpl_Initialize(
1344 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1345 LPDIRECTSOUNDCAPTURE lpDSC,
1346 LPCDSCBUFFERDESC lpcDSCBDesc )
1348 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1350 FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
1352 return DS_OK;
1355 static HRESULT WINAPI
1356 IDirectSoundCaptureBufferImpl_Lock(
1357 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1358 DWORD dwReadCusor,
1359 DWORD dwReadBytes,
1360 LPVOID* lplpvAudioPtr1,
1361 LPDWORD lpdwAudioBytes1,
1362 LPVOID* lplpvAudioPtr2,
1363 LPDWORD lpdwAudioBytes2,
1364 DWORD dwFlags )
1366 HRESULT hres = DS_OK;
1367 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1368 TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This, dwReadCusor,
1369 dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
1370 lpdwAudioBytes2, dwFlags, GetTickCount() );
1372 if (This == NULL) {
1373 WARN("invalid parameter: This == NULL\n");
1374 return DSERR_INVALIDPARAM;
1377 if (This->dsound == NULL) {
1378 WARN("invalid parameter: This->dsound == NULL\n");
1379 return DSERR_INVALIDPARAM;
1382 if (lplpvAudioPtr1 == NULL) {
1383 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
1384 return DSERR_INVALIDPARAM;
1387 if (lpdwAudioBytes1 == NULL) {
1388 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
1389 return DSERR_INVALIDPARAM;
1392 EnterCriticalSection(&(This->dsound->device->lock));
1394 if (This->dsound->device->driver) {
1395 hres = IDsCaptureDriverBuffer_Lock(This->dsound->device->hwbuf, lplpvAudioPtr1,
1396 lpdwAudioBytes1, lplpvAudioPtr2,
1397 lpdwAudioBytes2, dwReadCusor,
1398 dwReadBytes, dwFlags);
1399 if (hres != DS_OK)
1400 WARN("IDsCaptureDriverBuffer_Lock failed\n");
1401 } else if (This->dsound->device->hwi) {
1402 *lplpvAudioPtr1 = This->dsound->device->buffer + dwReadCusor;
1403 if ( (dwReadCusor + dwReadBytes) > This->dsound->device->buflen) {
1404 *lpdwAudioBytes1 = This->dsound->device->buflen - dwReadCusor;
1405 if (lplpvAudioPtr2)
1406 *lplpvAudioPtr2 = This->dsound->device->buffer;
1407 if (lpdwAudioBytes2)
1408 *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
1409 } else {
1410 *lpdwAudioBytes1 = dwReadBytes;
1411 if (lplpvAudioPtr2)
1412 *lplpvAudioPtr2 = 0;
1413 if (lpdwAudioBytes2)
1414 *lpdwAudioBytes2 = 0;
1416 } else {
1417 TRACE("invalid call\n");
1418 hres = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */
1421 LeaveCriticalSection(&(This->dsound->device->lock));
1423 TRACE("returning %08lx\n", hres);
1424 return hres;
1427 static HRESULT WINAPI
1428 IDirectSoundCaptureBufferImpl_Start(
1429 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1430 DWORD dwFlags )
1432 HRESULT hres = DS_OK;
1433 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1434 TRACE( "(%p,0x%08lx)\n", This, dwFlags );
1436 if (This == NULL) {
1437 WARN("invalid parameter: This == NULL\n");
1438 return DSERR_INVALIDPARAM;
1441 if (This->dsound == NULL) {
1442 WARN("invalid parameter: This->dsound == NULL\n");
1443 return DSERR_INVALIDPARAM;
1446 if ( (This->dsound->device->driver == 0) && (This->dsound->device->hwi == 0) ) {
1447 WARN("no driver\n");
1448 return DSERR_NODRIVER;
1451 EnterCriticalSection(&(This->dsound->device->lock));
1453 This->flags = dwFlags;
1454 TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->device->state]);
1455 if (This->dsound->device->state == STATE_STOPPED)
1456 This->dsound->device->state = STATE_STARTING;
1457 else if (This->dsound->device->state == STATE_STOPPING)
1458 This->dsound->device->state = STATE_CAPTURING;
1459 TRACE("new This->dsound->device->state=%s\n",captureStateString[This->dsound->device->state]);
1461 LeaveCriticalSection(&(This->dsound->device->lock));
1463 if (This->dsound->device->driver) {
1464 hres = IDsCaptureDriverBuffer_Start(This->dsound->device->hwbuf, dwFlags);
1465 if (hres != DS_OK)
1466 WARN("IDsCaptureDriverBuffer_Start failed\n");
1467 } else if (This->dsound->device->hwi) {
1468 IDirectSoundCaptureImpl* ipDSC = This->dsound;
1470 if (ipDSC->device->buffer) {
1471 if (This->nrofnotifies) {
1472 int c;
1474 ipDSC->device->nrofpwaves = This->nrofnotifies;
1475 TRACE("nrofnotifies=%d\n", This->nrofnotifies);
1477 /* prepare headers */
1478 if (ipDSC->device->pwave)
1479 ipDSC->device->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->device->pwave,
1480 ipDSC->device->nrofpwaves*sizeof(WAVEHDR));
1481 else
1482 ipDSC->device->pwave = HeapAlloc(GetProcessHeap(),0,
1483 ipDSC->device->nrofpwaves*sizeof(WAVEHDR));
1485 for (c = 0; c < ipDSC->device->nrofpwaves; c++) {
1486 if (This->notifies[c].dwOffset == DSBPN_OFFSETSTOP) {
1487 TRACE("got DSBPN_OFFSETSTOP\n");
1488 ipDSC->device->nrofpwaves = c;
1489 break;
1491 if (c == 0) {
1492 ipDSC->device->pwave[0].lpData = (LPSTR)ipDSC->device->buffer;
1493 ipDSC->device->pwave[0].dwBufferLength =
1494 This->notifies[0].dwOffset + 1;
1495 } else {
1496 ipDSC->device->pwave[c].lpData = (LPSTR)ipDSC->device->buffer +
1497 This->notifies[c-1].dwOffset + 1;
1498 ipDSC->device->pwave[c].dwBufferLength =
1499 This->notifies[c].dwOffset -
1500 This->notifies[c-1].dwOffset;
1502 ipDSC->device->pwave[c].dwBytesRecorded = 0;
1503 ipDSC->device->pwave[c].dwUser = (DWORD)ipDSC;
1504 ipDSC->device->pwave[c].dwFlags = 0;
1505 ipDSC->device->pwave[c].dwLoops = 0;
1506 hres = mmErr(waveInPrepareHeader(ipDSC->device->hwi,
1507 &(ipDSC->device->pwave[c]),sizeof(WAVEHDR)));
1508 if (hres != DS_OK) {
1509 WARN("waveInPrepareHeader failed\n");
1510 while (c--)
1511 waveInUnprepareHeader(ipDSC->device->hwi,
1512 &(ipDSC->device->pwave[c]),sizeof(WAVEHDR));
1513 break;
1516 hres = mmErr(waveInAddBuffer(ipDSC->device->hwi,
1517 &(ipDSC->device->pwave[c]), sizeof(WAVEHDR)));
1518 if (hres != DS_OK) {
1519 WARN("waveInAddBuffer failed\n");
1520 while (c--)
1521 waveInUnprepareHeader(ipDSC->device->hwi,
1522 &(ipDSC->device->pwave[c]),sizeof(WAVEHDR));
1523 break;
1527 FillMemory(ipDSC->device->buffer, ipDSC->device->buflen,
1528 (ipDSC->device->pwfx->wBitsPerSample == 8) ? 128 : 0);
1529 } else {
1530 TRACE("no notifiers specified\n");
1531 /* no notifiers specified so just create a single default header */
1532 ipDSC->device->nrofpwaves = 1;
1533 if (ipDSC->device->pwave)
1534 ipDSC->device->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->device->pwave,sizeof(WAVEHDR));
1535 else
1536 ipDSC->device->pwave = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR));
1538 ipDSC->device->pwave[0].lpData = (LPSTR)ipDSC->device->buffer;
1539 ipDSC->device->pwave[0].dwBufferLength = ipDSC->device->buflen;
1540 ipDSC->device->pwave[0].dwBytesRecorded = 0;
1541 ipDSC->device->pwave[0].dwUser = (DWORD)ipDSC;
1542 ipDSC->device->pwave[0].dwFlags = 0;
1543 ipDSC->device->pwave[0].dwLoops = 0;
1545 hres = mmErr(waveInPrepareHeader(ipDSC->device->hwi,
1546 &(ipDSC->device->pwave[0]),sizeof(WAVEHDR)));
1547 if (hres != DS_OK) {
1548 WARN("waveInPrepareHeader failed\n");
1549 waveInUnprepareHeader(ipDSC->device->hwi,
1550 &(ipDSC->device->pwave[0]),sizeof(WAVEHDR));
1552 hres = mmErr(waveInAddBuffer(ipDSC->device->hwi,
1553 &(ipDSC->device->pwave[0]), sizeof(WAVEHDR)));
1554 if (hres != DS_OK) {
1555 WARN("waveInAddBuffer failed\n");
1556 waveInUnprepareHeader(ipDSC->device->hwi,
1557 &(ipDSC->device->pwave[0]),sizeof(WAVEHDR));
1562 ipDSC->device->index = 0;
1563 ipDSC->device->read_position = 0;
1565 if (hres == DS_OK) {
1566 /* start filling the first buffer */
1567 hres = mmErr(waveInStart(ipDSC->device->hwi));
1568 if (hres != DS_OK)
1569 WARN("waveInStart failed\n");
1572 if (hres != DS_OK) {
1573 WARN("calling waveInClose because of error\n");
1574 waveInClose(This->dsound->device->hwi);
1575 This->dsound->device->hwi = 0;
1577 } else {
1578 WARN("no driver\n");
1579 hres = DSERR_NODRIVER;
1582 TRACE("returning %08lx\n", hres);
1583 return hres;
1586 static HRESULT WINAPI
1587 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
1589 HRESULT hres = DS_OK;
1590 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1591 TRACE( "(%p)\n", This );
1593 if (This == NULL) {
1594 WARN("invalid parameter: This == NULL\n");
1595 return DSERR_INVALIDPARAM;
1598 if (This->dsound == NULL) {
1599 WARN("invalid parameter: This->dsound == NULL\n");
1600 return DSERR_INVALIDPARAM;
1603 EnterCriticalSection(&(This->dsound->device->lock));
1605 TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->device->state]);
1606 if (This->dsound->device->state == STATE_CAPTURING)
1607 This->dsound->device->state = STATE_STOPPING;
1608 else if (This->dsound->device->state == STATE_STARTING)
1609 This->dsound->device->state = STATE_STOPPED;
1610 TRACE("new This->dsound->device->state=%s\n",captureStateString[This->dsound->device->state]);
1612 LeaveCriticalSection(&(This->dsound->device->lock));
1614 if (This->dsound->device->driver) {
1615 hres = IDsCaptureDriverBuffer_Stop(This->dsound->device->hwbuf);
1616 if (hres != DS_OK)
1617 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
1618 } else if (This->dsound->device->hwi) {
1619 hres = mmErr(waveInReset(This->dsound->device->hwi));
1620 if (hres != DS_OK)
1621 WARN("waveInReset() failed\n");
1622 } else {
1623 WARN("no driver\n");
1624 hres = DSERR_NODRIVER;
1627 TRACE("returning %08lx\n", hres);
1628 return hres;
1631 static HRESULT WINAPI
1632 IDirectSoundCaptureBufferImpl_Unlock(
1633 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1634 LPVOID lpvAudioPtr1,
1635 DWORD dwAudioBytes1,
1636 LPVOID lpvAudioPtr2,
1637 DWORD dwAudioBytes2 )
1639 HRESULT hres = DS_OK;
1640 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1641 TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This, lpvAudioPtr1, dwAudioBytes1,
1642 lpvAudioPtr2, dwAudioBytes2 );
1644 if (This == NULL) {
1645 WARN("invalid parameter: This == NULL\n");
1646 return DSERR_INVALIDPARAM;
1649 if (lpvAudioPtr1 == NULL) {
1650 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
1651 return DSERR_INVALIDPARAM;
1654 if (This->dsound->device->driver) {
1655 hres = IDsCaptureDriverBuffer_Unlock(This->dsound->device->hwbuf, lpvAudioPtr1,
1656 dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
1657 if (hres != DS_OK)
1658 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
1659 } else if (This->dsound->device->hwi) {
1660 This->dsound->device->read_position = (This->dsound->device->read_position +
1661 (dwAudioBytes1 + dwAudioBytes2)) % This->dsound->device->buflen;
1662 } else {
1663 WARN("invalid call\n");
1664 hres = DSERR_INVALIDCALL;
1667 TRACE("returning %08lx\n", hres);
1668 return hres;
1671 static HRESULT WINAPI
1672 IDirectSoundCaptureBufferImpl_GetObjectInPath(
1673 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1674 REFGUID rguidObject,
1675 DWORD dwIndex,
1676 REFGUID rguidInterface,
1677 LPVOID* ppObject )
1679 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1681 FIXME( "(%p,%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject),
1682 dwIndex, debugstr_guid(rguidInterface), ppObject );
1684 return DS_OK;
1687 static HRESULT WINAPI
1688 IDirectSoundCaptureBufferImpl_GetFXStatus(
1689 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
1690 DWORD dwFXCount,
1691 LPDWORD pdwFXStatus )
1693 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
1695 FIXME( "(%p,%lu,%p): stub\n", This, dwFXCount, pdwFXStatus );
1697 return DS_OK;
1700 static const IDirectSoundCaptureBuffer8Vtbl dscbvt =
1702 /* IUnknown methods */
1703 IDirectSoundCaptureBufferImpl_QueryInterface,
1704 IDirectSoundCaptureBufferImpl_AddRef,
1705 IDirectSoundCaptureBufferImpl_Release,
1707 /* IDirectSoundCaptureBuffer methods */
1708 IDirectSoundCaptureBufferImpl_GetCaps,
1709 IDirectSoundCaptureBufferImpl_GetCurrentPosition,
1710 IDirectSoundCaptureBufferImpl_GetFormat,
1711 IDirectSoundCaptureBufferImpl_GetStatus,
1712 IDirectSoundCaptureBufferImpl_Initialize,
1713 IDirectSoundCaptureBufferImpl_Lock,
1714 IDirectSoundCaptureBufferImpl_Start,
1715 IDirectSoundCaptureBufferImpl_Stop,
1716 IDirectSoundCaptureBufferImpl_Unlock,
1718 /* IDirectSoundCaptureBuffer methods */
1719 IDirectSoundCaptureBufferImpl_GetObjectInPath,
1720 IDirectSoundCaptureBufferImpl_GetFXStatus
1723 /*******************************************************************************
1724 * DirectSoundCapture ClassFactory
1727 static HRESULT WINAPI
1728 DSCCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
1730 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1732 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
1733 return E_NOINTERFACE;
1736 static ULONG WINAPI
1737 DSCCF_AddRef(LPCLASSFACTORY iface)
1739 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1740 ULONG ref = InterlockedIncrement(&(This->ref));
1741 TRACE("(%p) ref was %ld\n", This, ref - 1);
1742 return ref;
1745 static ULONG WINAPI
1746 DSCCF_Release(LPCLASSFACTORY iface)
1748 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1749 ULONG ref = InterlockedDecrement(&(This->ref));
1750 TRACE("(%p) ref was %ld\n", This, ref + 1);
1751 /* static class, won't be freed */
1752 return ref;
1755 static HRESULT WINAPI
1756 DSCCF_CreateInstance(
1757 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
1759 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1760 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
1762 if (pOuter) {
1763 WARN("aggregation not supported\n");
1764 return CLASS_E_NOAGGREGATION;
1767 if (ppobj == NULL) {
1768 WARN("invalid parameter\n");
1769 return E_INVALIDARG;
1772 *ppobj = NULL;
1774 if ( IsEqualGUID( &IID_IDirectSoundCapture, riid ) )
1775 return DSOUND_CaptureCreate8((LPDIRECTSOUNDCAPTURE*)ppobj,pOuter);
1777 WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
1778 return E_NOINTERFACE;
1781 static HRESULT WINAPI
1782 DSCCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
1784 IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
1785 FIXME("(%p)->(%d),stub!\n",This,dolock);
1786 return S_OK;
1789 static const IClassFactoryVtbl DSCCF_Vtbl =
1791 DSCCF_QueryInterface,
1792 DSCCF_AddRef,
1793 DSCCF_Release,
1794 DSCCF_CreateInstance,
1795 DSCCF_LockServer
1798 IClassFactoryImpl DSOUND_CAPTURE_CF = { &DSCCF_Vtbl, 1 };