mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
[DSOUND]
- Add more checks IDirectSoundCapture::CreateCaptureBuffer - Implement IDirectSoundNotify interface - Needs work from ks / portcls to work on formats supported natively by the driver svn path=/trunk/; revision=43997
This commit is contained in:
parent
c20bd4216f
commit
0abe48a157
5 changed files with 311 additions and 12 deletions
|
@ -18,7 +18,6 @@ typedef struct
|
|||
LPFILTERINFO Filter;
|
||||
}CDirectSoundCaptureImpl, *LPCDirectSoundCaptureImpl;
|
||||
|
||||
|
||||
HRESULT
|
||||
WINAPI
|
||||
CDirectSoundCapture_fnQueryInterface(
|
||||
|
@ -100,25 +99,20 @@ CDirectSoundCapture_fnCreateCaptureBuffer(
|
|||
|
||||
if (!lpcDSBufferDesc || !ppDSCBuffer || pUnkOuter != NULL)
|
||||
{
|
||||
DPRINT("Invalid parameter %p %p %p\n", lpcDSBufferDesc, ppDSCBuffer, pUnkOuter);
|
||||
/* invalid param */
|
||||
return DSERR_INVALIDPARAM;
|
||||
}
|
||||
|
||||
/* check buffer description */
|
||||
if ((lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC) && lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC1)) || lpcDSBufferDesc->dwReserved != 0)
|
||||
if ((lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC) && lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC1)) ||
|
||||
lpcDSBufferDesc->dwReserved != 0 || lpcDSBufferDesc->dwBufferBytes == 0 || lpcDSBufferDesc->lpwfxFormat == NULL)
|
||||
{
|
||||
DPRINT("Invalid buffer description size %u expected %u or %u dwReserved %u\n", lpcDSBufferDesc->dwSize, sizeof(DSBUFFERDESC1), sizeof(DSBUFFERDESC), lpcDSBufferDesc->dwReserved);
|
||||
/* invalid buffer description */
|
||||
return DSERR_INVALIDPARAM;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(lpcDSBufferDesc->lpwfxFormat);
|
||||
|
||||
if (lpcDSBufferDesc->lpwfxFormat)
|
||||
{
|
||||
DPRINT("This %p wFormatTag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u NBlockAlign %u wBitsPerSample %u cbSize %u\n",
|
||||
This, lpcDSBufferDesc->lpwfxFormat->wFormatTag, lpcDSBufferDesc->lpwfxFormat->nChannels, lpcDSBufferDesc->lpwfxFormat->nSamplesPerSec, lpcDSBufferDesc->lpwfxFormat->nAvgBytesPerSec, lpcDSBufferDesc->lpwfxFormat->nBlockAlign, lpcDSBufferDesc->lpwfxFormat->wBitsPerSample, lpcDSBufferDesc->lpwfxFormat->cbSize);
|
||||
}
|
||||
DPRINT("This %p wFormatTag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u NBlockAlign %u wBitsPerSample %u cbSize %u\n",
|
||||
This, lpcDSBufferDesc->lpwfxFormat->wFormatTag, lpcDSBufferDesc->lpwfxFormat->nChannels, lpcDSBufferDesc->lpwfxFormat->nSamplesPerSec, lpcDSBufferDesc->lpwfxFormat->nAvgBytesPerSec, lpcDSBufferDesc->lpwfxFormat->nBlockAlign, lpcDSBufferDesc->lpwfxFormat->wBitsPerSample, lpcDSBufferDesc->lpwfxFormat->cbSize);
|
||||
|
||||
hResult = NewDirectSoundCaptureBuffer((LPDIRECTSOUNDCAPTUREBUFFER8*)ppDSCBuffer, This->Filter, lpcDSBufferDesc);
|
||||
return hResult;
|
||||
|
|
|
@ -15,11 +15,14 @@ const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF,
|
|||
const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
|
||||
const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
|
||||
const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
|
||||
const GUID KSEVENTSETID_LoopedStreaming = {0x4682B940L, 0xC6EF, 0x11D0, {0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D}};
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IDirectSoundCaptureBuffer8Vtbl *lpVtbl;
|
||||
|
||||
LONG ref;
|
||||
LPFILTERINFO Filter;
|
||||
HANDLE hPin;
|
||||
|
@ -36,6 +39,8 @@ typedef struct
|
|||
volatile LONG StopMixerThread;
|
||||
volatile LONG CurrentMixPosition;
|
||||
|
||||
LPDIRECTSOUNDNOTIFY Notify;
|
||||
|
||||
}CDirectSoundCaptureBufferImpl, *LPCDirectSoundCaptureBufferImpl;
|
||||
|
||||
DWORD
|
||||
|
@ -108,6 +113,13 @@ MixerThreadRoutine(
|
|||
BufferPosition += BytesWritten;
|
||||
DPRINT("MixPosition %u BufferPosition %u BytesRead %u BytesWritten %u MixLength %u BufferLength %u\n", MixPosition, BufferPosition, BytesRead, BytesWritten, MixLength, BufferLength);
|
||||
}
|
||||
|
||||
/* Notify Events */
|
||||
if (This->Notify)
|
||||
{
|
||||
DoNotifyPositionEvents(This->Notify, This->CurrentMixPosition, BufferPosition);
|
||||
}
|
||||
|
||||
/* update offset */
|
||||
InterlockedExchange(&This->CurrentMixPosition, (LONG)BufferPosition);
|
||||
|
||||
|
@ -146,6 +158,25 @@ IDirectSoundCaptureBufferImpl_QueryInterface(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
/* check if the interface is supported */
|
||||
if (IsEqualIID(riid, &IID_IDirectSoundNotify))
|
||||
{
|
||||
if (!This->Notify)
|
||||
{
|
||||
HRESULT hr = NewDirectSoundNotify(&This->Notify, This->bLoop, This->bMix, This->hPin, This->BufferSize);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
*ppobj = (LPVOID)This->Notify;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* increment reference count on existing notify object */
|
||||
IDirectSoundNotify_AddRef(This->Notify);
|
||||
*ppobj = (LPVOID)This->Notify;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* interface not supported */
|
||||
if (SUCCEEDED(StringFromIID(riid, &pStr)))
|
||||
{
|
||||
|
@ -650,6 +681,8 @@ static IDirectSoundCaptureBuffer8Vtbl vt_DirectSoundCaptureBuffer8 =
|
|||
};
|
||||
|
||||
|
||||
|
||||
|
||||
HRESULT
|
||||
NewDirectSoundCaptureBuffer(
|
||||
LPDIRECTSOUNDCAPTUREBUFFER8 *OutBuffer,
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<file>dsound.c</file>
|
||||
<file>enum.c</file>
|
||||
<file>misc.c</file>
|
||||
<file>notify.c</file>
|
||||
<file>primary.c</file>
|
||||
<file>property.c</file>
|
||||
<file>regsvr.c</file>
|
||||
|
|
256
reactos/dll/directx/dsound_new/notify.c
Normal file
256
reactos/dll/directx/dsound_new/notify.c
Normal file
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS Configuration of network devices
|
||||
* FILE: dll/directx/dsound_new/notify.c
|
||||
* PURPOSE: IDirectSoundNotify implementation
|
||||
*
|
||||
* PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
|
||||
*/
|
||||
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
typedef struct tagNOTIFYEVENT
|
||||
{
|
||||
DWORD NotifyCount;
|
||||
PLOOPEDSTREAMING_POSITION_EVENT_DATA Notify;
|
||||
struct tagNOTIFYEVENT *lpNext;
|
||||
}NOTIFYEVENT, *LPNOTIFYEVENT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IDirectSoundNotifyVtbl * lpVtbl;
|
||||
LONG ref;
|
||||
|
||||
LPNOTIFYEVENT EventListHead;
|
||||
BOOL bLoop;
|
||||
BOOL bMix;
|
||||
HANDLE hPin;
|
||||
DWORD BufferSize;
|
||||
|
||||
}CDirectSoundNotifyImpl, *LPCDirectSoundNotifyImpl;
|
||||
|
||||
static
|
||||
ULONG
|
||||
WINAPI
|
||||
IDirectSoundNotify_fnAddRef(
|
||||
LPDIRECTSOUNDNOTIFY iface)
|
||||
{
|
||||
ULONG ref;
|
||||
LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
|
||||
|
||||
/* increment reference count */
|
||||
ref = InterlockedIncrement(&This->ref);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
static
|
||||
ULONG
|
||||
WINAPI
|
||||
IDirectSoundNotify_fnRelease(
|
||||
LPDIRECTSOUNDNOTIFY iface)
|
||||
{
|
||||
ULONG ref;
|
||||
LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
|
||||
|
||||
ref = InterlockedDecrement(&(This->ref));
|
||||
|
||||
if (!ref)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
WINAPI
|
||||
IDirectSoundNotify_fnQueryInterface(
|
||||
LPDIRECTSOUNDNOTIFY iface,
|
||||
IN REFIID riid,
|
||||
LPVOID* ppobj)
|
||||
{
|
||||
LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
|
||||
|
||||
/* check if the interface is supported */
|
||||
if (IsEqualIID(riid, &IID_IDirectSoundNotify) || IsEqualIID(riid, &IID_IUnknown))
|
||||
{
|
||||
*ppobj = (LPVOID)&This->lpVtbl;
|
||||
InterlockedIncrement(&This->ref);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
WINAPI
|
||||
IDirectSoundNotify_fnSetNotificationPositions(
|
||||
LPDIRECTSOUNDNOTIFY iface,
|
||||
DWORD dwPositionNotifies,
|
||||
LPCDSBPOSITIONNOTIFY pcPositionNotifies)
|
||||
{
|
||||
DWORD Index;
|
||||
LPNOTIFYEVENT Notify;
|
||||
DWORD Result;
|
||||
KSEVENT Request;
|
||||
|
||||
LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
|
||||
|
||||
if (dwPositionNotifies > DSBNOTIFICATIONS_MAX)
|
||||
{
|
||||
/* invalid param */
|
||||
return DSERR_INVALIDPARAM;
|
||||
}
|
||||
|
||||
/* verify notification event handles */
|
||||
for(Index = 0; Index < dwPositionNotifies; Index++)
|
||||
{
|
||||
ASSERT(pcPositionNotifies[Index].hEventNotify);
|
||||
ASSERT(pcPositionNotifies[Index].dwOffset < This->BufferSize || pcPositionNotifies[Index].dwOffset != DSBPN_OFFSETSTOP);
|
||||
|
||||
if (pcPositionNotifies[Index].hEventNotify == NULL)
|
||||
return DSERR_INVALIDPARAM;
|
||||
|
||||
if (pcPositionNotifies[Index].dwOffset > This->BufferSize && pcPositionNotifies[Index].dwOffset != DSBPN_OFFSETSTOP)
|
||||
return DSERR_INVALIDPARAM;
|
||||
}
|
||||
|
||||
/* allocate new array */
|
||||
Notify = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFYEVENT));
|
||||
if (!Notify)
|
||||
{
|
||||
/* not enough memory */
|
||||
return DSERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
/* allocate new array */
|
||||
Notify->Notify = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwPositionNotifies * sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA));
|
||||
if (!Notify->Notify)
|
||||
{
|
||||
/* not enough memory */
|
||||
HeapFree(GetProcessHeap(), 0, Notify);
|
||||
return DSERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
/* FIXME support non-looped streaming */
|
||||
ASSERT(This->bLoop);
|
||||
|
||||
/* prepare request */
|
||||
Request.Set = KSEVENTSETID_LoopedStreaming;
|
||||
Request.Id = KSEVENT_LOOPEDSTREAMING_POSITION;
|
||||
Request.Flags = KSEVENT_TYPE_ENABLE;
|
||||
|
||||
for(Index = 0; Index < dwPositionNotifies; Index++)
|
||||
{
|
||||
/* initialize event entries */
|
||||
Notify->Notify[Index].Position = pcPositionNotifies[Index].dwOffset;
|
||||
Notify->Notify[Index].KsEventData.EventHandle.Event = pcPositionNotifies[Index].hEventNotify;
|
||||
Notify->Notify[Index].KsEventData.NotificationType = KSEVENTF_EVENT_HANDLE;
|
||||
|
||||
if (This->bMix == FALSE)
|
||||
{
|
||||
/* format is supported natively */
|
||||
Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Request, sizeof(KSEVENT), (PVOID)&Notify->Notify[Index], sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA), NULL);
|
||||
|
||||
if (Result != ERROR_SUCCESS)
|
||||
{
|
||||
DPRINT1("Failed to enable event %p Position %u\n", pcPositionNotifies[Index].hEventNotify, pcPositionNotifies[Index].dwOffset);
|
||||
return DSERR_GENERIC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* enlarge notify count */
|
||||
Notify->NotifyCount = dwPositionNotifies;
|
||||
|
||||
if (This->EventListHead)
|
||||
{
|
||||
Notify->lpNext = This->EventListHead;
|
||||
}
|
||||
|
||||
/* insert at front */
|
||||
(void)InterlockedExchangePointer((LPVOID*)&This->EventListHead, Notify);
|
||||
|
||||
return DS_OK;
|
||||
}
|
||||
|
||||
static IDirectSoundNotifyVtbl vt_DirectSoundNotify =
|
||||
{
|
||||
/* IUnknown methods */
|
||||
IDirectSoundNotify_fnQueryInterface,
|
||||
IDirectSoundNotify_fnAddRef,
|
||||
IDirectSoundNotify_fnRelease,
|
||||
/* IDirectSoundNotify */
|
||||
IDirectSoundNotify_fnSetNotificationPositions
|
||||
};
|
||||
|
||||
|
||||
VOID
|
||||
DoNotifyPositionEvents(
|
||||
LPDIRECTSOUNDNOTIFY iface,
|
||||
DWORD OldPosition,
|
||||
DWORD NewPosition)
|
||||
{
|
||||
DWORD Index;
|
||||
LPNOTIFYEVENT CurEventList;
|
||||
|
||||
LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
|
||||
|
||||
CurEventList = This->EventListHead;
|
||||
|
||||
while(CurEventList)
|
||||
{
|
||||
for(Index = 0; Index < CurEventList->NotifyCount; Index++)
|
||||
{
|
||||
if (NewPosition > OldPosition)
|
||||
{
|
||||
/* buffer progress no overlap */
|
||||
if (OldPosition < CurEventList->Notify[Index].Position && CurEventList->Notify[Index].Position <= NewPosition)
|
||||
{
|
||||
/* process event */
|
||||
SetEvent(CurEventList->Notify[Index].KsEventData.EventHandle.Event);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* buffer wrap-arround */
|
||||
if (OldPosition < CurEventList->Notify[Index].Position || NewPosition > CurEventList->Notify[Index].Position)
|
||||
{
|
||||
/* process event */
|
||||
SetEvent(CurEventList->Notify[Index].KsEventData.EventHandle.Event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* iterate to next event list */
|
||||
CurEventList = CurEventList->lpNext;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
NewDirectSoundNotify(
|
||||
LPDIRECTSOUNDNOTIFY * Notify,
|
||||
BOOL bLoop,
|
||||
BOOL bMix,
|
||||
HANDLE hPin,
|
||||
DWORD BufferSize)
|
||||
{
|
||||
LPCDirectSoundNotifyImpl This = HeapAlloc(GetProcessHeap(), 0, sizeof(CDirectSoundNotifyImpl));
|
||||
|
||||
if (!This)
|
||||
return DSERR_OUTOFMEMORY;
|
||||
|
||||
This->lpVtbl = &vt_DirectSoundNotify;
|
||||
This->bLoop = bLoop;
|
||||
This->bMix = bMix;
|
||||
This->hPin = hPin;
|
||||
This->ref = 1;
|
||||
This->EventListHead = NULL;
|
||||
This->BufferSize = BufferSize;
|
||||
|
||||
*Notify = (LPDIRECTSOUNDNOTIFY)&This->lpVtbl;
|
||||
return DS_OK;
|
||||
|
||||
}
|
|
@ -252,4 +252,19 @@ NewDirectSoundCaptureBuffer(
|
|||
LPFILTERINFO Filter,
|
||||
LPCDSCBUFFERDESC lpcDSBufferDesc);
|
||||
|
||||
/* notify.c */
|
||||
VOID
|
||||
DoNotifyPositionEvents(
|
||||
LPDIRECTSOUNDNOTIFY iface,
|
||||
DWORD OldPosition,
|
||||
DWORD NewPosition);
|
||||
|
||||
HRESULT
|
||||
NewDirectSoundNotify(
|
||||
LPDIRECTSOUNDNOTIFY * Notify,
|
||||
BOOL bLoop,
|
||||
BOOL bMix,
|
||||
HANDLE hPin,
|
||||
DWORD BufferSize);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue