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 dwPatch, IDirectMusicInstrument** ppInstrument)
108 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicCollection(iface);
109 DMUS_PRIVATE_INSTRUMENTENTRY *tmpEntry;
110 struct list *listEntry;
113 TRACE("(%p, %d, %p)\n", This, dwPatch, ppInstrument);
115 LIST_FOR_EACH (listEntry, &This->Instruments) {
116 tmpEntry = LIST_ENTRY(listEntry, DMUS_PRIVATE_INSTRUMENTENTRY, entry);
117 IDirectMusicInstrument_GetPatch (tmpEntry->pInstrument, &dwInstPatch);
118 if (dwPatch == dwInstPatch) {
119 *ppInstrument = tmpEntry->pInstrument;
120 IDirectMusicInstrument_AddRef (tmpEntry->pInstrument);
121 IDirectMusicInstrumentImpl_Custom_Load (tmpEntry->pInstrument, This->pStm); /* load instrument before returning it */
122 TRACE(": returning instrument %p\n", *ppInstrument);
127 TRACE(": instrument not found\n");
129 return DMUS_E_INVALIDPATCH;
132 static HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicCollection_EnumInstrument(LPDIRECTMUSICCOLLECTION iface, DWORD dwIndex, DWORD* pdwPatch, LPWSTR pwszName, DWORD dwNameLen)
134 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicCollection(iface);
136 DMUS_PRIVATE_INSTRUMENTENTRY *tmpEntry;
137 struct list *listEntry;
140 TRACE("(%p, %d, %p, %p, %d)\n", This, dwIndex, pdwPatch, pwszName, dwNameLen);
141 LIST_FOR_EACH (listEntry, &This->Instruments) {
142 tmpEntry = LIST_ENTRY(listEntry, DMUS_PRIVATE_INSTRUMENTENTRY, entry);
144 IDirectMusicInstrumentImpl *pInstrument = impl_from_IDirectMusicInstrument(tmpEntry->pInstrument);
145 IDirectMusicInstrument_GetPatch (tmpEntry->pInstrument, pdwPatch);
147 dwLen = min(strlenW(pInstrument->wszName),dwNameLen-1);
148 memcpy (pwszName, pInstrument->wszName, dwLen * sizeof(WCHAR));
149 pwszName[dwLen] = '\0';
159 static const IDirectMusicCollectionVtbl DirectMusicCollection_Collection_Vtbl = {
160 IDirectMusicCollectionImpl_IDirectMusicCollection_QueryInterface,
161 IDirectMusicCollectionImpl_IDirectMusicCollection_AddRef,
162 IDirectMusicCollectionImpl_IDirectMusicCollection_Release,
163 IDirectMusicCollectionImpl_IDirectMusicCollection_GetInstrument,
164 IDirectMusicCollectionImpl_IDirectMusicCollection_EnumInstrument
167 /* IDirectMusicCollectionImpl IDirectMusicObject part: */
168 static HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_QueryInterface(LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ret_iface)
170 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicObject(iface);
171 return IDirectMusicCollection_QueryInterface(&This->IDirectMusicCollection_iface, riid, ret_iface);
174 static ULONG WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_AddRef(LPDIRECTMUSICOBJECT iface)
176 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicObject(iface);
177 return IDirectMusicCollection_AddRef(&This->IDirectMusicCollection_iface);
180 static ULONG WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_Release(LPDIRECTMUSICOBJECT iface)
182 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicObject(iface);
183 return IDirectMusicCollection_Release(&This->IDirectMusicCollection_iface);
186 static HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_GetDescriptor(LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc)
188 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicObject(iface);
190 TRACE("(%p/%p)->(%p)\n", iface, This, pDesc);
192 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
193 memcpy (pDesc, This->pDesc, This->pDesc->dwSize);
198 static HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_SetDescriptor(LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc)
200 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicObject(iface);
202 TRACE("(%p, %p)\n", iface, pDesc);
207 if (TRACE_ON(dmusic))
209 TRACE("Setting descriptor:\n");
210 dump_DMUS_OBJECTDESC(pDesc);
213 /* According to MSDN, we should copy only given values, not whole struct */
214 if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
215 This->pDesc->guidObject = pDesc->guidObject;
216 if (pDesc->dwValidData & DMUS_OBJ_CLASS)
217 This->pDesc->guidClass = pDesc->guidClass;
218 if (pDesc->dwValidData & DMUS_OBJ_NAME)
219 lstrcpynW(This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
220 if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
221 lstrcpynW(This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);
222 if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
223 lstrcpynW(This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);
224 if (pDesc->dwValidData & DMUS_OBJ_VERSION)
225 This->pDesc->vVersion = pDesc->vVersion;
226 if (pDesc->dwValidData & DMUS_OBJ_DATE)
227 This->pDesc->ftDate = pDesc->ftDate;
228 if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
229 This->pDesc->llMemLength = pDesc->llMemLength;
230 memcpy (This->pDesc->pbMemData, pDesc->pbMemData, pDesc->llMemLength);
232 if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
233 /* according to MSDN, we copy the stream */
234 IStream_Clone (pDesc->pStream, &This->pDesc->pStream);
238 This->pDesc->dwValidData |= pDesc->dwValidData;
243 static HRESULT read_from_stream(IStream *stream, void *data, ULONG size)
248 hr = IStream_Read(stream, data, size, &read);
250 TRACE("IStream_Read failed: %08x\n", hr);
254 TRACE("Didn't read full chunk: %u < %u\n", read, size);
261 static HRESULT WINAPI IDirectMusicCollectionImpl_IDirectMusicObject_ParseDescriptor(LPDIRECTMUSICOBJECT iface, LPSTREAM stream, LPDMUS_OBJECTDESC desc)
263 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicObject(iface);
264 DMUS_PRIVATE_CHUNK chunk;
265 DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
266 LARGE_INTEGER liMove; /* used when skipping chunks */
269 TRACE("(%p)->(%p, %p)\n", This, stream, desc);
271 /* FIXME: should this be determined from stream? */
272 desc->dwValidData |= DMUS_OBJ_CLASS;
273 desc->guidClass = CLSID_DirectMusicCollection;
275 hr = read_from_stream(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD));
278 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize);
280 if (chunk.fccID != FOURCC_RIFF) {
281 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
282 liMove.QuadPart = chunk.dwSize;
283 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
284 return DMUS_E_INVALIDFILE;
287 hr = read_from_stream(stream, &chunk.fccID, sizeof(FOURCC));
290 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(chunk.fccID));
291 StreamSize = chunk.dwSize - sizeof(FOURCC);
293 if (chunk.fccID != mmioFOURCC('D','L','S',' ')) {
294 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
295 liMove.QuadPart = StreamSize;
296 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
301 TRACE_(dmfile)(": collection form\n");
304 hr = read_from_stream(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD));
307 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize;
308 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize);
309 switch (chunk.fccID) {
311 TRACE_(dmfile)(": GUID chunk\n");
312 desc->dwValidData |= DMUS_OBJ_OBJECT;
313 hr = read_from_stream(stream, &desc->guidObject, chunk.dwSize);
318 case DMUS_FOURCC_VERSION_CHUNK:
319 TRACE_(dmfile)(": version chunk\n");
320 desc->dwValidData |= DMUS_OBJ_VERSION;
321 hr = read_from_stream(stream, &desc->vVersion, chunk.dwSize);
326 case DMUS_FOURCC_CATEGORY_CHUNK:
327 TRACE_(dmfile)(": category chunk\n");
328 desc->dwValidData |= DMUS_OBJ_CATEGORY;
329 hr = read_from_stream(stream, desc->wszCategory, chunk.dwSize);
335 hr = read_from_stream(stream, &chunk.fccID, sizeof(FOURCC));
338 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunk.fccID));
339 ListSize[0] = chunk.dwSize - sizeof(FOURCC);
341 switch (chunk.fccID) {
342 /* pure INFO list, such can be found in dls collections */
343 case mmioFOURCC('I','N','F','O'):
344 TRACE_(dmfile)(": INFO list\n");
346 hr = read_from_stream(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD));
349 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize;
350 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize);
351 switch (chunk.fccID) {
352 case mmioFOURCC('I','N','A','M'): {
353 CHAR szName[DMUS_MAX_NAME];
354 TRACE_(dmfile)(": name chunk\n");
355 desc->dwValidData |= DMUS_OBJ_NAME;
356 hr = read_from_stream(stream, szName, chunk.dwSize);
359 MultiByteToWideChar (CP_ACP, 0, szName, -1, desc->wszName, DMUS_MAX_NAME);
360 if (even_or_odd(chunk.dwSize)) {
363 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
368 case mmioFOURCC('I','A','R','T'):
369 TRACE_(dmfile)(": artist chunk (ignored)\n");
370 if (even_or_odd(chunk.dwSize)) {
374 liMove.QuadPart = chunk.dwSize;
375 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
378 case mmioFOURCC('I','C','O','P'):
379 TRACE_(dmfile)(": copyright chunk (ignored)\n");
380 if (even_or_odd(chunk.dwSize)) {
384 liMove.QuadPart = chunk.dwSize;
385 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
388 case mmioFOURCC('I','S','B','J'):
389 TRACE_(dmfile)(": subject chunk (ignored)\n");
390 if (even_or_odd(chunk.dwSize)) {
394 liMove.QuadPart = chunk.dwSize;
395 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
398 case mmioFOURCC('I','C','M','T'):
399 TRACE_(dmfile)(": comment chunk (ignored)\n");
400 if (even_or_odd(chunk.dwSize)) {
403 liMove.QuadPart = chunk.dwSize;
404 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
409 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
410 if (even_or_odd(chunk.dwSize)) {
414 liMove.QuadPart = chunk.dwSize;
415 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
418 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
419 } while (ListCount[0] < ListSize[0]);
423 TRACE_(dmfile)(": unknown (skipping)\n");
424 liMove.QuadPart = chunk.dwSize - sizeof(FOURCC);
425 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
431 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
432 liMove.QuadPart = chunk.dwSize;
433 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
436 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
437 } while (StreamCount < StreamSize);
439 TRACE_(dmfile)(": reading finished\n");
441 if (TRACE_ON(dmusic)) {
442 TRACE("Returning descriptor:\n");
443 dump_DMUS_OBJECTDESC(desc);
449 static const IDirectMusicObjectVtbl DirectMusicCollection_Object_Vtbl = {
450 IDirectMusicCollectionImpl_IDirectMusicObject_QueryInterface,
451 IDirectMusicCollectionImpl_IDirectMusicObject_AddRef,
452 IDirectMusicCollectionImpl_IDirectMusicObject_Release,
453 IDirectMusicCollectionImpl_IDirectMusicObject_GetDescriptor,
454 IDirectMusicCollectionImpl_IDirectMusicObject_SetDescriptor,
455 IDirectMusicCollectionImpl_IDirectMusicObject_ParseDescriptor
458 /* IDirectMusicCollectionImpl IPersistStream part: */
459 static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_QueryInterface(LPPERSISTSTREAM iface, REFIID riid, LPVOID *ret_iface)
461 IDirectMusicCollectionImpl *This = impl_from_IPersistStream(iface);
462 return IDirectMusicCollection_QueryInterface(&This->IDirectMusicCollection_iface, riid, ret_iface);
465 static ULONG WINAPI IDirectMusicCollectionImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface)
467 IDirectMusicCollectionImpl *This = impl_from_IPersistStream(iface);
468 return IDirectMusicCollection_AddRef(&This->IDirectMusicCollection_iface);
471 static ULONG WINAPI IDirectMusicCollectionImpl_IPersistStream_Release (LPPERSISTSTREAM iface)
473 IDirectMusicCollectionImpl *This = impl_from_IPersistStream(iface);
474 return IDirectMusicCollection_Release(&This->IDirectMusicCollection_iface);
477 static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_GetClassID(LPPERSISTSTREAM iface, CLSID* pClassID)
482 static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_IsDirty(LPPERSISTSTREAM iface)
487 static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm)
489 IDirectMusicCollectionImpl *This = impl_from_IPersistStream(iface);
490 DMUS_PRIVATE_CHUNK Chunk;
491 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
492 LARGE_INTEGER liMove; /* used when skipping chunks */
493 ULARGE_INTEGER dlibCollectionPosition, dlibInstrumentPosition, dlibWavePoolPosition;
495 IStream_AddRef (pStm); /* add count for later references */
497 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibCollectionPosition); /* store offset, in case it'll be needed later */
498 This->liCollectionPosition.QuadPart = dlibCollectionPosition.QuadPart;
501 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
502 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
503 switch (Chunk.fccID) {
505 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
506 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
507 StreamSize = Chunk.dwSize - sizeof(FOURCC);
509 switch (Chunk.fccID) {
511 TRACE_(dmfile)(": collection form\n");
513 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
514 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
515 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
516 switch (Chunk.fccID) {
518 TRACE_(dmfile)(": collection header chunk\n");
519 This->pHeader = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
520 IStream_Read (pStm, This->pHeader, Chunk.dwSize, NULL);
524 TRACE_(dmfile)(": DLID (GUID) chunk\n");
525 This->pDesc->dwValidData |= DMUS_OBJ_OBJECT;
526 IStream_Read (pStm, &This->pDesc->guidObject, Chunk.dwSize, NULL);
530 TRACE_(dmfile)(": version chunk\n");
531 This->pDesc->dwValidData |= DMUS_OBJ_VERSION;
532 IStream_Read (pStm, &This->pDesc->vVersion, Chunk.dwSize, NULL);
536 TRACE_(dmfile)(": pool table chunk\n");
537 This->pPoolTable = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(POOLTABLE));
538 IStream_Read (pStm, This->pPoolTable, sizeof(POOLTABLE), NULL);
539 Chunk.dwSize -= sizeof(POOLTABLE);
540 This->pPoolCues = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, This->pPoolTable->cCues*sizeof(POOLCUE));
541 IStream_Read (pStm, This->pPoolCues, Chunk.dwSize, NULL);
545 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
546 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
547 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
549 switch (Chunk.fccID) {
550 case mmioFOURCC('I','N','F','O'): {
551 TRACE_(dmfile)(": INFO list\n");
553 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
554 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
555 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
556 switch (Chunk.fccID) {
557 case mmioFOURCC('I','N','A','M'): {
558 CHAR szName[DMUS_MAX_NAME];
559 TRACE_(dmfile)(": name chunk\n");
560 This->pDesc->dwValidData |= DMUS_OBJ_NAME;
561 IStream_Read (pStm, szName, Chunk.dwSize, NULL);
562 MultiByteToWideChar (CP_ACP, 0, szName, -1, This->pDesc->wszName, DMUS_MAX_NAME);
563 if (even_or_odd(Chunk.dwSize)) {
566 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
570 case mmioFOURCC('I','A','R','T'): {
571 TRACE_(dmfile)(": artist chunk (ignored)\n");
572 if (even_or_odd(Chunk.dwSize)) {
576 liMove.QuadPart = Chunk.dwSize;
577 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
580 case mmioFOURCC('I','C','O','P'): {
581 TRACE_(dmfile)(": copyright chunk\n");
582 This->szCopyright = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
583 IStream_Read (pStm, This->szCopyright, Chunk.dwSize, NULL);
584 if (even_or_odd(Chunk.dwSize)) {
587 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
591 case mmioFOURCC('I','S','B','J'): {
592 TRACE_(dmfile)(": subject chunk (ignored)\n");
593 if (even_or_odd(Chunk.dwSize)) {
597 liMove.QuadPart = Chunk.dwSize;
598 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
601 case mmioFOURCC('I','C','M','T'): {
602 TRACE_(dmfile)(": comment chunk (ignored)\n");
603 if (even_or_odd(Chunk.dwSize)) {
607 liMove.QuadPart = Chunk.dwSize;
608 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
612 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
613 if (even_or_odd(Chunk.dwSize)) {
617 liMove.QuadPart = Chunk.dwSize;
618 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
622 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
623 } while (ListCount[0] < ListSize[0]);
627 TRACE_(dmfile)(": wave pool list (mark & skip)\n");
629 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibWavePoolPosition); /* store position */
630 This->liWavePoolTablePosition.QuadPart = dlibWavePoolPosition.QuadPart;
631 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
632 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
636 TRACE_(dmfile)(": instruments list\n");
638 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
639 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
640 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
641 switch (Chunk.fccID) {
643 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
644 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
645 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
647 switch (Chunk.fccID) {
649 LPDMUS_PRIVATE_INSTRUMENTENTRY pNewInstrument = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_INSTRUMENTENTRY));
650 TRACE_(dmfile)(": instrument list\n");
651 DMUSIC_CreateDirectMusicInstrumentImpl (&IID_IDirectMusicInstrument, (LPVOID*)&pNewInstrument->pInstrument, NULL); /* only way to create this one... even M$ does it discretely */
653 IDirectMusicInstrumentImpl *pInstrument = impl_from_IDirectMusicInstrument(pNewInstrument->pInstrument);
655 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, &dlibInstrumentPosition);
656 pInstrument->liInstrumentPosition.QuadPart = dlibInstrumentPosition.QuadPart - (2*sizeof(FOURCC) + sizeof(DWORD)); /* store offset, it'll be needed later */
659 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
660 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
661 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
662 switch (Chunk.fccID) {
664 TRACE_(dmfile)(": instrument header chunk\n");
665 pInstrument->pHeader = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
666 IStream_Read (pStm, pInstrument->pHeader, Chunk.dwSize, NULL);
670 TRACE_(dmfile)(": DLID (GUID) chunk\n");
671 pInstrument->pInstrumentID = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
672 IStream_Read (pStm, pInstrument->pInstrumentID, Chunk.dwSize, NULL);
676 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
677 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
678 ListSize[2] = Chunk.dwSize - sizeof(FOURCC);
680 switch (Chunk.fccID) {
682 TRACE_(dmfile)(": unknown (skipping)\n");
683 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
684 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
691 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
692 liMove.QuadPart = Chunk.dwSize;
693 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
697 TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]);
698 } while (ListCount[1] < ListSize[1]);
699 /* DEBUG: dumps whole instrument object tree: */
700 if (TRACE_ON(dmusic)) {
701 TRACE("*** IDirectMusicInstrument (%p) ***\n", pInstrument);
702 if (pInstrument->pInstrumentID)
703 TRACE(" - GUID = %s\n", debugstr_dmguid(pInstrument->pInstrumentID));
705 TRACE(" - Instrument header:\n");
706 TRACE(" - cRegions: %d\n", pInstrument->pHeader->cRegions);
707 TRACE(" - Locale:\n");
708 TRACE(" - ulBank: %d\n", pInstrument->pHeader->Locale.ulBank);
709 TRACE(" - ulInstrument: %d\n", pInstrument->pHeader->Locale.ulInstrument);
710 TRACE(" => dwPatch: %d\n", MIDILOCALE2Patch(&pInstrument->pHeader->Locale));
712 list_add_tail (&This->Instruments, &pNewInstrument->entry);
720 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
721 liMove.QuadPart = Chunk.dwSize;
722 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
726 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
727 } while (ListCount[0] < ListSize[0]);
731 TRACE_(dmfile)(": unknown (skipping)\n");
732 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
733 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
740 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
741 liMove.QuadPart = Chunk.dwSize;
742 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
746 TRACE_(dmfile)(": StreamCount = %d < StreamSize = %d\n", StreamCount, StreamSize);
747 } while (StreamCount < StreamSize);
751 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
752 liMove.QuadPart = StreamSize;
753 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
757 TRACE_(dmfile)(": reading finished\n");
761 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
762 liMove.QuadPart = Chunk.dwSize;
763 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
768 /* DEBUG: dumps whole collection object tree: */
769 if (TRACE_ON(dmusic)) {
771 DMUS_PRIVATE_INSTRUMENTENTRY *tmpEntry;
772 struct list *listEntry;
774 TRACE("*** IDirectMusicCollection (%p) ***\n", &This->IDirectMusicCollection_iface);
775 if (This->pDesc->dwValidData & DMUS_OBJ_OBJECT)
776 TRACE(" - GUID = %s\n", debugstr_dmguid(&This->pDesc->guidObject));
777 if (This->pDesc->dwValidData & DMUS_OBJ_VERSION)
778 TRACE(" - Version = %i,%i,%i,%i\n", (This->pDesc->vVersion.dwVersionMS >> 8) & 0x0000FFFF, This->pDesc->vVersion.dwVersionMS & 0x0000FFFF,
779 (This->pDesc->vVersion.dwVersionLS >> 8) & 0x0000FFFF, This->pDesc->vVersion.dwVersionLS & 0x0000FFFF);
780 if (This->pDesc->dwValidData & DMUS_OBJ_NAME)
781 TRACE(" - Name = %s\n", debugstr_w(This->pDesc->wszName));
783 TRACE(" - Collection header:\n");
784 TRACE(" - cInstruments: %d\n", This->pHeader->cInstruments);
785 TRACE(" - Instruments:\n");
787 LIST_FOR_EACH (listEntry, &This->Instruments) {
788 tmpEntry = LIST_ENTRY( listEntry, DMUS_PRIVATE_INSTRUMENTENTRY, entry );
789 TRACE(" - Instrument[%i]: %p\n", r, tmpEntry->pInstrument);
797 static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_Save(LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty)
802 static HRESULT WINAPI IDirectMusicCollectionImpl_IPersistStream_GetSizeMax(LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize)
807 static const IPersistStreamVtbl DirectMusicCollection_PersistStream_Vtbl = {
808 IDirectMusicCollectionImpl_IPersistStream_QueryInterface,
809 IDirectMusicCollectionImpl_IPersistStream_AddRef,
810 IDirectMusicCollectionImpl_IPersistStream_Release,
811 IDirectMusicCollectionImpl_IPersistStream_GetClassID,
812 IDirectMusicCollectionImpl_IPersistStream_IsDirty,
813 IDirectMusicCollectionImpl_IPersistStream_Load,
814 IDirectMusicCollectionImpl_IPersistStream_Save,
815 IDirectMusicCollectionImpl_IPersistStream_GetSizeMax
819 /* for ClassFactory */
820 HRESULT WINAPI DMUSIC_CreateDirectMusicCollectionImpl(LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter)
822 IDirectMusicCollectionImpl* obj;
824 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicCollectionImpl));
827 return E_OUTOFMEMORY;
829 obj->IDirectMusicCollection_iface.lpVtbl = &DirectMusicCollection_Collection_Vtbl;
830 obj->IDirectMusicObject_iface.lpVtbl = &DirectMusicCollection_Object_Vtbl;
831 obj->IPersistStream_iface.lpVtbl = &DirectMusicCollection_PersistStream_Vtbl;
832 obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
833 DM_STRUCT_INIT(obj->pDesc);
834 obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
835 obj->pDesc->guidClass = CLSID_DirectMusicCollection;
836 obj->ref = 0; /* will be inited by QueryInterface */
837 list_init (&obj->Instruments);
839 return IDirectMusicCollection_QueryInterface(&obj->IDirectMusicCollection_iface, lpcGUID, ppobj);