user32/tests: Restructure the DDE end-to-end tests to make it easier to add new cases.
[wine/hacks.git] / dlls / dsound / capture.c
blobf089313027d87262c366f1d30ceb9da14f33ae38
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 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 "winternl.h"
38 #include "winnls.h"
39 #include "wine/debug.h"
40 #include "dsound.h"
41 #include "dsdriver.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 if (This->dscb->hwnotify)
93 IDsDriverNotify_Release(This->dscb->hwnotify);
94 This->dscb->notify=NULL;
95 IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
96 HeapFree(GetProcessHeap(),0,This);
97 TRACE("(%p) released\n", This);
99 return ref;
102 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
103 LPDIRECTSOUNDNOTIFY iface,
104 DWORD howmuch,
105 LPCDSBPOSITIONNOTIFY notify)
107 IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
108 TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
110 if (howmuch > 0 && notify == NULL) {
111 WARN("invalid parameter: notify == NULL\n");
112 return DSERR_INVALIDPARAM;
115 if (TRACE_ON(dsound)) {
116 unsigned int i;
117 for (i=0;i<howmuch;i++)
118 TRACE("notify at %d to %p\n",
119 notify[i].dwOffset,notify[i].hEventNotify);
122 if (This->dscb->hwnotify) {
123 HRESULT hres;
124 hres = IDsDriverNotify_SetNotificationPositions(This->dscb->hwnotify, howmuch, notify);
125 if (hres != DS_OK)
126 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
127 return hres;
128 } else if (howmuch > 0) {
129 /* Make an internal copy of the caller-supplied array.
130 * Replace the existing copy if one is already present. */
131 if (This->dscb->notifies)
132 This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
133 This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
134 else
135 This->dscb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
136 howmuch * sizeof(DSBPOSITIONNOTIFY));
138 if (This->dscb->notifies == NULL) {
139 WARN("out of memory\n");
140 return DSERR_OUTOFMEMORY;
142 CopyMemory(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
143 This->dscb->nrofnotifies = howmuch;
144 } else {
145 HeapFree(GetProcessHeap(), 0, This->dscb->notifies);
146 This->dscb->notifies = NULL;
147 This->dscb->nrofnotifies = 0;
150 return S_OK;
153 static const IDirectSoundNotifyVtbl dscnvt =
155 IDirectSoundCaptureNotifyImpl_QueryInterface,
156 IDirectSoundCaptureNotifyImpl_AddRef,
157 IDirectSoundCaptureNotifyImpl_Release,
158 IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
161 static HRESULT IDirectSoundCaptureNotifyImpl_Create(
162 IDirectSoundCaptureBufferImpl *dscb,
163 IDirectSoundCaptureNotifyImpl **pdscn)
165 IDirectSoundCaptureNotifyImpl * dscn;
166 TRACE("(%p,%p)\n",dscb,pdscn);
168 dscn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dscn));
170 if (dscn == NULL) {
171 WARN("out of memory\n");
172 return DSERR_OUTOFMEMORY;
175 dscn->ref = 0;
176 dscn->lpVtbl = &dscnvt;
177 dscn->dscb = dscb;
178 dscb->notify = dscn;
179 IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
181 *pdscn = dscn;
182 return DS_OK;
186 static const char * const captureStateString[] = {
187 "STATE_STOPPED",
188 "STATE_STARTING",
189 "STATE_CAPTURING",
190 "STATE_STOPPING"
194 /*******************************************************************************
195 * IDirectSoundCaptureBuffer
197 static HRESULT WINAPI
198 IDirectSoundCaptureBufferImpl_QueryInterface(
199 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
200 REFIID riid,
201 LPVOID* ppobj )
203 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
204 HRESULT hres;
205 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
207 if (ppobj == NULL) {
208 WARN("invalid parameter\n");
209 return E_INVALIDARG;
212 *ppobj = NULL;
214 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
215 if (!This->notify)
216 hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
217 if (This->notify) {
218 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
219 if (This->device->hwbuf && !This->hwnotify) {
220 hres = IDsCaptureDriverBuffer_QueryInterface(This->device->hwbuf,
221 &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
222 if (hres != DS_OK) {
223 WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
224 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
225 *ppobj = 0;
226 return hres;
230 *ppobj = This->notify;
231 return DS_OK;
234 WARN("IID_IDirectSoundNotify\n");
235 return E_FAIL;
238 if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
239 IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
240 IDirectSoundCaptureBuffer8_AddRef(iface);
241 *ppobj = This;
242 return NO_ERROR;
245 FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
246 return E_NOINTERFACE;
249 static ULONG WINAPI
250 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
252 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
253 ULONG ref = InterlockedIncrement(&(This->ref));
254 TRACE("(%p) ref was %d\n", This, ref - 1);
255 return ref;
258 static ULONG WINAPI
259 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
261 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
262 ULONG ref = InterlockedDecrement(&(This->ref));
263 TRACE("(%p) ref was %d\n", This, ref + 1);
265 if (!ref) {
266 TRACE("deleting object\n");
267 if (This->device->state == STATE_CAPTURING)
268 This->device->state = STATE_STOPPING;
270 HeapFree(GetProcessHeap(),0, This->pdscbd);
272 if (This->device->hwi) {
273 waveInReset(This->device->hwi);
274 waveInClose(This->device->hwi);
275 HeapFree(GetProcessHeap(),0, This->device->pwave);
276 This->device->pwave = 0;
277 This->device->hwi = 0;
280 if (This->device->hwbuf)
281 IDsCaptureDriverBuffer_Release(This->device->hwbuf);
283 /* remove from DirectSoundCaptureDevice */
284 This->device->capture_buffer = NULL;
286 if (This->notify)
287 IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
289 /* If driver manages its own buffer, IDsCaptureDriverBuffer_Release
290 should have freed the buffer. Prevent freeing it again in
291 IDirectSoundCaptureBufferImpl_Create */
292 if (!(This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY))
293 This->device->buffer = NULL;
295 HeapFree(GetProcessHeap(), 0, This->notifies);
296 HeapFree( GetProcessHeap(), 0, This );
297 TRACE("(%p) released\n", This);
299 return ref;
302 static HRESULT WINAPI
303 IDirectSoundCaptureBufferImpl_GetCaps(
304 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
305 LPDSCBCAPS lpDSCBCaps )
307 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
308 TRACE( "(%p,%p)\n", This, lpDSCBCaps );
310 if (lpDSCBCaps == NULL) {
311 WARN("invalid parameter: lpDSCBCaps == NULL\n");
312 return DSERR_INVALIDPARAM;
315 if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) {
316 WARN("invalid parameter: lpDSCBCaps->dwSize = %d\n", lpDSCBCaps->dwSize);
317 return DSERR_INVALIDPARAM;
320 if (This->device == NULL) {
321 WARN("invalid parameter: This->device == NULL\n");
322 return DSERR_INVALIDPARAM;
325 lpDSCBCaps->dwSize = sizeof(DSCBCAPS);
326 lpDSCBCaps->dwFlags = This->flags;
327 lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes;
328 lpDSCBCaps->dwReserved = 0;
330 TRACE("returning DS_OK\n");
331 return DS_OK;
334 static HRESULT WINAPI
335 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
336 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
337 LPDWORD lpdwCapturePosition,
338 LPDWORD lpdwReadPosition )
340 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
341 HRESULT hres = DS_OK;
342 TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
344 if (This->device == NULL) {
345 WARN("invalid parameter: This->device == NULL\n");
346 return DSERR_INVALIDPARAM;
349 if (This->device->driver) {
350 hres = IDsCaptureDriverBuffer_GetPosition(This->device->hwbuf, lpdwCapturePosition, lpdwReadPosition );
351 if (hres != DS_OK)
352 WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
353 } else if (This->device->hwi) {
354 DWORD pos;
356 EnterCriticalSection(&This->device->lock);
357 pos = (DWORD_PTR)This->device->pwave[This->device->index].lpData - (DWORD_PTR)This->device->buffer;
358 if (lpdwCapturePosition)
359 *lpdwCapturePosition = (This->device->pwave[This->device->index].dwBufferLength + pos) % This->device->buflen;
360 if (lpdwReadPosition)
361 *lpdwReadPosition = pos;
362 LeaveCriticalSection(&This->device->lock);
364 } else {
365 WARN("no driver\n");
366 hres = DSERR_NODRIVER;
369 TRACE("cappos=%d readpos=%d\n", (lpdwCapturePosition?*lpdwCapturePosition:-1), (lpdwReadPosition?*lpdwReadPosition:-1));
370 TRACE("returning %08x\n", hres);
371 return hres;
374 static HRESULT WINAPI
375 IDirectSoundCaptureBufferImpl_GetFormat(
376 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
377 LPWAVEFORMATEX lpwfxFormat,
378 DWORD dwSizeAllocated,
379 LPDWORD lpdwSizeWritten )
381 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
382 HRESULT hres = DS_OK;
383 TRACE( "(%p,%p,0x%08x,%p)\n", This, lpwfxFormat, dwSizeAllocated,
384 lpdwSizeWritten );
386 if (This->device == NULL) {
387 WARN("invalid parameter: This->device == NULL\n");
388 return DSERR_INVALIDPARAM;
391 if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize))
392 dwSizeAllocated = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
394 if (lpwfxFormat) { /* NULL is valid (just want size) */
395 CopyMemory(lpwfxFormat, This->device->pwfx, dwSizeAllocated);
396 if (lpdwSizeWritten)
397 *lpdwSizeWritten = dwSizeAllocated;
398 } else {
399 if (lpdwSizeWritten)
400 *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
401 else {
402 TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
403 hres = DSERR_INVALIDPARAM;
407 TRACE("returning %08x\n", hres);
408 return hres;
411 static HRESULT WINAPI
412 IDirectSoundCaptureBufferImpl_GetStatus(
413 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
414 LPDWORD lpdwStatus )
416 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
417 TRACE( "(%p, %p), thread is %04x\n", This, lpdwStatus, GetCurrentThreadId() );
419 if (This->device == NULL) {
420 WARN("invalid parameter: This->device == NULL\n");
421 return DSERR_INVALIDPARAM;
424 if (lpdwStatus == NULL) {
425 WARN("invalid parameter: lpdwStatus == NULL\n");
426 return DSERR_INVALIDPARAM;
429 *lpdwStatus = 0;
430 EnterCriticalSection(&(This->device->lock));
432 TRACE("old This->device->state=%s, old lpdwStatus=%08x\n",
433 captureStateString[This->device->state],*lpdwStatus);
434 if ((This->device->state == STATE_STARTING) ||
435 (This->device->state == STATE_CAPTURING)) {
436 *lpdwStatus |= DSCBSTATUS_CAPTURING;
437 if (This->flags & DSCBSTART_LOOPING)
438 *lpdwStatus |= DSCBSTATUS_LOOPING;
440 TRACE("new This->device->state=%s, new lpdwStatus=%08x\n",
441 captureStateString[This->device->state],*lpdwStatus);
442 LeaveCriticalSection(&(This->device->lock));
444 TRACE("status=%x\n", *lpdwStatus);
445 TRACE("returning DS_OK\n");
446 return DS_OK;
449 static HRESULT WINAPI
450 IDirectSoundCaptureBufferImpl_Initialize(
451 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
452 LPDIRECTSOUNDCAPTURE lpDSC,
453 LPCDSCBUFFERDESC lpcDSCBDesc )
455 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
457 FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
459 return DS_OK;
462 static HRESULT WINAPI
463 IDirectSoundCaptureBufferImpl_Lock(
464 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
465 DWORD dwReadCusor,
466 DWORD dwReadBytes,
467 LPVOID* lplpvAudioPtr1,
468 LPDWORD lpdwAudioBytes1,
469 LPVOID* lplpvAudioPtr2,
470 LPDWORD lpdwAudioBytes2,
471 DWORD dwFlags )
473 HRESULT hres = DS_OK;
474 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
475 TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This, dwReadCusor,
476 dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
477 lpdwAudioBytes2, dwFlags, GetTickCount() );
479 if (This->device == NULL) {
480 WARN("invalid parameter: This->device == NULL\n");
481 return DSERR_INVALIDPARAM;
484 if (lplpvAudioPtr1 == NULL) {
485 WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
486 return DSERR_INVALIDPARAM;
489 if (lpdwAudioBytes1 == NULL) {
490 WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
491 return DSERR_INVALIDPARAM;
494 EnterCriticalSection(&(This->device->lock));
496 if (This->device->driver) {
497 hres = IDsCaptureDriverBuffer_Lock(This->device->hwbuf, lplpvAudioPtr1,
498 lpdwAudioBytes1, lplpvAudioPtr2,
499 lpdwAudioBytes2, dwReadCusor,
500 dwReadBytes, dwFlags);
501 if (hres != DS_OK)
502 WARN("IDsCaptureDriverBuffer_Lock failed\n");
503 } else if (This->device->hwi) {
504 *lplpvAudioPtr1 = This->device->buffer + dwReadCusor;
505 if ( (dwReadCusor + dwReadBytes) > This->device->buflen) {
506 *lpdwAudioBytes1 = This->device->buflen - dwReadCusor;
507 if (lplpvAudioPtr2)
508 *lplpvAudioPtr2 = This->device->buffer;
509 if (lpdwAudioBytes2)
510 *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
511 } else {
512 *lpdwAudioBytes1 = dwReadBytes;
513 if (lplpvAudioPtr2)
514 *lplpvAudioPtr2 = 0;
515 if (lpdwAudioBytes2)
516 *lpdwAudioBytes2 = 0;
518 } else {
519 TRACE("invalid call\n");
520 hres = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */
523 LeaveCriticalSection(&(This->device->lock));
525 TRACE("returning %08x\n", hres);
526 return hres;
529 static HRESULT WINAPI
530 IDirectSoundCaptureBufferImpl_Start(
531 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
532 DWORD dwFlags )
534 HRESULT hres = DS_OK;
535 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
536 TRACE( "(%p,0x%08x)\n", This, dwFlags );
538 if (This->device == NULL) {
539 WARN("invalid parameter: This->device == NULL\n");
540 return DSERR_INVALIDPARAM;
543 if ( (This->device->driver == 0) && (This->device->hwi == 0) ) {
544 WARN("no driver\n");
545 return DSERR_NODRIVER;
548 EnterCriticalSection(&(This->device->lock));
550 This->flags = dwFlags;
551 TRACE("old This->state=%s\n",captureStateString[This->device->state]);
552 if (This->device->state == STATE_STOPPED)
553 This->device->state = STATE_STARTING;
554 else if (This->device->state == STATE_STOPPING)
555 This->device->state = STATE_CAPTURING;
556 TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
558 LeaveCriticalSection(&(This->device->lock));
560 if (This->device->driver) {
561 hres = IDsCaptureDriverBuffer_Start(This->device->hwbuf, dwFlags);
562 if (hres != DS_OK)
563 WARN("IDsCaptureDriverBuffer_Start failed\n");
564 } else if (This->device->hwi) {
565 DirectSoundCaptureDevice *device = This->device;
567 if (device->buffer) {
568 int c;
569 DWORD blocksize = DSOUND_fraglen(device->pwfx->nSamplesPerSec, device->pwfx->nBlockAlign);
570 device->nrofpwaves = device->buflen / blocksize + !!(device->buflen % blocksize);
571 TRACE("nrofpwaves=%d\n", device->nrofpwaves);
573 /* prepare headers */
574 if (device->pwave)
575 device->pwave = HeapReAlloc(GetProcessHeap(), 0,device->pwave, device->nrofpwaves*sizeof(WAVEHDR));
576 else
577 device->pwave = HeapAlloc(GetProcessHeap(), 0, device->nrofpwaves*sizeof(WAVEHDR));
579 for (c = 0; c < device->nrofpwaves; ++c) {
580 device->pwave[c].lpData = (char *)device->buffer + c * blocksize;
581 if (c + 1 == device->nrofpwaves)
582 device->pwave[c].dwBufferLength = device->buflen - c * blocksize;
583 else
584 device->pwave[c].dwBufferLength = blocksize;
585 device->pwave[c].dwBytesRecorded = 0;
586 device->pwave[c].dwUser = (DWORD_PTR)device;
587 device->pwave[c].dwFlags = 0;
588 device->pwave[c].dwLoops = 0;
589 hres = mmErr(waveInPrepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR)));
590 if (hres != DS_OK) {
591 WARN("waveInPrepareHeader failed\n");
592 while (c--)
593 waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR));
594 break;
597 hres = mmErr(waveInAddBuffer(device->hwi, &(device->pwave[c]), sizeof(WAVEHDR)));
598 if (hres != DS_OK) {
599 WARN("waveInAddBuffer failed\n");
600 while (c--)
601 waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR));
602 break;
606 FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
609 device->index = 0;
611 if (hres == DS_OK) {
612 /* start filling the first buffer */
613 hres = mmErr(waveInStart(device->hwi));
614 if (hres != DS_OK)
615 WARN("waveInStart failed\n");
618 if (hres != DS_OK) {
619 WARN("calling waveInClose because of error\n");
620 waveInClose(device->hwi);
621 device->hwi = 0;
623 } else {
624 WARN("no driver\n");
625 hres = DSERR_NODRIVER;
628 TRACE("returning %08x\n", hres);
629 return hres;
632 static HRESULT WINAPI
633 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
635 HRESULT hres = DS_OK;
636 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
637 TRACE( "(%p)\n", This );
639 if (This->device == NULL) {
640 WARN("invalid parameter: This->device == NULL\n");
641 return DSERR_INVALIDPARAM;
644 EnterCriticalSection(&(This->device->lock));
646 TRACE("old This->device->state=%s\n",captureStateString[This->device->state]);
647 if (This->device->state == STATE_CAPTURING)
648 This->device->state = STATE_STOPPING;
649 else if (This->device->state == STATE_STARTING)
650 This->device->state = STATE_STOPPED;
651 TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
653 LeaveCriticalSection(&(This->device->lock));
655 if (This->device->driver) {
656 hres = IDsCaptureDriverBuffer_Stop(This->device->hwbuf);
657 if (hres != DS_OK)
658 WARN("IDsCaptureDriverBuffer_Stop() failed\n");
659 } else if (This->device->hwi) {
660 hres = mmErr(waveInReset(This->device->hwi));
661 if (hres != DS_OK)
662 WARN("waveInReset() failed\n");
663 } else {
664 WARN("no driver\n");
665 hres = DSERR_NODRIVER;
668 TRACE("returning %08x\n", hres);
669 return hres;
672 static HRESULT WINAPI
673 IDirectSoundCaptureBufferImpl_Unlock(
674 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
675 LPVOID lpvAudioPtr1,
676 DWORD dwAudioBytes1,
677 LPVOID lpvAudioPtr2,
678 DWORD dwAudioBytes2 )
680 HRESULT hres = DS_OK;
681 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
682 TRACE( "(%p,%p,%08u,%p,%08u)\n", This, lpvAudioPtr1, dwAudioBytes1,
683 lpvAudioPtr2, dwAudioBytes2 );
685 if (lpvAudioPtr1 == NULL) {
686 WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
687 return DSERR_INVALIDPARAM;
690 if (This->device->driver) {
691 hres = IDsCaptureDriverBuffer_Unlock(This->device->hwbuf, lpvAudioPtr1,
692 dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
693 if (hres != DS_OK)
694 WARN("IDsCaptureDriverBuffer_Unlock failed\n");
695 } else if (!This->device->hwi) {
696 WARN("invalid call\n");
697 hres = DSERR_INVALIDCALL;
700 TRACE("returning %08x\n", hres);
701 return hres;
704 static HRESULT WINAPI
705 IDirectSoundCaptureBufferImpl_GetObjectInPath(
706 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
707 REFGUID rguidObject,
708 DWORD dwIndex,
709 REFGUID rguidInterface,
710 LPVOID* ppObject )
712 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
714 FIXME( "(%p,%s,%u,%s,%p): stub\n", This, debugstr_guid(rguidObject),
715 dwIndex, debugstr_guid(rguidInterface), ppObject );
717 return DS_OK;
720 static HRESULT WINAPI
721 IDirectSoundCaptureBufferImpl_GetFXStatus(
722 LPDIRECTSOUNDCAPTUREBUFFER8 iface,
723 DWORD dwFXCount,
724 LPDWORD pdwFXStatus )
726 IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
728 FIXME( "(%p,%u,%p): stub\n", This, dwFXCount, pdwFXStatus );
730 return DS_OK;
733 static const IDirectSoundCaptureBuffer8Vtbl dscbvt =
735 /* IUnknown methods */
736 IDirectSoundCaptureBufferImpl_QueryInterface,
737 IDirectSoundCaptureBufferImpl_AddRef,
738 IDirectSoundCaptureBufferImpl_Release,
740 /* IDirectSoundCaptureBuffer methods */
741 IDirectSoundCaptureBufferImpl_GetCaps,
742 IDirectSoundCaptureBufferImpl_GetCurrentPosition,
743 IDirectSoundCaptureBufferImpl_GetFormat,
744 IDirectSoundCaptureBufferImpl_GetStatus,
745 IDirectSoundCaptureBufferImpl_Initialize,
746 IDirectSoundCaptureBufferImpl_Lock,
747 IDirectSoundCaptureBufferImpl_Start,
748 IDirectSoundCaptureBufferImpl_Stop,
749 IDirectSoundCaptureBufferImpl_Unlock,
751 /* IDirectSoundCaptureBuffer methods */
752 IDirectSoundCaptureBufferImpl_GetObjectInPath,
753 IDirectSoundCaptureBufferImpl_GetFXStatus
756 static void capture_CheckNotify(IDirectSoundCaptureBufferImpl *This, DWORD from, DWORD len)
758 int i;
759 for (i = 0; i < This->nrofnotifies; ++i) {
760 LPDSBPOSITIONNOTIFY event = This->notifies + i;
761 DWORD offset = event->dwOffset;
762 TRACE("checking %d, position %d, event = %p\n", i, offset, event->hEventNotify);
764 if (offset == DSBPN_OFFSETSTOP) {
765 if (!from && !len) {
766 SetEvent(event->hEventNotify);
767 TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
768 return;
770 else return;
773 if (offset >= from && offset < (from + len))
775 TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
776 SetEvent(event->hEventNotify);
781 static void CALLBACK
782 DSOUND_capture_callback(HWAVEIN hwi, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1,
783 DWORD_PTR dw2)
785 DirectSoundCaptureDevice * This = (DirectSoundCaptureDevice*)dwUser;
786 IDirectSoundCaptureBufferImpl * Moi = This->capture_buffer;
787 TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %d\n",hwi,msg,
788 msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
789 msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
791 if (msg == MM_WIM_DATA) {
792 EnterCriticalSection( &(This->lock) );
793 TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
794 captureStateString[This->state],This->index);
795 if (This->state != STATE_STOPPED) {
796 int index = This->index;
797 if (This->state == STATE_STARTING)
798 This->state = STATE_CAPTURING;
799 capture_CheckNotify(Moi, (DWORD_PTR)This->pwave[index].lpData - (DWORD_PTR)This->buffer, This->pwave[index].dwBufferLength);
800 This->index = (This->index + 1) % This->nrofpwaves;
801 if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
802 TRACE("end of buffer\n");
803 This->state = STATE_STOPPED;
804 capture_CheckNotify(Moi, 0, 0);
805 } else {
806 if (This->state == STATE_CAPTURING) {
807 waveInUnprepareHeader(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
808 waveInPrepareHeader(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
809 waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
810 } else if (This->state == STATE_STOPPING) {
811 TRACE("stopping\n");
812 This->state = STATE_STOPPED;
816 TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
817 captureStateString[This->state],This->index);
818 LeaveCriticalSection( &(This->lock) );
821 TRACE("completed\n");
824 static HRESULT IDirectSoundCaptureBufferImpl_Create(
825 DirectSoundCaptureDevice *device,
826 IDirectSoundCaptureBufferImpl ** ppobj,
827 LPCDSCBUFFERDESC lpcDSCBufferDesc)
829 LPWAVEFORMATEX wfex;
830 TRACE( "(%p,%p,%p)\n", device, ppobj, lpcDSCBufferDesc);
832 if (ppobj == NULL) {
833 WARN("invalid parameter: ppobj == NULL\n");
834 return DSERR_INVALIDPARAM;
837 if (!device) {
838 WARN("not initialized\n");
839 *ppobj = NULL;
840 return DSERR_UNINITIALIZED;
843 if (lpcDSCBufferDesc == NULL) {
844 WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
845 *ppobj = NULL;
846 return DSERR_INVALIDPARAM;
849 if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) &&
850 (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) ||
851 (lpcDSCBufferDesc->dwBufferBytes == 0) ||
852 (lpcDSCBufferDesc->lpwfxFormat == NULL) ) { /* FIXME: DSERR_BADFORMAT ? */
853 WARN("invalid lpcDSCBufferDesc\n");
854 *ppobj = NULL;
855 return DSERR_INVALIDPARAM;
858 wfex = lpcDSCBufferDesc->lpwfxFormat;
860 TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
861 "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
862 wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
863 wfex->nAvgBytesPerSec, wfex->nBlockAlign,
864 wfex->wBitsPerSample, wfex->cbSize);
866 device->pwfx = DSOUND_CopyFormat(wfex);
867 if ( device->pwfx == NULL ) {
868 *ppobj = NULL;
869 return DSERR_OUTOFMEMORY;
872 *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
873 sizeof(IDirectSoundCaptureBufferImpl));
875 if ( *ppobj == NULL ) {
876 WARN("out of memory\n");
877 *ppobj = NULL;
878 return DSERR_OUTOFMEMORY;
879 } else {
880 HRESULT err = DS_OK;
881 LPBYTE newbuf;
882 DWORD buflen;
883 IDirectSoundCaptureBufferImpl *This = *ppobj;
885 This->ref = 1;
886 This->device = device;
887 This->device->capture_buffer = This;
888 This->notify = NULL;
889 This->nrofnotifies = 0;
890 This->hwnotify = NULL;
892 This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
893 lpcDSCBufferDesc->dwSize);
894 if (This->pdscbd)
895 CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
896 else {
897 WARN("no memory\n");
898 This->device->capture_buffer = 0;
899 HeapFree( GetProcessHeap(), 0, This );
900 *ppobj = NULL;
901 return DSERR_OUTOFMEMORY;
904 This->lpVtbl = &dscbvt;
906 if (device->driver) {
907 if (This->device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
908 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
910 if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
911 /* allocate buffer from system memory */
912 buflen = lpcDSCBufferDesc->dwBufferBytes;
913 TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
914 if (device->buffer)
915 newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
916 else
917 newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
919 if (newbuf == NULL) {
920 WARN("failed to allocate capture buffer\n");
921 err = DSERR_OUTOFMEMORY;
922 /* but the old buffer might still exist and must be re-prepared */
923 } else {
924 device->buffer = newbuf;
925 device->buflen = buflen;
927 } else {
928 /* let driver allocate memory */
929 device->buflen = lpcDSCBufferDesc->dwBufferBytes;
930 /* FIXME: */
931 HeapFree( GetProcessHeap(), 0, device->buffer);
932 device->buffer = NULL;
935 err = IDsCaptureDriver_CreateCaptureBuffer(device->driver,
936 device->pwfx,0,0,&(device->buflen),&(device->buffer),(LPVOID*)&(device->hwbuf));
937 if (err != DS_OK) {
938 WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
939 This->device->capture_buffer = 0;
940 HeapFree( GetProcessHeap(), 0, This );
941 *ppobj = NULL;
942 return err;
944 } else {
945 DWORD flags = CALLBACK_FUNCTION;
946 err = mmErr(waveInOpen(&(device->hwi),
947 device->drvdesc.dnDevNode, device->pwfx,
948 (DWORD_PTR)DSOUND_capture_callback, (DWORD_PTR)device, flags));
949 if (err != DS_OK) {
950 WARN("waveInOpen failed\n");
951 This->device->capture_buffer = 0;
952 HeapFree( GetProcessHeap(), 0, This );
953 *ppobj = NULL;
954 return err;
957 buflen = lpcDSCBufferDesc->dwBufferBytes;
958 TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
959 if (device->buffer)
960 newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
961 else
962 newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
963 if (newbuf == NULL) {
964 WARN("failed to allocate capture buffer\n");
965 err = DSERR_OUTOFMEMORY;
966 /* but the old buffer might still exist and must be re-prepared */
967 } else {
968 device->buffer = newbuf;
969 device->buflen = buflen;
974 TRACE("returning DS_OK\n");
975 return DS_OK;
979 /*******************************************************************************
980 * DirectSoundCaptureDevice
982 DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS];
984 static HRESULT DirectSoundCaptureDevice_Create(
985 DirectSoundCaptureDevice ** ppDevice)
987 DirectSoundCaptureDevice * device;
988 TRACE("(%p)\n", ppDevice);
990 /* Allocate memory */
991 device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectSoundCaptureDevice));
993 if (device == NULL) {
994 WARN("out of memory\n");
995 return DSERR_OUTOFMEMORY;
998 device->ref = 1;
999 device->state = STATE_STOPPED;
1001 InitializeCriticalSection( &(device->lock) );
1002 device->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundCaptureDevice.lock");
1004 *ppDevice = device;
1006 return DS_OK;
1009 static ULONG DirectSoundCaptureDevice_Release(
1010 DirectSoundCaptureDevice * device)
1012 ULONG ref = InterlockedDecrement(&(device->ref));
1013 TRACE("(%p) ref was %d\n", device, ref + 1);
1015 if (!ref) {
1016 TRACE("deleting object\n");
1017 if (device->capture_buffer)
1018 IDirectSoundCaptureBufferImpl_Release(
1019 (LPDIRECTSOUNDCAPTUREBUFFER8) device->capture_buffer);
1021 if (device->driver) {
1022 IDsCaptureDriver_Close(device->driver);
1023 IDsCaptureDriver_Release(device->driver);
1026 HeapFree(GetProcessHeap(), 0, device->pwfx);
1027 device->lock.DebugInfo->Spare[0] = 0;
1028 DeleteCriticalSection( &(device->lock) );
1029 DSOUND_capture[device->drvdesc.dnDevNode] = NULL;
1030 HeapFree(GetProcessHeap(), 0, device);
1031 TRACE("(%p) released\n", device);
1033 return ref;
1036 static HRESULT DirectSoundCaptureDevice_Initialize(
1037 DirectSoundCaptureDevice ** ppDevice,
1038 LPCGUID lpcGUID)
1040 HRESULT err = DSERR_INVALIDPARAM;
1041 unsigned wid, widn;
1042 BOOLEAN found = FALSE;
1043 GUID devGUID;
1044 DirectSoundCaptureDevice *device = *ppDevice;
1045 TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID));
1047 /* Default device? */
1048 if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
1049 lpcGUID = &DSDEVID_DefaultCapture;
1051 if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
1052 WARN("invalid parameter: lpcGUID\n");
1053 return DSERR_INVALIDPARAM;
1056 widn = waveInGetNumDevs();
1057 if (!widn) {
1058 WARN("no audio devices found\n");
1059 return DSERR_NODRIVER;
1062 /* enumerate WINMM audio devices and find the one we want */
1063 for (wid=0; wid<widn; wid++) {
1064 if (IsEqualGUID( &devGUID, &DSOUND_capture_guids[wid]) ) {
1065 found = TRUE;
1066 break;
1070 if (found == FALSE) {
1071 WARN("No device found matching given ID!\n");
1072 return DSERR_NODRIVER;
1075 if (DSOUND_capture[wid]) {
1076 WARN("already in use\n");
1077 return DSERR_ALLOCATED;
1080 err = DirectSoundCaptureDevice_Create(&(device));
1081 if (err != DS_OK) {
1082 WARN("DirectSoundCaptureDevice_Create failed\n");
1083 return err;
1086 *ppDevice = device;
1087 device->guid = devGUID;
1089 /* Disable the direct sound driver to force emulation if requested. */
1090 device->driver = NULL;
1091 if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
1093 err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&device->driver,0));
1094 if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
1095 WARN("waveInMessage failed; err=%x\n",err);
1096 return err;
1099 err = DS_OK;
1101 /* Get driver description */
1102 if (device->driver) {
1103 TRACE("using DirectSound driver\n");
1104 err = IDsCaptureDriver_GetDriverDesc(device->driver, &(device->drvdesc));
1105 if (err != DS_OK) {
1106 WARN("IDsCaptureDriver_GetDriverDesc failed\n");
1107 return err;
1109 } else {
1110 TRACE("using WINMM\n");
1111 /* if no DirectSound interface available, use WINMM API instead */
1112 device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |
1113 DSDDESC_DOMMSYSTEMSETFORMAT;
1116 device->drvdesc.dnDevNode = wid;
1118 /* open the DirectSound driver if available */
1119 if (device->driver && (err == DS_OK))
1120 err = IDsCaptureDriver_Open(device->driver);
1122 if (err == DS_OK) {
1123 *ppDevice = device;
1125 /* the driver is now open, so it's now allowed to call GetCaps */
1126 if (device->driver) {
1127 device->drvcaps.dwSize = sizeof(device->drvcaps);
1128 err = IDsCaptureDriver_GetCaps(device->driver,&(device->drvcaps));
1129 if (err != DS_OK) {
1130 WARN("IDsCaptureDriver_GetCaps failed\n");
1131 return err;
1133 } else /*if (device->hwi)*/ {
1134 WAVEINCAPSA wic;
1135 err = mmErr(waveInGetDevCapsA((UINT)device->drvdesc.dnDevNode, &wic, sizeof(wic)));
1137 if (err == DS_OK) {
1138 device->drvcaps.dwFlags = 0;
1139 lstrcpynA(device->drvdesc.szDrvname, wic.szPname,
1140 sizeof(device->drvdesc.szDrvname));
1142 device->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
1143 device->drvcaps.dwFormats = wic.dwFormats;
1144 device->drvcaps.dwChannels = wic.wChannels;
1149 return err;
1153 /*****************************************************************************
1154 * IDirectSoundCapture implementation structure
1156 struct IDirectSoundCaptureImpl
1158 /* IUnknown fields */
1159 const IDirectSoundCaptureVtbl *lpVtbl;
1160 LONG ref;
1162 DirectSoundCaptureDevice *device;
1165 /***************************************************************************
1166 * IDirectSoundCaptureImpl
1168 static HRESULT WINAPI
1169 IDirectSoundCaptureImpl_QueryInterface(
1170 LPDIRECTSOUNDCAPTURE iface,
1171 REFIID riid,
1172 LPVOID* ppobj )
1174 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
1175 TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
1177 if (ppobj == NULL) {
1178 WARN("invalid parameter\n");
1179 return E_INVALIDARG;
1182 *ppobj = NULL;
1184 if (IsEqualIID(riid, &IID_IUnknown)) {
1185 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
1186 *ppobj = This;
1187 return DS_OK;
1188 } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
1189 IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
1190 *ppobj = This;
1191 return DS_OK;
1194 WARN("unsupported riid: %s\n", debugstr_guid(riid));
1195 return E_NOINTERFACE;
1198 static ULONG WINAPI
1199 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
1201 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
1202 ULONG ref = InterlockedIncrement(&(This->ref));
1203 TRACE("(%p) ref was %d\n", This, ref - 1);
1204 return ref;
1207 static ULONG WINAPI
1208 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
1210 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
1211 ULONG ref = InterlockedDecrement(&(This->ref));
1212 TRACE("(%p) ref was %d\n", This, ref + 1);
1214 if (!ref) {
1215 if (This->device)
1216 DirectSoundCaptureDevice_Release(This->device);
1218 HeapFree( GetProcessHeap(), 0, This );
1219 TRACE("(%p) released\n", This);
1221 return ref;
1224 static HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer(
1225 LPDIRECTSOUNDCAPTURE iface,
1226 LPCDSCBUFFERDESC lpcDSCBufferDesc,
1227 LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
1228 LPUNKNOWN pUnk )
1230 HRESULT hr;
1231 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
1233 TRACE( "(%p,%p,%p,%p)\n",iface,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
1235 if (lpcDSCBufferDesc == NULL) {
1236 WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
1237 return DSERR_INVALIDPARAM;
1240 if (lplpDSCaptureBuffer == NULL) {
1241 WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
1242 return DSERR_INVALIDPARAM;
1245 if (pUnk != NULL) {
1246 WARN("invalid parameter: pUnk != NULL\n");
1247 return DSERR_INVALIDPARAM;
1250 /* FIXME: We can only have one buffer so what do we do here? */
1251 if (This->device->capture_buffer) {
1252 WARN("invalid parameter: already has buffer\n");
1253 return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */
1256 hr = IDirectSoundCaptureBufferImpl_Create(This->device,
1257 (IDirectSoundCaptureBufferImpl **)lplpDSCaptureBuffer, lpcDSCBufferDesc);
1259 if (hr != DS_OK)
1260 WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
1262 return hr;
1265 static HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps(
1266 LPDIRECTSOUNDCAPTURE iface,
1267 LPDSCCAPS lpDSCCaps )
1269 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
1270 TRACE("(%p,%p)\n",This,lpDSCCaps);
1272 if (This->device == NULL) {
1273 WARN("not initialized\n");
1274 return DSERR_UNINITIALIZED;
1277 if (lpDSCCaps== NULL) {
1278 WARN("invalid parameter: lpDSCCaps== NULL\n");
1279 return DSERR_INVALIDPARAM;
1282 if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
1283 WARN("invalid parameter: lpDSCCaps->dwSize = %d\n", lpDSCCaps->dwSize);
1284 return DSERR_INVALIDPARAM;
1287 lpDSCCaps->dwFlags = This->device->drvcaps.dwFlags;
1288 lpDSCCaps->dwFormats = This->device->drvcaps.dwFormats;
1289 lpDSCCaps->dwChannels = This->device->drvcaps.dwChannels;
1291 TRACE("(flags=0x%08x,format=0x%08x,channels=%d)\n",lpDSCCaps->dwFlags,
1292 lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
1294 return DS_OK;
1297 static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(
1298 LPDIRECTSOUNDCAPTURE iface,
1299 LPCGUID lpcGUID )
1301 IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
1302 TRACE("(%p,%s)\n", This, debugstr_guid(lpcGUID));
1304 if (This->device != NULL) {
1305 WARN("already initialized\n");
1306 return DSERR_ALREADYINITIALIZED;
1308 return DirectSoundCaptureDevice_Initialize(&This->device, lpcGUID);
1311 static const IDirectSoundCaptureVtbl dscvt =
1313 /* IUnknown methods */
1314 IDirectSoundCaptureImpl_QueryInterface,
1315 IDirectSoundCaptureImpl_AddRef,
1316 IDirectSoundCaptureImpl_Release,
1318 /* IDirectSoundCapture methods */
1319 IDirectSoundCaptureImpl_CreateCaptureBuffer,
1320 IDirectSoundCaptureImpl_GetCaps,
1321 IDirectSoundCaptureImpl_Initialize
1324 static HRESULT IDirectSoundCaptureImpl_Create(
1325 LPDIRECTSOUNDCAPTURE8 * ppDSC)
1327 IDirectSoundCaptureImpl *pDSC;
1328 TRACE("(%p)\n", ppDSC);
1330 /* Allocate memory */
1331 pDSC = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundCaptureImpl));
1332 if (pDSC == NULL) {
1333 WARN("out of memory\n");
1334 *ppDSC = NULL;
1335 return DSERR_OUTOFMEMORY;
1338 pDSC->lpVtbl = &dscvt;
1339 pDSC->ref = 0;
1340 pDSC->device = NULL;
1342 *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC;
1344 return DS_OK;
1347 HRESULT DSOUND_CaptureCreate(
1348 REFIID riid,
1349 LPDIRECTSOUNDCAPTURE *ppDSC)
1351 LPDIRECTSOUNDCAPTURE pDSC;
1352 HRESULT hr;
1353 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC);
1355 if (!IsEqualIID(riid, &IID_IUnknown) &&
1356 !IsEqualIID(riid, &IID_IDirectSoundCapture)) {
1357 *ppDSC = 0;
1358 return E_NOINTERFACE;
1361 /* Get dsound configuration */
1362 setup_dsound_options();
1364 hr = IDirectSoundCaptureImpl_Create(&pDSC);
1365 if (hr == DS_OK) {
1366 IDirectSoundCapture_AddRef(pDSC);
1367 *ppDSC = pDSC;
1368 } else {
1369 WARN("IDirectSoundCaptureImpl_Create failed\n");
1370 *ppDSC = 0;
1373 return hr;
1376 HRESULT DSOUND_CaptureCreate8(
1377 REFIID riid,
1378 LPDIRECTSOUNDCAPTURE8 *ppDSC8)
1380 LPDIRECTSOUNDCAPTURE8 pDSC8;
1381 HRESULT hr;
1382 TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC8);
1384 if (!IsEqualIID(riid, &IID_IUnknown) &&
1385 !IsEqualIID(riid, &IID_IDirectSoundCapture8)) {
1386 *ppDSC8 = 0;
1387 return E_NOINTERFACE;
1390 /* Get dsound configuration */
1391 setup_dsound_options();
1393 hr = IDirectSoundCaptureImpl_Create(&pDSC8);
1394 if (hr == DS_OK) {
1395 IDirectSoundCapture_AddRef(pDSC8);
1396 *ppDSC8 = pDSC8;
1397 } else {
1398 WARN("IDirectSoundCaptureImpl_Create failed\n");
1399 *ppDSC8 = 0;
1402 return hr;
1405 /***************************************************************************
1406 * DirectSoundCaptureCreate [DSOUND.6]
1408 * Create and initialize a DirectSoundCapture interface.
1410 * PARAMS
1411 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
1412 * lplpDSC [O] Address of a variable to receive the interface pointer.
1413 * pUnkOuter [I] Must be NULL.
1415 * RETURNS
1416 * Success: DS_OK
1417 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1418 * DSERR_OUTOFMEMORY
1420 * NOTES
1421 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
1422 * or NULL for the default device or DSDEVID_DefaultCapture or
1423 * DSDEVID_DefaultVoiceCapture.
1425 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
1427 HRESULT WINAPI DirectSoundCaptureCreate(
1428 LPCGUID lpcGUID,
1429 LPDIRECTSOUNDCAPTURE *ppDSC,
1430 LPUNKNOWN pUnkOuter)
1432 HRESULT hr;
1433 LPDIRECTSOUNDCAPTURE pDSC;
1434 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC, pUnkOuter);
1436 if (ppDSC == NULL) {
1437 WARN("invalid parameter: ppDSC == NULL\n");
1438 return DSERR_INVALIDPARAM;
1441 if (pUnkOuter) {
1442 WARN("invalid parameter: pUnkOuter != NULL\n");
1443 *ppDSC = NULL;
1444 return DSERR_NOAGGREGATION;
1447 hr = DSOUND_CaptureCreate(&IID_IDirectSoundCapture, &pDSC);
1448 if (hr == DS_OK) {
1449 hr = IDirectSoundCapture_Initialize(pDSC, lpcGUID);
1450 if (hr != DS_OK) {
1451 IDirectSoundCapture_Release(pDSC);
1452 pDSC = 0;
1456 *ppDSC = pDSC;
1458 return hr;
1461 /***************************************************************************
1462 * DirectSoundCaptureCreate8 [DSOUND.12]
1464 * Create and initialize a DirectSoundCapture interface.
1466 * PARAMS
1467 * lpcGUID [I] Address of the GUID that identifies the sound capture device.
1468 * lplpDSC [O] Address of a variable to receive the interface pointer.
1469 * pUnkOuter [I] Must be NULL.
1471 * RETURNS
1472 * Success: DS_OK
1473 * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
1474 * DSERR_OUTOFMEMORY
1476 * NOTES
1477 * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
1478 * or NULL for the default device or DSDEVID_DefaultCapture or
1479 * DSDEVID_DefaultVoiceCapture.
1481 * DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
1483 HRESULT WINAPI DirectSoundCaptureCreate8(
1484 LPCGUID lpcGUID,
1485 LPDIRECTSOUNDCAPTURE8 *ppDSC8,
1486 LPUNKNOWN pUnkOuter)
1488 HRESULT hr;
1489 LPDIRECTSOUNDCAPTURE8 pDSC8;
1490 TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC8, pUnkOuter);
1492 if (ppDSC8 == NULL) {
1493 WARN("invalid parameter: ppDSC8 == NULL\n");
1494 return DSERR_INVALIDPARAM;
1497 if (pUnkOuter) {
1498 WARN("invalid parameter: pUnkOuter != NULL\n");
1499 *ppDSC8 = NULL;
1500 return DSERR_NOAGGREGATION;
1503 hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &pDSC8);
1504 if (hr == DS_OK) {
1505 hr = IDirectSoundCapture_Initialize(pDSC8, lpcGUID);
1506 if (hr != DS_OK) {
1507 IDirectSoundCapture_Release(pDSC8);
1508 pDSC8 = 0;
1512 *ppDSC8 = pDSC8;
1514 return hr;