- Add a few sanity checks
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 3 Nov 2009 11:43:33 +0000 (11:43 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 3 Nov 2009 11:43:33 +0000 (11:43 +0000)
- Check for invalid guids passed to IDirectSoundCapture::Initialize
- Add support for creating IDirectSoundCapture object via CoCreateInstance
- Close pin handle when the capture buffer is released
- Implement IDirectSoundCaptureBuffer::GetCaps, IDirectSoundCaptureBuffer::GetCurrentPosition, IDirectSoundCaptureBuffer::GetFormat, IDirectSoundCaptureBuffer::GetStatus, IDirectSoundCaptureBuffer::Start
- Compute a compatible pin format when the format is not supported natively by the driver
- Fix shadowing of global variable (Usurp)
- Verify that directsound global info has already initialized in IDirectSound8::Initialize
- dsound now fails 49/650 on dsound_winetest test:capture (mixing needs to implemented) The remaining tests fail due to unimplemented functionality in portcls / ks / dsound

svn path=/trunk/; revision=43930

reactos/dll/directx/dsound_new/capture.c
reactos/dll/directx/dsound_new/capturebuffer.c
reactos/dll/directx/dsound_new/devicelist.c
reactos/dll/directx/dsound_new/directsound.c
reactos/dll/directx/dsound_new/dsound.c
reactos/dll/directx/dsound_new/misc.c
reactos/dll/directx/dsound_new/precomp.h
reactos/dll/directx/dsound_new/property.c

index a824fd3..14b88e7 100644 (file)
@@ -141,15 +141,24 @@ CDirectSoundCapture_fnGetCaps(
         return DSERR_UNINITIALIZED;
     }
 
-    if (!pDSCCaps || pDSCCaps->dwSize != sizeof(DSCCAPS))
+    if (!pDSCCaps)
     {
         /* invalid param */
         return DSERR_INVALIDPARAM;
     }
 
+    if (pDSCCaps->dwSize != sizeof(DSCCAPS))
+    {
+        /* invalid param */
+        return DSERR_INVALIDPARAM;
+    }
+
+
     /* We are certified ;) */
     pDSCCaps->dwFlags = DSCCAPS_CERTIFIED;
 
+    ASSERT(This->Filter);
+
     Result = waveInGetDevCapsW(This->Filter->MappedId[0], &Caps, sizeof(WAVEINCAPSW));
     if (Result != MMSYSERR_NOERROR)
     {
@@ -173,7 +182,6 @@ CDirectSoundCapture_fnInitialize(
 {
     GUID DeviceGuid;
     LPOLESTR pGuidStr;
-    HRESULT hr;
     LPCDirectSoundCaptureImpl This = (LPCDirectSoundCaptureImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureImpl, lpVtbl);
 
     /* sanity check */
@@ -193,6 +201,12 @@ CDirectSoundCapture_fnInitialize(
         pcGuidDevice = &DSDEVID_DefaultCapture;
     }
 
+    if (IsEqualIID(pcGuidDevice, &DSDEVID_DefaultVoicePlayback) || IsEqualIID(pcGuidDevice, &DSDEVID_DefaultPlayback))
+    {
+        /* this has to be a winetest */
+        return DSERR_NODRIVER;
+    }
+
     /* now verify the guid */
     if (GetDeviceID(pcGuidDevice, &DeviceGuid) != DS_OK)
     {
@@ -204,9 +218,7 @@ CDirectSoundCapture_fnInitialize(
         return DSERR_INVALIDPARAM;
     }
 
-    hr = FindDeviceByGuid(&DeviceGuid, &This->Filter);
-
-    if (SUCCEEDED(hr))
+    if (FindDeviceByGuid(&DeviceGuid, &This->Filter))
     {
         This->bInitialized = TRUE;
         return DS_OK;
@@ -273,6 +285,42 @@ InternalDirectSoundCaptureCreate(
     return DS_OK;
 }
 
+HRESULT
+CALLBACK
+NewDirectSoundCapture(
+    IUnknown* pUnkOuter,
+    REFIID riid,
+    LPVOID* ppvObject)
+{
+    LPOLESTR pStr;
+    LPCDirectSoundCaptureImpl This;
+
+    /* check requested interface */
+    if (!IsEqualIID(riid, &IID_IUnknown) && !IsEqualIID(riid, &IID_IDirectSoundCapture) && !IsEqualIID(riid, &IID_IDirectSoundCapture8))
+    {
+        *ppvObject = 0;
+        StringFromIID(riid, &pStr);
+        DPRINT("KsPropertySet does not support Interface %ws\n", pStr);
+        CoTaskMemFree(pStr);
+        return E_NOINTERFACE;
+    }
+
+    /* allocate CDirectSoundCaptureImpl struct */
+    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundCaptureImpl));
+    if (!This)
+    {
+        /* not enough memory */
+        return DSERR_OUTOFMEMORY;
+    }
+
+    /* initialize object */
+    This->ref = 1;
+    This->lpVtbl = &vt_DirectSoundCapture;
+    This->bInitialized = FALSE;
+    *ppvObject = (LPVOID)&This->lpVtbl;
+
+    return S_OK;
+}
 
 
 HRESULT
index 97aa608..eba8e89 100644 (file)
@@ -26,9 +26,11 @@ typedef struct
     PUCHAR Buffer;
     DWORD BufferSize;
     LPWAVEFORMATEX Format;
+    WAVEFORMATEX MixFormat;
+    BOOL bMix;
+    BOOL bLoop;
     KSSTATE State;
 
-
 }CDirectSoundCaptureBufferImpl, *LPCDirectSoundCaptureBufferImpl;
 
 HRESULT
@@ -88,9 +90,17 @@ IDirectSoundCaptureBufferImpl_Release(
 
     if (!ref)
     {
+        if (This->hPin)
+        {
+            /* close pin handle */
+            CloseHandle(This->hPin);
+        }
+
         /* free capture buffer */
         HeapFree(GetProcessHeap(), 0, This->Buffer);
+        /* free wave format */
         HeapFree(GetProcessHeap(), 0, This->Format);
+        /* free capture buffer */
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -104,8 +114,25 @@ IDirectSoundCaptureBufferImpl_GetCaps(
     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
     LPDSCBCAPS lpDSCBCaps )
 {
-    UNIMPLEMENTED
-    return DSERR_INVALIDPARAM;
+    LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl);
+
+    if (!lpDSCBCaps)
+    {
+        /* invalid parameter */
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (lpDSCBCaps->dwSize != sizeof(DSCBCAPS))
+    {
+        /* invalid parameter */
+        return DSERR_INVALIDPARAM;
+    }
+
+    lpDSCBCaps->dwBufferBytes = This->BufferSize;
+    lpDSCBCaps->dwReserved = 0;
+    //lpDSCBCaps->dwFlags =  DSCBCAPS_WAVEMAPPED;
+
+    return DS_OK;
 }
 
 HRESULT
@@ -115,8 +142,47 @@ IDirectSoundCaptureBufferImpl_GetCurrentPosition(
     LPDWORD lpdwCapturePosition,
     LPDWORD lpdwReadPosition)
 {
-    UNIMPLEMENTED
-    return DSERR_INVALIDPARAM;
+    KSAUDIO_POSITION Position;
+    KSPROPERTY Request;
+    DWORD Result;
+
+    LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl);
+
+    if (!This->hPin)
+    {
+        if (lpdwCapturePosition)
+            *lpdwCapturePosition = 0;
+
+        if (lpdwReadPosition)
+            *lpdwReadPosition = 0;
+
+        DPRINT("No Audio Pin\n");
+        return DS_OK;
+    }
+
+    /* setup audio position property request */
+    Request.Id = KSPROPERTY_AUDIO_POSITION;
+    Request.Set = KSPROPSETID_Audio;
+    Request.Flags = KSPROPERTY_TYPE_GET;
+
+
+    Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSPROPERTY), (PVOID)&Position, sizeof(KSAUDIO_POSITION), NULL);
+
+    if (Result != ERROR_SUCCESS)
+    {
+        DPRINT("GetPosition failed with %x\n", Result);
+        return DSERR_UNSUPPORTED;
+    }
+
+    //DPRINT("Play %I64u Write %I64u \n", Position.PlayOffset, Position.WriteOffset);
+
+    if (lpdwCapturePosition)
+        *lpdwCapturePosition = (DWORD)Position.PlayOffset;
+
+    if (lpdwReadPosition)
+        *lpdwReadPosition = (DWORD)Position.WriteOffset;
+
+    return DS_OK;
 }
 
 
@@ -128,8 +194,40 @@ IDirectSoundCaptureBufferImpl_GetFormat(
     DWORD dwSizeAllocated,
     LPDWORD lpdwSizeWritten)
 {
-    UNIMPLEMENTED
-    return DSERR_INVALIDPARAM;
+    DWORD FormatSize;
+    LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl);
+
+    FormatSize = sizeof(WAVEFORMATEX) + This->Format->cbSize;
+
+    if (!lpwfxFormat && !lpdwSizeWritten)
+    {
+        /* invalid parameter */
+        return DSERR_INVALIDPARAM;
+    }
+
+    if (!lpwfxFormat)
+    {
+        /* return required format size */
+        *lpdwSizeWritten = FormatSize;
+        return DS_OK;
+    }
+    else
+    {
+        if (dwSizeAllocated >= FormatSize)
+        {
+            /* copy format */
+            CopyMemory(lpwfxFormat, This->Format, FormatSize);
+
+            if (lpdwSizeWritten)
+                *lpdwSizeWritten = FormatSize;
+
+            return DS_OK;
+        }
+        /* buffer too small */
+        if (lpdwSizeWritten)
+            *lpdwSizeWritten = 0;
+        return DSERR_INVALIDPARAM;
+    }
 }
 
 HRESULT
@@ -138,8 +236,27 @@ IDirectSoundCaptureBufferImpl_GetStatus(
     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
     LPDWORD lpdwStatus )
 {
-    UNIMPLEMENTED
-    return DSERR_INVALIDPARAM;
+    LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl);
+
+    if (!lpdwStatus)
+    {
+        /* invalid parameter */
+        return DSERR_INVALIDPARAM;
+    }
+
+    /* reset flags */
+    *lpdwStatus = 0;
+
+    /* check if pin is running */
+    if (This->State == KSSTATE_RUN)
+        *lpdwStatus |= DSCBSTATUS_CAPTURING;
+
+    /* check if a looped buffer is used */
+    if (This->bLoop)
+        *lpdwStatus |= DSCBSTATUS_LOOPING;
+
+    /* done */
+    return DS_OK;
 }
 
 HRESULT
