2 * IDirectMusicCollection Implementation
4 * Copyright (C) 2003-2004 Rok Mandeljc
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "dmusic_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmusic
);
24 WINE_DECLARE_DEBUG_CHANNEL(dmfile
);
26 static inline IDirectMusicCollectionImpl
*impl_from_IDirectMusicCollection(IDirectMusicCollection
*iface
)
28 return CONTAINING_RECORD(iface
, IDirectMusicCollectionImpl
, IDirectMusicCollection_iface
);
31 static inline IDirectMusicCollectionImpl
*impl_from_IDirectMusicObject(IDirectMusicObject
*iface
)
33 return CONTAINING_RECORD(iface
, IDirectMusicCollectionImpl
, IDirectMusicObject_iface
);
36 static inline IDirectMusicCollectionImpl
*impl_from_IPersistStream(IPersistStream
*iface
)
38 return CONTAINING_RECORD(iface
, IDirectMusicCollectionImpl
, IPersistStream_iface
);
41 /*****************************************************************************
42 * IDirectMusicCollectionImpl implementation
44 /* IDirectMusicCollectionImpl IUnknown part: */
45 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicCollection_QueryInterface(LPDIRECTMUSICCOLLECTION iface
, REFIID riid
, LPVOID
*ret_iface
)
47 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicCollection(iface
);
49 TRACE("(%p/%p)->(%s, %p)\n", iface
, This
, debugstr_dmguid(riid
), ret_iface
);
51 if (IsEqualIID(riid
, &IID_IUnknown
) ||
52 IsEqualIID(riid
, &IID_IDirectMusicCollection
))
55 IDirectMusicCollection_AddRef(iface
);
58 else if (IsEqualIID(riid
, &IID_IDirectMusicObject
))
60 *ret_iface
= &This
->IDirectMusicObject_iface
;
61 IDirectMusicCollection_AddRef(iface
);
64 else if (IsEqualIID(riid
, &IID_IPersistStream
))
66 *ret_iface
= &This
->IPersistStream_iface
;
67 IDirectMusicCollection_AddRef(iface
);
73 WARN("(%p/%p)->(%s, %p): not found\n", iface
, This
, debugstr_dmguid(riid
), ret_iface
);
78 static ULONG WINAPI
IDirectMusicCollectionImpl_IDirectMusicCollection_AddRef(LPDIRECTMUSICCOLLECTION iface
)
80 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicCollection(iface
);
81 ULONG ref
= InterlockedIncrement(&This
->ref
);
83 TRACE("(%p/%p)->(): new ref = %u)\n", iface
, This
, ref
);
90 static ULONG WINAPI
IDirectMusicCollectionImpl_IDirectMusicCollection_Release(LPDIRECTMUSICCOLLECTION iface
)
92 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicCollection(iface
);
93 ULONG ref
= InterlockedDecrement(&This
->ref
);
95 TRACE("(%p/%p)->(): new ref = %u)\n", iface
, This
, ref
);
98 HeapFree(GetProcessHeap(), 0, This
);
100 DMUSIC_UnlockModule();
105 /* IDirectMusicCollection Interface follows: */
106 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicCollection_GetInstrument(LPDIRECTMUSICCOLLECTION iface
, DWORD patch
, IDirectMusicInstrument
** instrument
)
108 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicCollection(iface
);
109 DMUS_PRIVATE_INSTRUMENTENTRY
*inst_entry
;
110 struct list
*list_entry
;
113 TRACE("(%p/%p)->(%u, %p)\n", iface
, This
, patch
, instrument
);
115 LIST_FOR_EACH(list_entry
, &This
->Instruments
) {
116 inst_entry
= LIST_ENTRY(list_entry
, DMUS_PRIVATE_INSTRUMENTENTRY
, entry
);
117 IDirectMusicInstrument_GetPatch(inst_entry
->pInstrument
, &inst_patch
);
118 if (patch
== inst_patch
) {
119 *instrument
= inst_entry
->pInstrument
;
120 IDirectMusicInstrument_AddRef(inst_entry
->pInstrument
);
121 IDirectMusicInstrumentImpl_Custom_Load(inst_entry
->pInstrument
, This
->pStm
);
122 TRACE(": returning instrument %p\n", *instrument
);
127 TRACE(": instrument not found\n");
129 return DMUS_E_INVALIDPATCH
;
132 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicCollection_EnumInstrument(LPDIRECTMUSICCOLLECTION iface
, DWORD index
, DWORD
* patch
, LPWSTR name
, DWORD name_length
)
134 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicCollection(iface
);
136 DMUS_PRIVATE_INSTRUMENTENTRY
*inst_entry
;
137 struct list
*list_entry
;
140 TRACE("(%p/%p)->(%d, %p, %p, %d)\n", iface
, This
, index
, patch
, name
, name_length
);
142 LIST_FOR_EACH(list_entry
, &This
->Instruments
) {
143 inst_entry
= LIST_ENTRY(list_entry
, DMUS_PRIVATE_INSTRUMENTENTRY
, entry
);
145 IDirectMusicInstrumentImpl
*instrument
= impl_from_IDirectMusicInstrument(inst_entry
->pInstrument
);
146 IDirectMusicInstrument_GetPatch(inst_entry
->pInstrument
, patch
);
148 length
= min(strlenW(instrument
->wszName
), name_length
- 1);
149 memcpy(name
, instrument
->wszName
, length
* sizeof(WCHAR
));
160 static const IDirectMusicCollectionVtbl DirectMusicCollection_Collection_Vtbl
= {
161 IDirectMusicCollectionImpl_IDirectMusicCollection_QueryInterface
,
162 IDirectMusicCollectionImpl_IDirectMusicCollection_AddRef
,
163 IDirectMusicCollectionImpl_IDirectMusicCollection_Release
,
164 IDirectMusicCollectionImpl_IDirectMusicCollection_GetInstrument
,
165 IDirectMusicCollectionImpl_IDirectMusicCollection_EnumInstrument
168 /* IDirectMusicCollectionImpl IDirectMusicObject part: */
169 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_QueryInterface(LPDIRECTMUSICOBJECT iface
, REFIID riid
, LPVOID
*ret_iface
)
171 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
172 return IDirectMusicCollection_QueryInterface(&This
->IDirectMusicCollection_iface
, riid
, ret_iface
);
175 static ULONG WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_AddRef(LPDIRECTMUSICOBJECT iface
)
177 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
178 return IDirectMusicCollection_AddRef(&This
->IDirectMusicCollection_iface
);
181 static ULONG WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_Release(LPDIRECTMUSICOBJECT iface
)
183 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
184 return IDirectMusicCollection_Release(&This
->IDirectMusicCollection_iface
);
187 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_GetDescriptor(LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
)
189 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
191 TRACE("(%p/%p)->(%p)\n", iface
, This
, pDesc
);
193 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
194 memcpy (pDesc
, This
->pDesc
, This
->pDesc
->dwSize
);
199 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_SetDescriptor(LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
)
201 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
203 TRACE("(%p, %p)\n", iface
, pDesc
);
208 if (TRACE_ON(dmusic
))
210 TRACE("Setting descriptor:\n");
211 dump_DMUS_OBJECTDESC(pDesc
);
214 /* According to MSDN, we should copy only given values, not whole struct */
215 if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
216 This
->pDesc
->guidObject
= pDesc
->guidObject
;
217 if (pDesc
->dwValidData
& DMUS_OBJ_CLASS
)
218 This
->pDesc
->guidClass
= pDesc
->guidClass
;
219 if (pDesc
->dwValidData
& DMUS_OBJ_NAME
)
220 lstrcpynW(This
->pDesc
->wszName
, pDesc
->wszName
, DMUS_MAX_NAME
);
221 if (pDesc
->dwValidData
& DMUS_OBJ_CATEGORY
)
222 lstrcpynW(This
->pDesc
->wszCategory
, pDesc
->wszCategory
, DMUS_MAX_CATEGORY
);
223 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
)
224 lstrcpynW(This
->pDesc
->wszFileName
, pDesc
->wszFileName
, DMUS_MAX_FILENAME
);
225 if (pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
226 This
->pDesc
->vVersion
= pDesc
->vVersion
;
227 if (pDesc
->dwValidData
& DMUS_OBJ_DATE
)
228 This
->pDesc
->ftDate
= pDesc
->ftDate
;
229 if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
230 This
->pDesc
->llMemLength
= pDesc
->llMemLength
;
231 memcpy (This
->pDesc
->pbMemData
, pDesc
->pbMemData
, pDesc
->llMemLength
);
233 if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
234 /* according to MSDN, we copy the stream */
235 IStream_Clone (pDesc
->pStream
, &This
->pDesc
->pStream
);
239 This
->pDesc
->dwValidData
|= pDesc
->dwValidData
;
244 static HRESULT
read_from_stream(IStream
*stream
, void *data
, ULONG size
)
249 hr
= IStream_Read(stream
, data
, size
, &read
);
251 TRACE("IStream_Read failed: %08x\n", hr
);
255 TRACE("Didn't read full chunk: %u < %u\n", read
, size
);
262 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_ParseDescriptor(LPDIRECTMUSICOBJECT iface
, LPSTREAM stream
, LPDMUS_OBJECTDESC desc
)
264 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
265 DMUS_PRIVATE_CHUNK chunk
;
266 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
267 LARGE_INTEGER liMove
; /* used when skipping chunks */
270 TRACE("(%p)->(%p, %p)\n", This
, stream
, desc
);
272 /* FIXME: should this be determined from stream? */
273 desc
->dwValidData
|= DMUS_OBJ_CLASS
;
274 desc
->guidClass
= CLSID_DirectMusicCollection
;
276 hr
= read_from_stream(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
));
279 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
281 if (chunk
.fccID
!= FOURCC_RIFF
) {
282 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
283 liMove
.QuadPart
= chunk
.dwSize
;
284 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
285 return DMUS_E_INVALIDFILE
;
288 hr
= read_from_stream(stream
, &chunk
.fccID
, sizeof(FOURCC
));
291 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(chunk
.fccID
));
292 StreamSize
= chunk
.dwSize
- sizeof(FOURCC
);
294 if (chunk
.fccID
!= mmioFOURCC('D','L','S',' ')) {
295 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
296 liMove
.QuadPart
= StreamSize
;
297 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
302 TRACE_(dmfile
)(": collection form\n");
305 hr
= read_from_stream(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
));
308 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
309 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
310 switch (chunk
.fccID
) {
312 TRACE_(dmfile
)(": GUID chunk\n");
313 desc
->dwValidData
|= DMUS_OBJ_OBJECT
;
314 hr
= read_from_stream(stream
, &desc
->guidObject
, chunk
.dwSize
);
319 case DMUS_FOURCC_VERSION_CHUNK
:
320 TRACE_(dmfile
)(": version chunk\n");
321 desc
->dwValidData
|= DMUS_OBJ_VERSION
;
322 hr
= read_from_stream(stream
, &desc
->vVersion
, chunk
.dwSize
);
327 case DMUS_FOURCC_CATEGORY_CHUNK
:
328 TRACE_(dmfile
)(": category chunk\n");
329 desc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
330 hr
= read_from_stream(stream
, desc
->wszCategory
, chunk
.dwSize
);
336 hr
= read_from_stream(stream
, &chunk
.fccID
, sizeof(FOURCC
));
339 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(chunk
.fccID
));
340 ListSize
[0] = chunk
.dwSize
- sizeof(FOURCC
);
342 switch (chunk
.fccID
) {
343 /* pure INFO list, such can be found in dls collections */
344 case mmioFOURCC('I','N','F','O'):
345 TRACE_(dmfile
)(": INFO list\n");
347 hr
= read_from_stream(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
));
350 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
351 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
352 switch (chunk
.fccID
) {
353 case mmioFOURCC('I','N','A','M'): {
354 CHAR szName
[DMUS_MAX_NAME
];
355 TRACE_(dmfile
)(": name chunk\n");
356 desc
->dwValidData
|= DMUS_OBJ_NAME
;
357 hr
= read_from_stream(stream
, szName
, chunk
.dwSize
);
360 MultiByteToWideChar (CP_ACP
, 0, szName
, -1, desc
->wszName
, DMUS_MAX_NAME
);
361 if (even_or_odd(chunk
.dwSize
)) {
364 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
369 case mmioFOURCC('I','A','R','T'):
370 TRACE_(dmfile
)(": artist chunk (ignored)\n");
371 if (even_or_odd(chunk
.dwSize
)) {
375 liMove
.QuadPart
= chunk
.dwSize
;
376 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
379 case mmioFOURCC('I','C','O','P'):
380 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
381 if (even_or_odd(chunk
.dwSize
)) {
385 liMove
.QuadPart
= chunk
.dwSize
;
386 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
389 case mmioFOURCC('I','S','B','J'):
390 TRACE_(dmfile
)(": subject chunk (ignored)\n");
391 if (even_or_odd(chunk
.dwSize
)) {
395 liMove
.QuadPart
= chunk
.dwSize
;
396 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
399 case mmioFOURCC('I','C','M','T'):
400 TRACE_(dmfile
)(": comment chunk (ignored)\n");
401 if (even_or_odd(chunk
.dwSize
)) {
404 liMove
.QuadPart
= chunk
.dwSize
;
405 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
410 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
411 if (even_or_odd(chunk
.dwSize
)) {
415 liMove
.QuadPart
= chunk
.dwSize
;
416 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
419 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
420 } while (ListCount
[0] < ListSize
[0]);
424 TRACE_(dmfile
)(": unknown (skipping)\n");
425 liMove
.QuadPart
= chunk
.dwSize
- sizeof(FOURCC
);
426 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
432 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
433 liMove
.QuadPart
= chunk
.dwSize
;
434 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
437 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
438 } while (StreamCount
< StreamSize
);
440 TRACE_(dmfile
)(": reading finished\n");
442 if (TRACE_ON(dmusic
)) {
443 TRACE("Returning descriptor:\n");
444 dump_DMUS_OBJECTDESC(desc
);
450 static const IDirectMusicObjectVtbl DirectMusicCollection_Object_Vtbl
= {
451 IDirectMusicCollectionImpl_IDirectMusicObject_QueryInterface
,
452 IDirectMusicCollectionImpl_IDirectMusicObject_AddRef
,
453 IDirectMusicCollectionImpl_IDirectMusicObject_Release
,
454 IDirectMusicCollectionImpl_IDirectMusicObject_GetDescriptor
,
455 IDirectMusicCollectionImpl_IDirectMusicObject_SetDescriptor
,
456 IDirectMusicCollectionImpl_IDirectMusicObject_ParseDescriptor
459 /* IDirectMusicCollectionImpl IPersistStream part: */
460 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_QueryInterface(LPPERSISTSTREAM iface
, REFIID riid
, LPVOID
*ret_iface
)
462 IDirectMusicCollectionImpl
*This
= impl_from_IPersistStream(iface
);
463 return IDirectMusicCollection_QueryInterface(&This
->IDirectMusicCollection_iface
, riid
, ret_iface
);
466 static ULONG WINAPI
IDirectMusicCollectionImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface
)
468 IDirectMusicCollectionImpl
*This
= impl_from_IPersistStream(iface
);
469 return IDirectMusicCollection_AddRef(&This
->IDirectMusicCollection_iface
);
472 static ULONG WINAPI
IDirectMusicCollectionImpl_IPersistStream_Release (LPPERSISTSTREAM iface
)
474 IDirectMusicCollectionImpl
*This
= impl_from_IPersistStream(iface
);
475 return IDirectMusicCollection_Release(&This
->IDirectMusicCollection_iface
);
478 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_GetClassID(LPPERSISTSTREAM iface
, CLSID
* pClassID
)
483 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_IsDirty(LPPERSISTSTREAM iface
)
488 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_Load(LPPERSISTSTREAM iface
, IStream
* stream
)
490 IDirectMusicCollectionImpl
*This
= impl_from_IPersistStream(iface
);
491 DMUS_PRIVATE_CHUNK chunk
;
492 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
493 LARGE_INTEGER liMove
; /* used when skipping chunks */
494 ULARGE_INTEGER dlibCollectionPosition
, dlibInstrumentPosition
, dlibWavePoolPosition
;
496 IStream_AddRef(stream
); /* add count for later references */
498 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, &dlibCollectionPosition
); /* store offset, in case it'll be needed later */
499 This
->liCollectionPosition
.QuadPart
= dlibCollectionPosition
.QuadPart
;
502 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
503 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
505 if (chunk
.fccID
!= FOURCC_RIFF
) {
506 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
507 liMove
.QuadPart
= chunk
.dwSize
;
508 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
512 IStream_Read(stream
, &chunk
.fccID
, sizeof(FOURCC
), NULL
);
513 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(chunk
.fccID
));
514 StreamSize
= chunk
.dwSize
- sizeof(FOURCC
);
517 if (chunk
.fccID
!= FOURCC_DLS
) {
518 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
519 liMove
.QuadPart
= StreamSize
;
520 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
524 TRACE_(dmfile
)(": collection form\n");
526 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
527 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
528 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
529 switch (chunk
.fccID
) {
531 TRACE_(dmfile
)(": collection header chunk\n");
532 This
->pHeader
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, chunk
.dwSize
);
533 IStream_Read(stream
, This
->pHeader
, chunk
.dwSize
, NULL
);
537 TRACE_(dmfile
)(": DLID (GUID) chunk\n");
538 This
->pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
539 IStream_Read(stream
, &This
->pDesc
->guidObject
, chunk
.dwSize
, NULL
);
543 TRACE_(dmfile
)(": version chunk\n");
544 This
->pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
545 IStream_Read(stream
, &This
->pDesc
->vVersion
, chunk
.dwSize
, NULL
);
549 TRACE_(dmfile
)(": pool table chunk\n");
550 This
->pPoolTable
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(POOLTABLE
));
551 IStream_Read(stream
, This
->pPoolTable
, sizeof(POOLTABLE
), NULL
);
552 chunk
.dwSize
-= sizeof(POOLTABLE
);
553 This
->pPoolCues
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->pPoolTable
->cCues
* sizeof(POOLCUE
));
554 IStream_Read(stream
, This
->pPoolCues
, chunk
.dwSize
, NULL
);
558 IStream_Read(stream
, &chunk
.fccID
, sizeof(FOURCC
), NULL
);
559 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(chunk
.fccID
));
560 ListSize
[0] = chunk
.dwSize
- sizeof(FOURCC
);
562 switch (chunk
.fccID
) {
563 case mmioFOURCC('I','N','F','O'): {
564 TRACE_(dmfile
)(": INFO list\n");
566 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
567 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
568 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
569 switch (chunk
.fccID
) {
570 case mmioFOURCC('I','N','A','M'): {
571 CHAR szName
[DMUS_MAX_NAME
];
572 TRACE_(dmfile
)(": name chunk\n");
573 This
->pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
574 IStream_Read(stream
, szName
, chunk
.dwSize
, NULL
);
575 MultiByteToWideChar(CP_ACP
, 0, szName
, -1, This
->pDesc
->wszName
, DMUS_MAX_NAME
);
576 if (even_or_odd(chunk
.dwSize
)) {
579 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
583 case mmioFOURCC('I','A','R','T'): {
584 TRACE_(dmfile
)(": artist chunk (ignored)\n");
585 if (even_or_odd(chunk
.dwSize
)) {
589 liMove
.QuadPart
= chunk
.dwSize
;
590 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
593 case mmioFOURCC('I','C','O','P'): {
594 TRACE_(dmfile
)(": copyright chunk\n");
595 This
->szCopyright
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, chunk
.dwSize
);
596 IStream_Read(stream
, This
->szCopyright
, chunk
.dwSize
, NULL
);
597 if (even_or_odd(chunk
.dwSize
)) {
600 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
604 case mmioFOURCC('I','S','B','J'): {
605 TRACE_(dmfile
)(": subject chunk (ignored)\n");
606 if (even_or_odd(chunk
.dwSize
)) {
610 liMove
.QuadPart
= chunk
.dwSize
;
611 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
614 case mmioFOURCC('I','C','M','T'): {
615 TRACE_(dmfile
)(": comment chunk (ignored)\n");
616 if (even_or_odd(chunk
.dwSize
)) {
620 liMove
.QuadPart
= chunk
.dwSize
;
621 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
625 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
626 if (even_or_odd(chunk
.dwSize
)) {
630 liMove
.QuadPart
= chunk
.dwSize
;
631 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
635 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
636 } while (ListCount
[0] < ListSize
[0]);
640 TRACE_(dmfile
)(": wave pool list (mark & skip)\n");
642 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, &dlibWavePoolPosition
); /* store position */
643 This
->liWavePoolTablePosition
.QuadPart
= dlibWavePoolPosition
.QuadPart
;
644 liMove
.QuadPart
= chunk
.dwSize
- sizeof(FOURCC
);
645 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
649 TRACE_(dmfile
)(": instruments list\n");
651 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
652 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
653 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
654 switch (chunk
.fccID
) {
656 IStream_Read(stream
, &chunk
.fccID
, sizeof(FOURCC
), NULL
);
657 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(chunk
.fccID
));
658 ListSize
[1] = chunk
.dwSize
- sizeof(FOURCC
);
660 switch (chunk
.fccID
) {
662 LPDMUS_PRIVATE_INSTRUMENTENTRY new_instrument
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DMUS_PRIVATE_INSTRUMENTENTRY
));
663 TRACE_(dmfile
)(": instrument list\n");
664 /* Only way to create this one... even M$ does it discretely */
665 DMUSIC_CreateDirectMusicInstrumentImpl(&IID_IDirectMusicInstrument
, (LPVOID
*)&new_instrument
->pInstrument
, NULL
);
667 IDirectMusicInstrumentImpl
*instrument
= impl_from_IDirectMusicInstrument(new_instrument
->pInstrument
);
669 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, &dlibInstrumentPosition
);
670 /* Store offset, it'll be needed later */
671 instrument
->liInstrumentPosition
.QuadPart
= dlibInstrumentPosition
.QuadPart
- (2 * sizeof(FOURCC
) + sizeof(DWORD
));
673 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
674 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
675 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
676 switch (chunk
.fccID
) {
678 TRACE_(dmfile
)(": instrument header chunk\n");
679 instrument
->pHeader
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, chunk
.dwSize
);
680 IStream_Read(stream
, instrument
->pHeader
, chunk
.dwSize
, NULL
);
684 TRACE_(dmfile
)(": DLID (GUID) chunk\n");
685 instrument
->pInstrumentID
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, chunk
.dwSize
);
686 IStream_Read(stream
, instrument
->pInstrumentID
, chunk
.dwSize
, NULL
);
690 IStream_Read(stream
, &chunk
.fccID
, sizeof(FOURCC
), NULL
);
691 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(chunk
.fccID
));
692 ListSize
[2] = chunk
.dwSize
- sizeof(FOURCC
);
694 switch (chunk
.fccID
) {
696 TRACE_(dmfile
)(": unknown (skipping)\n");
697 liMove
.QuadPart
= chunk
.dwSize
- sizeof(FOURCC
);
698 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
705 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
706 liMove
.QuadPart
= chunk
.dwSize
;
707 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
711 TRACE_(dmfile
)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount
[1], ListSize
[1]);
712 } while (ListCount
[1] < ListSize
[1]);
713 /* DEBUG: dumps whole instrument object tree: */
714 if (TRACE_ON(dmusic
)) {
715 TRACE("*** IDirectMusicInstrument (%p) ***\n", instrument
);
716 if (instrument
->pInstrumentID
)
717 TRACE(" - GUID = %s\n", debugstr_dmguid(instrument
->pInstrumentID
));
718 TRACE(" - Instrument header:\n");
719 TRACE(" - cRegions: %d\n", instrument
->pHeader
->cRegions
);
720 TRACE(" - Locale:\n");
721 TRACE(" - ulBank: %d\n", instrument
->pHeader
->Locale
.ulBank
);
722 TRACE(" - ulInstrument: %d\n", instrument
->pHeader
->Locale
.ulInstrument
);
723 TRACE(" => dwPatch: %d\n", MIDILOCALE2Patch(&instrument
->pHeader
->Locale
));
725 list_add_tail(&This
->Instruments
, &new_instrument
->entry
);
733 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
734 liMove
.QuadPart
= chunk
.dwSize
;
735 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
739 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
740 } while (ListCount
[0] < ListSize
[0]);
744 TRACE_(dmfile
)(": unknown (skipping)\n");
745 liMove
.QuadPart
= chunk
.dwSize
- sizeof(FOURCC
);
746 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
753 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
754 liMove
.QuadPart
= chunk
.dwSize
;
755 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
759 TRACE_(dmfile
)(": StreamCount = %d < StreamSize = %d\n", StreamCount
, StreamSize
);
760 } while (StreamCount
< StreamSize
);
762 TRACE_(dmfile
)(": reading finished\n");
765 /* DEBUG: dumps whole collection object tree: */
766 if (TRACE_ON(dmusic
)) {
768 DMUS_PRIVATE_INSTRUMENTENTRY
*tmpEntry
;
769 struct list
*listEntry
;
771 TRACE("*** IDirectMusicCollection (%p) ***\n", &This
->IDirectMusicCollection_iface
);
772 if (This
->pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
773 TRACE(" - GUID = %s\n", debugstr_dmguid(&This
->pDesc
->guidObject
));
774 if (This
->pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
775 TRACE(" - Version = %i,%i,%i,%i\n", (This
->pDesc
->vVersion
.dwVersionMS
>> 8) & 0x0000FFFF, This
->pDesc
->vVersion
.dwVersionMS
& 0x0000FFFF,
776 (This
->pDesc
->vVersion
.dwVersionLS
>> 8) & 0x0000FFFF, This
->pDesc
->vVersion
.dwVersionLS
& 0x0000FFFF);
777 if (This
->pDesc
->dwValidData
& DMUS_OBJ_NAME
)
778 TRACE(" - Name = %s\n", debugstr_w(This
->pDesc
->wszName
));
780 TRACE(" - Collection header:\n");
781 TRACE(" - cInstruments: %d\n", This
->pHeader
->cInstruments
);
782 TRACE(" - Instruments:\n");
784 LIST_FOR_EACH(listEntry
, &This
->Instruments
) {
785 tmpEntry
= LIST_ENTRY( listEntry
, DMUS_PRIVATE_INSTRUMENTENTRY
, entry
);
786 TRACE(" - Instrument[%i]: %p\n", r
, tmpEntry
->pInstrument
);
794 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_Save(LPPERSISTSTREAM iface
, IStream
* pStm
, BOOL fClearDirty
)
799 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_GetSizeMax(LPPERSISTSTREAM iface
, ULARGE_INTEGER
* pcbSize
)
804 static const IPersistStreamVtbl DirectMusicCollection_PersistStream_Vtbl
= {
805 IDirectMusicCollectionImpl_IPersistStream_QueryInterface
,
806 IDirectMusicCollectionImpl_IPersistStream_AddRef
,
807 IDirectMusicCollectionImpl_IPersistStream_Release
,
808 IDirectMusicCollectionImpl_IPersistStream_GetClassID
,
809 IDirectMusicCollectionImpl_IPersistStream_IsDirty
,
810 IDirectMusicCollectionImpl_IPersistStream_Load
,
811 IDirectMusicCollectionImpl_IPersistStream_Save
,
812 IDirectMusicCollectionImpl_IPersistStream_GetSizeMax
816 /* for ClassFactory */
817 HRESULT WINAPI
DMUSIC_CreateDirectMusicCollectionImpl(LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
)
819 IDirectMusicCollectionImpl
* obj
;
821 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicCollectionImpl
));
824 return E_OUTOFMEMORY
;
826 obj
->IDirectMusicCollection_iface
.lpVtbl
= &DirectMusicCollection_Collection_Vtbl
;
827 obj
->IDirectMusicObject_iface
.lpVtbl
= &DirectMusicCollection_Object_Vtbl
;
828 obj
->IPersistStream_iface
.lpVtbl
= &DirectMusicCollection_PersistStream_Vtbl
;
829 obj
->pDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DMUS_OBJECTDESC
));
830 DM_STRUCT_INIT(obj
->pDesc
);
831 obj
->pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
832 obj
->pDesc
->guidClass
= CLSID_DirectMusicCollection
;
833 obj
->ref
= 0; /* will be inited by QueryInterface */
834 list_init (&obj
->Instruments
);
836 return IDirectMusicCollection_QueryInterface(&obj
->IDirectMusicCollection_iface
, lpcGUID
, ppobj
);