d3dx9_36: Add DIB file support to D3DXSaveSurfaceToFileInMemory.
[wine/wine-gecko.git] / dlls / dsound / capture.c
blob1b004e6ada3efd2a2e98ad923a09ca42f8d70298
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);
46 typedef struct DirectSoundCaptureDevice DirectSoundCaptureDevice;
48 /* IDirectSoundCaptureBuffer implementation structure */
49 typedef struct IDirectSoundCaptureBufferImpl
51 IDirectSoundCaptureBuffer8 IDirectSoundCaptureBuffer8_iface;
52 IDirectSoundNotify IDirectSoundNotify_iface;
53 LONG numIfaces; /* "in use interfaces" refcount */
54 LONG ref, refn;
55 /* IDirectSoundCaptureBuffer fields */
56 DirectSoundCaptureDevice *device;
57 DSCBUFFERDESC *pdscbd;
58 DWORD flags;
59 /* IDirectSoundNotify fields */
60 DSBPOSITIONNOTIFY *notifies;
61 int nrofnotifies;
62 } IDirectSoundCaptureBufferImpl;
64 /* DirectSoundCaptureDevice implementation structure */
65 struct DirectSoundCaptureDevice
67 GUID guid;
68 LONG ref;
69 DSCCAPS drvcaps;
70 BYTE *buffer;
71 DWORD buflen, write_pos_bytes;
72 WAVEFORMATEX *pwfx;
73 IDirectSoundCaptureBufferImpl *capture_buffer;
74 DWORD state;
75 UINT timerID;
76 CRITICAL_SECTION lock;
77 IMMDevice *mmdevice;
78 IAudioClient *client;
79 IAudioCaptureClient *capture;
80 struct list entry;
84 static void capturebuffer_destroy(IDirectSoundCaptureBufferImpl *This)
86 if (This->device->state == STATE_CAPTURING)
87 This->device->state = STATE_STOPPING;
89 HeapFree(GetProcessHeap(),0, This->pdscbd);
91 if (This->device->client) {
92 IAudioClient_Release(This->device->client);
93 This->device->client = NULL;
96 if (This->device->capture) {
97 IAudioCaptureClient_Release(This->device->capture);
98 This->device->capture = NULL;
101 /* remove from DirectSoundCaptureDevice */
102 This->device->capture_buffer = NULL;
104 HeapFree(GetProcessHeap(), 0, This->notifies);
105 HeapFree(GetProcessHeap(), 0, This);
106 TRACE("(%p) released\n", This);
109 /*******************************************************************************
110 * IDirectSoundNotify
112 static inline struct IDirectSoundCaptureBufferImpl *impl_from_IDirectSoundNotify(IDirectSoundNotify *iface)
114 return CONTAINING_RECORD(iface, IDirectSoundCaptureBufferImpl, IDirectSoundNotify_iface);
117 static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(IDirectSoundNotify *iface, REFIID riid,
118 void **ppobj)
120 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundNotify(iface);
122 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj);
124 return IDirectSoundCaptureBuffer_QueryInterface(&This->IDirectSoundCaptureBuffer8_iface, riid, ppobj);
127 static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(IDirectSoundNotify *iface)
129 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundNotify(iface);
130 ULONG ref = InterlockedIncrement(&This->refn);
132 TRACE("(%p) ref was %d\n", This, ref - 1);
134 if(ref == 1)
135 InterlockedIncrement(&This->numIfaces);
137 return ref;
140 static ULONG WINAPI IDirectSoundNotifyImpl_Release(IDirectSoundNotify *iface)
142 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundNotify(iface);
143 ULONG ref = InterlockedDecrement(&This->refn);
145 TRACE("(%p) ref was %d\n", This, ref + 1);
147 if (!ref && !InterlockedDecrement(&This->numIfaces))
148 capturebuffer_destroy(This);
150 return ref;
153 static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(IDirectSoundNotify *iface,
154 DWORD howmuch, const DSBPOSITIONNOTIFY *notify)
156 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundNotify(iface);
157 TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
159 if (howmuch > 0 && notify == NULL) {
160 WARN("invalid parameter: notify == NULL\n");
161 return DSERR_INVALIDPARAM;
164 if (TRACE_ON(dsound)) {
165 unsigned int i;
166 for (i=0;i<howmuch;i++)
167 TRACE("notify at %d to %p\n",
168 notify[i].dwOffset,notify[i].hEventNotify);
171 if (howmuch > 0) {
172 /* Make an internal copy of the caller-supplied array.
173 * Replace the existing copy if one is already present. */
174 if (This->notifies)
175 This->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->notifies,
176 howmuch * sizeof(DSBPOSITIONNOTIFY));
177 else
178 This->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
179 howmuch * sizeof(DSBPOSITIONNOTIFY));
181 if (!This->notifies) {
182 WARN("out of memory\n");
183 return DSERR_OUTOFMEMORY;
185 CopyMemory(This->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
186 This->nrofnotifies = howmuch;
187 } else {
188 HeapFree(GetProcessHeap(), 0, This->notifies);
189 This->notifies = NULL;
190 This->nrofnotifies = 0;
193 return S_OK;
196 static const IDirectSoundNotifyVtbl dscnvt =
198 IDirectSoundNotifyImpl_QueryInterface,
199 IDirectSoundNotifyImpl_AddRef,
200 IDirectSoundNotifyImpl_Release,
201 IDirectSoundNotifyImpl_SetNotificationPositions
205 static const char * const captureStateString[] = {
206 "STATE_STOPPED",
207 "STATE_STARTING",
208 "STATE_CAPTURING",
209 "STATE_STOPPING"
213 /*******************************************************************************
214 * IDirectSoundCaptureBuffer
216 static inline IDirectSoundCaptureBufferImpl *impl_from_IDirectSoundCaptureBuffer8(IDirectSoundCaptureBuffer8 *iface)
218 return CONTAINING_RECORD(iface, IDirectSoundCaptureBufferImpl, IDirectSoundCaptureBuffer8_iface);
221 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_QueryInterface(IDirectSoundCaptureBuffer8 *iface,
222 REFIID riid, void **ppobj)
224 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
226 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
228 if (ppobj == NULL) {
229 WARN("invalid parameter\n");
230 return E_INVALIDARG;
233 *ppobj = NULL;
235 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
236 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
237 IDirectSoundCaptureBuffer8_AddRef(iface);
238 *ppobj = iface;
239 return S_OK;
242 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
243 IDirectSoundNotify_AddRef(&This->IDirectSoundNotify_iface);
244 *ppobj = &This->IDirectSoundNotify_iface;
245 return S_OK;
248 FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
249 return E_NOINTERFACE;
252 static ULONG WINAPI IDirectSoundCaptureBufferImpl_AddRef(IDirectSoundCaptureBuffer8 *iface)
254 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
255 ULONG ref = InterlockedIncrement(&This->ref);
257 TRACE("(%p) ref was %d\n", This, ref - 1);
259 if(ref == 1)
260 InterlockedIncrement(&This->numIfaces);
262 return ref;
265 static ULONG WINAPI IDirectSoundCaptureBufferImpl_Release(IDirectSoundCaptureBuffer8 *iface)
267 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
268 ULONG ref = InterlockedDecrement(&This->ref);
270 TRACE("(%p) ref was %d\n", This, ref + 1);
272 if (!ref && !InterlockedDecrement(&This->numIfaces))
273 capturebuffer_destroy(This);
275 return ref;
278 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetCaps(IDirectSoundCaptureBuffer8 *iface,
279 DSCBCAPS *lpDSCBCaps)
281 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(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 IDirectSoundCaptureBufferImpl_GetCurrentPosition(IDirectSoundCaptureBuffer8 *iface,
309 DWORD *lpdwCapturePosition, DWORD *lpdwReadPosition)
311 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
313 TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
315 if (This->device == NULL) {
316 WARN("invalid parameter: This->device == NULL\n");
317 return DSERR_INVALIDPARAM;
320 EnterCriticalSection(&This->device->lock);
322 if (!This->device->client) {
323 LeaveCriticalSection(&This->device->lock);
324 WARN("no driver\n");
325 return DSERR_NODRIVER;
328 if(lpdwCapturePosition)
329 *lpdwCapturePosition = This->device->write_pos_bytes;
331 if(lpdwReadPosition)
332 *lpdwReadPosition = This->device->write_pos_bytes;
334 LeaveCriticalSection(&This->device->lock);
336 TRACE("cappos=%d readpos=%d\n", (lpdwCapturePosition?*lpdwCapturePosition:-1), (lpdwReadPosition?*lpdwReadPosition:-1));
337 TRACE("returning DS_OK\n");
339 return DS_OK;
342 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetFormat(IDirectSoundCaptureBuffer8 *iface,
343 WAVEFORMATEX *lpwfxFormat, DWORD dwSizeAllocated, DWORD *lpdwSizeWritten)
345 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
346 HRESULT hres = DS_OK;
348 TRACE("(%p,%p,0x%08x,%p)\n", This, lpwfxFormat, dwSizeAllocated, lpdwSizeWritten);
350 if (This->device == NULL) {
351 WARN("invalid parameter: This->device == NULL\n");
352 return DSERR_INVALIDPARAM;
355 if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize))
356 dwSizeAllocated = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
358 if (lpwfxFormat) { /* NULL is valid (just want size) */
359 CopyMemory(lpwfxFormat, This->device->pwfx, dwSizeAllocated);
360 if (lpdwSizeWritten)
361 *lpdwSizeWritten = dwSizeAllocated;
362 } else {
363 if (lpdwSizeWritten)
364 *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
365 else {
366 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
367 hres = DSERR_INVALIDPARAM;
371 TRACE("returning %08x\n", hres);
372 return hres;
375 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetStatus(IDirectSoundCaptureBuffer8 *iface,
376 DWORD *lpdwStatus)
378 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
380 TRACE( "(%p, %p), thread is %04x\n", This, lpdwStatus, GetCurrentThreadId() );
382 if (This->device == NULL) {
383 WARN("invalid parameter: This->device == NULL\n");
384 return DSERR_INVALIDPARAM;
387 if (lpdwStatus == NULL) {
388 WARN("invalid parameter: lpdwStatus == NULL\n");
389 return DSERR_INVALIDPARAM;
392 *lpdwStatus = 0;
393 EnterCriticalSection(&(This->device->lock));
395 TRACE("old This->device->state=%s, old lpdwStatus=%08x\n",
396 captureStateString[This->device->state],*lpdwStatus);
397 if ((This->device->state == STATE_STARTING) ||
398 (This->device->state == STATE_CAPTURING)) {
399 *lpdwStatus |= DSCBSTATUS_CAPTURING;
400 if (This->flags & DSCBSTART_LOOPING)
401 *lpdwStatus |= DSCBSTATUS_LOOPING;
403 TRACE("new This->device->state=%s, new lpdwStatus=%08x\n",
404 captureStateString[This->device->state],*lpdwStatus);
405 LeaveCriticalSection(&(This->device->lock));
407 TRACE("status=%x\n", *lpdwStatus);
408 TRACE("returning DS_OK\n");
409 return DS_OK;
412 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Initialize(IDirectSoundCaptureBuffer8 *iface,
413 IDirectSoundCapture *lpDSC, const DSCBUFFERDESC *lpcDSCBDesc)
415 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
417 FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
419 return DS_OK;
422 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Lock(IDirectSoundCaptureBuffer8 *iface,
423 DWORD dwReadCusor, DWORD dwReadBytes, void **lplpvAudioPtr1, DWORD *lpdwAudioBytes1,
424 void **lplpvAudioPtr2, DWORD *lpdwAudioBytes2, DWORD dwFlags)
426 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
427 HRESULT hres = DS_OK;
429 TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This, dwReadCusor,
430 dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
431 lpdwAudioBytes2, dwFlags, GetTickCount() );
433 if (This->device == NULL) {
434 WARN("invalid parameter: This->device == NULL\n");
435 return DSERR_INVALIDPARAM;
438 if (lplpvAudioPtr1 == NULL) {
439 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
440 return DSERR_INVALIDPARAM;
443 if (lpdwAudioBytes1 == NULL) {
444 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
445 return DSERR_INVALIDPARAM;
448 EnterCriticalSection(&(This->device->lock));
450 if (This->device->client) {
451 *lplpvAudioPtr1 = This->device->buffer + dwReadCusor;
452 if ( (dwReadCusor + dwReadBytes) > This->device->buflen) {
453 *lpdwAudioBytes1 = This->device->buflen - dwReadCusor;
454 if (lplpvAudioPtr2)
455 *lplpvAudioPtr2 = This->device->buffer;
456 if (lpdwAudioBytes2)
457 *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
458 } else {
459 *lpdwAudioBytes1 = dwReadBytes;
460 if (lplpvAudioPtr2)
461 *lplpvAudioPtr2 = 0;
462 if (lpdwAudioBytes2)
463 *lpdwAudioBytes2 = 0;
465 } else {
466 TRACE("invalid call\n");
467 hres = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */
470 LeaveCriticalSection(&(This->device->lock));
472 TRACE("returning %08x\n", hres);
473 return hres;
476 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Start(IDirectSoundCaptureBuffer8 *iface,
477 DWORD dwFlags)
479 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
480 HRESULT hres;
482 TRACE( "(%p,0x%08x)\n", This, dwFlags );
484 if (This->device == NULL) {
485 WARN("invalid parameter: This->device == NULL\n");
486 return DSERR_INVALIDPARAM;
489 if ( !This->device->client ) {
490 WARN("no driver\n");
491 return DSERR_NODRIVER;
494 EnterCriticalSection(&(This->device->lock));
496 if (This->device->state == STATE_STOPPED)
497 This->device->state = STATE_STARTING;
498 else if (This->device->state == STATE_STOPPING)
499 This->device->state = STATE_CAPTURING;
500 else
501 goto out;
502 TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
503 This->flags = dwFlags;
505 if (This->device->buffer)
506 FillMemory(This->device->buffer, This->device->buflen, (This->device->pwfx->wBitsPerSample == 8) ? 128 : 0);
508 hres = IAudioClient_Start(This->device->client);
509 if(FAILED(hres)){
510 WARN("Start failed: %08x\n", hres);
511 LeaveCriticalSection(&This->device->lock);
512 return hres;
515 out:
516 LeaveCriticalSection(&This->device->lock);
518 TRACE("returning DS_OK\n");
519 return DS_OK;
522 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Stop(IDirectSoundCaptureBuffer8 *iface)
524 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
525 HRESULT hres;
527 TRACE("(%p)\n", This);
529 if (This->device == NULL) {
530 WARN("invalid parameter: This->device == NULL\n");
531 return DSERR_INVALIDPARAM;
534 EnterCriticalSection(&(This->device->lock));
536 TRACE("old This->device->state=%s\n",captureStateString[This->device->state]);
537 if (This->device->state == STATE_CAPTURING)
538 This->device->state = STATE_STOPPING;
539 else if (This->device->state == STATE_STARTING)
540 This->device->state = STATE_STOPPED;
541 TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
543 if(This->device->client){
544 hres = IAudioClient_Stop(This->device->client);
545 if(FAILED(hres)){
546 LeaveCriticalSection(&This->device->lock);
547 return hres;
551 LeaveCriticalSection(&(This->device->lock));
553 TRACE("returning DS_OK\n");
554 return DS_OK;
557 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Unlock(IDirectSoundCaptureBuffer8 *iface,
558 void *lpvAudioPtr1, DWORD dwAudioBytes1, void *lpvAudioPtr2, DWORD dwAudioBytes2)
560 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
561 HRESULT hres = DS_OK;
563 TRACE( "(%p,%p,%08u,%p,%08u)\n", This, lpvAudioPtr1, dwAudioBytes1,
564 lpvAudioPtr2, dwAudioBytes2 );
566 if (lpvAudioPtr1 == NULL) {
567 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
568 return DSERR_INVALIDPARAM;
571 if (!This->device->client) {
572 WARN("invalid call\n");
573 hres = DSERR_INVALIDCALL;
576 TRACE("returning %08x\n", hres);
577 return hres;
580 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetObjectInPath(IDirectSoundCaptureBuffer8 *iface,
581 REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, void **ppObject)
583 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
585 FIXME( "(%p,%s,%u,%s,%p): stub\n", This, debugstr_guid(rguidObject),
586 dwIndex, debugstr_guid(rguidInterface), ppObject );
588 if (!ppObject)
589 return DSERR_INVALIDPARAM;
591 *ppObject = NULL;
592 return DSERR_CONTROLUNAVAIL;
595 static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetFXStatus(IDirectSoundCaptureBuffer8 *iface,
596 DWORD dwFXCount, DWORD *pdwFXStatus)
598 IDirectSoundCaptureBufferImpl *This = impl_from_IDirectSoundCaptureBuffer8(iface);
600 FIXME( "(%p,%u,%p): stub\n", This, dwFXCount, pdwFXStatus );
602 return DS_OK;
605 static const IDirectSoundCaptureBuffer8Vtbl dscbvt =
607 /* IUnknown methods */
608 IDirectSoundCaptureBufferImpl_QueryInterface,
609 IDirectSoundCaptureBufferImpl_AddRef,
610 IDirectSoundCaptureBufferImpl_Release,
612 /* IDirectSoundCaptureBuffer methods */
613 IDirectSoundCaptureBufferImpl_GetCaps,
614 IDirectSoundCaptureBufferImpl_GetCurrentPosition,
615 IDirectSoundCaptureBufferImpl_GetFormat,
616 IDirectSoundCaptureBufferImpl_GetStatus,
617 IDirectSoundCaptureBufferImpl_Initialize,
618 IDirectSoundCaptureBufferImpl_Lock,
619 IDirectSoundCaptureBufferImpl_Start,
620 IDirectSoundCaptureBufferImpl_Stop,
621 IDirectSoundCaptureBufferImpl_Unlock,
623 /* IDirectSoundCaptureBuffer methods */
624 IDirectSoundCaptureBufferImpl_GetObjectInPath,
625 IDirectSoundCaptureBufferImpl_GetFXStatus
628 static void capture_CheckNotify(IDirectSoundCaptureBufferImpl *This, DWORD from, DWORD len)
630 int i;
631 for (i = 0; i < This->nrofnotifies; ++i) {
632 LPDSBPOSITIONNOTIFY event = This->notifies + i;
633 DWORD offset = event->dwOffset;
634 TRACE("checking %d, position %d, event = %p\n", i, offset, event->hEventNotify);
636 if (offset == DSBPN_OFFSETSTOP) {
637 if (!from && !len) {
638 SetEvent(event->hEventNotify);
639 TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
640 return;
642 else return;
645 if (offset >= from && offset < (from + len))
647 TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
648 SetEvent(event->hEventNotify);
653 static HRESULT IDirectSoundCaptureBufferImpl_Create(
654 DirectSoundCaptureDevice *device,
655 IDirectSoundCaptureBufferImpl ** ppobj,
656 LPCDSCBUFFERDESC lpcDSCBufferDesc)
658 LPWAVEFORMATEX wfex;
659 IDirectSoundCaptureBufferImpl *This;
660 TRACE( "(%p,%p,%p)\n", device, ppobj, lpcDSCBufferDesc);
662 if (ppobj == NULL) {
663 WARN("invalid parameter: ppobj == NULL\n");
664 return DSERR_INVALIDPARAM;
667 *ppobj = NULL;
669 if (!device) {
670 WARN("not initialized\n");
671 return DSERR_UNINITIALIZED;
674 if (lpcDSCBufferDesc == NULL) {
675 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
676 return DSERR_INVALIDPARAM;
679 if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) &&
680 (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) ||
681 (lpcDSCBufferDesc->dwBufferBytes == 0) ||
682 (lpcDSCBufferDesc->lpwfxFormat == NULL) ) { /* FIXME: DSERR_BADFORMAT ? */
683 WARN("invalid lpcDSCBufferDesc\n");
684 return DSERR_INVALIDPARAM;
687 wfex = lpcDSCBufferDesc->lpwfxFormat;
689 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
690 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
691 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
692 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
693 wfex->wBitsPerSample, wfex->cbSize);
695 device->pwfx = DSOUND_CopyFormat(wfex);
696 if ( device->pwfx == NULL )
697 return DSERR_OUTOFMEMORY;
699 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
700 sizeof(IDirectSoundCaptureBufferImpl));
702 if ( This == NULL ) {
703 WARN("out of memory\n");
704 return DSERR_OUTOFMEMORY;
705 } else {
706 HRESULT err = DS_OK;
707 LPBYTE newbuf;
708 DWORD buflen;
710 This->numIfaces = 0;
711 This->ref = 0;
712 This->refn = 0;
713 This->device = device;
714 This->device->capture_buffer = This;
715 This->nrofnotifies = 0;
717 This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
718 lpcDSCBufferDesc->dwSize);
719 if (This->pdscbd)
720 CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
721 else {
722 WARN("no memory\n");
723 This->device->capture_buffer = 0;
724 HeapFree( GetProcessHeap(), 0, This );
725 return DSERR_OUTOFMEMORY;
728 This->IDirectSoundCaptureBuffer8_iface.lpVtbl = &dscbvt;
729 This->IDirectSoundNotify_iface.lpVtbl = &dscnvt;
731 err = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
732 CLSCTX_INPROC_SERVER, NULL, (void**)&device->client);
733 if(FAILED(err)){
734 WARN("Activate failed: %08x\n", err);
735 HeapFree(GetProcessHeap(), 0, This->pdscbd);
736 This->device->capture_buffer = 0;
737 HeapFree( GetProcessHeap(), 0, This );
738 return err;
741 err = IAudioClient_Initialize(device->client,
742 AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST,
743 200 * 100000, 50000, device->pwfx, NULL);
744 if(FAILED(err)){
745 WARN("Initialize failed: %08x\n", err);
746 IAudioClient_Release(device->client);
747 device->client = NULL;
748 HeapFree(GetProcessHeap(), 0, This->pdscbd);
749 This->device->capture_buffer = 0;
750 HeapFree( GetProcessHeap(), 0, This );
751 if(err == AUDCLNT_E_UNSUPPORTED_FORMAT)
752 return DSERR_BADFORMAT;
753 return err;
756 err = IAudioClient_GetService(device->client, &IID_IAudioCaptureClient,
757 (void**)&device->capture);
758 if(FAILED(err)){
759 WARN("GetService failed: %08x\n", err);
760 IAudioClient_Release(device->client);
761 device->client = NULL;
762 HeapFree(GetProcessHeap(), 0, This->pdscbd);
763 This->device->capture_buffer = 0;
764 HeapFree( GetProcessHeap(), 0, This );
765 return err;
768 buflen = lpcDSCBufferDesc->dwBufferBytes;
769 TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
770 if (device->buffer)
771 newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
772 else
773 newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
774 if (newbuf == NULL) {
775 IAudioClient_Release(device->client);
776 device->client = NULL;
777 IAudioCaptureClient_Release(device->capture);
778 device->capture = NULL;
779 HeapFree(GetProcessHeap(), 0, This->pdscbd);
780 This->device->capture_buffer = 0;
781 HeapFree( GetProcessHeap(), 0, This );
782 return DSERR_OUTOFMEMORY;
784 device->buffer = newbuf;
785 device->buflen = buflen;
788 IDirectSoundCaptureBuffer_AddRef(&This->IDirectSoundCaptureBuffer8_iface);
789 *ppobj = This;
791 TRACE("returning DS_OK\n");
792 return DS_OK;
796 /*******************************************************************************
797 * DirectSoundCaptureDevice
799 static HRESULT DirectSoundCaptureDevice_Create(
800 DirectSoundCaptureDevice ** ppDevice)
802 DirectSoundCaptureDevice * device;
803 TRACE("(%p)\n", ppDevice);
805 /* Allocate memory */
806 device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectSoundCaptureDevice));
808 if (device == NULL) {
809 WARN("out of memory\n");
810 return DSERR_OUTOFMEMORY;
813 device->ref = 1;
814 device->state = STATE_STOPPED;
816 InitializeCriticalSection( &(device->lock) );
817 device->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundCaptureDevice.lock");
819 *ppDevice = device;
821 return DS_OK;
824 static ULONG DirectSoundCaptureDevice_Release(
825 DirectSoundCaptureDevice * device)
827 ULONG ref = InterlockedDecrement(&(device->ref));
828 TRACE("(%p) ref was %d\n", device, ref + 1);
830 if (!ref) {
831 TRACE("deleting object\n");
833 timeKillEvent(device->timerID);
834 timeEndPeriod(DS_TIME_RES);
836 EnterCriticalSection(&DSOUND_capturers_lock);
837 list_remove(&device->entry);
838 LeaveCriticalSection(&DSOUND_capturers_lock);
840 if (device->capture_buffer)
841 IDirectSoundCaptureBufferImpl_Release(&device->capture_buffer->IDirectSoundCaptureBuffer8_iface);
843 if(device->mmdevice)
844 IMMDevice_Release(device->mmdevice);
845 HeapFree(GetProcessHeap(), 0, device->pwfx);
846 device->lock.DebugInfo->Spare[0] = 0;
847 DeleteCriticalSection( &(device->lock) );
848 HeapFree(GetProcessHeap(), 0, device);
849 TRACE("(%p) released\n", device);
851 return ref;
854 static void CALLBACK DSOUND_capture_timer(UINT timerID, UINT msg, DWORD_PTR user,
855 DWORD_PTR dw1, DWORD_PTR dw2)
857 DirectSoundCaptureDevice *device = (DirectSoundCaptureDevice*)user;
858 UINT32 packet_frames, packet_bytes, avail_bytes;
859 DWORD flags;
860 BYTE *buf;
861 HRESULT hr;
863 if(!device->ref)
864 return;
866 EnterCriticalSection(&device->lock);
868 if(!device->capture_buffer || device->state == STATE_STOPPED){
869 LeaveCriticalSection(&device->lock);
870 return;
873 if(device->state == STATE_STOPPING){
874 device->state = STATE_STOPPED;
875 LeaveCriticalSection(&device->lock);
876 return;
879 if(device->state == STATE_STARTING)
880 device->state = STATE_CAPTURING;
882 hr = IAudioCaptureClient_GetBuffer(device->capture, &buf, &packet_frames,
883 &flags, NULL, NULL);
884 if(FAILED(hr)){
885 LeaveCriticalSection(&device->lock);
886 WARN("GetBuffer failed: %08x\n", hr);
887 return;
890 packet_bytes = packet_frames * device->pwfx->nBlockAlign;
892 avail_bytes = device->buflen - device->write_pos_bytes;
893 if(avail_bytes > packet_bytes)
894 avail_bytes = packet_bytes;
896 memcpy(device->buffer + device->write_pos_bytes, buf, avail_bytes);
897 capture_CheckNotify(device->capture_buffer, device->write_pos_bytes, avail_bytes);
899 packet_bytes -= avail_bytes;
900 if(packet_bytes > 0){
901 if(device->capture_buffer->flags & DSCBSTART_LOOPING){
902 memcpy(device->buffer, buf + avail_bytes, packet_bytes);
903 capture_CheckNotify(device->capture_buffer, 0, packet_bytes);
904 }else{
905 device->state = STATE_STOPPED;
906 capture_CheckNotify(device->capture_buffer, 0, 0);
910 device->write_pos_bytes += avail_bytes + packet_bytes;
911 device->write_pos_bytes %= device->buflen;
913 hr = IAudioCaptureClient_ReleaseBuffer(device->capture, packet_frames);
914 if(FAILED(hr)){
915 LeaveCriticalSection(&device->lock);
916 WARN("ReleaseBuffer failed: %08x\n", hr);
917 return;
920 LeaveCriticalSection(&device->lock);
923 static struct _TestFormat {
924 DWORD flag;
925 DWORD rate;
926 DWORD depth;
927 WORD channels;
928 } formats_to_test[] = {
929 { WAVE_FORMAT_1M08, 11025, 8, 1 },
930 { WAVE_FORMAT_1M16, 11025, 16, 1 },
931 { WAVE_FORMAT_1S08, 11025, 8, 2 },
932 { WAVE_FORMAT_1S16, 11025, 16, 2 },
933 { WAVE_FORMAT_2M08, 22050, 8, 1 },
934 { WAVE_FORMAT_2M16, 22050, 16, 1 },
935 { WAVE_FORMAT_2S08, 22050, 8, 2 },
936 { WAVE_FORMAT_2S16, 22050, 16, 2 },
937 { WAVE_FORMAT_4M08, 44100, 8, 1 },
938 { WAVE_FORMAT_4M16, 44100, 16, 1 },
939 { WAVE_FORMAT_4S08, 44100, 8, 2 },
940 { WAVE_FORMAT_4S16, 44100, 16, 2 },
941 { WAVE_FORMAT_48M08, 48000, 8, 1 },
942 { WAVE_FORMAT_48M16, 48000, 16, 1 },
943 { WAVE_FORMAT_48S08, 48000, 8, 2 },
944 { WAVE_FORMAT_48S16, 48000, 16, 2 },
945 { WAVE_FORMAT_96M08, 96000, 8, 1 },
946 { WAVE_FORMAT_96M16, 96000, 16, 1 },
947 { WAVE_FORMAT_96S08, 96000, 8, 2 },
948 { WAVE_FORMAT_96S16, 96000, 16, 2 },
952 static HRESULT DirectSoundCaptureDevice_Initialize(
953 DirectSoundCaptureDevice ** ppDevice,
954 LPCGUID lpcGUID)
956 HRESULT hr;
957 GUID devGUID;
958 IMMDevice *mmdevice;
959 struct _TestFormat *fmt;
960 DirectSoundCaptureDevice *device;
961 IAudioClient *client;
963 TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID));
965 /* Default device? */
966 if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
967 lpcGUID = &DSDEVID_DefaultCapture;
969 if(IsEqualGUID(lpcGUID, &DSDEVID_DefaultPlayback) ||
970 IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoicePlayback))
971 return DSERR_NODRIVER;
973 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
974 WARN("invalid parameter: lpcGUID\n");
975 return DSERR_INVALIDPARAM;
978 hr = get_mmdevice(eCapture, &devGUID, &mmdevice);
979 if(FAILED(hr))
980 return hr;
982 EnterCriticalSection(&DSOUND_capturers_lock);
984 LIST_FOR_EACH_ENTRY(device, &DSOUND_capturers, DirectSoundCaptureDevice, entry){
985 if(IsEqualGUID(&device->guid, &devGUID)){
986 IMMDevice_Release(mmdevice);
987 LeaveCriticalSection(&DSOUND_capturers_lock);
988 return DSERR_ALLOCATED;
992 hr = DirectSoundCaptureDevice_Create(&device);
993 if (hr != DS_OK) {
994 WARN("DirectSoundCaptureDevice_Create failed\n");
995 LeaveCriticalSection(&DSOUND_capturers_lock);
996 return hr;
999 device->guid = devGUID;
1001 device->mmdevice = mmdevice;
1003 device->drvcaps.dwFlags = 0;
1005 device->drvcaps.dwFormats = 0;
1006 device->drvcaps.dwChannels = 0;
1007 hr = IMMDevice_Activate(mmdevice, &IID_IAudioClient,
1008 CLSCTX_INPROC_SERVER, NULL, (void**)&client);
1009 if(FAILED(hr)){
1010 device->lock.DebugInfo->Spare[0] = 0;
1011 DeleteCriticalSection(&device->lock);
1012 HeapFree(GetProcessHeap(), 0, device);
1013 LeaveCriticalSection(&DSOUND_capturers_lock);
1014 return DSERR_NODRIVER;
1017 for(fmt = formats_to_test; fmt->flag; ++fmt){
1018 if(DSOUND_check_supported(client, fmt->rate, fmt->depth, fmt->channels)){
1019 device->drvcaps.dwFormats |= fmt->flag;
1020 if(fmt->channels > device->drvcaps.dwChannels)
1021 device->drvcaps.dwChannels = fmt->channels;
1024 IAudioClient_Release(client);
1026 device->timerID = DSOUND_create_timer(DSOUND_capture_timer, (DWORD_PTR)device);
1028 list_add_tail(&DSOUND_capturers, &device->entry);
1030 *ppDevice = device;
1032 LeaveCriticalSection(&DSOUND_capturers_lock);
1034 return S_OK;
1038 /*****************************************************************************
1039 * IDirectSoundCapture implementation structure
1041 typedef struct IDirectSoundCaptureImpl
1043 IUnknown IUnknown_inner;
1044 IDirectSoundCapture IDirectSoundCapture_iface;
1045 LONG ref, refdsc, numIfaces;
1046 IUnknown *outer_unk; /* internal */
1047 DirectSoundCaptureDevice *device;
1048 BOOL has_dsc8;
1049 } IDirectSoundCaptureImpl;
1051 static void capture_destroy(IDirectSoundCaptureImpl *This)
1053 if (This->device)
1054 DirectSoundCaptureDevice_Release(This->device);
1055 HeapFree(GetProcessHeap(),0,This);
1056 TRACE("(%p) released\n", This);
1059 /*******************************************************************************
1060 * IUnknown Implementation for DirectSoundCapture
1062 static inline IDirectSoundCaptureImpl *impl_from_IUnknown(IUnknown *iface)
1064 return CONTAINING_RECORD(iface, IDirectSoundCaptureImpl, IUnknown_inner);
1067 static HRESULT WINAPI IUnknownImpl_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1069 IDirectSoundCaptureImpl *This = impl_from_IUnknown(iface);
1071 TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppv);
1073 if (!ppv) {
1074 WARN("invalid parameter\n");
1075 return E_INVALIDARG;
1077 *ppv = NULL;
1079 if (IsEqualIID(riid, &IID_IUnknown))
1080 *ppv = &This->IUnknown_inner;
1081 else if (IsEqualIID(riid, &IID_IDirectSoundCapture))
1082 *ppv = &This->IDirectSoundCapture_iface;
1083 else {
1084 WARN("unknown IID %s\n", debugstr_guid(riid));
1085 return E_NOINTERFACE;
1088 IUnknown_AddRef((IUnknown*)*ppv);
1089 return S_OK;
1092 static ULONG WINAPI IUnknownImpl_AddRef(IUnknown *iface)
1094 IDirectSoundCaptureImpl *This = impl_from_IUnknown(iface);
1095 ULONG ref = InterlockedIncrement(&This->ref);
1097 TRACE("(%p) ref=%d\n", This, ref);
1099 if(ref == 1)
1100 InterlockedIncrement(&This->numIfaces);
1101 return ref;
1104 static ULONG WINAPI IUnknownImpl_Release(IUnknown *iface)
1106 IDirectSoundCaptureImpl *This = impl_from_IUnknown(iface);
1107 ULONG ref = InterlockedDecrement(&This->ref);
1109 TRACE("(%p) ref=%d\n", This, ref);
1111 if (!ref && !InterlockedDecrement(&This->numIfaces))
1112 capture_destroy(This);
1113 return ref;
1116 static const IUnknownVtbl unk_vtbl =
1118 IUnknownImpl_QueryInterface,
1119 IUnknownImpl_AddRef,
1120 IUnknownImpl_Release
1123 /***************************************************************************
1124 * IDirectSoundCaptureImpl
1126 static inline struct IDirectSoundCaptureImpl *impl_from_IDirectSoundCapture(IDirectSoundCapture *iface)
1128 return CONTAINING_RECORD(iface, struct IDirectSoundCaptureImpl, IDirectSoundCapture_iface);
1131 static HRESULT WINAPI IDirectSoundCaptureImpl_QueryInterface(IDirectSoundCapture *iface,
1132 REFIID riid, void **ppv)
1134 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1135 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
1136 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
1139 static ULONG WINAPI IDirectSoundCaptureImpl_AddRef(IDirectSoundCapture *iface)
1141 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1142 ULONG ref = InterlockedIncrement(&This->refdsc);
1144 TRACE("(%p) ref=%d\n", This, ref);
1146 if(ref == 1)
1147 InterlockedIncrement(&This->numIfaces);
1148 return ref;
1151 static ULONG WINAPI IDirectSoundCaptureImpl_Release(IDirectSoundCapture *iface)
1153 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1154 ULONG ref = InterlockedDecrement(&This->refdsc);
1156 TRACE("(%p) ref=%d\n", This, ref);
1158 if (!ref && !InterlockedDecrement(&This->numIfaces))
1159 capture_destroy(This);
1160 return ref;
1163 static HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer(IDirectSoundCapture *iface,
1164 LPCDSCBUFFERDESC lpcDSCBufferDesc, IDirectSoundCaptureBuffer **lplpDSCaptureBuffer,
1165 IUnknown *pUnk)
1167 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1168 HRESULT hr;
1170 TRACE( "(%p,%p,%p,%p)\n",iface,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
1172 if (pUnk) {
1173 WARN("invalid parameter: pUnk != NULL\n");
1174 return DSERR_NOAGGREGATION;
1177 if (lpcDSCBufferDesc == NULL) {
1178 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
1179 return DSERR_INVALIDPARAM;
1182 if (lplpDSCaptureBuffer == NULL) {
1183 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
1184 return DSERR_INVALIDPARAM;
1187 if (pUnk != NULL) {
1188 WARN("invalid parameter: pUnk != NULL\n");
1189 return DSERR_INVALIDPARAM;
1192 /* FIXME: We can only have one buffer so what do we do here? */
1193 if (This->device->capture_buffer) {
1194 WARN("invalid parameter: already has buffer\n");
1195 return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */
1198 hr = IDirectSoundCaptureBufferImpl_Create(This->device,
1199 (IDirectSoundCaptureBufferImpl **)lplpDSCaptureBuffer, lpcDSCBufferDesc);
1201 if (hr != DS_OK)
1202 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
1204 return hr;
1207 static HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps(IDirectSoundCapture *iface,
1208 LPDSCCAPS lpDSCCaps)
1210 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1212 TRACE("(%p,%p)\n",This,lpDSCCaps);
1214 if (This->device == NULL) {
1215 WARN("not initialized\n");
1216 return DSERR_UNINITIALIZED;
1219 if (lpDSCCaps== NULL) {
1220 WARN("invalid parameter: lpDSCCaps== NULL\n");
1221 return DSERR_INVALIDPARAM;
1224 if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
1225 WARN("invalid parameter: lpDSCCaps->dwSize = %d\n", lpDSCCaps->dwSize);
1226 return DSERR_INVALIDPARAM;
1229 lpDSCCaps->dwFlags = This->device->drvcaps.dwFlags;
1230 lpDSCCaps->dwFormats = This->device->drvcaps.dwFormats;
1231 lpDSCCaps->dwChannels = This->device->drvcaps.dwChannels;
1233 TRACE("(flags=0x%08x,format=0x%08x,channels=%d)\n",lpDSCCaps->dwFlags,
1234 lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
1236 return DS_OK;
1239 static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(IDirectSoundCapture *iface,
1240 LPCGUID lpcGUID)
1242 IDirectSoundCaptureImpl *This = impl_from_IDirectSoundCapture(iface);
1244 TRACE("(%p,%s)\n", This, debugstr_guid(lpcGUID));
1246 if (This->device != NULL) {
1247 WARN("already initialized\n");
1248 return DSERR_ALREADYINITIALIZED;
1250 return DirectSoundCaptureDevice_Initialize(&This->device, lpcGUID);
1253 static const IDirectSoundCaptureVtbl dscvt =
1255 /* IUnknown methods */
1256 IDirectSoundCaptureImpl_QueryInterface,
1257 IDirectSoundCaptureImpl_AddRef,
1258 IDirectSoundCaptureImpl_Release,
1260 /* IDirectSoundCapture methods */
1261 IDirectSoundCaptureImpl_CreateCaptureBuffer,
1262 IDirectSoundCaptureImpl_GetCaps,
1263 IDirectSoundCaptureImpl_Initialize
1266 HRESULT IDirectSoundCaptureImpl_Create(IUnknown *outer_unk, REFIID riid, void **ppv, BOOL has_dsc8)
1268 IDirectSoundCaptureImpl *obj;
1269 HRESULT hr;
1271 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1273 *ppv = NULL;
1274 obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
1275 if (obj == NULL) {
1276 WARN("out of memory\n");
1277 return DSERR_OUTOFMEMORY;
1280 setup_dsound_options();
1282 obj->IUnknown_inner.lpVtbl = &unk_vtbl;
1283 obj->IDirectSoundCapture_iface.lpVtbl = &dscvt;
1284 obj->ref = 1;
1285 obj->refdsc = 0;
1286 obj->numIfaces = 1;
1287 obj->device = NULL;
1288 obj->has_dsc8 = has_dsc8;
1290 /* COM aggregation supported only internally */
1291 if (outer_unk)
1292 obj->outer_unk = outer_unk;
1293 else
1294 obj->outer_unk = &obj->IUnknown_inner;
1296 hr = IUnknown_QueryInterface(&obj->IUnknown_inner, riid, ppv);
1297 IUnknown_Release(&obj->IUnknown_inner);
1299 return hr;
1302 HRESULT DSOUND_CaptureCreate(REFIID riid, void **ppv)
1304 return IDirectSoundCaptureImpl_Create(NULL, riid, ppv, FALSE);
1307 HRESULT DSOUND_CaptureCreate8(REFIID riid, void **ppv)
1309 return IDirectSoundCaptureImpl_Create(NULL, riid, ppv, TRUE);
1312 /***************************************************************************
1313 * DirectSoundCaptureCreate [DSOUND.6]
1315 * Create and initialize a DirectSoundCapture interface.
1317 * PARAMS
1318 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
1319 * lplpDSC [O] Address of a variable to receive the interface pointer.
1320 * pUnkOuter [I] Must be NULL.
1322 * RETURNS
1323 * Success: DS_OK
1324 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1325 * DSERR_OUTOFMEMORY
1327 * NOTES
1328 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
1329 * or NULL for the default device or DSDEVID_DefaultCapture or
1330 * DSDEVID_DefaultVoiceCapture.
1332 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
1334 HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID lpcGUID, IDirectSoundCapture **ppDSC,
1335 IUnknown *pUnkOuter)
1337 HRESULT hr;
1338 IDirectSoundCapture *pDSC;
1340 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC, pUnkOuter);
1342 if (ppDSC == NULL) {
1343 WARN("invalid parameter: ppDSC == NULL\n");
1344 return DSERR_INVALIDPARAM;
1347 if (pUnkOuter) {
1348 WARN("invalid parameter: pUnkOuter != NULL\n");
1349 return DSERR_NOAGGREGATION;
1352 hr = DSOUND_CaptureCreate(&IID_IDirectSoundCapture, (void**)&pDSC);
1353 if (hr == DS_OK) {
1354 hr = IDirectSoundCapture_Initialize(pDSC, lpcGUID);
1355 if (hr != DS_OK) {
1356 IDirectSoundCapture_Release(pDSC);
1357 pDSC = 0;
1361 *ppDSC = pDSC;
1363 return hr;
1366 /***************************************************************************
1367 * DirectSoundCaptureCreate8 [DSOUND.12]
1369 * Create and initialize a DirectSoundCapture interface.
1371 * PARAMS
1372 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
1373 * lplpDSC [O] Address of a variable to receive the interface pointer.
1374 * pUnkOuter [I] Must be NULL.
1376 * RETURNS
1377 * Success: DS_OK
1378 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1379 * DSERR_OUTOFMEMORY
1381 * NOTES
1382 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
1383 * or NULL for the default device or DSDEVID_DefaultCapture or
1384 * DSDEVID_DefaultVoiceCapture.
1386 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
1388 HRESULT WINAPI DirectSoundCaptureCreate8(
1389 LPCGUID lpcGUID,
1390 LPDIRECTSOUNDCAPTURE8 *ppDSC8,
1391 LPUNKNOWN pUnkOuter)
1393 HRESULT hr;
1394 LPDIRECTSOUNDCAPTURE8 pDSC8;
1395 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC8, pUnkOuter);
1397 if (ppDSC8 == NULL) {
1398 WARN("invalid parameter: ppDSC8 == NULL\n");
1399 return DSERR_INVALIDPARAM;
1402 if (pUnkOuter) {
1403 WARN("invalid parameter: pUnkOuter != NULL\n");
1404 *ppDSC8 = NULL;
1405 return DSERR_NOAGGREGATION;
1408 hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, (void**)&pDSC8);
1409 if (hr == DS_OK) {
1410 hr = IDirectSoundCapture_Initialize(pDSC8, lpcGUID);
1411 if (hr != DS_OK) {
1412 IDirectSoundCapture_Release(pDSC8);
1413 pDSC8 = 0;
1417 *ppDSC8 = pDSC8;
1419 return hr;