Get rid of the no longer used ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
[wine/multimedia.git] / dlls / dmusic / collection.c
blob6430c70c9879a3dde9dd3affc2402e92760a3871
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);
36 return S_OK;
37 } else if (IsEqualIID (riid, &IID_IDirectMusicCollection)) {
38 *ppobj = (LPVOID)&This->CollectionVtbl;
39 IDirectMusicCollectionImpl_IDirectMusicCollection_AddRef ((LPDIRECTMUSICCOLLECTION)&This->CollectionVtbl);
40 return S_OK;
41 } else if (IsEqualIID (riid, &IID_IDirectMusicObject)) {
42 *ppobj = (LPVOID)&This->ObjectVtbl;
43 IDirectMusicCollectionImpl_IDirectMusicObject_AddRef ((LPDIRECTMUSICOBJECT)&This->ObjectVtbl);
44 return S_OK;
45 } else if (IsEqualIID (riid, &IID_IPersistStream)) {
46 *ppobj = (LPVOID)&This->PersistStreamVtbl;
47 IDirectMusicCollectionImpl_IPersistStream_AddRef ((LPPERSISTSTREAM)&This->PersistStreamVtbl);
48 return S_OK;
51 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
52 return E_NOINTERFACE;
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);
58 return ++(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);
65 if (ref == 0) {
66 HeapFree(GetProcessHeap(), 0, This);
68 return ref;
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;
98 DWORD dwInstPatch;
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);
110 return S_OK;
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);
121 int r = 0;
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);
128 if (r == dwIndex) {
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);
133 return S_OK;
135 r++;
138 return S_FALSE;
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);
170 return S_OK;
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);
201 /* add new flags */
202 This->pDesc->dwValidData |= pDesc->dwValidData;
204 return S_OK;
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) {
222 case FOURCC_RIFF: {
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);
226 StreamCount = 0;
227 if (Chunk.fccID == mmioFOURCC('D','L','S',' ')) {
228 TRACE_(dmfile)(": collection form\n");
229 do {
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) {
234 case FOURCC_DLID: {
235 TRACE_(dmfile)(": GUID chunk\n");
236 pDesc->dwValidData |= DMUS_OBJ_OBJECT;
237 IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL);
238 break;
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);
244 break;
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);
250 break;
252 case FOURCC_LIST: {
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);
256 ListCount[0] = 0;
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");
261 do {
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)) {
273 ListCount[0] ++;
274 liMove.QuadPart = 1;
275 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
277 break;
279 case mmioFOURCC('I','A','R','T'): {
280 TRACE_(dmfile)(": artist chunk (ignored)\n");
281 if (even_or_odd(Chunk.dwSize)) {
282 ListCount[0] ++;
283 Chunk.dwSize++;
285 liMove.QuadPart = Chunk.dwSize;
286 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
287 break;
289 case mmioFOURCC('I','C','O','P'): {
290 TRACE_(dmfile)(": copyright chunk (ignored)\n");
291 if (even_or_odd(Chunk.dwSize)) {
292 ListCount[0] ++;
293 Chunk.dwSize++;
295 liMove.QuadPart = Chunk.dwSize;
296 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
297 break;
299 case mmioFOURCC('I','S','B','J'): {
300 TRACE_(dmfile)(": subject chunk (ignored)\n");
301 if (even_or_odd(Chunk.dwSize)) {
302 ListCount[0] ++;
303 Chunk.dwSize++;
305 liMove.QuadPart = Chunk.dwSize;
306 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
307 break;
309 case mmioFOURCC('I','C','M','T'): {
310 TRACE_(dmfile)(": comment chunk (ignored)\n");
311 if (even_or_odd(Chunk.dwSize)) {
312 ListCount[0] ++;
313 Chunk.dwSize++;
315 liMove.QuadPart = Chunk.dwSize;
316 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
317 break;
319 default: {
320 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
321 if (even_or_odd(Chunk.dwSize)) {
322 ListCount[0] ++;
323 Chunk.dwSize++;
325 liMove.QuadPart = Chunk.dwSize;
326 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
327 break;
330 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
331 } while (ListCount[0] < ListSize[0]);
332 break;
334 default: {
335 TRACE_(dmfile)(": unknown (skipping)\n");
336 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
337 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
338 break;
341 break;
343 default: {
344 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
345 liMove.QuadPart = Chunk.dwSize;
346 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
347 break;
350 TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
351 } while (StreamCount < StreamSize);
352 break;
353 } else {
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 */
357 return E_FAIL;
360 TRACE_(dmfile)(": reading finished\n");
361 break;
363 default: {
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));
373 return S_OK;
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) {
402 return E_NOTIMPL;
405 HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
406 return E_NOTIMPL;
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 */
418 liMove.QuadPart = 0;
419 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibCollectionPosition); /* store offset, in case it'll be needed later */
420 This->liCollectionPosition.QuadPart = dlibCollectionPosition.QuadPart;
421 This->pStm = pStm;
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) {
426 case FOURCC_RIFF: {
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);
430 StreamCount = 0;
431 switch (Chunk.fccID) {
432 case FOURCC_DLS: {
433 TRACE_(dmfile)(": collection form\n");
434 do {
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) {
439 case FOURCC_COLH: {
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);
443 break;
445 case FOURCC_DLID: {
446 TRACE_(dmfile)(": DLID (GUID) chunk\n");
447 This->pDesc->dwValidData |= DMUS_OBJ_OBJECT;
448 IStream_Read (pStm, &This->pDesc->guidObject, Chunk.dwSize, NULL);
449 break;
451 case FOURCC_VERS: {
452 TRACE_(dmfile)(": version chunk\n");
453 This->pDesc->dwValidData |= DMUS_OBJ_VERSION;
454 IStream_Read (pStm, &This->pDesc->vVersion, Chunk.dwSize, NULL);
455 break;
457 case FOURCC_PTBL: {
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);
464 break;
466 case FOURCC_LIST: {
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);
470 ListCount[0] = 0;
471 switch (Chunk.fccID) {
472 case mmioFOURCC('I','N','F','O'): {
473 TRACE_(dmfile)(": INFO list\n");
474 do {
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)) {
486 ListCount[0] ++;
487 liMove.QuadPart = 1;
488 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
490 break;
492 case mmioFOURCC('I','A','R','T'): {
493 TRACE_(dmfile)(": artist chunk (ignored)\n");
494 if (even_or_odd(Chunk.dwSize)) {
495 ListCount[0] ++;
496 Chunk.dwSize++;
498 liMove.QuadPart = Chunk.dwSize;
499 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
500 break;
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)) {
507 ListCount[0] ++;
508 liMove.QuadPart = 1;
509 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
511 break;
513 case mmioFOURCC('I','S','B','J'): {
514 TRACE_(dmfile)(": subject chunk (ignored)\n");
515 if (even_or_odd(Chunk.dwSize)) {
516 ListCount[0] ++;
517 Chunk.dwSize++;
519 liMove.QuadPart = Chunk.dwSize;
520 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
521 break;
523 case mmioFOURCC('I','C','M','T'): {
524 TRACE_(dmfile)(": comment chunk (ignored)\n");
525 if (even_or_odd(Chunk.dwSize)) {
526 ListCount[0] ++;
527 Chunk.dwSize++;
529 liMove.QuadPart = Chunk.dwSize;
530 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
531 break;
533 default: {
534 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
535 if (even_or_odd(Chunk.dwSize)) {
536 ListCount[0] ++;
537 Chunk.dwSize++;
539 liMove.QuadPart = Chunk.dwSize;
540 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
541 break;
544 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
545 } while (ListCount[0] < ListSize[0]);
546 break;
548 case FOURCC_WVPL: {
549 TRACE_(dmfile)(": wave pool list (mark & skip)\n");
550 liMove.QuadPart = 0;
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);
555 break;
557 case FOURCC_LINS: {
558 TRACE_(dmfile)(": instruments list\n");
559 do {
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) {
564 case FOURCC_LIST: {
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);
568 ListCount[1] = 0;
569 switch (Chunk.fccID) {
570 case FOURCC_INS: {
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);
576 liMove.QuadPart = 0;
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 */
580 do {
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) {
585 case FOURCC_INSH: {
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);
589 break;
591 case FOURCC_DLID: {
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);
595 break;
597 case FOURCC_LIST: {
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);
601 ListCount[2] = 0;
602 switch (Chunk.fccID) {
603 default: {
604 TRACE_(dmfile)(": unknown (skipping)\n");
605 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
606 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
607 break;
610 break;
612 default: {
613 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
614 liMove.QuadPart = Chunk.dwSize;
615 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
616 break;
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);
636 break;
639 break;
641 default: {
642 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
643 liMove.QuadPart = Chunk.dwSize;
644 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
645 break;
648 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
649 } while (ListCount[0] < ListSize[0]);
650 break;
652 default: {
653 TRACE_(dmfile)(": unknown (skipping)\n");
654 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
655 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
656 break;
659 break;
661 default: {
662 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
663 liMove.QuadPart = Chunk.dwSize;
664 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
665 break;
668 TRACE_(dmfile)(": StreamCount = %ld < StreamSize = %ld\n", StreamCount, StreamSize);
669 } while (StreamCount < StreamSize);
670 break;
672 default: {
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 */
676 return E_FAIL;
679 TRACE_(dmfile)(": reading finished\n");
680 break;
682 default: {
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 */
686 return E_FAIL;
690 /* DEBUG: dumps whole collection object tree: */
691 if (TRACE_ON(dmusic)) {
692 int r = 0;
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);
712 r++;
716 return S_OK;
719 HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
720 return E_NOTIMPL;
723 HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
724 return E_NOTIMPL;
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));
744 if (NULL == obj) {
745 *ppobj = (LPVOID) NULL;
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);