1 /* IDirectMusicCollection Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (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
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "dmusic_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
23 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
25 /*****************************************************************************
26 * IDirectMusicCollectionImpl implementation
28 /* IDirectMusicCollectionImpl IUnknown part: */
29 HRESULT WINAPI IDirectMusicCollectionImpl_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
30 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, UnknownVtbl, iface);
31 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
33 if (IsEqualIID (riid, &IID_IUnknown)) {
34 *ppobj = (LPVOID)&This->UnknownVtbl;
35 IDirectMusicCollectionImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
37 } else if (IsEqualIID (riid, &IID_IDirectMusicCollection)) {
38 *ppobj = (LPVOID)&This->CollectionVtbl;
39 IDirectMusicCollectionImpl_IDirectMusicCollection_AddRef ((LPDIRECTMUSICCOLLECTION)&This->CollectionVtbl);
41 } else if (IsEqualIID (riid, &IID_IDirectMusicObject)) {
42 *ppobj = (LPVOID)&This->ObjectVtbl;
43 IDirectMusicCollectionImpl_IDirectMusicObject_AddRef ((LPDIRECTMUSICOBJECT)&This->ObjectVtbl);
45 } else if (IsEqualIID (riid, &IID_IPersistStream)) {
46 *ppobj = (LPVOID)&This->PersistStreamVtbl;
47 IDirectMusicCollectionImpl_IPersistStream_AddRef ((LPPERSISTSTREAM)&This->PersistStreamVtbl);
51 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
55 ULONG WINAPI IDirectMusicCollectionImpl_IUnknown_AddRef (LPUNKNOWN iface) {
56 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, UnknownVtbl, iface);
57 TRACE("(%p): AddRef from %ld\n", This, This->ref);
61 ULONG WINAPI IDirectMusicCollectionImpl_IUnknown_Release (LPUNKNOWN iface) {
62 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, UnknownVtbl, iface);
63 ULONG ref = --This->ref;
64 TRACE("(%p): ReleaseRef to %ld\n", This, This->ref);
66 HeapFree(GetProcessHeap(), 0, This);
71 IUnknownVtbl DirectMusicCollection_Unknown_Vtbl = {
72 IDirectMusicCollectionImpl_IUnknown_QueryInterface,
73 IDirectMusicCollectionImpl_IUnknown_AddRef,
74 IDirectMusicCollectionImpl_IUnknown_Release
77 /* IDirectMusicCollectionImpl IDirectMusicCollection part: */
78 HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicCollection_QueryInterface (LPDIRECTMUSICCOLLECTION iface, REFIID riid, LPVOID *ppobj) {
79 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, CollectionVtbl, iface);
80 return IDirectMusicCollectionImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
83 ULONG WINAPI IDirectMusicCollectionImpl_IDirectMusicCollection_AddRef (LPDIRECTMUSICCOLLECTION iface) {
84 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, CollectionVtbl, iface);
85 return IDirectMusicCollectionImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
88 ULONG WINAPI IDirectMusicCollectionImpl_IDirectMusicCollection_Release (LPDIRECTMUSICCOLLECTION iface) {
89 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, CollectionVtbl, iface);
90 return IDirectMusicCollectionImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
93 /* IDirectMusicCollection Interface follow: */
94 HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicCollection_GetInstrument (LPDIRECTMUSICCOLLECTION iface, DWORD dwPatch, IDirectMusicInstrument** ppInstrument) {
95 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, CollectionVtbl, iface);
96 DMUS_PRIVATE_INSTRUMENTENTRY *tmpEntry;
97 struct list *listEntry;
100 TRACE("(%p, %ld, %p)\n", This, dwPatch, ppInstrument);
102 LIST_FOR_EACH (listEntry, &This->Instruments) {
103 tmpEntry = LIST_ENTRY(listEntry, DMUS_PRIVATE_INSTRUMENTENTRY, entry);
104 IDirectMusicInstrument_GetPatch (tmpEntry->pInstrument, &dwInstPatch);
105 if (dwPatch == dwInstPatch) {
106 *ppInstrument = (LPDIRECTMUSICINSTRUMENT)tmpEntry->pInstrument;
107 IDirectMusicInstrument_AddRef (tmpEntry->pInstrument);
108 IDirectMusicInstrumentImpl_Custom_Load (tmpEntry->pInstrument, This->pStm); /* load instrument before returning it */
109 TRACE(": returning instrument %p\n", *ppInstrument);
114 TRACE(": instrument not found\n");
116 return DMUS_E_INVALIDPATCH;
119 HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicCollection_EnumInstrument (LPDIRECTMUSICCOLLECTION iface, DWORD dwIndex, DWORD* pdwPatch, LPWSTR pwszName, DWORD dwNameLen) {
120 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, CollectionVtbl, iface);
122 DMUS_PRIVATE_INSTRUMENTENTRY *tmpEntry;
123 struct list *listEntry;
125 TRACE("(%p, %ld, %p, %p, %ld)\n", This, dwIndex, pdwPatch, pwszName, dwNameLen);
126 LIST_FOR_EACH (listEntry, &This->Instruments) {
127 tmpEntry = LIST_ENTRY(listEntry, DMUS_PRIVATE_INSTRUMENTENTRY, entry);
129 ICOM_NAME_MULTI (IDirectMusicInstrumentImpl, InstrumentVtbl, tmpEntry->pInstrument, pInstrument);
130 IDirectMusicInstrument_GetPatch (tmpEntry->pInstrument, pdwPatch);
131 dwNameLen = strlenW (pInstrument->wszName);
132 strncpyW (pwszName, pInstrument->wszName, dwNameLen);
141 IDirectMusicCollectionVtbl DirectMusicCollection_Collection_Vtbl = {
142 IDirectMusicCollectionImpl_IDirectMusicCollection_QueryInterface,
143 IDirectMusicCollectionImpl_IDirectMusicCollection_AddRef,
144 IDirectMusicCollectionImpl_IDirectMusicCollection_Release,
145 IDirectMusicCollectionImpl_IDirectMusicCollection_GetInstrument,
146 IDirectMusicCollectionImpl_IDirectMusicCollection_EnumInstrument
149 /* IDirectMusicCollectionImpl IDirectMusicObject part: */
150 HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj) {
151 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, ObjectVtbl, iface);
152 return IDirectMusicCollectionImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
155 ULONG WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface) {
156 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, ObjectVtbl, iface);
157 return IDirectMusicCollectionImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
160 ULONG WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface) {
161 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, ObjectVtbl, iface);
162 return IDirectMusicCollectionImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
165 HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
166 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, ObjectVtbl, iface);
167 TRACE("(%p, %p)\n", This, pDesc);
168 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
169 memcpy (pDesc, This->pDesc, This->pDesc->dwSize);
173 HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
174 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, ObjectVtbl, iface);
175 TRACE("(%p, %p): setting descriptor:\n%s\n", This, pDesc, debugstr_DMUS_OBJECTDESC (pDesc));
177 /* According to MSDN, we should copy only given values, not whole struct */
178 if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
179 memcpy (&This->pDesc->guidObject, &pDesc->guidObject, sizeof (pDesc->guidObject));
180 if (pDesc->dwValidData & DMUS_OBJ_CLASS)
181 memcpy (&This->pDesc->guidClass, &pDesc->guidClass, sizeof (pDesc->guidClass));
182 if (pDesc->dwValidData & DMUS_OBJ_NAME)
183 strncpyW (This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
184 if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
185 strncpyW (This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);
186 if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
187 strncpyW (This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);
188 if (pDesc->dwValidData & DMUS_OBJ_VERSION)
189 memcpy (&This->pDesc->vVersion, &pDesc->vVersion, sizeof (pDesc->vVersion));
190 if (pDesc->dwValidData & DMUS_OBJ_DATE)
191 memcpy (&This->pDesc->ftDate, &pDesc->ftDate, sizeof (pDesc->ftDate));
192 if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
193 memcpy (&This->pDesc->llMemLength, &pDesc->llMemLength, sizeof (pDesc->llMemLength));
194 memcpy (This->pDesc->pbMemData, pDesc->pbMemData, sizeof (pDesc->pbMemData));
196 if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
197 /* according to MSDN, we copy the stream */
198 IStream_Clone (pDesc->pStream, &This->pDesc->pStream);
202 This->pDesc->dwValidData |= pDesc->dwValidData;
207 HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) {
208 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, ObjectVtbl, iface);
209 DMUS_PRIVATE_CHUNK Chunk;
210 DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
211 LARGE_INTEGER liMove; /* used when skipping chunks */
213 TRACE("(%p, %p, %p)\n", This, pStream, pDesc);
215 /* FIXME: should this be determined from stream? */
216 pDesc->dwValidData |= DMUS_OBJ_CLASS;
217 memcpy (&pDesc->guidClass, &CLSID_DirectMusicCollection, sizeof(CLSID));
219 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
220 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
221 switch (Chunk.fccID) {
223 IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);
224 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
225 StreamSize = Chunk.dwSize - sizeof(FOURCC);
227 if (Chunk.fccID == mmioFOURCC('D','L','S',' ')) {
228 TRACE_(dmfile)(": collection form\n");
230 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
231 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
232 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
233 switch (Chunk.fccID) {
235 TRACE_(dmfile)(": GUID chunk\n");
236 pDesc->dwValidData |= DMUS_OBJ_OBJECT;
237 IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL);
240 case DMUS_FOURCC_VERSION_CHUNK: {
241 TRACE_(dmfile)(": version chunk\n");
242 pDesc->dwValidData |= DMUS_OBJ_VERSION;
243 IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL);
246 case DMUS_FOURCC_CATEGORY_CHUNK: {
247 TRACE_(dmfile)(": category chunk\n");
248 pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
249 IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL);
253 IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);
254 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
255 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
257 switch (Chunk.fccID) {
258 /* pure INFO list, such can be found in dls collections */
259 case mmioFOURCC('I','N','F','O'): {
260 TRACE_(dmfile)(": INFO list\n");
262 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
263 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
264 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
265 switch (Chunk.fccID) {
266 case mmioFOURCC('I','N','A','M'):{
267 CHAR szName[DMUS_MAX_NAME];
268 TRACE_(dmfile)(": name chunk\n");
269 pDesc->dwValidData |= DMUS_OBJ_NAME;
270 IStream_Read (pStream, szName, Chunk.dwSize, NULL);
271 MultiByteToWideChar (CP_ACP, 0, szName, -1, pDesc->wszName, DMUS_MAX_NAME);
272 if (even_or_odd(Chunk.dwSize)) {
275 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
279 case mmioFOURCC('I','A','R','T'): {
280 TRACE_(dmfile)(": artist chunk (ignored)\n");
281 if (even_or_odd(Chunk.dwSize)) {
285 liMove.QuadPart = Chunk.dwSize;
286 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
289 case mmioFOURCC('I','C','O','P'): {
290 TRACE_(dmfile)(": copyright chunk (ignored)\n");
291 if (even_or_odd(Chunk.dwSize)) {
295 liMove.QuadPart = Chunk.dwSize;
296 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
299 case mmioFOURCC('I','S','B','J'): {
300 TRACE_(dmfile)(": subject chunk (ignored)\n");
301 if (even_or_odd(Chunk.dwSize)) {
305 liMove.QuadPart = Chunk.dwSize;
306 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
309 case mmioFOURCC('I','C','M','T'): {
310 TRACE_(dmfile)(": comment chunk (ignored)\n");
311 if (even_or_odd(Chunk.dwSize)) {
315 liMove.QuadPart = Chunk.dwSize;
316 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
320 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
321 if (even_or_odd(Chunk.dwSize)) {
325 liMove.QuadPart = Chunk.dwSize;
326 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
330 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
331 } while (ListCount[0] < ListSize[0]);
335 TRACE_(dmfile)(": unknown (skipping)\n");
336 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
337 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
344 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
345 liMove.QuadPart = Chunk.dwSize;
346 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
350 TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
351 } while (StreamCount < StreamSize);
354 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
355 liMove.QuadPart = StreamSize;
356 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
360 TRACE_(dmfile)(": reading finished\n");
364 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
365 liMove.QuadPart = Chunk.dwSize;
366 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
367 return DMUS_E_INVALIDFILE;
371 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc));
376 IDirectMusicObjectVtbl DirectMusicCollection_Object_Vtbl = {
377 IDirectMusicCollectionImpl_IDirectMusicObject_QueryInterface,
378 IDirectMusicCollectionImpl_IDirectMusicObject_AddRef,
379 IDirectMusicCollectionImpl_IDirectMusicObject_Release,
380 IDirectMusicCollectionImpl_IDirectMusicObject_GetDescriptor,
381 IDirectMusicCollectionImpl_IDirectMusicObject_SetDescriptor,
382 IDirectMusicCollectionImpl_IDirectMusicObject_ParseDescriptor
385 /* IDirectMusicCollectionImpl IPersistStream part: */
386 HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
387 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, PersistStreamVtbl, iface);
388 return IDirectMusicCollectionImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
391 ULONG WINAPI IDirectMusicCollectionImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
392 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, PersistStreamVtbl, iface);
393 return IDirectMusicCollectionImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
396 ULONG WINAPI IDirectMusicCollectionImpl_IPersistStream_Release (LPPERSISTSTREAM iface) {
397 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, PersistStreamVtbl, iface);
398 return IDirectMusicCollectionImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
401 HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
405 HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
409 HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
410 ICOM_THIS_MULTI(IDirectMusicCollectionImpl, PersistStreamVtbl, iface);
412 DMUS_PRIVATE_CHUNK Chunk;
413 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
414 LARGE_INTEGER liMove; /* used when skipping chunks */
415 ULARGE_INTEGER dlibCollectionPosition, dlibInstrumentPosition, dlibWavePoolPosition;
417 IStream_AddRef (pStm); /* add count for later references */
419 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibCollectionPosition); /* store offset, in case it'll be needed later */
420 This->liCollectionPosition.QuadPart = dlibCollectionPosition.QuadPart;
423 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
424 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
425 switch (Chunk.fccID) {
427 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
428 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
429 StreamSize = Chunk.dwSize - sizeof(FOURCC);
431 switch (Chunk.fccID) {
433 TRACE_(dmfile)(": collection form\n");
435 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
436 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
437 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
438 switch (Chunk.fccID) {
440 TRACE_(dmfile)(": collection header chunk\n");
441 This->pHeader = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
442 IStream_Read (pStm, This->pHeader, Chunk.dwSize, NULL);
446 TRACE_(dmfile)(": DLID (GUID) chunk\n");
447 This->pDesc->dwValidData |= DMUS_OBJ_OBJECT;
448 IStream_Read (pStm, &This->pDesc->guidObject, Chunk.dwSize, NULL);
452 TRACE_(dmfile)(": version chunk\n");
453 This->pDesc->dwValidData |= DMUS_OBJ_VERSION;
454 IStream_Read (pStm, &This->pDesc->vVersion, Chunk.dwSize, NULL);
458 TRACE_(dmfile)(": pool table chunk\n");
459 This->pPoolTable = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(POOLTABLE));
460 IStream_Read (pStm, This->pPoolTable, sizeof(POOLTABLE), NULL);
461 Chunk.dwSize -= sizeof(POOLTABLE);
462 This->pPoolCues = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, This->pPoolTable->cCues*sizeof(POOLCUE));
463 IStream_Read (pStm, This->pPoolCues, Chunk.dwSize, NULL);
467 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
468 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
469 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
471 switch (Chunk.fccID) {
472 case mmioFOURCC('I','N','F','O'): {
473 TRACE_(dmfile)(": INFO list\n");
475 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
476 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
477 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
478 switch (Chunk.fccID) {
479 case mmioFOURCC('I','N','A','M'): {
480 CHAR szName[DMUS_MAX_NAME];
481 TRACE_(dmfile)(": name chunk\n");
482 This->pDesc->dwValidData |= DMUS_OBJ_NAME;
483 IStream_Read (pStm, szName, Chunk.dwSize, NULL);
484 MultiByteToWideChar (CP_ACP, 0, szName, -1, This->pDesc->wszName, DMUS_MAX_NAME);
485 if (even_or_odd(Chunk.dwSize)) {
488 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
492 case mmioFOURCC('I','A','R','T'): {
493 TRACE_(dmfile)(": artist chunk (ignored)\n");
494 if (even_or_odd(Chunk.dwSize)) {
498 liMove.QuadPart = Chunk.dwSize;
499 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
502 case mmioFOURCC('I','C','O','P'): {
503 TRACE_(dmfile)(": copyright chunk\n");
504 This->szCopyright = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
505 IStream_Read (pStm, This->szCopyright, Chunk.dwSize, NULL);
506 if (even_or_odd(Chunk.dwSize)) {
509 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
513 case mmioFOURCC('I','S','B','J'): {
514 TRACE_(dmfile)(": subject chunk (ignored)\n");
515 if (even_or_odd(Chunk.dwSize)) {
519 liMove.QuadPart = Chunk.dwSize;
520 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
523 case mmioFOURCC('I','C','M','T'): {
524 TRACE_(dmfile)(": comment chunk (ignored)\n");
525 if (even_or_odd(Chunk.dwSize)) {
529 liMove.QuadPart = Chunk.dwSize;
530 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
534 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
535 if (even_or_odd(Chunk.dwSize)) {
539 liMove.QuadPart = Chunk.dwSize;
540 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
544 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
545 } while (ListCount[0] < ListSize[0]);
549 TRACE_(dmfile)(": wave pool list (mark & skip)\n");
551 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibWavePoolPosition); /* store position */
552 This->liWavePoolTablePosition.QuadPart = dlibWavePoolPosition.QuadPart;
553 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
554 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
558 TRACE_(dmfile)(": instruments list\n");
560 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
561 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
562 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
563 switch (Chunk.fccID) {
565 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
566 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
567 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
569 switch (Chunk.fccID) {
571 LPDMUS_PRIVATE_INSTRUMENTENTRY pNewInstrument = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_INSTRUMENTENTRY));
572 TRACE_(dmfile)(": instrument list\n");
573 DMUSIC_CreateDirectMusicInstrumentImpl (&IID_IDirectMusicInstrument, (LPVOID*)&pNewInstrument->pInstrument, NULL); /* only way to create this one... even M$ does it discretly */
575 ICOM_NAME_MULTI (IDirectMusicInstrumentImpl, InstrumentVtbl, pNewInstrument->pInstrument, pInstrument);
577 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibInstrumentPosition);
578 pInstrument->liInstrumentPosition.QuadPart = dlibInstrumentPosition.QuadPart - (2*sizeof(FOURCC) + sizeof(DWORD)); /* store offset, it'll be needed later */
581 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
582 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
583 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
584 switch (Chunk.fccID) {
586 TRACE_(dmfile)(": instrument header chunk\n");
587 pInstrument->pHeader = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
588 IStream_Read (pStm, pInstrument->pHeader, Chunk.dwSize, NULL);
592 TRACE_(dmfile)(": DLID (GUID) chunk\n");
593 pInstrument->pInstrumentID = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
594 IStream_Read (pStm, pInstrument->pInstrumentID, Chunk.dwSize, NULL);
598 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
599 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
600 ListSize[2] = Chunk.dwSize - sizeof(FOURCC);
602 switch (Chunk.fccID) {
604 TRACE_(dmfile)(": unknown (skipping)\n");
605 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
606 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
613 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
614 liMove.QuadPart = Chunk.dwSize;
615 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
619 TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
620 } while (ListCount[1] < ListSize[1]);
621 /* DEBUG: dumps whole instrument object tree: */
622 if (TRACE_ON(dmusic)) {
623 TRACE("*** IDirectMusicInstrument (%p) ***\n", pInstrument);
624 if (pInstrument->pInstrumentID)
625 TRACE(" - GUID = %s\n", debugstr_dmguid(pInstrument->pInstrumentID));
627 TRACE(" - Instrument header:\n");
628 TRACE(" - cRegions: %ld\n", pInstrument->pHeader->cRegions);
629 TRACE(" - Locale:\n");
630 TRACE(" - ulBank: %ld\n", pInstrument->pHeader->Locale.ulBank);
631 TRACE(" - ulInstrument: %ld\n", pInstrument->pHeader->Locale.ulInstrument);
632 TRACE(" => dwPatch: %ld\n", MIDILOCALE2Patch(&pInstrument->pHeader->Locale));
634 list_add_tail (&This->Instruments, &pNewInstrument->entry);
642 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
643 liMove.QuadPart = Chunk.dwSize;
644 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
648 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
649 } while (ListCount[0] < ListSize[0]);
653 TRACE_(dmfile)(": unknown (skipping)\n");
654 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
655 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
662 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
663 liMove.QuadPart = Chunk.dwSize;
664 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
668 TRACE_(dmfile)(": StreamCount = %ld < StreamSize = %ld\n", StreamCount, StreamSize);
669 } while (StreamCount < StreamSize);
673 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
674 liMove.QuadPart = StreamSize;
675 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
679 TRACE_(dmfile)(": reading finished\n");
683 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
684 liMove.QuadPart = Chunk.dwSize;
685 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
690 /* DEBUG: dumps whole collection object tree: */
691 if (TRACE_ON(dmusic)) {
693 DMUS_PRIVATE_INSTRUMENTENTRY *tmpEntry;
694 struct list *listEntry;
696 TRACE("*** IDirectMusicCollection (%p) ***\n", This->CollectionVtbl);
697 if (This->pDesc->dwValidData & DMUS_OBJ_OBJECT)
698 TRACE(" - GUID = %s\n", debugstr_dmguid(&This->pDesc->guidObject));
699 if (This->pDesc->dwValidData & DMUS_OBJ_VERSION)
700 TRACE(" - Version = %i,%i,%i,%i\n", (This->pDesc->vVersion.dwVersionMS >> 8) && 0x0000FFFF, This->pDesc->vVersion.dwVersionMS && 0x0000FFFF, \
701 (This->pDesc->vVersion.dwVersionLS >> 8) && 0x0000FFFF, This->pDesc->vVersion.dwVersionLS && 0x0000FFFF);
702 if (This->pDesc->dwValidData & DMUS_OBJ_NAME)
703 TRACE(" - Name = %s\n", debugstr_w(This->pDesc->wszName));
705 TRACE(" - Collection header:\n");
706 TRACE(" - cInstruments: %ld\n", This->pHeader->cInstruments);
707 TRACE(" - Instruments:\n");
709 LIST_FOR_EACH (listEntry, &This->Instruments) {
710 tmpEntry = LIST_ENTRY( listEntry, DMUS_PRIVATE_INSTRUMENTENTRY, entry );
711 TRACE(" - Instrument[%i]: %p\n", r, tmpEntry->pInstrument);
719 HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
723 HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
727 IPersistStreamVtbl DirectMusicCollection_PersistStream_Vtbl = {
728 IDirectMusicCollectionImpl_IPersistStream_QueryInterface,
729 IDirectMusicCollectionImpl_IPersistStream_AddRef,
730 IDirectMusicCollectionImpl_IPersistStream_Release,
731 IDirectMusicCollectionImpl_IPersistStream_GetClassID,
732 IDirectMusicCollectionImpl_IPersistStream_IsDirty,
733 IDirectMusicCollectionImpl_IPersistStream_Load,
734 IDirectMusicCollectionImpl_IPersistStream_Save,
735 IDirectMusicCollectionImpl_IPersistStream_GetSizeMax
739 /* for ClassFactory */
740 HRESULT WINAPI DMUSIC_CreateDirectMusicCollectionImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter) {
741 IDirectMusicCollectionImpl* obj;
743 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicCollectionImpl));
746 return E_OUTOFMEMORY;
748 obj->UnknownVtbl = &DirectMusicCollection_Unknown_Vtbl;
749 obj->CollectionVtbl = &DirectMusicCollection_Collection_Vtbl;
750 obj->ObjectVtbl = &DirectMusicCollection_Object_Vtbl;
751 obj->PersistStreamVtbl = &DirectMusicCollection_PersistStream_Vtbl;
752 obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
753 DM_STRUCT_INIT(obj->pDesc);
754 obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
755 memcpy (&obj->pDesc->guidClass, &CLSID_DirectMusicCollection, sizeof (CLSID));
756 obj->ref = 0; /* will be inited by QueryInterface */
757 list_init (&obj->Instruments);
759 return IDirectMusicCollectionImpl_IUnknown_QueryInterface ((LPUNKNOWN)&obj->UnknownVtbl, lpcGUID, ppobj);