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"
24 WINE_DEFAULT_DEBUG_CHANNEL(dmstyle
);
25 WINE_DECLARE_DEBUG_CHANNEL(dmfile
);
29 IDirectMusicBand
*pBand
;
32 struct style_partref_item
{
35 DMUS_IO_PARTREF part_ref
;
41 DMUS_IO_PATTERN pattern
;
43 /** optional for motifs */
44 DMUS_IO_MOTIFSETTINGS settings
;
45 IDirectMusicBand
*pBand
;
49 /*****************************************************************************
50 * IDirectMusicStyleImpl implementation
52 typedef struct IDirectMusicStyle8Impl
{
53 IDirectMusicStyle8 IDirectMusicStyle8_iface
;
54 struct dmobject dmobj
;
59 } IDirectMusicStyle8Impl
;
61 static inline IDirectMusicStyle8Impl
*impl_from_IDirectMusicStyle8(IDirectMusicStyle8
*iface
)
63 return CONTAINING_RECORD(iface
, IDirectMusicStyle8Impl
, IDirectMusicStyle8_iface
);
66 /* DirectMusicStyle8Impl IDirectMusicStyle8 part: */
67 static HRESULT WINAPI
IDirectMusicStyle8Impl_QueryInterface(IDirectMusicStyle8
*iface
, REFIID riid
,
70 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
72 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ret_iface
);
76 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDirectMusicStyle
) ||
77 IsEqualIID(riid
, &IID_IDirectMusicStyle8
))
79 else if (IsEqualIID(riid
, &IID_IDirectMusicObject
))
80 *ret_iface
= &This
->dmobj
.IDirectMusicObject_iface
;
81 else if (IsEqualIID(riid
, &IID_IPersistStream
))
82 *ret_iface
= &This
->dmobj
.IPersistStream_iface
;
84 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ret_iface
);
88 IUnknown_AddRef((IUnknown
*)*ret_iface
);
92 static ULONG WINAPI
IDirectMusicStyle8Impl_AddRef(IDirectMusicStyle8
*iface
)
94 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
95 LONG ref
= InterlockedIncrement(&This
->ref
);
97 TRACE("(%p) ref=%ld\n", This
, ref
);
102 static ULONG WINAPI
IDirectMusicStyle8Impl_Release(IDirectMusicStyle8
*iface
)
104 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
105 LONG ref
= InterlockedDecrement(&This
->ref
);
107 TRACE("(%p) ref=%ld\n", This
, ref
);
110 struct style_band
*band
, *band2
;
111 struct style_motif
*motif
, *motif2
;
112 struct style_partref_item
*item
, *item2
;
114 LIST_FOR_EACH_ENTRY_SAFE(band
, band2
, &This
->bands
, struct style_band
, entry
) {
115 list_remove(&band
->entry
);
117 IDirectMusicBand_Release(band
->pBand
);
120 LIST_FOR_EACH_ENTRY_SAFE(motif
, motif2
, &This
->motifs
, struct style_motif
, entry
) {
121 list_remove(&motif
->entry
);
122 LIST_FOR_EACH_ENTRY_SAFE(item
, item2
, &motif
->Items
, struct style_partref_item
, entry
) {
123 list_remove(&item
->entry
);
134 /* IDirectMusicStyle8Impl IDirectMusicStyle(8) part: */
135 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetBand(IDirectMusicStyle8
*iface
, WCHAR
*name
,
136 IDirectMusicBand
**band
)
138 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
139 struct style_band
*sband
;
142 TRACE("(%p, %s, %p)\n", This
, debugstr_w(name
), band
);
147 LIST_FOR_EACH_ENTRY(sband
, &This
->bands
, struct style_band
, entry
) {
148 IDirectMusicObject
*obj
;
150 hr
= IDirectMusicBand_QueryInterface(sband
->pBand
, &IID_IDirectMusicObject
, (void**)&obj
);
152 DMUS_OBJECTDESC desc
;
154 if (IDirectMusicObject_GetDescriptor(obj
, &desc
) == S_OK
) {
155 if (desc
.dwValidData
& DMUS_OBJ_NAME
&& !lstrcmpW(name
, desc
.wszName
)) {
156 IDirectMusicObject_Release(obj
);
157 IDirectMusicBand_AddRef(sband
->pBand
);
158 *band
= sband
->pBand
;
163 IDirectMusicObject_Release(obj
);
170 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumBand(IDirectMusicStyle8
*iface
, DWORD dwIndex
,
173 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
174 FIXME("(%p, %ld, %p): stub\n", This
, dwIndex
, pwszName
);
178 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetDefaultBand(IDirectMusicStyle8
*iface
,
179 IDirectMusicBand
**band
)
181 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
182 FIXME("(%p, %p): stub\n", This
, band
);
192 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumMotif(IDirectMusicStyle8
*iface
, DWORD index
,
195 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
196 const struct style_motif
*motif
= NULL
;
197 const struct list
*cursor
;
200 TRACE("(%p, %lu, %p)\n", This
, index
, name
);
205 /* index is zero based */
206 LIST_FOR_EACH(cursor
, &This
->motifs
) {
208 motif
= LIST_ENTRY(cursor
, struct style_motif
, entry
);
216 if (motif
->desc
.dwValidData
& DMUS_OBJ_NAME
)
217 lstrcpynW(name
, motif
->desc
.wszName
, DMUS_MAX_NAME
);
221 TRACE("returning name: %s\n", debugstr_w(name
));
225 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetMotif(IDirectMusicStyle8
*iface
, WCHAR
*pwszName
,
226 IDirectMusicSegment
**ppSegment
)
228 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
229 FIXME("(%p, %s, %p): stub\n", This
, debugstr_w(pwszName
), ppSegment
);
233 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetDefaultChordMap(IDirectMusicStyle8
*iface
,
234 IDirectMusicChordMap
**ppChordMap
)
236 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
237 FIXME("(%p, %p): stub\n", This
, ppChordMap
);
241 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumChordMap(IDirectMusicStyle8
*iface
, DWORD dwIndex
,
244 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
245 FIXME("(%p, %ld, %p): stub\n", This
, dwIndex
, pwszName
);
249 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetChordMap(IDirectMusicStyle8
*iface
, WCHAR
*pwszName
,
250 IDirectMusicChordMap
**ppChordMap
)
252 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
253 FIXME("(%p, %p, %p): stub\n", This
, pwszName
, ppChordMap
);
257 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetTimeSignature(IDirectMusicStyle8
*iface
,
258 DMUS_TIMESIGNATURE
*pTimeSig
)
260 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
261 FIXME("(%p, %p): stub\n", This
, pTimeSig
);
265 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetEmbellishmentLength(IDirectMusicStyle8
*iface
,
266 DWORD dwType
, DWORD dwLevel
, DWORD
*pdwMin
, DWORD
*pdwMax
)
268 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
269 FIXME("(%p, %ld, %ld, %p, %p): stub\n", This
, dwType
, dwLevel
, pdwMin
, pdwMax
);
273 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetTempo(IDirectMusicStyle8
*iface
, double *pTempo
)
275 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
276 FIXME("(%p, %p): stub\n", This
, pTempo
);
280 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumPattern(IDirectMusicStyle8
*iface
, DWORD dwIndex
,
281 DWORD dwPatternType
, WCHAR
*pwszName
)
283 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
284 FIXME("(%p, %ld, %ld, %p): stub\n", This
, dwIndex
, dwPatternType
, pwszName
);
288 static const IDirectMusicStyle8Vtbl dmstyle8_vtbl
= {
289 IDirectMusicStyle8Impl_QueryInterface
,
290 IDirectMusicStyle8Impl_AddRef
,
291 IDirectMusicStyle8Impl_Release
,
292 IDirectMusicStyle8Impl_GetBand
,
293 IDirectMusicStyle8Impl_EnumBand
,
294 IDirectMusicStyle8Impl_GetDefaultBand
,
295 IDirectMusicStyle8Impl_EnumMotif
,
296 IDirectMusicStyle8Impl_GetMotif
,
297 IDirectMusicStyle8Impl_GetDefaultChordMap
,
298 IDirectMusicStyle8Impl_EnumChordMap
,
299 IDirectMusicStyle8Impl_GetChordMap
,
300 IDirectMusicStyle8Impl_GetTimeSignature
,
301 IDirectMusicStyle8Impl_GetEmbellishmentLength
,
302 IDirectMusicStyle8Impl_GetTempo
,
303 IDirectMusicStyle8Impl_EnumPattern
306 /* IDirectMusicStyle8Impl IDirectMusicObject part: */
307 static HRESULT WINAPI
style_IDirectMusicObject_ParseDescriptor(IDirectMusicObject
*iface
,
308 IStream
*stream
, DMUS_OBJECTDESC
*desc
)
310 struct chunk_entry riff
= {0};
313 TRACE("(%p, %p, %p)\n", iface
, stream
, desc
);
315 if (!stream
|| !desc
)
318 if ((hr
= stream_get_chunk(stream
, &riff
)) != S_OK
)
320 if (riff
.id
!= FOURCC_RIFF
|| riff
.type
!= DMUS_FOURCC_STYLE_FORM
) {
321 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff
));
322 stream_skip_chunk(stream
, &riff
);
323 return DMUS_E_CHUNKNOTFOUND
;
326 hr
= dmobj_parsedescriptor(stream
, &riff
, desc
,
327 DMUS_OBJ_OBJECT
|DMUS_OBJ_NAME
|DMUS_OBJ_NAME_INAM
|DMUS_OBJ_VERSION
);
331 desc
->guidClass
= CLSID_DirectMusicStyle
;
332 desc
->dwValidData
|= DMUS_OBJ_CLASS
;
334 dump_DMUS_OBJECTDESC(desc
);
338 static const IDirectMusicObjectVtbl dmobject_vtbl
= {
339 dmobj_IDirectMusicObject_QueryInterface
,
340 dmobj_IDirectMusicObject_AddRef
,
341 dmobj_IDirectMusicObject_Release
,
342 dmobj_IDirectMusicObject_GetDescriptor
,
343 dmobj_IDirectMusicObject_SetDescriptor
,
344 style_IDirectMusicObject_ParseDescriptor
347 /* IDirectMusicStyle8Impl IPersistStream part: */
348 static inline IDirectMusicStyle8Impl
*impl_from_IPersistStream(IPersistStream
*iface
)
350 return CONTAINING_RECORD(iface
, IDirectMusicStyle8Impl
, dmobj
.IPersistStream_iface
);
353 static HRESULT
load_band(IStream
*pClonedStream
, IDirectMusicBand
**ppBand
)
356 IPersistStream
* pPersistStream
= NULL
;
358 hr
= CoCreateInstance (&CLSID_DirectMusicBand
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicBand
, (LPVOID
*) ppBand
);
360 ERR(": could not create object\n");
363 /* acquire PersistStream interface */
364 hr
= IDirectMusicBand_QueryInterface (*ppBand
, &IID_IPersistStream
, (LPVOID
*) &pPersistStream
);
366 ERR(": could not acquire IPersistStream\n");
370 hr
= IPersistStream_Load (pPersistStream
, pClonedStream
);
372 ERR(": failed to load object\n");
376 /* release all loading-related stuff */
377 IPersistStream_Release (pPersistStream
);
382 static HRESULT
parse_part_ref_list(DMUS_PRIVATE_CHUNK
*pChunk
, IStream
*pStm
,
383 struct style_motif
*pNewMotif
)
386 DMUS_PRIVATE_CHUNK Chunk
;
387 DWORD ListSize
[3], ListCount
[3];
388 LARGE_INTEGER liMove
; /* used when skipping chunks */
389 struct style_partref_item
*pNewItem
= NULL
;
392 if (pChunk
->fccID
!= DMUS_FOURCC_PARTREF_LIST
) {
393 ERR_(dmfile
)(": %s chunk should be a PARTREF list\n", debugstr_fourcc (pChunk
->fccID
));
397 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
401 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
402 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
403 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
404 switch (Chunk
.fccID
) {
405 case DMUS_FOURCC_PARTREF_CHUNK
: {
406 TRACE_(dmfile
)(": PartRef chunk\n");
407 if (!(pNewItem
= calloc(1, sizeof(*pNewItem
)))) return E_OUTOFMEMORY
;
408 hr
= IStream_Read (pStm
, &pNewItem
->part_ref
, sizeof(DMUS_IO_PARTREF
), NULL
);
409 /*TRACE_(dmfile)(" - sizeof %lu\n", sizeof(DMUS_IO_PARTREF));*/
410 list_add_tail (&pNewMotif
->Items
, &pNewItem
->entry
);
411 pNewItem
->desc
.dwSize
= sizeof(pNewItem
->desc
);
415 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
416 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
417 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
419 switch (Chunk
.fccID
) {
420 case DMUS_FOURCC_UNFO_LIST
: {
421 TRACE_(dmfile
)(": UNFO list\n");
423 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
424 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
425 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
428 ERR(": pNewItem not yet allocated, chunk order bad?\n");
429 return E_OUTOFMEMORY
;
431 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &pNewItem
->desc
);
432 if (FAILED(hr
)) return hr
;
435 switch (Chunk
.fccID
) {
437 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
438 liMove
.QuadPart
= Chunk
.dwSize
;
439 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
444 TRACE_(dmfile
)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount
[1], ListSize
[1]);
445 } while (ListCount
[1] < ListSize
[1]);
449 TRACE_(dmfile
)(": unknown chunk (skipping)\n");
450 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
451 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
458 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
459 liMove
.QuadPart
= Chunk
.dwSize
;
460 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
464 TRACE_(dmfile
)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount
[0], ListSize
[0]);
465 } while (ListCount
[0] < ListSize
[0]);
470 static HRESULT
parse_part_list(DMUS_PRIVATE_CHUNK
*pChunk
, IStream
*pStm
)
473 DMUS_PRIVATE_CHUNK Chunk
;
474 DWORD ListSize
[3], ListCount
[3];
475 LARGE_INTEGER liMove
; /* used when skipping chunks */
477 DMUS_OBJECTDESC desc
;
481 if (pChunk
->fccID
!= DMUS_FOURCC_PART_LIST
) {
482 ERR_(dmfile
)(": %s chunk should be a PART list\n", debugstr_fourcc (pChunk
->fccID
));
486 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
490 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
491 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
492 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
493 switch (Chunk
.fccID
) {
494 case DMUS_FOURCC_PART_CHUNK
: {
495 TRACE_(dmfile
)(": Part chunk (skipping for now)\n" );
496 liMove
.QuadPart
= Chunk
.dwSize
;
497 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
500 case DMUS_FOURCC_NOTE_CHUNK
: {
501 TRACE_(dmfile
)(": Note chunk (skipping for now)\n");
502 IStream_Read (pStm
, &dwSize
, sizeof(DWORD
), NULL
);
503 cnt
= (Chunk
.dwSize
- sizeof(DWORD
));
504 TRACE_(dmfile
)(" - dwSize: %lu\n", dwSize
);
505 TRACE_(dmfile
)(" - cnt: %lu (%lu / %lu)\n", cnt
/ dwSize
, cnt
, dwSize
);
506 if (cnt
% dwSize
!= 0) {
507 ERR("Invalid Array Size\n");
512 liMove
.QuadPart
= cnt
* dwSize
;
513 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
516 case DMUS_FOURCC_CURVE_CHUNK
: {
517 TRACE_(dmfile
)(": Curve chunk (skipping for now)\n");
518 IStream_Read (pStm
, &dwSize
, sizeof(DWORD
), NULL
);
519 cnt
= (Chunk
.dwSize
- sizeof(DWORD
));
520 TRACE_(dmfile
)(" - dwSize: %lu\n", dwSize
);
521 TRACE_(dmfile
)(" - cnt: %lu (%lu / %lu)\n", cnt
/ dwSize
, cnt
, dwSize
);
522 if (cnt
% dwSize
!= 0) {
523 ERR("Invalid Array Size\n");
528 liMove
.QuadPart
= cnt
* dwSize
;
529 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
532 case DMUS_FOURCC_MARKER_CHUNK
: {
533 TRACE_(dmfile
)(": Marker chunk (skipping for now)\n");
534 liMove
.QuadPart
= Chunk
.dwSize
;
535 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
538 case DMUS_FOURCC_RESOLUTION_CHUNK
: {
539 TRACE_(dmfile
)(": Resolution chunk (skipping for now)\n");
540 liMove
.QuadPart
= Chunk
.dwSize
;
541 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
544 case DMUS_FOURCC_ANTICIPATION_CHUNK
: {
545 TRACE_(dmfile
)(": Anticipation chunk (skipping for now)\n");
546 liMove
.QuadPart
= Chunk
.dwSize
;
547 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
551 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
552 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
553 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
555 switch (Chunk
.fccID
) {
556 case DMUS_FOURCC_UNFO_LIST
: {
557 TRACE_(dmfile
)(": UNFO list\n");
559 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
560 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
561 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
563 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &desc
);
564 if (FAILED(hr
)) return hr
;
567 switch (Chunk
.fccID
) {
569 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
570 liMove
.QuadPart
= Chunk
.dwSize
;
571 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
576 TRACE_(dmfile
)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount
[1], ListSize
[1]);
577 } while (ListCount
[1] < ListSize
[1]);
581 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
582 liMove
.QuadPart
= Chunk
.dwSize
;
583 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
590 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
591 liMove
.QuadPart
= Chunk
.dwSize
;
592 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
596 TRACE_(dmfile
)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount
[0], ListSize
[0]);
597 } while (ListCount
[0] < ListSize
[0]);
602 static HRESULT
parse_pattern_list(IDirectMusicStyle8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
606 DMUS_PRIVATE_CHUNK Chunk
;
607 DWORD ListSize
[3], ListCount
[3];
608 LARGE_INTEGER liMove
; /* used when skipping chunks */
609 IDirectMusicBand
* pBand
= NULL
;
610 struct style_motif
*pNewMotif
= NULL
;
612 if (pChunk
->fccID
!= DMUS_FOURCC_PATTERN_LIST
) {
613 ERR_(dmfile
)(": %s chunk should be a PATTERN list\n", debugstr_fourcc (pChunk
->fccID
));
617 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
621 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
622 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
623 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
624 switch (Chunk
.fccID
) {
625 case DMUS_FOURCC_PATTERN_CHUNK
: {
626 TRACE_(dmfile
)(": Pattern chunk\n");
627 /** alloc new motif entry */
628 if (!(pNewMotif
= calloc(1, sizeof(*pNewMotif
)))) return E_OUTOFMEMORY
;
629 list_add_tail(&This
->motifs
, &pNewMotif
->entry
);
631 IStream_Read (pStm
, &pNewMotif
->pattern
, Chunk
.dwSize
, NULL
);
632 /** TODO trace pattern */
634 /** reset all data, as a new pattern begin */
635 pNewMotif
->desc
.dwSize
= sizeof(pNewMotif
->desc
);
636 list_init (&pNewMotif
->Items
);
639 case DMUS_FOURCC_RHYTHM_CHUNK
: {
640 TRACE_(dmfile
)(": Rhythm chunk\n");
641 IStream_Read (pStm
, &pNewMotif
->dwRhythm
, sizeof(DWORD
), NULL
);
642 TRACE_(dmfile
)(" - dwRhythm: %lu\n", pNewMotif
->dwRhythm
);
643 /** TODO understand why some Chunks have size > 4 */
644 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(DWORD
);
645 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
648 case DMUS_FOURCC_MOTIFSETTINGS_CHUNK
: {
649 TRACE_(dmfile
)(": MotifSettings chunk (skipping for now)\n");
650 IStream_Read (pStm
, &pNewMotif
->settings
, Chunk
.dwSize
, NULL
);
651 /** TODO trace settings */
656 * should be embedded Bands into pattern
658 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
659 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
660 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
662 switch (Chunk
.fccID
) {
663 case DMUS_FOURCC_BAND_FORM
: {
664 LPSTREAM pClonedStream
= NULL
;
666 TRACE_(dmfile
)(": BAND RIFF\n");
668 IStream_Clone (pStm
, &pClonedStream
);
671 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
672 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
674 hr
= load_band(pClonedStream
, &pBand
);
676 ERR(": could not load track\n");
679 IStream_Release (pClonedStream
);
681 pNewMotif
->pBand
= pBand
;
682 IDirectMusicBand_AddRef(pBand
);
684 IDirectMusicTrack_Release(pBand
); pBand
= NULL
; /* now we can release it as it's inserted */
686 /** now safe move the cursor */
687 liMove
.QuadPart
= ListSize
[1];
688 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
693 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
694 liMove
.QuadPart
= ListSize
[1];
695 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
702 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
703 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
704 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
706 switch (Chunk
.fccID
) {
707 case DMUS_FOURCC_UNFO_LIST
: {
708 TRACE_(dmfile
)(": UNFO list\n");
710 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
711 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
712 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
714 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &pNewMotif
->desc
);
715 if (FAILED(hr
)) return hr
;
718 switch (Chunk
.fccID
) {
720 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
721 liMove
.QuadPart
= Chunk
.dwSize
;
722 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
727 TRACE_(dmfile
)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount
[1], ListSize
[1]);
728 } while (ListCount
[1] < ListSize
[1]);
731 case DMUS_FOURCC_PARTREF_LIST
: {
732 TRACE_(dmfile
)(": PartRef list\n");
733 hr
= parse_part_ref_list(&Chunk
, pStm
, pNewMotif
);
734 if (FAILED(hr
)) return hr
;
738 TRACE_(dmfile
)(": unknown (skipping)\n");
739 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
740 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
747 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
748 liMove
.QuadPart
= Chunk
.dwSize
;
749 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
753 TRACE_(dmfile
)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount
[0], ListSize
[0]);
754 } while (ListCount
[0] < ListSize
[0]);
759 static HRESULT
parse_style_form(IDirectMusicStyle8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
763 DMUS_PRIVATE_CHUNK Chunk
;
764 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
765 LARGE_INTEGER liMove
; /* used when skipping chunks */
767 IDirectMusicBand
* pBand
= NULL
;
769 if (pChunk
->fccID
!= DMUS_FOURCC_STYLE_FORM
) {
770 ERR_(dmfile
)(": %s chunk should be a STYLE form\n", debugstr_fourcc (pChunk
->fccID
));
774 StreamSize
= pChunk
->dwSize
- sizeof(FOURCC
);
778 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
779 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
780 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
782 hr
= IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
783 if (FAILED(hr
)) return hr
;
786 switch (Chunk
.fccID
) {
787 case DMUS_FOURCC_STYLE_CHUNK
: {
788 TRACE_(dmfile
)(": Style chunk\n");
789 IStream_Read (pStm
, &This
->style
, sizeof(DMUS_IO_STYLE
), NULL
);
790 /** TODO dump DMUS_IO_TIMESIG style.timeSig */
791 TRACE_(dmfile
)(" - dblTempo: %g\n", This
->style
.dblTempo
);
796 * should be embedded Bands into style
798 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
799 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
800 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
802 switch (Chunk
.fccID
) {
803 case DMUS_FOURCC_BAND_FORM
: {
805 struct style_band
*pNewBand
;
807 TRACE_(dmfile
)(": BAND RIFF\n");
809 /* Can be application provided IStream without Clone method */
811 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
812 IStream_Seek(pStm
, liMove
, STREAM_SEEK_CUR
, &save
);
814 hr
= load_band(pStm
, &pBand
);
816 ERR(": could not load track\n");
820 if (!(pNewBand
= calloc(1, sizeof(*pNewBand
)))) return E_OUTOFMEMORY
;
821 pNewBand
->pBand
= pBand
;
822 IDirectMusicBand_AddRef(pBand
);
823 list_add_tail(&This
->bands
, &pNewBand
->entry
);
825 IDirectMusicTrack_Release(pBand
); pBand
= NULL
; /* now we can release it as it's inserted */
827 /** now safely move the cursor */
828 liMove
.QuadPart
= save
.QuadPart
- liMove
.QuadPart
+ ListSize
[0];
829 IStream_Seek(pStm
, liMove
, STREAM_SEEK_SET
, NULL
);
834 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
835 liMove
.QuadPart
= ListSize
[0];
836 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
843 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
844 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
845 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
847 switch (Chunk
.fccID
) {
848 case DMUS_FOURCC_UNFO_LIST
: {
849 TRACE_(dmfile
)(": UNFO list\n");
851 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
852 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
853 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
855 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
856 if (FAILED(hr
)) return hr
;
859 switch (Chunk
.fccID
) {
861 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
862 liMove
.QuadPart
= Chunk
.dwSize
;
863 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
868 TRACE_(dmfile
)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount
[0], ListSize
[0]);
869 } while (ListCount
[0] < ListSize
[0]);
872 case DMUS_FOURCC_PART_LIST
: {
873 TRACE_(dmfile
)(": PART list\n");
874 hr
= parse_part_list(&Chunk
, pStm
);
875 if (FAILED(hr
)) return hr
;
878 case DMUS_FOURCC_PATTERN_LIST
: {
879 TRACE_(dmfile
)(": PATTERN list\n");
880 hr
= parse_pattern_list(This
, &Chunk
, pStm
);
881 if (FAILED(hr
)) return hr
;
885 TRACE_(dmfile
)(": unknown (skipping)\n");
886 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
887 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
894 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
895 liMove
.QuadPart
= Chunk
.dwSize
;
896 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
901 TRACE_(dmfile
)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount
, StreamSize
);
902 } while (StreamCount
< StreamSize
);
907 static HRESULT WINAPI
IPersistStreamImpl_Load(IPersistStream
*iface
, IStream
*pStm
)
909 IDirectMusicStyle8Impl
*This
= impl_from_IPersistStream(iface
);
910 DMUS_PRIVATE_CHUNK Chunk
;
911 LARGE_INTEGER liMove
; /* used when skipping chunks */
914 FIXME("(%p, %p): Loading\n", This
, pStm
);
916 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
917 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
918 switch (Chunk
.fccID
) {
920 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
921 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
922 switch (Chunk
.fccID
) {
923 case DMUS_FOURCC_STYLE_FORM
: {
924 TRACE_(dmfile
)(": Style form\n");
925 hr
= parse_style_form(This
, &Chunk
, pStm
);
926 if (FAILED(hr
)) return hr
;
930 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
931 liMove
.QuadPart
= Chunk
.dwSize
;
932 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
936 TRACE_(dmfile
)(": reading finished\n");
940 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
941 liMove
.QuadPart
= Chunk
.dwSize
;
942 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
950 static const IPersistStreamVtbl persiststream_vtbl
= {
951 dmobj_IPersistStream_QueryInterface
,
952 dmobj_IPersistStream_AddRef
,
953 dmobj_IPersistStream_Release
,
954 dmobj_IPersistStream_GetClassID
,
955 unimpl_IPersistStream_IsDirty
,
956 IPersistStreamImpl_Load
,
957 unimpl_IPersistStream_Save
,
958 unimpl_IPersistStream_GetSizeMax
961 /* for ClassFactory */
962 HRESULT
create_dmstyle(REFIID lpcGUID
, void **ppobj
)
964 IDirectMusicStyle8Impl
* obj
;
968 if (!(obj
= calloc(1, sizeof(*obj
)))) return E_OUTOFMEMORY
;
969 obj
->IDirectMusicStyle8_iface
.lpVtbl
= &dmstyle8_vtbl
;
971 dmobject_init(&obj
->dmobj
, &CLSID_DirectMusicStyle
, (IUnknown
*)&obj
->IDirectMusicStyle8_iface
);
972 obj
->dmobj
.IDirectMusicObject_iface
.lpVtbl
= &dmobject_vtbl
;
973 obj
->dmobj
.IPersistStream_iface
.lpVtbl
= &persiststream_vtbl
;
974 list_init(&obj
->bands
);
975 list_init(&obj
->motifs
);
977 hr
= IDirectMusicStyle8_QueryInterface(&obj
->IDirectMusicStyle8_iface
, lpcGUID
, ppobj
);
978 IDirectMusicStyle8_Release(&obj
->IDirectMusicStyle8_iface
);