msxml3: Get rid of libxml2 output buffer implementation.
[wine/multimedia.git] / dlls / dsound / capture.c
blob4897e175770fc978e49b4c176a573588546310e0
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 COBJMACROS
31 #define NONAMELESSSTRUCT
32 #define NONAMELESSUNION
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winuser.h"
36 #include "mmsystem.h"
37 #include "mmddk.h"
38 #include "winternl.h"
39 #include "winnls.h"
40 #include "wine/debug.h"
41 #include "dsound.h"
42 #include "dsound_private.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
47 /*****************************************************************************
48 * IDirectSoundCaptureNotify implementation structure
50 struct IDirectSoundCaptureNotifyImpl
52 /* IUnknown fields */
53 const IDirectSoundNotifyVtbl *lpVtbl;
54 LONG ref;
55 IDirectSoundCaptureBufferImpl* dscb;
58 /*******************************************************************************
59 * IDirectSoundCaptureNotify
61 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
62 LPDIRECTSOUNDNOTIFY iface,
63 REFIID riid,
64 LPVOID *ppobj)
66 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
67 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
69 if (This->dscb == NULL) {
70 WARN("invalid parameter\n");
71 return E_INVALIDARG;
74 return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
77 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
79 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
80 ULONG ref = InterlockedIncrement(&(This->ref));
81 TRACE("(%p) ref was %d\n", This, ref - 1);
82 return ref;
85 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
87 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
88 ULONG ref = InterlockedDecrement(&(This->ref));
89 TRACE("(%p) ref was %d\n", This, ref + 1);
91 if (!ref) {
92 This->dscb->notify=NULL;
93 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
94 HeapFree(GetProcessHeap(),0,This);
95 TRACE("(%p) released\n", This);
97 return ref;
100 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
101 LPDIRECTSOUNDNOTIFY iface,
102 DWORD howmuch,
103 LPCDSBPOSITIONNOTIFY notify)
105 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
106 TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
108 if (howmuch > 0 && notify == NULL) {
109 WARN("invalid parameter: notify == NULL\n");
110 return DSERR_INVALIDPARAM;
113 if (TRACE_ON(dsound)) {
114 unsigned int i;
115 for (i=0;i<howmuch;i++)
116 TRACE("notify at %d to %p\n",
117 notify[i].dwOffset,notify[i].hEventNotify);
120 if (howmuch > 0) {
121 /* Make an internal copy of the caller-supplied array.
122 * Replace the existing copy if one is already present. */
123 if (This->dscb->notifies)
124 This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
125 This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
126 else
127 This->dscb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
128 howmuch * sizeof(DSBPOSITIONNOTIFY));
130 if (This->dscb->notifies == NULL) {
131 WARN("out of memory\n");
132 return DSERR_OUTOFMEMORY;
134 CopyMemory(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
135 This->dscb->nrofnotifies = howmuch;
136 } else {
137 HeapFree(GetProcessHeap(), 0, This->dscb->notifies);
138 This->dscb->notifies = NULL;
139 This->dscb->nrofnotifies = 0;
142 return S_OK;
145 static const IDirectSoundNotifyVtbl dscnvt =
147 IDirectSoundCaptureNotifyImpl_QueryInterface,
148 IDirectSoundCaptureNotifyImpl_AddRef,
149 IDirectSoundCaptureNotifyImpl_Release,
150 IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
153 static HRESULT IDirectSoundCaptureNotifyImpl_Create(
154 IDirectSoundCaptureBufferImpl *dscb,
155 IDirectSoundCaptureNotifyImpl **pdscn)
157 IDirectSoundCaptureNotifyImpl * dscn;
158 TRACE("(%p,%p)\n",dscb,pdscn);
160 dscn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dscn));
162 if (dscn == NULL) {
163 WARN("out of memory\n");
164 return DSERR_OUTOFMEMORY;
167 dscn->ref = 0;
168 dscn->lpVtbl = &dscnvt;
169 dscn->dscb = dscb;
170 dscb->notify = dscn;
171 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
173 *pdscn = dscn;
174 return DS_OK;
178 static const char * const captureStateString[] = {
179 "STATE_STOPPED",
180 "STATE_STARTING",
181 "STATE_CAPTURING",
182 "STATE_STOPPING"
186 /*******************************************************************************
187 * IDirectSoundCaptureBuffer
189 static HRESULT WINAPI
190 IDirectSoundCaptureBufferImpl_QueryInterface(
191 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
192 REFIID riid,
193 LPVOID* ppobj )
195 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
196 HRESULT hres;
198 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
200 if (ppobj == NULL) {
201 WARN("invalid parameter\n");
202 return E_INVALIDARG;
205 *ppobj = NULL;
207 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
208 if (!This->notify){
209 hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
210 if(FAILED(hres))
211 return hres;
214 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
215 *ppobj = This->notify;
216 return DS_OK;
219 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
220 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
221 IDirectSoundCaptureBuffer8_AddRef(iface);
222 *ppobj = This;
223 return NO_ERROR;
226 FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
227 return E_NOINTERFACE;
230 static ULONG WINAPI
231 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
233 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
234 ULONG ref = InterlockedIncrement(&(This->ref));
235 TRACE("(%p) ref was %d\n", This, ref - 1);
236 return ref;
239 static ULONG WINAPI
240 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
242 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
243 ULONG ref = InterlockedDecrement(&(This->ref));
244 TRACE("(%p) ref was %d\n", This, ref + 1);
246 if (!ref) {
247 TRACE("deleting object\n");
248 if (This->device->state == STATE_CAPTURING)
249 This->device->state = STATE_STOPPING;
251 HeapFree(GetProcessHeap(),0, This->pdscbd);
253 if (This->device->client) {
254 IAudioClient_Release(This->device->client);
255 This->device->client = NULL;
258 if (This->device->capture) {
259 IAudioCaptureClient_Release(This->device->capture);
260 This->device->capture = NULL;
263 /* remove from DirectSoundCaptureDevice */
264 This->device->capture_buffer = NULL;
266 if (This->notify)
267 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
269 HeapFree(GetProcessHeap(), 0, This->notifies);
270 HeapFree( GetProcessHeap(), 0, This );
271 TRACE("(%p) released\n", This);
273 return ref;
276 static HRESULT WINAPI
277 IDirectSoundCaptureBufferImpl_GetCaps(
278 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
279 LPDSCBCAPS lpDSCBCaps )
281 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
282 TRACE( "(%p,%p)\n", This, lpDSCBCaps );
284 if (lpDSCBCaps == NULL) {
285 WARN("invalid parameter: lpDSCBCaps == NULL\n");
286 return DSERR_INVALIDPARAM;
289 if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) {
290 WARN("invalid parameter: lpDSCBCaps->dwSize = %d\n", lpDSCBCaps->dwSize);
291 return DSERR_INVALIDPARAM;
294 if (This->device == NULL) {
295 WARN("invalid parameter: This->device == NULL\n");
296 return DSERR_INVALIDPARAM;
299 lpDSCBCaps->dwSize = sizeof(DSCBCAPS);
300 lpDSCBCaps->dwFlags = This->flags;
301 lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes;
302 lpDSCBCaps->dwReserved = 0;
304 TRACE("returning DS_OK\n");
305 return DS_OK;
308 static HRESULT WINAPI
309 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
310 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
311 LPDWORD lpdwCapturePosition,
312 LPDWORD lpdwReadPosition )
314 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
315 TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
317 if (This->device == NULL) {
318 WARN("invalid parameter: This->device == NULL\n");
319 return DSERR_INVALIDPARAM;
322 EnterCriticalSection(&This->device->lock);
324 if (!This->device->client) {
325 LeaveCriticalSection(&This->device->lock);
326 WARN("no driver\n");
327 return DSERR_NODRIVER;
330 if(lpdwCapturePosition)
331 *lpdwCapturePosition = This->device->write_pos_bytes;
333 if(lpdwReadPosition)
334 *lpdwReadPosition = This->device->write_pos_bytes;
336 LeaveCriticalSection(&This->device->lock);
338 TRACE("cappos=%d readpos=%d\n", (lpdwCapturePosition?*lpdwCapturePosition:-1), (lpdwReadPosition?*lpdwReadPosition:-1));
339 TRACE("returning DS_OK\n");
341 return DS_OK;
344 static HRESULT WINAPI
345 IDirectSoundCaptureBufferImpl_GetFormat(
346 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
347 LPWAVEFORMATEX lpwfxFormat,
348 DWORD dwSizeAllocated,
349 LPDWORD lpdwSizeWritten )
351 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
352 HRESULT hres = DS_OK;
353 TRACE( "(%p,%p,0x%08x,%p)\n", This, lpwfxFormat, dwSizeAllocated,
354 lpdwSizeWritten );
356 if (This->device == NULL) {
357 WARN("invalid parameter: This->device == NULL\n");
358 return DSERR_INVALIDPARAM;
361 if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize))
362 dwSizeAllocated = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
364 if (lpwfxFormat) { /* NULL is valid (just want size) */
365 CopyMemory(lpwfxFormat, This->device->pwfx, dwSizeAllocated);
366 if (lpdwSizeWritten)
367 *lpdwSizeWritten = dwSizeAllocated;
368 } else {
369 if (lpdwSizeWritten)
370 *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
371 else {
372 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
373 hres = DSERR_INVALIDPARAM;
377 TRACE("returning %08x\n", hres);
378 return hres;
381 static HRESULT WINAPI
382 IDirectSoundCaptureBufferImpl_GetStatus(
383 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
384 LPDWORD lpdwStatus )
386 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
387 TRACE( "(%p, %p), thread is %04x\n", This, lpdwStatus, GetCurrentThreadId() );
389 if (This->device == NULL) {
390 WARN("invalid parameter: This->device == NULL\n");
391 return DSERR_INVALIDPARAM;
394 if (lpdwStatus == NULL) {
395 WARN("invalid parameter: lpdwStatus == NULL\n");
396 return DSERR_INVALIDPARAM;
399 *lpdwStatus = 0;
400 EnterCriticalSection(&(This->device->lock));
402 TRACE("old This->device->state=%s, old lpdwStatus=%08x\n",
403 captureStateString[This->device->state],*lpdwStatus);
404 if ((This->device->state == STATE_STARTING) ||
405 (This->device->state == STATE_CAPTURING)) {
406 *lpdwStatus |= DSCBSTATUS_CAPTURING;
407 if (This->flags & DSCBSTART_LOOPING)
408 *lpdwStatus |= DSCBSTATUS_LOOPING;
410 TRACE("new This->device->state=%s, new lpdwStatus=%08x\n",
411 captureStateString[This->device->state],*lpdwStatus);
412 LeaveCriticalSection(&(This->device->lock));
414 TRACE("status=%x\n", *lpdwStatus);
415 TRACE("returning DS_OK\n");
416 return DS_OK;
419 static HRESULT WINAPI
420 IDirectSoundCaptureBufferImpl_Initialize(
421 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
422 LPDIRECTSOUNDCAPTURE lpDSC,
423 LPCDSCBUFFERDESC lpcDSCBDesc )
425 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
427 FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
429 return DS_OK;
432 static HRESULT WINAPI
433 IDirectSoundCaptureBufferImpl_Lock(
434 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
435 DWORD dwReadCusor,
436 DWORD dwReadBytes,
437 LPVOID* lplpvAudioPtr1,
438 LPDWORD lpdwAudioBytes1,
439 LPVOID* lplpvAudioPtr2,
440 LPDWORD lpdwAudioBytes2,
441 DWORD dwFlags )
443 HRESULT hres = DS_OK;
444 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
445 TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This, dwReadCusor,
446 dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
447 lpdwAudioBytes2, dwFlags, GetTickCount() );
449 if (This->device == NULL) {
450 WARN("invalid parameter: This->device == NULL\n");
451 return DSERR_INVALIDPARAM;
454 if (lplpvAudioPtr1 == NULL) {
455 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
456 return DSERR_INVALIDPARAM;
459 if (lpdwAudioBytes1 == NULL) {
460 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
461 return DSERR_INVALIDPARAM;
464 EnterCriticalSection(&(This->device->lock));
466 if (This->device->client) {
467 *lplpvAudioPtr1 = This->device->buffer + dwReadCusor;
468 if ( (dwReadCusor + dwReadBytes) > This->device->buflen) {
469 *lpdwAudioBytes1 = This->device->buflen - dwReadCusor;
470 if (lplpvAudioPtr2)
471 *lplpvAudioPtr2 = This->device->buffer;
472 if (lpdwAudioBytes2)
473 *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
474 } else {
475 *lpdwAudioBytes1 = dwReadBytes;
476 if (lplpvAudioPtr2)
477 *lplpvAudioPtr2 = 0;
478 if (lpdwAudioBytes2)
479 *lpdwAudioBytes2 = 0;
481 } else {
482 TRACE("invalid call\n");
483 hres = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */
486 LeaveCriticalSection(&(This->device->lock));
488 TRACE("returning %08x\n", hres);
489 return hres;
492 static HRESULT WINAPI
493 IDirectSoundCaptureBufferImpl_Start(
494 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
495 DWORD dwFlags )
497 HRESULT hres;
498 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
500 TRACE( "(%p,0x%08x)\n", This, dwFlags );
502 if (This->device == NULL) {
503 WARN("invalid parameter: This->device == NULL\n");
504 return DSERR_INVALIDPARAM;
507 if ( !This->device->client ) {
508 WARN("no driver\n");
509 return DSERR_NODRIVER;
512 EnterCriticalSection(&(This->device->lock));
514 This->flags = dwFlags;
515 TRACE("old This->device->state=%s\n",captureStateString[This->device->state]);
516 if (This->device->state == STATE_STOPPED)
517 This->device->state = STATE_STARTING;
518 else if (This->device->state == STATE_STOPPING)
519 This->device->state = STATE_CAPTURING;
520 TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
522 if (This->device->buffer)
523 FillMemory(This->device->buffer, This->device->buflen, (This->device->pwfx->wBitsPerSample == 8) ? 128 : 0);
525 hres = IAudioClient_Start(This->device->client);
526 if(FAILED(hres)){
527 WARN("Start failed: %08x\n", hres);
528 LeaveCriticalSection(&This->device->lock);
529 return hres;
532 LeaveCriticalSection(&This->device->lock);
534 TRACE("returning DS_OK\n");
535 return DS_OK;
538 static HRESULT WINAPI
539 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
541 HRESULT hres;
542 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
543 TRACE( "(%p)\n", This );
545 if (This->device == NULL) {
546 WARN("invalid parameter: This->device == NULL\n");
547 return DSERR_INVALIDPARAM;
550 EnterCriticalSection(&(This->device->lock));
552 TRACE("old This->device->state=%s\n",captureStateString[This->device->state]);
553 if (This->device->state == STATE_CAPTURING)
554 This->device->state = STATE_STOPPING;
555 else if (This->device->state == STATE_STARTING)
556 This->device->state = STATE_STOPPED;
557 TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
559 if(This->device->client){
560 hres = IAudioClient_Stop(This->device->client);
561 if(FAILED(hres)){
562 LeaveCriticalSection(&This->device->lock);
563 return hres;
567 LeaveCriticalSection(&(This->device->lock));
569 TRACE("returning DS_OK\n");
570 return DS_OK;
573 static HRESULT WINAPI
574 IDirectSoundCaptureBufferImpl_Unlock(
575 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
576 LPVOID lpvAudioPtr1,
577 DWORD dwAudioBytes1,
578 LPVOID lpvAudioPtr2,
579 DWORD dwAudioBytes2 )
581 HRESULT hres = DS_OK;
582 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
583 TRACE( "(%p,%p,%08u,%p,%08u)\n", This, lpvAudioPtr1, dwAudioBytes1,
584 lpvAudioPtr2, dwAudioBytes2 );
586 if (lpvAudioPtr1 == NULL) {
587 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
588 return DSERR_INVALIDPARAM;
591 if (!This->device->client) {
592 WARN("invalid call\n");
593 hres = DSERR_INVALIDCALL;
596 TRACE("returning %08x\n", hres);
597 return hres;
600 static HRESULT WINAPI
601 IDirectSoundCaptureBufferImpl_GetObjectInPath(
602 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
603 REFGUID rguidObject,
604 DWORD dwIndex,
605 REFGUID rguidInterface,
606 LPVOID* ppObject )
608 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
610 FIXME( "(%p,%s,%u,%s,%p): stub\n", This, debugstr_guid(rguidObject),
611 dwIndex, debugstr_guid(rguidInterface), ppObject );
613 return DS_OK;
616 static HRESULT WINAPI
617 IDirectSoundCaptureBufferImpl_GetFXStatus(
618 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
619 DWORD dwFXCount,
620 LPDWORD pdwFXStatus )
622 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
624 FIXME( "(%p,%u,%p): stub\n", This, dwFXCount, pdwFXStatus );
626 return DS_OK;
629 static const IDirectSoundCaptureBuffer8Vtbl dscbvt =
631 /* IUnknown methods */
632 IDirectSoundCaptureBufferImpl_QueryInterface,
633 IDirectSoundCaptureBufferImpl_AddRef,
634 IDirectSoundCaptureBufferImpl_Release,
636 /* IDirectSoundCaptureBuffer methods */
637 IDirectSoundCaptureBufferImpl_GetCaps,
638 IDirectSoundCaptureBufferImpl_GetCurrentPosition,
639 IDirectSoundCaptureBufferImpl_GetFormat,
640 IDirectSoundCaptureBufferImpl_GetStatus,
641 IDirectSoundCaptureBufferImpl_Initialize,
642 IDirectSoundCaptureBufferImpl_Lock,
643 IDirectSoundCaptureBufferImpl_Start,
644 IDirectSoundCaptureBufferImpl_Stop,
645 IDirectSoundCaptureBufferImpl_Unlock,
647 /* IDirectSoundCaptureBuffer methods */
648 IDirectSoundCaptureBufferImpl_GetObjectInPath,
649 IDirectSoundCaptureBufferImpl_GetFXStatus
652 static void capture_CheckNotify(IDirectSoundCaptureBufferImpl *This, DWORD from, DWORD len)
654 int i;
655 for (i = 0; i < This->nrofnotifies; ++i) {
656 LPDSBPOSITIONNOTIFY event = This->notifies + i;
657 DWORD offset = event->dwOffset;
658 TRACE("checking %d, position %d, event = %p\n", i, offset, event->hEventNotify);
660 if (offset == DSBPN_OFFSETSTOP) {
661 if (!from && !len) {
662 SetEvent(event->hEventNotify);
663 TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
664 return;
666 else return;
669 if (offset >= from && offset < (from + len))
671 TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
672 SetEvent(event->hEventNotify);
677 static HRESULT IDirectSoundCaptureBufferImpl_Create(
678 DirectSoundCaptureDevice *device,
679 IDirectSoundCaptureBufferImpl ** ppobj,
680 LPCDSCBUFFERDESC lpcDSCBufferDesc)
682 LPWAVEFORMATEX wfex;
683 IDirectSoundCaptureBufferImpl *This;
684 TRACE( "(%p,%p,%p)\n", device, ppobj, lpcDSCBufferDesc);
686 if (ppobj == NULL) {
687 WARN("invalid parameter: ppobj == NULL\n");
688 return DSERR_INVALIDPARAM;
691 *ppobj = NULL;
693 if (!device) {
694 WARN("not initialized\n");
695 return DSERR_UNINITIALIZED;
698 if (lpcDSCBufferDesc == NULL) {
699 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
700 return DSERR_INVALIDPARAM;
703 if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) &&
704 (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) ||
705 (lpcDSCBufferDesc->dwBufferBytes == 0) ||
706 (lpcDSCBufferDesc->lpwfxFormat == NULL) ) { /* FIXME: DSERR_BADFORMAT ? */
707 WARN("invalid lpcDSCBufferDesc\n");
708 return DSERR_INVALIDPARAM;
711 wfex = lpcDSCBufferDesc->lpwfxFormat;
713 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
714 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
715 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
716 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
717 wfex->wBitsPerSample, wfex->cbSize);
719 device->pwfx = DSOUND_CopyFormat(wfex);
720 if ( device->pwfx == NULL )
721 return DSERR_OUTOFMEMORY;
723 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
724 sizeof(IDirectSoundCaptureBufferImpl));
726 if ( This == NULL ) {
727 WARN("out of memory\n");
728 return DSERR_OUTOFMEMORY;
729 } else {
730 HRESULT err = DS_OK;
731 LPBYTE newbuf;
732 DWORD buflen;
734 This->ref = 1;
735 This->device = device;
736 This->device->capture_buffer = This;
737 This->notify = NULL;
738 This->nrofnotifies = 0;
740 This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
741 lpcDSCBufferDesc->dwSize);
742 if (This->pdscbd)
743 CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
744 else {
745 WARN("no memory\n");
746 This->device->capture_buffer = 0;
747 HeapFree( GetProcessHeap(), 0, This );
748 return DSERR_OUTOFMEMORY;
751 This->lpVtbl = &dscbvt;
753 err = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
754 CLSCTX_INPROC_SERVER, NULL, (void**)&device->client);
755 if(FAILED(err)){
756 WARN("Activate failed: %08x\n", err);
757 HeapFree(GetProcessHeap(), 0, This->pdscbd);
758 This->device->capture_buffer = 0;
759 HeapFree( GetProcessHeap(), 0, This );
760 return err;
763 err = IAudioClient_Initialize(device->client,
764 AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST,
765 200 * 100000, 50000, device->pwfx, NULL);
766 if(FAILED(err)){
767 WARN("Initialize failed: %08x\n", err);
768 IAudioClient_Release(device->client);
769 device->client = NULL;
770 HeapFree(GetProcessHeap(), 0, This->pdscbd);
771 This->device->capture_buffer = 0;
772 HeapFree( GetProcessHeap(), 0, This );
773 return err;
776 err = IAudioClient_GetService(device->client, &IID_IAudioCaptureClient,
777 (void**)&device->capture);
778 if(FAILED(err)){
779 WARN("GetService failed: %08x\n", err);
780 IAudioClient_Release(device->client);
781 device->client = NULL;
782 HeapFree(GetProcessHeap(), 0, This->pdscbd);
783 This->device->capture_buffer = 0;
784 HeapFree( GetProcessHeap(), 0, This );
785 return err;
788 buflen = lpcDSCBufferDesc->dwBufferBytes;
789 TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
790 if (device->buffer)
791 newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
792 else
793 newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
794 if (newbuf == NULL) {
795 IAudioClient_Release(device->client);
796 device->client = NULL;
797 IAudioCaptureClient_Release(device->capture);
798 device->capture = NULL;
799 HeapFree(GetProcessHeap(), 0, This->pdscbd);
800 This->device->capture_buffer = 0;
801 HeapFree( GetProcessHeap(), 0, This );
802 return DSERR_OUTOFMEMORY;
804 device->buffer = newbuf;
805 device->buflen = buflen;
808 *ppobj = This;
810 TRACE("returning DS_OK\n");
811 return DS_OK;
815 /*******************************************************************************
816 * DirectSoundCaptureDevice
818 static HRESULT DirectSoundCaptureDevice_Create(
819 DirectSoundCaptureDevice ** ppDevice)
821 DirectSoundCaptureDevice * device;
822 TRACE("(%p)\n", ppDevice);
824 /* Allocate memory */
825 device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectSoundCaptureDevice));
827 if (device == NULL) {
828 WARN("out of memory\n");
829 return DSERR_OUTOFMEMORY;
832 device->ref = 1;
833 device->state = STATE_STOPPED;
835 InitializeCriticalSection( &(device->lock) );
836 device->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundCaptureDevice.lock");
838 *ppDevice = device;
840 return DS_OK;
843 static ULONG DirectSoundCaptureDevice_Release(
844 DirectSoundCaptureDevice * device)
846 ULONG ref = InterlockedDecrement(&(device->ref));
847 TRACE("(%p) ref was %d\n", device, ref + 1);
849 if (!ref) {
850 TRACE("deleting object\n");
852 timeKillEvent(device->timerID);
853 timeEndPeriod(DS_TIME_RES);
855 EnterCriticalSection(&DSOUND_capturers_lock);
856 list_remove(&device->entry);
857 LeaveCriticalSection(&DSOUND_capturers_lock);
859 if (device->capture_buffer)
860 IDirectSoundCaptureBufferImpl_Release(
861 (LPDIRECTSOUNDCAPTUREBUFFER8) device->capture_buffer);
863 if(device->mmdevice)
864 IMMDevice_Release(device->mmdevice);
865 HeapFree(GetProcessHeap(), 0, device->pwfx);
866 device->lock.DebugInfo->Spare[0] = 0;
867 DeleteCriticalSection( &(device->lock) );
868 HeapFree(GetProcessHeap(), 0, device);
869 TRACE("(%p) released\n", device);
871 return ref;
874 static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user,
875 DWORD_PTR dw1, DWORD_PTR dw2)
877 DirectSoundCaptureDevice *device = (DirectSoundCaptureDevice*)user;
878 UINT32 packet_frames, packet_bytes, avail_bytes;
879 DWORD flags;
880 BYTE *buf;
881 HRESULT hr;
883 if(!device->ref)
884 return;
886 EnterCriticalSection(&device->lock);
888 if(!device->capture_buffer || device->state == STATE_STOPPED){
889 LeaveCriticalSection(&device->lock);
890 return;
893 if(device->state == STATE_STOPPING){
894 device->state = STATE_STOPPED;
895 LeaveCriticalSection(&device->lock);
896 return;
899 if(device->state == STATE_STARTING)
900 device->state = STATE_CAPTURING;
902 hr = IAudioCaptureClient_GetBuffer(device->capture, &buf, &packet_frames,
903 &flags, NULL, NULL);
904 if(FAILED(hr)){
905 LeaveCriticalSection(&device->lock);
906 WARN("GetBuffer failed: %08x\n", hr);
907 return;
910 packet_bytes = packet_frames * device->pwfx->nBlockAlign;
912 avail_bytes = device->buflen - device->write_pos_bytes;
913 if(avail_bytes > packet_bytes)
914 avail_bytes = packet_bytes;
916 memcpy(device->buffer + device->write_pos_bytes, buf, avail_bytes);
917 capture_CheckNotify(device->capture_buffer, device->write_pos_bytes, avail_bytes);
919 packet_bytes -= avail_bytes;
920 if(packet_bytes > 0){
921 if(device->capture_buffer->flags & DSCBSTART_LOOPING){
922 memcpy(device->buffer, buf + avail_bytes, packet_bytes);
923 capture_CheckNotify(device->capture_buffer, 0, packet_bytes);
924 }else{
925 device->state = STATE_STOPPED;
926 capture_CheckNotify(device->capture_buffer, 0, 0);
930 device->write_pos_bytes += avail_bytes + packet_bytes;
931 device->write_pos_bytes %= device->buflen;
933 hr = IAudioCaptureClient_ReleaseBuffer(device->capture, packet_frames);
934 if(FAILED(hr)){
935 LeaveCriticalSection(&device->lock);
936 WARN("ReleaseBuffer failed: %08x\n", hr);
937 return;
940 LeaveCriticalSection(&device->lock);
943 static struct _TestFormat {
944 DWORD flag;
945 DWORD rate;
946 DWORD depth;
947 WORD channels;
948 } formats_to_test[] = {
949 { WAVE_FORMAT_1M08, 11025, 8, 1 },
950 { WAVE_FORMAT_1M16, 11025, 16, 1 },
951 { WAVE_FORMAT_1S08, 11025, 8, 2 },
952 { WAVE_FORMAT_1S16, 11025, 16, 2 },
953 { WAVE_FORMAT_2M08, 22050, 8, 1 },
954 { WAVE_FORMAT_2M16, 22050, 16, 1 },
955 { WAVE_FORMAT_2S08, 22050, 8, 2 },
956 { WAVE_FORMAT_2S16, 22050, 16, 2 },
957 { WAVE_FORMAT_4M08, 44100, 8, 1 },
958 { WAVE_FORMAT_4M16, 44100, 16, 1 },
959 { WAVE_FORMAT_4S08, 44100, 8, 2 },
960 { WAVE_FORMAT_4S16, 44100, 16, 2 },
961 { WAVE_FORMAT_48M08, 48000, 8, 1 },
962 { WAVE_FORMAT_48M16, 48000, 16, 1 },
963 { WAVE_FORMAT_48S08, 48000, 8, 2 },
964 { WAVE_FORMAT_48S16, 48000, 16, 2 },
965 { WAVE_FORMAT_96M08, 96000, 8, 1 },
966 { WAVE_FORMAT_96M16, 96000, 16, 1 },
967 { WAVE_FORMAT_96S08, 96000, 8, 2 },
968 { WAVE_FORMAT_96S16, 96000, 16, 2 },
972 static HRESULT DirectSoundCaptureDevice_Initialize(
973 DirectSoundCaptureDevice ** ppDevice,
974 LPCGUID lpcGUID)
976 HRESULT hr;
977 GUID devGUID;
978 IMMDevice *mmdevice;
979 struct _TestFormat *fmt;
980 DirectSoundCaptureDevice *device;
981 IAudioClient *client;
983 TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID));
985 /* Default device? */
986 if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
987 lpcGUID = &DSDEVID_DefaultCapture;
989 if(IsEqualGUID(lpcGUID, &DSDEVID_DefaultPlayback) ||
990 IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoicePlayback))
991 return DSERR_NODRIVER;
993 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
994 WARN("invalid parameter: lpcGUID\n");
995 return DSERR_INVALIDPARAM;
998 hr = get_mmdevice(eCapture, &devGUID, &mmdevice);
999 if(FAILED(hr))
1000 return hr;
1002 EnterCriticalSection(&DSOUND_capturers_lock);
1004 LIST_FOR_EACH_ENTRY(device, &DSOUND_capturers, DirectSoundCaptureDevice, entry){
1005 if(IsEqualGUID(&device->guid, &devGUID)){
1006 IMMDevice_Release(mmdevice);
1007 LeaveCriticalSection(&DSOUND_capturers_lock);
1008 return DSERR_ALLOCATED;
1012 hr = DirectSoundCaptureDevice_Create(&device);
1013 if (hr != DS_OK) {
1014 WARN("DirectSoundCaptureDevice_Create failed\n");
1015 LeaveCriticalSection(&DSOUND_capturers_lock);
1016 return hr;
1019 device->guid = devGUID;
1021 device->mmdevice = mmdevice;
1023 device->drvcaps.dwFlags = 0;
1025 device->drvcaps.dwFormats = 0;
1026 device->drvcaps.dwChannels = 0;
1027 hr = IMMDevice_Activate(mmdevice, &IID_IAudioClient,
1028 CLSCTX_INPROC_SERVER, NULL, (void**)&client);
1029 if(FAILED(hr)){
1030 device->lock.DebugInfo->Spare[0] = 0;
1031 DeleteCriticalSection(&device->lock);
1032 HeapFree(GetProcessHeap(), 0, device);
1033 LeaveCriticalSection(&DSOUND_capturers_lock);
1034 return DSERR_NODRIVER;
1037 for(fmt = formats_to_test; fmt->flag; ++fmt){
1038 if(DSOUND_check_supported(client, fmt->rate, fmt->depth, fmt->channels)){
1039 device->drvcaps.dwFormats |= fmt->flag;
1040 if(fmt->channels > device->drvcaps.dwChannels)
1041 device->drvcaps.dwChannels = fmt->channels;
1044 IAudioClient_Release(client);
1046 device->timerID = DSOUND_create_timer(DSOUND_capture_timer, (DWORD_PTR)device);
1048 list_add_tail(&DSOUND_capturers, &device->entry);
1050 *ppDevice = device;
1052 LeaveCriticalSection(&DSOUND_capturers_lock);
1054 return S_OK;
1058 /*****************************************************************************
1059 * IDirectSoundCapture implementation structure
1061 struct IDirectSoundCaptureImpl
1063 IDirectSoundCapture IDirectSoundCapture_iface;
1064 LONG ref;
1065 DirectSoundCaptureDevice *device;
1068 static inline struct IDirectSoundCaptureImpl *impl_from_IDirectSoundCapture(IDirectSoundCapture *iface)
1070 return CONTAINING_RECORD(iface, struct IDirectSoundCaptureImpl, IDirectSoundCapture_iface);
1073 /***************************************************************************
1074 * IDirectSoundCaptureImpl
1076 static HRESULT WINAPI IDirectSoundCaptureImpl_QueryInterface(IDirectSoundCapture *iface,
1077 REFIID riid, void **ppobj)
1079 TRACE( "(%p,%s,%p)\n", iface, debugstr_guid(riid), ppobj );
1081 if (ppobj == NULL) {
1082 WARN("invalid parameter\n");
1083 return E_INVALIDARG;
1086 *ppobj = NULL;
1088 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectSoundCapture)) {
1089 IDirectSoundCapture_AddRef(iface);
1090 *ppobj = iface;
1091 return S_OK;
1094 WARN("unsupported riid: %s\n", debugstr_guid(riid));
1095 return E_NOINTERFACE;
1098 static ULONG WINAPI IDirectSoundCaptureImpl_AddRef(IDirectSoundCapture *iface)
1100 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1101 ULONG ref = InterlockedIncrement(&(This->ref));
1103 TRACE("(%p) ref was %d\n", This, ref - 1);
1104 return ref;
1107 static ULONG WINAPI IDirectSoundCaptureImpl_Release(IDirectSoundCapture *iface)
1109 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1110 ULONG ref = InterlockedDecrement(&(This->ref));
1112 TRACE("(%p) ref was %d\n", This, ref + 1);
1114 if (!ref) {
1115 if (This->device)
1116 DirectSoundCaptureDevice_Release(This->device);
1118 HeapFree( GetProcessHeap(), 0, This );
1119 TRACE("(%p) released\n", This);
1121 return ref;
1124 static HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer(IDirectSoundCapture *iface,
1125 LPCDSCBUFFERDESC lpcDSCBufferDesc, IDirectSoundCaptureBuffer **lplpDSCaptureBuffer,
1126 IUnknown *pUnk)
1128 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1129 HRESULT hr;
1131 TRACE( "(%p,%p,%p,%p)\n",iface,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
1133 if (lpcDSCBufferDesc == NULL) {
1134 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
1135 return DSERR_INVALIDPARAM;
1138 if (lplpDSCaptureBuffer == NULL) {
1139 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
1140 return DSERR_INVALIDPARAM;
1143 if (pUnk != NULL) {
1144 WARN("invalid parameter: pUnk != NULL\n");
1145 return DSERR_INVALIDPARAM;
1148 /* FIXME: We can only have one buffer so what do we do here? */
1149 if (This->device->capture_buffer) {
1150 WARN("invalid parameter: already has buffer\n");
1151 return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */
1154 hr = IDirectSoundCaptureBufferImpl_Create(This->device,
1155 (IDirectSoundCaptureBufferImpl **)lplpDSCaptureBuffer, lpcDSCBufferDesc);
1157 if (hr != DS_OK)
1158 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
1160 return hr;
1163 static HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps(IDirectSoundCapture *iface,
1164 LPDSCCAPS lpDSCCaps)
1166 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1168 TRACE("(%p,%p)\n",This,lpDSCCaps);
1170 if (This->device == NULL) {
1171 WARN("not initialized\n");
1172 return DSERR_UNINITIALIZED;
1175 if (lpDSCCaps== NULL) {
1176 WARN("invalid parameter: lpDSCCaps== NULL\n");
1177 return DSERR_INVALIDPARAM;
1180 if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
1181 WARN("invalid parameter: lpDSCCaps->dwSize = %d\n", lpDSCCaps->dwSize);
1182 return DSERR_INVALIDPARAM;
1185 lpDSCCaps->dwFlags = This->device->drvcaps.dwFlags;
1186 lpDSCCaps->dwFormats = This->device->drvcaps.dwFormats;
1187 lpDSCCaps->dwChannels = This->device->drvcaps.dwChannels;
1189 TRACE("(flags=0x%08x,format=0x%08x,channels=%d)\n",lpDSCCaps->dwFlags,
1190 lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
1192 return DS_OK;
1195 static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(IDirectSoundCapture *iface,
1196 LPCGUID lpcGUID)
1198 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1200 TRACE("(%p,%s)\n", This, debugstr_guid(lpcGUID));
1202 if (This->device != NULL) {
1203 WARN("already initialized\n");
1204 return DSERR_ALREADYINITIALIZED;
1206 return DirectSoundCaptureDevice_Initialize(&This->device, lpcGUID);
1209 static const IDirectSoundCaptureVtbl dscvt =
1211 /* IUnknown methods */
1212 IDirectSoundCaptureImpl_QueryInterface,
1213 IDirectSoundCaptureImpl_AddRef,
1214 IDirectSoundCaptureImpl_Release,
1216 /* IDirectSoundCapture methods */
1217 IDirectSoundCaptureImpl_CreateCaptureBuffer,
1218 IDirectSoundCaptureImpl_GetCaps,
1219 IDirectSoundCaptureImpl_Initialize
1222 static HRESULT IDirectSoundCaptureImpl_Create(
1223 LPDIRECTSOUNDCAPTURE8 * ppDSC)
1225 IDirectSoundCaptureImpl *pDSC;
1226 TRACE("(%p)\n", ppDSC);
1228 /* Allocate memory */
1229 pDSC = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundCaptureImpl));
1230 if (pDSC == NULL) {
1231 WARN("out of memory\n");
1232 *ppDSC = NULL;
1233 return DSERR_OUTOFMEMORY;
1236 pDSC->IDirectSoundCapture_iface.lpVtbl = &dscvt;
1237 pDSC->ref = 0;
1238 pDSC->device = NULL;
1240 *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC;
1242 return DS_OK;
1245 HRESULT DSOUND_CaptureCreate(REFIID riid, IDirectSoundCapture **ppDSC)
1247 IDirectSoundCapture *pDSC;
1248 HRESULT hr;
1249 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC);
1251 if (!IsEqualIID(riid, &IID_IUnknown) &&
1252 !IsEqualIID(riid, &IID_IDirectSoundCapture)) {
1253 *ppDSC = 0;
1254 return E_NOINTERFACE;
1257 /* Get dsound configuration */
1258 setup_dsound_options();
1260 hr = IDirectSoundCaptureImpl_Create(&pDSC);
1261 if (hr == DS_OK) {
1262 IDirectSoundCapture_AddRef(pDSC);
1263 *ppDSC = pDSC;
1264 } else {
1265 WARN("IDirectSoundCaptureImpl_Create failed\n");
1266 *ppDSC = 0;
1269 return hr;
1272 HRESULT DSOUND_CaptureCreate8(
1273 REFIID riid,
1274 LPDIRECTSOUNDCAPTURE8 *ppDSC8)
1276 LPDIRECTSOUNDCAPTURE8 pDSC8;
1277 HRESULT hr;
1278 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC8);
1280 if (!IsEqualIID(riid, &IID_IUnknown) &&
1281 !IsEqualIID(riid, &IID_IDirectSoundCapture8)) {
1282 *ppDSC8 = 0;
1283 return E_NOINTERFACE;
1286 /* Get dsound configuration */
1287 setup_dsound_options();
1289 hr = IDirectSoundCaptureImpl_Create(&pDSC8);
1290 if (hr == DS_OK) {
1291 IDirectSoundCapture_AddRef(pDSC8);
1292 *ppDSC8 = pDSC8;
1293 } else {
1294 WARN("IDirectSoundCaptureImpl_Create failed\n");
1295 *ppDSC8 = 0;
1298 return hr;
1301 /***************************************************************************
1302 * DirectSoundCaptureCreate [DSOUND.6]
1304 * Create and initialize a DirectSoundCapture interface.
1306 * PARAMS
1307 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
1308 * lplpDSC [O] Address of a variable to receive the interface pointer.
1309 * pUnkOuter [I] Must be NULL.
1311 * RETURNS
1312 * Success: DS_OK
1313 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1314 * DSERR_OUTOFMEMORY
1316 * NOTES
1317 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
1318 * or NULL for the default device or DSDEVID_DefaultCapture or
1319 * DSDEVID_DefaultVoiceCapture.
1321 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
1323 HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID lpcGUID, IDirectSoundCapture **ppDSC,
1324 IUnknown *pUnkOuter)
1326 HRESULT hr;
1327 IDirectSoundCapture *pDSC;
1329 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC, pUnkOuter);
1331 if (ppDSC == NULL) {
1332 WARN("invalid parameter: ppDSC == NULL\n");
1333 return DSERR_INVALIDPARAM;
1336 if (pUnkOuter) {
1337 WARN("invalid parameter: pUnkOuter != NULL\n");
1338 *ppDSC = NULL;
1339 return DSERR_NOAGGREGATION;
1342 hr = DSOUND_CaptureCreate(&IID_IDirectSoundCapture, &pDSC);
1343 if (hr == DS_OK) {
1344 hr = IDirectSoundCapture_Initialize(pDSC, lpcGUID);
1345 if (hr != DS_OK) {
1346 IDirectSoundCapture_Release(pDSC);
1347 pDSC = 0;
1351 *ppDSC = pDSC;
1353 return hr;
1356 /***************************************************************************
1357 * DirectSoundCaptureCreate8 [DSOUND.12]
1359 * Create and initialize a DirectSoundCapture interface.
1361 * PARAMS
1362 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
1363 * lplpDSC [O] Address of a variable to receive the interface pointer.
1364 * pUnkOuter [I] Must be NULL.
1366 * RETURNS
1367 * Success: DS_OK
1368 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1369 * DSERR_OUTOFMEMORY
1371 * NOTES
1372 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
1373 * or NULL for the default device or DSDEVID_DefaultCapture or
1374 * DSDEVID_DefaultVoiceCapture.
1376 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
1378 HRESULT WINAPI DirectSoundCaptureCreate8(
1379 LPCGUID lpcGUID,
1380 LPDIRECTSOUNDCAPTURE8 *ppDSC8,
1381 LPUNKNOWN pUnkOuter)
1383 HRESULT hr;
1384 LPDIRECTSOUNDCAPTURE8 pDSC8;
1385 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC8, pUnkOuter);
1387 if (ppDSC8 == NULL) {
1388 WARN("invalid parameter: ppDSC8 == NULL\n");
1389 return DSERR_INVALIDPARAM;
1392 if (pUnkOuter) {
1393 WARN("invalid parameter: pUnkOuter != NULL\n");
1394 *ppDSC8 = NULL;
1395 return DSERR_NOAGGREGATION;
1398 hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &pDSC8);
1399 if (hr == DS_OK) {
1400 hr = IDirectSoundCapture_Initialize(pDSC8, lpcGUID);
1401 if (hr != DS_OK) {
1402 IDirectSoundCapture_Release(pDSC8);
1403 pDSC8 = 0;
1407 *ppDSC8 = pDSC8;
1409 return hr;