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"
24 #include "wine/heap.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dmime
);
28 /*****************************************************************************
29 * IDirectMusicSegTriggerTrack implementation
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 */
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
,
54 IDirectMusicSegTriggerTrack
*This
= impl_from_IDirectMusicTrack8(iface
);
56 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ret_iface
);
60 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDirectMusicTrack
) ||
61 IsEqualIID(riid
, &IID_IDirectMusicTrack8
))
63 else if (IsEqualIID(riid
, &IID_IPersistStream
))
64 *ret_iface
= &This
->dmobj
.IPersistStream_iface
;
66 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ret_iface
);
70 IUnknown_AddRef((IUnknown
*)*ret_iface
);
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
);
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
);
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
);
100 IDirectMusicObject_Release(item
->dmobj
);
105 DMIME_UnlockModule();
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
);
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
);
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
);
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
);
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
);
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
));
169 static HRESULT WINAPI
segment_track_AddNotificationType(IDirectMusicTrack8
*iface
,
172 IDirectMusicSegTriggerTrack
*This
= impl_from_IDirectMusicTrack8(iface
);
174 TRACE("(%p, %s): method not implemented\n", This
, debugstr_dmguid(notiftype
));
178 static HRESULT WINAPI
segment_track_RemoveNotificationType(IDirectMusicTrack8
*iface
,
181 IDirectMusicSegTriggerTrack
*This
= impl_from_IDirectMusicTrack8(iface
);
183 TRACE("(%p, %s): method not implemented\n", This
, debugstr_dmguid(notiftype
));
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
);
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
);
205 static HRESULT WINAPI
segment_track_GetParamEx(IDirectMusicTrack8
*iface
, REFGUID rguidType
,
206 REFERENCE_TIME rtTime
, REFERENCE_TIME
*prtNext
, void *pParam
, void *pStateData
,
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
);
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
);
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
);
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
);
242 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl
= {
243 segment_track_QueryInterface
,
244 segment_track_AddRef
,
245 segment_track_Release
,
247 segment_track_InitPlay
,
248 segment_track_EndPlay
,
250 segment_track_GetParam
,
251 segment_track_SetParam
,
252 segment_track_IsParamSupported
,
253 segment_track_AddNotificationType
,
254 segment_track_RemoveNotificationType
,
256 segment_track_PlayEx
,
257 segment_track_GetParamEx
,
258 segment_track_SetParamEx
,
259 segment_track_Compose
,
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
;
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
));
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
;
296 if (FAILED(hr
= dmobj_parsereference(stream
, &chunk
, &item
->dmobj
)))
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
)))
303 if (chunk
.id
== DMUS_FOURCC_SEGMENTITEMNAME_CHUNK
)
304 if (FAILED(hr
= stream_chunk_get_wstr(stream
, &chunk
, item
->name
, DMUS_MAX_NAME
)))
307 TRACE("Found motif name: %s\n", debugstr_w(item
->name
));
310 list_add_tail(&This
->Items
, &item
->entry
);
319 static HRESULT
parse_segments_list(IDirectMusicSegTriggerTrack
*This
, IStream
*stream
,
320 const struct chunk_entry
*lsgl
)
322 struct chunk_entry chunk
= {.parent
= lsgl
};
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
)))
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
;
343 TRACE("(%p, %p): Loading\n", This
, stream
);
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
));
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
;
390 track
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*track
));
393 return E_OUTOFMEMORY
;
395 track
->IDirectMusicTrack8_iface
.lpVtbl
= &dmtrack8_vtbl
;
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
);
403 hr
= IDirectMusicTrack8_QueryInterface(&track
->IDirectMusicTrack8_iface
, lpcGUID
, ppobj
);
404 IDirectMusicTrack8_Release(&track
->IDirectMusicTrack8_iface
);