1 /*
2 * IDirectMusicCollection Implementation
3 *
4 * Copyright (C) 2003-2004 Rok Mandeljc
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include "dmusic_private.h"
22 #include "dmobject.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
25 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
26
27 /*****************************************************************************
28 * IDirectMusicCollectionImpl implementation
29 */
30 typedef struct IDirectMusicCollectionImpl {
31 IDirectMusicCollection IDirectMusicCollection_iface;
32 struct dmobject dmobj;
33 LONG ref;
34 /* IDirectMusicCollectionImpl fields */
35 IStream *pStm; /* stream from which we load collection and later instruments */
36 LARGE_INTEGER liCollectionPosition; /* offset in a stream where collection was loaded from */
37 LARGE_INTEGER liWavePoolTablePosition; /* offset in a stream where wave pool table can be found */
38 CHAR *szCopyright; /* FIXME: should probably be placed somewhere else */
39 DLSHEADER *pHeader;
40 /* pool table */
41 POOLTABLE *pPoolTable;
42 POOLCUE *pPoolCues;
43 /* instruments */
44 struct list Instruments;
45 } IDirectMusicCollectionImpl;
46
impl_from_IDirectMusicCollection(IDirectMusicCollection * iface)47 static inline IDirectMusicCollectionImpl *impl_from_IDirectMusicCollection(IDirectMusicCollection *iface)
48 {
49 return CONTAINING_RECORD(iface, IDirectMusicCollectionImpl, IDirectMusicCollection_iface);
50 }
51
impl_from_IDirectMusicObject(IDirectMusicObject * iface)52 static inline struct dmobject *impl_from_IDirectMusicObject(IDirectMusicObject *iface)
53 {
54 return CONTAINING_RECORD(iface, struct dmobject, IDirectMusicObject_iface);
55 }
56
impl_from_IPersistStream(IPersistStream * iface)57 static inline IDirectMusicCollectionImpl *impl_from_IPersistStream(IPersistStream *iface)
58 {
59 return CONTAINING_RECORD(iface, IDirectMusicCollectionImpl, dmobj.IPersistStream_iface);
60 }
61
62 /* IDirectMusicCollectionImpl IUnknown part: */
IDirectMusicCollectionImpl_QueryInterface(IDirectMusicCollection * iface,REFIID riid,void ** ret_iface)63 static HRESULT WINAPI IDirectMusicCollectionImpl_QueryInterface(IDirectMusicCollection *iface,
64 REFIID riid, void **ret_iface)
65 {
66 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicCollection(iface);
67
68 TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_dmguid(riid), ret_iface);
69
70 *ret_iface = NULL;
71
72 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicCollection))
73 *ret_iface = iface;
74 else if (IsEqualIID(riid, &IID_IDirectMusicObject))
75 *ret_iface = &This->dmobj.IDirectMusicObject_iface;
76 else if (IsEqualIID(riid, &IID_IPersistStream))
77 *ret_iface = &This->dmobj.IPersistStream_iface;
78 else
79 {
80 WARN("(%p/%p)->(%s, %p): not found\n", iface, This, debugstr_dmguid(riid), ret_iface);
81 return E_NOINTERFACE;
82 }
83
84 IUnknown_AddRef((IUnknown*)*ret_iface);
85 return S_OK;
86 }
87
IDirectMusicCollectionImpl_AddRef(IDirectMusicCollection * iface)88 static ULONG WINAPI IDirectMusicCollectionImpl_AddRef(IDirectMusicCollection *iface)
89 {
90 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicCollection(iface);
91 ULONG ref = InterlockedIncrement(&This->ref);
92
93 TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
94
95 return ref;
96 }
97
IDirectMusicCollectionImpl_Release(IDirectMusicCollection * iface)98 static ULONG WINAPI IDirectMusicCollectionImpl_Release(IDirectMusicCollection *iface)
99 {
100 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicCollection(iface);
101 ULONG ref = InterlockedDecrement(&This->ref);
102
103 TRACE("(%p/%p)->(): new ref = %u\n", iface, This, ref);
104
105 if (!ref) {
106 HeapFree(GetProcessHeap(), 0, This);
107 DMUSIC_UnlockModule();
108 }
109
110 return ref;
111 }
112
113 /* IDirectMusicCollection Interface follows: */
IDirectMusicCollectionImpl_GetInstrument(IDirectMusicCollection * iface,DWORD patch,IDirectMusicInstrument ** instrument)114 static HRESULT WINAPI IDirectMusicCollectionImpl_GetInstrument(IDirectMusicCollection *iface,
115 DWORD patch, IDirectMusicInstrument **instrument)
116 {
117 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicCollection(iface);
118 DMUS_PRIVATE_INSTRUMENTENTRY *inst_entry;
119 struct list *list_entry;
120 DWORD inst_patch;
121
122 TRACE("(%p/%p)->(%u, %p)\n", iface, This, patch, instrument);
123
124 LIST_FOR_EACH(list_entry, &This->Instruments) {
125 inst_entry = LIST_ENTRY(list_entry, DMUS_PRIVATE_INSTRUMENTENTRY, entry);
126 IDirectMusicInstrument_GetPatch(inst_entry->pInstrument, &inst_patch);
127 if (patch == inst_patch) {
128 *instrument = inst_entry->pInstrument;
129 IDirectMusicInstrument_AddRef(inst_entry->pInstrument);
130 IDirectMusicInstrumentImpl_CustomLoad(inst_entry->pInstrument, This->pStm);
131 TRACE(": returning instrument %p\n", *instrument);
132 return S_OK;
133 }
134 }
135
136 TRACE(": instrument not found\n");
137
138 return DMUS_E_INVALIDPATCH;
139 }
140
IDirectMusicCollectionImpl_EnumInstrument(IDirectMusicCollection * iface,DWORD index,DWORD * patch,LPWSTR name,DWORD name_length)141 static HRESULT WINAPI IDirectMusicCollectionImpl_EnumInstrument(IDirectMusicCollection *iface,
142 DWORD index, DWORD *patch, LPWSTR name, DWORD name_length)
143 {
144 IDirectMusicCollectionImpl *This = impl_from_IDirectMusicCollection(iface);
145 DWORD i = 0;
146 DMUS_PRIVATE_INSTRUMENTENTRY *inst_entry;
147 struct list *list_entry;
148 DWORD length;
149
150 TRACE("(%p/%p)->(%d, %p, %p, %d)\n", iface, This, index, patch, name, name_length);
151
152 LIST_FOR_EACH(list_entry, &This->Instruments) {
153 inst_entry = LIST_ENTRY(list_entry, DMUS_PRIVATE_INSTRUMENTENTRY, entry);
154 if (i == index) {
155 IDirectMusicInstrumentImpl *instrument = impl_from_IDirectMusicInstrument(inst_entry->pInstrument);
156 IDirectMusicInstrument_GetPatch(inst_entry->pInstrument, patch);
157 if (name) {
158 length = min(lstrlenW(instrument->wszName), name_length - 1);
159 memcpy(name, instrument->wszName, length * sizeof(WCHAR));
160 name[length] = '\0';
161 }
162 return S_OK;
163 }
164 i++;
165 }
166
167 return S_FALSE;
168 }
169
170 static const IDirectMusicCollectionVtbl DirectMusicCollection_Collection_Vtbl = {
171 IDirectMusicCollectionImpl_QueryInterface,
172 IDirectMusicCollectionImpl_AddRef,
173 IDirectMusicCollectionImpl_Release,
174 IDirectMusicCollectionImpl_GetInstrument,
175 IDirectMusicCollectionImpl_EnumInstrument
176 };
177
178 /* IDirectMusicCollectionImpl IDirectMusicObject part: */
col_IDirectMusicObject_ParseDescriptor(IDirectMusicObject * iface,IStream * stream,DMUS_OBJECTDESC * desc)179 static HRESULT WINAPI col_IDirectMusicObject_ParseDescriptor(IDirectMusicObject *iface,
180 IStream *stream, DMUS_OBJECTDESC *desc)
181 {
182 struct chunk_entry riff = {0};
183 HRESULT hr;
184
185 TRACE("(%p, %p, %p)\n", iface, stream, desc);
186
187 if (!stream || !desc)
188 return E_POINTER;
189
190 if ((hr = stream_get_chunk(stream, &riff)) != S_OK)
191 return hr;
192 if (riff.id != FOURCC_RIFF || riff.type != FOURCC_DLS) {
193 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff));
194 stream_skip_chunk(stream, &riff);
195 return DMUS_E_NOTADLSCOL;
196 }
197
198 hr = dmobj_parsedescriptor(stream, &riff, desc, DMUS_OBJ_NAME_INFO|DMUS_OBJ_VERSION);
199 if (FAILED(hr))
200 return hr;
201
202 desc->guidClass = CLSID_DirectMusicCollection;
203 desc->dwValidData |= DMUS_OBJ_CLASS;
204
205 TRACE("returning descriptor:\n");
206 dump_DMUS_OBJECTDESC(desc);
207 return S_OK;
208 }
209
210 static const IDirectMusicObjectVtbl dmobject_vtbl = {
211 dmobj_IDirectMusicObject_QueryInterface,
212 dmobj_IDirectMusicObject_AddRef,
213 dmobj_IDirectMusicObject_Release,
214 dmobj_IDirectMusicObject_GetDescriptor,
215 dmobj_IDirectMusicObject_SetDescriptor,
216 col_IDirectMusicObject_ParseDescriptor
217 };
218
219 /* IDirectMusicCollectionImpl IPersistStream part: */
IPersistStreamImpl_Load(IPersistStream * iface,IStream * stream)220 static HRESULT WINAPI IPersistStreamImpl_Load(IPersistStream *iface,
221 IStream *stream)
222 {
223 IDirectMusicCollectionImpl *This = impl_from_IPersistStream(iface);
224 DMUS_PRIVATE_CHUNK chunk;
225 DWORD StreamSize, StreamCount, ListSize[2], ListCount[2];
226 LARGE_INTEGER liMove; /* used when skipping chunks */
227 ULARGE_INTEGER dlibCollectionPosition, dlibInstrumentPosition, dlibWavePoolPosition;
228
229 IStream_AddRef(stream); /* add count for later references */
230 liMove.QuadPart = 0;
231 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, &dlibCollectionPosition); /* store offset, in case it'll be needed later */
232 This->liCollectionPosition.QuadPart = dlibCollectionPosition.QuadPart;
233 This->pStm = stream;
234
235 IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL);
236 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize);
237
238 if (chunk.fccID != FOURCC_RIFF) {
239 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
240 liMove.QuadPart = chunk.dwSize;
241 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
242 return E_FAIL;
243 }
244
245 IStream_Read(stream, &chunk.fccID, sizeof(FOURCC), NULL);
246 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(chunk.fccID));
247 StreamSize = chunk.dwSize - sizeof(FOURCC);
248 StreamCount = 0;
249
250 if (chunk.fccID != FOURCC_DLS) {
251 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
252 liMove.QuadPart = StreamSize;
253 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
254 return E_FAIL;
255 }
256
257 TRACE_(dmfile)(": collection form\n");
258 do {
259 IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL);
260 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize;
261 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize);
262 switch (chunk.fccID) {
263 case FOURCC_COLH: {
264 TRACE_(dmfile)(": collection header chunk\n");
265 This->pHeader = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, chunk.dwSize);
266 IStream_Read(stream, This->pHeader, chunk.dwSize, NULL);
267 break;
268 }
269 case FOURCC_DLID: {
270 TRACE_(dmfile)(": DLID (GUID) chunk\n");
271 This->dmobj.desc.dwValidData |= DMUS_OBJ_OBJECT;
272 IStream_Read(stream, &This->dmobj.desc.guidObject, chunk.dwSize, NULL);
273 break;
274 }
275 case FOURCC_VERS: {
276 TRACE_(dmfile)(": version chunk\n");
277 This->dmobj.desc.dwValidData |= DMUS_OBJ_VERSION;
278 IStream_Read(stream, &This->dmobj.desc.vVersion, chunk.dwSize, NULL);
279 break;
280 }
281 case FOURCC_PTBL: {
282 TRACE_(dmfile)(": pool table chunk\n");
283 This->pPoolTable = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(POOLTABLE));
284 IStream_Read(stream, This->pPoolTable, sizeof(POOLTABLE), NULL);
285 chunk.dwSize -= sizeof(POOLTABLE);
286 This->pPoolCues = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->pPoolTable->cCues * sizeof(POOLCUE));
287 IStream_Read(stream, This->pPoolCues, chunk.dwSize, NULL);
288 break;
289 }
290 case FOURCC_LIST: {
291 IStream_Read(stream, &chunk.fccID, sizeof(FOURCC), NULL);
292 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunk.fccID));
293 ListSize[0] = chunk.dwSize - sizeof(FOURCC);
294 ListCount[0] = 0;
295 switch (chunk.fccID) {
296 case DMUS_FOURCC_INFO_LIST: {
297 TRACE_(dmfile)(": INFO list\n");
298 do {
299 IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL);
300 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize;
301 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize);
302 switch (chunk.fccID) {
303 case mmioFOURCC('I','N','A','M'): {
304 CHAR szName[DMUS_MAX_NAME];
305 TRACE_(dmfile)(": name chunk\n");
306 This->dmobj.desc.dwValidData |= DMUS_OBJ_NAME;
307 IStream_Read(stream, szName, chunk.dwSize, NULL);
308 MultiByteToWideChar(CP_ACP, 0, szName, -1, This->dmobj.desc.wszName, DMUS_MAX_NAME);
309 if (even_or_odd(chunk.dwSize)) {
310 ListCount[0]++;
311 liMove.QuadPart = 1;
312 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
313 }
314 break;
315 }
316 case mmioFOURCC('I','A','R','T'): {
317 TRACE_(dmfile)(": artist chunk (ignored)\n");
318 if (even_or_odd(chunk.dwSize)) {
319 ListCount[0]++;
320 chunk.dwSize++;
321 }
322 liMove.QuadPart = chunk.dwSize;
323 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
324 break;
325 }
326 case mmioFOURCC('I','C','O','P'): {
327 TRACE_(dmfile)(": copyright chunk\n");
328 This->szCopyright = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, chunk.dwSize);
329 IStream_Read(stream, This->szCopyright, chunk.dwSize, NULL);
330 if (even_or_odd(chunk.dwSize)) {
331 ListCount[0]++;
332 liMove.QuadPart = 1;
333 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
334 }
335 break;
336 }
337 case mmioFOURCC('I','S','B','J'): {
338 TRACE_(dmfile)(": subject chunk (ignored)\n");
339 if (even_or_odd(chunk.dwSize)) {
340 ListCount[0]++;
341 chunk.dwSize++;
342 }
343 liMove.QuadPart = chunk.dwSize;
344 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
345 break;
346 }
347 case mmioFOURCC('I','C','M','T'): {
348 TRACE_(dmfile)(": comment chunk (ignored)\n");
349 if (even_or_odd(chunk.dwSize)) {
350 ListCount[0]++;
351 chunk.dwSize++;
352 }
353 liMove.QuadPart = chunk.dwSize;
354 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
355 break;
356 }
357 default: {
358 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
359 if (even_or_odd(chunk.dwSize)) {
360 ListCount[0]++;
361 chunk.dwSize++;
362 }
363 liMove.QuadPart = chunk.dwSize;
364 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
365 break;
366 }
367 }
368 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
369 } while (ListCount[0] < ListSize[0]);
370 break;
371 }
372 case FOURCC_WVPL: {
373 TRACE_(dmfile)(": wave pool list (mark & skip)\n");
374 liMove.QuadPart = 0;
375 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, &dlibWavePoolPosition); /* store position */
376 This->liWavePoolTablePosition.QuadPart = dlibWavePoolPosition.QuadPart;
377 liMove.QuadPart = chunk.dwSize - sizeof(FOURCC);
378 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
379 break;
380 }
381 case FOURCC_LINS: {
382 TRACE_(dmfile)(": instruments list\n");
383 do {
384 IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL);
385 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize;
386 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize);
387 switch (chunk.fccID) {
388 case FOURCC_LIST: {
389 IStream_Read(stream, &chunk.fccID, sizeof(FOURCC), NULL);
390 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunk.fccID));
391 ListSize[1] = chunk.dwSize - sizeof(FOURCC);
392 ListCount[1] = 0;
393 switch (chunk.fccID) {
394 case FOURCC_INS: {
395 LPDMUS_PRIVATE_INSTRUMENTENTRY new_instrument = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_INSTRUMENTENTRY));
396 TRACE_(dmfile)(": instrument list\n");
397 /* Only way to create this one... even M$ does it discretely */
398 DMUSIC_CreateDirectMusicInstrumentImpl(&IID_IDirectMusicInstrument, (void**)&new_instrument->pInstrument, NULL);
399 {
400 IDirectMusicInstrumentImpl *instrument = impl_from_IDirectMusicInstrument(new_instrument->pInstrument);
401 /* Store offset and length, they will be needed when loading the instrument */
402 liMove.QuadPart = 0;
403 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, &dlibInstrumentPosition);
404 instrument->liInstrumentPosition.QuadPart = dlibInstrumentPosition.QuadPart;
405 instrument->length = ListSize[1];
406 do {
407 IStream_Read(stream, &chunk, sizeof(FOURCC) + sizeof(DWORD), NULL);
408 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + chunk.dwSize;
409 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc(chunk.fccID), chunk.dwSize);
410 switch (chunk.fccID) {
411 case FOURCC_INSH: {
412 TRACE_(dmfile)(": instrument header chunk\n");
413 IStream_Read(stream, &instrument->header, chunk.dwSize, NULL);
414 break;
415 }
416 case FOURCC_DLID: {
417 TRACE_(dmfile)(": DLID (GUID) chunk\n");
418 IStream_Read(stream, &instrument->id, chunk.dwSize, NULL);
419 break;
420 }
421 case FOURCC_LIST: {
422 IStream_Read(stream, &chunk.fccID, sizeof(FOURCC), NULL);
423 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunk.fccID));
424 switch (chunk.fccID) {
425 default: {
426 TRACE_(dmfile)(": unknown (skipping)\n");
427 liMove.QuadPart = chunk.dwSize - sizeof(FOURCC);
428 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
429 break;
430 }
431 }
432 break;
433 }
434 default: {
435 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
436 liMove.QuadPart = chunk.dwSize;
437 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
438 break;
439 }
440 }
441 TRACE_(dmfile)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount[1], ListSize[1]);
442 } while (ListCount[1] < ListSize[1]);
443 /* DEBUG: dumps whole instrument object tree: */
444 if (TRACE_ON(dmusic)) {
445 TRACE("*** IDirectMusicInstrument (%p) ***\n", instrument);
446 if (!IsEqualGUID(&instrument->id, &GUID_NULL))
447 TRACE(" - GUID = %s\n", debugstr_dmguid(&instrument->id));
448 TRACE(" - Instrument header:\n");
449 TRACE(" - cRegions: %d\n", instrument->header.cRegions);
450 TRACE(" - Locale:\n");
451 TRACE(" - ulBank: %d\n", instrument->header.Locale.ulBank);
452 TRACE(" - ulInstrument: %d\n", instrument->header.Locale.ulInstrument);
453 TRACE(" => dwPatch: %d\n", MIDILOCALE2Patch(&instrument->header.Locale));
454 }
455 list_add_tail(&This->Instruments, &new_instrument->entry);
456 }
457 break;
458 }
459 }
460 break;
461 }
462 default: {
463 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
464 liMove.QuadPart = chunk.dwSize;
465 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
466 break;
467 }
468 }
469 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
470 } while (ListCount[0] < ListSize[0]);
471 break;
472 }
473 default: {
474 TRACE_(dmfile)(": unknown (skipping)\n");
475 liMove.QuadPart = chunk.dwSize - sizeof(FOURCC);
476 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
477 break;
478 }
479 }
480 break;
481 }
482 default: {
483 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
484 liMove.QuadPart = chunk.dwSize;
485 IStream_Seek(stream, liMove, STREAM_SEEK_CUR, NULL);
486 break;
487 }
488 }
489 TRACE_(dmfile)(": StreamCount = %d < StreamSize = %d\n", StreamCount, StreamSize);
490 } while (StreamCount < StreamSize);
491
492 TRACE_(dmfile)(": reading finished\n");
493
494
495 /* DEBUG: dumps whole collection object tree: */
496 if (TRACE_ON(dmusic)) {
497 int r = 0;
498 DMUS_PRIVATE_INSTRUMENTENTRY *tmpEntry;
499 struct list *listEntry;
500
501 TRACE("*** IDirectMusicCollection (%p) ***\n", &This->IDirectMusicCollection_iface);
502 dump_DMUS_OBJECTDESC(&This->dmobj.desc);
503
504 TRACE(" - Collection header:\n");
505 TRACE(" - cInstruments: %d\n", This->pHeader->cInstruments);
506 TRACE(" - Instruments:\n");
507
508 LIST_FOR_EACH(listEntry, &This->Instruments) {
509 tmpEntry = LIST_ENTRY( listEntry, DMUS_PRIVATE_INSTRUMENTENTRY, entry );
510 TRACE(" - Instrument[%i]: %p\n", r, tmpEntry->pInstrument);
511 r++;
512 }
513 }
514
515 return S_OK;
516 }
517
518 static const IPersistStreamVtbl persiststream_vtbl = {
519 dmobj_IPersistStream_QueryInterface,
520 dmobj_IPersistStream_AddRef,
521 dmobj_IPersistStream_Release,
522 unimpl_IPersistStream_GetClassID,
523 unimpl_IPersistStream_IsDirty,
524 IPersistStreamImpl_Load,
525 unimpl_IPersistStream_Save,
526 unimpl_IPersistStream_GetSizeMax
527 };
528
529
DMUSIC_CreateDirectMusicCollectionImpl(LPCGUID lpcGUID,LPVOID * ppobj,LPUNKNOWN pUnkOuter)530 HRESULT WINAPI DMUSIC_CreateDirectMusicCollectionImpl(LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter)
531 {
532 IDirectMusicCollectionImpl* obj;
533 HRESULT hr;
534
535 *ppobj = NULL;
536 if (pUnkOuter)
537 return CLASS_E_NOAGGREGATION;
538
539 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicCollectionImpl));
540 if (!obj)
541 return E_OUTOFMEMORY;
542
543 obj->IDirectMusicCollection_iface.lpVtbl = &DirectMusicCollection_Collection_Vtbl;
544 obj->ref = 1;
545 dmobject_init(&obj->dmobj, &CLSID_DirectMusicCollection,
546 (IUnknown*)&obj->IDirectMusicCollection_iface);
547 obj->dmobj.IDirectMusicObject_iface.lpVtbl = &dmobject_vtbl;
548 obj->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
549
550 list_init (&obj->Instruments);
551
552 DMUSIC_LockModule();
553 hr = IDirectMusicCollection_QueryInterface(&obj->IDirectMusicCollection_iface, lpcGUID, ppobj);
554 IDirectMusicCollection_Release(&obj->IDirectMusicCollection_iface);
555
556 return hr;
557 }
558