ntdll: Implement support for AT_ROUND_TO_PAGE flag in NtMapViewOfSection.
[wine.git] / dlls / dmband / bandtrack.c
blob3913e141d9fa9fb588a2af45e7572b0771e4af04
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 IDirectMusicTrack8Impl_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
44 void **ret_iface)
46 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
48 *ret_iface = NULL;
50 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicTrack) ||
51 IsEqualIID(riid, &IID_IDirectMusicTrack8))
52 *ret_iface = iface;
53 else if (IsEqualIID(riid, &IID_IPersistStream))
54 *ret_iface = &This->dmobj.IPersistStream_iface;
55 else {
56 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
57 return E_NOINTERFACE;
60 IUnknown_AddRef((IUnknown*)*ret_iface);
61 return S_OK;
64 static ULONG WINAPI IDirectMusicTrack8Impl_AddRef(IDirectMusicTrack8 *iface)
66 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
67 LONG ref = InterlockedIncrement(&This->ref);
69 TRACE("(%p) ref=%d\n", This, ref);
71 return ref;
74 static ULONG WINAPI IDirectMusicTrack8Impl_Release(IDirectMusicTrack8 *iface)
76 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
77 LONG ref = InterlockedDecrement(&This->ref);
79 TRACE("(%p) ref=%d\n", This, ref);
81 if (!ref) {
82 HeapFree(GetProcessHeap(), 0, This);
83 DMBAND_UnlockModule();
86 return ref;
89 static HRESULT WINAPI IDirectMusicTrack8Impl_Init(IDirectMusicTrack8 *iface,
90 IDirectMusicSegment *pSegment)
92 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
93 FIXME("(%p, %p): stub\n", This, pSegment);
94 return S_OK;
97 static HRESULT WINAPI IDirectMusicTrack8Impl_InitPlay(IDirectMusicTrack8 *iface,
98 IDirectMusicSegmentState *segment_state, IDirectMusicPerformance *performance,
99 void **state_data, DWORD virtual_track8id, DWORD flags)
101 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
103 FIXME("(%p, %p, %p, %p, %d, %x): stub\n", This, segment_state, performance, state_data, virtual_track8id, flags);
105 return S_OK;
108 static HRESULT WINAPI IDirectMusicTrack8Impl_EndPlay(IDirectMusicTrack8 *iface, void *pStateData)
110 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
111 FIXME("(%p, %p): stub\n", This, pStateData);
112 return S_OK;
115 static HRESULT WINAPI IDirectMusicTrack8Impl_Play(IDirectMusicTrack8 *iface, void *state_data,
116 MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, DWORD flags,
117 IDirectMusicPerformance *performance, IDirectMusicSegmentState *segment_state,
118 DWORD virtual_id)
120 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
122 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);
124 /* Sends following pMSG:
125 - DMUS_PATCH_PMSG
126 - DMUS_TRANSPOSE_PMSG
127 - DMUS_CHANNEL_PRIORITY_PMSG
128 - DMUS_MIDI_PMSG
131 return S_OK;
134 static HRESULT WINAPI IDirectMusicTrack8Impl_GetParam(IDirectMusicTrack8 *iface, REFGUID rguidType,
135 MUSIC_TIME mtTime, MUSIC_TIME *pmtNext, void *pParam)
137 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
138 FIXME("(%p, %s, %d, %p, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pmtNext, pParam);
139 return S_OK;
142 static HRESULT WINAPI IDirectMusicTrack8Impl_SetParam(IDirectMusicTrack8 *iface, REFGUID rguidType,
143 MUSIC_TIME mtTime, void *pParam)
145 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
146 FIXME("(%p, %s, %d, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pParam);
147 return S_OK;
150 static HRESULT WINAPI IDirectMusicTrack8Impl_IsParamSupported(IDirectMusicTrack8 *iface,
151 REFGUID rguidType)
153 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
155 TRACE("(%p, %s)\n", This, debugstr_dmguid(rguidType));
157 if (!rguidType)
158 return E_POINTER;
160 if (IsEqualGUID (rguidType, &GUID_BandParam)
161 || IsEqualGUID (rguidType, &GUID_Clear_All_Bands)
162 || IsEqualGUID (rguidType, &GUID_ConnectToDLSCollection)
163 || IsEqualGUID (rguidType, &GUID_Disable_Auto_Download)
164 || IsEqualGUID (rguidType, &GUID_Download)
165 || IsEqualGUID (rguidType, &GUID_DownloadToAudioPath)
166 || IsEqualGUID (rguidType, &GUID_Enable_Auto_Download)
167 || IsEqualGUID (rguidType, &GUID_IDirectMusicBand)
168 || IsEqualGUID (rguidType, &GUID_StandardMIDIFile)
169 || IsEqualGUID (rguidType, &GUID_Unload)
170 || IsEqualGUID (rguidType, &GUID_UnloadFromAudioPath)) {
171 TRACE("param supported\n");
172 return S_OK;
175 TRACE("param unsupported\n");
176 return DMUS_E_TYPE_UNSUPPORTED;
179 static HRESULT WINAPI IDirectMusicTrack8Impl_AddNotificationType(IDirectMusicTrack8 *iface,
180 REFGUID notiftype)
182 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
184 TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype));
185 return E_NOTIMPL;
188 static HRESULT WINAPI IDirectMusicTrack8Impl_RemoveNotificationType(IDirectMusicTrack8 *iface,
189 REFGUID notiftype)
191 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
193 TRACE("(%p, %s): method not implemented\n", This, debugstr_dmguid(notiftype));
194 return E_NOTIMPL;
197 static HRESULT WINAPI IDirectMusicTrack8Impl_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME mtStart,
198 MUSIC_TIME mtEnd, IDirectMusicTrack **ppTrack)
200 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
201 FIXME("(%p, %d, %d, %p): stub\n", This, mtStart, mtEnd, ppTrack);
202 return S_OK;
205 static HRESULT WINAPI IDirectMusicTrack8Impl_PlayEx(IDirectMusicTrack8 *iface, void *state_data,
206 REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD flags,
207 IDirectMusicPerformance *performance, IDirectMusicSegmentState *segment_state,
208 DWORD virtual_id)
210 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
212 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %x, %p, %p, %d): stub\n", This, state_data, wine_dbgstr_longlong(rtStart),
213 wine_dbgstr_longlong(rtEnd), wine_dbgstr_longlong(rtOffset), flags, performance, segment_state, virtual_id);
215 return S_OK;
218 static HRESULT WINAPI IDirectMusicTrack8Impl_GetParamEx(IDirectMusicTrack8 *iface,
219 REFGUID rguidType, REFERENCE_TIME rtTime, REFERENCE_TIME *rtNext, void *param,
220 void *state_data, DWORD flags)
222 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
224 FIXME("(%p, %s, 0x%s, %p, %p, %p, %x): stub\n", This, debugstr_dmguid(rguidType),
225 wine_dbgstr_longlong(rtTime), rtNext, param, state_data, flags);
227 return S_OK;
230 static HRESULT WINAPI IDirectMusicTrack8Impl_SetParamEx(IDirectMusicTrack8 *iface,
231 REFGUID rguidType, REFERENCE_TIME rtTime, void *param, void *state_data, DWORD flags)
233 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
235 FIXME("(%p, %s, 0x%s, %p, %p, %x): stub\n", This, debugstr_dmguid(rguidType),
236 wine_dbgstr_longlong(rtTime), param, state_data, flags);
238 return S_OK;
241 static HRESULT WINAPI IDirectMusicTrack8Impl_Compose(IDirectMusicTrack8 *iface, IUnknown *context,
242 DWORD trackgroup, IDirectMusicTrack **track)
244 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
246 TRACE("(%p, %p, %d, %p): method not implemented\n", This, context, trackgroup, track);
247 return E_NOTIMPL;
250 static HRESULT WINAPI IDirectMusicTrack8Impl_Join(IDirectMusicTrack8 *iface,
251 IDirectMusicTrack *pNewTrack, MUSIC_TIME mtJoin, IUnknown *pContext, DWORD dwTrackGroup,
252 IDirectMusicTrack **ppResultTrack)
254 IDirectMusicBandTrack *This = impl_from_IDirectMusicTrack8(iface);
255 FIXME("(%p, %p, %d, %p, %d, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
256 return S_OK;
259 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
260 IDirectMusicTrack8Impl_QueryInterface,
261 IDirectMusicTrack8Impl_AddRef,
262 IDirectMusicTrack8Impl_Release,
263 IDirectMusicTrack8Impl_Init,
264 IDirectMusicTrack8Impl_InitPlay,
265 IDirectMusicTrack8Impl_EndPlay,
266 IDirectMusicTrack8Impl_Play,
267 IDirectMusicTrack8Impl_GetParam,
268 IDirectMusicTrack8Impl_SetParam,
269 IDirectMusicTrack8Impl_IsParamSupported,
270 IDirectMusicTrack8Impl_AddNotificationType,
271 IDirectMusicTrack8Impl_RemoveNotificationType,
272 IDirectMusicTrack8Impl_Clone,
273 IDirectMusicTrack8Impl_PlayEx,
274 IDirectMusicTrack8Impl_GetParamEx,
275 IDirectMusicTrack8Impl_SetParamEx,
276 IDirectMusicTrack8Impl_Compose,
277 IDirectMusicTrack8Impl_Join
280 /* IDirectMusicBandTrack IPersistStream part: */
281 static HRESULT load_band(IDirectMusicBandTrack *This, IStream *pClonedStream,
282 IDirectMusicBand **ppBand, DMUS_PRIVATE_BAND_ITEM_HEADER *pHeader)
284 HRESULT hr = E_FAIL;
285 IPersistStream* pPersistStream = NULL;
287 hr = CoCreateInstance (&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicBand, (LPVOID*) ppBand);
288 if (FAILED(hr)) {
289 ERR(": could not create object\n");
290 return hr;
292 /* acquire PersistStream interface */
293 hr = IDirectMusicBand_QueryInterface (*ppBand, &IID_IPersistStream, (LPVOID*) &pPersistStream);
294 if (FAILED(hr)) {
295 ERR(": could not acquire IPersistStream\n");
296 return hr;
298 /* load */
299 hr = IPersistStream_Load (pPersistStream, pClonedStream);
300 if (FAILED(hr)) {
301 ERR(": failed to load object\n");
302 return hr;
305 /* release all loading-related stuff */
306 IPersistStream_Release (pPersistStream);
309 * @TODO insert pBand into This
311 if (SUCCEEDED(hr)) {
312 LPDMUS_PRIVATE_BAND pNewBand = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_BAND));
313 if (NULL == pNewBand) {
314 ERR(": no more memory\n");
315 return E_OUTOFMEMORY;
317 pNewBand->BandHeader = *pHeader;
318 pNewBand->band = *ppBand;
319 IDirectMusicBand_AddRef(*ppBand);
320 list_add_tail (&This->Bands, &pNewBand->entry);
323 return S_OK;
326 static HRESULT parse_bands_list(IDirectMusicBandTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
327 IStream *pStm)
329 HRESULT hr = E_FAIL;
330 DMUS_PRIVATE_CHUNK Chunk;
331 DWORD StreamSize, ListSize[3], ListCount[3];
332 LARGE_INTEGER liMove; /* used when skipping chunks */
334 IDirectMusicBand* pBand = NULL;
335 DMUS_PRIVATE_BAND_ITEM_HEADER header;
337 memset(&header, 0, sizeof header);
339 if (pChunk->fccID != DMUS_FOURCC_BANDS_LIST) {
340 ERR_(dmfile)(": %s chunk should be a BANDS list\n", debugstr_fourcc (pChunk->fccID));
341 return E_FAIL;
344 ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
345 ListCount[0] = 0;
347 do {
348 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
349 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
350 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
351 switch (Chunk.fccID) {
352 case FOURCC_LIST: {
353 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
354 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
355 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
356 ListCount[1] = 0;
357 do {
358 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
359 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
360 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
361 switch (Chunk.fccID) {
362 case DMUS_FOURCC_BANDITEM_CHUNK: {
363 DMUS_IO_BAND_ITEM_HEADER tmp_header;
364 TRACE_(dmfile)(": Band Item chunk v1\n");
366 IStream_Read (pStm, &tmp_header, sizeof(DMUS_IO_BAND_ITEM_HEADER), NULL);
367 TRACE_(dmfile)(" - lBandTime: %u\n", tmp_header.lBandTime);
369 header.dwVersion = 1;
370 header.lBandTime = tmp_header.lBandTime;
371 break;
373 case DMUS_FOURCC_BANDITEM_CHUNK2: {
374 DMUS_IO_BAND_ITEM_HEADER2 tmp_header2;
375 TRACE_(dmfile)(": Band Item chunk v2\n");
377 IStream_Read (pStm, &tmp_header2, sizeof(DMUS_IO_BAND_ITEM_HEADER2), NULL);
378 TRACE_(dmfile)(" - lBandTimeLogical: %u\n", tmp_header2.lBandTimeLogical);
379 TRACE_(dmfile)(" - lBandTimePhysical: %u\n", tmp_header2.lBandTimePhysical);
381 header.dwVersion = 2;
382 header.lBandTimeLogical = tmp_header2.lBandTimeLogical;
383 header.lBandTimePhysical = tmp_header2.lBandTimePhysical;
384 break;
386 case FOURCC_RIFF: {
387 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
388 TRACE_(dmfile)(": RIFF chunk of type %s\n", debugstr_fourcc(Chunk.fccID));
389 StreamSize = Chunk.dwSize - sizeof(FOURCC);
390 switch (Chunk.fccID) {
391 case DMUS_FOURCC_BAND_FORM: {
392 LPSTREAM pClonedStream = NULL;
393 TRACE_(dmfile)(": BAND RIFF\n");
395 IStream_Clone (pStm, &pClonedStream);
397 liMove.QuadPart = 0;
398 liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
399 IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
401 hr = load_band(This, pClonedStream, &pBand, &header);
402 if (FAILED(hr)) {
403 ERR(": could not load track\n");
404 return hr;
406 IStream_Release (pClonedStream);
408 IDirectMusicTrack_Release(pBand); pBand = NULL; /* now we can release at as it inserted */
410 /** now safe move the cursor */
411 liMove.QuadPart = StreamSize;
412 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
413 break;
415 default: {
416 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
417 liMove.QuadPart = StreamSize;
418 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
419 break;
422 break;
424 default: {
425 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
426 liMove.QuadPart = Chunk.dwSize;
427 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
428 break;
431 TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]);
432 } while (ListCount[1] < ListSize[1]);
433 break;
435 default: {
436 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
437 liMove.QuadPart = Chunk.dwSize;
438 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
439 break;
442 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
443 } while (ListCount[0] < ListSize[0]);
445 return S_OK;
448 static HRESULT parse_bandtrack_form(IDirectMusicBandTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
449 IStream *pStm)
451 HRESULT hr = E_FAIL;
452 DMUS_PRIVATE_CHUNK Chunk;
453 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
454 LARGE_INTEGER liMove; /* used when skipping chunks */
456 if (pChunk->fccID != DMUS_FOURCC_BANDTRACK_FORM) {
457 ERR_(dmfile)(": %s chunk should be a BANDTRACK form\n", debugstr_fourcc (pChunk->fccID));
458 return E_FAIL;
461 StreamSize = pChunk->dwSize - sizeof(FOURCC);
462 StreamCount = 0;
464 do {
465 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
466 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
467 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
469 hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, &This->dmobj.desc);
470 if (FAILED(hr)) return hr;
472 if (hr == S_FALSE) {
473 switch (Chunk.fccID) {
474 case DMUS_FOURCC_BANDTRACK_CHUNK: {
475 TRACE_(dmfile)(": BandTrack chunk\n");
476 IStream_Read (pStm, &This->header, sizeof(DMUS_IO_BAND_TRACK_HEADER), NULL);
477 TRACE_(dmfile)(" - bAutoDownload: %u\n", This->header.bAutoDownload);
478 break;
480 case FOURCC_LIST: {
481 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
482 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
483 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
484 ListCount[0] = 0;
485 switch (Chunk.fccID) {
486 case DMUS_FOURCC_UNFO_LIST: {
487 TRACE_(dmfile)(": UNFO list\n");
488 do {
489 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
490 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
491 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
493 hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &This->dmobj.desc);
494 if (FAILED(hr)) return hr;
496 if (hr == S_FALSE) {
497 switch (Chunk.fccID) {
498 default: {
499 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
500 liMove.QuadPart = Chunk.dwSize;
501 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
502 break;
506 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
507 } while (ListCount[0] < ListSize[0]);
508 break;
510 case DMUS_FOURCC_BANDS_LIST: {
511 TRACE_(dmfile)(": TRACK list\n");
512 hr = parse_bands_list(This, &Chunk, pStm);
513 if (FAILED(hr)) return hr;
514 break;
516 default: {
517 TRACE_(dmfile)(": unknown (skipping)\n");
518 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
519 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
520 break;
523 break;
525 default: {
526 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
527 liMove.QuadPart = Chunk.dwSize;
528 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
529 break;
533 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
534 } while (StreamCount < StreamSize);
536 return S_OK;
539 static inline IDirectMusicBandTrack *impl_from_IPersistStream(IPersistStream *iface)
541 return CONTAINING_RECORD(iface, IDirectMusicBandTrack, dmobj.IPersistStream_iface);
544 static HRESULT WINAPI IPersistStreamImpl_Load(IPersistStream *iface, IStream *pStm)
546 IDirectMusicBandTrack *This = impl_from_IPersistStream(iface);
547 DMUS_PRIVATE_CHUNK Chunk;
548 LARGE_INTEGER liMove;
549 HRESULT hr;
551 TRACE("(%p, %p): Loading\n", This, pStm);
553 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
554 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
555 switch (Chunk.fccID) {
556 case FOURCC_RIFF: {
557 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
558 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
559 switch (Chunk.fccID) {
560 case DMUS_FOURCC_BANDTRACK_FORM: {
561 TRACE_(dmfile)(": Band track form\n");
562 hr = parse_bandtrack_form(This, &Chunk, pStm);
563 if (FAILED(hr)) return hr;
564 break;
566 default: {
567 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
568 liMove.QuadPart = Chunk.dwSize;
569 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
570 return E_FAIL;
573 TRACE_(dmfile)(": reading finished\n");
574 break;
576 default: {
577 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
578 liMove.QuadPart = Chunk.dwSize;
579 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
580 return E_FAIL;
584 return S_OK;
587 static const IPersistStreamVtbl persiststream_vtbl = {
588 dmobj_IPersistStream_QueryInterface,
589 dmobj_IPersistStream_AddRef,
590 dmobj_IPersistStream_Release,
591 dmobj_IPersistStream_GetClassID,
592 unimpl_IPersistStream_IsDirty,
593 IPersistStreamImpl_Load,
594 unimpl_IPersistStream_Save,
595 unimpl_IPersistStream_GetSizeMax
598 /* for ClassFactory */
599 HRESULT WINAPI create_dmbandtrack(REFIID lpcGUID, void **ppobj)
601 IDirectMusicBandTrack *track;
602 HRESULT hr;
604 track = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*track));
605 if (!track) {
606 *ppobj = NULL;
607 return E_OUTOFMEMORY;
609 track->IDirectMusicTrack8_iface.lpVtbl = &dmtrack8_vtbl;
610 track->ref = 1;
611 dmobject_init(&track->dmobj, &CLSID_DirectMusicBandTrack,
612 (IUnknown *)&track->IDirectMusicTrack8_iface);
613 track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
614 list_init (&track->Bands);
616 DMBAND_LockModule();
617 hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
618 IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface);
620 return hr;