wined3d: Correctly destroy the adapter on format initialization failure in no3d mode.
[wine/zf.git] / dlls / dmband / bandtrack.c
blob14d2c7a571cab046884a1c528a8f19559ac3db60
1 /* IDirectMusicBandTrack Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "dmband_private.h"
21 #include "dmobject.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmband);
24 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
26 /*****************************************************************************
27 * IDirectMusicBandTrack implementation
29 typedef struct IDirectMusicBandTrack {
30 IDirectMusicTrack8 IDirectMusicTrack8_iface;
31 struct dmobject dmobj; /* IPersistStream only */
32 LONG ref;
33 DMUS_IO_BAND_TRACK_HEADER header;
34 struct list Bands;
35 } IDirectMusicBandTrack;
37 /* IDirectMusicBandTrack IDirectMusicTrack8 part: */
38 static inline IDirectMusicBandTrack *impl_from_IDirectMusicTrack8(IDirectMusicTrack8 *iface)
40 return CONTAINING_RECORD(iface, IDirectMusicBandTrack, IDirectMusicTrack8_iface);
43 static HRESULT WINAPI band_track_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
44 void **ret_iface)
46 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
48 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
50 *ret_iface = NULL;
52 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicTrack) ||
53 IsEqualIID(riid, &IID_IDirectMusicTrack8))
54 *ret_iface = iface;
55 else if (IsEqualIID(riid, &IID_IPersistStream))
56 *ret_iface = &This->dmobj.IPersistStream_iface;
57 else {
58 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
59 return E_NOINTERFACE;
62 IUnknown_AddRef((IUnknown*)*ret_iface);
63 return S_OK;
66 static ULONG WINAPI band_track_AddRef(IDirectMusicTrack8 *iface)
68 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
69 LONG ref = InterlockedIncrement(&This->ref);
71 TRACE("(%p) ref=%d\n", This, ref);
73 return ref;
76 static ULONG WINAPI band_track_Release(IDirectMusicTrack8 *iface)
78 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
79 LONG ref = InterlockedDecrement(&This->ref);
81 TRACE("(%p) ref=%d\n", This, ref);
83 if (!ref) {
84 HeapFree(GetProcessHeap(), 0, This);
85 DMBAND_UnlockModule();
88 return ref;
91 static HRESULT WINAPI band_track_Init(IDirectMusicTrack8 *iface, IDirectMusicSegment *pSegment)
93 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
94 FIXME("(%p, %p): stub\n", This, pSegment);
95 return S_OK;
98 static HRESULT WINAPI band_track_InitPlay(IDirectMusicTrack8 *iface,
99 IDirectMusicSegmentState *segment_state, IDirectMusicPerformance *performance,
100 void **state_data, DWORD virtual_track8id, DWORD flags)
102 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
104 FIXME("(%p, %p, %p, %p, %d, %x): stub\n", This, segment_state, performance, state_data, virtual_track8id, flags);
106 return S_OK;
109 static HRESULT WINAPI band_track_EndPlay(IDirectMusicTrack8 *iface, void *pStateData)
111 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
112 FIXME("(%p, %p): stub\n", This, pStateData);
113 return S_OK;
116 static HRESULT WINAPI band_track_Play(IDirectMusicTrack8 *iface, void *state_data,
117 MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, DWORD flags,
118 IDirectMusicPerformance *performance, IDirectMusicSegmentState *segment_state,
119 DWORD virtual_id)
121 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
123 FIXME("(%p, %p, %d, %d, %d, %x, %p, %p, %d): semi-stub\n", This, state_data, mtStart, mtEnd, mtOffset, flags, performance, segment_state, virtual_id);
125 /* Sends following pMSG:
126 - DMUS_PATCH_PMSG
127 - DMUS_TRANSPOSE_PMSG
128 - DMUS_CHANNEL_PRIORITY_PMSG
129 - DMUS_MIDI_PMSG
132 return S_OK;
135 static HRESULT WINAPI band_track_GetParam(IDirectMusicTrack8 *iface, REFGUID type, MUSIC_TIME time,
136 MUSIC_TIME *next, void *param)
138 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
140 TRACE("(%p, %s, %d, %p, %p)\n", This, debugstr_dmguid(type), time, next, param);
142 if (!type)
143 return E_POINTER;
144 if (!IsEqualGUID(type, &GUID_BandParam))
145 return DMUS_E_GET_UNSUPPORTED;
147 FIXME("GUID_BandParam not handled yet\n");
149 return S_OK;
152 static HRESULT WINAPI band_track_SetParam(IDirectMusicTrack8 *iface, REFGUID type, MUSIC_TIME time,
153 void *param)
155 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
157 TRACE("(%p, %s, %d, %p)\n", This, debugstr_dmguid(type), time, param);
159 if (!type)
160 return E_POINTER;
161 if (FAILED(IDirectMusicTrack8_IsParamSupported(iface, type)))
162 return DMUS_E_TYPE_UNSUPPORTED;
164 if (IsEqualGUID(type, &GUID_BandParam))
165 FIXME("GUID_BandParam not handled yet\n");
166 else if (IsEqualGUID(type, &GUID_Clear_All_Bands))
167 FIXME("GUID_Clear_All_Bands not handled yet\n");
168 else if (IsEqualGUID(type, &GUID_ConnectToDLSCollection))
169 FIXME("GUID_ConnectToDLSCollection not handled yet\n");
170 else if (IsEqualGUID(type, &GUID_Disable_Auto_Download))
171 FIXME("GUID_Disable_Auto_Download not handled yet\n");
172 else if (IsEqualGUID(type, &GUID_Download))
173 FIXME("GUID_Download not handled yet\n");
174 else if (IsEqualGUID(type, &GUID_DownloadToAudioPath))
175 FIXME("GUID_DownloadToAudioPath not handled yet\n");
176 else if (IsEqualGUID(type, &GUID_Enable_Auto_Download))
177 FIXME("GUID_Enable_Auto_Download not handled yet\n");
178 else if (IsEqualGUID(type, &GUID_IDirectMusicBand))
179 FIXME("GUID_IDirectMusicBand not handled yet\n");
180 else if (IsEqualGUID(type, &GUID_StandardMIDIFile))
181 FIXME("GUID_StandardMIDIFile not handled yet\n");
182 else if (IsEqualGUID(type, &GUID_UnloadFromAudioPath))
183 FIXME("GUID_UnloadFromAudioPath not handled yet\n");
185 return S_OK;
188 static HRESULT WINAPI band_track_IsParamSupported(IDirectMusicTrack8 *iface, REFGUID rguidType)
190 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
192 TRACE("(%p, %s)\n", This, debugstr_dmguid(rguidType));
194 if (!rguidType)
195 return E_POINTER;
197 if (IsEqualGUID (rguidType, &GUID_BandParam)
198 || IsEqualGUID (rguidType, &GUID_Clear_All_Bands)
199 || IsEqualGUID (rguidType, &GUID_ConnectToDLSCollection)
200 || IsEqualGUID (rguidType, &GUID_Disable_Auto_Download)
201 || IsEqualGUID (rguidType, &GUID_Download)
202 || IsEqualGUID (rguidType, &GUID_DownloadToAudioPath)
203 || IsEqualGUID (rguidType, &GUID_Enable_Auto_Download)
204 || IsEqualGUID (rguidType, &GUID_IDirectMusicBand)
205 || IsEqualGUID (rguidType, &GUID_StandardMIDIFile)
206 || IsEqualGUID (rguidType, &GUID_Unload)
207 || IsEqualGUID (rguidType, &GUID_UnloadFromAudioPath)) {
208 TRACE("param supported\n");
209 return S_OK;
212 TRACE("param unsupported\n");
213 return DMUS_E_TYPE_UNSUPPORTED;
216 static HRESULT WINAPI band_track_AddNotificationType(IDirectMusicTrack8 *iface, REFGUID notiftype)
218 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
220 TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype));
221 return E_NOTIMPL;
224 static HRESULT WINAPI band_track_RemoveNotificationType(IDirectMusicTrack8 *iface,
225 REFGUID notiftype)
227 IDirectMusicBandTrack *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 band_track_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME mtStart,
234 MUSIC_TIME mtEnd, IDirectMusicTrack **ppTrack)
236 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
237 FIXME("(%p, %d, %d, %p): stub\n", This, mtStart, mtEnd, ppTrack);
238 return S_OK;
241 static HRESULT WINAPI band_track_PlayEx(IDirectMusicTrack8 *iface, void *state_data,
242 REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD flags,
243 IDirectMusicPerformance *performance, IDirectMusicSegmentState *segment_state,
244 DWORD virtual_id)
246 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
248 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %x, %p, %p, %d): stub\n", This, state_data, wine_dbgstr_longlong(rtStart),
249 wine_dbgstr_longlong(rtEnd), wine_dbgstr_longlong(rtOffset), flags, performance, segment_state, virtual_id);
251 return S_OK;
254 static HRESULT WINAPI band_track_GetParamEx(IDirectMusicTrack8 *iface,
255 REFGUID rguidType, REFERENCE_TIME rtTime, REFERENCE_TIME *rtNext, void *param,
256 void *state_data, DWORD flags)
258 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
260 FIXME("(%p, %s, 0x%s, %p, %p, %p, %x): stub\n", This, debugstr_dmguid(rguidType),
261 wine_dbgstr_longlong(rtTime), rtNext, param, state_data, flags);
263 return S_OK;
266 static HRESULT WINAPI band_track_SetParamEx(IDirectMusicTrack8 *iface, REFGUID rguidType,
267 REFERENCE_TIME rtTime, void *param, void *state_data, DWORD flags)
269 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
271 FIXME("(%p, %s, 0x%s, %p, %p, %x): stub\n", This, debugstr_dmguid(rguidType),
272 wine_dbgstr_longlong(rtTime), param, state_data, flags);
274 return S_OK;
277 static HRESULT WINAPI band_track_Compose(IDirectMusicTrack8 *iface, IUnknown *context,
278 DWORD trackgroup, IDirectMusicTrack **track)
280 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
282 TRACE("(%p, %p, %d, %p): method not implemented\n", This, context, trackgroup, track);
283 return E_NOTIMPL;
286 static HRESULT WINAPI band_track_Join(IDirectMusicTrack8 *iface, IDirectMusicTrack *pNewTrack,
287 MUSIC_TIME mtJoin, IUnknown *pContext, DWORD dwTrackGroup,
288 IDirectMusicTrack **ppResultTrack)
290 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
291 FIXME("(%p, %p, %d, %p, %d, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
292 return S_OK;
295 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
296 band_track_QueryInterface,
297 band_track_AddRef,
298 band_track_Release,
299 band_track_Init,
300 band_track_InitPlay,
301 band_track_EndPlay,
302 band_track_Play,
303 band_track_GetParam,
304 band_track_SetParam,
305 band_track_IsParamSupported,
306 band_track_AddNotificationType,
307 band_track_RemoveNotificationType,
308 band_track_Clone,
309 band_track_PlayEx,
310 band_track_GetParamEx,
311 band_track_SetParamEx,
312 band_track_Compose,
313 band_track_Join
316 /* IDirectMusicBandTrack IPersistStream part: */
317 static HRESULT load_band(IDirectMusicBandTrack *This, IStream *pClonedStream,
318 IDirectMusicBand **ppBand, DMUS_PRIVATE_BAND_ITEM_HEADER *pHeader)
320 HRESULT hr = E_FAIL;
321 IPersistStream* pPersistStream = NULL;
323 hr = CoCreateInstance (&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicBand, (LPVOID*) ppBand);
324 if (FAILED(hr)) {
325 ERR(": could not create object\n");
326 return hr;
328 /* acquire PersistStream interface */
329 hr = IDirectMusicBand_QueryInterface (*ppBand, &IID_IPersistStream, (LPVOID*) &pPersistStream);
330 if (FAILED(hr)) {
331 ERR(": could not acquire IPersistStream\n");
332 return hr;
334 /* load */
335 hr = IPersistStream_Load (pPersistStream, pClonedStream);
336 if (FAILED(hr)) {
337 ERR(": failed to load object\n");
338 return hr;
341 /* release all loading-related stuff */
342 IPersistStream_Release (pPersistStream);
345 * @TODO insert pBand into This
347 if (SUCCEEDED(hr)) {
348 LPDMUS_PRIVATE_BAND pNewBand = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_BAND));
349 if (NULL == pNewBand) {
350 ERR(": no more memory\n");
351 return E_OUTOFMEMORY;
353 pNewBand->BandHeader = *pHeader;
354 pNewBand->band = *ppBand;
355 IDirectMusicBand_AddRef(*ppBand);
356 list_add_tail (&This->Bands, &pNewBand->entry);
359 return S_OK;
362 static HRESULT parse_bands_list(IDirectMusicBandTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
363 IStream *pStm)
365 HRESULT hr = E_FAIL;
366 DMUS_PRIVATE_CHUNK Chunk;
367 DWORD StreamSize, ListSize[3], ListCount[3];
368 LARGE_INTEGER liMove; /* used when skipping chunks */
370 IDirectMusicBand* pBand = NULL;
371 DMUS_PRIVATE_BAND_ITEM_HEADER header;
373 memset(&header, 0, sizeof header);
375 if (pChunk->fccID != DMUS_FOURCC_BANDS_LIST) {
376 ERR_(dmfile)(": %s chunk should be a BANDS list\n", debugstr_fourcc (pChunk->fccID));
377 return E_FAIL;
380 ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
381 ListCount[0] = 0;
383 do {
384 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
385 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
386 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
387 switch (Chunk.fccID) {
388 case FOURCC_LIST: {
389 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
390 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
391 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
392 ListCount[1] = 0;
393 do {
394 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
395 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
396 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
397 switch (Chunk.fccID) {
398 case DMUS_FOURCC_BANDITEM_CHUNK: {
399 DMUS_IO_BAND_ITEM_HEADER tmp_header;
400 TRACE_(dmfile)(": Band Item chunk v1\n");
402 IStream_Read (pStm, &tmp_header, sizeof(DMUS_IO_BAND_ITEM_HEADER), NULL);
403 TRACE_(dmfile)(" - lBandTime: %u\n", tmp_header.lBandTime);
405 header.dwVersion = 1;
406 header.lBandTime = tmp_header.lBandTime;
407 break;
409 case DMUS_FOURCC_BANDITEM_CHUNK2: {
410 DMUS_IO_BAND_ITEM_HEADER2 tmp_header2;
411 TRACE_(dmfile)(": Band Item chunk v2\n");
413 IStream_Read (pStm, &tmp_header2, sizeof(DMUS_IO_BAND_ITEM_HEADER2), NULL);
414 TRACE_(dmfile)(" - lBandTimeLogical: %u\n", tmp_header2.lBandTimeLogical);
415 TRACE_(dmfile)(" - lBandTimePhysical: %u\n", tmp_header2.lBandTimePhysical);
417 header.dwVersion = 2;
418 header.lBandTimeLogical = tmp_header2.lBandTimeLogical;
419 header.lBandTimePhysical = tmp_header2.lBandTimePhysical;
420 break;
422 case FOURCC_RIFF: {
423 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
424 TRACE_(dmfile)(": RIFF chunk of type %s\n", debugstr_fourcc(Chunk.fccID));
425 StreamSize = Chunk.dwSize - sizeof(FOURCC);
426 switch (Chunk.fccID) {
427 case DMUS_FOURCC_BAND_FORM: {
428 LPSTREAM pClonedStream = NULL;
429 TRACE_(dmfile)(": BAND RIFF\n");
431 IStream_Clone (pStm, &pClonedStream);
433 liMove.QuadPart = 0;
434 liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
435 IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
437 hr = load_band(This, pClonedStream, &pBand, &header);
438 if (FAILED(hr)) {
439 ERR(": could not load track\n");
440 return hr;
442 IStream_Release (pClonedStream);
444 IDirectMusicTrack_Release(pBand); pBand = NULL; /* now we can release at as it inserted */
446 /** now safe move the cursor */
447 liMove.QuadPart = StreamSize;
448 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
449 break;
451 default: {
452 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
453 liMove.QuadPart = StreamSize;
454 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
455 break;
458 break;
460 default: {
461 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
462 liMove.QuadPart = Chunk.dwSize;
463 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
464 break;
467 TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]);
468 } while (ListCount[1] < ListSize[1]);
469 break;
471 default: {
472 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
473 liMove.QuadPart = Chunk.dwSize;
474 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
475 break;
478 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
479 } while (ListCount[0] < ListSize[0]);
481 return S_OK;
484 static HRESULT parse_bandtrack_form(IDirectMusicBandTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
485 IStream *pStm)
487 HRESULT hr = E_FAIL;
488 DMUS_PRIVATE_CHUNK Chunk;
489 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
490 LARGE_INTEGER liMove; /* used when skipping chunks */
492 if (pChunk->fccID != DMUS_FOURCC_BANDTRACK_FORM) {
493 ERR_(dmfile)(": %s chunk should be a BANDTRACK form\n", debugstr_fourcc (pChunk->fccID));
494 return E_FAIL;
497 StreamSize = pChunk->dwSize - sizeof(FOURCC);
498 StreamCount = 0;
500 do {
501 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
502 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
503 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
505 hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, &This->dmobj.desc);
506 if (FAILED(hr)) return hr;
508 if (hr == S_FALSE) {
509 switch (Chunk.fccID) {
510 case DMUS_FOURCC_BANDTRACK_CHUNK: {
511 TRACE_(dmfile)(": BandTrack chunk\n");
512 IStream_Read (pStm, &This->header, sizeof(DMUS_IO_BAND_TRACK_HEADER), NULL);
513 TRACE_(dmfile)(" - bAutoDownload: %u\n", This->header.bAutoDownload);
514 break;
516 case FOURCC_LIST: {
517 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
518 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
519 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
520 ListCount[0] = 0;
521 switch (Chunk.fccID) {
522 case DMUS_FOURCC_UNFO_LIST: {
523 TRACE_(dmfile)(": UNFO list\n");
524 do {
525 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
526 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
527 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
529 hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &This->dmobj.desc);
530 if (FAILED(hr)) return hr;
532 if (hr == S_FALSE) {
533 switch (Chunk.fccID) {
534 default: {
535 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
536 liMove.QuadPart = Chunk.dwSize;
537 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
538 break;
542 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
543 } while (ListCount[0] < ListSize[0]);
544 break;
546 case DMUS_FOURCC_BANDS_LIST: {
547 TRACE_(dmfile)(": TRACK list\n");
548 hr = parse_bands_list(This, &Chunk, pStm);
549 if (FAILED(hr)) return hr;
550 break;
552 default: {
553 TRACE_(dmfile)(": unknown (skipping)\n");
554 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
555 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
556 break;
559 break;
561 default: {
562 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
563 liMove.QuadPart = Chunk.dwSize;
564 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
565 break;
569 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
570 } while (StreamCount < StreamSize);
572 return S_OK;
575 static inline IDirectMusicBandTrack *impl_from_IPersistStream(IPersistStream *iface)
577 return CONTAINING_RECORD(iface, IDirectMusicBandTrack, dmobj.IPersistStream_iface);
580 static HRESULT WINAPI IPersistStreamImpl_Load(IPersistStream *iface, IStream *pStm)
582 IDirectMusicBandTrack *This = impl_from_IPersistStream(iface);
583 DMUS_PRIVATE_CHUNK Chunk;
584 LARGE_INTEGER liMove;
585 HRESULT hr;
587 TRACE("(%p, %p): Loading\n", This, pStm);
589 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
590 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
591 switch (Chunk.fccID) {
592 case FOURCC_RIFF: {
593 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
594 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
595 switch (Chunk.fccID) {
596 case DMUS_FOURCC_BANDTRACK_FORM: {
597 TRACE_(dmfile)(": Band track form\n");
598 hr = parse_bandtrack_form(This, &Chunk, pStm);
599 if (FAILED(hr)) return hr;
600 break;
602 default: {
603 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
604 liMove.QuadPart = Chunk.dwSize;
605 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
606 return E_FAIL;
609 TRACE_(dmfile)(": reading finished\n");
610 break;
612 default: {
613 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
614 liMove.QuadPart = Chunk.dwSize;
615 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
616 return E_FAIL;
620 return S_OK;
623 static const IPersistStreamVtbl persiststream_vtbl = {
624 dmobj_IPersistStream_QueryInterface,
625 dmobj_IPersistStream_AddRef,
626 dmobj_IPersistStream_Release,
627 dmobj_IPersistStream_GetClassID,
628 unimpl_IPersistStream_IsDirty,
629 IPersistStreamImpl_Load,
630 unimpl_IPersistStream_Save,
631 unimpl_IPersistStream_GetSizeMax
634 /* for ClassFactory */
635 HRESULT WINAPI create_dmbandtrack(REFIID lpcGUID, void **ppobj)
637 IDirectMusicBandTrack *track;
638 HRESULT hr;
640 track = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*track));
641 if (!track) {
642 *ppobj = NULL;
643 return E_OUTOFMEMORY;
645 track->IDirectMusicTrack8_iface.lpVtbl = &dmtrack8_vtbl;
646 track->ref = 1;
647 dmobject_init(&track->dmobj, &CLSID_DirectMusicBandTrack,
648 (IUnknown *)&track->IDirectMusicTrack8_iface);
649 track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
650 list_init (&track->Bands);
652 DMBAND_LockModule();
653 hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
654 IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface);
656 return hr;