xref: /reactos/dll/directx/dsound_new/notify.c (revision c2c66aff)
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