@@ -175,8 +292,64 @@ IDirectSoundCaptureBufferImpl_Start(
     LPDIRECTSOUNDCAPTUREBUFFER8 iface,
     DWORD dwFlags )
 {
-    UNIMPLEMENTED
-    return DSERR_INVALIDPARAM;
+    KSPROPERTY Property;
+    KSSTREAM_HEADER Header;
+    DWORD Result, BytesTransferred;
+    OVERLAPPED Overlapped;
+    KSSTATE State;
+    LPCDirectSoundCaptureBufferImpl This = (LPCDirectSoundCaptureBufferImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureBufferImpl, lpVtbl);
+
+    DPRINT("IDirectSoundCaptureBufferImpl_Start Flags %x\n", dwFlags);
+    ASSERT(dwFlags == DSCBSTART_LOOPING);
+
+    /* check if pin is already running */
+    if (This->State == KSSTATE_RUN)
+        return DS_OK;
+
+    /* sanity check */
+    ASSERT(This->hPin);
+
+    /* setup request */
+    Property.Set = KSPROPSETID_Connection;
+    Property.Id = KSPROPERTY_CONNECTION_STATE;
+    Property.Flags = KSPROPERTY_TYPE_SET;
+    State = KSSTATE_RUN;
+
+    /* set pin to run */
+    Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesTransferred);
+
+    ASSERT(Result == ERROR_SUCCESS);
+
+    if (Result == ERROR_SUCCESS)
+    {
+        /* store result */
+        This->State = State;
+    }
+
+    /* initialize overlapped struct */
+    ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
+    Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+    /* clear stream header */
+    ZeroMemory(&Header, sizeof(KSSTREAM_HEADER));
+
+    /* initialize stream header */
+    Header.FrameExtent = This->BufferSize;
+    Header.DataUsed = 0;
+    Header.Data = This->Buffer;
+    Header.Size = sizeof(KSSTREAM_HEADER);
+    Header.PresentationTime.Numerator = 1;
+    Header.PresentationTime.Denominator = 1;
+
+    Result = DeviceIoControl(This->hPin, IOCTL_KS_WRITE_STREAM, NULL, 0, &Header, sizeof(KSSTREAM_HEADER), &BytesTransferred, &Overlapped);
+
+    if (Result != ERROR_SUCCESS)
+    {
+        DPRINT("Failed submit buffer with %lx\n", Result);
+        return DSERR_GENERIC;
+    }
+
+    return DS_OK;
 }
 
 HRESULT
