1 /* IDirectMusicBand 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"
22 WINE_DEFAULT_DEBUG_CHANNEL(dmband
);
23 WINE_DECLARE_DEBUG_CHANNEL(dmfile
);
26 /*****************************************************************************
27 * IDirectMusicBandImpl implementation
29 /* IDirectMusicBandImpl IUnknown part: */
30 static HRESULT WINAPI
IDirectMusicBandImpl_IUnknown_QueryInterface (LPUNKNOWN iface
, REFIID riid
, LPVOID
*ppobj
) {
31 ICOM_THIS_MULTI(IDirectMusicBandImpl
, UnknownVtbl
, iface
);
33 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ppobj
);
34 if (IsEqualIID (riid
, &IID_IUnknown
)) {
35 *ppobj
= &This
->UnknownVtbl
;
36 IUnknown_AddRef (iface
);
38 } else if (IsEqualIID (riid
, &IID_IDirectMusicBand
)) {
39 *ppobj
= &This
->BandVtbl
;
40 IUnknown_AddRef (iface
);
42 } else if (IsEqualIID (riid
, &IID_IDirectMusicObject
)) {
43 *ppobj
= &This
->ObjectVtbl
;
44 IUnknown_AddRef (iface
);
46 } else if (IsEqualIID (riid
, &IID_IPersistStream
)) {
47 *ppobj
= &This
->PersistStreamVtbl
;
48 IUnknown_AddRef (iface
);
52 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ppobj
);
56 static ULONG WINAPI
IDirectMusicBandImpl_IUnknown_AddRef (LPUNKNOWN iface
) {
57 ICOM_THIS_MULTI(IDirectMusicBandImpl
, UnknownVtbl
, iface
);
58 ULONG ref
= InterlockedIncrement(&This
->ref
);
60 TRACE("(%p) : AddRef from %d\n", This
, ref
- 1);
67 static ULONG WINAPI
IDirectMusicBandImpl_IUnknown_Release (LPUNKNOWN iface
) {
68 ICOM_THIS_MULTI(IDirectMusicBandImpl
, UnknownVtbl
, iface
);
69 ULONG ref
= InterlockedDecrement(&This
->ref
);
71 TRACE("(%p) : ReleaseRef to %d\n", This
, ref
);
74 HeapFree(GetProcessHeap(), 0, This
);
77 DMBAND_UnlockModule();
82 static const IUnknownVtbl DirectMusicBand_Unknown_Vtbl
= {
83 IDirectMusicBandImpl_IUnknown_QueryInterface
,
84 IDirectMusicBandImpl_IUnknown_AddRef
,
85 IDirectMusicBandImpl_IUnknown_Release
88 /* IDirectMusicBandImpl IDirectMusicBand part: */
89 static HRESULT WINAPI
IDirectMusicBandImpl_IDirectMusicBand_QueryInterface (LPDIRECTMUSICBAND iface
, REFIID riid
, LPVOID
*ppobj
) {
90 ICOM_THIS_MULTI(IDirectMusicBandImpl
, BandVtbl
, iface
);
91 return IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
94 static ULONG WINAPI
IDirectMusicBandImpl_IDirectMusicBand_AddRef (LPDIRECTMUSICBAND iface
) {
95 ICOM_THIS_MULTI(IDirectMusicBandImpl
, BandVtbl
, iface
);
96 return IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
99 static ULONG WINAPI
IDirectMusicBandImpl_IDirectMusicBand_Release (LPDIRECTMUSICBAND iface
) {
100 ICOM_THIS_MULTI(IDirectMusicBandImpl
, BandVtbl
, iface
);
101 return IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
104 static HRESULT WINAPI
IDirectMusicBandImpl_IDirectMusicBand_CreateSegment (LPDIRECTMUSICBAND iface
, IDirectMusicSegment
** ppSegment
) {
105 ICOM_THIS_MULTI(IDirectMusicBandImpl
, BandVtbl
, iface
);
106 FIXME("(%p, %p): stub\n", This
, ppSegment
);
110 static HRESULT WINAPI
IDirectMusicBandImpl_IDirectMusicBand_Download (LPDIRECTMUSICBAND iface
, IDirectMusicPerformance
* pPerformance
) {
111 ICOM_THIS_MULTI(IDirectMusicBandImpl
, BandVtbl
, iface
);
112 FIXME("(%p, %p): stub\n", This
, pPerformance
);
116 static HRESULT WINAPI
IDirectMusicBandImpl_IDirectMusicBand_Unload (LPDIRECTMUSICBAND iface
, IDirectMusicPerformance
* pPerformance
) {
117 ICOM_THIS_MULTI(IDirectMusicBandImpl
, BandVtbl
, iface
);
118 FIXME("(%p, %p): stub\n", This
, pPerformance
);
122 static const IDirectMusicBandVtbl DirectMusicBand_Band_Vtbl
= {
123 IDirectMusicBandImpl_IDirectMusicBand_QueryInterface
,
124 IDirectMusicBandImpl_IDirectMusicBand_AddRef
,
125 IDirectMusicBandImpl_IDirectMusicBand_Release
,
126 IDirectMusicBandImpl_IDirectMusicBand_CreateSegment
,
127 IDirectMusicBandImpl_IDirectMusicBand_Download
,
128 IDirectMusicBandImpl_IDirectMusicBand_Unload
131 /* IDirectMusicBandImpl IDirectMusicObject part: */
132 static HRESULT WINAPI
IDirectMusicBandImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface
, REFIID riid
, LPVOID
*ppobj
) {
133 ICOM_THIS_MULTI(IDirectMusicBandImpl
, ObjectVtbl
, iface
);
134 return IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
137 static ULONG WINAPI
IDirectMusicBandImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface
) {
138 ICOM_THIS_MULTI(IDirectMusicBandImpl
, ObjectVtbl
, iface
);
139 return IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
142 static ULONG WINAPI
IDirectMusicBandImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface
) {
143 ICOM_THIS_MULTI(IDirectMusicBandImpl
, ObjectVtbl
, iface
);
144 return IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
147 static HRESULT WINAPI
IDirectMusicBandImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
148 ICOM_THIS_MULTI(IDirectMusicBandImpl
, ObjectVtbl
, iface
);
149 TRACE("(%p, %p)\n", This
, pDesc
);
150 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
151 memcpy (pDesc
, This
->pDesc
, This
->pDesc
->dwSize
);
155 static HRESULT WINAPI
IDirectMusicBandImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
156 ICOM_THIS_MULTI(IDirectMusicBandImpl
, ObjectVtbl
, iface
);
157 TRACE("(%p, %p): setting descriptor:\n", This
, pDesc
); debug_DMUS_OBJECTDESC (pDesc
);
159 /* According to MSDN, we should copy only given values, not whole struct */
160 if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
161 This
->pDesc
->guidObject
= pDesc
->guidObject
;
162 if (pDesc
->dwValidData
& DMUS_OBJ_CLASS
)
163 This
->pDesc
->guidClass
= pDesc
->guidClass
;
164 if (pDesc
->dwValidData
& DMUS_OBJ_NAME
)
165 lstrcpynW (This
->pDesc
->wszName
, pDesc
->wszName
, DMUS_MAX_NAME
);
166 if (pDesc
->dwValidData
& DMUS_OBJ_CATEGORY
)
167 lstrcpynW (This
->pDesc
->wszCategory
, pDesc
->wszCategory
, DMUS_MAX_CATEGORY
);
168 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
)
169 lstrcpynW (This
->pDesc
->wszFileName
, pDesc
->wszFileName
, DMUS_MAX_FILENAME
);
170 if (pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
171 This
->pDesc
->vVersion
= pDesc
->vVersion
;
172 if (pDesc
->dwValidData
& DMUS_OBJ_DATE
)
173 This
->pDesc
->ftDate
= pDesc
->ftDate
;
174 if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
175 This
->pDesc
->llMemLength
= pDesc
->llMemLength
;
176 memcpy (This
->pDesc
->pbMemData
, pDesc
->pbMemData
, sizeof (pDesc
->pbMemData
));
178 if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
179 /* according to MSDN, we copy the stream */
180 IStream_Clone (pDesc
->pStream
, &This
->pDesc
->pStream
);
184 This
->pDesc
->dwValidData
|= pDesc
->dwValidData
;
189 static HRESULT WINAPI
IDirectMusicBandImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface
, LPSTREAM pStream
, LPDMUS_OBJECTDESC pDesc
) {
190 DMUS_PRIVATE_CHUNK Chunk
;
191 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
192 LARGE_INTEGER liMove
; /* used when skipping chunks */
194 TRACE("(%p, %p)\n", pStream
, pDesc
);
196 /* FIXME: should this be determined from stream? */
197 pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
198 pDesc
->guidClass
= CLSID_DirectMusicBand
;
200 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
201 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
202 switch (Chunk
.fccID
) {
204 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
205 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
206 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
208 if (Chunk
.fccID
== DMUS_FOURCC_BAND_FORM
) {
209 TRACE_(dmfile
)(": band form\n");
211 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
212 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
213 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
214 switch (Chunk
.fccID
) {
215 case DMUS_FOURCC_GUID_CHUNK
: {
216 TRACE_(dmfile
)(": GUID chunk\n");
217 pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
218 IStream_Read (pStream
, &pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
221 case DMUS_FOURCC_VERSION_CHUNK
: {
222 TRACE_(dmfile
)(": version chunk\n");
223 pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
224 IStream_Read (pStream
, &pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
227 case DMUS_FOURCC_CATEGORY_CHUNK
: {
228 TRACE_(dmfile
)(": category chunk\n");
229 pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
230 IStream_Read (pStream
, pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
234 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
235 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
236 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
238 switch (Chunk
.fccID
) {
239 /* evil M$ UNFO list, which can (!?) contain INFO elements */
240 case DMUS_FOURCC_UNFO_LIST
: {
241 TRACE_(dmfile
)(": UNFO list\n");
243 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
244 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
245 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
246 switch (Chunk
.fccID
) {
247 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
248 (though strings seem to be valid unicode) */
249 case mmioFOURCC('I','N','A','M'):
250 case DMUS_FOURCC_UNAM_CHUNK
: {
251 TRACE_(dmfile
)(": name chunk\n");
252 pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
253 IStream_Read (pStream
, pDesc
->wszName
, Chunk
.dwSize
, NULL
);
256 case mmioFOURCC('I','A','R','T'):
257 case DMUS_FOURCC_UART_CHUNK
: {
258 TRACE_(dmfile
)(": artist chunk (ignored)\n");
259 liMove
.QuadPart
= Chunk
.dwSize
;
260 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
263 case mmioFOURCC('I','C','O','P'):
264 case DMUS_FOURCC_UCOP_CHUNK
: {
265 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
266 liMove
.QuadPart
= Chunk
.dwSize
;
267 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
270 case mmioFOURCC('I','S','B','J'):
271 case DMUS_FOURCC_USBJ_CHUNK
: {
272 TRACE_(dmfile
)(": subject chunk (ignored)\n");
273 liMove
.QuadPart
= Chunk
.dwSize
;
274 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
277 case mmioFOURCC('I','C','M','T'):
278 case DMUS_FOURCC_UCMT_CHUNK
: {
279 TRACE_(dmfile
)(": comment chunk (ignored)\n");
280 liMove
.QuadPart
= Chunk
.dwSize
;
281 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
285 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
286 liMove
.QuadPart
= Chunk
.dwSize
;
287 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
291 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
292 } while (ListCount
[0] < ListSize
[0]);
296 TRACE_(dmfile
)(": unknown (skipping)\n");
297 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
298 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
305 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
306 liMove
.QuadPart
= Chunk
.dwSize
;
307 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
311 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
312 } while (StreamCount
< StreamSize
);
314 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
315 liMove
.QuadPart
= StreamSize
;
316 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
320 TRACE_(dmfile
)(": reading finished\n");
324 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
325 liMove
.QuadPart
= Chunk
.dwSize
;
326 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
327 return DMUS_E_INVALIDFILE
;
331 TRACE(": returning descriptor:\n"); debug_DMUS_OBJECTDESC (pDesc
);
336 static const IDirectMusicObjectVtbl DirectMusicBand_Object_Vtbl
= {
337 IDirectMusicBandImpl_IDirectMusicObject_QueryInterface
,
338 IDirectMusicBandImpl_IDirectMusicObject_AddRef
,
339 IDirectMusicBandImpl_IDirectMusicObject_Release
,
340 IDirectMusicBandImpl_IDirectMusicObject_GetDescriptor
,
341 IDirectMusicBandImpl_IDirectMusicObject_SetDescriptor
,
342 IDirectMusicBandImpl_IDirectMusicObject_ParseDescriptor
345 /* IDirectMusicBandImpl IPersistStream part: */
346 static HRESULT WINAPI
IDirectMusicBandImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface
, REFIID riid
, LPVOID
*ppobj
) {
347 ICOM_THIS_MULTI(IDirectMusicBandImpl
, PersistStreamVtbl
, iface
);
348 return IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
351 static ULONG WINAPI
IDirectMusicBandImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface
) {
352 ICOM_THIS_MULTI(IDirectMusicBandImpl
, PersistStreamVtbl
, iface
);
353 return IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
356 static ULONG WINAPI
IDirectMusicBandImpl_IPersistStream_Release (LPPERSISTSTREAM iface
) {
357 ICOM_THIS_MULTI(IDirectMusicBandImpl
, PersistStreamVtbl
, iface
);
358 return IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
361 static HRESULT WINAPI
IDirectMusicBandImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface
, CLSID
* pClassID
) {
362 ICOM_THIS_MULTI(IDirectMusicBandImpl
, PersistStreamVtbl
, iface
);
363 TRACE("(%p, %p)\n", This
, pClassID
);
364 *pClassID
= CLSID_DirectMusicBand
;
368 static HRESULT WINAPI
IDirectMusicBandImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface
) {
369 ICOM_THIS_MULTI(IDirectMusicBandImpl
, PersistStreamVtbl
, iface
);
370 FIXME("(%p): stub, always S_FALSE\n", This
);
374 static HRESULT
IDirectMusicBandImpl_IPersistStream_ParseInstrument (LPPERSISTSTREAM iface
, DMUS_PRIVATE_CHUNK
* pChunk
, IStream
* pStm
) {
375 ICOM_THIS_MULTI(IDirectMusicBandImpl
, PersistStreamVtbl
, iface
);
376 DMUS_PRIVATE_CHUNK Chunk
;
377 DWORD ListSize
[3], ListCount
[3];
378 LARGE_INTEGER liMove
; /* used when skipping chunks */
381 DMUS_IO_INSTRUMENT inst
;
382 LPDMUS_PRIVATE_INSTRUMENT pNewInstrument
;
383 IDirectMusicObject
* pObject
= NULL
;
385 if (pChunk
->fccID
!= DMUS_FOURCC_INSTRUMENT_LIST
) {
386 ERR_(dmfile
)(": %s chunk should be an INSTRUMENT list\n", debugstr_fourcc (pChunk
->fccID
));
390 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
394 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
395 ListCount
[0] += 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_INSTRUMENT_CHUNK
: {
399 TRACE_(dmfile
)(": Instrument chunk\n");
400 if (Chunk
.dwSize
!= sizeof(DMUS_IO_INSTRUMENT
)) return E_FAIL
;
401 IStream_Read (pStm
, &inst
, sizeof(DMUS_IO_INSTRUMENT
), NULL
);
402 TRACE_(dmfile
)(" - dwPatch: %u\n", inst
.dwPatch
);
403 TRACE_(dmfile
)(" - dwAssignPatch: %u\n", inst
.dwAssignPatch
);
404 TRACE_(dmfile
)(" - dwNoteRanges[0]: %u\n", inst
.dwNoteRanges
[0]);
405 TRACE_(dmfile
)(" - dwNoteRanges[1]: %u\n", inst
.dwNoteRanges
[1]);
406 TRACE_(dmfile
)(" - dwNoteRanges[2]: %u\n", inst
.dwNoteRanges
[2]);
407 TRACE_(dmfile
)(" - dwNoteRanges[3]: %u\n", inst
.dwNoteRanges
[3]);
408 TRACE_(dmfile
)(" - dwPChannel: %u\n", inst
.dwPChannel
);
409 TRACE_(dmfile
)(" - dwFlags: %u\n", inst
.dwFlags
);
410 TRACE_(dmfile
)(" - bPan: %u\n", inst
.bPan
);
411 TRACE_(dmfile
)(" - bVolume: %u\n", inst
.bVolume
);
412 TRACE_(dmfile
)(" - nTranspose: %d\n", inst
.nTranspose
);
413 TRACE_(dmfile
)(" - dwChannelPriority: %u\n", inst
.dwChannelPriority
);
414 TRACE_(dmfile
)(" - nPitchBendRange: %d\n", inst
.nPitchBendRange
);
418 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
419 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
420 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
422 switch (Chunk
.fccID
) {
423 case DMUS_FOURCC_REF_LIST
: {
424 FIXME_(dmfile
)(": DMRF (DM References) list\n");
425 hr
= IDirectMusicUtils_IPersistStream_ParseReference (iface
, &Chunk
, pStm
, &pObject
);
427 ERR(": could not load Reference\n");
433 TRACE_(dmfile
)(": unknown (skipping)\n");
434 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
435 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
442 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
443 liMove
.QuadPart
= Chunk
.dwSize
;
444 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
448 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
449 } while (ListCount
[0] < ListSize
[0]);
452 * @TODO insert pNewInstrument into This
454 pNewInstrument
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(DMUS_PRIVATE_INSTRUMENT
));
455 if (NULL
== pNewInstrument
) {
456 ERR(": no more memory\n");
457 return E_OUTOFMEMORY
;
459 memcpy(&pNewInstrument
->pInstrument
, &inst
, sizeof(DMUS_IO_INSTRUMENT
));
460 pNewInstrument
->ppReferenceCollection
= NULL
;
461 if (NULL
!= pObject
) {
462 IDirectMusicCollection
* pCol
= NULL
;
463 hr
= IDirectMusicObject_QueryInterface (pObject
, &IID_IDirectMusicCollection
, (void**) &pCol
);
465 ERR(": failed to get IDirectMusicCollection Interface from DMObject\n");
466 HeapFree(GetProcessHeap(), 0, pNewInstrument
);
470 pNewInstrument
->ppReferenceCollection
= pCol
;
471 IDirectMusicObject_Release(pObject
);
473 list_add_tail (&This
->Instruments
, &pNewInstrument
->entry
);
478 static HRESULT
IDirectMusicBandImpl_IPersistStream_ParseInstrumentsList (LPPERSISTSTREAM iface
, DMUS_PRIVATE_CHUNK
* pChunk
, IStream
* pStm
) {
479 /*ICOM_THIS_MULTI(IDirectMusicBandImpl, PersistStreamVtbl, iface);*/
481 DMUS_PRIVATE_CHUNK Chunk
;
482 DWORD ListSize
[3], ListCount
[3];
483 LARGE_INTEGER liMove
; /* used when skipping chunks */
485 if (pChunk
->fccID
!= DMUS_FOURCC_INSTRUMENTS_LIST
) {
486 ERR_(dmfile
)(": %s chunk should be an INSTRUMENTS list\n", debugstr_fourcc (pChunk
->fccID
));
490 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
494 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
495 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
496 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
497 switch (Chunk
.fccID
) {
499 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
500 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
501 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
503 switch (Chunk
.fccID
) {
504 case DMUS_FOURCC_INSTRUMENT_LIST
: {
505 TRACE_(dmfile
)(": Instrument list\n");
506 hr
= IDirectMusicBandImpl_IPersistStream_ParseInstrument (iface
, &Chunk
, pStm
);
507 if (FAILED(hr
)) return hr
;
511 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
512 liMove
.QuadPart
= ListSize
[1];
513 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
520 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
521 liMove
.QuadPart
= Chunk
.dwSize
;
522 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
526 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
527 } while (ListCount
[0] < ListSize
[0]);
532 static HRESULT
IDirectMusicBandImpl_IPersistStream_ParseBandForm (LPPERSISTSTREAM iface
, DMUS_PRIVATE_CHUNK
* pChunk
, IStream
* pStm
) {
534 ICOM_THIS_MULTI(IDirectMusicBandImpl
, PersistStreamVtbl
, iface
);
536 DMUS_PRIVATE_CHUNK Chunk
;
537 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
538 LARGE_INTEGER liMove
; /* used when skipping chunks */
542 if (pChunk
->fccID
!= DMUS_FOURCC_BAND_FORM
) {
543 ERR_(dmfile
)(": %s chunk should be a BAND form\n", debugstr_fourcc (pChunk
->fccID
));
547 StreamSize
= pChunk
->dwSize
- sizeof(FOURCC
);
551 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
552 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
553 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
555 hr
= IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk
, pStm
, This
->pDesc
);
556 if (FAILED(hr
)) return hr
;
559 switch (Chunk
.fccID
) {
560 case DMUS_FOURCC_GUID_CHUNK
: {
561 TRACE_(dmfile
)(": GUID\n");
562 IStream_Read (pStm
, &tmp_guid
, sizeof(GUID
), NULL
);
563 TRACE_(dmfile
)(" - guid: %s\n", debugstr_dmguid(&tmp_guid
));
567 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
568 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
569 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
571 switch (Chunk
.fccID
) {
572 case DMUS_FOURCC_UNFO_LIST
: {
573 TRACE_(dmfile
)(": UNFO list\n");
575 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
576 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
577 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
579 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, This
->pDesc
);
580 if (FAILED(hr
)) return hr
;
583 switch (Chunk
.fccID
) {
585 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
586 liMove
.QuadPart
= Chunk
.dwSize
;
587 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
592 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
593 } while (ListCount
[0] < ListSize
[0]);
596 case DMUS_FOURCC_INSTRUMENTS_LIST
: {
597 TRACE_(dmfile
)(": INSTRUMENTS list\n");
598 hr
= IDirectMusicBandImpl_IPersistStream_ParseInstrumentsList (iface
, &Chunk
, pStm
);
599 if (FAILED(hr
)) return hr
;
603 TRACE_(dmfile
)(": unknown (skipping)\n");
604 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
605 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
612 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
613 liMove
.QuadPart
= Chunk
.dwSize
;
614 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
619 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
620 } while (StreamCount
< StreamSize
);
625 static HRESULT WINAPI
IDirectMusicBandImpl_IPersistStream_Load (LPPERSISTSTREAM iface
, IStream
* pStm
) {
626 ICOM_THIS_MULTI(IDirectMusicBandImpl
, PersistStreamVtbl
, iface
);
628 DMUS_PRIVATE_CHUNK Chunk
;
629 LARGE_INTEGER liMove
;
632 TRACE("(%p,%p): loading\n", This
, pStm
);
634 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
635 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
636 switch (Chunk
.fccID
) {
638 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
639 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
640 switch (Chunk
.fccID
) {
641 case DMUS_FOURCC_BAND_FORM
: {
642 TRACE_(dmfile
)(": Band form\n");
643 hr
= IDirectMusicBandImpl_IPersistStream_ParseBandForm (iface
, &Chunk
, pStm
);
644 if (FAILED(hr
)) return hr
;
648 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
649 liMove
.QuadPart
= Chunk
.dwSize
;
650 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
654 TRACE_(dmfile
)(": reading finished\n");
658 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
659 liMove
.QuadPart
= Chunk
.dwSize
;
660 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
668 static HRESULT WINAPI
IDirectMusicBandImpl_IPersistStream_Save (LPPERSISTSTREAM iface
, IStream
* pStm
, BOOL fClearDirty
) {
669 ICOM_THIS_MULTI(IDirectMusicBandImpl
, PersistStreamVtbl
, iface
);
670 FIXME("(%p): Saving not implemented yet\n", This
);
674 static HRESULT WINAPI
IDirectMusicBandImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface
, ULARGE_INTEGER
* pcbSize
) {
678 static const IPersistStreamVtbl DirectMusicBand_PersistStream_Vtbl
= {
679 IDirectMusicBandImpl_IPersistStream_QueryInterface
,
680 IDirectMusicBandImpl_IPersistStream_AddRef
,
681 IDirectMusicBandImpl_IPersistStream_Release
,
682 IDirectMusicBandImpl_IPersistStream_GetClassID
,
683 IDirectMusicBandImpl_IPersistStream_IsDirty
,
684 IDirectMusicBandImpl_IPersistStream_Load
,
685 IDirectMusicBandImpl_IPersistStream_Save
,
686 IDirectMusicBandImpl_IPersistStream_GetSizeMax
689 /* for ClassFactory */
690 HRESULT WINAPI
DMUSIC_CreateDirectMusicBandImpl (LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
) {
691 IDirectMusicBandImpl
* obj
;
693 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicBandImpl
));
696 return E_OUTOFMEMORY
;
698 obj
->UnknownVtbl
= &DirectMusicBand_Unknown_Vtbl
;
699 obj
->BandVtbl
= &DirectMusicBand_Band_Vtbl
;
700 obj
->ObjectVtbl
= &DirectMusicBand_Object_Vtbl
;
701 obj
->PersistStreamVtbl
= &DirectMusicBand_PersistStream_Vtbl
;
702 obj
->pDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DMUS_OBJECTDESC
));
703 DM_STRUCT_INIT(obj
->pDesc
);
704 obj
->pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
705 obj
->pDesc
->guidClass
= CLSID_DirectMusicBand
;
706 obj
->ref
= 0; /* will be inited by QueryInterface */
707 list_init (&obj
->Instruments
);
709 return IDirectMusicBandImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&obj
->UnknownVtbl
, lpcGUID
, ppobj
);