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
*name
,
138 IDirectMusicBand
**band
)
140 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
141 struct style_band
*sband
;
144 TRACE("(%p, %s, %p)\n", This
, debugstr_w(name
), band
);
149 LIST_FOR_EACH_ENTRY(sband
, &This
->bands
, struct style_band
, entry
) {
150 IDirectMusicObject
*obj
;
152 hr
= IDirectMusicBand_QueryInterface(sband
->pBand
, &IID_IDirectMusicObject
, (void**)&obj
);
154 DMUS_OBJECTDESC desc
;
156 if (IDirectMusicObject_GetDescriptor(obj
, &desc
) == S_OK
) {
157 if (desc
.dwValidData
& DMUS_OBJ_NAME
&& !lstrcmpW(name
, desc
.wszName
)) {
158 IDirectMusicObject_Release(obj
);
159 IDirectMusicBand_AddRef(sband
->pBand
);
160 *band
= sband
->pBand
;
165 IDirectMusicObject_Release(obj
);
172 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumBand(IDirectMusicStyle8
*iface
, DWORD dwIndex
,
175 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
176 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
180 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetDefaultBand(IDirectMusicStyle8
*iface
,
181 IDirectMusicBand
**band
)
183 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
184 FIXME("(%p, %p): stub\n", This
, band
);
194 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumMotif(IDirectMusicStyle8
*iface
, DWORD index
,
197 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
198 const struct style_motif
*motif
= NULL
;
199 const struct list
*cursor
;
202 TRACE("(%p, %u, %p)\n", This
, index
, name
);
207 /* index is zero based */
208 LIST_FOR_EACH(cursor
, &This
->motifs
) {
210 motif
= LIST_ENTRY(cursor
, struct style_motif
, entry
);
218 if (motif
->desc
.dwValidData
& DMUS_OBJ_NAME
)
219 lstrcpynW(name
, motif
->desc
.wszName
, DMUS_MAX_NAME
);
223 TRACE("returning name: %s\n", debugstr_w(name
));
227 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetMotif(IDirectMusicStyle8
*iface
, WCHAR
*pwszName
,
228 IDirectMusicSegment
**ppSegment
)
230 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
231 FIXME("(%p, %s, %p): stub\n", This
, debugstr_w(pwszName
), ppSegment
);
235 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetDefaultChordMap(IDirectMusicStyle8
*iface
,
236 IDirectMusicChordMap
**ppChordMap
)
238 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
239 FIXME("(%p, %p): stub\n", This
, ppChordMap
);
243 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumChordMap(IDirectMusicStyle8
*iface
, DWORD dwIndex
,
246 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
247 FIXME("(%p, %d, %p): stub\n", This
, dwIndex
, pwszName
);
251 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetChordMap(IDirectMusicStyle8
*iface
, WCHAR
*pwszName
,
252 IDirectMusicChordMap
**ppChordMap
)
254 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
255 FIXME("(%p, %p, %p): stub\n", This
, pwszName
, ppChordMap
);
259 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetTimeSignature(IDirectMusicStyle8
*iface
,
260 DMUS_TIMESIGNATURE
*pTimeSig
)
262 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
263 FIXME("(%p, %p): stub\n", This
, pTimeSig
);
267 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetEmbellishmentLength(IDirectMusicStyle8
*iface
,
268 DWORD dwType
, DWORD dwLevel
, DWORD
*pdwMin
, DWORD
*pdwMax
)
270 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
271 FIXME("(%p, %d, %d, %p, %p): stub\n", This
, dwType
, dwLevel
, pdwMin
, pdwMax
);
275 static HRESULT WINAPI
IDirectMusicStyle8Impl_GetTempo(IDirectMusicStyle8
*iface
, double *pTempo
)
277 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
278 FIXME("(%p, %p): stub\n", This
, pTempo
);
282 static HRESULT WINAPI
IDirectMusicStyle8Impl_EnumPattern(IDirectMusicStyle8
*iface
, DWORD dwIndex
,
283 DWORD dwPatternType
, WCHAR
*pwszName
)
285 IDirectMusicStyle8Impl
*This
= impl_from_IDirectMusicStyle8(iface
);
286 FIXME("(%p, %d, %d, %p): stub\n", This
, dwIndex
, dwPatternType
, pwszName
);
290 static const IDirectMusicStyle8Vtbl dmstyle8_vtbl
= {
291 IDirectMusicStyle8Impl_QueryInterface
,
292 IDirectMusicStyle8Impl_AddRef
,
293 IDirectMusicStyle8Impl_Release
,
294 IDirectMusicStyle8Impl_GetBand
,
295 IDirectMusicStyle8Impl_EnumBand
,
296 IDirectMusicStyle8Impl_GetDefaultBand
,
297 IDirectMusicStyle8Impl_EnumMotif
,
298 IDirectMusicStyle8Impl_GetMotif
,
299 IDirectMusicStyle8Impl_GetDefaultChordMap
,
300 IDirectMusicStyle8Impl_EnumChordMap
,
301 IDirectMusicStyle8Impl_GetChordMap
,
302 IDirectMusicStyle8Impl_GetTimeSignature
,
303 IDirectMusicStyle8Impl_GetEmbellishmentLength
,
304 IDirectMusicStyle8Impl_GetTempo
,
305 IDirectMusicStyle8Impl_EnumPattern
308 /* IDirectMusicStyle8Impl IDirectMusicObject part: */
309 static HRESULT WINAPI
style_IDirectMusicObject_ParseDescriptor(IDirectMusicObject
*iface
,
310 IStream
*stream
, DMUS_OBJECTDESC
*desc
)
312 struct chunk_entry riff
= {0};
315 TRACE("(%p, %p, %p)\n", iface
, stream
, desc
);
317 if (!stream
|| !desc
)
320 if ((hr
= stream_get_chunk(stream
, &riff
)) != S_OK
)
322 if (riff
.id
!= FOURCC_RIFF
|| riff
.type
!= DMUS_FOURCC_STYLE_FORM
) {
323 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff
));
324 stream_skip_chunk(stream
, &riff
);
325 return DMUS_E_CHUNKNOTFOUND
;
328 hr
= dmobj_parsedescriptor(stream
, &riff
, desc
,
329 DMUS_OBJ_OBJECT
|DMUS_OBJ_NAME
|DMUS_OBJ_NAME_INAM
|DMUS_OBJ_VERSION
);
333 desc
->guidClass
= CLSID_DirectMusicStyle
;
334 desc
->dwValidData
|= DMUS_OBJ_CLASS
;
336 dump_DMUS_OBJECTDESC(desc
);
340 static const IDirectMusicObjectVtbl dmobject_vtbl
= {
341 dmobj_IDirectMusicObject_QueryInterface
,
342 dmobj_IDirectMusicObject_AddRef
,
343 dmobj_IDirectMusicObject_Release
,
344 dmobj_IDirectMusicObject_GetDescriptor
,
345 dmobj_IDirectMusicObject_SetDescriptor
,
346 style_IDirectMusicObject_ParseDescriptor
349 /* IDirectMusicStyle8Impl IPersistStream part: */
350 static inline IDirectMusicStyle8Impl
*impl_from_IPersistStream(IPersistStream
*iface
)
352 return CONTAINING_RECORD(iface
, IDirectMusicStyle8Impl
, dmobj
.IPersistStream_iface
);
355 static HRESULT
load_band(IStream
*pClonedStream
, IDirectMusicBand
**ppBand
)
358 IPersistStream
* pPersistStream
= NULL
;
360 hr
= CoCreateInstance (&CLSID_DirectMusicBand
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicBand
, (LPVOID
*) ppBand
);
362 ERR(": could not create object\n");
365 /* acquire PersistStream interface */
366 hr
= IDirectMusicBand_QueryInterface (*ppBand
, &IID_IPersistStream
, (LPVOID
*) &pPersistStream
);
368 ERR(": could not acquire IPersistStream\n");
372 hr
= IPersistStream_Load (pPersistStream
, pClonedStream
);
374 ERR(": failed to load object\n");
378 /* release all loading-related stuff */
379 IPersistStream_Release (pPersistStream
);
384 static HRESULT
parse_part_ref_list(DMUS_PRIVATE_CHUNK
*pChunk
, IStream
*pStm
,
385 struct style_motif
*pNewMotif
)
388 DMUS_PRIVATE_CHUNK Chunk
;
389 DWORD ListSize
[3], ListCount
[3];
390 LARGE_INTEGER liMove
; /* used when skipping chunks */
391 struct style_partref_item
*pNewItem
= NULL
;
394 if (pChunk
->fccID
!= DMUS_FOURCC_PARTREF_LIST
) {
395 ERR_(dmfile
)(": %s chunk should be a PARTREF list\n", debugstr_fourcc (pChunk
->fccID
));
399 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
403 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
404 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
405 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
406 switch (Chunk
.fccID
) {
407 case DMUS_FOURCC_PARTREF_CHUNK
: {
408 TRACE_(dmfile
)(": PartRef chunk\n");
409 pNewItem
= heap_alloc_zero(sizeof(*pNewItem
));
411 ERR(": no more memory\n");
412 return E_OUTOFMEMORY
;
414 hr
= IStream_Read (pStm
, &pNewItem
->part_ref
, sizeof(DMUS_IO_PARTREF
), NULL
);
415 /*TRACE_(dmfile)(" - sizeof %lu\n", sizeof(DMUS_IO_PARTREF));*/
416 list_add_tail (&pNewMotif
->Items
, &pNewItem
->entry
);
417 pNewItem
->desc
.dwSize
= sizeof(pNewItem
->desc
);
421 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
422 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
423 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
425 switch (Chunk
.fccID
) {
426 case DMUS_FOURCC_UNFO_LIST
: {
427 TRACE_(dmfile
)(": UNFO list\n");
429 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
430 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
431 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
434 ERR(": pNewItem not yet allocated, chunk order bad?\n");
435 return E_OUTOFMEMORY
;
437 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &pNewItem
->desc
);
438 if (FAILED(hr
)) return hr
;
441 switch (Chunk
.fccID
) {
443 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
444 liMove
.QuadPart
= Chunk
.dwSize
;
445 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
450 TRACE_(dmfile
)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount
[1], ListSize
[1]);
451 } while (ListCount
[1] < ListSize
[1]);
455 TRACE_(dmfile
)(": unknown chunk (skipping)\n");
456 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
457 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
464 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
465 liMove
.QuadPart
= Chunk
.dwSize
;
466 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
470 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
471 } while (ListCount
[0] < ListSize
[0]);
476 static HRESULT
parse_part_list(DMUS_PRIVATE_CHUNK
*pChunk
, IStream
*pStm
)
479 DMUS_PRIVATE_CHUNK Chunk
;
480 DWORD ListSize
[3], ListCount
[3];
481 LARGE_INTEGER liMove
; /* used when skipping chunks */
483 DMUS_OBJECTDESC desc
;
487 if (pChunk
->fccID
!= DMUS_FOURCC_PART_LIST
) {
488 ERR_(dmfile
)(": %s chunk should be a PART list\n", debugstr_fourcc (pChunk
->fccID
));
492 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
496 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
497 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
498 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
499 switch (Chunk
.fccID
) {
500 case DMUS_FOURCC_PART_CHUNK
: {
501 TRACE_(dmfile
)(": Part chunk (skipping for now)\n" );
502 liMove
.QuadPart
= Chunk
.dwSize
;
503 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
506 case DMUS_FOURCC_NOTE_CHUNK
: {
507 TRACE_(dmfile
)(": Note chunk (skipping for now)\n");
508 IStream_Read (pStm
, &dwSize
, sizeof(DWORD
), NULL
);
509 cnt
= (Chunk
.dwSize
- sizeof(DWORD
));
510 TRACE_(dmfile
)(" - dwSize: %u\n", dwSize
);
511 TRACE_(dmfile
)(" - cnt: %u (%u / %u)\n", cnt
/ dwSize
, (DWORD
)(Chunk
.dwSize
- sizeof(DWORD
)), dwSize
);
512 if (cnt
% dwSize
!= 0) {
513 ERR("Invalid Array Size\n");
518 liMove
.QuadPart
= cnt
* dwSize
;
519 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
522 case DMUS_FOURCC_CURVE_CHUNK
: {
523 TRACE_(dmfile
)(": Curve chunk (skipping for now)\n");
524 IStream_Read (pStm
, &dwSize
, sizeof(DWORD
), NULL
);
525 cnt
= (Chunk
.dwSize
- sizeof(DWORD
));
526 TRACE_(dmfile
)(" - dwSize: %u\n", dwSize
);
527 TRACE_(dmfile
)(" - cnt: %u (%u / %u)\n", cnt
/ dwSize
, (DWORD
)(Chunk
.dwSize
- sizeof(DWORD
)), dwSize
);
528 if (cnt
% dwSize
!= 0) {
529 ERR("Invalid Array Size\n");
534 liMove
.QuadPart
= cnt
* dwSize
;
535 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
538 case DMUS_FOURCC_MARKER_CHUNK
: {
539 TRACE_(dmfile
)(": Marker chunk (skipping for now)\n");
540 liMove
.QuadPart
= Chunk
.dwSize
;
541 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
544 case DMUS_FOURCC_RESOLUTION_CHUNK
: {
545 TRACE_(dmfile
)(": Resolution chunk (skipping for now)\n");
546 liMove
.QuadPart
= Chunk
.dwSize
;
547 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
550 case DMUS_FOURCC_ANTICIPATION_CHUNK
: {
551 TRACE_(dmfile
)(": Anticipation chunk (skipping for now)\n");
552 liMove
.QuadPart
= Chunk
.dwSize
;
553 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
557 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
558 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
559 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
561 switch (Chunk
.fccID
) {
562 case DMUS_FOURCC_UNFO_LIST
: {
563 TRACE_(dmfile
)(": UNFO list\n");
565 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
566 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
567 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
569 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &desc
);
570 if (FAILED(hr
)) return hr
;
573 switch (Chunk
.fccID
) {
575 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
576 liMove
.QuadPart
= Chunk
.dwSize
;
577 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
582 TRACE_(dmfile
)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount
[1], ListSize
[1]);
583 } while (ListCount
[1] < ListSize
[1]);
587 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
588 liMove
.QuadPart
= Chunk
.dwSize
;
589 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
596 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
597 liMove
.QuadPart
= Chunk
.dwSize
;
598 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
602 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
603 } while (ListCount
[0] < ListSize
[0]);
608 static HRESULT
parse_pattern_list(IDirectMusicStyle8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
612 DMUS_PRIVATE_CHUNK Chunk
;
613 DWORD ListSize
[3], ListCount
[3];
614 LARGE_INTEGER liMove
; /* used when skipping chunks */
615 IDirectMusicBand
* pBand
= NULL
;
616 struct style_motif
*pNewMotif
= NULL
;
618 if (pChunk
->fccID
!= DMUS_FOURCC_PATTERN_LIST
) {
619 ERR_(dmfile
)(": %s chunk should be a PATTERN list\n", debugstr_fourcc (pChunk
->fccID
));
623 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
627 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
628 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
629 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
630 switch (Chunk
.fccID
) {
631 case DMUS_FOURCC_PATTERN_CHUNK
: {
632 TRACE_(dmfile
)(": Pattern chunk\n");
633 /** alloc new motif entry */
634 pNewMotif
= heap_alloc_zero(sizeof(*pNewMotif
));
635 if (NULL
== pNewMotif
) {
636 ERR(": no more memory\n");
637 return E_OUTOFMEMORY
;
639 list_add_tail(&This
->motifs
, &pNewMotif
->entry
);
641 IStream_Read (pStm
, &pNewMotif
->pattern
, Chunk
.dwSize
, NULL
);
642 /** TODO trace pattern */
644 /** reset all data, as a new pattern begin */
645 pNewMotif
->desc
.dwSize
= sizeof(pNewMotif
->desc
);
646 list_init (&pNewMotif
->Items
);
649 case DMUS_FOURCC_RHYTHM_CHUNK
: {
650 TRACE_(dmfile
)(": Rhythm chunk\n");
651 IStream_Read (pStm
, &pNewMotif
->dwRhythm
, sizeof(DWORD
), NULL
);
652 TRACE_(dmfile
)(" - dwRhythm: %u\n", pNewMotif
->dwRhythm
);
653 /** TODO understand why some Chunks have size > 4 */
654 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(DWORD
);
655 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
658 case DMUS_FOURCC_MOTIFSETTINGS_CHUNK
: {
659 TRACE_(dmfile
)(": MotifSettings chunk (skipping for now)\n");
660 IStream_Read (pStm
, &pNewMotif
->settings
, Chunk
.dwSize
, NULL
);
661 /** TODO trace settings */
666 * should be embedded Bands into pattern
668 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
669 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
670 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
672 switch (Chunk
.fccID
) {
673 case DMUS_FOURCC_BAND_FORM
: {
674 LPSTREAM pClonedStream
= NULL
;
676 TRACE_(dmfile
)(": BAND RIFF\n");
678 IStream_Clone (pStm
, &pClonedStream
);
681 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
682 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
684 hr
= load_band(pClonedStream
, &pBand
);
686 ERR(": could not load track\n");
689 IStream_Release (pClonedStream
);
691 pNewMotif
->pBand
= pBand
;
692 IDirectMusicBand_AddRef(pBand
);
694 IDirectMusicTrack_Release(pBand
); pBand
= NULL
; /* now we can release it as it's inserted */
696 /** now safe move the cursor */
697 liMove
.QuadPart
= ListSize
[1];
698 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
703 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
704 liMove
.QuadPart
= ListSize
[1];
705 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
712 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
713 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
714 ListSize
[1] = Chunk
.dwSize
- sizeof(FOURCC
);
716 switch (Chunk
.fccID
) {
717 case DMUS_FOURCC_UNFO_LIST
: {
718 TRACE_(dmfile
)(": UNFO list\n");
720 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
721 ListCount
[1] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
722 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
724 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &pNewMotif
->desc
);
725 if (FAILED(hr
)) return hr
;
728 switch (Chunk
.fccID
) {
730 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
731 liMove
.QuadPart
= Chunk
.dwSize
;
732 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
737 TRACE_(dmfile
)(": ListCount[1] = %d < ListSize[1] = %d\n", ListCount
[1], ListSize
[1]);
738 } while (ListCount
[1] < ListSize
[1]);
741 case DMUS_FOURCC_PARTREF_LIST
: {
742 TRACE_(dmfile
)(": PartRef list\n");
743 hr
= parse_part_ref_list(&Chunk
, pStm
, pNewMotif
);
744 if (FAILED(hr
)) return hr
;
748 TRACE_(dmfile
)(": unknown (skipping)\n");
749 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
750 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
757 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
758 liMove
.QuadPart
= Chunk
.dwSize
;
759 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
763 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
764 } while (ListCount
[0] < ListSize
[0]);
769 static HRESULT
parse_style_form(IDirectMusicStyle8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
773 DMUS_PRIVATE_CHUNK Chunk
;
774 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
775 LARGE_INTEGER liMove
; /* used when skipping chunks */
777 IDirectMusicBand
* pBand
= NULL
;
779 if (pChunk
->fccID
!= DMUS_FOURCC_STYLE_FORM
) {
780 ERR_(dmfile
)(": %s chunk should be a STYLE form\n", debugstr_fourcc (pChunk
->fccID
));
784 StreamSize
= pChunk
->dwSize
- sizeof(FOURCC
);
788 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
789 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
790 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
792 hr
= IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
793 if (FAILED(hr
)) return hr
;
796 switch (Chunk
.fccID
) {
797 case DMUS_FOURCC_STYLE_CHUNK
: {
798 TRACE_(dmfile
)(": Style chunk\n");
799 IStream_Read (pStm
, &This
->style
, sizeof(DMUS_IO_STYLE
), NULL
);
800 /** TODO dump DMUS_IO_TIMESIG style.timeSig */
801 TRACE_(dmfile
)(" - dblTempo: %g\n", This
->style
.dblTempo
);
806 * should be embedded Bands into style
808 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
809 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
810 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
812 switch (Chunk
.fccID
) {
813 case DMUS_FOURCC_BAND_FORM
: {
815 struct style_band
*pNewBand
;
817 TRACE_(dmfile
)(": BAND RIFF\n");
819 /* Can be application provided IStream without Clone method */
821 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
822 IStream_Seek(pStm
, liMove
, STREAM_SEEK_CUR
, &save
);
824 hr
= load_band(pStm
, &pBand
);
826 ERR(": could not load track\n");
830 pNewBand
= heap_alloc_zero(sizeof(*pNewBand
));
831 if (NULL
== pNewBand
) {
832 ERR(": no more memory\n");
833 return E_OUTOFMEMORY
;
835 pNewBand
->pBand
= pBand
;
836 IDirectMusicBand_AddRef(pBand
);
837 list_add_tail(&This
->bands
, &pNewBand
->entry
);
839 IDirectMusicTrack_Release(pBand
); pBand
= NULL
; /* now we can release it as it's inserted */
841 /** now safely move the cursor */
842 liMove
.QuadPart
= save
.QuadPart
- liMove
.QuadPart
+ ListSize
[0];
843 IStream_Seek(pStm
, liMove
, STREAM_SEEK_SET
, NULL
);
848 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
849 liMove
.QuadPart
= ListSize
[0];
850 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
857 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
858 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
859 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
861 switch (Chunk
.fccID
) {
862 case DMUS_FOURCC_UNFO_LIST
: {
863 TRACE_(dmfile
)(": UNFO list\n");
865 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
866 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
867 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
869 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
870 if (FAILED(hr
)) return hr
;
873 switch (Chunk
.fccID
) {
875 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
876 liMove
.QuadPart
= Chunk
.dwSize
;
877 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
882 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
883 } while (ListCount
[0] < ListSize
[0]);
886 case DMUS_FOURCC_PART_LIST
: {
887 TRACE_(dmfile
)(": PART list\n");
888 hr
= parse_part_list(&Chunk
, pStm
);
889 if (FAILED(hr
)) return hr
;
892 case DMUS_FOURCC_PATTERN_LIST
: {
893 TRACE_(dmfile
)(": PATTERN list\n");
894 hr
= parse_pattern_list(This
, &Chunk
, pStm
);
895 if (FAILED(hr
)) return hr
;
899 TRACE_(dmfile
)(": unknown (skipping)\n");
900 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
901 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
908 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
909 liMove
.QuadPart
= Chunk
.dwSize
;
910 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
915 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
916 } while (StreamCount
< StreamSize
);
921 static HRESULT WINAPI
IPersistStreamImpl_Load(IPersistStream
*iface
, IStream
*pStm
)
923 IDirectMusicStyle8Impl
*This
= impl_from_IPersistStream(iface
);
924 DMUS_PRIVATE_CHUNK Chunk
;
925 LARGE_INTEGER liMove
; /* used when skipping chunks */
928 FIXME("(%p, %p): Loading\n", This
, pStm
);
930 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
931 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
932 switch (Chunk
.fccID
) {
934 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
935 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
936 switch (Chunk
.fccID
) {
937 case DMUS_FOURCC_STYLE_FORM
: {
938 TRACE_(dmfile
)(": Style form\n");
939 hr
= parse_style_form(This
, &Chunk
, pStm
);
940 if (FAILED(hr
)) return hr
;
944 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
945 liMove
.QuadPart
= Chunk
.dwSize
;
946 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
950 TRACE_(dmfile
)(": reading finished\n");
954 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
955 liMove
.QuadPart
= Chunk
.dwSize
;
956 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
964 static const IPersistStreamVtbl persiststream_vtbl
= {
965 dmobj_IPersistStream_QueryInterface
,
966 dmobj_IPersistStream_AddRef
,
967 dmobj_IPersistStream_Release
,
968 dmobj_IPersistStream_GetClassID
,
969 unimpl_IPersistStream_IsDirty
,
970 IPersistStreamImpl_Load
,
971 unimpl_IPersistStream_Save
,
972 unimpl_IPersistStream_GetSizeMax
975 /* for ClassFactory */
976 HRESULT WINAPI
create_dmstyle(REFIID lpcGUID
, void **ppobj
)
978 IDirectMusicStyle8Impl
* obj
;
981 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicStyle8Impl
));
984 return E_OUTOFMEMORY
;
986 obj
->IDirectMusicStyle8_iface
.lpVtbl
= &dmstyle8_vtbl
;
988 dmobject_init(&obj
->dmobj
, &CLSID_DirectMusicStyle
, (IUnknown
*)&obj
->IDirectMusicStyle8_iface
);
989 obj
->dmobj
.IDirectMusicObject_iface
.lpVtbl
= &dmobject_vtbl
;
990 obj
->dmobj
.IPersistStream_iface
.lpVtbl
= &persiststream_vtbl
;
991 list_init(&obj
->bands
);
992 list_init(&obj
->motifs
);
994 DMSTYLE_LockModule();
995 hr
= IDirectMusicStyle8_QueryInterface(&obj
->IDirectMusicStyle8_iface
, lpcGUID
, ppobj
);
996 IDirectMusicStyle8_Release(&obj
->IDirectMusicStyle8_iface
);