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
);
53 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDirectMusicCollection
))
55 else if (IsEqualIID(riid
, &IID_IDirectMusicObject
))
56 *ret_iface
= &This
->IDirectMusicObject_iface
;
57 else if (IsEqualIID(riid
, &IID_IPersistStream
))
58 *ret_iface
= &This
->IPersistStream_iface
;
61 WARN("(%p/%p)->(%s, %p): not found\n", iface
, This
, debugstr_dmguid(riid
), ret_iface
);
65 IUnknown_AddRef((IUnknown
*)*ret_iface
);
69 static ULONG WINAPI
IDirectMusicCollectionImpl_IDirectMusicCollection_AddRef(LPDIRECTMUSICCOLLECTION iface
)
71 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicCollection(iface
);
72 ULONG ref
= InterlockedIncrement(&This
->ref
);
74 TRACE("(%p/%p)->(): new ref = %u\n", iface
, This
, ref
);
81 static ULONG WINAPI
IDirectMusicCollectionImpl_IDirectMusicCollection_Release(LPDIRECTMUSICCOLLECTION iface
)
83 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicCollection(iface
);
84 ULONG ref
= InterlockedDecrement(&This
->ref
);
86 TRACE("(%p/%p)->(): new ref = %u\n", iface
, This
, ref
);
89 HeapFree(GetProcessHeap(), 0, This
);
91 DMUSIC_UnlockModule();
96 /* IDirectMusicCollection Interface follows: */
97 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicCollection_GetInstrument(LPDIRECTMUSICCOLLECTION iface
, DWORD patch
, IDirectMusicInstrument
** instrument
)
99 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicCollection(iface
);
100 DMUS_PRIVATE_INSTRUMENTENTRY
*inst_entry
;
101 struct list
*list_entry
;
104 TRACE("(%p/%p)->(%u, %p)\n", iface
, This
, patch
, instrument
);
106 LIST_FOR_EACH(list_entry
, &This
->Instruments
) {
107 inst_entry
= LIST_ENTRY(list_entry
, DMUS_PRIVATE_INSTRUMENTENTRY
, entry
);
108 IDirectMusicInstrument_GetPatch(inst_entry
->pInstrument
, &inst_patch
);
109 if (patch
== inst_patch
) {
110 *instrument
= inst_entry
->pInstrument
;
111 IDirectMusicInstrument_AddRef(inst_entry
->pInstrument
);
112 IDirectMusicInstrumentImpl_CustomLoad(inst_entry
->pInstrument
, This
->pStm
);
113 TRACE(": returning instrument %p\n", *instrument
);
118 TRACE(": instrument not found\n");
120 return DMUS_E_INVALIDPATCH
;
123 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicCollection_EnumInstrument(LPDIRECTMUSICCOLLECTION iface
, DWORD index
, DWORD
* patch
, LPWSTR name
, DWORD name_length
)
125 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicCollection(iface
);
127 DMUS_PRIVATE_INSTRUMENTENTRY
*inst_entry
;
128 struct list
*list_entry
;
131 TRACE("(%p/%p)->(%d, %p, %p, %d)\n", iface
, This
, index
, patch
, name
, name_length
);
133 LIST_FOR_EACH(list_entry
, &This
->Instruments
) {
134 inst_entry
= LIST_ENTRY(list_entry
, DMUS_PRIVATE_INSTRUMENTENTRY
, entry
);
136 IDirectMusicInstrumentImpl
*instrument
= impl_from_IDirectMusicInstrument(inst_entry
->pInstrument
);
137 IDirectMusicInstrument_GetPatch(inst_entry
->pInstrument
, patch
);
139 length
= min(strlenW(instrument
->wszName
), name_length
- 1);
140 memcpy(name
, instrument
->wszName
, length
* sizeof(WCHAR
));
151 static const IDirectMusicCollectionVtbl DirectMusicCollection_Collection_Vtbl
= {
152 IDirectMusicCollectionImpl_IDirectMusicCollection_QueryInterface
,
153 IDirectMusicCollectionImpl_IDirectMusicCollection_AddRef
,
154 IDirectMusicCollectionImpl_IDirectMusicCollection_Release
,
155 IDirectMusicCollectionImpl_IDirectMusicCollection_GetInstrument
,
156 IDirectMusicCollectionImpl_IDirectMusicCollection_EnumInstrument
159 /* IDirectMusicCollectionImpl IDirectMusicObject part: */
160 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_QueryInterface(LPDIRECTMUSICOBJECT iface
, REFIID riid
, LPVOID
*ret_iface
)
162 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
163 return IDirectMusicCollection_QueryInterface(&This
->IDirectMusicCollection_iface
, riid
, ret_iface
);
166 static ULONG WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_AddRef(LPDIRECTMUSICOBJECT iface
)
168 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
169 return IDirectMusicCollection_AddRef(&This
->IDirectMusicCollection_iface
);
172 static ULONG WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_Release(LPDIRECTMUSICOBJECT iface
)
174 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
175 return IDirectMusicCollection_Release(&This
->IDirectMusicCollection_iface
);
178 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_GetDescriptor(LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
)
180 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
182 TRACE("(%p/%p)->(%p)\n", iface
, This
, pDesc
);
187 memcpy (pDesc
, This
->pDesc
, This
->pDesc
->dwSize
);
192 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_SetDescriptor(LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
)
194 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
198 TRACE("(%p, %p)\n", iface
, pDesc
);
203 if (TRACE_ON(dmusic
))
205 TRACE("Setting descriptor:\n");
206 dump_DMUS_OBJECTDESC(pDesc
);
209 /* According to MSDN, we should copy only given values, not whole struct */
210 if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
211 This
->pDesc
->guidObject
= pDesc
->guidObject
;
212 if (pDesc
->dwValidData
& DMUS_OBJ_CLASS
)
214 pDesc
->dwValidData
&= ~DMUS_OBJ_CLASS
;
217 if (pDesc
->dwValidData
& DMUS_OBJ_NAME
)
218 lstrcpynW(This
->pDesc
->wszName
, pDesc
->wszName
, DMUS_MAX_NAME
);
219 if (pDesc
->dwValidData
& DMUS_OBJ_CATEGORY
)
220 lstrcpynW(This
->pDesc
->wszCategory
, pDesc
->wszCategory
, DMUS_MAX_CATEGORY
);
221 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
)
222 lstrcpynW(This
->pDesc
->wszFileName
, pDesc
->wszFileName
, DMUS_MAX_FILENAME
);
223 if (pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
224 This
->pDesc
->vVersion
= pDesc
->vVersion
;
225 if (pDesc
->dwValidData
& DMUS_OBJ_DATE
)
226 This
->pDesc
->ftDate
= pDesc
->ftDate
;
227 if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
228 This
->pDesc
->llMemLength
= pDesc
->llMemLength
;
229 memcpy (This
->pDesc
->pbMemData
, pDesc
->pbMemData
, pDesc
->llMemLength
);
231 if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
232 /* according to MSDN, we copy the stream */
233 IStream_Clone (pDesc
->pStream
, &This
->pDesc
->pStream
);
237 This
->pDesc
->dwValidData
|= pDesc
->dwValidData
;
242 static HRESULT
read_from_stream(IStream
*stream
, void *data
, ULONG size
)
247 hr
= IStream_Read(stream
, data
, size
, &read
);
249 TRACE("IStream_Read failed: %08x\n", hr
);
253 TRACE("Didn't read full chunk: %u < %u\n", read
, size
);
260 static HRESULT WINAPI
IDirectMusicCollectionImpl_IDirectMusicObject_ParseDescriptor(LPDIRECTMUSICOBJECT iface
, LPSTREAM stream
, LPDMUS_OBJECTDESC desc
)
262 IDirectMusicCollectionImpl
*This
= impl_from_IDirectMusicObject(iface
);
263 DMUS_PRIVATE_CHUNK chunk
;
264 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
265 LARGE_INTEGER liMove
; /* used when skipping chunks */
268 TRACE("(%p)->(%p, %p)\n", This
, stream
, desc
);
270 /* FIXME: should this be determined from stream? */
271 desc
->dwValidData
|= DMUS_OBJ_CLASS
;
272 desc
->guidClass
= This
->pDesc
->guidClass
;
274 hr
= read_from_stream(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
));
277 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
279 if (chunk
.fccID
!= FOURCC_RIFF
) {
280 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
281 liMove
.QuadPart
= chunk
.dwSize
;
282 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
283 return DMUS_E_INVALIDFILE
;
286 hr
= read_from_stream(stream
, &chunk
.fccID
, sizeof(FOURCC
));
289 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(chunk
.fccID
));
290 StreamSize
= chunk
.dwSize
- sizeof(FOURCC
);
292 if (chunk
.fccID
!= FOURCC_DLS
) {
293 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
294 liMove
.QuadPart
= StreamSize
;
295 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
300 TRACE_(dmfile
)(": collection form\n");
303 hr
= read_from_stream(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
));
306 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
307 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
308 switch (chunk
.fccID
) {
310 TRACE_(dmfile
)(": GUID chunk\n");
311 desc
->dwValidData
|= DMUS_OBJ_OBJECT
;
312 hr
= read_from_stream(stream
, &desc
->guidObject
, chunk
.dwSize
);
317 case DMUS_FOURCC_VERSION_CHUNK
:
318 TRACE_(dmfile
)(": version chunk\n");
319 desc
->dwValidData
|= DMUS_OBJ_VERSION
;
320 hr
= read_from_stream(stream
, &desc
->vVersion
, chunk
.dwSize
);
325 case DMUS_FOURCC_CATEGORY_CHUNK
:
326 TRACE_(dmfile
)(": category chunk\n");
327 desc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
328 hr
= read_from_stream(stream
, desc
->wszCategory
, chunk
.dwSize
);
334 hr
= read_from_stream(stream
, &chunk
.fccID
, sizeof(FOURCC
));
337 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(chunk
.fccID
));
338 ListSize
[0] = chunk
.dwSize
- sizeof(FOURCC
);
340 switch (chunk
.fccID
) {
341 /* pure INFO list, such can be found in dls collections */
342 case DMUS_FOURCC_INFO_LIST
:
343 TRACE_(dmfile
)(": INFO list\n");
345 hr
= read_from_stream(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
));
348 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
349 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
350 switch (chunk
.fccID
) {
351 case mmioFOURCC('I','N','A','M'): {
352 CHAR szName
[DMUS_MAX_NAME
];
353 TRACE_(dmfile
)(": name chunk\n");
354 desc
->dwValidData
|= DMUS_OBJ_NAME
;
355 hr
= read_from_stream(stream
, szName
, chunk
.dwSize
);
358 MultiByteToWideChar (CP_ACP
, 0, szName
, -1, desc
->wszName
, DMUS_MAX_NAME
);
359 if (even_or_odd(chunk
.dwSize
)) {
362 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
367 case mmioFOURCC('I','A','R','T'):
368 TRACE_(dmfile
)(": artist chunk (ignored)\n");
369 if (even_or_odd(chunk
.dwSize
)) {
373 liMove
.QuadPart
= chunk
.dwSize
;
374 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
377 case mmioFOURCC('I','C','O','P'):
378 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
379 if (even_or_odd(chunk
.dwSize
)) {
383 liMove
.QuadPart
= chunk
.dwSize
;
384 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
387 case mmioFOURCC('I','S','B','J'):
388 TRACE_(dmfile
)(": subject chunk (ignored)\n");
389 if (even_or_odd(chunk
.dwSize
)) {
393 liMove
.QuadPart
= chunk
.dwSize
;
394 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
397 case mmioFOURCC('I','C','M','T'):
398 TRACE_(dmfile
)(": comment chunk (ignored)\n");
399 if (even_or_odd(chunk
.dwSize
)) {
402 liMove
.QuadPart
= chunk
.dwSize
;
403 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
408 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
409 if (even_or_odd(chunk
.dwSize
)) {
413 liMove
.QuadPart
= chunk
.dwSize
;
414 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
417 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
418 } while (ListCount
[0] < ListSize
[0]);
422 TRACE_(dmfile
)(": unknown (skipping)\n");
423 liMove
.QuadPart
= chunk
.dwSize
- sizeof(FOURCC
);
424 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
430 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
431 liMove
.QuadPart
= chunk
.dwSize
;
432 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
435 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
436 } while (StreamCount
< StreamSize
);
438 TRACE_(dmfile
)(": reading finished\n");
440 if (TRACE_ON(dmusic
)) {
441 TRACE("Returning descriptor:\n");
442 dump_DMUS_OBJECTDESC(desc
);
448 static const IDirectMusicObjectVtbl DirectMusicCollection_Object_Vtbl
= {
449 IDirectMusicCollectionImpl_IDirectMusicObject_QueryInterface
,
450 IDirectMusicCollectionImpl_IDirectMusicObject_AddRef
,
451 IDirectMusicCollectionImpl_IDirectMusicObject_Release
,
452 IDirectMusicCollectionImpl_IDirectMusicObject_GetDescriptor
,
453 IDirectMusicCollectionImpl_IDirectMusicObject_SetDescriptor
,
454 IDirectMusicCollectionImpl_IDirectMusicObject_ParseDescriptor
457 /* IDirectMusicCollectionImpl IPersistStream part: */
458 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_QueryInterface(LPPERSISTSTREAM iface
, REFIID riid
, LPVOID
*ret_iface
)
460 IDirectMusicCollectionImpl
*This
= impl_from_IPersistStream(iface
);
461 return IDirectMusicCollection_QueryInterface(&This
->IDirectMusicCollection_iface
, riid
, ret_iface
);
464 static ULONG WINAPI
IDirectMusicCollectionImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface
)
466 IDirectMusicCollectionImpl
*This
= impl_from_IPersistStream(iface
);
467 return IDirectMusicCollection_AddRef(&This
->IDirectMusicCollection_iface
);
470 static ULONG WINAPI
IDirectMusicCollectionImpl_IPersistStream_Release (LPPERSISTSTREAM iface
)
472 IDirectMusicCollectionImpl
*This
= impl_from_IPersistStream(iface
);
473 return IDirectMusicCollection_Release(&This
->IDirectMusicCollection_iface
);
476 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_GetClassID(LPPERSISTSTREAM iface
, CLSID
* pClassID
)
481 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_IsDirty(LPPERSISTSTREAM iface
)
486 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_Load(LPPERSISTSTREAM iface
, IStream
* stream
)
488 IDirectMusicCollectionImpl
*This
= impl_from_IPersistStream(iface
);
489 DMUS_PRIVATE_CHUNK chunk
;
490 DWORD StreamSize
, StreamCount
, ListSize
[2], ListCount
[2];
491 LARGE_INTEGER liMove
; /* used when skipping chunks */
492 ULARGE_INTEGER dlibCollectionPosition
, dlibInstrumentPosition
, dlibWavePoolPosition
;
494 IStream_AddRef(stream
); /* add count for later references */
496 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, &dlibCollectionPosition
); /* store offset, in case it'll be needed later */
497 This
->liCollectionPosition
.QuadPart
= dlibCollectionPosition
.QuadPart
;
500 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
501 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
503 if (chunk
.fccID
!= FOURCC_RIFF
) {
504 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
505 liMove
.QuadPart
= chunk
.dwSize
;
506 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
510 IStream_Read(stream
, &chunk
.fccID
, sizeof(FOURCC
), NULL
);
511 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(chunk
.fccID
));
512 StreamSize
= chunk
.dwSize
- sizeof(FOURCC
);
515 if (chunk
.fccID
!= FOURCC_DLS
) {
516 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
517 liMove
.QuadPart
= StreamSize
;
518 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
522 TRACE_(dmfile
)(": collection form\n");
524 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
525 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
526 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
527 switch (chunk
.fccID
) {
529 TRACE_(dmfile
)(": collection header chunk\n");
530 This
->pHeader
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, chunk
.dwSize
);
531 IStream_Read(stream
, This
->pHeader
, chunk
.dwSize
, NULL
);
535 TRACE_(dmfile
)(": DLID (GUID) chunk\n");
536 This
->pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
537 IStream_Read(stream
, &This
->pDesc
->guidObject
, chunk
.dwSize
, NULL
);
541 TRACE_(dmfile
)(": version chunk\n");
542 This
->pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
543 IStream_Read(stream
, &This
->pDesc
->vVersion
, chunk
.dwSize
, NULL
);
547 TRACE_(dmfile
)(": pool table chunk\n");
548 This
->pPoolTable
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(POOLTABLE
));
549 IStream_Read(stream
, This
->pPoolTable
, sizeof(POOLTABLE
), NULL
);
550 chunk
.dwSize
-= sizeof(POOLTABLE
);
551 This
->pPoolCues
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->pPoolTable
->cCues
* sizeof(POOLCUE
));
552 IStream_Read(stream
, This
->pPoolCues
, chunk
.dwSize
, NULL
);
556 IStream_Read(stream
, &chunk
.fccID
, sizeof(FOURCC
), NULL
);
557 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(chunk
.fccID
));
558 ListSize
[0] = chunk
.dwSize
- sizeof(FOURCC
);
560 switch (chunk
.fccID
) {
561 case DMUS_FOURCC_INFO_LIST
: {
562 TRACE_(dmfile
)(": INFO list\n");
564 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
565 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
566 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
567 switch (chunk
.fccID
) {
568 case mmioFOURCC('I','N','A','M'): {
569 CHAR szName
[DMUS_MAX_NAME
];
570 TRACE_(dmfile
)(": name chunk\n");
571 This
->pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
572 IStream_Read(stream
, szName
, chunk
.dwSize
, NULL
);
573 MultiByteToWideChar(CP_ACP
, 0, szName
, -1, This
->pDesc
->wszName
, DMUS_MAX_NAME
);
574 if (even_or_odd(chunk
.dwSize
)) {
577 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
581 case mmioFOURCC('I','A','R','T'): {
582 TRACE_(dmfile
)(": artist chunk (ignored)\n");
583 if (even_or_odd(chunk
.dwSize
)) {
587 liMove
.QuadPart
= chunk
.dwSize
;
588 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
591 case mmioFOURCC('I','C','O','P'): {
592 TRACE_(dmfile
)(": copyright chunk\n");
593 This
->szCopyright
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, chunk
.dwSize
);
594 IStream_Read(stream
, This
->szCopyright
, chunk
.dwSize
, NULL
);
595 if (even_or_odd(chunk
.dwSize
)) {
598 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
602 case mmioFOURCC('I','S','B','J'): {
603 TRACE_(dmfile
)(": subject chunk (ignored)\n");
604 if (even_or_odd(chunk
.dwSize
)) {
608 liMove
.QuadPart
= chunk
.dwSize
;
609 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
612 case mmioFOURCC('I','C','M','T'): {
613 TRACE_(dmfile
)(": comment chunk (ignored)\n");
614 if (even_or_odd(chunk
.dwSize
)) {
618 liMove
.QuadPart
= chunk
.dwSize
;
619 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
623 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
624 if (even_or_odd(chunk
.dwSize
)) {
628 liMove
.QuadPart
= chunk
.dwSize
;
629 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
633 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
634 } while (ListCount
[0] < ListSize
[0]);
638 TRACE_(dmfile
)(": wave pool list (mark & skip)\n");
640 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, &dlibWavePoolPosition
); /* store position */
641 This
->liWavePoolTablePosition
.QuadPart
= dlibWavePoolPosition
.QuadPart
;
642 liMove
.QuadPart
= chunk
.dwSize
- sizeof(FOURCC
);
643 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
647 TRACE_(dmfile
)(": instruments list\n");
649 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
650 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
651 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
652 switch (chunk
.fccID
) {
654 IStream_Read(stream
, &chunk
.fccID
, sizeof(FOURCC
), NULL
);
655 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(chunk
.fccID
));
656 ListSize
[1] = chunk
.dwSize
- sizeof(FOURCC
);
658 switch (chunk
.fccID
) {
660 LPDMUS_PRIVATE_INSTRUMENTENTRY new_instrument
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DMUS_PRIVATE_INSTRUMENTENTRY
));
661 TRACE_(dmfile
)(": instrument list\n");
662 /* Only way to create this one... even M$ does it discretely */
663 DMUSIC_CreateDirectMusicInstrumentImpl(&IID_IDirectMusicInstrument
, (void**)&new_instrument
->pInstrument
, NULL
);
665 IDirectMusicInstrumentImpl
*instrument
= impl_from_IDirectMusicInstrument(new_instrument
->pInstrument
);
666 /* Store offset and length, they will be needed when loading the instrument */
668 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, &dlibInstrumentPosition
);
669 instrument
->liInstrumentPosition
.QuadPart
= dlibInstrumentPosition
.QuadPart
;
670 instrument
->length
= ListSize
[1];
672 IStream_Read(stream
, &chunk
, sizeof(FOURCC
) + sizeof(DWORD
), NULL
);
673 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + chunk
.dwSize
;
674 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
675 switch (chunk
.fccID
) {
677 TRACE_(dmfile
)(": instrument header chunk\n");
678 IStream_Read(stream
, &instrument
->header
, chunk
.dwSize
, NULL
);
682 TRACE_(dmfile
)(": DLID (GUID) chunk\n");
683 IStream_Read(stream
, &instrument
->id
, chunk
.dwSize
, NULL
);
687 IStream_Read(stream
, &chunk
.fccID
, sizeof(FOURCC
), NULL
);
688 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(chunk
.fccID
));
689 switch (chunk
.fccID
) {
691 TRACE_(dmfile
)(": unknown (skipping)\n");
692 liMove
.QuadPart
= chunk
.dwSize
- sizeof(FOURCC
);
693 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
700 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
701 liMove
.QuadPart
= chunk
.dwSize
;
702 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
706 TRACE_(dmfile
)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount
[1], ListSize
[1]);
707 } while (ListCount
[1] < ListSize
[1]);
708 /* DEBUG: dumps whole instrument object tree: */
709 if (TRACE_ON(dmusic
)) {
710 TRACE("*** IDirectMusicInstrument (%p) ***\n", instrument
);
711 if (!IsEqualGUID(&instrument
->id
, &GUID_NULL
))
712 TRACE(" - GUID = %s\n", debugstr_dmguid(&instrument
->id
));
713 TRACE(" - Instrument header:\n");
714 TRACE(" - cRegions: %d\n", instrument
->header
.cRegions
);
715 TRACE(" - Locale:\n");
716 TRACE(" - ulBank: %d\n", instrument
->header
.Locale
.ulBank
);
717 TRACE(" - ulInstrument: %d\n", instrument
->header
.Locale
.ulInstrument
);
718 TRACE(" => dwPatch: %d\n", MIDILOCALE2Patch(&instrument
->header
.Locale
));
720 list_add_tail(&This
->Instruments
, &new_instrument
->entry
);
728 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
729 liMove
.QuadPart
= chunk
.dwSize
;
730 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
734 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
735 } while (ListCount
[0] < ListSize
[0]);
739 TRACE_(dmfile
)(": unknown (skipping)\n");
740 liMove
.QuadPart
= chunk
.dwSize
- sizeof(FOURCC
);
741 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
748 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
749 liMove
.QuadPart
= chunk
.dwSize
;
750 IStream_Seek(stream
, liMove
, STREAM_SEEK_CUR
, NULL
);
754 TRACE_(dmfile
)(": StreamCount = %d < StreamSize = %d\n", StreamCount
, StreamSize
);
755 } while (StreamCount
< StreamSize
);
757 TRACE_(dmfile
)(": reading finished\n");
760 /* DEBUG: dumps whole collection object tree: */
761 if (TRACE_ON(dmusic
)) {
763 DMUS_PRIVATE_INSTRUMENTENTRY
*tmpEntry
;
764 struct list
*listEntry
;
766 TRACE("*** IDirectMusicCollection (%p) ***\n", &This
->IDirectMusicCollection_iface
);
767 if (This
->pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
768 TRACE(" - GUID = %s\n", debugstr_dmguid(&This
->pDesc
->guidObject
));
769 if (This
->pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
770 TRACE(" - Version = %i,%i,%i,%i\n", (This
->pDesc
->vVersion
.dwVersionMS
>> 8) & 0x0000FFFF, This
->pDesc
->vVersion
.dwVersionMS
& 0x0000FFFF,
771 (This
->pDesc
->vVersion
.dwVersionLS
>> 8) & 0x0000FFFF, This
->pDesc
->vVersion
.dwVersionLS
& 0x0000FFFF);
772 if (This
->pDesc
->dwValidData
& DMUS_OBJ_NAME
)
773 TRACE(" - Name = %s\n", debugstr_w(This
->pDesc
->wszName
));
775 TRACE(" - Collection header:\n");
776 TRACE(" - cInstruments: %d\n", This
->pHeader
->cInstruments
);
777 TRACE(" - Instruments:\n");
779 LIST_FOR_EACH(listEntry
, &This
->Instruments
) {
780 tmpEntry
= LIST_ENTRY( listEntry
, DMUS_PRIVATE_INSTRUMENTENTRY
, entry
);
781 TRACE(" - Instrument[%i]: %p\n", r
, tmpEntry
->pInstrument
);
789 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_Save(LPPERSISTSTREAM iface
, IStream
* pStm
, BOOL fClearDirty
)
794 static HRESULT WINAPI
IDirectMusicCollectionImpl_IPersistStream_GetSizeMax(LPPERSISTSTREAM iface
, ULARGE_INTEGER
* pcbSize
)
799 static const IPersistStreamVtbl DirectMusicCollection_PersistStream_Vtbl
= {
800 IDirectMusicCollectionImpl_IPersistStream_QueryInterface
,
801 IDirectMusicCollectionImpl_IPersistStream_AddRef
,
802 IDirectMusicCollectionImpl_IPersistStream_Release
,
803 IDirectMusicCollectionImpl_IPersistStream_GetClassID
,
804 IDirectMusicCollectionImpl_IPersistStream_IsDirty
,
805 IDirectMusicCollectionImpl_IPersistStream_Load
,
806 IDirectMusicCollectionImpl_IPersistStream_Save
,
807 IDirectMusicCollectionImpl_IPersistStream_GetSizeMax
811 /* for ClassFactory */
812 HRESULT WINAPI
DMUSIC_CreateDirectMusicCollectionImpl(LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
)
814 IDirectMusicCollectionImpl
* obj
;
819 return CLASS_E_NOAGGREGATION
;
821 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicCollectionImpl
));
823 return E_OUTOFMEMORY
;
825 obj
->IDirectMusicCollection_iface
.lpVtbl
= &DirectMusicCollection_Collection_Vtbl
;
826 obj
->IDirectMusicObject_iface
.lpVtbl
= &DirectMusicCollection_Object_Vtbl
;
827 obj
->IPersistStream_iface
.lpVtbl
= &DirectMusicCollection_PersistStream_Vtbl
;
828 obj
->pDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DMUS_OBJECTDESC
));
829 DM_STRUCT_INIT(obj
->pDesc
);
830 obj
->pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
831 obj
->pDesc
->guidClass
= CLSID_DirectMusicCollection
;
833 list_init (&obj
->Instruments
);
835 hr
= IDirectMusicCollection_QueryInterface(&obj
->IDirectMusicCollection_iface
, lpcGUID
, ppobj
);
836 IDirectMusicCollection_Release(&obj
->IDirectMusicCollection_iface
);