msvcrt: Don't include MSVC 7.0+ exception functions in SOs for older DLLs.
[wine.git] / dlls / dmime / tempotrack.c
blob537845e83850c53fb55499cff64638a12a6d6137
1 /* IDirectMusicTempoTrack Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
4 * Copyright (C) 2004 Raphael Junqueira
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "dmime_private.h"
22 #include "dmobject.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(dmime);
25 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
27 /*****************************************************************************
28 * IDirectMusicTempoTrack implementation
30 typedef struct IDirectMusicTempoTrack {
31 IDirectMusicTrack8 IDirectMusicTrack8_iface;
32 struct dmobject dmobj; /* IPersistStream only */
33 LONG ref;
34 BOOL enabled;
35 struct list Items;
36 } IDirectMusicTempoTrack;
38 /* IDirectMusicTempoTrack IDirectMusicTrack8 part: */
39 static inline IDirectMusicTempoTrack *impl_from_IDirectMusicTrack8(IDirectMusicTrack8 *iface)
41 return CONTAINING_RECORD(iface, IDirectMusicTempoTrack, IDirectMusicTrack8_iface);
44 static HRESULT WINAPI IDirectMusicTrack8Impl_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
45 void **ret_iface)
47 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
49 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
51 *ret_iface = NULL;
53 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicTrack) ||
54 IsEqualIID(riid, &IID_IDirectMusicTrack8))
55 *ret_iface = iface;
56 else if (IsEqualIID(riid, &IID_IPersistStream))
57 *ret_iface = &This->dmobj.IPersistStream_iface;
58 else {
59 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
60 return E_NOINTERFACE;
63 IUnknown_AddRef((IUnknown*)*ret_iface);
64 return S_OK;
67 static ULONG WINAPI IDirectMusicTrack8Impl_AddRef(IDirectMusicTrack8 *iface)
69 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
70 LONG ref = InterlockedIncrement(&This->ref);
72 TRACE("(%p) ref=%d\n", This, ref);
74 return ref;
77 static ULONG WINAPI IDirectMusicTrack8Impl_Release(IDirectMusicTrack8 *iface)
79 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
80 LONG ref = InterlockedDecrement(&This->ref);
82 TRACE("(%p) ref=%d\n", This, ref);
84 if (!ref) {
85 HeapFree(GetProcessHeap(), 0, This);
86 DMIME_UnlockModule();
89 return ref;
92 static HRESULT WINAPI IDirectMusicTrack8Impl_Init(IDirectMusicTrack8 *iface,
93 IDirectMusicSegment *pSegment)
95 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
96 TRACE("(%p, %p): nothing to do here\n", This, pSegment);
97 return S_OK;
100 static HRESULT WINAPI IDirectMusicTrack8Impl_InitPlay(IDirectMusicTrack8 *iface,
101 IDirectMusicSegmentState *pSegmentState, IDirectMusicPerformance *pPerformance,
102 void **ppStateData, DWORD dwVirtualTrack8ID, DWORD dwFlags)
104 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
106 LPDMUS_PRIVATE_TEMPO_PLAY_STATE pState = NULL;
108 FIXME("(%p, %p, %p, %p, %d, %d): semi-stub\n", This, pSegmentState, pPerformance, ppStateData, dwVirtualTrack8ID, dwFlags);
110 pState = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_TEMPO_PLAY_STATE));
111 if (NULL == pState)
112 return E_OUTOFMEMORY;
114 /** TODO real fill useful data */
115 pState->dummy = 0;
116 *ppStateData = pState;
117 return S_OK;
120 static HRESULT WINAPI IDirectMusicTrack8Impl_EndPlay(IDirectMusicTrack8 *iface, void *pStateData)
122 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
124 LPDMUS_PRIVATE_TEMPO_PLAY_STATE pState = pStateData;
126 FIXME("(%p, %p): semi-stub\n", This, pStateData);
128 if (NULL == pStateData) {
129 return E_POINTER;
131 /** TODO real clean up */
132 HeapFree(GetProcessHeap(), 0, pState);
133 return S_OK;
136 static HRESULT WINAPI IDirectMusicTrack8Impl_Play(IDirectMusicTrack8 *iface, void *pStateData,
137 MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, DWORD dwFlags,
138 IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID)
140 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
141 FIXME("(%p, %p, %d, %d, %d, %d, %p, %p, %d): stub\n", This, pStateData, mtStart, mtEnd, mtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
142 /** should use IDirectMusicPerformance_SendPMsg here */
143 return S_OK;
146 static HRESULT WINAPI IDirectMusicTrack8Impl_GetParam(IDirectMusicTrack8 *iface, REFGUID rguidType,
147 MUSIC_TIME mtTime, MUSIC_TIME *pmtNext, void *pParam)
149 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
151 HRESULT hr = S_OK;
152 struct list* pEntry = NULL;
153 LPDMUS_PRIVATE_TEMPO_ITEM pIt = NULL;
154 DMUS_TEMPO_PARAM* prm = pParam;
156 FIXME("(%p, %s, %d, %p, %p): almost stub\n", This, debugstr_dmguid(rguidType), mtTime, pmtNext, pParam);
158 if (NULL == pParam) {
159 return E_POINTER;
162 hr = IDirectMusicTrack_IsParamSupported (iface, rguidType);
163 if (FAILED(hr)) {
164 return hr;
166 if (FALSE == This->enabled) {
167 return DMUS_E_TYPE_DISABLED;
170 if (NULL != pmtNext) *pmtNext = 0;
171 prm->mtTime = 0;
172 prm->dblTempo = 0.123456;
174 LIST_FOR_EACH (pEntry, &This->Items) {
175 pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_TEMPO_ITEM, entry);
176 /*TRACE(" - %p -> 0x%lx,%p\n", pIt, pIt->item.lTime, pIt->item.dblTempo);*/
177 if (pIt->item.lTime <= mtTime) {
178 MUSIC_TIME ofs = pIt->item.lTime - mtTime;
179 if (ofs > prm->mtTime) {
180 prm->mtTime = ofs;
181 prm->dblTempo = pIt->item.dblTempo;
183 if (NULL != pmtNext && pIt->item.lTime > mtTime) {
184 if (pIt->item.lTime < *pmtNext) {
185 *pmtNext = pIt->item.lTime;
191 if (0.123456 == prm->dblTempo) {
192 return DMUS_E_NOT_FOUND;
194 return S_OK;
197 static HRESULT WINAPI IDirectMusicTrack8Impl_SetParam(IDirectMusicTrack8 *iface, REFGUID rguidType,
198 MUSIC_TIME mtTime, void *pParam)
200 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
201 FIXME("(%p, %s, %d, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pParam);
202 return S_OK;
205 static HRESULT WINAPI IDirectMusicTrack8Impl_IsParamSupported(IDirectMusicTrack8 *iface,
206 REFGUID rguidType)
208 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
210 TRACE("(%p, %s)\n", This, debugstr_dmguid(rguidType));
211 if (IsEqualGUID (rguidType, &GUID_DisableTempo)
212 || IsEqualGUID (rguidType, &GUID_EnableTempo)
213 || IsEqualGUID (rguidType, &GUID_TempoParam)) {
214 TRACE("param supported\n");
215 return S_OK;
217 if (FALSE == This->enabled) {
218 return DMUS_E_TYPE_DISABLED;
220 TRACE("param unsupported\n");
221 return DMUS_E_TYPE_UNSUPPORTED;
224 static HRESULT WINAPI IDirectMusicTrack8Impl_AddNotificationType(IDirectMusicTrack8 *iface,
225 REFGUID notiftype)
227 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
229 TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype));
230 return E_NOTIMPL;
233 static HRESULT WINAPI IDirectMusicTrack8Impl_RemoveNotificationType(IDirectMusicTrack8 *iface,
234 REFGUID notiftype)
236 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
238 TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype));
239 return E_NOTIMPL;
242 static HRESULT WINAPI IDirectMusicTrack8Impl_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME mtStart,
243 MUSIC_TIME mtEnd, IDirectMusicTrack **ppTrack)
245 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
246 FIXME("(%p, %d, %d, %p): stub\n", This, mtStart, mtEnd, ppTrack);
247 return S_OK;
250 static HRESULT WINAPI IDirectMusicTrack8Impl_PlayEx(IDirectMusicTrack8 *iface, void *pStateData,
251 REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD dwFlags,
252 IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID)
254 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
255 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %d, %p, %p, %d): stub\n", This, pStateData, wine_dbgstr_longlong(rtStart),
256 wine_dbgstr_longlong(rtEnd), wine_dbgstr_longlong(rtOffset), dwFlags, pPerf, pSegSt, dwVirtualID);
257 return S_OK;
260 static HRESULT WINAPI IDirectMusicTrack8Impl_GetParamEx(IDirectMusicTrack8 *iface,
261 REFGUID rguidType, REFERENCE_TIME rtTime, REFERENCE_TIME *prtNext, void *pParam,
262 void *pStateData, DWORD dwFlags)
264 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
265 FIXME("(%p, %s, 0x%s, %p, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
266 wine_dbgstr_longlong(rtTime), prtNext, pParam, pStateData, dwFlags);
267 return S_OK;
270 static HRESULT WINAPI IDirectMusicTrack8Impl_SetParamEx(IDirectMusicTrack8 *iface,
271 REFGUID rguidType, REFERENCE_TIME rtTime, void *pParam, void *pStateData, DWORD dwFlags)
273 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
274 FIXME("(%p, %s, 0x%s, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
275 wine_dbgstr_longlong(rtTime), pParam, pStateData, dwFlags);
276 return S_OK;
279 static HRESULT WINAPI IDirectMusicTrack8Impl_Compose(IDirectMusicTrack8 *iface, IUnknown *context,
280 DWORD trackgroup, IDirectMusicTrack **track)
282 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
284 TRACE("(%p, %p, %d, %p): method not implemented\n", This, context, trackgroup, track);
285 return E_NOTIMPL;
288 static HRESULT WINAPI IDirectMusicTrack8Impl_Join(IDirectMusicTrack8 *iface,
289 IDirectMusicTrack *pNewTrack, MUSIC_TIME mtJoin, IUnknown *pContext, DWORD dwTrackGroup,
290 IDirectMusicTrack **ppResultTrack)
292 IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface);
293 FIXME("(%p, %p, %d, %p, %d, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
294 return S_OK;
297 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
298 IDirectMusicTrack8Impl_QueryInterface,
299 IDirectMusicTrack8Impl_AddRef,
300 IDirectMusicTrack8Impl_Release,
301 IDirectMusicTrack8Impl_Init,
302 IDirectMusicTrack8Impl_InitPlay,
303 IDirectMusicTrack8Impl_EndPlay,
304 IDirectMusicTrack8Impl_Play,
305 IDirectMusicTrack8Impl_GetParam,
306 IDirectMusicTrack8Impl_SetParam,
307 IDirectMusicTrack8Impl_IsParamSupported,
308 IDirectMusicTrack8Impl_AddNotificationType,
309 IDirectMusicTrack8Impl_RemoveNotificationType,
310 IDirectMusicTrack8Impl_Clone,
311 IDirectMusicTrack8Impl_PlayEx,
312 IDirectMusicTrack8Impl_GetParamEx,
313 IDirectMusicTrack8Impl_SetParamEx,
314 IDirectMusicTrack8Impl_Compose,
315 IDirectMusicTrack8Impl_Join
318 static inline IDirectMusicTempoTrack *impl_from_IPersistStream(IPersistStream *iface)
320 return CONTAINING_RECORD(iface, IDirectMusicTempoTrack, dmobj.IPersistStream_iface);
323 static HRESULT WINAPI tempo_IPersistStream_Load(IPersistStream *iface, IStream *pStm)
325 IDirectMusicTempoTrack *This = impl_from_IPersistStream(iface);
326 DMUS_PRIVATE_CHUNK Chunk;
327 DWORD StreamSize, StreamCount;
328 LARGE_INTEGER liMove;
329 DMUS_IO_TEMPO_ITEM item;
330 LPDMUS_PRIVATE_TEMPO_ITEM pNewItem = NULL;
331 DWORD nItem = 0;
332 FIXME("(%p, %p): Loading not fully implemented yet\n", This, pStm);
334 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
335 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
336 switch (Chunk.fccID) {
337 case DMUS_FOURCC_TEMPO_TRACK: {
338 TRACE_(dmfile)(": Tempo track\n");
339 IStream_Read (pStm, &StreamSize, sizeof(DWORD), NULL);
340 StreamSize -= sizeof(DWORD);
341 StreamCount = 0;
342 TRACE_(dmfile)(" - sizeof(DMUS_IO_TEMPO_ITEM): %u (chunkSize = %u)\n", StreamSize, Chunk.dwSize);
343 do {
344 IStream_Read (pStm, &item, sizeof(item), NULL);
345 ++nItem;
346 TRACE_(dmfile)("DMUS_IO_TEMPO_ITEM #%d\n", nItem);
347 TRACE_(dmfile)(" - lTime = %u\n", item.lTime);
348 TRACE_(dmfile)(" - dblTempo = %g\n", item.dblTempo);
349 pNewItem = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_TEMPO_ITEM));
350 if (NULL == pNewItem)
351 return E_OUTOFMEMORY;
353 pNewItem->item = item;
354 list_add_tail (&This->Items, &pNewItem->entry);
355 pNewItem = NULL;
356 StreamCount += sizeof(item);
357 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
358 } while (StreamCount < StreamSize);
359 break;
361 default: {
362 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
363 liMove.QuadPart = Chunk.dwSize;
364 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
365 return E_FAIL;
369 return S_OK;
372 static const IPersistStreamVtbl persiststream_vtbl = {
373 dmobj_IPersistStream_QueryInterface,
374 dmobj_IPersistStream_AddRef,
375 dmobj_IPersistStream_Release,
376 dmobj_IPersistStream_GetClassID,
377 unimpl_IPersistStream_IsDirty,
378 tempo_IPersistStream_Load,
379 unimpl_IPersistStream_Save,
380 unimpl_IPersistStream_GetSizeMax
383 /* for ClassFactory */
384 HRESULT WINAPI create_dmtempotrack(REFIID lpcGUID, void **ppobj)
386 IDirectMusicTempoTrack *track;
387 HRESULT hr;
389 track = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*track));
390 if (!track) {
391 *ppobj = NULL;
392 return E_OUTOFMEMORY;
394 track->IDirectMusicTrack8_iface.lpVtbl = &dmtrack8_vtbl;
395 track->ref = 1;
396 dmobject_init(&track->dmobj, &CLSID_DirectMusicTempoTrack,
397 (IUnknown *)&track->IDirectMusicTrack8_iface);
398 track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
399 track->enabled = TRUE;
400 list_init(&track->Items);
402 DMIME_LockModule();
403 hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
404 IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface);
406 return hr;