msvcrt: Use fpclass constants from public header.
[wine/zf.git] / dlls / dmime / segtriggertrack.c
blob9a7602f58dbbb7a681790723aa351945c91f017b
1 /* IDirectMusicSegTriggerTrack Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
4 * Copyright (C) 2003-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 #include "wine/heap.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dmime);
28 /*****************************************************************************
29 * IDirectMusicSegTriggerTrack implementation
31 struct segment_item {
32 struct list entry;
33 DMUS_IO_SEGMENT_ITEM_HEADER header;
34 IDirectMusicObject *dmobj;
35 WCHAR name[DMUS_MAX_NAME];
38 typedef struct IDirectMusicSegTriggerTrack {
39 IDirectMusicTrack8 IDirectMusicTrack8_iface;
40 struct dmobject dmobj;/* IPersistStream only */
41 LONG ref;
42 struct list Items;
43 } IDirectMusicSegTriggerTrack;
45 /* IDirectMusicSegTriggerTrack IDirectMusicTrack8 part: */
46 static inline IDirectMusicSegTriggerTrack *impl_from_IDirectMusicTrack8(IDirectMusicTrack8 *iface)
48 return CONTAINING_RECORD(iface, IDirectMusicSegTriggerTrack, IDirectMusicTrack8_iface);
51 static HRESULT WINAPI segment_track_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
52 void **ret_iface)
54 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
56 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
58 *ret_iface = NULL;
60 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicTrack) ||
61 IsEqualIID(riid, &IID_IDirectMusicTrack8))
62 *ret_iface = iface;
63 else if (IsEqualIID(riid, &IID_IPersistStream))
64 *ret_iface = &This->dmobj.IPersistStream_iface;
65 else {
66 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
67 return E_NOINTERFACE;
70 IUnknown_AddRef((IUnknown*)*ret_iface);
71 return S_OK;
74 static ULONG WINAPI segment_track_AddRef(IDirectMusicTrack8 *iface)
76 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
77 LONG ref = InterlockedIncrement(&This->ref);
79 TRACE("(%p) ref=%d\n", This, ref);
81 return ref;
84 static ULONG WINAPI segment_track_Release(IDirectMusicTrack8 *iface)
86 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
87 LONG ref = InterlockedDecrement(&This->ref);
89 TRACE("(%p) ref=%d\n", This, ref);
91 if (!ref) {
92 struct list *cursor, *cursor2;
93 struct segment_item *item;
95 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->Items) {
96 item = LIST_ENTRY(cursor, struct segment_item, entry);
97 list_remove(cursor);
99 if (item->dmobj)
100 IDirectMusicObject_Release(item->dmobj);
101 heap_free(item);
104 heap_free(This);
105 DMIME_UnlockModule();
108 return ref;
111 static HRESULT WINAPI segment_track_Init(IDirectMusicTrack8 *iface, IDirectMusicSegment *pSegment)
113 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
114 FIXME("(%p, %p): stub\n", This, pSegment);
115 return S_OK;
118 static HRESULT WINAPI segment_track_InitPlay(IDirectMusicTrack8 *iface,
119 IDirectMusicSegmentState *pSegmentState, IDirectMusicPerformance *pPerformance,
120 void **ppStateData, DWORD dwVirtualTrack8ID, DWORD dwFlags)
122 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
123 FIXME("(%p, %p, %p, %p, %d, %d): stub\n", This, pSegmentState, pPerformance, ppStateData, dwVirtualTrack8ID, dwFlags);
124 return S_OK;
127 static HRESULT WINAPI segment_track_EndPlay(IDirectMusicTrack8 *iface, void *pStateData)
129 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
130 FIXME("(%p, %p): stub\n", This, pStateData);
131 return S_OK;
134 static HRESULT WINAPI segment_track_Play(IDirectMusicTrack8 *iface, void *pStateData,
135 MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, DWORD dwFlags,
136 IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID)
138 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
139 FIXME("(%p, %p, %d, %d, %d, %d, %p, %p, %d): stub\n", This, pStateData, mtStart, mtEnd, mtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
140 return S_OK;
143 static HRESULT WINAPI segment_track_GetParam(IDirectMusicTrack8 *iface, REFGUID type,
144 MUSIC_TIME time, MUSIC_TIME *next, void *param)
146 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
148 TRACE("(%p, %s, %d, %p, %p): not supported\n", This, debugstr_dmguid(type), time, next, param);
149 return DMUS_E_GET_UNSUPPORTED;
152 static HRESULT WINAPI segment_track_SetParam(IDirectMusicTrack8 *iface, REFGUID type,
153 MUSIC_TIME time, void *param)
155 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
157 TRACE("(%p, %s, %d, %p): not supported\n", This, debugstr_dmguid(type), time, param);
158 return S_OK;
161 static HRESULT WINAPI segment_track_IsParamSupported(IDirectMusicTrack8 *iface, REFGUID type)
163 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
165 TRACE("(%p, %s)\n", This, debugstr_dmguid(type));
166 return S_OK;
169 static HRESULT WINAPI segment_track_AddNotificationType(IDirectMusicTrack8 *iface,
170 REFGUID notiftype)
172 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
174 TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype));
175 return E_NOTIMPL;
178 static HRESULT WINAPI segment_track_RemoveNotificationType(IDirectMusicTrack8 *iface,
179 REFGUID notiftype)
181 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
183 TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype));
184 return E_NOTIMPL;
187 static HRESULT WINAPI segment_track_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME mtStart,
188 MUSIC_TIME mtEnd, IDirectMusicTrack **ppTrack)
190 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
191 FIXME("(%p, %d, %d, %p): stub\n", This, mtStart, mtEnd, ppTrack);
192 return S_OK;
195 static HRESULT WINAPI segment_track_PlayEx(IDirectMusicTrack8 *iface, void *pStateData,
196 REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD dwFlags,
197 IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID)
199 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
200 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %d, %p, %p, %d): stub\n", This, pStateData, wine_dbgstr_longlong(rtStart),
201 wine_dbgstr_longlong(rtEnd), wine_dbgstr_longlong(rtOffset), dwFlags, pPerf, pSegSt, dwVirtualID);
202 return S_OK;
205 static HRESULT WINAPI segment_track_GetParamEx(IDirectMusicTrack8 *iface, REFGUID rguidType,
206 REFERENCE_TIME rtTime, REFERENCE_TIME *prtNext, void *pParam, void *pStateData,
207 DWORD dwFlags)
209 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
210 FIXME("(%p, %s, 0x%s, %p, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
211 wine_dbgstr_longlong(rtTime), prtNext, pParam, pStateData, dwFlags);
212 return S_OK;
215 static HRESULT WINAPI segment_track_SetParamEx(IDirectMusicTrack8 *iface, REFGUID rguidType,
216 REFERENCE_TIME rtTime, void *pParam, void *pStateData, DWORD dwFlags)
218 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
219 FIXME("(%p, %s, 0x%s, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
220 wine_dbgstr_longlong(rtTime), pParam, pStateData, dwFlags);
221 return S_OK;
224 static HRESULT WINAPI segment_track_Compose(IDirectMusicTrack8 *iface, IUnknown *context,
225 DWORD trackgroup, IDirectMusicTrack **track)
227 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
229 TRACE("(%p, %p, %d, %p): method not implemented\n", This, context, trackgroup, track);
230 return E_NOTIMPL;
233 static HRESULT WINAPI segment_track_Join(IDirectMusicTrack8 *iface, IDirectMusicTrack *newtrack,
234 MUSIC_TIME join, IUnknown *context, DWORD trackgroup, IDirectMusicTrack **resulttrack)
236 IDirectMusicSegTriggerTrack *This = impl_from_IDirectMusicTrack8(iface);
237 TRACE("(%p, %p, %d, %p, %d, %p): method not implemented\n", This, newtrack, join, context,
238 trackgroup, resulttrack);
239 return E_NOTIMPL;
242 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
243 segment_track_QueryInterface,
244 segment_track_AddRef,
245 segment_track_Release,
246 segment_track_Init,
247 segment_track_InitPlay,
248 segment_track_EndPlay,
249 segment_track_Play,
250 segment_track_GetParam,
251 segment_track_SetParam,
252 segment_track_IsParamSupported,
253 segment_track_AddNotificationType,
254 segment_track_RemoveNotificationType,
255 segment_track_Clone,
256 segment_track_PlayEx,
257 segment_track_GetParamEx,
258 segment_track_SetParamEx,
259 segment_track_Compose,
260 segment_track_Join
263 static inline IDirectMusicSegTriggerTrack *impl_from_IPersistStream(IPersistStream *iface)
265 return CONTAINING_RECORD(iface, IDirectMusicSegTriggerTrack, dmobj.IPersistStream_iface);
268 static HRESULT parse_segment_item(IDirectMusicSegTriggerTrack *This, IStream *stream,
269 const struct chunk_entry *lseg)
271 struct chunk_entry chunk = {.parent = lseg};
272 struct segment_item *item;
273 HRESULT hr;
275 /* First chunk is a header */
276 if (stream_get_chunk(stream, &chunk) != S_OK || chunk.id != DMUS_FOURCC_SEGMENTITEM_CHUNK)
277 return DMUS_E_TRACK_HDR_NOT_FIRST_CK;
278 if (!(item = heap_alloc_zero(sizeof(*item))))
279 return E_OUTOFMEMORY;
280 hr = stream_chunk_get_data(stream, &chunk, &item->header, sizeof(DMUS_IO_SEGMENT_ITEM_HEADER));
281 if (FAILED(hr))
282 goto error;
284 TRACE("Found DMUS_IO_SEGMENT_ITEM_HEADER\n");
285 TRACE("\tlTimePhysical: %u\n", item->header.lTimeLogical);
286 TRACE("\tlTimePhysical: %u\n", item->header.lTimePhysical);
287 TRACE("\tdwPlayFlags: %#08x\n", item->header.dwPlayFlags);
288 TRACE("\tdwFlags: %#08x\n", item->header.dwFlags);
290 /* Second chunk is a reference list */
291 if (stream_next_chunk(stream, &chunk) != S_OK || chunk.id != FOURCC_LIST ||
292 chunk.type != DMUS_FOURCC_REF_LIST) {
293 hr = DMUS_E_INVALID_SEGMENTTRIGGERTRACK;
294 goto error;
296 if (FAILED(hr = dmobj_parsereference(stream, &chunk, &item->dmobj)))
297 goto error;
299 /* Optional third chunk if the reference is a motif */
300 if (item->header.dwFlags & DMUS_SEGMENTTRACKF_MOTIF) {
301 if (FAILED(hr = stream_next_chunk(stream, &chunk)))
302 goto error;
303 if (chunk.id == DMUS_FOURCC_SEGMENTITEMNAME_CHUNK)
304 if (FAILED(hr = stream_chunk_get_wstr(stream, &chunk, item->name, DMUS_MAX_NAME)))
305 goto error;
307 TRACE("Found motif name: %s\n", debugstr_w(item->name));
310 list_add_tail(&This->Items, &item->entry);
312 return S_OK;
314 error:
315 heap_free(item);
316 return hr;
319 static HRESULT parse_segments_list(IDirectMusicSegTriggerTrack *This, IStream *stream,
320 const struct chunk_entry *lsgl)
322 struct chunk_entry chunk = {.parent = lsgl};
323 HRESULT hr;
325 TRACE("Parsing segment list in %p: %s\n", stream, debugstr_chunk(lsgl));
327 while ((hr = stream_next_chunk(stream, &chunk)) == S_OK)
328 if (chunk.id == FOURCC_LIST && chunk.type == DMUS_FOURCC_SEGMENT_LIST)
329 if (FAILED(hr = parse_segment_item(This, stream, &chunk)))
330 break;
332 return SUCCEEDED(hr) ? S_OK : hr;
335 static HRESULT WINAPI trigger_IPersistStream_Load(IPersistStream *iface, IStream *stream)
337 IDirectMusicSegTriggerTrack *This = impl_from_IPersistStream(iface);
338 struct chunk_entry segt = {0};
339 struct chunk_entry chunk = {.parent = &segt};
340 DMUS_IO_SEGMENT_TRACK_HEADER header;
341 HRESULT hr;
343 TRACE("(%p, %p): Loading\n", This, stream);
345 if (!stream)
346 return E_POINTER;
348 if (stream_get_chunk(stream, &segt) != S_OK || segt.id != FOURCC_LIST ||
349 segt.type != DMUS_FOURCC_SEGTRACK_LIST)
350 return DMUS_E_INVALID_SEGMENTTRIGGERTRACK;
352 if ((hr = stream_get_chunk(stream, &chunk)) != S_OK)
353 return FAILED(hr) ? hr : DMUS_E_INVALID_SEGMENTTRIGGERTRACK;
355 /* Optional and useless header chunk */
356 if (chunk.id == DMUS_FOURCC_SEGTRACK_CHUNK) {
357 hr = stream_chunk_get_data(stream, &chunk, &header, sizeof(DMUS_IO_SEGMENT_TRACK_HEADER));
358 if (FAILED(hr))
359 return hr;
360 if (header.dwFlags)
361 WARN("Got flags %#x; must be zero\n", header.dwFlags);
363 if ((hr = stream_get_chunk(stream, &chunk)) != S_OK)
364 return FAILED(hr) ? hr : DMUS_E_INVALID_SEGMENTTRIGGERTRACK;
367 if (chunk.id != FOURCC_LIST || chunk.type != DMUS_FOURCC_SEGMENTS_LIST)
368 return DMUS_E_INVALID_SEGMENTTRIGGERTRACK;
370 return parse_segments_list(This, stream, &chunk);
373 static const IPersistStreamVtbl persiststream_vtbl = {
374 dmobj_IPersistStream_QueryInterface,
375 dmobj_IPersistStream_AddRef,
376 dmobj_IPersistStream_Release,
377 dmobj_IPersistStream_GetClassID,
378 unimpl_IPersistStream_IsDirty,
379 trigger_IPersistStream_Load,
380 unimpl_IPersistStream_Save,
381 unimpl_IPersistStream_GetSizeMax
384 /* for ClassFactory */
385 HRESULT WINAPI create_dmsegtriggertrack(REFIID lpcGUID, void **ppobj)
387 IDirectMusicSegTriggerTrack *track;
388 HRESULT hr;
390 track = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*track));
391 if (!track) {
392 *ppobj = NULL;
393 return E_OUTOFMEMORY;
395 track->IDirectMusicTrack8_iface.lpVtbl = &dmtrack8_vtbl;
396 track->ref = 1;
397 dmobject_init(&track->dmobj, &CLSID_DirectMusicSegTriggerTrack,
398 (IUnknown *)&track->IDirectMusicTrack8_iface);
399 track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
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;