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"
22 #include "soundfont.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(dmusic
);
26 struct instrument_entry
31 IDirectMusicInstrument
*instrument
;
40 C_ASSERT(sizeof(struct pool
) == offsetof(struct pool
, cues
[0]));
45 IDirectMusicObject
*wave
;
51 IDirectMusicCollection IDirectMusicCollection_iface
;
52 struct dmobject dmobj
;
58 struct list instruments
;
62 void collection_internal_addref(struct collection
*collection
)
64 ULONG ref
= InterlockedIncrement( &collection
->internal_ref
);
65 TRACE( "collection %p, internal ref %lu.\n", collection
, ref
);
68 void collection_internal_release(struct collection
*collection
)
70 ULONG ref
= InterlockedDecrement( &collection
->internal_ref
);
71 TRACE( "collection %p, internal ref %lu.\n", collection
, ref
);
77 HRESULT
collection_get_wave(struct collection
*collection
, DWORD index
, IDirectMusicObject
**out
)
79 struct wave_entry
*wave_entry
;
82 if (index
>= collection
->pool
->table
.cCues
) return E_INVALIDARG
;
83 offset
= collection
->pool
->cues
[index
].ulOffset
;
85 LIST_FOR_EACH_ENTRY(wave_entry
, &collection
->waves
, struct wave_entry
, entry
)
87 if (offset
== wave_entry
->offset
)
89 *out
= wave_entry
->wave
;
90 IUnknown_AddRef(wave_entry
->wave
);
98 static inline struct collection
*impl_from_IDirectMusicCollection(IDirectMusicCollection
*iface
)
100 return CONTAINING_RECORD(iface
, struct collection
, IDirectMusicCollection_iface
);
103 static inline struct collection
*impl_from_IPersistStream(IPersistStream
*iface
)
105 return CONTAINING_RECORD(iface
, struct collection
, dmobj
.IPersistStream_iface
);
108 static HRESULT WINAPI
collection_QueryInterface(IDirectMusicCollection
*iface
,
109 REFIID riid
, void **ret_iface
)
111 struct collection
*This
= impl_from_IDirectMusicCollection(iface
);
113 TRACE("(%p, %s, %p)\n", iface
, debugstr_dmguid(riid
), ret_iface
);
117 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDirectMusicCollection
))
119 else if (IsEqualIID(riid
, &IID_IDirectMusicObject
))
120 *ret_iface
= &This
->dmobj
.IDirectMusicObject_iface
;
121 else if (IsEqualIID(riid
, &IID_IPersistStream
))
122 *ret_iface
= &This
->dmobj
.IPersistStream_iface
;
125 WARN("(%p, %s, %p): not found\n", iface
, debugstr_dmguid(riid
), ret_iface
);
126 return E_NOINTERFACE
;
129 IUnknown_AddRef((IUnknown
*)*ret_iface
);
133 static ULONG WINAPI
collection_AddRef(IDirectMusicCollection
*iface
)
135 struct collection
*This
= impl_from_IDirectMusicCollection(iface
);
136 ULONG ref
= InterlockedIncrement(&This
->ref
);
138 TRACE("(%p): new ref = %lu\n", iface
, ref
);
143 static ULONG WINAPI
collection_Release(IDirectMusicCollection
*iface
)
145 struct collection
*This
= impl_from_IDirectMusicCollection(iface
);
146 ULONG ref
= InterlockedDecrement(&This
->ref
);
148 TRACE("(%p): new ref = %lu\n", iface
, ref
);
152 struct instrument_entry
*instrument_entry
;
153 struct wave_entry
*wave_entry
;
156 LIST_FOR_EACH_ENTRY_SAFE(instrument_entry
, next
, &This
->instruments
, struct instrument_entry
, entry
)
158 list_remove(&instrument_entry
->entry
);
159 IDirectMusicInstrument_Release(instrument_entry
->instrument
);
160 free(instrument_entry
);
163 LIST_FOR_EACH_ENTRY_SAFE(wave_entry
, next
, &This
->waves
, struct wave_entry
, entry
)
165 list_remove(&wave_entry
->entry
);
166 IDirectMusicInstrument_Release(wave_entry
->wave
);
170 collection_internal_release(This
);
176 static HRESULT WINAPI
collection_GetInstrument(IDirectMusicCollection
*iface
,
177 DWORD patch
, IDirectMusicInstrument
**instrument
)
179 struct collection
*This
= impl_from_IDirectMusicCollection(iface
);
180 struct instrument_entry
*entry
;
182 TRACE("(%p, %lu, %p)\n", iface
, patch
, instrument
);
184 LIST_FOR_EACH_ENTRY(entry
, &This
->instruments
, struct instrument_entry
, entry
)
186 if (patch
== entry
->patch
)
188 *instrument
= entry
->instrument
;
189 IDirectMusicInstrument_AddRef(entry
->instrument
);
190 TRACE(": returning instrument %p\n", entry
->instrument
);
195 TRACE(": instrument not found\n");
196 return DMUS_E_INVALIDPATCH
;
199 static HRESULT WINAPI
collection_EnumInstrument(IDirectMusicCollection
*iface
,
200 DWORD index
, DWORD
*patch
, LPWSTR name
, DWORD name_length
)
202 struct collection
*This
= impl_from_IDirectMusicCollection(iface
);
203 struct instrument_entry
*entry
;
205 TRACE("(%p, %ld, %p, %p, %ld)\n", iface
, index
, patch
, name
, name_length
);
207 LIST_FOR_EACH_ENTRY(entry
, &This
->instruments
, struct instrument_entry
, entry
)
209 if (index
--) continue;
210 *patch
= entry
->patch
;
211 if (name
) lstrcpynW(name
, entry
->desc
.wszName
, name_length
);
218 static const IDirectMusicCollectionVtbl collection_vtbl
=
220 collection_QueryInterface
,
223 collection_GetInstrument
,
224 collection_EnumInstrument
,
227 static HRESULT
parse_lins_list(struct collection
*This
, IStream
*stream
, struct chunk_entry
*parent
)
229 struct chunk_entry chunk
= {.parent
= parent
};
230 struct instrument_entry
*entry
;
233 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
235 switch (MAKE_IDTYPE(chunk
.id
, chunk
.type
))
237 case MAKE_IDTYPE(FOURCC_LIST
, FOURCC_INS
):
238 if (!(entry
= malloc(sizeof(*entry
)))) return E_OUTOFMEMORY
;
239 hr
= instrument_create_from_chunk(stream
, &chunk
, This
, &entry
->desc
, &entry
->instrument
);
240 if (SUCCEEDED(hr
)) hr
= IDirectMusicInstrument_GetPatch(entry
->instrument
, &entry
->patch
);
241 if (SUCCEEDED(hr
)) list_add_tail(&This
->instruments
, &entry
->entry
);
246 FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk
.id
), debugstr_fourcc(chunk
.type
));
250 if (FAILED(hr
)) break;
256 static HRESULT
parse_wvpl_list(struct collection
*This
, IStream
*stream
, struct chunk_entry
*parent
)
258 struct chunk_entry chunk
= {.parent
= parent
};
259 struct wave_entry
*entry
;
262 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
264 switch (MAKE_IDTYPE(chunk
.id
, chunk
.type
))
266 case MAKE_IDTYPE(FOURCC_LIST
, FOURCC_wave
):
267 if (!(entry
= malloc(sizeof(*entry
)))) return E_OUTOFMEMORY
;
268 if (FAILED(hr
= wave_create_from_chunk(stream
, &chunk
, &entry
->wave
))) free(entry
);
271 entry
->offset
= chunk
.offset
.QuadPart
- parent
->offset
.QuadPart
- 12;
272 list_add_tail(&This
->waves
, &entry
->entry
);
277 FIXME("Skipping unknown chunk %s %s\n", debugstr_fourcc(chunk
.id
), debugstr_fourcc(chunk
.type
));
281 if (FAILED(hr
)) break;
287 static HRESULT
parse_ptbl_chunk(struct collection
*This
, IStream
*stream
, struct chunk_entry
*chunk
)
294 if (chunk
->size
< sizeof(table
)) return E_INVALIDARG
;
295 if (FAILED(hr
= stream_read(stream
, &table
, sizeof(table
)))) return hr
;
296 if (chunk
->size
!= table
.cbSize
+ sizeof(POOLCUE
) * table
.cCues
) return E_INVALIDARG
;
297 if (table
.cbSize
!= sizeof(table
)) return E_INVALIDARG
;
299 size
= offsetof(struct pool
, cues
[table
.cCues
]);
300 if (!(pool
= malloc(size
))) return E_OUTOFMEMORY
;
303 size
= sizeof(POOLCUE
) * table
.cCues
;
304 if (FAILED(hr
= stream_read(stream
, pool
->cues
, size
))) free(pool
);
305 else This
->pool
= pool
;
310 static HRESULT
parse_dls_chunk(struct collection
*This
, IStream
*stream
, struct chunk_entry
*parent
)
312 struct chunk_entry chunk
= {.parent
= parent
};
315 if (FAILED(hr
= dmobj_parsedescriptor(stream
, parent
, &This
->dmobj
.desc
,
316 DMUS_OBJ_NAME_INFO
|DMUS_OBJ_VERSION
|DMUS_OBJ_OBJECT
|DMUS_OBJ_GUID_DLID
))
317 || FAILED(hr
= stream_reset_chunk_data(stream
, parent
)))
320 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
322 switch (MAKE_IDTYPE(chunk
.id
, chunk
.type
))
326 case MAKE_IDTYPE(FOURCC_LIST
, DMUS_FOURCC_INFO_LIST
):
327 /* already parsed by dmobj_parsedescriptor */
331 hr
= stream_chunk_get_data(stream
, &chunk
, &This
->header
, sizeof(This
->header
));
335 hr
= parse_ptbl_chunk(This
, stream
, &chunk
);
338 case MAKE_IDTYPE(FOURCC_LIST
, FOURCC_LINS
):
339 hr
= parse_lins_list(This
, stream
, &chunk
);
342 case MAKE_IDTYPE(FOURCC_LIST
, FOURCC_WVPL
):
343 hr
= parse_wvpl_list(This
, stream
, &chunk
);
347 FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk
.id
), debugstr_fourcc(chunk
.type
));
351 if (FAILED(hr
)) break;
357 static HRESULT
parse_sdta_list(struct collection
*This
, IStream
*stream
, struct chunk_entry
*parent
,
358 struct soundfont
*soundfont
)
360 struct chunk_entry chunk
= {.parent
= parent
};
363 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
365 switch (MAKE_IDTYPE(chunk
.id
, chunk
.type
))
367 case mmioFOURCC('s','m','p','l'):
368 if (soundfont
->sdta
) return E_INVALIDARG
;
369 if (!(soundfont
->sdta
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
370 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->sdta
, chunk
.size
);
374 FIXME("Skipping unknown chunk %s %s\n", debugstr_fourcc(chunk
.id
), debugstr_fourcc(chunk
.type
));
378 if (FAILED(hr
)) break;
384 static HRESULT
parse_pdta_list(struct collection
*This
, IStream
*stream
, struct chunk_entry
*parent
,
385 struct soundfont
*soundfont
)
387 struct chunk_entry chunk
= {.parent
= parent
};
390 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
392 switch (MAKE_IDTYPE(chunk
.id
, chunk
.type
))
394 case mmioFOURCC('p','h','d','r'):
395 if (soundfont
->phdr
) return E_INVALIDARG
;
396 if (!(soundfont
->phdr
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
397 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->phdr
, chunk
.size
);
398 soundfont
->preset_count
= chunk
.size
/ sizeof(*soundfont
->phdr
) - 1;
401 case mmioFOURCC('p','b','a','g'):
402 if (soundfont
->pbag
) return E_INVALIDARG
;
403 if (!(soundfont
->pbag
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
404 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->pbag
, chunk
.size
);
407 case mmioFOURCC('p','m','o','d'):
408 if (soundfont
->pmod
) return E_INVALIDARG
;
409 if (!(soundfont
->pmod
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
410 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->pmod
, chunk
.size
);
413 case mmioFOURCC('p','g','e','n'):
414 if (soundfont
->pgen
) return E_INVALIDARG
;
415 if (!(soundfont
->pgen
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
416 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->pgen
, chunk
.size
);
419 case mmioFOURCC('i','n','s','t'):
420 if (soundfont
->inst
) return E_INVALIDARG
;
421 if (!(soundfont
->inst
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
422 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->inst
, chunk
.size
);
423 soundfont
->instrument_count
= chunk
.size
/ sizeof(*soundfont
->inst
) - 1;
426 case mmioFOURCC('i','b','a','g'):
427 if (soundfont
->ibag
) return E_INVALIDARG
;
428 if (!(soundfont
->ibag
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
429 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->ibag
, chunk
.size
);
432 case mmioFOURCC('i','m','o','d'):
433 if (soundfont
->imod
) return E_INVALIDARG
;
434 if (!(soundfont
->imod
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
435 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->imod
, chunk
.size
);
438 case mmioFOURCC('i','g','e','n'):
439 if (soundfont
->igen
) return E_INVALIDARG
;
440 if (!(soundfont
->igen
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
441 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->igen
, chunk
.size
);
444 case mmioFOURCC('s','h','d','r'):
445 if (soundfont
->shdr
) return E_INVALIDARG
;
446 if (!(soundfont
->shdr
= malloc(chunk
.size
))) return E_OUTOFMEMORY
;
447 hr
= stream_chunk_get_data(stream
, &chunk
, soundfont
->shdr
, chunk
.size
);
448 soundfont
->sample_count
= chunk
.size
/ sizeof(*soundfont
->shdr
) - 1;
452 FIXME("Skipping unknown chunk %s %s\n", debugstr_fourcc(chunk
.id
), debugstr_fourcc(chunk
.type
));
456 if (FAILED(hr
)) break;
462 static HRESULT
parse_sfbk_chunk(struct collection
*This
, IStream
*stream
, struct chunk_entry
*parent
)
464 struct chunk_entry chunk
= {.parent
= parent
};
465 struct soundfont soundfont
= {0};
469 if (FAILED(hr
= dmobj_parsedescriptor(stream
, parent
, &This
->dmobj
.desc
,
470 DMUS_OBJ_NAME_INFO
|DMUS_OBJ_VERSION
|DMUS_OBJ_OBJECT
|DMUS_OBJ_GUID_DLID
))
471 || FAILED(hr
= stream_reset_chunk_data(stream
, parent
)))
474 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
476 switch (MAKE_IDTYPE(chunk
.id
, chunk
.type
))
478 case MAKE_IDTYPE(FOURCC_LIST
, DMUS_FOURCC_INFO_LIST
):
479 /* already parsed by dmobj_parsedescriptor */
482 case MAKE_IDTYPE(FOURCC_LIST
, mmioFOURCC('s','d','t','a')):
483 hr
= parse_sdta_list(This
, stream
, &chunk
, &soundfont
);
486 case MAKE_IDTYPE(FOURCC_LIST
, mmioFOURCC('p','d','t','a')):
487 hr
= parse_pdta_list(This
, stream
, &chunk
, &soundfont
);
491 FIXME("Ignoring chunk %s %s\n", debugstr_fourcc(chunk
.id
), debugstr_fourcc(chunk
.type
));
495 if (FAILED(hr
)) break;
501 for (i
= 0; i
< soundfont
.preset_count
; i
++)
503 struct sf_preset
*preset
= soundfont
.phdr
+ i
;
505 TRACE("preset[%u]:\n", i
);
506 TRACE(" - name: %s\n", debugstr_a(preset
->name
));
507 TRACE(" - preset: %u\n", preset
->preset
);
508 TRACE(" - bank: %u\n", preset
->bank
);
509 TRACE(" - preset_bag_ndx: %u\n", preset
->bag_ndx
);
510 TRACE(" - library: %lu\n", preset
->library
);
511 TRACE(" - genre: %lu\n", preset
->genre
);
512 TRACE(" - morphology: %#lx\n", preset
->morphology
);
514 for (j
= preset
->bag_ndx
; j
< (preset
+ 1)->bag_ndx
; j
++)
516 struct sf_bag
*bag
= soundfont
.pbag
+ j
;
517 TRACE(" - bag[%u]:\n", j
);
518 TRACE(" - gen_ndx: %u\n", bag
->gen_ndx
);
519 TRACE(" - mod_ndx: %u\n", bag
->mod_ndx
);
521 for (k
= bag
->gen_ndx
; k
< (bag
+ 1)->gen_ndx
; k
++)
523 struct sf_gen
*gen
= soundfont
.pgen
+ k
;
524 TRACE(" - gen[%u]: %s\n", k
, debugstr_sf_gen(gen
));
527 for (k
= bag
->mod_ndx
; k
< (bag
+ 1)->mod_ndx
; k
++)
529 struct sf_mod
*mod
= soundfont
.pmod
+ k
;
530 TRACE(" - mod[%u]: %s\n", k
, debugstr_sf_mod(mod
));
535 TRACE("instruments:\n");
536 for (i
= 0; i
< soundfont
.instrument_count
; i
++)
538 struct sf_instrument
*instrument
= soundfont
.inst
+ i
;
539 TRACE("instrument[%u]:\n", i
);
540 TRACE(" - name: %s\n", debugstr_a(instrument
->name
));
541 TRACE(" - bag_ndx: %u\n", instrument
->bag_ndx
);
543 for (j
= instrument
->bag_ndx
; j
< (instrument
+ 1)->bag_ndx
; j
++)
545 struct sf_bag
*bag
= soundfont
.ibag
+ j
;
546 TRACE(" - bag[%u]:\n", j
);
547 TRACE(" - wGenNdx: %u\n", bag
->gen_ndx
);
548 TRACE(" - wModNdx: %u\n", bag
->mod_ndx
);
550 for (k
= bag
->gen_ndx
; k
< (bag
+ 1)->gen_ndx
; k
++)
552 struct sf_gen
*gen
= soundfont
.igen
+ k
;
553 TRACE(" - gen[%u]: %s\n", k
, debugstr_sf_gen(gen
));
556 for (k
= bag
->mod_ndx
; k
< (bag
+ 1)->mod_ndx
; k
++)
558 struct sf_mod
*mod
= soundfont
.imod
+ k
;
559 TRACE(" - mod[%u]: %s\n", k
, debugstr_sf_mod(mod
));
565 for (i
= 0; i
< soundfont
.sample_count
; i
++)
567 struct sf_sample
*sample
= soundfont
.shdr
+ i
;
569 TRACE("sample[%u]:\n", i
);
570 TRACE(" - name: %s\n", debugstr_a(sample
->name
));
571 TRACE(" - start: %lu\n", sample
->start
);
572 TRACE(" - end: %lu\n", sample
->end
);
573 TRACE(" - start_loop: %lu\n", sample
->start_loop
);
574 TRACE(" - end_loop: %lu\n", sample
->end_loop
);
575 TRACE(" - sample_rate: %lu\n", sample
->sample_rate
);
576 TRACE(" - original_key: %u\n", sample
->original_key
);
577 TRACE(" - correction: %d\n", sample
->correction
);
578 TRACE(" - sample_link: %#x\n", sample
->sample_link
);
579 TRACE(" - sample_type: %#x\n", sample
->sample_type
);
583 for (i
= 0; SUCCEEDED(hr
) && i
< soundfont
.preset_count
; i
++)
585 struct instrument_entry
*entry
;
587 if (!(entry
= malloc(sizeof(*entry
)))) return E_OUTOFMEMORY
;
588 hr
= instrument_create_from_soundfont(&soundfont
, i
, This
, &entry
->desc
, &entry
->instrument
);
589 if (SUCCEEDED(hr
)) hr
= IDirectMusicInstrument_GetPatch(entry
->instrument
, &entry
->patch
);
590 if (SUCCEEDED(hr
)) list_add_tail(&This
->instruments
, &entry
->entry
);
596 UINT size
= offsetof(struct pool
, cues
[soundfont
.sample_count
]);
597 if (!(This
->pool
= calloc(1, size
))) return E_OUTOFMEMORY
;
598 This
->pool
->table
.cbSize
= sizeof(This
->pool
->table
);
601 for (i
= 0; SUCCEEDED(hr
) && i
< soundfont
.sample_count
; i
++)
603 struct wave_entry
*entry
;
605 if (!(entry
= malloc(sizeof(*entry
)))) return E_OUTOFMEMORY
;
606 hr
= wave_create_from_soundfont(&soundfont
, i
, &entry
->wave
);
607 if (FAILED(hr
)) free(entry
);
611 This
->pool
->table
.cCues
++;
612 This
->pool
->cues
[i
].ulOffset
= i
;
613 list_add_tail(&This
->waves
, &entry
->entry
);
617 free(soundfont
.phdr
);
618 free(soundfont
.pbag
);
619 free(soundfont
.pmod
);
620 free(soundfont
.pgen
);
621 free(soundfont
.inst
);
622 free(soundfont
.ibag
);
623 free(soundfont
.imod
);
624 free(soundfont
.igen
);
625 free(soundfont
.shdr
);
626 free(soundfont
.sdta
);
631 static HRESULT WINAPI
collection_object_ParseDescriptor(IDirectMusicObject
*iface
,
632 IStream
*stream
, DMUS_OBJECTDESC
*desc
)
634 struct chunk_entry riff
= {0};
637 TRACE("(%p, %p, %p)\n", iface
, stream
, desc
);
639 if (!stream
|| !desc
)
642 if ((hr
= stream_get_chunk(stream
, &riff
)) != S_OK
)
644 if (riff
.id
!= FOURCC_RIFF
|| (riff
.type
!= FOURCC_DLS
&& riff
.type
!= mmioFOURCC('s','f','b','k'))) {
645 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff
));
646 stream_skip_chunk(stream
, &riff
);
647 return DMUS_E_NOTADLSCOL
;
650 hr
= dmobj_parsedescriptor(stream
, &riff
, desc
, DMUS_OBJ_NAME_INFO
|DMUS_OBJ_VERSION
);
654 desc
->guidClass
= CLSID_DirectMusicCollection
;
655 desc
->dwValidData
|= DMUS_OBJ_CLASS
;
657 TRACE("returning descriptor:\n");
658 dump_DMUS_OBJECTDESC(desc
);
662 static const IDirectMusicObjectVtbl collection_object_vtbl
=
664 dmobj_IDirectMusicObject_QueryInterface
,
665 dmobj_IDirectMusicObject_AddRef
,
666 dmobj_IDirectMusicObject_Release
,
667 dmobj_IDirectMusicObject_GetDescriptor
,
668 dmobj_IDirectMusicObject_SetDescriptor
,
669 collection_object_ParseDescriptor
,
672 static HRESULT WINAPI
collection_stream_Load(IPersistStream
*iface
, IStream
*stream
)
674 struct collection
*This
= impl_from_IPersistStream(iface
);
675 struct chunk_entry chunk
= {0};
678 TRACE("(%p, %p)\n", This
, stream
);
680 if ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
682 switch (MAKE_IDTYPE(chunk
.id
, chunk
.type
))
684 case MAKE_IDTYPE(FOURCC_RIFF
, FOURCC_DLS
):
685 hr
= parse_dls_chunk(This
, stream
, &chunk
);
688 case MAKE_IDTYPE(FOURCC_RIFF
, mmioFOURCC('s','f','b','k')):
689 hr
= parse_sfbk_chunk(This
, stream
, &chunk
);
693 WARN("Invalid collection chunk %s %s\n", debugstr_fourcc(chunk
.id
), debugstr_fourcc(chunk
.type
));
694 hr
= DMUS_E_UNSUPPORTED_STREAM
;
699 if (FAILED(hr
)) return hr
;
701 if (TRACE_ON(dmusic
))
703 struct instrument_entry
*entry
;
704 struct wave_entry
*wave_entry
;
707 TRACE("*** IDirectMusicCollection (%p) ***\n", &This
->IDirectMusicCollection_iface
);
708 dump_DMUS_OBJECTDESC(&This
->dmobj
.desc
);
710 TRACE(" - Collection header:\n");
711 TRACE(" - cInstruments: %ld\n", This
->header
.cInstruments
);
712 TRACE(" - Instruments:\n");
714 LIST_FOR_EACH_ENTRY(entry
, &This
->instruments
, struct instrument_entry
, entry
)
716 TRACE(" - Instrument[%i]: %p\n", i
, entry
->instrument
);
721 for (i
= 0; This
->pool
&& i
< This
->pool
->table
.cCues
; i
++)
722 TRACE(" - index: %u, offset: %lu\n", i
, This
->pool
->cues
[i
].ulOffset
);
724 TRACE(" - waves:\n");
725 LIST_FOR_EACH_ENTRY(wave_entry
, &This
->waves
, struct wave_entry
, entry
)
726 TRACE(" - offset: %lu, wave %p\n", wave_entry
->offset
, wave_entry
->wave
);
729 stream_skip_chunk(stream
, &chunk
);
733 static const IPersistStreamVtbl collection_stream_vtbl
=
735 dmobj_IPersistStream_QueryInterface
,
736 dmobj_IPersistStream_AddRef
,
737 dmobj_IPersistStream_Release
,
738 unimpl_IPersistStream_GetClassID
,
739 unimpl_IPersistStream_IsDirty
,
740 collection_stream_Load
,
741 unimpl_IPersistStream_Save
,
742 unimpl_IPersistStream_GetSizeMax
,
745 HRESULT
collection_create(IUnknown
**ret_iface
)
747 struct collection
*collection
;
750 if (!(collection
= calloc(1, sizeof(*collection
)))) return E_OUTOFMEMORY
;
751 collection
->IDirectMusicCollection_iface
.lpVtbl
= &collection_vtbl
;
752 collection
->internal_ref
= 1;
754 dmobject_init(&collection
->dmobj
, &CLSID_DirectMusicCollection
,
755 (IUnknown
*)&collection
->IDirectMusicCollection_iface
);
756 collection
->dmobj
.IDirectMusicObject_iface
.lpVtbl
= &collection_object_vtbl
;
757 collection
->dmobj
.IPersistStream_iface
.lpVtbl
= &collection_stream_vtbl
;
758 list_init(&collection
->instruments
);
759 list_init(&collection
->waves
);
761 TRACE("Created DirectMusicCollection %p\n", collection
);
762 *ret_iface
= (IUnknown
*)&collection
->IDirectMusicCollection_iface
;