winex11.drv: Map coordinates before calling send_mouse_input.
[wine/zf.git] / dlls / dmband / bandtrack.c
blob612be063e190d5f037da4c7ac35dfabca8d24121
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 ULARGE_INTEGER liOrigPos;
429 TRACE_(dmfile)(": BAND RIFF\n");
431 liMove.QuadPart = 0;
432 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &liOrigPos);
434 liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
435 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
437 hr = load_band(This, pStm, &pBand, &header);
438 if (FAILED(hr)) {
439 ERR(": could not load track\n");
440 return hr;
442 liMove.QuadPart = (LONGLONG)liOrigPos.QuadPart;
443 IStream_Seek (pStm, liMove, STREAM_SEEK_SET, NULL);
445 IDirectMusicTrack_Release(pBand); pBand = NULL; /* now we can release at as it inserted */
447 /** now safe move the cursor */
448 liMove.QuadPart = StreamSize;
449 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
450 break;
452 default: {
453 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
454 liMove.QuadPart = StreamSize;
455 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
456 break;
459 break;
461 default: {
462 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
463 liMove.QuadPart = Chunk.dwSize;
464 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
465 break;
468 TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]);
469 } while (ListCount[1] < ListSize[1]);
470 break;
472 default: {
473 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
474 liMove.QuadPart = Chunk.dwSize;
475 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
476 break;
479 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
480 } while (ListCount[0] < ListSize[0]);
482 return S_OK;
485 static HRESULT parse_bandtrack_form(IDirectMusicBandTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
486 IStream *pStm)
488 HRESULT hr = E_FAIL;
489 DMUS_PRIVATE_CHUNK Chunk;
490 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
491 LARGE_INTEGER liMove; /* used when skipping chunks */
493 if (pChunk->fccID != DMUS_FOURCC_BANDTRACK_FORM) {
494 ERR_(dmfile)(": %s chunk should be a BANDTRACK form\n", debugstr_fourcc (pChunk->fccID));
495 return E_FAIL;
498 StreamSize = pChunk->dwSize - sizeof(FOURCC);
499 StreamCount = 0;
501 do {
502 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
503 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
504 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
506 hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, &This->dmobj.desc);
507 if (FAILED(hr)) return hr;
509 if (hr == S_FALSE) {
510 switch (Chunk.fccID) {
511 case DMUS_FOURCC_BANDTRACK_CHUNK: {
512 TRACE_(dmfile)(": BandTrack chunk\n");
513 IStream_Read (pStm, &This->header, sizeof(DMUS_IO_BAND_TRACK_HEADER), NULL);
514 TRACE_(dmfile)(" - bAutoDownload: %u\n", This->header.bAutoDownload);
515 break;
517 case FOURCC_LIST: {
518 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
519 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
520 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
521 ListCount[0] = 0;
522 switch (Chunk.fccID) {
523 case DMUS_FOURCC_UNFO_LIST: {
524 TRACE_(dmfile)(": UNFO list\n");
525 do {
526 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
527 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
528 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
530 hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &This->dmobj.desc);
531 if (FAILED(hr)) return hr;
533 if (hr == S_FALSE) {
534 switch (Chunk.fccID) {
535 default: {
536 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
537 liMove.QuadPart = Chunk.dwSize;
538 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
539 break;
543 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
544 } while (ListCount[0] < ListSize[0]);
545 break;
547 case DMUS_FOURCC_BANDS_LIST: {
548 TRACE_(dmfile)(": TRACK list\n");
549 hr = parse_bands_list(This, &Chunk, pStm);
550 if (FAILED(hr)) return hr;
551 break;
553 default: {
554 TRACE_(dmfile)(": unknown (skipping)\n");
555 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
556 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
557 break;
560 break;
562 default: {
563 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
564 liMove.QuadPart = Chunk.dwSize;
565 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
566 break;
570 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
571 } while (StreamCount < StreamSize);
573 return S_OK;
576 static inline IDirectMusicBandTrack *impl_from_IPersistStream(IPersistStream *iface)
578 return CONTAINING_RECORD(iface, IDirectMusicBandTrack, dmobj.IPersistStream_iface);
581 static HRESULT WINAPI IPersistStreamImpl_Load(IPersistStream *iface, IStream *pStm)
583 IDirectMusicBandTrack *This = impl_from_IPersistStream(iface);
584 DMUS_PRIVATE_CHUNK Chunk;
585 LARGE_INTEGER liMove;
586 HRESULT hr;
588 TRACE("(%p, %p): Loading\n", This, pStm);
590 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
591 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
592 switch (Chunk.fccID) {
593 case FOURCC_RIFF: {
594 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
595 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
596 switch (Chunk.fccID) {
597 case DMUS_FOURCC_BANDTRACK_FORM: {
598 TRACE_(dmfile)(": Band track form\n");
599 hr = parse_bandtrack_form(This, &Chunk, pStm);
600 if (FAILED(hr)) return hr;
601 break;
603 default: {
604 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
605 liMove.QuadPart = Chunk.dwSize;
606 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
607 return E_FAIL;
610 TRACE_(dmfile)(": reading finished\n");
611 break;
613 default: {
614 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
615 liMove.QuadPart = Chunk.dwSize;
616 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
617 return E_FAIL;
621 return S_OK;
624 static const IPersistStreamVtbl persiststream_vtbl = {
625 dmobj_IPersistStream_QueryInterface,
626 dmobj_IPersistStream_AddRef,
627 dmobj_IPersistStream_Release,
628 dmobj_IPersistStream_GetClassID,
629 unimpl_IPersistStream_IsDirty,
630 IPersistStreamImpl_Load,
631 unimpl_IPersistStream_Save,
632 unimpl_IPersistStream_GetSizeMax
635 /* for ClassFactory */
636 HRESULT WINAPI create_dmbandtrack(REFIID lpcGUID, void **ppobj)
638 IDirectMusicBandTrack *track;
639 HRESULT hr;
641 track = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*track));
642 if (!track) {
643 *ppobj = NULL;
644 return E_OUTOFMEMORY;
646 track->IDirectMusicTrack8_iface.lpVtbl = &dmtrack8_vtbl;
647 track->ref = 1;
648 dmobject_init(&track->dmobj, &CLSID_DirectMusicBandTrack,
649 (IUnknown *)&track->IDirectMusicTrack8_iface);
650 track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
651 list_init (&track->Bands);
653 DMBAND_LockModule();
654 hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
655 IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface);
657 return hr;