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

capturebuffer.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 doxygen 1.7.6.1

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