mirror of
https://github.com/reactos/reactos.git
synced 2024-08-26 21:28:48 +00:00
256 lines
6.9 KiB
C
256 lines
6.9 KiB
C
/*
|
|
* 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 (johannes.anderwald@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);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 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;
|
|
|
|
}
|