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