Get rid of the non-standard ICOM_VTABLE macro.
[wine] / dlls / dmstyle / style.c
1 /* IDirectMusicStyle8 Implementation
2  *
3  * Copyright (C) 2003-2004 Rok Mandeljc
4  * Copyright (C) 2003-2004 Raphael Junqueira
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #include "dmstyle_private.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(dmstyle);
24 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
25
26 /*****************************************************************************
27  * IDirectMusicStyleImpl implementation
28  */
29 /* IDirectMusicStyleImpl IUnknown part: */
30 HRESULT WINAPI IDirectMusicStyle8Impl_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
31         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, UnknownVtbl, iface);
32         TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
33         
34         if (IsEqualIID (riid, &IID_IUnknown)) {
35                 *ppobj = (LPVOID)&This->UnknownVtbl;
36                 IDirectMusicStyle8Impl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
37                 return S_OK;    
38         } else if (IsEqualIID (riid, &IID_IDirectMusicStyle)) {
39                 *ppobj = (LPVOID)&This->StyleVtbl;
40                 IDirectMusicStyle8Impl_IDirectMusicStyle8_AddRef ((LPDIRECTMUSICSTYLE8)&This->StyleVtbl);
41                 return S_OK;
42         } else if (IsEqualIID (riid, &IID_IDirectMusicObject)) {
43                 *ppobj = (LPVOID)&This->ObjectVtbl;
44                 IDirectMusicStyle8Impl_IDirectMusicObject_AddRef ((LPDIRECTMUSICOBJECT)&This->ObjectVtbl);              
45                 return S_OK;
46         } else if (IsEqualIID (riid, &IID_IPersistStream)) {
47                 *ppobj = (LPVOID)&This->PersistStreamVtbl;
48                 IDirectMusicStyle8Impl_IPersistStream_AddRef ((LPPERSISTSTREAM)&This->PersistStreamVtbl);               
49                 return S_OK;
50         }
51         
52         WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
53         return E_NOINTERFACE;
54 }
55
56 ULONG WINAPI IDirectMusicStyle8Impl_IUnknown_AddRef (LPUNKNOWN iface) {
57         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, UnknownVtbl, iface);
58         TRACE("(%p): AddRef from %ld\n", This, This->ref);
59         return ++(This->ref);
60 }
61
62 ULONG WINAPI IDirectMusicStyle8Impl_IUnknown_Release (LPUNKNOWN iface) {
63         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, UnknownVtbl, iface);
64         ULONG ref = --This->ref;
65         TRACE("(%p): ReleaseRef to %ld\n", This, This->ref);
66         if (ref == 0) {
67                 HeapFree(GetProcessHeap(), 0, This);
68         }
69         return ref;
70 }
71
72 IUnknownVtbl DirectMusicStyle8_Unknown_Vtbl = {
73     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
74         IDirectMusicStyle8Impl_IUnknown_QueryInterface,
75         IDirectMusicStyle8Impl_IUnknown_AddRef,
76         IDirectMusicStyle8Impl_IUnknown_Release
77 };
78
79 /* IDirectMusicStyle8Impl IDirectMusicStyle8 part: */
80 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_QueryInterface (LPDIRECTMUSICSTYLE8 iface, REFIID riid, LPVOID *ppobj) {
81         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
82         return IDirectMusicStyle8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
83 }
84
85 ULONG WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_AddRef (LPDIRECTMUSICSTYLE8 iface) {
86         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
87         return IDirectMusicStyle8Impl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
88 }
89
90 ULONG WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_Release (LPDIRECTMUSICSTYLE8 iface) {
91         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
92         return IDirectMusicStyle8Impl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
93 }
94
95 /* IDirectMusicStyle8Impl IDirectMusicStyle(8) part: */
96 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetBand (LPDIRECTMUSICSTYLE8 iface, WCHAR* pwszName, IDirectMusicBand** ppBand) {
97         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
98         FIXME("(%p, %p, %p): stub\n", This, pwszName, ppBand);
99         return S_OK;
100 }
101
102 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumBand (LPDIRECTMUSICSTYLE8 iface, DWORD dwIndex, WCHAR* pwszName) {
103         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
104         FIXME("(%p, %ld, %p): stub\n", This, dwIndex, pwszName);
105         return S_OK;
106 }
107
108 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetDefaultBand (LPDIRECTMUSICSTYLE8 iface, IDirectMusicBand** ppBand) {
109         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
110         FIXME("(%p, %p): stub\n", This, ppBand);
111         return S_OK;
112 }
113
114 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumMotif (LPDIRECTMUSICSTYLE8 iface, DWORD dwIndex, WCHAR* pwszName) {
115         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
116         FIXME("(%p, %ld, %p): stub\n", This, dwIndex, pwszName);
117         return S_OK;
118 }
119
120 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetMotif (LPDIRECTMUSICSTYLE8 iface, WCHAR* pwszName, IDirectMusicSegment** ppSegment) {
121         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
122         FIXME("(%p, %p, %p): stub\n", This, pwszName, ppSegment);
123         return S_OK;
124 }
125
126 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetDefaultChordMap (LPDIRECTMUSICSTYLE8 iface, IDirectMusicChordMap** ppChordMap) {
127         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
128         FIXME("(%p, %p): stub\n", This, ppChordMap);
129         return S_OK;
130 }
131
132 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumChordMap (LPDIRECTMUSICSTYLE8 iface, DWORD dwIndex, WCHAR* pwszName) {
133         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
134         FIXME("(%p, %ld, %p): stub\n", This, dwIndex, pwszName);
135         return S_OK;
136 }
137
138 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetChordMap (LPDIRECTMUSICSTYLE8 iface, WCHAR* pwszName, IDirectMusicChordMap** ppChordMap) {
139         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
140         FIXME("(%p, %p, %p): stub\n", This, pwszName, ppChordMap);
141         return S_OK;
142 }
143
144 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetTimeSignature (LPDIRECTMUSICSTYLE8 iface, DMUS_TIMESIGNATURE* pTimeSig) {
145         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
146         FIXME("(%p, %p): stub\n", This, pTimeSig);
147         return S_OK;
148 }
149
150 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetEmbellishmentLength (LPDIRECTMUSICSTYLE8 iface, DWORD dwType, DWORD dwLevel, DWORD* pdwMin, DWORD* pdwMax) {
151         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
152         FIXME("(%p, %ld, %ld, %p, %p): stub\n", This, dwType, dwLevel, pdwMin, pdwMax);
153         return S_OK;
154 }
155
156 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_GetTempo (LPDIRECTMUSICSTYLE8 iface, double* pTempo) {
157         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
158         FIXME("(%p, %p): stub\n", This, pTempo);
159         return S_OK;
160 }
161
162 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumPattern (LPDIRECTMUSICSTYLE8 iface, DWORD dwIndex, DWORD dwPatternType, WCHAR* pwszName) {
163         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, StyleVtbl, iface);
164         FIXME("(%p, %ld, %ld, %p): stub\n", This, dwIndex, dwPatternType, pwszName);
165         return S_OK;
166 }
167
168 IDirectMusicStyle8Vtbl DirectMusicStyle8_Style_Vtbl = {
169     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
170         IDirectMusicStyle8Impl_IDirectMusicStyle8_QueryInterface,
171         IDirectMusicStyle8Impl_IDirectMusicStyle8_AddRef,
172         IDirectMusicStyle8Impl_IDirectMusicStyle8_Release,
173         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetBand,
174         IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumBand,
175         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetDefaultBand,
176         IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumMotif,
177         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetMotif,
178         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetDefaultChordMap,
179         IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumChordMap,
180         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetChordMap,
181         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetTimeSignature,
182         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetEmbellishmentLength,
183         IDirectMusicStyle8Impl_IDirectMusicStyle8_GetTempo,
184         IDirectMusicStyle8Impl_IDirectMusicStyle8_EnumPattern
185 };
186
187 /* IDirectMusicStyle8Impl IDirectMusicObject part: */
188 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj) {
189         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
190         return IDirectMusicStyle8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
191 }
192
193 ULONG WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface) {
194         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
195         return IDirectMusicStyle8Impl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
196 }
197
198 ULONG WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface) {
199         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
200         return IDirectMusicStyle8Impl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
201 }
202
203 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
204         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
205         TRACE("(%p, %p)\n", This, pDesc);
206         /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
207         memcpy (pDesc, This->pDesc, This->pDesc->dwSize);
208         return S_OK;
209 }
210
211 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
212         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
213         TRACE("(%p, %p): setting descriptor:\n%s\n", This, pDesc, debugstr_DMUS_OBJECTDESC (pDesc));
214         
215         /* According to MSDN, we should copy only given values, not whole struct */     
216         if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
217                 memcpy (&This->pDesc->guidObject, &pDesc->guidObject, sizeof (pDesc->guidObject));
218         if (pDesc->dwValidData & DMUS_OBJ_CLASS)
219                 memcpy (&This->pDesc->guidClass, &pDesc->guidClass, sizeof (pDesc->guidClass));         
220         if (pDesc->dwValidData & DMUS_OBJ_NAME)
221                 strncpyW (This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
222         if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
223                 strncpyW (This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);             
224         if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
225                 strncpyW (This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);             
226         if (pDesc->dwValidData & DMUS_OBJ_VERSION)
227                 memcpy (&This->pDesc->vVersion, &pDesc->vVersion, sizeof (pDesc->vVersion));                            
228         if (pDesc->dwValidData & DMUS_OBJ_DATE)
229                 memcpy (&This->pDesc->ftDate, &pDesc->ftDate, sizeof (pDesc->ftDate));                          
230         if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
231                 memcpy (&This->pDesc->llMemLength, &pDesc->llMemLength, sizeof (pDesc->llMemLength));                           
232                 memcpy (This->pDesc->pbMemData, pDesc->pbMemData, sizeof (pDesc->pbMemData));
233         }
234         if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
235                 /* according to MSDN, we copy the stream */
236                 IStream_Clone (pDesc->pStream, &This->pDesc->pStream);  
237         }
238         
239         /* add new flags */
240         This->pDesc->dwValidData |= pDesc->dwValidData;
241
242         return S_OK;
243 }
244
245 HRESULT WINAPI IDirectMusicStyle8Impl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) {
246         ICOM_THIS_MULTI(IDirectMusicStyle8Impl, ObjectVtbl, iface);
247         DMUS_PRIVATE_CHUNK Chunk;
248         DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
249         LARGE_INTEGER liMove; /* used when skipping chunks */
250
251         TRACE("(%p, %p, %p)\n", This, pStream, pDesc);
252         
253         /* FIXME: should this be determined from stream? */
254         pDesc->dwValidData |= DMUS_OBJ_CLASS;
255         memcpy (&pDesc->guidClass, &CLSID_DirectMusicStyle, sizeof(CLSID));
256         
257         IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
258         TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
259         switch (Chunk.fccID) {  
260                 case FOURCC_RIFF: {
261                         IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);                             
262                         TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
263                         StreamSize = Chunk.dwSize - sizeof(FOURCC);
264                         StreamCount = 0;
265                         if (Chunk.fccID == DMUS_FOURCC_STYLE_FORM) {
266                                 TRACE_(dmfile)(": style form\n");
267                                 do {
268                                         IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
269                                         StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
270                                         TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
271                                         switch (Chunk.fccID) {
272                                                 case DMUS_FOURCC_GUID_CHUNK: {
273                                                         TRACE_(dmfile)(": GUID chunk\n");
274                                                         pDesc->dwValidData |= DMUS_OBJ_OBJECT;
275                                                         IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL);
276                                                         break;
277                                                 }
278                                                 case DMUS_FOURCC_VERSION_CHUNK: {
279                                                         TRACE_(dmfile)(": version chunk\n");
280                                                         pDesc->dwValidData |= DMUS_OBJ_VERSION;
281                                                         IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL);
282                                                         break;
283                                                 }
284                                                 case DMUS_FOURCC_CATEGORY_CHUNK: {
285                                                         TRACE_(dmfile)(": category chunk\n");
286                                                         pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
287                                                         IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL);
288                                                         break;
289                                                 }
290                                                 case FOURCC_LIST: {
291                                                         IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);                             
292                                                         TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
293                                                         ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
294                                                         ListCount[0] = 0;
295                                                         switch (Chunk.fccID) {
296                                                                 /* evil M$ UNFO list, which can (!?) contain INFO elements */
297                                                                 case DMUS_FOURCC_UNFO_LIST: {
298                                                                         TRACE_(dmfile)(": UNFO list\n");
299                                                                         do {
300                                                                                 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
301                                                                                 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
302                                                                                 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
303                                                                                 switch (Chunk.fccID) {
304                                                                                         /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
305                                              (though strings seem to be valid unicode) */
306                                                                                         case mmioFOURCC('I','N','A','M'):
307                                                                                         case DMUS_FOURCC_UNAM_CHUNK: {
308                                                                                                 TRACE_(dmfile)(": name chunk\n");
309                                                                                                 pDesc->dwValidData |= DMUS_OBJ_NAME;
310                                                                                                 IStream_Read (pStream, pDesc->wszName, Chunk.dwSize, NULL);
311                                                                                                 break;
312                                                                                         }
313                                                                                         case mmioFOURCC('I','A','R','T'):
314                                                                                         case DMUS_FOURCC_UART_CHUNK: {
315                                                                                                 TRACE_(dmfile)(": artist chunk (ignored)\n");
316                                                                                                 liMove.QuadPart = Chunk.dwSize;
317                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
318                                                                                                 break;
319                                                                                         }
320                                                                                         case mmioFOURCC('I','C','O','P'):
321                                                                                         case DMUS_FOURCC_UCOP_CHUNK: {
322                                                                                                 TRACE_(dmfile)(": copyright chunk (ignored)\n");
323                                                                                                 liMove.QuadPart = Chunk.dwSize;
324                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
325                                                                                                 break;
326                                                                                         }
327                                                                                         case mmioFOURCC('I','S','B','J'):
328                                                                                         case DMUS_FOURCC_USBJ_CHUNK: {
329                                                                                                 TRACE_(dmfile)(": subject chunk (ignored)\n");
330                                                                                                 liMove.QuadPart = Chunk.dwSize;
331                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
332                                                                                                 break;
333                                                                                         }
334                                                                                         case mmioFOURCC('I','C','M','T'):
335                                                                                         case DMUS_FOURCC_UCMT_CHUNK: {
336                                                                                                 TRACE_(dmfile)(": comment chunk (ignored)\n");
337                                                                                                 liMove.QuadPart = Chunk.dwSize;
338                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
339                                                                                                 break;
340                                                                                         }
341                                                                                         default: {
342                                                                                                 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
343                                                                                                 liMove.QuadPart = Chunk.dwSize;
344                                                                                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
345                                                                                                 break;                                          
346                                                                                         }
347                                                                                 }
348                                                                                 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
349                                                                         } while (ListCount[0] < ListSize[0]);
350                                                                         break;
351                                                                 }
352                                                                 default: {
353                                                                         TRACE_(dmfile)(": unknown (skipping)\n");
354                                                                         liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
355                                                                         IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
356                                                                         break;                                          
357                                                                 }
358                                                         }
359                                                         break;
360                                                 }       
361                                                 default: {
362                                                         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
363                                                         liMove.QuadPart = Chunk.dwSize;
364                                                         IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
365                                                         break;                                          
366                                                 }
367                                         }
368                                         TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
369                                 } while (StreamCount < StreamSize);
370                                 break;
371                         } else {
372                                 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
373                                 liMove.QuadPart = StreamSize;
374                                 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
375                                 return E_FAIL;
376                         }
377                 
378                         TRACE_(dmfile)(": reading finished\n");
379                         break;
380                 }
381                 default: {
382                         TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
383                         liMove.QuadPart = Chunk.dwSize;
384                         IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
385                         return DMUS_E_INVALIDFILE;
386                 }
387         }       
388         
389         TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc));
390         
391         return S_OK;
392 }
393
394 IDirectMusicObjectVtbl DirectMusicStyle8_Object_Vtbl = {
395   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
396   IDirectMusicStyle8Impl_IDirectMusicObject_QueryInterface,
397   IDirectMusicStyle8Impl_IDirectMusicObject_AddRef,
398   IDirectMusicStyle8Impl_IDirectMusicObject_Release,
399   IDirectMusicStyle8Impl_IDirectMusicObject_GetDescriptor,
400   IDirectMusicStyle8Impl_IDirectMusicObject_SetDescriptor,
401   IDirectMusicStyle8Impl_IDirectMusicObject_ParseDescriptor
402 };
403
404 /* IDirectMusicStyle8Impl IPersistStream part: */
405 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
406   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
407   return IDirectMusicStyle8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
408 }
409
410 ULONG WINAPI IDirectMusicStyle8Impl_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
411   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
412   return IDirectMusicStyle8Impl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
413 }
414
415 ULONG WINAPI IDirectMusicStyle8Impl_IPersistStream_Release (LPPERSISTSTREAM iface) {
416   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
417   return IDirectMusicStyle8Impl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
418 }
419
420 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
421   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
422   TRACE("(%p, %p)\n", This, pClassID);
423   memcpy(pClassID, &CLSID_DirectMusicStyle, sizeof(CLSID));
424   return S_OK;
425 }
426
427 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
428   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
429   FIXME("(%p): stub, always S_FALSE\n", This);
430   return S_FALSE;
431 }
432
433 static HRESULT IDirectMusicStyle8Impl_IPersistStream_LoadBand (LPPERSISTSTREAM iface, IStream* pClonedStream, IDirectMusicBand** ppBand) {
434
435   HRESULT hr = E_FAIL;
436   IPersistStream* pPersistStream = NULL;
437   
438   hr = CoCreateInstance (&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicBand, (LPVOID*) ppBand);
439   if (FAILED(hr)) {
440     ERR(": could not create object\n");
441     return hr;
442   }
443   /* acquire PersistStream interface */
444   hr = IDirectMusicBand_QueryInterface (*ppBand, &IID_IPersistStream, (LPVOID*) &pPersistStream);
445   if (FAILED(hr)) {
446     ERR(": could not acquire IPersistStream\n");
447     return hr;
448   }
449   /* load */
450   hr = IPersistStream_Load (pPersistStream, pClonedStream);
451   if (FAILED(hr)) {
452     ERR(": failed to load object\n");
453     return hr;
454   }
455   
456   /* release all loading-related stuff */
457   IPersistStream_Release (pPersistStream);
458
459   return S_OK;
460 }
461
462 static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm, LPDMUS_PRIVATE_STYLE_MOTIF pNewMotif) {
463   /*ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);*/
464   HRESULT hr = E_FAIL;
465   DMUS_PRIVATE_CHUNK Chunk;
466   DWORD ListSize[3], ListCount[3];
467   LARGE_INTEGER liMove; /* used when skipping chunks */
468
469   DMUS_OBJECTDESC desc;
470
471   if (pChunk->fccID != DMUS_FOURCC_PARTREF_LIST) {
472     ERR_(dmfile)(": %s chunk should be a PARTREF list\n", debugstr_fourcc (pChunk->fccID));
473     return E_FAIL;
474   }  
475
476   ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
477   ListCount[0] = 0;
478
479   do {
480     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
481     ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
482     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
483     switch (Chunk.fccID) {
484     case DMUS_FOURCC_PARTREF_CHUNK: {
485       TRACE_(dmfile)(": PartRef chunk (skipping for now)\n");
486       liMove.QuadPart = Chunk.dwSize;
487       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
488       break;
489     }    
490     case FOURCC_LIST: {
491       IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
492       TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
493       ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
494       ListCount[1] = 0;
495       switch (Chunk.fccID) {  
496       case DMUS_FOURCC_UNFO_LIST: { 
497         TRACE_(dmfile)(": UNFO list\n");
498         do {
499           IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
500           ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
501           TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
502           
503           hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &desc);
504           if (FAILED(hr)) return hr;
505           
506           if (hr == S_FALSE) {
507             switch (Chunk.fccID) {
508             default: {
509               TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
510               liMove.QuadPart = Chunk.dwSize;
511               IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
512               break;                            
513             }
514             }
515           }  
516           TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
517         } while (ListCount[1] < ListSize[1]);
518         break;
519       }
520       default: {
521         TRACE_(dmfile)(": unknown chunk (skipping)\n");
522         liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
523         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
524         break;                                          
525       }
526       }
527       break;
528     }
529     default: {
530       TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
531       liMove.QuadPart = Chunk.dwSize;
532       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
533       break;                                            
534     }
535     }
536     TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
537   } while (ListCount[0] < ListSize[0]);
538
539   return S_OK;
540 }
541
542 static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePartList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
543
544   /*ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);*/
545   HRESULT hr = E_FAIL;
546   DMUS_PRIVATE_CHUNK Chunk;
547   DWORD ListSize[3], ListCount[3];
548   LARGE_INTEGER liMove; /* used when skipping chunks */
549
550   DMUS_OBJECTDESC desc;
551
552   if (pChunk->fccID != DMUS_FOURCC_PART_LIST) {
553     ERR_(dmfile)(": %s chunk should be a PART list\n", debugstr_fourcc (pChunk->fccID));
554     return E_FAIL;
555   }  
556
557   ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
558   ListCount[0] = 0;
559
560   do {
561     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
562     ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
563     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
564     switch (Chunk.fccID) {
565     case DMUS_FOURCC_PART_CHUNK: {
566       TRACE_(dmfile)(": Part chunk (skipping for now)\n");
567       liMove.QuadPart = Chunk.dwSize;
568       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
569       break;
570     }
571     case DMUS_FOURCC_NOTE_CHUNK: { 
572       TRACE_(dmfile)(": Note chunk (skipping for now)\n");
573       liMove.QuadPart = Chunk.dwSize;
574       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
575       break;
576     }
577     case DMUS_FOURCC_CURVE_CHUNK: { 
578       TRACE_(dmfile)(": Curve chunk (skipping for now)\n");
579       liMove.QuadPart = Chunk.dwSize;
580       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
581       break;
582     }
583     case DMUS_FOURCC_MARKER_CHUNK: { 
584       TRACE_(dmfile)(": Marker chunk (skipping for now)\n");
585       liMove.QuadPart = Chunk.dwSize;
586       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
587       break;
588     }
589     case DMUS_FOURCC_RESOLUTION_CHUNK: { 
590       TRACE_(dmfile)(": Resolution chunk (skipping for now)\n");
591       liMove.QuadPart = Chunk.dwSize;
592       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
593       break;
594     }
595     case DMUS_FOURCC_ANTICIPATION_CHUNK: { 
596       TRACE_(dmfile)(": Anticipation chunk (skipping for now)\n");
597       liMove.QuadPart = Chunk.dwSize;
598       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
599       break;
600     }
601     case FOURCC_LIST: {
602       IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
603       TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
604       ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
605       ListCount[1] = 0;
606       switch (Chunk.fccID) { 
607       case DMUS_FOURCC_UNFO_LIST: { 
608         TRACE_(dmfile)(": UNFO list\n");
609         do {
610           IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
611           ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
612           TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
613           
614           hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &desc);
615           if (FAILED(hr)) return hr;
616           
617           if (hr == S_FALSE) {
618             switch (Chunk.fccID) {
619             default: {
620               TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
621               liMove.QuadPart = Chunk.dwSize;
622               IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
623               break;                            
624             }
625             }
626           }  
627           TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
628         } while (ListCount[1] < ListSize[1]);
629         break;
630       }
631       default: {
632         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
633         liMove.QuadPart = Chunk.dwSize;
634         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
635         break;                                          
636       }
637       }
638     break;
639     }
640     default: {
641       TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
642       liMove.QuadPart = Chunk.dwSize;
643       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
644       break;                                            
645     }
646     }
647     TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
648   } while (ListCount[0] < ListSize[0]);
649
650   return S_OK;
651 }
652
653 static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
654
655   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
656   HRESULT hr = E_FAIL;
657   DMUS_PRIVATE_CHUNK Chunk;
658   DWORD ListSize[3], ListCount[3];
659   LARGE_INTEGER liMove; /* used when skipping chunks */
660
661   DWORD dwRythm;
662   DMUS_OBJECTDESC desc;
663   IDirectMusicBand* pBand = NULL;
664   LPDMUS_PRIVATE_STYLE_MOTIF pNewMotif = NULL;
665
666   dwRythm = 0;
667   DM_STRUCT_INIT(&desc);
668
669   if (pChunk->fccID != DMUS_FOURCC_PATTERN_LIST) {
670     ERR_(dmfile)(": %s chunk should be a PATTERN list\n", debugstr_fourcc (pChunk->fccID));
671     return E_FAIL;
672   }  
673
674   ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
675   ListCount[0] = 0;
676
677   do {
678     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
679     ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
680     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
681     switch (Chunk.fccID) {
682     case DMUS_FOURCC_PATTERN_CHUNK: {
683       TRACE_(dmfile)(": Pattern chunk\n");
684       /** alloc new motif entry */
685       pNewMotif = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_MOTIF));
686       list_add_tail (&This->Motifs, &pNewMotif->entry);
687       if (NULL == pNewMotif) {
688         ERR(": no more memory\n");
689         return  E_OUTOFMEMORY;
690       }
691
692       IStream_Read (pStm, &pNewMotif->pattern, Chunk.dwSize, NULL);
693       /** TODO trace pattern */
694
695       /** reset all datas, as a new pattern begin */
696       dwRythm = 0;
697       DM_STRUCT_INIT(&pNewMotif->desc);
698       break;
699     }
700     case DMUS_FOURCC_RHYTHM_CHUNK: { 
701       TRACE_(dmfile)(": Rythm chunk\n");
702       IStream_Read (pStm, &dwRythm, sizeof(DWORD), NULL);
703       TRACE_(dmfile)(" - dwRythm: %lu\n", dwRythm);
704       /** TODO understand why some Chunks have size > 4 */
705       liMove.QuadPart = Chunk.dwSize - sizeof(DWORD);
706       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
707       break;
708     }
709     case DMUS_FOURCC_MOTIFSETTINGS_CHUNK: {
710       TRACE_(dmfile)(": MotifSettigns chunk (skipping for now)\n");
711       IStream_Read (pStm, &pNewMotif->settings, Chunk.dwSize, NULL);
712       /** TODO trace settings */
713       break;
714     }
715     case FOURCC_RIFF: {
716       /**
717        * sould be embededs Bands into pattern
718        */
719       IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
720       TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
721       ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
722       ListCount[1] = 0;
723       switch (Chunk.fccID) {
724       case DMUS_FOURCC_BAND_FORM: { 
725         LPSTREAM pClonedStream = NULL;
726         
727         TRACE_(dmfile)(": BAND RIFF\n");
728         
729         IStream_Clone (pStm, &pClonedStream);
730         
731         liMove.QuadPart = 0;
732         liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
733         IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
734         
735         hr = IDirectMusicStyle8Impl_IPersistStream_LoadBand (iface, pClonedStream, &pBand);
736         if (FAILED(hr)) {
737           ERR(": could not load track\n");
738           return hr;
739         }
740         IStream_Release (pClonedStream);
741         
742         pNewMotif->pBand = pBand;
743         IDirectMusicBand_AddRef(pBand);
744
745         IDirectMusicTrack_Release(pBand); pBand = NULL;  /* now we can release at as it inserted */
746         
747         /** now safe move the cursor */
748         liMove.QuadPart = ListSize[1];
749         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
750         
751         break;
752       }
753       default: {
754         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
755         liMove.QuadPart = ListSize[1];
756         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
757         break;
758       }
759       }
760       break;
761     }
762     case FOURCC_LIST: {
763       IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
764       TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
765       ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
766       ListCount[1] = 0;
767       switch (Chunk.fccID) {
768       case DMUS_FOURCC_UNFO_LIST: { 
769         TRACE_(dmfile)(": UNFO list\n");
770         do {
771           IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
772           ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
773           TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
774           
775           hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, &pNewMotif->desc);
776           if (FAILED(hr)) return hr;
777           
778           if (hr == S_FALSE) {
779             switch (Chunk.fccID) {
780             default: {
781               TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
782               liMove.QuadPart = Chunk.dwSize;
783               IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
784               break;                            
785             }
786             }
787           }  
788           TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
789         } while (ListCount[1] < ListSize[1]);
790         break;
791       }
792       case DMUS_FOURCC_PARTREF_LIST: {
793         TRACE_(dmfile)(": PartRef list\n");
794         hr = IDirectMusicStyle8Impl_IPersistStream_ParsePartRefList (iface, &Chunk, pStm, pNewMotif);
795         if (FAILED(hr)) return hr;
796         break;
797       }
798       default: {
799         TRACE_(dmfile)(": unknown (skipping)\n");
800         liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
801         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
802         break;                                          
803       }
804       }
805       break;    
806     }
807     default: {
808       TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
809       liMove.QuadPart = Chunk.dwSize;
810       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
811       break;                                            
812     }
813     }
814     TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
815   } while (ListCount[0] < ListSize[0]);
816
817   return S_OK;
818 }
819
820 static HRESULT IDirectMusicStyle8Impl_IPersistStream_ParseStyleForm (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
821   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
822
823   HRESULT hr = E_FAIL;
824   DMUS_PRIVATE_CHUNK Chunk;
825   DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
826   LARGE_INTEGER liMove; /* used when skipping chunks */
827
828   IDirectMusicBand* pBand = NULL;
829
830   if (pChunk->fccID != DMUS_FOURCC_STYLE_FORM) {
831     ERR_(dmfile)(": %s chunk should be a STYLE form\n", debugstr_fourcc (pChunk->fccID));
832     return E_FAIL;
833   }  
834
835   StreamSize = pChunk->dwSize - sizeof(FOURCC);
836   StreamCount = 0;
837
838   do {
839     IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
840     StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
841     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
842     
843     hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, This->pDesc);
844     if (FAILED(hr)) return hr;
845
846     if (hr == S_FALSE) {
847       switch (Chunk.fccID) {
848       case DMUS_FOURCC_STYLE_CHUNK: {
849         TRACE_(dmfile)(": Style chunk\n");
850         IStream_Read (pStm, &This->style, sizeof(DMUS_IO_STYLE), NULL);
851         /** TODO dump DMUS_IO_TIMESIG style.timeSig */
852         TRACE_(dmfile)(" - dblTempo: %g\n", This->style.dblTempo);
853         break;
854       }   
855       case FOURCC_RIFF: {
856         /**
857          * sould be embededs Bands into style
858          */
859         IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
860         TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
861         ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
862         ListCount[0] = 0;
863         switch (Chunk.fccID) {
864         case DMUS_FOURCC_BAND_FORM: { 
865           LPSTREAM pClonedStream = NULL;
866           LPDMUS_PRIVATE_STYLE_BAND pNewBand;
867
868           TRACE_(dmfile)(": BAND RIFF\n");
869           
870           IStream_Clone (pStm, &pClonedStream);
871             
872           liMove.QuadPart = 0;
873           liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
874           IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
875           
876           hr = IDirectMusicStyle8Impl_IPersistStream_LoadBand (iface, pClonedStream, &pBand);
877           if (FAILED(hr)) {
878             ERR(": could not load track\n");
879             return hr;
880           }
881           IStream_Release (pClonedStream);
882           
883           pNewBand = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_BAND));
884           if (NULL == pNewBand) {
885             ERR(": no more memory\n");
886             return  E_OUTOFMEMORY;
887           }
888           pNewBand->pBand = pBand;
889           IDirectMusicBand_AddRef(pBand);
890           list_add_tail (&This->Bands, &pNewBand->entry);
891
892           IDirectMusicTrack_Release(pBand); pBand = NULL;  /* now we can release at as it inserted */
893         
894           /** now safe move the cursor */
895           liMove.QuadPart = ListSize[0];
896           IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
897           
898           break;
899         }
900         default: {
901           TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
902           liMove.QuadPart = ListSize[0];
903           IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
904           break;
905         }
906         }
907         break;
908       }
909       case FOURCC_LIST: {
910         IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
911         TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
912         ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
913         ListCount[0] = 0;
914         switch (Chunk.fccID) {
915         case DMUS_FOURCC_UNFO_LIST: { 
916           TRACE_(dmfile)(": UNFO list\n");
917           do {
918             IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
919             ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
920             TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
921             
922             hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, This->pDesc);
923             if (FAILED(hr)) return hr;
924             
925             if (hr == S_FALSE) {
926               switch (Chunk.fccID) {
927               default: {
928                 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
929                 liMove.QuadPart = Chunk.dwSize;
930                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
931                 break;                          
932               }
933               }
934             }  
935             TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
936           } while (ListCount[0] < ListSize[0]);
937           break;
938         }
939         case DMUS_FOURCC_PART_LIST: {
940           TRACE_(dmfile)(": PART list\n");
941           hr = IDirectMusicStyle8Impl_IPersistStream_ParsePartList (iface, &Chunk, pStm);
942           if (FAILED(hr)) return hr;
943           break;
944         }
945         case  DMUS_FOURCC_PATTERN_LIST: {
946           TRACE_(dmfile)(": PATTERN list\n");
947           hr = IDirectMusicStyle8Impl_IPersistStream_ParsePatternList (iface, &Chunk, pStm);
948           if (FAILED(hr)) return hr;
949           break;
950         }
951         default: {
952           TRACE_(dmfile)(": unknown (skipping)\n");
953           liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
954           IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
955           break;                                                
956         }
957         }
958         break;
959       }
960       default: {
961         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
962         liMove.QuadPart = Chunk.dwSize;
963         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
964         break;                                          
965       }
966       }
967     }
968     TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
969   } while (StreamCount < StreamSize);  
970
971   return S_OK;
972 }
973
974 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
975   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
976   
977   DMUS_PRIVATE_CHUNK Chunk;
978   LARGE_INTEGER liMove; /* used when skipping chunks */
979   HRESULT hr;
980
981   FIXME("(%p, %p): Loading\n", This, pStm);
982
983   IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
984   TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
985   switch (Chunk.fccID) {
986   case FOURCC_RIFF: {
987     IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
988     TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
989     switch (Chunk.fccID) {
990     case DMUS_FOURCC_STYLE_FORM: {
991       TRACE_(dmfile)(": Style form\n");
992       hr = IDirectMusicStyle8Impl_IPersistStream_ParseStyleForm (iface, &Chunk, pStm);
993       if (FAILED(hr)) return hr;
994       break;
995     }
996     default: {
997       TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
998       liMove.QuadPart = Chunk.dwSize;
999       IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
1000       return E_FAIL;
1001     }
1002     }
1003     TRACE_(dmfile)(": reading finished\n");
1004     break;
1005   }
1006   default: {
1007     TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
1008     liMove.QuadPart = Chunk.dwSize;
1009     IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
1010     return E_FAIL;
1011   }
1012   }
1013   
1014   return S_OK;
1015 }
1016
1017 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
1018   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
1019   FIXME("(%p): Saving not implemented yet\n", This);
1020   return E_NOTIMPL;
1021 }
1022
1023 HRESULT WINAPI IDirectMusicStyle8Impl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
1024   ICOM_THIS_MULTI(IDirectMusicStyle8Impl, PersistStreamVtbl, iface);
1025   FIXME("(%p, %p): stub\n", This, pcbSize);
1026   return E_NOTIMPL;
1027
1028 }
1029
1030 IPersistStreamVtbl DirectMusicStyle8_PersistStream_Vtbl = {
1031   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1032   IDirectMusicStyle8Impl_IPersistStream_QueryInterface,
1033   IDirectMusicStyle8Impl_IPersistStream_AddRef,
1034   IDirectMusicStyle8Impl_IPersistStream_Release,
1035   IDirectMusicStyle8Impl_IPersistStream_GetClassID,
1036   IDirectMusicStyle8Impl_IPersistStream_IsDirty,
1037   IDirectMusicStyle8Impl_IPersistStream_Load,
1038   IDirectMusicStyle8Impl_IPersistStream_Save,
1039   IDirectMusicStyle8Impl_IPersistStream_GetSizeMax
1040 };
1041
1042 /* for ClassFactory */
1043 HRESULT WINAPI DMUSIC_CreateDirectMusicStyleImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter) {
1044   IDirectMusicStyle8Impl* obj;
1045         
1046   obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicStyle8Impl));
1047   if (NULL == obj) {
1048     *ppobj = (LPVOID) NULL;
1049     return E_OUTOFMEMORY;
1050   }
1051   obj->UnknownVtbl = &DirectMusicStyle8_Unknown_Vtbl;
1052   obj->StyleVtbl = &DirectMusicStyle8_Style_Vtbl;
1053   obj->ObjectVtbl = &DirectMusicStyle8_Object_Vtbl;
1054   obj->PersistStreamVtbl = &DirectMusicStyle8_PersistStream_Vtbl;
1055   obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
1056   DM_STRUCT_INIT(obj->pDesc);
1057   obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
1058   memcpy (&obj->pDesc->guidClass, &CLSID_DirectMusicStyle, sizeof (CLSID));
1059   obj->ref = 0; /* will be inited by QueryInterface */
1060   list_init (&obj->Bands);
1061   list_init (&obj->Motifs);
1062
1063   return IDirectMusicStyle8Impl_IUnknown_QueryInterface ((LPUNKNOWN)&obj->UnknownVtbl, lpcGUID, ppobj);
1064 }