1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3*c2c66affSColin Finck * PROJECT: ReactOS Configuration of network devices
4*c2c66affSColin Finck * FILE: dll/directx/dsound_new/notify.c
5*c2c66affSColin Finck * PURPOSE: IDirectSoundNotify implementation
6*c2c66affSColin Finck *
7*c2c66affSColin Finck * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
8*c2c66affSColin Finck */
9*c2c66affSColin Finck
10*c2c66affSColin Finck
11*c2c66affSColin Finck #include "precomp.h"
12*c2c66affSColin Finck
13*c2c66affSColin Finck typedef struct tagNOTIFYEVENT
14*c2c66affSColin Finck {
15*c2c66affSColin Finck DWORD NotifyCount;
16*c2c66affSColin Finck PLOOPEDSTREAMING_POSITION_EVENT_DATA Notify;
17*c2c66affSColin Finck struct tagNOTIFYEVENT *lpNext;
18*c2c66affSColin Finck }NOTIFYEVENT, *LPNOTIFYEVENT;
19*c2c66affSColin Finck
20*c2c66affSColin Finck typedef struct
21*c2c66affSColin Finck {
22*c2c66affSColin Finck IDirectSoundNotifyVtbl * lpVtbl;
23*c2c66affSColin Finck LONG ref;
24*c2c66affSColin Finck
25*c2c66affSColin Finck LPNOTIFYEVENT EventListHead;
26*c2c66affSColin Finck BOOL bLoop;
27*c2c66affSColin Finck BOOL bMix;
28*c2c66affSColin Finck HANDLE hPin;
29*c2c66affSColin Finck DWORD BufferSize;
30*c2c66affSColin Finck
31*c2c66affSColin Finck }CDirectSoundNotifyImpl, *LPCDirectSoundNotifyImpl;
32*c2c66affSColin Finck
33*c2c66affSColin Finck static
34*c2c66affSColin Finck ULONG
35*c2c66affSColin Finck WINAPI
IDirectSoundNotify_fnAddRef(LPDIRECTSOUNDNOTIFY iface)36*c2c66affSColin Finck IDirectSoundNotify_fnAddRef(
37*c2c66affSColin Finck LPDIRECTSOUNDNOTIFY iface)
38*c2c66affSColin Finck {
39*c2c66affSColin Finck ULONG ref;
40*c2c66affSColin Finck LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
41*c2c66affSColin Finck
42*c2c66affSColin Finck /* increment reference count */
43*c2c66affSColin Finck ref = InterlockedIncrement(&This->ref);
44*c2c66affSColin Finck
45*c2c66affSColin Finck return ref;
46*c2c66affSColin Finck }
47*c2c66affSColin Finck
48*c2c66affSColin Finck static
49*c2c66affSColin Finck ULONG
50*c2c66affSColin Finck WINAPI
IDirectSoundNotify_fnRelease(LPDIRECTSOUNDNOTIFY iface)51*c2c66affSColin Finck IDirectSoundNotify_fnRelease(
52*c2c66affSColin Finck LPDIRECTSOUNDNOTIFY iface)
53*c2c66affSColin Finck {
54*c2c66affSColin Finck ULONG ref;
55*c2c66affSColin Finck LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
56*c2c66affSColin Finck
57*c2c66affSColin Finck ref = InterlockedDecrement(&(This->ref));
58*c2c66affSColin Finck
59*c2c66affSColin Finck if (!ref)
60*c2c66affSColin Finck {
61*c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This);
62*c2c66affSColin Finck }
63*c2c66affSColin Finck
64*c2c66affSColin Finck return ref;
65*c2c66affSColin Finck }
66*c2c66affSColin Finck
67*c2c66affSColin Finck HRESULT
68*c2c66affSColin Finck WINAPI
IDirectSoundNotify_fnQueryInterface(LPDIRECTSOUNDNOTIFY iface,IN REFIID riid,LPVOID * ppobj)69*c2c66affSColin Finck IDirectSoundNotify_fnQueryInterface(
70*c2c66affSColin Finck LPDIRECTSOUNDNOTIFY iface,
71*c2c66affSColin Finck IN REFIID riid,
72*c2c66affSColin Finck LPVOID* ppobj)
73*c2c66affSColin Finck {
74*c2c66affSColin Finck LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
75*c2c66affSColin Finck
76*c2c66affSColin Finck /* check if the interface is supported */
77*c2c66affSColin Finck if (IsEqualIID(riid, &IID_IDirectSoundNotify) || IsEqualIID(riid, &IID_IUnknown))
78*c2c66affSColin Finck {
79*c2c66affSColin Finck *ppobj = (LPVOID)&This->lpVtbl;
80*c2c66affSColin Finck InterlockedIncrement(&This->ref);
81*c2c66affSColin Finck return S_OK;
82*c2c66affSColin Finck }
83*c2c66affSColin Finck
84*c2c66affSColin Finck return E_NOINTERFACE;
85*c2c66affSColin Finck }
86*c2c66affSColin Finck
87*c2c66affSColin Finck HRESULT
88*c2c66affSColin Finck WINAPI
IDirectSoundNotify_fnSetNotificationPositions(LPDIRECTSOUNDNOTIFY iface,DWORD dwPositionNotifies,LPCDSBPOSITIONNOTIFY pcPositionNotifies)89*c2c66affSColin Finck IDirectSoundNotify_fnSetNotificationPositions(
90*c2c66affSColin Finck LPDIRECTSOUNDNOTIFY iface,
91*c2c66affSColin Finck DWORD dwPositionNotifies,
92*c2c66affSColin Finck LPCDSBPOSITIONNOTIFY pcPositionNotifies)
93*c2c66affSColin Finck {
94*c2c66affSColin Finck DWORD Index;
95*c2c66affSColin Finck LPNOTIFYEVENT Notify;
96*c2c66affSColin Finck DWORD Result;
97*c2c66affSColin Finck KSEVENT Request;
98*c2c66affSColin Finck
99*c2c66affSColin Finck LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
100*c2c66affSColin Finck
101*c2c66affSColin Finck if (dwPositionNotifies > DSBNOTIFICATIONS_MAX)
102*c2c66affSColin Finck {
103*c2c66affSColin Finck /* invalid param */
104*c2c66affSColin Finck return DSERR_INVALIDPARAM;
105*c2c66affSColin Finck }
106*c2c66affSColin Finck
107*c2c66affSColin Finck /* verify notification event handles */
108*c2c66affSColin Finck for(Index = 0; Index < dwPositionNotifies; Index++)
109*c2c66affSColin Finck {
110*c2c66affSColin Finck ASSERT(pcPositionNotifies[Index].hEventNotify);
111*c2c66affSColin Finck ASSERT(pcPositionNotifies[Index].dwOffset < This->BufferSize || pcPositionNotifies[Index].dwOffset != DSBPN_OFFSETSTOP);
112*c2c66affSColin Finck
113*c2c66affSColin Finck if (pcPositionNotifies[Index].hEventNotify == NULL)
114*c2c66affSColin Finck return DSERR_INVALIDPARAM;
115*c2c66affSColin Finck
116*c2c66affSColin Finck if (pcPositionNotifies[Index].dwOffset > This->BufferSize && pcPositionNotifies[Index].dwOffset != DSBPN_OFFSETSTOP)
117*c2c66affSColin Finck return DSERR_INVALIDPARAM;
118*c2c66affSColin Finck }
119*c2c66affSColin Finck
120*c2c66affSColin Finck /* allocate new array */
121*c2c66affSColin Finck Notify = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFYEVENT));
122*c2c66affSColin Finck if (!Notify)
123*c2c66affSColin Finck {
124*c2c66affSColin Finck /* not enough memory */
125*c2c66affSColin Finck return DSERR_OUTOFMEMORY;
126*c2c66affSColin Finck }
127*c2c66affSColin Finck
128*c2c66affSColin Finck /* allocate new array */
129*c2c66affSColin Finck Notify->Notify = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwPositionNotifies * sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA));
130*c2c66affSColin Finck if (!Notify->Notify)
131*c2c66affSColin Finck {
132*c2c66affSColin Finck /* not enough memory */
133*c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, Notify);
134*c2c66affSColin Finck return DSERR_OUTOFMEMORY;
135*c2c66affSColin Finck }
136*c2c66affSColin Finck
137*c2c66affSColin Finck /* FIXME support non-looped streaming */
138*c2c66affSColin Finck ASSERT(This->bLoop);
139*c2c66affSColin Finck
140*c2c66affSColin Finck /* prepare request */
141*c2c66affSColin Finck Request.Set = KSEVENTSETID_LoopedStreaming;
142*c2c66affSColin Finck Request.Id = KSEVENT_LOOPEDSTREAMING_POSITION;
143*c2c66affSColin Finck Request.Flags = KSEVENT_TYPE_ENABLE;
144*c2c66affSColin Finck
145*c2c66affSColin Finck for(Index = 0; Index < dwPositionNotifies; Index++)
146*c2c66affSColin Finck {
147*c2c66affSColin Finck /* initialize event entries */
148*c2c66affSColin Finck Notify->Notify[Index].Position = pcPositionNotifies[Index].dwOffset;
149*c2c66affSColin Finck Notify->Notify[Index].KsEventData.EventHandle.Event = pcPositionNotifies[Index].hEventNotify;
150*c2c66affSColin Finck Notify->Notify[Index].KsEventData.NotificationType = KSEVENTF_EVENT_HANDLE;
151*c2c66affSColin Finck
152*c2c66affSColin Finck if (This->bMix == FALSE)
153*c2c66affSColin Finck {
154*c2c66affSColin Finck /* format is supported natively */
155*c2c66affSColin Finck Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Request, sizeof(KSEVENT), (PVOID)&Notify->Notify[Index], sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA), NULL);
156*c2c66affSColin Finck
157*c2c66affSColin Finck if (Result != ERROR_SUCCESS)
158*c2c66affSColin Finck {
159*c2c66affSColin Finck DPRINT1("Failed to enable event %p Position %u\n", pcPositionNotifies[Index].hEventNotify, pcPositionNotifies[Index].dwOffset);
160*c2c66affSColin Finck }
161*c2c66affSColin Finck }
162*c2c66affSColin Finck }
163*c2c66affSColin Finck
164*c2c66affSColin Finck /* enlarge notify count */
165*c2c66affSColin Finck Notify->NotifyCount = dwPositionNotifies;
166*c2c66affSColin Finck
167*c2c66affSColin Finck if (This->EventListHead)
168*c2c66affSColin Finck {
169*c2c66affSColin Finck Notify->lpNext = This->EventListHead;
170*c2c66affSColin Finck }
171*c2c66affSColin Finck
172*c2c66affSColin Finck /* insert at front */
173*c2c66affSColin Finck (void)InterlockedExchangePointer((LPVOID*)&This->EventListHead, Notify);
174*c2c66affSColin Finck
175*c2c66affSColin Finck return DS_OK;
176*c2c66affSColin Finck }
177*c2c66affSColin Finck
178*c2c66affSColin Finck static IDirectSoundNotifyVtbl vt_DirectSoundNotify =
179*c2c66affSColin Finck {
180*c2c66affSColin Finck /* IUnknown methods */
181*c2c66affSColin Finck IDirectSoundNotify_fnQueryInterface,
182*c2c66affSColin Finck IDirectSoundNotify_fnAddRef,
183*c2c66affSColin Finck IDirectSoundNotify_fnRelease,
184*c2c66affSColin Finck /* IDirectSoundNotify */
185*c2c66affSColin Finck IDirectSoundNotify_fnSetNotificationPositions
186*c2c66affSColin Finck };
187*c2c66affSColin Finck
188*c2c66affSColin Finck
189*c2c66affSColin Finck VOID
DoNotifyPositionEvents(LPDIRECTSOUNDNOTIFY iface,DWORD OldPosition,DWORD NewPosition)190*c2c66affSColin Finck DoNotifyPositionEvents(
191*c2c66affSColin Finck LPDIRECTSOUNDNOTIFY iface,
192*c2c66affSColin Finck DWORD OldPosition,
193*c2c66affSColin Finck DWORD NewPosition)
194*c2c66affSColin Finck {
195*c2c66affSColin Finck DWORD Index;
196*c2c66affSColin Finck LPNOTIFYEVENT CurEventList;
197*c2c66affSColin Finck
198*c2c66affSColin Finck LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl);
199*c2c66affSColin Finck
200*c2c66affSColin Finck CurEventList = This->EventListHead;
201*c2c66affSColin Finck
202*c2c66affSColin Finck while(CurEventList)
203*c2c66affSColin Finck {
204*c2c66affSColin Finck for(Index = 0; Index < CurEventList->NotifyCount; Index++)
205*c2c66affSColin Finck {
206*c2c66affSColin Finck if (NewPosition > OldPosition)
207*c2c66affSColin Finck {
208*c2c66affSColin Finck /* buffer progress no overlap */
209*c2c66affSColin Finck if (OldPosition < CurEventList->Notify[Index].Position && CurEventList->Notify[Index].Position <= NewPosition)
210*c2c66affSColin Finck {
211*c2c66affSColin Finck /* process event */
212*c2c66affSColin Finck SetEvent(CurEventList->Notify[Index].KsEventData.EventHandle.Event);
213*c2c66affSColin Finck }
214*c2c66affSColin Finck }
215*c2c66affSColin Finck else
216*c2c66affSColin Finck {
217*c2c66affSColin Finck /* buffer wrap-arround */
218*c2c66affSColin Finck if (OldPosition < CurEventList->Notify[Index].Position || NewPosition > CurEventList->Notify[Index].Position)
219*c2c66affSColin Finck {
220*c2c66affSColin Finck /* process event */
221*c2c66affSColin Finck SetEvent(CurEventList->Notify[Index].KsEventData.EventHandle.Event);
222*c2c66affSColin Finck }
223*c2c66affSColin Finck }
224*c2c66affSColin Finck }
225*c2c66affSColin Finck
226*c2c66affSColin Finck /* iterate to next event list */
227*c2c66affSColin Finck CurEventList = CurEventList->lpNext;
228*c2c66affSColin Finck }
229*c2c66affSColin Finck }
230*c2c66affSColin Finck
231*c2c66affSColin Finck HRESULT
NewDirectSoundNotify(LPDIRECTSOUNDNOTIFY * Notify,BOOL bLoop,BOOL bMix,HANDLE hPin,DWORD BufferSize)232*c2c66affSColin Finck NewDirectSoundNotify(
233*c2c66affSColin Finck LPDIRECTSOUNDNOTIFY * Notify,
234*c2c66affSColin Finck BOOL bLoop,
235*c2c66affSColin Finck BOOL bMix,
236*c2c66affSColin Finck HANDLE hPin,
237*c2c66affSColin Finck DWORD BufferSize)
238*c2c66affSColin Finck {
239*c2c66affSColin Finck LPCDirectSoundNotifyImpl This = HeapAlloc(GetProcessHeap(), 0, sizeof(CDirectSoundNotifyImpl));
240*c2c66affSColin Finck
241*c2c66affSColin Finck if (!This)
242*c2c66affSColin Finck return DSERR_OUTOFMEMORY;
243*c2c66affSColin Finck
244*c2c66affSColin Finck This->lpVtbl = &vt_DirectSoundNotify;
245*c2c66affSColin Finck This->bLoop = bLoop;
246*c2c66affSColin Finck This->bMix = bMix;
247*c2c66affSColin Finck This->hPin = hPin;
248*c2c66affSColin Finck This->ref = 1;
249*c2c66affSColin Finck This->EventListHead = NULL;
250*c2c66affSColin Finck This->BufferSize = BufferSize;
251*c2c66affSColin Finck
252*c2c66affSColin Finck *Notify = (LPDIRECTSOUNDNOTIFY)&This->lpVtbl;
253*c2c66affSColin Finck return DS_OK;
254*c2c66affSColin Finck
255*c2c66affSColin Finck }
256