Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencapturebuffer.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Configuration of network devices 00004 * FILE: dll/directx/dsound_new/capturebuffer.c 00005 * PURPOSE: IDirectSoundCaptureBuffer8 implementation 00006 * 00007 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) 00008 */ 00009 00010 00011 #include "precomp.h" 00012 00013 const GUID KSINTERFACESETID_Standard = {0x1A8766A0L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00014 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00015 const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; 00016 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; 00017 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00018 const GUID KSEVENTSETID_LoopedStreaming = {0x4682B940L, 0xC6EF, 0x11D0, {0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D}}; 00019 00020 00021 00022 typedef struct 00023 { 00024 IDirectSoundCaptureBuffer8Vtbl *lpVtbl; 00025 00026 LONG ref; 00027 LPFILTERINFO Filter; 00028 HANDLE hPin; 00029 PUCHAR Buffer; 00030 DWORD BufferSize; 00031 LPWAVEFORMATEX Format; 00032 WAVEFORMATEX MixFormat; 00033 BOOL bMix; 00034 BOOL bLoop; 00035 KSSTATE State; 00036 PUCHAR MixBuffer; 00037 ULONG MixBufferSize; 00038 HANDLE hStopEvent; 00039 volatile LONG StopMixerThread; 00040 volatile LONG CurrentMixPosition; 00041 00042 LPDIRECTSOUNDNOTIFY Notify; 00043 00044 }CDirectSoundCaptureBufferImpl, *LPCDirectSoundCaptureBufferImpl; 00045 00046 DWORD 00047 WINAPI 00048 MixerThreadRoutine( 00049 LPVOID lpParameter) 00050 { 00051 KSPROPERTY Request; 00052 KSAUDIO_POSITION Position; 00053 DWORD Result, MixPosition, BufferPosition, BytesWritten, BytesRead, MixLength, BufferLength; 00054 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)lpParameter; 00055 00056 /* setup audio position property request */ 00057 Request.Id = KSPROPERTY_AUDIO_POSITION; 00058 Request.Set = KSPROPSETID_Audio; 00059 Request.Flags = KSPROPERTY_TYPE_GET; 00060 00061 MixPosition = 0; 00062 BufferPosition = 0; 00063 do 00064 { 00065 /* query current position */ 00066 Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSPROPERTY), (PVOID)&Position, sizeof(KSAUDIO_POSITION), NULL); 00067 00068 /* sanity check */ 00069 ASSERT(Result == ERROR_SUCCESS); 00070 00071 /* FIXME implement samplerate conversion */ 00072 ASSERT(This->MixFormat.nSamplesPerSec == This->Format->nSamplesPerSec); 00073 00074 /* FIXME implement bitrate conversion */ 00075 ASSERT(This->MixFormat.wBitsPerSample == This->Format->wBitsPerSample); 00076 00077 /* sanity check */ 00078 ASSERT(BufferPosition <= This->BufferSize); 00079 ASSERT(MixPosition <= This->MixBufferSize); 00080 00081 if (BufferPosition == This->BufferSize) 00082 { 00083 /* restart from front */ 00084 BufferPosition = 0; 00085 } 00086 00087 if (MixPosition == This->MixBufferSize) 00088 { 00089 /* restart from front */ 00090 MixPosition = 0; 00091 } 00092 00093 if (This->MixFormat.nChannels != This->Format->nChannels) 00094 { 00095 if ((DWORD)Position.PlayOffset >= MixPosition) 00096 { 00097 /* calculate buffer position difference */ 00098 MixLength = Position.PlayOffset - MixPosition; 00099 } 00100 else 00101 { 00102 /* buffer overlap */ 00103 MixLength = This->MixBufferSize - MixPosition; 00104 } 00105 00106 BufferLength = This->BufferSize - BufferPosition; 00107 00108 /* convert the format */ 00109 PerformChannelConversion(&This->MixBuffer[MixPosition], MixLength, &BytesRead, This->MixFormat.nChannels, This->Format->nChannels, This->Format->wBitsPerSample, &This->Buffer[BufferPosition], BufferLength, &BytesWritten); 00110 00111 /* update buffer offsets */ 00112 MixPosition += BytesRead; 00113 BufferPosition += BytesWritten; 00114 DPRINT("MixPosition %u BufferPosition %u BytesRead %u BytesWritten %u MixLength %u BufferLength %u\n", MixPosition, BufferPosition, BytesRead, BytesWritten, MixLength, BufferLength); 00115 } 00116 00117 /* Notify Events */ 00118 if (This->Notify) 00119 { 00120 DoNotifyPositionEvents(This->Notify, This->CurrentMixPosition, BufferPosition); 00121 } 00122 00123 /* update offset */ 00124 InterlockedExchange(&This->CurrentMixPosition, (LONG)BufferPosition); 00125 00126 /* FIXME use timer */ 00127 Sleep(10); 00128 00129 }while(InterlockedCompareExchange(&This->StopMixerThread, 0, 0) == 0); 00130 00131 00132 /* signal stop event */ 00133 SetEvent(This->hStopEvent); 00134 00135 /* done */ 00136 return 0; 00137 } 00138 00139 00140 00141 HRESULT 00142 WINAPI 00143 IDirectSoundCaptureBufferImpl_QueryInterface( 00144 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00145 IN REFIID riid, 00146 LPVOID* ppobj) 00147 { 00148 LPOLESTR pStr; 00149 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00150 00151 /* check if requested interface is supported */ 00152 if (IsEqualIID(riid, &IID_IUnknown) || 00153 IsEqualIID(riid, &IID_IDirectSoundCaptureBuffer) || 00154 IsEqualIID(riid, &IID_IDirectSoundCaptureBuffer8)) 00155 { 00156 *ppobj = (LPVOID)&This->lpVtbl; 00157 InterlockedIncrement(&This->ref); 00158 return S_OK; 00159 } 00160 00161 /* check if the interface is supported */ 00162 if (IsEqualIID(riid, &IID_IDirectSoundNotify)) 00163 { 00164 if (!This->Notify) 00165 { 00166 HRESULT hr = NewDirectSoundNotify(&This->Notify, This->bLoop, This->bMix, This->hPin, This->BufferSize); 00167 if (FAILED(hr)) 00168 return hr; 00169 00170 *ppobj = (LPVOID)This->Notify; 00171 return S_OK; 00172 } 00173 00174 /* increment reference count on existing notify object */ 00175 IDirectSoundNotify_AddRef(This->Notify); 00176 *ppobj = (LPVOID)This->Notify; 00177 return S_OK; 00178 } 00179 00180 /* interface not supported */ 00181 if (SUCCEEDED(StringFromIID(riid, &pStr))) 00182 { 00183 DPRINT("No Interface for class %s\n", pStr); 00184 CoTaskMemFree(pStr); 00185 } 00186 return E_NOINTERFACE; 00187 } 00188 00189 ULONG 00190 WINAPI 00191 IDirectSoundCaptureBufferImpl_AddRef( 00192 LPDIRECTSOUNDCAPTUREBUFFER8 iface) 00193 { 00194 ULONG ref; 00195 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00196 00197 /* increment reference count */ 00198 ref = InterlockedIncrement(&This->ref); 00199 00200 return ref; 00201 00202 } 00203 00204 ULONG 00205 WINAPI 00206 IDirectSoundCaptureBufferImpl_Release( 00207 LPDIRECTSOUNDCAPTUREBUFFER8 iface) 00208 { 00209 ULONG ref; 00210 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00211 00212 /* release reference count */ 00213 ref = InterlockedDecrement(&(This->ref)); 00214 00215 if (!ref) 00216 { 00217 if (This->hPin) 00218 { 00219 /* close pin handle */ 00220 CloseHandle(This->hPin); 00221 } 00222 00223 if (This->hStopEvent) 00224 { 00225 /* close stop event handle */ 00226 CloseHandle(This->hStopEvent); 00227 } 00228 00229 if (This->MixBuffer) 00230 { 00231 /* free mix buffer */ 00232 HeapFree(GetProcessHeap(), 0, This->MixBuffer); 00233 } 00234 00235 /* free capture buffer */ 00236 HeapFree(GetProcessHeap(), 0, This->Buffer); 00237 /* free wave format */ 00238 HeapFree(GetProcessHeap(), 0, This->Format); 00239 /* free capture buffer */ 00240 HeapFree(GetProcessHeap(), 0, This); 00241 } 00242 00243 return ref; 00244 } 00245 00246 00247 HRESULT 00248 WINAPI 00249 IDirectSoundCaptureBufferImpl_GetCaps( 00250 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00251 LPDSCBCAPS lpDSCBCaps ) 00252 { 00253 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00254 00255 if (!lpDSCBCaps) 00256 { 00257 /* invalid parameter */ 00258 return DSERR_INVALIDPARAM; 00259 } 00260 00261 if (lpDSCBCaps->dwSize != sizeof(DSCBCAPS)) 00262 { 00263 /* invalid parameter */ 00264 return DSERR_INVALIDPARAM; 00265 } 00266 00267 lpDSCBCaps->dwBufferBytes = This->BufferSize; 00268 lpDSCBCaps->dwReserved = 0; 00269 //lpDSCBCaps->dwFlags = DSCBCAPS_WAVEMAPPED; 00270 00271 return DS_OK; 00272 } 00273 00274 HRESULT 00275 WINAPI 00276 IDirectSoundCaptureBufferImpl_GetCurrentPosition( 00277 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00278 LPDWORD lpdwCapturePosition, 00279 LPDWORD lpdwReadPosition) 00280 { 00281 KSAUDIO_POSITION Position; 00282 KSPROPERTY Request; 00283 DWORD Result; 00284 DWORD Value; 00285 00286 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00287 00288 if (!This->hPin) 00289 { 00290 if (lpdwCapturePosition) 00291 *lpdwCapturePosition = 0; 00292 00293 if (lpdwReadPosition) 00294 *lpdwReadPosition = 0; 00295 00296 DPRINT("No Audio Pin\n"); 00297 return DS_OK; 00298 } 00299 00300 if (This->bMix) 00301 { 00302 /* read current position */ 00303 Value = InterlockedCompareExchange(&This->CurrentMixPosition, 0, 0); 00304 00305 if (lpdwCapturePosition) 00306 *lpdwCapturePosition = (DWORD)Value; 00307 00308 if (lpdwReadPosition) 00309 *lpdwReadPosition = (DWORD)Value; 00310 00311 return DS_OK; 00312 } 00313 00314 /* setup audio position property request */ 00315 Request.Id = KSPROPERTY_AUDIO_POSITION; 00316 Request.Set = KSPROPSETID_Audio; 00317 Request.Flags = KSPROPERTY_TYPE_GET; 00318 00319 00320 Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSPROPERTY), (PVOID)&Position, sizeof(KSAUDIO_POSITION), NULL); 00321 00322 if (Result != ERROR_SUCCESS) 00323 { 00324 DPRINT("GetPosition failed with %x\n", Result); 00325 return DSERR_UNSUPPORTED; 00326 } 00327 00328 //DPRINT("Play %I64u Write %I64u \n", Position.PlayOffset, Position.WriteOffset); 00329 00330 if (lpdwCapturePosition) 00331 *lpdwCapturePosition = (DWORD)Position.PlayOffset; 00332 00333 if (lpdwReadPosition) 00334 *lpdwReadPosition = (DWORD)Position.WriteOffset; 00335 00336 return DS_OK; 00337 } 00338 00339 00340 HRESULT 00341 WINAPI 00342 IDirectSoundCaptureBufferImpl_GetFormat( 00343 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00344 LPWAVEFORMATEX lpwfxFormat, 00345 DWORD dwSizeAllocated, 00346 LPDWORD lpdwSizeWritten) 00347 { 00348 DWORD FormatSize; 00349 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00350 00351 FormatSize = sizeof(WAVEFORMATEX) + This->Format->cbSize; 00352 00353 if (!lpwfxFormat && !lpdwSizeWritten) 00354 { 00355 /* invalid parameter */ 00356 return DSERR_INVALIDPARAM; 00357 } 00358 00359 if (!lpwfxFormat) 00360 { 00361 /* return required format size */ 00362 *lpdwSizeWritten = FormatSize; 00363 return DS_OK; 00364 } 00365 else 00366 { 00367 if (dwSizeAllocated >= FormatSize) 00368 { 00369 /* copy format */ 00370 CopyMemory(lpwfxFormat, This->Format, FormatSize); 00371 00372 if (lpdwSizeWritten) 00373 *lpdwSizeWritten = FormatSize; 00374 00375 return DS_OK; 00376 } 00377 /* buffer too small */ 00378 if (lpdwSizeWritten) 00379 *lpdwSizeWritten = 0; 00380 return DSERR_INVALIDPARAM; 00381 } 00382 } 00383 00384 HRESULT 00385 WINAPI 00386 IDirectSoundCaptureBufferImpl_GetStatus( 00387 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00388 LPDWORD lpdwStatus ) 00389 { 00390 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00391 00392 if (!lpdwStatus) 00393 { 00394 /* invalid parameter */ 00395 return DSERR_INVALIDPARAM; 00396 } 00397 00398 /* reset flags */ 00399 *lpdwStatus = 0; 00400 00401 /* check if pin is running */ 00402 if (This->State == KSSTATE_RUN) 00403 *lpdwStatus |= DSCBSTATUS_CAPTURING; 00404 00405 /* check if a looped buffer is used */ 00406 if (This->bLoop) 00407 *lpdwStatus |= DSCBSTATUS_LOOPING; 00408 00409 /* done */ 00410 return DS_OK; 00411 } 00412 00413 HRESULT 00414 WINAPI 00415 IDirectSoundCaptureBufferImpl_Initialize( 00416 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00417 LPDIRECTSOUNDCAPTURE lpDSC, 00418 LPCDSCBUFFERDESC lpcDSCBDesc) 00419 { 00420 /* capture buffer is already initialized */ 00421 return DSERR_ALREADYINITIALIZED; 00422 } 00423 00424 HRESULT 00425 WINAPI 00426 IDirectSoundCaptureBufferImpl_Lock( 00427 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00428 DWORD dwOffset, 00429 DWORD dwBytes, 00430 LPVOID* ppvAudioPtr1, 00431 LPDWORD pdwAudioBytes1, 00432 LPVOID* ppvAudioPtr2, 00433 LPDWORD pdwAudioBytes2, 00434 DWORD dwFlags ) 00435 { 00436 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00437 00438 DPRINT("This %p dwOffset %u dwBytes %u ppvAudioPtr1 %p pdwAudioBytes1 %p ppvAudioPtr2 %p pdwAudioBytes2 %p dwFlags %x This->BufferSize %u\n", 00439 This, dwOffset, dwBytes, ppvAudioPtr1, pdwAudioBytes1, ppvAudioPtr2, pdwAudioBytes2, dwFlags, This->BufferSize); 00440 00441 if (dwFlags == DSBLOCK_ENTIREBUFFER) 00442 { 00443 *ppvAudioPtr1 = (LPVOID)This->Buffer; 00444 *pdwAudioBytes1 = This->BufferSize; 00445 if (ppvAudioPtr2) 00446 *ppvAudioPtr2 = NULL; 00447 if (pdwAudioBytes2) 00448 *pdwAudioBytes2 = 0; 00449 00450 return DS_OK; 00451 } 00452 else 00453 { 00454 ASSERT(dwOffset < This->BufferSize); 00455 ASSERT(dwBytes < This->BufferSize); 00456 ASSERT(dwBytes + dwOffset <= This->BufferSize); 00457 00458 *ppvAudioPtr1 = This->Buffer + dwOffset; 00459 *pdwAudioBytes1 = dwBytes; 00460 if (ppvAudioPtr2) 00461 *ppvAudioPtr2 = NULL; 00462 if (pdwAudioBytes2) 00463 *pdwAudioBytes2 = 0; 00464 00465 return DS_OK; 00466 } 00467 } 00468 00469 HRESULT 00470 WINAPI 00471 IDirectSoundCaptureBufferImpl_Start( 00472 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00473 DWORD dwFlags ) 00474 { 00475 KSPROPERTY Property; 00476 KSSTREAM_HEADER Header; 00477 DWORD Result, BytesTransferred; 00478 OVERLAPPED Overlapped; 00479 KSSTATE State; 00480 HANDLE hThread; 00481 00482 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00483 00484 DPRINT("IDirectSoundCaptureBufferImpl_Start Flags %x\n", dwFlags); 00485 ASSERT(dwFlags == DSCBSTART_LOOPING); 00486 00487 /* check if pin is already running */ 00488 if (This->State == KSSTATE_RUN) 00489 return DS_OK; 00490 00491 00492 /* check if there is a pin instance */ 00493 if (!This->hPin) 00494 return DSERR_GENERIC; 00495 00496 /* setup request */ 00497 Property.Set = KSPROPSETID_Connection; 00498 Property.Id = KSPROPERTY_CONNECTION_STATE; 00499 Property.Flags = KSPROPERTY_TYPE_SET; 00500 State = KSSTATE_RUN; 00501 00502 /* set pin to run */ 00503 Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesTransferred); 00504 00505 ASSERT(Result == ERROR_SUCCESS); 00506 00507 if (Result == ERROR_SUCCESS) 00508 { 00509 /* store result */ 00510 This->State = State; 00511 } 00512 00513 /* initialize overlapped struct */ 00514 ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); 00515 Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 00516 00517 /* clear stream header */ 00518 ZeroMemory(&Header, sizeof(KSSTREAM_HEADER)); 00519 00520 /* initialize stream header */ 00521 Header.FrameExtent = This->BufferSize; 00522 Header.DataUsed = 0; 00523 Header.Data = (This->bMix ? This->MixBuffer : This->Buffer); 00524 Header.Size = sizeof(KSSTREAM_HEADER); 00525 Header.PresentationTime.Numerator = 1; 00526 Header.PresentationTime.Denominator = 1; 00527 00528 Result = DeviceIoControl(This->hPin, IOCTL_KS_WRITE_STREAM, NULL, 0, &Header, sizeof(KSSTREAM_HEADER), &BytesTransferred, &Overlapped); 00529 00530 if (Result != ERROR_SUCCESS) 00531 { 00532 DPRINT("Failed submit buffer with %lx\n", Result); 00533 return DSERR_GENERIC; 00534 } 00535 00536 if (This->bMix) 00537 { 00538 if (!This->hStopEvent) 00539 { 00540 /* create stop event */ 00541 This->hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 00542 if (!This->hStopEvent) 00543 { 00544 DPRINT1("Failed to create event object with %x\n", GetLastError()); 00545 return DSERR_GENERIC; 00546 } 00547 } 00548 00549 /* set state to stop false */ 00550 This->StopMixerThread = FALSE; 00551 00552 hThread = CreateThread(NULL, 0, MixerThreadRoutine, (PVOID)This, 0, NULL); 00553 if (!hThread) 00554 { 00555 DPRINT1("Failed to create thread with %x\n", GetLastError()); 00556 return DSERR_GENERIC; 00557 } 00558 00559 /* close thread handle */ 00560 CloseHandle(hThread); 00561 } 00562 00563 00564 return DS_OK; 00565 } 00566 00567 HRESULT 00568 WINAPI 00569 IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) 00570 { 00571 KSPROPERTY Property; 00572 DWORD Result; 00573 KSSTATE State; 00574 00575 LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl); 00576 00577 if (This->State == KSSTATE_STOP) 00578 { 00579 /* stream has already been stopped */ 00580 return DS_OK; 00581 } 00582 00583 if (!This->hPin) 00584 return DSERR_GENERIC; 00585 00586 /* setup request */ 00587 Property.Set = KSPROPSETID_Connection; 00588 Property.Id = KSPROPERTY_CONNECTION_STATE; 00589 Property.Flags = KSPROPERTY_TYPE_SET; 00590 State = KSSTATE_STOP; 00591 00592 00593 /* set pin to stop */ 00594 Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), NULL); 00595 00596 ASSERT(Result == ERROR_SUCCESS); 00597 00598 00599 if (This->bMix) 00600 { 00601 /* sanity check */ 00602 ASSERT(This->hStopEvent); 00603 /* reset event */ 00604 ResetEvent(This->hStopEvent); 00605 /* signal event to stop */ 00606 This->StopMixerThread = TRUE; 00607 /* Wait for the event to stop */ 00608 WaitForSingleObject(This->hStopEvent, INFINITE); 00609 } 00610 00611 00612 if (Result == ERROR_SUCCESS) 00613 { 00614 /* store result */ 00615 This->State = State; 00616 return DS_OK; 00617 } 00618 00619 DPRINT("Failed to stop pin\n"); 00620 return DSERR_GENERIC; 00621 } 00622 00623 HRESULT 00624 WINAPI 00625 IDirectSoundCaptureBufferImpl_Unlock( 00626 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00627 LPVOID lpvAudioPtr1, 00628 DWORD dwAudioBytes1, 00629 LPVOID lpvAudioPtr2, 00630 DWORD dwAudioBytes2 ) 00631 { 00632 return DS_OK; 00633 } 00634 00635 HRESULT 00636 WINAPI 00637 IDirectSoundCaptureBufferImpl_GetObjectInPath( 00638 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00639 REFGUID rguidObject, 00640 DWORD dwIndex, 00641 REFGUID rguidInterface, 00642 LPVOID* ppObject ) 00643 { 00644 UNIMPLEMENTED 00645 return DSERR_INVALIDPARAM; 00646 } 00647 00648 HRESULT 00649 WINAPI 00650 IDirectSoundCaptureBufferImpl_GetFXStatus( 00651 LPDIRECTSOUNDCAPTUREBUFFER8 iface, 00652 DWORD dwFXCount, 00653 LPDWORD pdwFXStatus ) 00654 { 00655 UNIMPLEMENTED 00656 return DSERR_INVALIDPARAM; 00657 } 00658 00659 00660 static IDirectSoundCaptureBuffer8Vtbl vt_DirectSoundCaptureBuffer8 = 00661 { 00662 /* IUnknown methods */ 00663 IDirectSoundCaptureBufferImpl_QueryInterface, 00664 IDirectSoundCaptureBufferImpl_AddRef, 00665 IDirectSoundCaptureBufferImpl_Release, 00666 00667 /* IDirectSoundCaptureBuffer methods */ 00668 IDirectSoundCaptureBufferImpl_GetCaps, 00669 IDirectSoundCaptureBufferImpl_GetCurrentPosition, 00670 IDirectSoundCaptureBufferImpl_GetFormat, 00671 IDirectSoundCaptureBufferImpl_GetStatus, 00672 IDirectSoundCaptureBufferImpl_Initialize, 00673 IDirectSoundCaptureBufferImpl_Lock, 00674 IDirectSoundCaptureBufferImpl_Start, 00675 IDirectSoundCaptureBufferImpl_Stop, 00676 IDirectSoundCaptureBufferImpl_Unlock, 00677 00678 /* IDirectSoundCaptureBuffer methods */ 00679 IDirectSoundCaptureBufferImpl_GetObjectInPath, 00680 IDirectSoundCaptureBufferImpl_GetFXStatus 00681 }; 00682 00683 00684 00685 00686 HRESULT 00687 NewDirectSoundCaptureBuffer( 00688 LPDIRECTSOUNDCAPTUREBUFFER8 *OutBuffer, 00689 LPFILTERINFO Filter, 00690 LPCDSCBUFFERDESC lpcDSBufferDesc) 00691 { 00692 DWORD FormatSize, MixBufferSize; 00693 ULONG DeviceId = 0, PinId; 00694 DWORD Result = ERROR_SUCCESS; 00695 WAVEFORMATEX MixFormat; 00696 00697 LPCDirectSoundCaptureBufferImpl This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundCaptureBufferImpl)); 00698 00699 if (!This) 00700 { 00701 /* not enough memory */ 00702 return DSERR_OUTOFMEMORY; 00703 } 00704 00705 /* calculate format size */ 00706 FormatSize = sizeof(WAVEFORMATEX) + lpcDSBufferDesc->lpwfxFormat->cbSize; 00707 /* allocate format struct */ 00708 This->Format = HeapAlloc(GetProcessHeap(), 0, FormatSize); 00709 if (!This->Format) 00710 { 00711 /* not enough memory */ 00712 HeapFree(GetProcessHeap(), 0, This); 00713 return DSERR_OUTOFMEMORY; 00714 } 00715 00716 /* sanity check */ 00717 ASSERT(lpcDSBufferDesc->dwBufferBytes); 00718 00719 /* allocate capture buffer */ 00720 This->Buffer = HeapAlloc(GetProcessHeap(), 0, lpcDSBufferDesc->dwBufferBytes); 00721 if (!This->Buffer) 00722 { 00723 /* not enough memory */ 00724 HeapFree(GetProcessHeap(), 0, This->Format); 00725 HeapFree(GetProcessHeap(), 0, This); 00726 return DSERR_OUTOFMEMORY; 00727 } 00728 00729 /* store buffer size */ 00730 This->BufferSize = lpcDSBufferDesc->dwBufferBytes; 00731 ASSERT(lpcDSBufferDesc->lpwfxFormat->cbSize == 0); 00732 00733 do 00734 { 00735 /* try all available recording pins on that filter */ 00736 PinId = GetPinIdFromFilter(Filter, TRUE, DeviceId); 00737 00738 if (PinId == ULONG_MAX) 00739 break; 00740 00741 Result = OpenPin(Filter->hFilter, PinId, lpcDSBufferDesc->lpwfxFormat, &This->hPin, TRUE); 00742 if (Result == ERROR_SUCCESS) 00743 break; 00744 00745 DeviceId++; 00746 }while(TRUE); 00747 00748 if (Result != ERROR_SUCCESS) 00749 { 00750 /* failed to instantiate the capture pin with the native format 00751 * try to compute a compatible format and use that 00752 * we could use the mixer api for this purpose but... the kmixer isnt working very good atm 00753 */ 00754 00755 DeviceId = 0; 00756 do 00757 { 00758 /* try all available recording pins on that filter */ 00759 PinId = GetPinIdFromFilter(Filter, TRUE, DeviceId); 00760 DPRINT("PinId %u DeviceId %u\n", PinId, DeviceId); 00761 00762 if (PinId == ULONG_MAX) 00763 break; 00764 00765 if (CreateCompatiblePin(Filter->hFilter, PinId, TRUE, lpcDSBufferDesc->lpwfxFormat, &MixFormat, &This->hPin)) 00766 { 00767 This->bMix = TRUE; 00768 CopyMemory(&This->MixFormat, &MixFormat, sizeof(WAVEFORMATEX)); 00769 break; 00770 } 00771 00772 DeviceId++; 00773 }while(TRUE); 00774 00775 00776 if (!This->bMix) 00777 { 00778 /* FIXME should not happen */ 00779 DPRINT("failed to compute a compatible format\n"); 00780 HeapFree(GetProcessHeap(), 0, This->MixBuffer); 00781 HeapFree(GetProcessHeap(), 0, This->Buffer); 00782 HeapFree(GetProcessHeap(), 0, This->Format); 00783 HeapFree(GetProcessHeap(), 0, This); 00784 return DSERR_GENERIC; 00785 } 00786 00787 MixBufferSize = lpcDSBufferDesc->dwBufferBytes; 00788 MixBufferSize /= lpcDSBufferDesc->lpwfxFormat->nChannels; 00789 MixBufferSize /= (lpcDSBufferDesc->lpwfxFormat->wBitsPerSample/8); 00790 00791 MixBufferSize *= This->MixFormat.nChannels; 00792 MixBufferSize *= (This->MixFormat.wBitsPerSample/8); 00793 00794 /* allocate buffer for mixing */ 00795 This->MixBuffer = HeapAlloc(GetProcessHeap(), 0, MixBufferSize); 00796 if (!This->Buffer) 00797 { 00798 /* not enough memory */ 00799 CloseHandle(This->hPin); 00800 HeapFree(GetProcessHeap(), 0, This->Buffer); 00801 HeapFree(GetProcessHeap(), 0, This->Format); 00802 HeapFree(GetProcessHeap(), 0, This); 00803 return DSERR_OUTOFMEMORY; 00804 } 00805 This->MixBufferSize = MixBufferSize; 00806 DPRINT1("MixBufferSize %u BufferSize %u\n", MixBufferSize, This->BufferSize); 00807 } 00808 00809 /* initialize capture buffer */ 00810 This->ref = 1; 00811 This->lpVtbl = &vt_DirectSoundCaptureBuffer8; 00812 This->Filter = Filter; 00813 This->State = KSSTATE_STOP; 00814 This->bLoop = TRUE; 00815 00816 RtlMoveMemory(This->Format, lpcDSBufferDesc->lpwfxFormat, FormatSize); 00817 00818 *OutBuffer = (LPDIRECTSOUNDCAPTUREBUFFER8)&This->lpVtbl; 00819 return DS_OK; 00820 } Generated on Sat May 26 2012 04:20:14 for ReactOS by
1.7.6.1
|