2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Configuration of network devices
4 * FILE: dll/directx/dsound_new/notify.c
5 * PURPOSE: IDirectSoundNotify implementation
7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
13 typedef struct tagNOTIFYEVENT
16 PLOOPEDSTREAMING_POSITION_EVENT_DATA Notify
;
17 struct tagNOTIFYEVENT
*lpNext
;
18 }NOTIFYEVENT
, *LPNOTIFYEVENT
;
22 IDirectSoundNotifyVtbl
* lpVtbl
;
25 LPNOTIFYEVENT EventListHead
;
31 }CDirectSoundNotifyImpl
, *LPCDirectSoundNotifyImpl
;
36 IDirectSoundNotify_fnAddRef(
37 LPDIRECTSOUNDNOTIFY iface
)
40 LPCDirectSoundNotifyImpl This
= (LPCDirectSoundNotifyImpl
)CONTAINING_RECORD(iface
, CDirectSoundNotifyImpl
, lpVtbl
);
42 /* increment reference count */
43 ref
= InterlockedIncrement(&This
->ref
);
51 IDirectSoundNotify_fnRelease(
52 LPDIRECTSOUNDNOTIFY iface
)
55 LPCDirectSoundNotifyImpl This
= (LPCDirectSoundNotifyImpl
)CONTAINING_RECORD(iface
, CDirectSoundNotifyImpl
, lpVtbl
);
57 ref
= InterlockedDecrement(&(This
->ref
));
61 HeapFree(GetProcessHeap(), 0, This
);
69 IDirectSoundNotify_fnQueryInterface(
70 LPDIRECTSOUNDNOTIFY iface
,
74 LPCDirectSoundNotifyImpl This
= (LPCDirectSoundNotifyImpl
)CONTAINING_RECORD(iface
, CDirectSoundNotifyImpl
, lpVtbl
);
76 /* check if the interface is supported */
77 if (IsEqualIID(riid
, &IID_IDirectSoundNotify
) || IsEqualIID(riid
, &IID_IUnknown
))
79 *ppobj
= (LPVOID
)&This
->lpVtbl
;
80 InterlockedIncrement(&This
->ref
);
89 IDirectSoundNotify_fnSetNotificationPositions(
90 LPDIRECTSOUNDNOTIFY iface
,
91 DWORD dwPositionNotifies
,
92 LPCDSBPOSITIONNOTIFY pcPositionNotifies
)
99 LPCDirectSoundNotifyImpl This
= (LPCDirectSoundNotifyImpl
)CONTAINING_RECORD(iface
, CDirectSoundNotifyImpl
, lpVtbl
);
101 if (dwPositionNotifies
> DSBNOTIFICATIONS_MAX
)
104 return DSERR_INVALIDPARAM
;
107 /* verify notification event handles */
108 for(Index
= 0; Index
< dwPositionNotifies
; Index
++)
110 ASSERT(pcPositionNotifies
[Index
].hEventNotify
);
111 ASSERT(pcPositionNotifies
[Index
].dwOffset
< This
->BufferSize
|| pcPositionNotifies
[Index
].dwOffset
!= DSBPN_OFFSETSTOP
);
113 if (pcPositionNotifies
[Index
].hEventNotify
== NULL
)
114 return DSERR_INVALIDPARAM
;
116 if (pcPositionNotifies
[Index
].dwOffset
> This
->BufferSize
&& pcPositionNotifies
[Index
].dwOffset
!= DSBPN_OFFSETSTOP
)
117 return DSERR_INVALIDPARAM
;
120 /* allocate new array */
121 Notify
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(NOTIFYEVENT
));
124 /* not enough memory */
125 return DSERR_OUTOFMEMORY
;
128 /* allocate new array */
129 Notify
->Notify
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwPositionNotifies
* sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA
));
132 /* not enough memory */
133 HeapFree(GetProcessHeap(), 0, Notify
);
134 return DSERR_OUTOFMEMORY
;
137 /* FIXME support non-looped streaming */
140 /* prepare request */
141 Request
.Set
= KSEVENTSETID_LoopedStreaming
;
142 Request
.Id
= KSEVENT_LOOPEDSTREAMING_POSITION
;
143 Request
.Flags
= KSEVENT_TYPE_ENABLE
;
145 for(Index
= 0; Index
< dwPositionNotifies
; Index
++)
147 /* initialize event entries */
148 Notify
->Notify
[Index
].Position
= pcPositionNotifies
[Index
].dwOffset
;
149 Notify
->Notify
[Index
].KsEventData
.EventHandle
.Event
= pcPositionNotifies
[Index
].hEventNotify
;
150 Notify
->Notify
[Index
].KsEventData
.NotificationType
= KSEVENTF_EVENT_HANDLE
;
152 if (This
->bMix
== FALSE
)
154 /* format is supported natively */
155 Result
= SyncOverlappedDeviceIoControl(This
->hPin
, IOCTL_KS_ENABLE_EVENT
, (PVOID
)&Request
, sizeof(KSEVENT
), (PVOID
)&Notify
->Notify
[Index
], sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA
), NULL
);
157 if (Result
!= ERROR_SUCCESS
)
159 DPRINT1("Failed to enable event %p Position %u\n", pcPositionNotifies
[Index
].hEventNotify
, pcPositionNotifies
[Index
].dwOffset
);
164 /* enlarge notify count */
165 Notify
->NotifyCount
= dwPositionNotifies
;
167 if (This
->EventListHead
)
169 Notify
->lpNext
= This
->EventListHead
;
172 /* insert at front */
173 (void)InterlockedExchangePointer((LPVOID
*)&This
->EventListHead
, Notify
);
178 static IDirectSoundNotifyVtbl vt_DirectSoundNotify
=
180 /* IUnknown methods */
181 IDirectSoundNotify_fnQueryInterface
,
182 IDirectSoundNotify_fnAddRef
,
183 IDirectSoundNotify_fnRelease
,
184 /* IDirectSoundNotify */
185 IDirectSoundNotify_fnSetNotificationPositions
190 DoNotifyPositionEvents(
191 LPDIRECTSOUNDNOTIFY iface
,
196 LPNOTIFYEVENT CurEventList
;
198 LPCDirectSoundNotifyImpl This
= (LPCDirectSoundNotifyImpl
)CONTAINING_RECORD(iface
, CDirectSoundNotifyImpl
, lpVtbl
);
200 CurEventList
= This
->EventListHead
;
204 for(Index
= 0; Index
< CurEventList
->NotifyCount
; Index
++)
206 if (NewPosition
> OldPosition
)
208 /* buffer progress no overlap */
209 if (OldPosition
< CurEventList
->Notify
[Index
].Position
&& CurEventList
->Notify
[Index
].Position
<= NewPosition
)
212 SetEvent(CurEventList
->Notify
[Index
].KsEventData
.EventHandle
.Event
);
217 /* buffer wrap-arround */
218 if (OldPosition
< CurEventList
->Notify
[Index
].Position
|| NewPosition
> CurEventList
->Notify
[Index
].Position
)
221 SetEvent(CurEventList
->Notify
[Index
].KsEventData
.EventHandle
.Event
);
226 /* iterate to next event list */
227 CurEventList
= CurEventList
->lpNext
;
232 NewDirectSoundNotify(
233 LPDIRECTSOUNDNOTIFY
* Notify
,
239 LPCDirectSoundNotifyImpl This
= HeapAlloc(GetProcessHeap(), 0, sizeof(CDirectSoundNotifyImpl
));
242 return DSERR_OUTOFMEMORY
;
244 This
->lpVtbl
= &vt_DirectSoundNotify
;
249 This
->EventListHead
= NULL
;
250 This
->BufferSize
= BufferSize
;
252 *Notify
= (LPDIRECTSOUNDNOTIFY
)&This
->lpVtbl
;