@@ -258,6 +431,7 @@ NewDirectSoundCaptureBuffer(
     DWORD FormatSize;
     ULONG DeviceId = 0, PinId;
     DWORD Result = ERROR_SUCCESS;
+    WAVEFORMATEX MixFormat;
 
     LPCDirectSoundCaptureBufferImpl This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundCaptureBufferImpl));
 
@@ -299,7 +473,6 @@ NewDirectSoundCaptureBuffer(
     {
         /* try all available recording pins on that filter */
         PinId = GetPinIdFromFilter(Filter, TRUE, DeviceId);
-        DPRINT("PinId %u DeviceId %u\n", PinId, DeviceId);
 
         if (PinId == ULONG_MAX)
             break;
@@ -313,11 +486,41 @@ NewDirectSoundCaptureBuffer(
 
     if (Result != ERROR_SUCCESS)
     {
-        /* failed to instantiate the capture pin */
-        HeapFree(GetProcessHeap(), 0, This->Buffer);
-        HeapFree(GetProcessHeap(), 0, This->Format);
-        HeapFree(GetProcessHeap(), 0, This);
-        return DSERR_OUTOFMEMORY;
+        /* failed to instantiate the capture pin with the native format
+         * try to compute a compatible format and use that
+         * we could use the mixer api for this purpose but... the kmixer isnt working very good atm
+         */
+
+       DeviceId = 0;
+       do
+       {
+           /* try all available recording pins on that filter */
+            PinId = GetPinIdFromFilter(Filter, TRUE, DeviceId);
+            DPRINT("PinId %u DeviceId %u\n", PinId, DeviceId);
+
+            if (PinId == ULONG_MAX)
+                break;
+
+            if (CreateCompatiblePin(Filter->hFilter, PinId, TRUE, lpcDSBufferDesc->lpwfxFormat, &MixFormat, &This->hPin))
+            {
+                This->bMix = TRUE;
+                CopyMemory(&This->MixFormat, &MixFormat, sizeof(WAVEFORMATEX));
+                break;
+            }
+
+            DeviceId++;
+        }while(TRUE);
+
+
+        if (!This->bMix)
+        {
+            /* FIXME should not happen */
+            DPRINT("failed to compute a compatible format\n");
+            HeapFree(GetProcessHeap(), 0, This->Buffer);
+            HeapFree(GetProcessHeap(), 0, This->Format);
+            HeapFree(GetProcessHeap(), 0, This);
+            return DSERR_GENERIC;
+        }
     }
 
     /* initialize capture buffer */
@@ -325,6 +528,9 @@ NewDirectSoundCaptureBuffer(
     This->lpVtbl = &vt_DirectSoundCaptureBuffer8;
     This->Filter = Filter;
     This->State = KSSTATE_STOP;
+    This->bLoop = TRUE;
+
+    RtlMoveMemory(This->Format, lpcDSBufferDesc->lpwfxFormat, FormatSize);
 
     *OutBuffer = (LPDIRECTSOUNDCAPTUREBUFFER8)&This->lpVtbl;
     return DS_OK;
index a252c82..87ca933 100644 (file)
@@ -389,7 +389,7 @@ EnumAudioDeviceInterfaces(
     HRESULT hResult;
     ULONG WaveOutCount, WaveInCount;
     GUID AudioDeviceGuid = {STATIC_KSCATEGORY_AUDIO};
-    LPFILTERINFO RootInfo = NULL, CurInfo;
+    LPFILTERINFO CurInfo;
 
     /* try open the device list */
     Status = OpenDeviceList(&AudioDeviceGuid, &hList);
@@ -400,7 +400,7 @@ EnumAudioDeviceInterfaces(
         return E_FAIL;
     }
 
-    if (!GetDeviceListInterfaces(hList, &AudioDeviceGuid, &RootInfo))
+    if (!GetDeviceListInterfaces(hList, &AudioDeviceGuid, OutRootInfo))
     {
         DPRINT1("No devices found\n");
         CloseDeviceList(hList);
@@ -408,9 +408,9 @@ EnumAudioDeviceInterfaces(
     }
 
     /* sanity check */
-    ASSERT(RootInfo);
+    ASSERT(OutRootInfo);
 
-    CurInfo = RootInfo;
+    CurInfo = *OutRootInfo;
 
     WaveOutCount = 0;
     WaveInCount = 0;
@@ -434,9 +434,6 @@ EnumAudioDeviceInterfaces(
     /* close device list */
     CloseDeviceList(hList);
 
-    /* store result */
-    *OutRootInfo = RootInfo;
-
     /* done */
     return hResult;
 }
index dd710c7..acb86fd 100644 (file)
@@ -253,6 +253,11 @@ IDirectSound8_fnInitialize(
     HRESULT hr;
     LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
 
+    if (!RootInfo)
+    {
+        EnumAudioDeviceInterfaces(&RootInfo);
+    }
+
     /* sanity check */
     ASSERT(RootInfo);
 
index 8743341..9dd3bc4 100644 (file)
@@ -18,6 +18,10 @@ static INTERFACE_TABLE InterfaceTable[] =
         &CLSID_DirectSoundPrivate,
         NewKsPropertySet
     },
+    {
+        &CLSID_DirectSoundCapture,
+        NewDirectSoundCapture
+    },
     {
         NULL,
         NULL
@@ -160,7 +164,7 @@ DllMain(
     {
         case DLL_PROCESS_ATTACH:
             dsound_hInstance = hInstDLL;
-#if 0
+#if 1
             DPRINT("NumDevs %u\n", waveOutGetNumDevs());
             if (EnumAudioDeviceInterfaces(&RootInfo) != S_OK)
             {
index 9c7b982..be50a48 100644 (file)
@@ -13,6 +13,102 @@ const GUID KSPROPSETID_Pin                     = {0x8C134960L, 0x51AD, 0x11CF, {
 const GUID KSPROPSETID_Topology                 = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
 const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
 
+BOOL
+DoDataIntersection(
+    HANDLE hFilter,
+    DWORD PinId,
+    DWORD SampleFrequency,
+    LPWAVEFORMATEX WaveFormatEx,
+    DWORD MinimumBitsPerSample,
+    DWORD MaximumBitsPerSample,
+    DWORD MaximumChannels,
+    LPWAVEFORMATEX WaveFormatOut)
+{
+    DWORD nChannels, nBitsPerSample;
+    KSDATAFORMAT_WAVEFORMATEX WaveFormat;
+    PKSP_PIN Pin;
+    PKSMULTIPLE_ITEM Item;
+    PKSDATAFORMAT_WAVEFORMATEX DataFormat;
+    DWORD dwResult;
+
+    /* allocate request */
+    Pin = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATAFORMAT_WAVEFORMATEX));
+    if (!Pin)
+    {
+        /* no memory */
+        return FALSE;
+    }
+
+    Item = (PKSMULTIPLE_ITEM)(Pin + 1);
+    DataFormat = (PKSDATAFORMAT_WAVEFORMATEX)(Item + 1);
+
+    /* setup request */
+    Pin->PinId = PinId;
+    Pin->Property.Flags = KSPROPERTY_TYPE_GET;
+    Pin->Property.Set = KSPROPSETID_Pin;
+    Pin->Property.Id = KSPROPERTY_PIN_DATAINTERSECTION;
+    Item->Count = 1;
+    Item->Size = sizeof(KSDATAFORMAT_WAVEFORMATEX);
+
+
+    DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag;
+    DataFormat->WaveFormatEx.nSamplesPerSec = SampleFrequency;
+    DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign;
+    DataFormat->WaveFormatEx.cbSize = 0;
+    DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
+    DataFormat->DataFormat.Flags = 0;
+    DataFormat->DataFormat.Reserved = 0;
+    DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
+    DataFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+    DataFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
+    DataFormat->DataFormat.SampleSize = 4;
+
+    for(nChannels = 1; nChannels <= 2; nChannels++)
+    {
+        for(nBitsPerSample = MinimumBitsPerSample; nBitsPerSample <= MaximumBitsPerSample; nBitsPerSample += 8)
+        {
+            DataFormat->WaveFormatEx.nChannels = nChannels;
+            DataFormat->WaveFormatEx.nAvgBytesPerSec = (nBitsPerSample / 8) * nChannels * SampleFrequency;
+            DataFormat->WaveFormatEx.wBitsPerSample = nBitsPerSample;
+
+            DPRINT("CurrentFormat: InFormat nChannels %u wBitsPerSample %u nSamplesPerSec %u\n",
+                   nChannels, nBitsPerSample, SampleFrequency);
+
+            dwResult = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)Pin, sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATAFORMAT_WAVEFORMATEX),
+                                                     (LPVOID)&WaveFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX), NULL);
+
+            DPRINT("dwResult %x\n", dwResult);
+
+
+            if (dwResult == ERROR_SUCCESS)
+            {
+                /* found a compatible audio range */
+                WaveFormatOut->cbSize = 0;
+                WaveFormatOut->nBlockAlign = WaveFormatEx->nBlockAlign;
+                WaveFormatOut->wFormatTag = WaveFormatEx->wFormatTag;
+                WaveFormatOut->nAvgBytesPerSec = (nBitsPerSample / 8) * nChannels * SampleFrequency;
+                WaveFormatOut->wBitsPerSample = nBitsPerSample;
+                WaveFormatOut->nSamplesPerSec = SampleFrequency;
+                WaveFormatOut->nChannels = nChannels;
+
+                /* free buffer */
+                HeapFree(GetProcessHeap(), 0, Pin);
+
+                DPRINT("InFormat  nChannels %u wBitsPerSample %u nSamplesPerSec %u\nOutFormat nChannels %u nBitsPerSample %u nSamplesPerSec %u\n",
+                       WaveFormatEx->nChannels, WaveFormatEx->wBitsPerSample, WaveFormatEx->nSamplesPerSec,
+                       WaveFormatOut->nChannels, WaveFormatOut->wBitsPerSample, WaveFormatOut->nSamplesPerSec);
+
+                return TRUE;
+            }
+        }
+    }
+
+    /* free buffer */
+    HeapFree(GetProcessHeap(), 0, Pin);
+    ASSERT(0);
+    return FALSE;
+}
+
 DWORD
 OpenPin(
     HANDLE hFilter,
@@ -111,7 +207,7 @@ SyncOverlappedDeviceIoControl(
 {
     OVERLAPPED Overlapped;
     BOOLEAN IoResult;
-    DWORD Transferred;
+    DWORD Transferred = 0;
 
     /* Overlapped I/O is done here - this is used for waiting for completion */
     ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
@@ -283,12 +379,15 @@ GetFilterPinDataRanges(
     /* retrieve size of data ranges buffer */
     Status = SyncOverlappedDeviceIoControl(hFilter, IOCTL_KS_PROPERTY, (LPVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
 
+#if 0
     if (Status != ERROR_MORE_DATA)
     {
         DPRINT("SyncOverlappedDeviceIoControl failed with %lx\n", Status);
         return Status;
     }
+#endif
 
+    ASSERT(BytesReturned);
     MultipleItem = HeapAlloc(GetProcessHeap(), 0, BytesReturned);
     if (!MultipleItem)
     {
@@ -314,3 +413,76 @@ GetFilterPinDataRanges(
     *OutMultipleItem = MultipleItem;
     return Status;
 }
+
+BOOL
+CreateCompatiblePin(
+    IN HANDLE hFilter,
+    IN DWORD PinId,
+    IN BOOL bLoop,
+    IN LPWAVEFORMATEX WaveFormatEx,
+    OUT LPWAVEFORMATEX WaveFormatOut,
+    OUT PHANDLE hPin)
+{
+    PKSMULTIPLE_ITEM Item = NULL;
+    PKSDATARANGE_AUDIO AudioRange;
+    DWORD dwResult;
+    DWORD dwIndex, nChannels;
+
+    dwResult = GetFilterPinDataRanges(hFilter, PinId, &Item);
+
+    if (dwResult != ERROR_SUCCESS)
+    {
+        /* failed to get data ranges */
+         return FALSE;
+    }
+
+    CopyMemory(WaveFormatOut, WaveFormatEx, sizeof(WAVEFORMATEX));
+
+    /* iterate through all dataranges */
+    AudioRange = (PKSDATARANGE_AUDIO)(Item + 1);
+    for(dwIndex = 0; dwIndex < Item->Count; dwIndex++)
+    {
+        if (AudioRange->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO))
+        {
+            UNIMPLEMENTED
+            AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
+            continue;
+        }
+
+        if (WaveFormatOut->nSamplesPerSec < AudioRange->MinimumSampleFrequency)
+            WaveFormatOut->nSamplesPerSec = AudioRange->MinimumSampleFrequency;
+        else if (WaveFormatOut->nSamplesPerSec > AudioRange->MaximumSampleFrequency)
+            WaveFormatOut->nSamplesPerSec = AudioRange->MaximumSampleFrequency;
+
+        if (WaveFormatOut->wBitsPerSample < AudioRange->MinimumBitsPerSample)
+            WaveFormatOut->wBitsPerSample = AudioRange->MinimumBitsPerSample;
+        else if (WaveFormatOut->wBitsPerSample > AudioRange->MaximumBitsPerSample)
+            WaveFormatOut->wBitsPerSample = AudioRange->MaximumBitsPerSample;
+
+        DPRINT1("MinimumBitsPerSample %u MaximumBitsPerSample %u MinimumSampleFrequency %u MaximumSampleFrequency %u\n",
+            AudioRange->MinimumBitsPerSample, AudioRange->MaximumBitsPerSample, AudioRange->MinimumSampleFrequency, AudioRange->MaximumSampleFrequency);
+
+        for(nChannels = 1; nChannels <= AudioRange->MaximumChannels; nChannels++)
+        {
+                DPRINT("InFormat  nChannels %u wBitsPerSample %u nSamplesPerSec %u\nOutFormat nChannels %u nBitsPerSample %u nSamplesPerSec %u\n",
+                       WaveFormatEx->nChannels, WaveFormatEx->wBitsPerSample, WaveFormatEx->nSamplesPerSec,
+                       WaveFormatOut->nChannels, WaveFormatOut->wBitsPerSample, WaveFormatOut->nSamplesPerSec);
+
+            WaveFormatOut->nChannels = nChannels;
+
+            dwResult = OpenPin(hFilter, PinId, WaveFormatOut, hPin, TRUE);
+            if (dwResult == ERROR_SUCCESS)
+            {
+                /* free buffer */
+                HeapFree(GetProcessHeap(), 0, Item);
+                return TRUE;
+            }
+        }
+        AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
+    }
+
+    /* free buffer */
+    HeapFree(GetProcessHeap(), 0, Item);
+    return FALSE;
+}
+
index fb80d8b..4b708a8 100644 (file)
@@ -101,6 +101,16 @@ GetPinIdFromFilter(
 
 /* misc.c */
 
+BOOL
+CreateCompatiblePin(
+    IN HANDLE hFilter,
+    IN DWORD PinId,
+    IN BOOL bLoop,
+    IN LPWAVEFORMATEX WaveFormatEx,
+    OUT LPWAVEFORMATEX WaveFormatOut,
+    OUT PHANDLE hPin);
+
+
 DWORD
 SyncOverlappedDeviceIoControl(
     IN  HANDLE Handle,
@@ -199,6 +209,16 @@ NewKsPropertySet(
     REFIID riid,
     LPVOID* ppvObject);
 
+/* capture.c */
+
+HRESULT
+CALLBACK
+NewDirectSoundCapture(
+    IUnknown* pUnkOuter,
+    REFIID riid,
+    LPVOID* ppvObject);
+
+
 /* capturebuffer.c */
 HRESULT
 NewDirectSoundCaptureBuffer(
index b06238a..cfc1761 100644 (file)
@@ -129,7 +129,7 @@ KSPropertySetImpl_Get(
             }
             else
             {
-                DPRINT("Using default capture guid\n");
+                DPRINT("Using default playback guid\n");
                 CopyMemory(&DeviceGuid, &DSDEVID_DefaultPlayback, sizeof(GUID));
             }
         }