Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencapture.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
1.7.6.1
|