include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / dmband / bandtrack.c
blob45346ad1f7a76fdfe5cac5a9110e472d8e23c6c9
1 /*
2 * Copyright (C) 2003-2004 Rok Mandeljc
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "dmband_private.h"
20 #include "dmusic_band.h"
21 #include "dmobject.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmband);
25 struct band_entry
27 struct list entry;
28 DMUS_IO_BAND_ITEM_HEADER2 head;
29 IDirectMusicBand *band;
32 static void band_entry_destroy(struct band_entry *entry)
34 IDirectMusicTrack_Release(entry->band);
35 free(entry);
38 struct band_track
40 IDirectMusicTrack8 IDirectMusicTrack8_iface;
41 struct dmobject dmobj; /* IPersistStream only */
42 LONG ref;
43 DMUS_IO_BAND_TRACK_HEADER header;
44 struct list bands;
47 static inline struct band_track *impl_from_IDirectMusicTrack8(IDirectMusicTrack8 *iface)
49 return CONTAINING_RECORD(iface, struct band_track, IDirectMusicTrack8_iface);
52 static HRESULT WINAPI band_track_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
53 void **ret_iface)
55 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
57 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
59 *ret_iface = NULL;
61 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicTrack) ||
62 IsEqualIID(riid, &IID_IDirectMusicTrack8))
63 *ret_iface = iface;
64 else if (IsEqualIID(riid, &IID_IPersistStream))
65 *ret_iface = &This->dmobj.IPersistStream_iface;
66 else {
67 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
68 return E_NOINTERFACE;
71 IUnknown_AddRef((IUnknown*)*ret_iface);
72 return S_OK;
75 static ULONG WINAPI band_track_AddRef(IDirectMusicTrack8 *iface)
77 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
78 LONG ref = InterlockedIncrement(&This->ref);
80 TRACE("(%p) ref=%ld\n", This, ref);
82 return ref;
85 static ULONG WINAPI band_track_Release(IDirectMusicTrack8 *iface)
87 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
88 LONG ref = InterlockedDecrement(&This->ref);
90 TRACE("(%p) ref=%ld\n", This, ref);
92 if (!ref)
94 struct band_entry *entry, *next;
96 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &This->bands, struct band_entry, entry)
98 list_remove(&entry->entry);
99 band_entry_destroy(entry);
102 free(This);
105 return ref;
108 static HRESULT WINAPI band_track_Init(IDirectMusicTrack8 *iface, IDirectMusicSegment *segment)
110 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
112 FIXME("(%p, %p): stub\n", This, segment);
114 if (!segment) return E_POINTER;
115 return S_OK;
118 static HRESULT WINAPI band_track_InitPlay(IDirectMusicTrack8 *iface,
119 IDirectMusicSegmentState *segment_state, IDirectMusicPerformance *performance,
120 void **state_data, DWORD virtual_track8id, DWORD flags)
122 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
123 struct band_entry *entry;
124 HRESULT hr;
126 FIXME("(%p, %p, %p, %p, %ld, %lx): semi-stub\n", This, segment_state, performance, state_data, virtual_track8id, flags);
128 if (!performance) return E_POINTER;
130 if (This->header.bAutoDownload)
132 LIST_FOR_EACH_ENTRY(entry, &This->bands, struct band_entry, entry)
134 if (FAILED(hr = IDirectMusicBand_Download(entry->band, performance)))
135 return hr;
139 return S_OK;
142 static HRESULT WINAPI band_track_EndPlay(IDirectMusicTrack8 *iface, void *state_data)
144 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
145 struct band_entry *entry;
146 HRESULT hr;
148 FIXME("(%p, %p): semi-stub\n", This, state_data);
150 if (This->header.bAutoDownload)
152 LIST_FOR_EACH_ENTRY(entry, &This->bands, struct band_entry, entry)
154 if (FAILED(hr = IDirectMusicBand_Unload(entry->band, NULL)))
155 return hr;
159 return S_OK;
162 static HRESULT WINAPI band_track_Play(IDirectMusicTrack8 *iface, void *state_data,
163 MUSIC_TIME start_time, MUSIC_TIME end_time, MUSIC_TIME time_offset, DWORD track_flags,
164 IDirectMusicPerformance *performance, IDirectMusicSegmentState *segment_state, DWORD track_id)
166 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
167 IDirectMusicGraph *graph;
168 struct band_entry *entry;
169 HRESULT hr;
171 TRACE("(%p, %p, %ld, %ld, %ld, %#lx, %p, %p, %ld)\n", This, state_data, start_time, end_time,
172 time_offset, track_flags, performance, segment_state, track_id);
174 if (!performance) return DMUS_S_END;
176 if (track_flags) FIXME("track_flags %#lx not implemented\n", track_flags);
177 if (segment_state) FIXME("segment_state %p not implemented\n", segment_state);
179 if (FAILED(hr = IDirectMusicPerformance_QueryInterface(performance,
180 &IID_IDirectMusicGraph, (void **)&graph)))
181 return hr;
183 LIST_FOR_EACH_ENTRY(entry, &This->bands, struct band_entry, entry)
185 MUSIC_TIME music_time = entry->head.lBandTimeLogical;
186 if (music_time == -1 && !(track_flags & DMUS_TRACKF_START)) continue;
187 else if (music_time != -1)
189 if (music_time < start_time || music_time >= end_time) continue;
190 music_time += time_offset;
193 if (FAILED(hr = band_send_messages(entry->band, performance, graph, music_time, track_id)))
194 break;
197 IDirectMusicGraph_Release(graph);
198 return hr;
201 static HRESULT WINAPI band_track_GetParam(IDirectMusicTrack8 *iface, REFGUID type, MUSIC_TIME time,
202 MUSIC_TIME *out_next, void *param)
204 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
205 struct band_entry *band, *next_band;
206 DMUS_BAND_PARAM *bandparam;
208 TRACE("(%p, %s, %ld, %p, %p)\n", This, debugstr_dmguid(type), time, out_next, param);
210 if (!type)
211 return E_POINTER;
212 if (!IsEqualGUID(type, &GUID_BandParam))
213 return DMUS_E_GET_UNSUPPORTED;
214 if (list_empty(&This->bands))
215 return DMUS_E_NOT_FOUND;
217 bandparam = param;
218 if (out_next) *out_next = 0;
220 LIST_FOR_EACH_ENTRY_SAFE(band, next_band, &This->bands, struct band_entry, entry)
222 /* we want to return the first band even when there's nothing with lBandTime <= time */
223 bandparam->pBand = band->band;
224 bandparam->mtTimePhysical = band->head.lBandTimePhysical;
225 if (band->entry.next == &This->bands) break;
226 if (out_next) *out_next = next_band->head.lBandTimeLogical;
227 if (next_band->head.lBandTimeLogical > time) break;
230 IDirectMusicBand_AddRef(bandparam->pBand);
231 return S_OK;
234 static HRESULT WINAPI band_track_SetParam(IDirectMusicTrack8 *iface, REFGUID type, MUSIC_TIME time,
235 void *param)
237 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
239 TRACE("(%p, %s, %ld, %p)\n", This, debugstr_dmguid(type), time, param);
241 if (!type)
242 return E_POINTER;
243 if (FAILED(IDirectMusicTrack8_IsParamSupported(iface, type)))
244 return DMUS_E_TYPE_UNSUPPORTED;
246 if (IsEqualGUID(type, &GUID_BandParam))
248 struct band_entry *new_entry = NULL, *entry, *next_entry;
249 DMUS_BAND_PARAM *band_param = param;
250 if (!band_param || !band_param->pBand)
251 return E_POINTER;
252 if (!(new_entry = calloc(1, sizeof(*new_entry))))
253 return E_OUTOFMEMORY;
254 new_entry->band = band_param->pBand;
255 new_entry->head.lBandTimeLogical = time;
256 new_entry->head.lBandTimePhysical = band_param->mtTimePhysical;
257 IDirectMusicBand_AddRef(new_entry->band);
258 if (list_empty(&This->bands))
259 list_add_tail(&This->bands, &new_entry->entry);
260 else
262 LIST_FOR_EACH_ENTRY_SAFE(entry, next_entry, &This->bands, struct band_entry, entry)
263 if (entry->entry.next == &This->bands || next_entry->head.lBandTimeLogical > time)
265 list_add_after(&entry->entry, &new_entry->entry);
266 break;
270 else if (IsEqualGUID(type, &GUID_Clear_All_Bands))
271 FIXME("GUID_Clear_All_Bands not handled yet\n");
272 else if (IsEqualGUID(type, &GUID_ConnectToDLSCollection))
274 struct band_entry *entry;
276 LIST_FOR_EACH_ENTRY(entry, &This->bands, struct band_entry, entry)
277 band_connect_to_collection(entry->band, param);
279 else if (IsEqualGUID(type, &GUID_Disable_Auto_Download))
280 This->header.bAutoDownload = FALSE;
281 else if (IsEqualGUID(type, &GUID_Download))
282 FIXME("GUID_Download not handled yet\n");
283 else if (IsEqualGUID(type, &GUID_DownloadToAudioPath))
285 IDirectMusicPerformance *performance;
286 IDirectMusicAudioPath *audio_path;
287 IUnknown *object = param;
288 struct band_entry *entry;
289 HRESULT hr;
291 if (FAILED(hr = IDirectMusicAudioPath_QueryInterface(object, &IID_IDirectMusicPerformance8, (void **)&performance))
292 && SUCCEEDED(hr = IDirectMusicAudioPath_QueryInterface(object, &IID_IDirectMusicAudioPath, (void **)&audio_path)))
294 hr = IDirectMusicAudioPath_GetObjectInPath(audio_path, DMUS_PCHANNEL_ALL, DMUS_PATH_PERFORMANCE, 0,
295 &GUID_All_Objects, 0, &IID_IDirectMusicPerformance8, (void **)&performance);
296 IDirectMusicAudioPath_Release(audio_path);
299 if (FAILED(hr))
301 WARN("Failed to get IDirectMusicPerformance from param %p\n", param);
302 return hr;
305 LIST_FOR_EACH_ENTRY(entry, &This->bands, struct band_entry, entry)
306 if (FAILED(hr = IDirectMusicBand_Download(entry->band, performance))) break;
308 IDirectMusicPerformance_Release(performance);
310 else if (IsEqualGUID(type, &GUID_Enable_Auto_Download))
311 This->header.bAutoDownload = TRUE;
312 else if (IsEqualGUID(type, &GUID_IDirectMusicBand))
313 FIXME("GUID_IDirectMusicBand not handled yet\n");
314 else if (IsEqualGUID(type, &GUID_StandardMIDIFile))
315 FIXME("GUID_StandardMIDIFile not handled yet\n");
316 else if (IsEqualGUID(type, &GUID_UnloadFromAudioPath))
318 struct band_entry *entry;
319 HRESULT hr;
321 LIST_FOR_EACH_ENTRY(entry, &This->bands, struct band_entry, entry)
322 if (FAILED(hr = IDirectMusicBand_Unload(entry->band, NULL))) break;
325 return S_OK;
328 static HRESULT WINAPI band_track_IsParamSupported(IDirectMusicTrack8 *iface, REFGUID rguidType)
330 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
332 TRACE("(%p, %s)\n", This, debugstr_dmguid(rguidType));
334 if (!rguidType)
335 return E_POINTER;
337 if (IsEqualGUID (rguidType, &GUID_BandParam)
338 || IsEqualGUID (rguidType, &GUID_Clear_All_Bands)
339 || IsEqualGUID (rguidType, &GUID_ConnectToDLSCollection)
340 || IsEqualGUID (rguidType, &GUID_Disable_Auto_Download)
341 || IsEqualGUID (rguidType, &GUID_Download)
342 || IsEqualGUID (rguidType, &GUID_DownloadToAudioPath)
343 || IsEqualGUID (rguidType, &GUID_Enable_Auto_Download)
344 || IsEqualGUID (rguidType, &GUID_IDirectMusicBand)
345 || IsEqualGUID (rguidType, &GUID_StandardMIDIFile)
346 || IsEqualGUID (rguidType, &GUID_Unload)
347 || IsEqualGUID (rguidType, &GUID_UnloadFromAudioPath)) {
348 TRACE("param supported\n");
349 return S_OK;
352 TRACE("param unsupported\n");
353 return DMUS_E_TYPE_UNSUPPORTED;
356 static HRESULT WINAPI band_track_AddNotificationType(IDirectMusicTrack8 *iface, REFGUID notiftype)
358 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
360 TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype));
361 return E_NOTIMPL;
364 static HRESULT WINAPI band_track_RemoveNotificationType(IDirectMusicTrack8 *iface,
365 REFGUID notiftype)
367 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
369 TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype));
370 return E_NOTIMPL;
373 static HRESULT WINAPI band_track_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME mtStart,
374 MUSIC_TIME mtEnd, IDirectMusicTrack **ppTrack)
376 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
377 FIXME("(%p, %ld, %ld, %p): stub\n", This, mtStart, mtEnd, ppTrack);
378 return S_OK;
381 static HRESULT WINAPI band_track_PlayEx(IDirectMusicTrack8 *iface, void *state_data,
382 REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD flags,
383 IDirectMusicPerformance *performance, IDirectMusicSegmentState *segment_state,
384 DWORD virtual_id)
386 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
388 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %lx, %p, %p, %ld): stub\n", This, state_data, wine_dbgstr_longlong(rtStart),
389 wine_dbgstr_longlong(rtEnd), wine_dbgstr_longlong(rtOffset), flags, performance, segment_state, virtual_id);
391 return S_OK;
394 static HRESULT WINAPI band_track_GetParamEx(IDirectMusicTrack8 *iface,
395 REFGUID rguidType, REFERENCE_TIME rtTime, REFERENCE_TIME *rtNext, void *param,
396 void *state_data, DWORD flags)
398 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
400 FIXME("(%p, %s, 0x%s, %p, %p, %p, %lx): stub\n", This, debugstr_dmguid(rguidType),
401 wine_dbgstr_longlong(rtTime), rtNext, param, state_data, flags);
403 return S_OK;
406 static HRESULT WINAPI band_track_SetParamEx(IDirectMusicTrack8 *iface, REFGUID rguidType,
407 REFERENCE_TIME rtTime, void *param, void *state_data, DWORD flags)
409 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
411 FIXME("(%p, %s, 0x%s, %p, %p, %lx): stub\n", This, debugstr_dmguid(rguidType),
412 wine_dbgstr_longlong(rtTime), param, state_data, flags);
414 return S_OK;
417 static HRESULT WINAPI band_track_Compose(IDirectMusicTrack8 *iface, IUnknown *context,
418 DWORD trackgroup, IDirectMusicTrack **track)
420 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
422 TRACE("(%p, %p, %ld, %p): method not implemented\n", This, context, trackgroup, track);
423 return E_NOTIMPL;
426 static HRESULT WINAPI band_track_Join(IDirectMusicTrack8 *iface, IDirectMusicTrack *pNewTrack,
427 MUSIC_TIME mtJoin, IUnknown *pContext, DWORD dwTrackGroup,
428 IDirectMusicTrack **ppResultTrack)
430 struct band_track *This = impl_from_IDirectMusicTrack8(iface);
431 FIXME("(%p, %p, %ld, %p, %ld, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
432 return S_OK;
435 static const IDirectMusicTrack8Vtbl band_track_vtbl =
437 band_track_QueryInterface,
438 band_track_AddRef,
439 band_track_Release,
440 band_track_Init,
441 band_track_InitPlay,
442 band_track_EndPlay,
443 band_track_Play,
444 band_track_GetParam,
445 band_track_SetParam,
446 band_track_IsParamSupported,
447 band_track_AddNotificationType,
448 band_track_RemoveNotificationType,
449 band_track_Clone,
450 band_track_PlayEx,
451 band_track_GetParamEx,
452 band_track_SetParamEx,
453 band_track_Compose,
454 band_track_Join,
457 static HRESULT parse_lbnd_list(struct band_track *This, IStream *stream, struct chunk_entry *parent)
459 struct chunk_entry chunk = {.parent = parent};
460 DMUS_IO_BAND_ITEM_HEADER2 header2;
461 struct band_entry *entry;
462 IDirectMusicBand *band;
463 HRESULT hr;
465 while ((hr = stream_next_chunk(stream, &chunk)) == S_OK)
467 switch (MAKE_IDTYPE(chunk.id, chunk.type))
469 case DMUS_FOURCC_BANDITEM_CHUNK:
471 DMUS_IO_BAND_ITEM_HEADER header;
473 if (SUCCEEDED(hr = stream_chunk_get_data(stream, &chunk, &header, sizeof(header))))
475 header2.lBandTimeLogical = header.lBandTime;
476 header2.lBandTimePhysical = header.lBandTime;
479 break;
482 case DMUS_FOURCC_BANDITEM_CHUNK2:
483 hr = stream_chunk_get_data(stream, &chunk, &header2, sizeof(header2));
484 break;
486 case MAKE_IDTYPE(FOURCC_RIFF, DMUS_FOURCC_BAND_FORM):
488 IPersistStream *persist;
490 if (FAILED(hr = CoCreateInstance(&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER,
491 &IID_IDirectMusicBand, (void **)&band)))
492 break;
494 if (SUCCEEDED(hr = IDirectMusicBand_QueryInterface(band, &IID_IPersistStream, (void **)&persist)))
496 if (SUCCEEDED(hr = stream_reset_chunk_start(stream, &chunk)))
497 hr = IPersistStream_Load(persist, stream);
498 IPersistStream_Release(persist);
501 break;
504 default:
505 FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
506 break;
509 if (FAILED(hr)) break;
512 if (FAILED(hr)) return hr;
514 if (!(entry = calloc(1, sizeof(*entry)))) return E_OUTOFMEMORY;
515 entry->head = header2;
516 entry->band = band;
517 IDirectMusicBand_AddRef(band);
518 list_add_tail(&This->bands, &entry->entry);
520 return S_OK;
523 static HRESULT parse_lbdl_list(struct band_track *This, IStream *stream, struct chunk_entry *parent)
525 struct chunk_entry chunk = {.parent = parent};
526 HRESULT hr;
528 while ((hr = stream_next_chunk(stream, &chunk)) == S_OK)
530 switch (MAKE_IDTYPE(chunk.id, chunk.type))
532 case MAKE_IDTYPE(FOURCC_LIST, DMUS_FOURCC_BAND_LIST):
533 hr = parse_lbnd_list(This, stream, &chunk);
534 break;
536 default:
537 FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
538 break;
541 if (FAILED(hr)) break;
544 return S_OK;
547 static HRESULT parse_dmbt_chunk(struct band_track *This, IStream *stream, struct chunk_entry *parent)
549 struct chunk_entry chunk = {.parent = parent};
550 HRESULT hr;
552 if (FAILED(hr = dmobj_parsedescriptor(stream, parent, &This->dmobj.desc,
553 DMUS_OBJ_OBJECT|DMUS_OBJ_NAME|DMUS_OBJ_NAME_INAM|DMUS_OBJ_VERSION))
554 || FAILED(hr = stream_reset_chunk_data(stream, parent)))
555 return hr;
557 while ((hr = stream_next_chunk(stream, &chunk)) == S_OK)
559 switch (MAKE_IDTYPE(chunk.id, chunk.type))
561 case DMUS_FOURCC_GUID_CHUNK:
562 case DMUS_FOURCC_VERSION_CHUNK:
563 case MAKE_IDTYPE(FOURCC_LIST, DMUS_FOURCC_UNFO_LIST):
564 /* already parsed by dmobj_parsedescriptor */
565 break;
567 case DMUS_FOURCC_BANDTRACK_CHUNK:
568 hr = stream_chunk_get_data(stream, &chunk, &This->header, sizeof(This->header));
569 break;
571 case MAKE_IDTYPE(FOURCC_LIST, DMUS_FOURCC_BANDS_LIST):
572 hr = parse_lbdl_list(This, stream, &chunk);
573 break;
575 default:
576 FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
577 break;
580 if (FAILED(hr)) break;
583 return hr;
586 static inline struct band_track *impl_from_IPersistStream(IPersistStream *iface)
588 return CONTAINING_RECORD(iface, struct band_track, dmobj.IPersistStream_iface);
591 static HRESULT WINAPI band_track_persist_stream_Load(IPersistStream *iface, IStream *stream)
593 struct band_track *This = impl_from_IPersistStream(iface);
594 struct chunk_entry chunk = {0};
595 HRESULT hr;
597 TRACE("(%p, %p)\n", This, stream);
599 if ((hr = stream_get_chunk(stream, &chunk)) == S_OK)
601 switch (MAKE_IDTYPE(chunk.id, chunk.type))
603 case MAKE_IDTYPE(FOURCC_RIFF, DMUS_FOURCC_BANDTRACK_FORM):
604 hr = parse_dmbt_chunk(This, stream, &chunk);
605 break;
607 default:
608 WARN("Invalid band track chunk %s %s\n", debugstr_fourcc(chunk.id), debugstr_fourcc(chunk.type));
609 hr = DMUS_E_UNSUPPORTED_STREAM;
610 break;
614 stream_skip_chunk(stream, &chunk);
615 if (FAILED(hr)) return hr;
617 if (TRACE_ON(dmband))
619 struct band_entry *entry;
620 int i = 0;
622 TRACE("Loaded DirectMusicBandTrack %p\n", This);
623 dump_DMUS_OBJECTDESC(&This->dmobj.desc);
625 TRACE(" - header:\n");
626 TRACE(" - bAutoDownload: %u\n", This->header.bAutoDownload);
628 TRACE(" - bands:\n");
629 LIST_FOR_EACH_ENTRY(entry, &This->bands, struct band_entry, entry)
631 TRACE(" - band[%u]: %p\n", i++, entry->band);
632 TRACE(" - lBandTimeLogical: %ld\n", entry->head.lBandTimeLogical);
633 TRACE(" - lBandTimePhysical: %ld\n", entry->head.lBandTimePhysical);
637 return S_OK;
640 static const IPersistStreamVtbl band_track_persist_stream_vtbl =
642 dmobj_IPersistStream_QueryInterface,
643 dmobj_IPersistStream_AddRef,
644 dmobj_IPersistStream_Release,
645 dmobj_IPersistStream_GetClassID,
646 unimpl_IPersistStream_IsDirty,
647 band_track_persist_stream_Load,
648 unimpl_IPersistStream_Save,
649 unimpl_IPersistStream_GetSizeMax,
652 /* for ClassFactory */
653 HRESULT create_dmbandtrack(REFIID lpcGUID, void **ppobj)
655 struct band_track *track;
656 HRESULT hr;
658 *ppobj = NULL;
659 if (!(track = calloc(1, sizeof(*track)))) return E_OUTOFMEMORY;
660 track->IDirectMusicTrack8_iface.lpVtbl = &band_track_vtbl;
661 track->ref = 1;
662 dmobject_init(&track->dmobj, &CLSID_DirectMusicBandTrack, (IUnknown *)&track->IDirectMusicTrack8_iface);
663 track->dmobj.IPersistStream_iface.lpVtbl = &band_track_persist_stream_vtbl;
664 list_init(&track->bands);
666 hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
667 IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface);
669 return hr;