1 /* IDirectMusicStyle8 Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
4 * Copyright (C) 2003-2004 Raphael Junqueira
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 "dmstyle_private.h"
23 #include "wine/heap.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(dmstyle
);
26 WINE_DECLARE_DEBUG_CHANNEL(dmfile
);
30 IDirectMusicBand
*pBand
;
33 struct style_partref_item
{
36 DMUS_IO_PARTREF part_ref
;
42 DMUS_IO_PATTERN pattern
;
44 /** optional for motifs */
45 DMUS_IO_MOTIFSETTINGS settings
;
46 IDirectMusicBand
*pBand
;
50 /*****************************************************************************
51 * IDirectMusicStyleImpl implementation
53 typedef struct IDirectMusicStyle8Impl
{
54 IDirectMusicStyle8 IDirectMusicStyle8_iface
;
55 struct dmobject dmobj
;
60 } IDirectMusicStyle8Impl
;
62 static inline IDirectMusicStyle8Impl
*impl_from_IDirectMusicStyle8(IDirectMusicStyle8
*iface
)
64 return CONTAINING_RECORD(iface
, IDirectMusicStyle8Impl
, IDirectMusicStyle8_iface
);
67 /* DirectMusicStyle8Impl IDirectMusicStyle8 part: */
68 static HRESULT WINAPI
IDirectMusicStyle8Impl_QueryInterface(IDirectMusicStyle8
*iface
, REFIID riid
,
71 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
73 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ret_iface
);
77 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDirectMusicStyle
) ||
78 IsEqualIID(riid
, &IID_IDirectMusicStyle8
))
80 else if (IsEqualIID(riid
, &IID_IDirectMusicObject
))
81 *ret_iface
= &This
->dmobj
.IDirectMusicObject_iface
;
82 else if (IsEqualIID(riid
, &IID_IPersistStream
))
83 *ret_iface
= &This
->dmobj
.IPersistStream_iface
;
85 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ret_iface
);
89 IUnknown_AddRef((IUnknown
*)*ret_iface
);
93 static ULONG WINAPI
IDirectMusicStyle8Impl_AddRef(IDirectMusicStyle8
*iface
)
95 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
96 LONG ref
= InterlockedIncrement(&This
->ref
);
98 TRACE("(%p) ref=%d\n", This
, ref
);
103 static ULONG WINAPI
IDirectMusicStyle8Impl_Release(IDirectMusicStyle8
*iface
)
105 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
106 LONG ref
= InterlockedDecrement(&This
->ref
);
108 TRACE("(%p) ref=%d\n", This
, ref
);
111 struct style_band
*band
, *band2
;
112 struct style_motif
*motif
, *motif2
;
113 struct style_partref_item
*item
, *item2
;
115 LIST_FOR_EACH_ENTRY_SAFE(band
, band2
, &This
->bands
, struct style_band
, entry
) {
116 list_remove(&band
->entry
);
118 IDirectMusicBand_Release(band
->pBand
);
121 LIST_FOR_EACH_ENTRY_SAFE(motif
, motif2
, &This
->motifs
, struct style_motif
, entry
) {
122 list_remove(&motif
->entry
);
123 LIST_FOR_EACH_ENTRY_SAFE(item
, item2
, &motif
->Items
, struct style_partref_item
, entry
) {
124 list_remove(&item
->entry
);
130 DMSTYLE_UnlockModule();
136 /* IDirectMusicStyle8Impl IDirectMusicStyle(8) part: */
137 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetBand(IDirectMusicStyle8
*iface
, WCHAR
*pwszName
,
138 IDirectMusicBand
**ppBand
)
140 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
141 FIXME("(%p, %p, %p): stub\n", This
, pwszName
, ppBand
);
145 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumBand(IDirectMusicStyle8
*iface
, DWORD dwIndex
,
148 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
149 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
153 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetDefaultBand(IDirectMusicStyle8
*iface
,
154 IDirectMusicBand
**band
)
156 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
157 FIXME("(%p, %p): stub\n", This
, band
);
167 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumMotif(IDirectMusicStyle8
*iface
, DWORD index
,
170 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
171 const struct style_motif
*motif
= NULL
;
172 const struct list
*cursor
;
175 TRACE("(%p, %u, %p)\n", This
, index
, name
);
180 /* index is zero based */
181 LIST_FOR_EACH(cursor
, &This
->motifs
) {
183 motif
= LIST_ENTRY(cursor
, struct style_motif
, entry
);
191 if (motif
->desc
.dwValidData
& DMUS_OBJ_NAME
)
192 lstrcpynW(name
, motif
->desc
.wszName
, DMUS_MAX_NAME
);
196 TRACE("returning name: %s\n", debugstr_w(name
));
200 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetMotif(IDirectMusicStyle8
*iface
, WCHAR
*pwszName
,
201 IDirectMusicSegment
**ppSegment
)
203 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
204 FIXME("(%p, %p, %p): stub\n", This
, pwszName
, ppSegment
);
208 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetDefaultChordMap(IDirectMusicStyle8
*iface
,
209 IDirectMusicChordMap
**ppChordMap
)
211 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
212 FIXME("(%p, %p): stub\n", This
, ppChordMap
);
216 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumChordMap(IDirectMusicStyle8
*iface
, DWORD dwIndex
,
219 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
220 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
224 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetChordMap(IDirectMusicStyle8
*iface
, WCHAR
*pwszName
,
225 IDirectMusicChordMap
**ppChordMap
)
227 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
228 FIXME("(%p, %p, %p): stub\n", This
, pwszName
, ppChordMap
);
232 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetTimeSignature(IDirectMusicStyle8
*iface
,
233 DMUS_TIMESIGNATURE
*pTimeSig
)
235 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
236 FIXME("(%p, %p): stub\n", This
, pTimeSig
);
240 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetEmbellishmentLength(IDirectMusicStyle8
*iface
,
241 DWORD dwType
, DWORD dwLevel
, DWORD
*pdwMin
, DWORD
*pdwMax
)
243 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
244 FIXME("(%p, %d, %d, %p, %p): stub\n", This
, dwType
, dwLevel
, pdwMin
, pdwMax
);
248 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetTempo(IDirectMusicStyle8
*iface
, double *pTempo
)
250 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
251 FIXME("(%p, %p): stub\n", This
, pTempo
);
255 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumPattern(IDirectMusicStyle8
*iface
, DWORD dwIndex
,
256 DWORD dwPatternType
, WCHAR
*pwszName
)
258 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
259 FIXME("(%p, %d, %d, %p): stub\n", This
, dwIndex
, dwPatternType
, pwszName
);
263 static const IDirectMusicStyle8Vtbl dmstyle8_vtbl
= {
264 IDirectMusicStyle8Impl_QueryInterface
,
265 IDirectMusicStyle8Impl_AddRef
,
266 IDirectMusicStyle8Impl_Release
,
267 IDirectMusicStyle8Impl_GetBand
,
268 IDirectMusicStyle8Impl_EnumBand
,
269 IDirectMusicStyle8Impl_GetDefaultBand
,
270 IDirectMusicStyle8Impl_EnumMotif
,
271 IDirectMusicStyle8Impl_GetMotif
,
272 IDirectMusicStyle8Impl_GetDefaultChordMap
,
273 IDirectMusicStyle8Impl_EnumChordMap
,
274 IDirectMusicStyle8Impl_GetChordMap
,
275 IDirectMusicStyle8Impl_GetTimeSignature
,
276 IDirectMusicStyle8Impl_GetEmbellishmentLength
,
277 IDirectMusicStyle8Impl_GetTempo
,
278 IDirectMusicStyle8Impl_EnumPattern
281 /* IDirectMusicStyle8Impl IDirectMusicObject part: */
282 static HRESULT WINAPI
style_IDirectMusicObject_ParseDescriptor(IDirectMusicObject
*iface
,
283 IStream
*stream
, DMUS_OBJECTDESC
*desc
)
285 struct chunk_entry riff
= {0};
288 TRACE("(%p, %p, %p)\n", iface
, stream
, desc
);
290 if (!stream
|| !desc
)
293 if ((hr
= stream_get_chunk(stream
, &riff
)) != S_OK
)
295 if (riff
.id
!= FOURCC_RIFF
|| riff
.type
!= DMUS_FOURCC_STYLE_FORM
) {
296 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff
));
297 stream_skip_chunk(stream
, &riff
);
298 return DMUS_E_CHUNKNOTFOUND
;
301 hr
= dmobj_parsedescriptor(stream
, &riff
, desc
,
302 DMUS_OBJ_OBJECT
|DMUS_OBJ_NAME
|DMUS_OBJ_NAME_INAM
|DMUS_OBJ_VERSION
);
306 desc
->guidClass
= CLSID_DirectMusicStyle
;
307 desc
->dwValidData
|= DMUS_OBJ_CLASS
;
309 dump_DMUS_OBJECTDESC(desc
);
313 static const IDirectMusicObjectVtbl dmobject_vtbl
= {
314 dmobj_IDirectMusicObject_QueryInterface
,
315 dmobj_IDirectMusicObject_AddRef
,
316 dmobj_IDirectMusicObject_Release
,
317 dmobj_IDirectMusicObject_GetDescriptor
,
318 dmobj_IDirectMusicObject_SetDescriptor
,
319 style_IDirectMusicObject_ParseDescriptor
322 /* IDirectMusicStyle8Impl IPersistStream part: */
323 static inline IDirectMusicStyle8Impl
*impl_from_IPersistStream(IPersistStream
*iface
)
325 return CONTAINING_RECORD(iface
, IDirectMusicStyle8Impl
, dmobj
.IPersistStream_iface
);
328 static HRESULT
load_band(IStream
*pClonedStream
, IDirectMusicBand
**ppBand
)
331 IPersistStream
* pPersistStream
= NULL
;
333 hr
= CoCreateInstance (&CLSID_DirectMusicBand
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicBand
, (LPVOID
*) ppBand
);
335 ERR(": could not create object\n");
338 /* acquire PersistStream interface */
339 hr
= IDirectMusicBand_QueryInterface (*ppBand
, &IID_IPersistStream
, (LPVOID
*) &pPersistStream
);
341 ERR(": could not acquire IPersistStream\n");
345 hr
= IPersistStream_Load (pPersistStream
, pClonedStream
);
347 ERR(": failed to load object\n");
351 /* release all loading-related stuff */
352 IPersistStream_Release (pPersistStream
);
357 static HRESULT
parse_part_ref_list(DMUS_PRIVATE_CHUNK
*pChunk
, IStream
*pStm
,
358 struct style_motif
*pNewMotif
)
361 DMUS_PRIVATE_CHUNK Chunk
;
362 DWORD ListSize
[3], ListCount
[3];
363 LARGE_INTEGER liMove
; /* used when skipping chunks */
364 struct style_partref_item
*pNewItem
= NULL
;
367 if (pChunk
->fccID
!= DMUS_FOURCC_PARTREF_LIST
) {
368 ERR_(dmfile
)(": %s chunk should be a PARTREF list\n", debugstr_fourcc (pChunk
->fccID
));
372 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
376 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
377 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
378 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
379 switch (Chunk
.fccID
) {
380 case DMUS_FOURCC_PARTREF_CHUNK
: {
381 TRACE_(dmfile
)(": PartRef chunk\n");
382 pNewItem
= heap_alloc_zero(sizeof(*pNewItem
));
384 ERR(": no more memory\n");
385 return E_OUTOFMEMORY
;
387 hr
= IStream_Read (pStm
, &pNewItem
->part_ref
, sizeof(DMUS_IO_PARTREF
), NULL
);
388 /*TRACE_(dmfile)(" - sizeof %lu\n", sizeof(DMUS_IO_PARTREF));*/
389 list_add_tail (&pNewMotif
->Items
, &pNewItem
->entry
);
390 pNewItem
->desc
.dwSize
= sizeof(pNewItem
->desc
);
394 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
395 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
396 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
398 switch (Chunk
.fccID
) {
399 case DMUS_FOURCC_UNFO_LIST
: {
400 TRACE_(dmfile
)(": UNFO list\n");
402 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
403 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
404 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
407 ERR(": pNewItem not yet allocated, chunk order bad?\n");
408 return E_OUTOFMEMORY
;
410 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &pNewItem
->desc
);
411 if (FAILED(hr
)) return hr
;
414 switch (Chunk
.fccID
) {
416 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
417 liMove
.QuadPart
= Chunk
.dwSize
;
418 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
423 TRACE_(dmfile
)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount
[1], ListSize
[1]);
424 } while (ListCount
[1] < ListSize
[1]);
428 TRACE_(dmfile
)(": unknown chunk (skipping)\n");
429 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
430 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
437 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
438 liMove
.QuadPart
= Chunk
.dwSize
;
439 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
443 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
444 } while (ListCount
[0] < ListSize
[0]);
449 static HRESULT
parse_part_list(DMUS_PRIVATE_CHUNK
*pChunk
, IStream
*pStm
)
452 DMUS_PRIVATE_CHUNK Chunk
;
453 DWORD ListSize
[3], ListCount
[3];
454 LARGE_INTEGER liMove
; /* used when skipping chunks */
456 DMUS_OBJECTDESC desc
;
460 if (pChunk
->fccID
!= DMUS_FOURCC_PART_LIST
) {
461 ERR_(dmfile
)(": %s chunk should be a PART list\n", debugstr_fourcc (pChunk
->fccID
));
465 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
469 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
470 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
471 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
472 switch (Chunk
.fccID
) {
473 case DMUS_FOURCC_PART_CHUNK
: {
474 TRACE_(dmfile
)(": Part chunk (skipping for now)\n" );
475 liMove
.QuadPart
= Chunk
.dwSize
;
476 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
479 case DMUS_FOURCC_NOTE_CHUNK
: {
480 TRACE_(dmfile
)(": Note chunk (skipping for now)\n");
481 IStream_Read (pStm
, &dwSize
, sizeof(DWORD
), NULL
);
482 cnt
= (Chunk
.dwSize
- sizeof(DWORD
));
483 TRACE_(dmfile
)(" - dwSize: %u\n", dwSize
);
484 TRACE_(dmfile
)(" - cnt: %u (%u / %u)\n", cnt
/ dwSize
, (DWORD
)(Chunk
.dwSize
- sizeof(DWORD
)), dwSize
);
485 if (cnt
% dwSize
!= 0) {
486 ERR("Invalid Array Size\n");
491 liMove
.QuadPart
= cnt
* dwSize
;
492 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
495 case DMUS_FOURCC_CURVE_CHUNK
: {
496 TRACE_(dmfile
)(": Curve chunk (skipping for now)\n");
497 IStream_Read (pStm
, &dwSize
, sizeof(DWORD
), NULL
);
498 cnt
= (Chunk
.dwSize
- sizeof(DWORD
));
499 TRACE_(dmfile
)(" - dwSize: %u\n", dwSize
);
500 TRACE_(dmfile
)(" - cnt: %u (%u / %u)\n", cnt
/ dwSize
, (DWORD
)(Chunk
.dwSize
- sizeof(DWORD
)), dwSize
);
501 if (cnt
% dwSize
!= 0) {
502 ERR("Invalid Array Size\n");
507 liMove
.QuadPart
= cnt
* dwSize
;
508 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
511 case DMUS_FOURCC_MARKER_CHUNK
: {
512 TRACE_(dmfile
)(": Marker chunk (skipping for now)\n");
513 liMove
.QuadPart
= Chunk
.dwSize
;
514 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
517 case DMUS_FOURCC_RESOLUTION_CHUNK
: {
518 TRACE_(dmfile
)(": Resolution chunk (skipping for now)\n");
519 liMove
.QuadPart
= Chunk
.dwSize
;
520 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
523 case DMUS_FOURCC_ANTICIPATION_CHUNK
: {
524 TRACE_(dmfile
)(": Anticipation chunk (skipping for now)\n");
525 liMove
.QuadPart
= Chunk
.dwSize
;
526 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
530 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
531 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
532 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
534 switch (Chunk
.fccID
) {
535 case DMUS_FOURCC_UNFO_LIST
: {
536 TRACE_(dmfile
)(": UNFO list\n");
538 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
539 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
540 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
542 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &desc
);
543 if (FAILED(hr
)) return hr
;
546 switch (Chunk
.fccID
) {
548 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
549 liMove
.QuadPart
= Chunk
.dwSize
;
550 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
555 TRACE_(dmfile
)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount
[1], ListSize
[1]);
556 } while (ListCount
[1] < ListSize
[1]);
560 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
561 liMove
.QuadPart
= Chunk
.dwSize
;
562 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
569 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
570 liMove
.QuadPart
= Chunk
.dwSize
;
571 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
575 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
576 } while (ListCount
[0] < ListSize
[0]);
581 static HRESULT
parse_pattern_list(IDirectMusicStyle8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
585 DMUS_PRIVATE_CHUNK Chunk
;
586 DWORD ListSize
[3], ListCount
[3];
587 LARGE_INTEGER liMove
; /* used when skipping chunks */
588 IDirectMusicBand
* pBand
= NULL
;
589 struct style_motif
*pNewMotif
= NULL
;
591 if (pChunk
->fccID
!= DMUS_FOURCC_PATTERN_LIST
) {
592 ERR_(dmfile
)(": %s chunk should be a PATTERN list\n", debugstr_fourcc (pChunk
->fccID
));
596 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
600 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
601 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
602 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
603 switch (Chunk
.fccID
) {
604 case DMUS_FOURCC_PATTERN_CHUNK
: {
605 TRACE_(dmfile
)(": Pattern chunk\n");
606 /** alloc new motif entry */
607 pNewMotif
= heap_alloc_zero(sizeof(*pNewMotif
));
608 if (NULL
== pNewMotif
) {
609 ERR(": no more memory\n");
610 return E_OUTOFMEMORY
;
612 list_add_tail(&This
->motifs
, &pNewMotif
->entry
);
614 IStream_Read (pStm
, &pNewMotif
->pattern
, Chunk
.dwSize
, NULL
);
615 /** TODO trace pattern */
617 /** reset all data, as a new pattern begin */
618 pNewMotif
->desc
.dwSize
= sizeof(pNewMotif
->desc
);
619 list_init (&pNewMotif
->Items
);
622 case DMUS_FOURCC_RHYTHM_CHUNK
: {
623 TRACE_(dmfile
)(": Rhythm chunk\n");
624 IStream_Read (pStm
, &pNewMotif
->dwRhythm
, sizeof(DWORD
), NULL
);
625 TRACE_(dmfile
)(" - dwRhythm: %u\n", pNewMotif
->dwRhythm
);
626 /** TODO understand why some Chunks have size > 4 */
627 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(DWORD
);
628 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
631 case DMUS_FOURCC_MOTIFSETTINGS_CHUNK
: {
632 TRACE_(dmfile
)(": MotifSettings chunk (skipping for now)\n");
633 IStream_Read (pStm
, &pNewMotif
->settings
, Chunk
.dwSize
, NULL
);
634 /** TODO trace settings */
639 * should be embedded Bands into pattern
641 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
642 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
643 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
645 switch (Chunk
.fccID
) {
646 case DMUS_FOURCC_BAND_FORM
: {
647 LPSTREAM pClonedStream
= NULL
;
649 TRACE_(dmfile
)(": BAND RIFF\n");
651 IStream_Clone (pStm
, &pClonedStream
);
654 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
655 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
657 hr
= load_band(pClonedStream
, &pBand
);
659 ERR(": could not load track\n");
662 IStream_Release (pClonedStream
);
664 pNewMotif
->pBand
= pBand
;
665 IDirectMusicBand_AddRef(pBand
);
667 IDirectMusicTrack_Release(pBand
); pBand
= NULL
; /* now we can release it as it's inserted */
669 /** now safe move the cursor */
670 liMove
.QuadPart
= ListSize
[1];
671 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
676 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
677 liMove
.QuadPart
= ListSize
[1];
678 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
685 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
686 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
687 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
689 switch (Chunk
.fccID
) {
690 case DMUS_FOURCC_UNFO_LIST
: {
691 TRACE_(dmfile
)(": UNFO list\n");
693 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
694 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
695 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
697 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &pNewMotif
->desc
);
698 if (FAILED(hr
)) return hr
;
701 switch (Chunk
.fccID
) {
703 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
704 liMove
.QuadPart
= Chunk
.dwSize
;
705 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
710 TRACE_(dmfile
)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount
[1], ListSize
[1]);
711 } while (ListCount
[1] < ListSize
[1]);
714 case DMUS_FOURCC_PARTREF_LIST
: {
715 TRACE_(dmfile
)(": PartRef list\n");
716 hr
= parse_part_ref_list(&Chunk
, pStm
, pNewMotif
);
717 if (FAILED(hr
)) return hr
;
721 TRACE_(dmfile
)(": unknown (skipping)\n");
722 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
723 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
730 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
731 liMove
.QuadPart
= Chunk
.dwSize
;
732 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
736 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
737 } while (ListCount
[0] < ListSize
[0]);
742 static HRESULT
parse_style_form(IDirectMusicStyle8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
746 DMUS_PRIVATE_CHUNK Chunk
;
747 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
748 LARGE_INTEGER liMove
; /* used when skipping chunks */
750 IDirectMusicBand
* pBand
= NULL
;
752 if (pChunk
->fccID
!= DMUS_FOURCC_STYLE_FORM
) {
753 ERR_(dmfile
)(": %s chunk should be a STYLE form\n", debugstr_fourcc (pChunk
->fccID
));
757 StreamSize
= pChunk
->dwSize
- sizeof(FOURCC
);
761 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
762 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
763 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
765 hr
= IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
766 if (FAILED(hr
)) return hr
;
769 switch (Chunk
.fccID
) {
770 case DMUS_FOURCC_STYLE_CHUNK
: {
771 TRACE_(dmfile
)(": Style chunk\n");
772 IStream_Read (pStm
, &This
->style
, sizeof(DMUS_IO_STYLE
), NULL
);
773 /** TODO dump DMUS_IO_TIMESIG style.timeSig */
774 TRACE_(dmfile
)(" - dblTempo: %g\n", This
->style
.dblTempo
);
779 * should be embedded Bands into style
781 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
782 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
783 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
785 switch (Chunk
.fccID
) {
786 case DMUS_FOURCC_BAND_FORM
: {
788 struct style_band
*pNewBand
;
790 TRACE_(dmfile
)(": BAND RIFF\n");
792 /* Can be application provided IStream without Clone method */
794 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
795 IStream_Seek(pStm
, liMove
, STREAM_SEEK_CUR
, &save
);
797 hr
= load_band(pStm
, &pBand
);
799 ERR(": could not load track\n");
803 pNewBand
= heap_alloc_zero(sizeof(*pNewBand
));
804 if (NULL
== pNewBand
) {
805 ERR(": no more memory\n");
806 return E_OUTOFMEMORY
;
808 pNewBand
->pBand
= pBand
;
809 IDirectMusicBand_AddRef(pBand
);
810 list_add_tail(&This
->bands
, &pNewBand
->entry
);
812 IDirectMusicTrack_Release(pBand
); pBand
= NULL
; /* now we can release it as it's inserted */
814 /** now safely move the cursor */
815 liMove
.QuadPart
= save
.QuadPart
- liMove
.QuadPart
+ ListSize
[0];
816 IStream_Seek(pStm
, liMove
, STREAM_SEEK_SET
, NULL
);
821 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
822 liMove
.QuadPart
= ListSize
[0];
823 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
830 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
831 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
832 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
834 switch (Chunk
.fccID
) {
835 case DMUS_FOURCC_UNFO_LIST
: {
836 TRACE_(dmfile
)(": UNFO list\n");
838 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
839 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
840 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
842 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
843 if (FAILED(hr
)) return hr
;
846 switch (Chunk
.fccID
) {
848 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
849 liMove
.QuadPart
= Chunk
.dwSize
;
850 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
855 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
856 } while (ListCount
[0] < ListSize
[0]);
859 case DMUS_FOURCC_PART_LIST
: {
860 TRACE_(dmfile
)(": PART list\n");
861 hr
= parse_part_list(&Chunk
, pStm
);
862 if (FAILED(hr
)) return hr
;
865 case DMUS_FOURCC_PATTERN_LIST
: {
866 TRACE_(dmfile
)(": PATTERN list\n");
867 hr
= parse_pattern_list(This
, &Chunk
, pStm
);
868 if (FAILED(hr
)) return hr
;
872 TRACE_(dmfile
)(": unknown (skipping)\n");
873 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
874 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
881 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
882 liMove
.QuadPart
= Chunk
.dwSize
;
883 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
888 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
889 } while (StreamCount
< StreamSize
);
894 static HRESULT WINAPI
IPersistStreamImpl_Load(IPersistStream
*iface
, IStream
*pStm
)
896 IDirectMusicStyle8Impl
*This
= impl_from_IPersistStream(iface
);
897 DMUS_PRIVATE_CHUNK Chunk
;
898 LARGE_INTEGER liMove
; /* used when skipping chunks */
901 FIXME("(%p, %p): Loading\n", This
, pStm
);
903 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
904 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
905 switch (Chunk
.fccID
) {
907 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
908 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
909 switch (Chunk
.fccID
) {
910 case DMUS_FOURCC_STYLE_FORM
: {
911 TRACE_(dmfile
)(": Style form\n");
912 hr
= parse_style_form(This
, &Chunk
, pStm
);
913 if (FAILED(hr
)) return hr
;
917 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
918 liMove
.QuadPart
= Chunk
.dwSize
;
919 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
923 TRACE_(dmfile
)(": reading finished\n");
927 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
928 liMove
.QuadPart
= Chunk
.dwSize
;
929 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
937 static const IPersistStreamVtbl persiststream_vtbl
= {
938 dmobj_IPersistStream_QueryInterface
,
939 dmobj_IPersistStream_AddRef
,
940 dmobj_IPersistStream_Release
,
941 dmobj_IPersistStream_GetClassID
,
942 unimpl_IPersistStream_IsDirty
,
943 IPersistStreamImpl_Load
,
944 unimpl_IPersistStream_Save
,
945 unimpl_IPersistStream_GetSizeMax
948 /* for ClassFactory */
949 HRESULT WINAPI
create_dmstyle(REFIID lpcGUID
, void **ppobj
)
951 IDirectMusicStyle8Impl
* obj
;
954 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicStyle8Impl
));
957 return E_OUTOFMEMORY
;
959 obj
->IDirectMusicStyle8_iface
.lpVtbl
= &dmstyle8_vtbl
;
961 dmobject_init(&obj
->dmobj
, &CLSID_DirectMusicStyle
, (IUnknown
*)&obj
->IDirectMusicStyle8_iface
);
962 obj
->dmobj
.IDirectMusicObject_iface
.lpVtbl
= &dmobject_vtbl
;
963 obj
->dmobj
.IPersistStream_iface
.lpVtbl
= &persiststream_vtbl
;
964 list_init(&obj
->bands
);
965 list_init(&obj
->motifs
);
967 DMSTYLE_LockModule();
968 hr
= IDirectMusicStyle8_QueryInterface(&obj
->IDirectMusicStyle8_iface
, lpcGUID
, ppobj
);
969 IDirectMusicStyle8_Release(&obj
->IDirectMusicStyle8_iface
);