ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

capture.c
Go to the documentation of this file.
00001 /*              DirectSoundCapture
00002  *
00003  * Copyright 1998 Marcus Meissner
00004  * Copyright 1998 Rob Riggs
00005  * Copyright 2000-2001 TransGaming Technologies, Inc.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 /*
00022  * TODO:
00023  *  Implement FX support.
00024  *  Implement both IDirectSoundCaptureBuffer and IDirectSoundCaptureBuffer8
00025  *  Make DirectSoundCaptureCreate and DirectSoundCaptureCreate8 behave differently
00026  */
00027 
00028 #include <stdarg.h>
00029 
00030 #define NONAMELESSSTRUCT
00031 #define NONAMELESSUNION
00032 #include "windef.h"
00033 #include "winbase.h"
00034 #include "winuser.h"
00035 #include "mmsystem.h"
00036 #include "mmddk.h"
00037 #include "winternl.h"
00038 #include "winnls.h"
00039 #include "wine/debug.h"
00040 #include "dsound.h"
00041 #include "dsdriver.h"
00042 #include "dsound_private.h"
00043 
00044 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
00045 
00046 /*****************************************************************************
00047  * IDirectSoundCapture implementation structure
00048  */
00049 struct IDirectSoundCaptureImpl
00050 {
00051     /* IUnknown fields */
00052     const IDirectSoundCaptureVtbl     *lpVtbl;
00053     LONG                               ref;
00054 
00055     DirectSoundCaptureDevice          *device;
00056 };
00057 
00058 static HRESULT IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8 * ppds);
00059 
00060 
00061 /*****************************************************************************
00062  * IDirectSoundCaptureNotify implementation structure
00063  */
00064 struct IDirectSoundCaptureNotifyImpl
00065 {
00066     /* IUnknown fields */
00067     const IDirectSoundNotifyVtbl       *lpVtbl;
00068     LONG                                ref;
00069     IDirectSoundCaptureBufferImpl*      dscb;
00070 };
00071 
00072 static HRESULT IDirectSoundCaptureNotifyImpl_Create(IDirectSoundCaptureBufferImpl *dscb,
00073                                                     IDirectSoundCaptureNotifyImpl ** pdscn);
00074 
00075 
00076 DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS];
00077 
00078 static HRESULT DirectSoundCaptureDevice_Create(DirectSoundCaptureDevice ** ppDevice);
00079 
00080 static const char * const captureStateString[] = {
00081     "STATE_STOPPED",
00082     "STATE_STARTING",
00083     "STATE_CAPTURING",
00084     "STATE_STOPPING"
00085 };
00086 
00087 HRESULT DSOUND_CaptureCreate(
00088     REFIID riid,
00089     LPDIRECTSOUNDCAPTURE *ppDSC)
00090 {
00091     LPDIRECTSOUNDCAPTURE pDSC;
00092     HRESULT hr;
00093     TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC);
00094 
00095     if (!IsEqualIID(riid, &IID_IUnknown) &&
00096         !IsEqualIID(riid, &IID_IDirectSoundCapture)) {
00097         *ppDSC = 0;
00098         return E_NOINTERFACE;
00099     }
00100 
00101     /* Get dsound configuration */
00102     setup_dsound_options();
00103 
00104     hr = IDirectSoundCaptureImpl_Create(&pDSC);
00105     if (hr == DS_OK) {
00106         IDirectSoundCapture_AddRef(pDSC);
00107         *ppDSC = pDSC;
00108     } else {
00109         WARN("IDirectSoundCaptureImpl_Create failed\n");
00110         *ppDSC = 0;
00111     }
00112 
00113     return hr;
00114 }
00115 
00116 HRESULT DSOUND_CaptureCreate8(
00117     REFIID riid,
00118     LPDIRECTSOUNDCAPTURE8 *ppDSC8)
00119 {
00120     LPDIRECTSOUNDCAPTURE8 pDSC8;
00121     HRESULT hr;
00122     TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC8);
00123 
00124     if (!IsEqualIID(riid, &IID_IUnknown) &&
00125         !IsEqualIID(riid, &IID_IDirectSoundCapture8)) {
00126         *ppDSC8 = 0;
00127         return E_NOINTERFACE;
00128     }
00129 
00130     /* Get dsound configuration */
00131     setup_dsound_options();
00132 
00133     hr = IDirectSoundCaptureImpl_Create(&pDSC8);
00134     if (hr == DS_OK) {
00135         IDirectSoundCapture_AddRef(pDSC8);
00136         *ppDSC8 = pDSC8;
00137     } else {
00138         WARN("IDirectSoundCaptureImpl_Create failed\n");
00139         *ppDSC8 = 0;
00140     }
00141 
00142     return hr;
00143 }
00144 
00145 /***************************************************************************
00146  * DirectSoundCaptureCreate [DSOUND.6]
00147  *
00148  * Create and initialize a DirectSoundCapture interface.
00149  *
00150  * PARAMS
00151  *    lpcGUID   [I] Address of the GUID that identifies the sound capture device.
00152  *    lplpDSC   [O] Address of a variable to receive the interface pointer.
00153  *    pUnkOuter [I] Must be NULL.
00154  *
00155  * RETURNS
00156  *    Success: DS_OK
00157  *    Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
00158  *             DSERR_OUTOFMEMORY
00159  *
00160  * NOTES
00161  *    lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
00162  *    or NULL for the default device or DSDEVID_DefaultCapture or
00163  *    DSDEVID_DefaultVoiceCapture.
00164  *
00165  *    DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
00166  */
00167 HRESULT WINAPI DirectSoundCaptureCreate(
00168     LPCGUID lpcGUID,
00169     LPDIRECTSOUNDCAPTURE *ppDSC,
00170     LPUNKNOWN pUnkOuter)
00171 {
00172     HRESULT hr;
00173     LPDIRECTSOUNDCAPTURE pDSC;
00174     TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC, pUnkOuter);
00175 
00176     if (ppDSC == NULL) {
00177     WARN("invalid parameter: ppDSC == NULL\n");
00178         return DSERR_INVALIDPARAM;
00179     }
00180 
00181     if (pUnkOuter) {
00182     WARN("invalid parameter: pUnkOuter != NULL\n");
00183         *ppDSC = NULL;
00184         return DSERR_NOAGGREGATION;
00185     }
00186 
00187     hr = DSOUND_CaptureCreate(&IID_IDirectSoundCapture, &pDSC);
00188     if (hr == DS_OK) {
00189         hr = IDirectSoundCapture_Initialize(pDSC, lpcGUID);
00190         if (hr != DS_OK) {
00191             IDirectSoundCapture_Release(pDSC);
00192             pDSC = 0;
00193         }
00194     }
00195 
00196     *ppDSC = pDSC;
00197 
00198     return hr;
00199 }
00200 
00201 /***************************************************************************
00202  * DirectSoundCaptureCreate8 [DSOUND.12]
00203  *
00204  * Create and initialize a DirectSoundCapture interface.
00205  *
00206  * PARAMS
00207  *    lpcGUID   [I] Address of the GUID that identifies the sound capture device.
00208  *    lplpDSC   [O] Address of a variable to receive the interface pointer.
00209  *    pUnkOuter [I] Must be NULL.
00210  *
00211  * RETURNS
00212  *    Success: DS_OK
00213  *    Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
00214  *             DSERR_OUTOFMEMORY
00215  *
00216  * NOTES
00217  *    lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate
00218  *    or NULL for the default device or DSDEVID_DefaultCapture or
00219  *    DSDEVID_DefaultVoiceCapture.
00220  *
00221  *    DSERR_ALLOCATED is returned for sound devices that do not support full duplex.
00222  */
00223 HRESULT WINAPI DirectSoundCaptureCreate8(
00224     LPCGUID lpcGUID,
00225     LPDIRECTSOUNDCAPTURE8 *ppDSC8,
00226     LPUNKNOWN pUnkOuter)
00227 {
00228     HRESULT hr;
00229     LPDIRECTSOUNDCAPTURE8 pDSC8;
00230     TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), ppDSC8, pUnkOuter);
00231 
00232     if (ppDSC8 == NULL) {
00233     WARN("invalid parameter: ppDSC8 == NULL\n");
00234         return DSERR_INVALIDPARAM;
00235     }
00236 
00237     if (pUnkOuter) {
00238     WARN("invalid parameter: pUnkOuter != NULL\n");
00239         *ppDSC8 = NULL;
00240         return DSERR_NOAGGREGATION;
00241     }
00242 
00243     hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &pDSC8);
00244     if (hr == DS_OK) {
00245         hr = IDirectSoundCapture_Initialize(pDSC8, lpcGUID);
00246         if (hr != DS_OK) {
00247             IDirectSoundCapture_Release(pDSC8);
00248             pDSC8 = 0;
00249         }
00250     }
00251 
00252     *ppDSC8 = pDSC8;
00253 
00254     return hr;
00255 }
00256 
00257 /***************************************************************************
00258  * DirectSoundCaptureEnumerateA [DSOUND.7]
00259  *
00260  * Enumerate all DirectSound drivers installed in the system.
00261  *
00262  * PARAMS
00263  *    lpDSEnumCallback  [I] Address of callback function.
00264  *    lpContext         [I] Address of user defined context passed to callback function.
00265  *
00266  * RETURNS
00267  *    Success: DS_OK
00268  *    Failure: DSERR_INVALIDPARAM
00269  */
00270 HRESULT WINAPI
00271 DirectSoundCaptureEnumerateA(
00272     LPDSENUMCALLBACKA lpDSEnumCallback,
00273     LPVOID lpContext)
00274 {
00275     unsigned devs, wid;
00276     DSDRIVERDESC desc;
00277     GUID guid;
00278     int err;
00279 
00280     TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
00281 
00282     if (lpDSEnumCallback == NULL) {
00283     WARN("invalid parameter: lpDSEnumCallback == NULL\n");
00284         return DSERR_INVALIDPARAM;
00285     }
00286 
00287     devs = waveInGetNumDevs();
00288     if (devs > 0) {
00289     if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
00290             for (wid = 0; wid < devs; ++wid) {
00291                 if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
00292                     err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
00293                     if (err == DS_OK) {
00294                         TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
00295                               "Primary Sound Capture Driver",desc.szDrvname,lpContext);
00296                         if (lpDSEnumCallback(NULL, "Primary Sound Capture Driver", desc.szDrvname, lpContext) == FALSE)
00297                             return DS_OK;
00298                     }
00299                 }
00300         }
00301     }
00302     }
00303 
00304     for (wid = 0; wid < devs; ++wid) {
00305         err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
00306     if (err == DS_OK) {
00307             TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
00308                   debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
00309             if (lpDSEnumCallback(&DSOUND_capture_guids[wid], desc.szDesc, desc.szDrvname, lpContext) == FALSE)
00310                 return DS_OK;
00311     }
00312     }
00313 
00314     return DS_OK;
00315 }
00316 
00317 /***************************************************************************
00318  * DirectSoundCaptureEnumerateW [DSOUND.8]
00319  *
00320  * Enumerate all DirectSound drivers installed in the system.
00321  *
00322  * PARAMS
00323  *    lpDSEnumCallback  [I] Address of callback function.
00324  *    lpContext         [I] Address of user defined context passed to callback function.
00325  *
00326  * RETURNS
00327  *    Success: DS_OK
00328  *    Failure: DSERR_INVALIDPARAM
00329  */
00330 HRESULT WINAPI
00331 DirectSoundCaptureEnumerateW(
00332     LPDSENUMCALLBACKW lpDSEnumCallback,
00333     LPVOID lpContext)
00334 {
00335     unsigned devs, wid;
00336     DSDRIVERDESC desc;
00337     GUID guid;
00338     int err;
00339     WCHAR wDesc[MAXPNAMELEN];
00340     WCHAR wName[MAXPNAMELEN];
00341 
00342     TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext );
00343 
00344     if (lpDSEnumCallback == NULL) {
00345     WARN("invalid parameter: lpDSEnumCallback == NULL\n");
00346         return DSERR_INVALIDPARAM;
00347     }
00348 
00349     devs = waveInGetNumDevs();
00350     if (devs > 0) {
00351     if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) {
00352             for (wid = 0; wid < devs; ++wid) {
00353                 if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) {
00354                     err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
00355                     if (err == DS_OK) {
00356                         TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
00357                               "Primary Sound Capture Driver",desc.szDrvname,lpContext);
00358                         MultiByteToWideChar( CP_ACP, 0, "Primary Sound Capture Driver", -1,
00359                                              wDesc, sizeof(wDesc)/sizeof(WCHAR) );
00360                         MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
00361                                              wName, sizeof(wName)/sizeof(WCHAR) );
00362                         if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE)
00363                             return DS_OK;
00364                     }
00365                 }
00366         }
00367     }
00368     }
00369 
00370     for (wid = 0; wid < devs; ++wid) {
00371         err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0));
00372     if (err == DS_OK) {
00373             TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
00374                   debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext);
00375             MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
00376                                  wDesc, sizeof(wDesc)/sizeof(WCHAR) );
00377             MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
00378                                  wName, sizeof(wName)/sizeof(WCHAR) );
00379             if (lpDSEnumCallback(&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE)
00380                 return DS_OK;
00381     }
00382     }
00383 
00384     return DS_OK;
00385 }
00386 
00387 static void capture_CheckNotify(IDirectSoundCaptureBufferImpl *This, DWORD from, DWORD len)
00388 {
00389     int i;
00390     for (i = 0; i < This->nrofnotifies; ++i) {
00391         LPDSBPOSITIONNOTIFY event = This->notifies + i;
00392         DWORD offset = event->dwOffset;
00393         TRACE("checking %d, position %d, event = %p\n", i, offset, event->hEventNotify);
00394 
00395         if (offset == DSBPN_OFFSETSTOP) {
00396             if (!from && !len) {
00397                 SetEvent(event->hEventNotify);
00398                 TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
00399                 return;
00400             }
00401             else return;
00402         }
00403 
00404         if (offset >= from && offset < (from + len))
00405         {
00406             TRACE("signalled event %p (%d)\n", event->hEventNotify, i);
00407             SetEvent(event->hEventNotify);
00408         }
00409     }
00410 }
00411 
00412 static void CALLBACK
00413 DSOUND_capture_callback(HWAVEIN hwi, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1,
00414                         DWORD_PTR dw2)
00415 {
00416     DirectSoundCaptureDevice * This = (DirectSoundCaptureDevice*)dwUser;
00417     IDirectSoundCaptureBufferImpl * Moi = This->capture_buffer;
00418     TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %d\n",hwi,msg,
00419     msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" :
00420     msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount());
00421 
00422     if (msg == MM_WIM_DATA) {
00423         EnterCriticalSection( &(This->lock) );
00424     TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n",
00425         captureStateString[This->state],This->index);
00426     if (This->state != STATE_STOPPED) {
00427         int index = This->index;
00428         if (This->state == STATE_STARTING)
00429         This->state = STATE_CAPTURING;
00430         capture_CheckNotify(Moi, (DWORD_PTR)This->pwave[index].lpData - (DWORD_PTR)This->buffer, This->pwave[index].dwBufferLength);
00431         This->index = (This->index + 1) % This->nrofpwaves;
00432         if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) {
00433         TRACE("end of buffer\n");
00434         This->state = STATE_STOPPED;
00435         capture_CheckNotify(Moi, 0, 0);
00436         } else {
00437         if (This->state == STATE_CAPTURING) {
00438             waveInUnprepareHeader(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
00439             waveInPrepareHeader(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
00440             waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR));
00441             } else if (This->state == STATE_STOPPING) {
00442             TRACE("stopping\n");
00443             This->state = STATE_STOPPED;
00444         }
00445         }
00446     }
00447     TRACE("DirectSoundCapture new This->state=%s, new This->index=%d\n",
00448         captureStateString[This->state],This->index);
00449         LeaveCriticalSection( &(This->lock) );
00450     }
00451 
00452     TRACE("completed\n");
00453 }
00454 
00455 /***************************************************************************
00456  * IDirectSoundCaptureImpl
00457  */
00458 static HRESULT WINAPI
00459 IDirectSoundCaptureImpl_QueryInterface(
00460     LPDIRECTSOUNDCAPTURE iface,
00461     REFIID riid,
00462     LPVOID* ppobj )
00463 {
00464     IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
00465     TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
00466 
00467     if (ppobj == NULL) {
00468     WARN("invalid parameter\n");
00469     return E_INVALIDARG;
00470     }
00471 
00472     *ppobj = NULL;
00473 
00474     if (IsEqualIID(riid, &IID_IUnknown)) {
00475         IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
00476         *ppobj = This;
00477         return DS_OK;
00478     } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) {
00479         IDirectSoundCapture_AddRef((LPDIRECTSOUNDCAPTURE)This);
00480         *ppobj = This;
00481         return DS_OK;
00482     }
00483 
00484     WARN("unsupported riid: %s\n", debugstr_guid(riid));
00485     return E_NOINTERFACE;
00486 }
00487 
00488 static ULONG WINAPI
00489 IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface )
00490 {
00491     IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
00492     ULONG ref = InterlockedIncrement(&(This->ref));
00493     TRACE("(%p) ref was %d\n", This, ref - 1);
00494     return ref;
00495 }
00496 
00497 static ULONG WINAPI
00498 IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface )
00499 {
00500     IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
00501     ULONG ref = InterlockedDecrement(&(This->ref));
00502     TRACE("(%p) ref was %d\n", This, ref + 1);
00503 
00504     if (!ref) {
00505         if (This->device)
00506             DirectSoundCaptureDevice_Release(This->device);
00507 
00508         HeapFree( GetProcessHeap(), 0, This );
00509         TRACE("(%p) released\n", This);
00510     }
00511     return ref;
00512 }
00513 
00514 HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer(
00515     LPDIRECTSOUNDCAPTURE iface,
00516     LPCDSCBUFFERDESC lpcDSCBufferDesc,
00517     LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer,
00518     LPUNKNOWN pUnk )
00519 {
00520     HRESULT hr;
00521     IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
00522 
00523     TRACE( "(%p,%p,%p,%p)\n",iface,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk);
00524 
00525     if (lpcDSCBufferDesc == NULL) {
00526     WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n");
00527     return DSERR_INVALIDPARAM;
00528     }
00529 
00530     if (lplpDSCaptureBuffer == NULL) {
00531     WARN("invalid parameter: lplpDSCaptureBuffer == NULL\n");
00532     return DSERR_INVALIDPARAM;
00533     }
00534 
00535     if (pUnk != NULL) {
00536     WARN("invalid parameter: pUnk != NULL\n");
00537     return DSERR_INVALIDPARAM;
00538     }
00539 
00540     /* FIXME: We can only have one buffer so what do we do here? */
00541     if (This->device->capture_buffer) {
00542     WARN("lnvalid parameter: already has buffer\n");
00543     return DSERR_INVALIDPARAM;    /* DSERR_GENERIC ? */
00544     }
00545 
00546     hr = IDirectSoundCaptureBufferImpl_Create(This->device,
00547         (IDirectSoundCaptureBufferImpl **)lplpDSCaptureBuffer, lpcDSCBufferDesc);
00548 
00549     if (hr != DS_OK)
00550     WARN("IDirectSoundCaptureBufferImpl_Create failed\n");
00551 
00552     return hr;
00553 }
00554 
00555 HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps(
00556     LPDIRECTSOUNDCAPTURE iface,
00557     LPDSCCAPS lpDSCCaps )
00558 {
00559     IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
00560     TRACE("(%p,%p)\n",This,lpDSCCaps);
00561 
00562     if (This->device == NULL) {
00563     WARN("not initialized\n");
00564     return DSERR_UNINITIALIZED;
00565     }
00566 
00567     if (lpDSCCaps== NULL) {
00568     WARN("invalid parameter: lpDSCCaps== NULL\n");
00569     return DSERR_INVALIDPARAM;
00570     }
00571 
00572     if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) {
00573     WARN("invalid parameter: lpDSCCaps->dwSize = %d\n", lpDSCCaps->dwSize);
00574     return DSERR_INVALIDPARAM;
00575     }
00576 
00577     lpDSCCaps->dwFlags = This->device->drvcaps.dwFlags;
00578     lpDSCCaps->dwFormats = This->device->drvcaps.dwFormats;
00579     lpDSCCaps->dwChannels = This->device->drvcaps.dwChannels;
00580 
00581     TRACE("(flags=0x%08x,format=0x%08x,channels=%d)\n",lpDSCCaps->dwFlags,
00582         lpDSCCaps->dwFormats, lpDSCCaps->dwChannels);
00583 
00584     return DS_OK;
00585 }
00586 
00587 HRESULT WINAPI IDirectSoundCaptureImpl_Initialize(
00588     LPDIRECTSOUNDCAPTURE iface,
00589     LPCGUID lpcGUID )
00590 {
00591     IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface;
00592     TRACE("(%p,%s)\n", This, debugstr_guid(lpcGUID));
00593 
00594     if (This->device != NULL) {
00595     WARN("already initialized\n");
00596     return DSERR_ALREADYINITIALIZED;
00597     }
00598     return DirectSoundCaptureDevice_Initialize(&This->device, lpcGUID);
00599 }
00600 
00601 static const IDirectSoundCaptureVtbl dscvt =
00602 {
00603     /* IUnknown methods */
00604     IDirectSoundCaptureImpl_QueryInterface,
00605     IDirectSoundCaptureImpl_AddRef,
00606     IDirectSoundCaptureImpl_Release,
00607 
00608     /* IDirectSoundCapture methods */
00609     IDirectSoundCaptureImpl_CreateCaptureBuffer,
00610     IDirectSoundCaptureImpl_GetCaps,
00611     IDirectSoundCaptureImpl_Initialize
00612 };
00613 
00614 static HRESULT IDirectSoundCaptureImpl_Create(
00615     LPDIRECTSOUNDCAPTURE8 * ppDSC)
00616 {
00617     IDirectSoundCaptureImpl *pDSC;
00618     TRACE("(%p)\n", ppDSC);
00619 
00620     /* Allocate memory */
00621     pDSC = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundCaptureImpl));
00622     if (pDSC == NULL) {
00623         WARN("out of memory\n");
00624         *ppDSC = NULL;
00625         return DSERR_OUTOFMEMORY;
00626     }
00627 
00628     pDSC->lpVtbl = &dscvt;
00629     pDSC->ref    = 0;
00630     pDSC->device = NULL;
00631 
00632     *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC;
00633 
00634     return DS_OK;
00635 }
00636 
00637 /*******************************************************************************
00638  *      IDirectSoundCaptureNotify
00639  */
00640 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface(
00641     LPDIRECTSOUNDNOTIFY iface,
00642     REFIID riid,
00643     LPVOID *ppobj)
00644 {
00645     IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
00646     TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
00647 
00648     if (This->dscb == NULL) {
00649     WARN("invalid parameter\n");
00650     return E_INVALIDARG;
00651     }
00652 
00653     return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj);
00654 }
00655 
00656 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
00657 {
00658     IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
00659     ULONG ref = InterlockedIncrement(&(This->ref));
00660     TRACE("(%p) ref was %d\n", This, ref - 1);
00661     return ref;
00662 }
00663 
00664 static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
00665 {
00666     IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
00667     ULONG ref = InterlockedDecrement(&(This->ref));
00668     TRACE("(%p) ref was %d\n", This, ref + 1);
00669 
00670     if (!ref) {
00671         if (This->dscb->hwnotify)
00672             IDsDriverNotify_Release(This->dscb->hwnotify);
00673     This->dscb->notify=NULL;
00674     IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb);
00675     HeapFree(GetProcessHeap(),0,This);
00676     TRACE("(%p) released\n", This);
00677     }
00678     return ref;
00679 }
00680 
00681 static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions(
00682     LPDIRECTSOUNDNOTIFY iface,
00683     DWORD howmuch,
00684     LPCDSBPOSITIONNOTIFY notify)
00685 {
00686     IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface;
00687     TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
00688 
00689     if (howmuch > 0 && notify == NULL) {
00690     WARN("invalid parameter: notify == NULL\n");
00691     return DSERR_INVALIDPARAM;
00692     }
00693 
00694     if (TRACE_ON(dsound)) {
00695     unsigned int i;
00696     for (i=0;i<howmuch;i++)
00697             TRACE("notify at %d to %p\n",
00698         notify[i].dwOffset,notify[i].hEventNotify);
00699     }
00700 
00701     if (This->dscb->hwnotify) {
00702     HRESULT hres;
00703     hres = IDsDriverNotify_SetNotificationPositions(This->dscb->hwnotify, howmuch, notify);
00704     if (hres != DS_OK)
00705         WARN("IDsDriverNotify_SetNotificationPositions failed\n");
00706     return hres;
00707     } else if (howmuch > 0) {
00708     /* Make an internal copy of the caller-supplied array.
00709      * Replace the existing copy if one is already present. */
00710     if (This->dscb->notifies)
00711         This->dscb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00712         This->dscb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
00713     else
00714         This->dscb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
00715         howmuch * sizeof(DSBPOSITIONNOTIFY));
00716 
00717     if (This->dscb->notifies == NULL) {
00718         WARN("out of memory\n");
00719         return DSERR_OUTOFMEMORY;
00720     }
00721     CopyMemory(This->dscb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
00722     This->dscb->nrofnotifies = howmuch;
00723     } else {
00724         HeapFree(GetProcessHeap(), 0, This->dscb->notifies);
00725         This->dscb->notifies = NULL;
00726         This->dscb->nrofnotifies = 0;
00727     }
00728 
00729     return S_OK;
00730 }
00731 
00732 static const IDirectSoundNotifyVtbl dscnvt =
00733 {
00734     IDirectSoundCaptureNotifyImpl_QueryInterface,
00735     IDirectSoundCaptureNotifyImpl_AddRef,
00736     IDirectSoundCaptureNotifyImpl_Release,
00737     IDirectSoundCaptureNotifyImpl_SetNotificationPositions,
00738 };
00739 
00740 static HRESULT IDirectSoundCaptureNotifyImpl_Create(
00741     IDirectSoundCaptureBufferImpl *dscb,
00742     IDirectSoundCaptureNotifyImpl **pdscn)
00743 {
00744     IDirectSoundCaptureNotifyImpl * dscn;
00745     TRACE("(%p,%p)\n",dscb,pdscn);
00746 
00747     dscn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dscn));
00748 
00749     if (dscn == NULL) {
00750     WARN("out of memory\n");
00751     return DSERR_OUTOFMEMORY;
00752     }
00753 
00754     dscn->ref = 0;
00755     dscn->lpVtbl = &dscnvt;
00756     dscn->dscb = dscb;
00757     dscb->notify = dscn;
00758     IDirectSoundCaptureBuffer_AddRef((LPDIRECTSOUNDCAPTUREBUFFER)dscb);
00759 
00760     *pdscn = dscn;
00761     return DS_OK;
00762 }
00763 
00764 /*******************************************************************************
00765  *      IDirectSoundCaptureBuffer
00766  */
00767 static HRESULT WINAPI
00768 IDirectSoundCaptureBufferImpl_QueryInterface(
00769     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
00770     REFIID riid,
00771     LPVOID* ppobj )
00772 {
00773     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
00774     HRESULT hres;
00775     TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
00776 
00777     if (ppobj == NULL) {
00778     WARN("invalid parameter\n");
00779     return E_INVALIDARG;
00780     }
00781 
00782     *ppobj = NULL;
00783 
00784     if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
00785     if (!This->notify)
00786         hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify);
00787     if (This->notify) {
00788         IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
00789         if (This->device->hwbuf && !This->hwnotify) {
00790         hres = IDsCaptureDriverBuffer_QueryInterface(This->device->hwbuf,
00791             &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify));
00792         if (hres != DS_OK) {
00793             WARN("IDsCaptureDriverBuffer_QueryInterface failed\n");
00794             IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
00795             *ppobj = 0;
00796             return hres;
00797             }
00798         }
00799 
00800             *ppobj = This->notify;
00801         return DS_OK;
00802     }
00803 
00804     WARN("IID_IDirectSoundNotify\n");
00805     return E_FAIL;
00806     }
00807 
00808     if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) ||
00809          IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) {
00810     IDirectSoundCaptureBuffer8_AddRef(iface);
00811     *ppobj = This;
00812     return NO_ERROR;
00813     }
00814 
00815     FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj);
00816     return E_NOINTERFACE;
00817 }
00818 
00819 static ULONG WINAPI
00820 IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
00821 {
00822     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
00823     ULONG ref = InterlockedIncrement(&(This->ref));
00824     TRACE("(%p) ref was %d\n", This, ref - 1);
00825     return ref;
00826 }
00827 
00828 static ULONG WINAPI
00829 IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
00830 {
00831     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
00832     ULONG ref = InterlockedDecrement(&(This->ref));
00833     TRACE("(%p) ref was %d\n", This, ref + 1);
00834 
00835     if (!ref) {
00836         TRACE("deleting object\n");
00837     if (This->device->state == STATE_CAPTURING)
00838         This->device->state = STATE_STOPPING;
00839 
00840         HeapFree(GetProcessHeap(),0, This->pdscbd);
00841 
00842     if (This->device->hwi) {
00843         waveInReset(This->device->hwi);
00844         waveInClose(This->device->hwi);
00845             HeapFree(GetProcessHeap(),0, This->device->pwave);
00846             This->device->pwave = 0;
00847         This->device->hwi = 0;
00848     }
00849 
00850     if (This->device->hwbuf)
00851         IDsCaptureDriverBuffer_Release(This->device->hwbuf);
00852 
00853         /* remove from DirectSoundCaptureDevice */
00854         This->device->capture_buffer = NULL;
00855 
00856         if (This->notify)
00857         IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify);
00858 
00859         /* If driver manages its own buffer, IDsCaptureDriverBuffer_Release
00860            should have freed the buffer. Prevent freeing it again in
00861            IDirectSoundCaptureBufferImpl_Create */
00862         if (!(This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY))
00863         This->device->buffer = NULL;
00864 
00865     HeapFree(GetProcessHeap(), 0, This->notifies);
00866         HeapFree( GetProcessHeap(), 0, This );
00867     TRACE("(%p) released\n", This);
00868     }
00869     return ref;
00870 }
00871 
00872 static HRESULT WINAPI
00873 IDirectSoundCaptureBufferImpl_GetCaps(
00874     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
00875     LPDSCBCAPS lpDSCBCaps )
00876 {
00877     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
00878     TRACE( "(%p,%p)\n", This, lpDSCBCaps );
00879 
00880     if (lpDSCBCaps == NULL) {
00881         WARN("invalid parameter: lpDSCBCaps == NULL\n");
00882         return DSERR_INVALIDPARAM;
00883     }
00884 
00885     if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) {
00886         WARN("invalid parameter: lpDSCBCaps->dwSize = %d\n", lpDSCBCaps->dwSize);
00887         return DSERR_INVALIDPARAM;
00888     }
00889 
00890     if (This->device == NULL) {
00891         WARN("invalid parameter: This->device == NULL\n");
00892         return DSERR_INVALIDPARAM;
00893     }
00894 
00895     lpDSCBCaps->dwSize = sizeof(DSCBCAPS);
00896     lpDSCBCaps->dwFlags = This->flags;
00897     lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes;
00898     lpDSCBCaps->dwReserved = 0;
00899 
00900     TRACE("returning DS_OK\n");
00901     return DS_OK;
00902 }
00903 
00904 static HRESULT WINAPI
00905 IDirectSoundCaptureBufferImpl_GetCurrentPosition(
00906     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
00907     LPDWORD lpdwCapturePosition,
00908     LPDWORD lpdwReadPosition )
00909 {
00910     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
00911     HRESULT hres = DS_OK;
00912     TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition );
00913 
00914     if (This->device == NULL) {
00915         WARN("invalid parameter: This->device == NULL\n");
00916         return DSERR_INVALIDPARAM;
00917     }
00918 
00919     if (This->device->driver) {
00920         hres = IDsCaptureDriverBuffer_GetPosition(This->device->hwbuf, lpdwCapturePosition, lpdwReadPosition );
00921     if (hres != DS_OK)
00922         WARN("IDsCaptureDriverBuffer_GetPosition failed\n");
00923     } else if (This->device->hwi) {
00924         DWORD pos;
00925 
00926         EnterCriticalSection(&This->device->lock);
00927         pos = (DWORD_PTR)This->device->pwave[This->device->index].lpData - (DWORD_PTR)This->device->buffer;
00928         if (lpdwCapturePosition)
00929             *lpdwCapturePosition = (This->device->pwave[This->device->index].dwBufferLength + pos) % This->device->buflen;
00930         if (lpdwReadPosition)
00931             *lpdwReadPosition = pos;
00932         LeaveCriticalSection(&This->device->lock);
00933 
00934     } else {
00935         WARN("no driver\n");
00936         hres = DSERR_NODRIVER;
00937     }
00938 
00939     TRACE("cappos=%d readpos=%d\n", (lpdwCapturePosition?*lpdwCapturePosition:-1), (lpdwReadPosition?*lpdwReadPosition:-1));
00940     TRACE("returning %08x\n", hres);
00941     return hres;
00942 }
00943 
00944 static HRESULT WINAPI
00945 IDirectSoundCaptureBufferImpl_GetFormat(
00946     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
00947     LPWAVEFORMATEX lpwfxFormat,
00948     DWORD dwSizeAllocated,
00949     LPDWORD lpdwSizeWritten )
00950 {
00951     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
00952     HRESULT hres = DS_OK;
00953     TRACE( "(%p,%p,0x%08x,%p)\n", This, lpwfxFormat, dwSizeAllocated,
00954         lpdwSizeWritten );
00955 
00956     if (This->device == NULL) {
00957         WARN("invalid parameter: This->device == NULL\n");
00958         return DSERR_INVALIDPARAM;
00959     }
00960 
00961     if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize))
00962         dwSizeAllocated = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
00963 
00964     if (lpwfxFormat) { /* NULL is valid (just want size) */
00965         CopyMemory(lpwfxFormat, This->device->pwfx, dwSizeAllocated);
00966         if (lpdwSizeWritten)
00967             *lpdwSizeWritten = dwSizeAllocated;
00968     } else {
00969         if (lpdwSizeWritten)
00970             *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize;
00971         else {
00972             TRACE("invalid parameter: lpdwSizeWritten = NULL\n");
00973             hres = DSERR_INVALIDPARAM;
00974         }
00975     }
00976 
00977     TRACE("returning %08x\n", hres);
00978     return hres;
00979 }
00980 
00981 static HRESULT WINAPI
00982 IDirectSoundCaptureBufferImpl_GetStatus(
00983     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
00984     LPDWORD lpdwStatus )
00985 {
00986     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
00987     TRACE( "(%p, %p), thread is %04x\n", This, lpdwStatus, GetCurrentThreadId() );
00988 
00989     if (This->device == NULL) {
00990         WARN("invalid parameter: This->device == NULL\n");
00991         return DSERR_INVALIDPARAM;
00992     }
00993 
00994     if (lpdwStatus == NULL) {
00995         WARN("invalid parameter: lpdwStatus == NULL\n");
00996         return DSERR_INVALIDPARAM;
00997     }
00998 
00999     *lpdwStatus = 0;
01000     EnterCriticalSection(&(This->device->lock));
01001 
01002     TRACE("old This->device->state=%s, old lpdwStatus=%08x\n",
01003     captureStateString[This->device->state],*lpdwStatus);
01004     if ((This->device->state == STATE_STARTING) ||
01005         (This->device->state == STATE_CAPTURING)) {
01006         *lpdwStatus |= DSCBSTATUS_CAPTURING;
01007         if (This->flags & DSCBSTART_LOOPING)
01008             *lpdwStatus |= DSCBSTATUS_LOOPING;
01009     }
01010     TRACE("new This->device->state=%s, new lpdwStatus=%08x\n",
01011     captureStateString[This->device->state],*lpdwStatus);
01012     LeaveCriticalSection(&(This->device->lock));
01013 
01014     TRACE("status=%x\n", *lpdwStatus);
01015     TRACE("returning DS_OK\n");
01016     return DS_OK;
01017 }
01018 
01019 static HRESULT WINAPI
01020 IDirectSoundCaptureBufferImpl_Initialize(
01021     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
01022     LPDIRECTSOUNDCAPTURE lpDSC,
01023     LPCDSCBUFFERDESC lpcDSCBDesc )
01024 {
01025     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
01026 
01027     FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc );
01028 
01029     return DS_OK;
01030 }
01031 
01032 static HRESULT WINAPI
01033 IDirectSoundCaptureBufferImpl_Lock(
01034     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
01035     DWORD dwReadCusor,
01036     DWORD dwReadBytes,
01037     LPVOID* lplpvAudioPtr1,
01038     LPDWORD lpdwAudioBytes1,
01039     LPVOID* lplpvAudioPtr2,
01040     LPDWORD lpdwAudioBytes2,
01041     DWORD dwFlags )
01042 {
01043     HRESULT hres = DS_OK;
01044     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
01045     TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This, dwReadCusor,
01046         dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2,
01047         lpdwAudioBytes2, dwFlags, GetTickCount() );
01048 
01049     if (This->device == NULL) {
01050         WARN("invalid parameter: This->device == NULL\n");
01051         return DSERR_INVALIDPARAM;
01052     }
01053 
01054     if (lplpvAudioPtr1 == NULL) {
01055         WARN("invalid parameter: lplpvAudioPtr1 == NULL\n");
01056         return DSERR_INVALIDPARAM;
01057     }
01058 
01059     if (lpdwAudioBytes1 == NULL) {
01060         WARN("invalid parameter: lpdwAudioBytes1 == NULL\n");
01061         return DSERR_INVALIDPARAM;
01062     }
01063 
01064     EnterCriticalSection(&(This->device->lock));
01065 
01066     if (This->device->driver) {
01067         hres = IDsCaptureDriverBuffer_Lock(This->device->hwbuf, lplpvAudioPtr1,
01068                                            lpdwAudioBytes1, lplpvAudioPtr2,
01069                                            lpdwAudioBytes2, dwReadCusor,
01070                                            dwReadBytes, dwFlags);
01071     if (hres != DS_OK)
01072         WARN("IDsCaptureDriverBuffer_Lock failed\n");
01073     } else if (This->device->hwi) {
01074         *lplpvAudioPtr1 = This->device->buffer + dwReadCusor;
01075         if ( (dwReadCusor + dwReadBytes) > This->device->buflen) {
01076             *lpdwAudioBytes1 = This->device->buflen - dwReadCusor;
01077         if (lplpvAudioPtr2)
01078                 *lplpvAudioPtr2 = This->device->buffer;
01079         if (lpdwAudioBytes2)
01080         *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1;
01081         } else {
01082             *lpdwAudioBytes1 = dwReadBytes;
01083         if (lplpvAudioPtr2)
01084                 *lplpvAudioPtr2 = 0;
01085         if (lpdwAudioBytes2)
01086                 *lpdwAudioBytes2 = 0;
01087         }
01088     } else {
01089         TRACE("invalid call\n");
01090         hres = DSERR_INVALIDCALL;   /* DSERR_NODRIVER ? */
01091     }
01092 
01093     LeaveCriticalSection(&(This->device->lock));
01094 
01095     TRACE("returning %08x\n", hres);
01096     return hres;
01097 }
01098 
01099 static HRESULT WINAPI
01100 IDirectSoundCaptureBufferImpl_Start(
01101     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
01102     DWORD dwFlags )
01103 {
01104     HRESULT hres = DS_OK;
01105     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
01106     TRACE( "(%p,0x%08x)\n", This, dwFlags );
01107 
01108     if (This->device == NULL) {
01109         WARN("invalid parameter: This->device == NULL\n");
01110         return DSERR_INVALIDPARAM;
01111     }
01112 
01113     if ( (This->device->driver == 0) && (This->device->hwi == 0) ) {
01114         WARN("no driver\n");
01115         return DSERR_NODRIVER;
01116     }
01117 
01118     EnterCriticalSection(&(This->device->lock));
01119 
01120     This->flags = dwFlags;
01121     TRACE("old This->state=%s\n",captureStateString[This->device->state]);
01122     if (This->device->state == STATE_STOPPED)
01123         This->device->state = STATE_STARTING;
01124     else if (This->device->state == STATE_STOPPING)
01125         This->device->state = STATE_CAPTURING;
01126     TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
01127 
01128     LeaveCriticalSection(&(This->device->lock));
01129 
01130     if (This->device->driver) {
01131         hres = IDsCaptureDriverBuffer_Start(This->device->hwbuf, dwFlags);
01132     if (hres != DS_OK)
01133         WARN("IDsCaptureDriverBuffer_Start failed\n");
01134     } else if (This->device->hwi) {
01135         DirectSoundCaptureDevice *device = This->device;
01136 
01137         if (device->buffer) {
01138             int c;
01139             DWORD blocksize = DSOUND_fraglen(device->pwfx->nSamplesPerSec, device->pwfx->nBlockAlign);
01140             device->nrofpwaves = device->buflen / blocksize + !!(device->buflen % blocksize);
01141             TRACE("nrofpwaves=%d\n", device->nrofpwaves);
01142 
01143             /* prepare headers */
01144             if (device->pwave)
01145                 device->pwave = HeapReAlloc(GetProcessHeap(), 0,device->pwave, device->nrofpwaves*sizeof(WAVEHDR));
01146             else
01147                 device->pwave = HeapAlloc(GetProcessHeap(), 0, device->nrofpwaves*sizeof(WAVEHDR));
01148 
01149             for (c = 0; c < device->nrofpwaves; ++c) {
01150                 device->pwave[c].lpData = (char *)device->buffer + c * blocksize;
01151                 if (c + 1 == device->nrofpwaves)
01152                     device->pwave[c].dwBufferLength = device->buflen - c * blocksize;
01153                 else
01154                     device->pwave[c].dwBufferLength = blocksize;
01155                 device->pwave[c].dwBytesRecorded = 0;
01156                 device->pwave[c].dwUser = (DWORD_PTR)device;
01157                 device->pwave[c].dwFlags = 0;
01158                 device->pwave[c].dwLoops = 0;
01159                 hres = mmErr(waveInPrepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR)));
01160                 if (hres != DS_OK) {
01161                     WARN("waveInPrepareHeader failed\n");
01162                     while (c--)
01163                         waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR));
01164                     break;
01165                 }
01166 
01167                 hres = mmErr(waveInAddBuffer(device->hwi, &(device->pwave[c]), sizeof(WAVEHDR)));
01168                 if (hres != DS_OK) {
01169                     WARN("waveInAddBuffer failed\n");
01170                     while (c--)
01171                         waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR));
01172                     break;
01173                 }
01174             }
01175 
01176             FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
01177         }
01178 
01179         device->index = 0;
01180 
01181     if (hres == DS_OK) {
01182         /* start filling the first buffer */
01183         hres = mmErr(waveInStart(device->hwi));
01184             if (hres != DS_OK)
01185                 WARN("waveInStart failed\n");
01186         }
01187 
01188         if (hres != DS_OK) {
01189             WARN("calling waveInClose because of error\n");
01190             waveInClose(device->hwi);
01191             device->hwi = 0;
01192         }
01193     } else {
01194         WARN("no driver\n");
01195         hres = DSERR_NODRIVER;
01196     }
01197 
01198     TRACE("returning %08x\n", hres);
01199     return hres;
01200 }
01201 
01202 static HRESULT WINAPI
01203 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface )
01204 {
01205     HRESULT hres = DS_OK;
01206     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
01207     TRACE( "(%p)\n", This );
01208 
01209     if (This->device == NULL) {
01210         WARN("invalid parameter: This->device == NULL\n");
01211         return DSERR_INVALIDPARAM;
01212     }
01213 
01214     EnterCriticalSection(&(This->device->lock));
01215 
01216     TRACE("old This->device->state=%s\n",captureStateString[This->device->state]);
01217     if (This->device->state == STATE_CAPTURING)
01218     This->device->state = STATE_STOPPING;
01219     else if (This->device->state == STATE_STARTING)
01220     This->device->state = STATE_STOPPED;
01221     TRACE("new This->device->state=%s\n",captureStateString[This->device->state]);
01222 
01223     LeaveCriticalSection(&(This->device->lock));
01224 
01225     if (This->device->driver) {
01226         hres = IDsCaptureDriverBuffer_Stop(This->device->hwbuf);
01227         if (hres != DS_OK)
01228             WARN("IDsCaptureDriverBuffer_Stop() failed\n");
01229     } else if (This->device->hwi) {
01230         hres = mmErr(waveInReset(This->device->hwi));
01231         if (hres != DS_OK)
01232             WARN("waveInReset() failed\n");
01233     } else {
01234     WARN("no driver\n");
01235         hres = DSERR_NODRIVER;
01236     }
01237 
01238     TRACE("returning %08x\n", hres);
01239     return hres;
01240 }
01241 
01242 static HRESULT WINAPI
01243 IDirectSoundCaptureBufferImpl_Unlock(
01244     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
01245     LPVOID lpvAudioPtr1,
01246     DWORD dwAudioBytes1,
01247     LPVOID lpvAudioPtr2,
01248     DWORD dwAudioBytes2 )
01249 {
01250     HRESULT hres = DS_OK;
01251     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
01252     TRACE( "(%p,%p,%08u,%p,%08u)\n", This, lpvAudioPtr1, dwAudioBytes1,
01253         lpvAudioPtr2, dwAudioBytes2 );
01254 
01255     if (lpvAudioPtr1 == NULL) {
01256         WARN("invalid parameter: lpvAudioPtr1 == NULL\n");
01257         return DSERR_INVALIDPARAM;
01258     }
01259 
01260     if (This->device->driver) {
01261         hres = IDsCaptureDriverBuffer_Unlock(This->device->hwbuf, lpvAudioPtr1,
01262                                              dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
01263     if (hres != DS_OK)
01264         WARN("IDsCaptureDriverBuffer_Unlock failed\n");
01265     } else if (!This->device->hwi) {
01266         WARN("invalid call\n");
01267         hres = DSERR_INVALIDCALL;
01268     }
01269 
01270     TRACE("returning %08x\n", hres);
01271     return hres;
01272 }
01273 
01274 static HRESULT WINAPI
01275 IDirectSoundCaptureBufferImpl_GetObjectInPath(
01276     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
01277     REFGUID rguidObject,
01278     DWORD dwIndex,
01279     REFGUID rguidInterface,
01280     LPVOID* ppObject )
01281 {
01282     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
01283 
01284     FIXME( "(%p,%s,%u,%s,%p): stub\n", This, debugstr_guid(rguidObject),
01285         dwIndex, debugstr_guid(rguidInterface), ppObject );
01286 
01287     return DS_OK;
01288 }
01289 
01290 static HRESULT WINAPI
01291 IDirectSoundCaptureBufferImpl_GetFXStatus(
01292     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
01293     DWORD dwFXCount,
01294     LPDWORD pdwFXStatus )
01295 {
01296     IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface;
01297 
01298     FIXME( "(%p,%u,%p): stub\n", This, dwFXCount, pdwFXStatus );
01299 
01300     return DS_OK;
01301 }
01302 
01303 static const IDirectSoundCaptureBuffer8Vtbl dscbvt =
01304 {
01305     /* IUnknown methods */
01306     IDirectSoundCaptureBufferImpl_QueryInterface,
01307     IDirectSoundCaptureBufferImpl_AddRef,
01308     IDirectSoundCaptureBufferImpl_Release,
01309 
01310     /* IDirectSoundCaptureBuffer methods */
01311     IDirectSoundCaptureBufferImpl_GetCaps,
01312     IDirectSoundCaptureBufferImpl_GetCurrentPosition,
01313     IDirectSoundCaptureBufferImpl_GetFormat,
01314     IDirectSoundCaptureBufferImpl_GetStatus,
01315     IDirectSoundCaptureBufferImpl_Initialize,
01316     IDirectSoundCaptureBufferImpl_Lock,
01317     IDirectSoundCaptureBufferImpl_Start,
01318     IDirectSoundCaptureBufferImpl_Stop,
01319     IDirectSoundCaptureBufferImpl_Unlock,
01320 
01321     /* IDirectSoundCaptureBuffer methods */
01322     IDirectSoundCaptureBufferImpl_GetObjectInPath,
01323     IDirectSoundCaptureBufferImpl_GetFXStatus
01324 };
01325 
01326 HRESULT IDirectSoundCaptureBufferImpl_Create(
01327     DirectSoundCaptureDevice *device,
01328     IDirectSoundCaptureBufferImpl ** ppobj,
01329     LPCDSCBUFFERDESC lpcDSCBufferDesc)
01330 {
01331     LPWAVEFORMATEX  wfex;
01332     TRACE( "(%p,%p,%p)\n", device, ppobj, lpcDSCBufferDesc);
01333 
01334     if (ppobj == NULL) {
01335     WARN("invalid parameter: ppobj == NULL\n");
01336     return DSERR_INVALIDPARAM;
01337     }
01338 
01339     if (!device) {
01340     WARN("not initialized\n");
01341         *ppobj = NULL;
01342     return DSERR_UNINITIALIZED;
01343     }
01344 
01345     if (lpcDSCBufferDesc == NULL) {
01346     WARN("invalid parameter: lpcDSCBufferDesc == NULL\n");
01347         *ppobj = NULL;
01348     return DSERR_INVALIDPARAM;
01349     }
01350 
01351     if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) &&
01352           (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) ||
01353         (lpcDSCBufferDesc->dwBufferBytes == 0) ||
01354         (lpcDSCBufferDesc->lpwfxFormat == NULL) ) {
01355     WARN("invalid lpcDSCBufferDesc\n");
01356     *ppobj = NULL;
01357     return DSERR_INVALIDPARAM;
01358     }
01359 
01360     wfex = lpcDSCBufferDesc->lpwfxFormat;
01361 
01362     if (wfex) {
01363         TRACE("(formattag=0x%04x,chans=%d,samplerate=%d,"
01364             "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
01365             wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec,
01366             wfex->nAvgBytesPerSec, wfex->nBlockAlign,
01367             wfex->wBitsPerSample, wfex->cbSize);
01368 
01369         if (wfex->wFormatTag == WAVE_FORMAT_PCM) {
01370         device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX));
01371             *device->pwfx = *wfex;
01372         device->pwfx->cbSize = 0;
01373     } else {
01374         device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize);
01375             CopyMemory(device->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize);
01376         }
01377     } else {
01378     WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n");
01379     *ppobj = NULL;
01380     return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */
01381     }
01382 
01383     *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
01384         sizeof(IDirectSoundCaptureBufferImpl));
01385 
01386     if ( *ppobj == NULL ) {
01387     WARN("out of memory\n");
01388     *ppobj = NULL;
01389     return DSERR_OUTOFMEMORY;
01390     } else {
01391         HRESULT err = DS_OK;
01392         LPBYTE newbuf;
01393         DWORD buflen;
01394         IDirectSoundCaptureBufferImpl *This = *ppobj;
01395 
01396         This->ref = 1;
01397         This->device = device;
01398         This->device->capture_buffer = This;
01399     This->notify = NULL;
01400     This->nrofnotifies = 0;
01401     This->hwnotify = NULL;
01402 
01403         This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
01404             lpcDSCBufferDesc->dwSize);
01405         if (This->pdscbd)
01406             CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize);
01407         else {
01408             WARN("no memory\n");
01409             This->device->capture_buffer = 0;
01410             HeapFree( GetProcessHeap(), 0, This );
01411             *ppobj = NULL;
01412             return DSERR_OUTOFMEMORY;
01413         }
01414 
01415         This->lpVtbl = &dscbvt;
01416 
01417     if (device->driver) {
01418             if (This->device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
01419                 FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n");
01420 
01421             if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
01422                 /* allocate buffer from system memory */
01423                 buflen = lpcDSCBufferDesc->dwBufferBytes;
01424                 TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
01425                 if (device->buffer)
01426                     newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
01427                 else
01428                     newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
01429 
01430                 if (newbuf == NULL) {
01431                     WARN("failed to allocate capture buffer\n");
01432                     err = DSERR_OUTOFMEMORY;
01433                     /* but the old buffer might still exist and must be re-prepared */
01434                 } else {
01435                     device->buffer = newbuf;
01436                     device->buflen = buflen;
01437                 }
01438             } else {
01439                 /* let driver allocate memory */
01440                 device->buflen = lpcDSCBufferDesc->dwBufferBytes;
01441                 /* FIXME: */
01442                 HeapFree( GetProcessHeap(), 0, device->buffer);
01443                 device->buffer = NULL;
01444             }
01445 
01446         err = IDsCaptureDriver_CreateCaptureBuffer(device->driver,
01447         device->pwfx,0,0,&(device->buflen),&(device->buffer),(LPVOID*)&(device->hwbuf));
01448         if (err != DS_OK) {
01449         WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n");
01450         This->device->capture_buffer = 0;
01451         HeapFree( GetProcessHeap(), 0, This );
01452         *ppobj = NULL;
01453         return err;
01454         }
01455     } else {
01456         DWORD flags = CALLBACK_FUNCTION;
01457             err = mmErr(waveInOpen(&(device->hwi),
01458                 device->drvdesc.dnDevNode, device->pwfx,
01459                 (DWORD_PTR)DSOUND_capture_callback, (DWORD_PTR)device, flags));
01460             if (err != DS_OK) {
01461                 WARN("waveInOpen failed\n");
01462         This->device->capture_buffer = 0;
01463         HeapFree( GetProcessHeap(), 0, This );
01464         *ppobj = NULL;
01465         return err;
01466             }
01467 
01468         buflen = lpcDSCBufferDesc->dwBufferBytes;
01469             TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);
01470         if (device->buffer)
01471                 newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen);
01472         else
01473         newbuf = HeapAlloc(GetProcessHeap(),0,buflen);
01474             if (newbuf == NULL) {
01475                 WARN("failed to allocate capture buffer\n");
01476                 err = DSERR_OUTOFMEMORY;
01477                 /* but the old buffer might still exist and must be re-prepared */
01478             } else {
01479                 device->buffer = newbuf;
01480                 device->buflen = buflen;
01481             }
01482     }
01483     }
01484 
01485     TRACE("returning DS_OK\n");
01486     return DS_OK;
01487 }
01488 
01489 /*******************************************************************************
01490  * DirectSoundCaptureDevice
01491  */
01492 HRESULT DirectSoundCaptureDevice_Initialize(
01493     DirectSoundCaptureDevice ** ppDevice,
01494     LPCGUID lpcGUID)
01495 {
01496     HRESULT err = DSERR_INVALIDPARAM;
01497     unsigned wid, widn;
01498     BOOLEAN found = FALSE;
01499     GUID devGUID;
01500     DirectSoundCaptureDevice *device = *ppDevice;
01501     TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID));
01502 
01503     /* Default device? */
01504     if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) )
01505     lpcGUID = &DSDEVID_DefaultCapture;
01506 
01507     if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
01508         WARN("invalid parameter: lpcGUID\n");
01509         return DSERR_INVALIDPARAM;
01510     }
01511 
01512     widn = waveInGetNumDevs();
01513     if (!widn) {
01514     WARN("no audio devices found\n");
01515     return DSERR_NODRIVER;
01516     }
01517 
01518     /* enumerate WINMM audio devices and find the one we want */
01519     for (wid=0; wid<widn; wid++) {
01520         if (IsEqualGUID( &devGUID, &DSOUND_capture_guids[wid]) ) {
01521         found = TRUE;
01522         break;
01523     }
01524     }
01525 
01526     if (found == FALSE) {
01527     WARN("No device found matching given ID!\n");
01528     return DSERR_NODRIVER;
01529     }
01530 
01531     if (DSOUND_capture[wid]) {
01532         WARN("already in use\n");
01533         return DSERR_ALLOCATED;
01534     }
01535 
01536     err = DirectSoundCaptureDevice_Create(&(device));
01537     if (err != DS_OK) {
01538         WARN("DirectSoundCaptureDevice_Create failed\n");
01539         return err;
01540     }
01541 
01542     *ppDevice = device;
01543     device->guid = devGUID;
01544 
01545     /* Disable the direct sound driver to force emulation if requested. */
01546     device->driver = NULL;
01547     if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
01548     {
01549         err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&device->driver,0));
01550         if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) {
01551             WARN("waveInMessage failed; err=%x\n",err);
01552             return err;
01553         }
01554     }
01555     err = DS_OK;
01556 
01557     /* Get driver description */
01558     if (device->driver) {
01559         TRACE("using DirectSound driver\n");
01560         err = IDsCaptureDriver_GetDriverDesc(device->driver, &(device->drvdesc));
01561     if (err != DS_OK) {
01562         WARN("IDsCaptureDriver_GetDriverDesc failed\n");
01563         return err;
01564     }
01565     } else {
01566         TRACE("using WINMM\n");
01567         /* if no DirectSound interface available, use WINMM API instead */
01568         device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN |
01569             DSDDESC_DOMMSYSTEMSETFORMAT;
01570     }
01571 
01572     device->drvdesc.dnDevNode = wid;
01573 
01574     /* open the DirectSound driver if available */
01575     if (device->driver && (err == DS_OK))
01576         err = IDsCaptureDriver_Open(device->driver);
01577 
01578     if (err == DS_OK) {
01579         *ppDevice = device;
01580 
01581         /* the driver is now open, so it's now allowed to call GetCaps */
01582         if (device->driver) {
01583         device->drvcaps.dwSize = sizeof(device->drvcaps);
01584             err = IDsCaptureDriver_GetCaps(device->driver,&(device->drvcaps));
01585         if (err != DS_OK) {
01586         WARN("IDsCaptureDriver_GetCaps failed\n");
01587         return err;
01588         }
01589         } else /*if (device->hwi)*/ {
01590             WAVEINCAPSA    wic;
01591             err = mmErr(waveInGetDevCapsA((UINT)device->drvdesc.dnDevNode, &wic, sizeof(wic)));
01592 
01593             if (err == DS_OK) {
01594                 device->drvcaps.dwFlags = 0;
01595                 lstrcpynA(device->drvdesc.szDrvname, wic.szPname,
01596                           sizeof(device->drvdesc.szDrvname));
01597 
01598                 device->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER;
01599                 device->drvcaps.dwFormats = wic.dwFormats;
01600                 device->drvcaps.dwChannels = wic.wChannels;
01601             }
01602         }
01603     }
01604 
01605     return err;
01606 }
01607 
01608 static HRESULT DirectSoundCaptureDevice_Create(
01609     DirectSoundCaptureDevice ** ppDevice)
01610 {
01611     DirectSoundCaptureDevice * device;
01612     TRACE("(%p)\n", ppDevice);
01613 
01614     /* Allocate memory */
01615     device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectSoundCaptureDevice));
01616 
01617     if (device == NULL) {
01618     WARN("out of memory\n");
01619         return DSERR_OUTOFMEMORY;
01620     }
01621 
01622     device->ref = 1;
01623     device->state = STATE_STOPPED;
01624 
01625     InitializeCriticalSection( &(device->lock) );
01626     device->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundCaptureDevice.lock");
01627 
01628     *ppDevice = device;
01629 
01630     return DS_OK;
01631 }
01632 
01633 ULONG DirectSoundCaptureDevice_Release(
01634     DirectSoundCaptureDevice * device)
01635 {
01636     ULONG ref = InterlockedDecrement(&(device->ref));
01637     TRACE("(%p) ref was %d\n", device, ref + 1);
01638 
01639     if (!ref) {
01640         TRACE("deleting object\n");
01641         if (device->capture_buffer)
01642             IDirectSoundCaptureBufferImpl_Release(
01643         (LPDIRECTSOUNDCAPTUREBUFFER8) device->capture_buffer);
01644 
01645         if (device->driver) {
01646             IDsCaptureDriver_Close(device->driver);
01647             IDsCaptureDriver_Release(device->driver);
01648         }
01649 
01650         HeapFree(GetProcessHeap(), 0, device->pwfx);
01651         device->lock.DebugInfo->Spare[0] = 0;
01652         DeleteCriticalSection( &(device->lock) );
01653         DSOUND_capture[device->drvdesc.dnDevNode] = NULL;
01654         HeapFree(GetProcessHeap(), 0, device);
01655     TRACE("(%p) released\n", device);
01656     }
01657     return ref;
01658 }

Generated on Sun May 27 2012 04:21:39 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.