mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
- Add a few sanity checks
- 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
This commit is contained in:
parent
56a64b9357
commit
7b50f75936
8 changed files with 484 additions and 32 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -253,6 +253,11 @@ IDirectSound8_fnInitialize(
|
|||
HRESULT hr;
|
||||
LPCDirectSoundImpl This = (LPCDirectSoundImpl)CONTAINING_RECORD(iface, CDirectSoundImpl, lpVtbl);
|
||||
|
||||
if (!RootInfo)
|
||||
{
|
||||
EnumAudioDeviceInterfaces(&RootInfo);
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(RootInfo);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue