Some fixes in dmband loading.
[wine] / dlls / dmband / band.c
1 /* IDirectMusicBand Implementation
2  *
3  * Copyright (C) 2003 Rok Mandeljc
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include <stdarg.h>
21
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winuser.h"
25 #include "wingdi.h"
26 #include "wine/debug.h"
27
28 #include "dmband_private.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(dmband);
31 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
32
33 /*****************************************************************************
34  * IDirectMusicBandImpl implementation
35  */
36 /* IDirectMusicBand IUnknown part: */
37 HRESULT WINAPI IDirectMusicBandImpl_QueryInterface (LPDIRECTMUSICBAND iface, REFIID riid, LPVOID *ppobj)
38 {
39         ICOM_THIS(IDirectMusicBandImpl,iface);
40
41         if (IsEqualGUID(riid, &IID_IUnknown) || 
42             IsEqualGUID(riid, &IID_IDirectMusicBand)) {
43                 IDirectMusicBandImpl_AddRef(iface);
44                 *ppobj = This;
45                 return S_OK;
46         }
47         WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
48         return E_NOINTERFACE;
49 }
50
51 ULONG WINAPI IDirectMusicBandImpl_AddRef (LPDIRECTMUSICBAND iface)
52 {
53         ICOM_THIS(IDirectMusicBandImpl,iface);
54         TRACE("(%p) : AddRef from %ld\n", This, This->ref);
55         return ++(This->ref);
56 }
57
58 ULONG WINAPI IDirectMusicBandImpl_Release (LPDIRECTMUSICBAND iface)
59 {
60         ICOM_THIS(IDirectMusicBandImpl,iface);
61         ULONG ref = --This->ref;
62         TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
63         if (ref == 0) {
64                 HeapFree(GetProcessHeap(), 0, This);
65         }
66         return ref;
67 }
68
69 /* IDirectMusicBand IDirectMusicBand part: */
70 HRESULT WINAPI IDirectMusicBandImpl_CreateSegment (LPDIRECTMUSICBAND iface, IDirectMusicSegment** ppSegment)
71 {
72         ICOM_THIS(IDirectMusicBandImpl,iface);
73
74         FIXME("(%p, %p): stub\n", This, ppSegment);
75
76         return S_OK;
77 }
78
79 HRESULT WINAPI IDirectMusicBandImpl_Download (LPDIRECTMUSICBAND iface, IDirectMusicPerformance* pPerformance)
80 {
81         ICOM_THIS(IDirectMusicBandImpl,iface);
82
83         FIXME("(%p, %p): stub\n", This, pPerformance);
84
85         return S_OK;
86 }
87
88 HRESULT WINAPI IDirectMusicBandImpl_Unload (LPDIRECTMUSICBAND iface, IDirectMusicPerformance* pPerformance)
89 {
90         ICOM_THIS(IDirectMusicBandImpl,iface);
91
92         FIXME("(%p, %p): stub\n", This, pPerformance);
93
94         return S_OK;
95 }
96
97 ICOM_VTABLE(IDirectMusicBand) DirectMusicBand_Vtbl =
98 {
99     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
100         IDirectMusicBandImpl_QueryInterface,
101         IDirectMusicBandImpl_AddRef,
102         IDirectMusicBandImpl_Release,
103         IDirectMusicBandImpl_CreateSegment,
104         IDirectMusicBandImpl_Download,
105         IDirectMusicBandImpl_Unload
106 };
107
108 /* for ClassFactory */
109 HRESULT WINAPI DMUSIC_CreateDirectMusicBand (LPCGUID lpcGUID, LPDIRECTMUSICBAND* ppDMBand, LPUNKNOWN pUnkOuter)
110 {
111         IDirectMusicBandImpl* dmband;
112         
113         if (IsEqualGUID (lpcGUID, &IID_IDirectMusicBand)) {
114                 dmband = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicBandImpl));
115                 if (NULL == dmband) {
116                         *ppDMBand = (LPDIRECTMUSICBAND) NULL;
117                         return E_OUTOFMEMORY;
118                 }
119                 dmband->lpVtbl = &DirectMusicBand_Vtbl;
120                 dmband->ref = 1;
121                 list_init (&dmband->Instruments);
122                 *ppDMBand = (LPDIRECTMUSICBAND) dmband;
123                 return S_OK;
124         }
125         WARN("No interface found\n");
126         
127         return E_NOINTERFACE;
128 }
129
130 /*****************************************************************************
131  * IDirectMusicBandObject implementation
132  */
133 /* IDirectMusicBandObject IUnknown part: */
134 HRESULT WINAPI IDirectMusicBandObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj)
135 {
136         ICOM_THIS(IDirectMusicBandObject,iface);
137
138         if (IsEqualGUID (riid, &IID_IUnknown) 
139                 || IsEqualGUID(riid, &IID_IDirectMusicObject)) {
140                 IDirectMusicBandObject_AddRef(iface);
141                 *ppobj = This;
142                 return S_OK;
143         } else if (IsEqualGUID (riid, &IID_IPersistStream)) {
144                 IPersistStream_AddRef ((LPPERSISTSTREAM)This->pStream);
145                 *ppobj = (LPPERSISTSTREAM)This->pStream;
146                 return S_OK;
147         } else if (IsEqualGUID (riid, &IID_IDirectMusicBand)) {
148                 IDirectMusicBand_AddRef ((LPDIRECTMUSICBAND)This->pBand);
149                 *ppobj = (LPDIRECTMUSICBAND)This->pBand;
150                 return S_OK;
151         }
152         WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
153         return E_NOINTERFACE;
154 }
155
156 ULONG WINAPI IDirectMusicBandObject_AddRef (LPDIRECTMUSICOBJECT iface)
157 {
158         ICOM_THIS(IDirectMusicBandObject,iface);
159         TRACE("(%p) : AddRef from %ld\n", This, This->ref);
160         return ++(This->ref);
161 }
162
163 ULONG WINAPI IDirectMusicBandObject_Release (LPDIRECTMUSICOBJECT iface)
164 {
165         ICOM_THIS(IDirectMusicBandObject,iface);
166         ULONG ref = --This->ref;
167         TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
168         if (ref == 0)
169         {
170                 HeapFree(GetProcessHeap(), 0, This);
171         }
172         return ref;
173 }
174
175 /* IDirectMusicBandObject IDirectMusicObject part: */
176 HRESULT WINAPI IDirectMusicBandObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc)
177 {
178         ICOM_THIS(IDirectMusicBandObject,iface);
179
180         TRACE("(%p, %p)\n", This, pDesc);
181         pDesc = This->pDesc;
182         
183         return S_OK;
184 }
185
186 HRESULT WINAPI IDirectMusicBandObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc)
187 {
188         ICOM_THIS(IDirectMusicBandObject,iface);
189
190         TRACE("(%p, %p)\n", This, pDesc);
191         This->pDesc = pDesc;
192
193         return S_OK;
194 }
195
196 HRESULT WINAPI IDirectMusicBandObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc)
197 {
198         ICOM_THIS(IDirectMusicBandObject,iface);
199
200         FIXME("(%p, %p, %p): stub\n", This, pStream, pDesc);
201
202         return S_OK;
203 }
204
205 ICOM_VTABLE(IDirectMusicObject) DirectMusicBandObject_Vtbl =
206 {
207     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
208         IDirectMusicBandObject_QueryInterface,
209         IDirectMusicBandObject_AddRef,
210         IDirectMusicBandObject_Release,
211         IDirectMusicBandObject_GetDescriptor,
212         IDirectMusicBandObject_SetDescriptor,
213         IDirectMusicBandObject_ParseDescriptor
214 };
215
216 /* for ClassFactory */
217 HRESULT WINAPI DMUSIC_CreateDirectMusicBandObject (LPCGUID lpcGUID, LPDIRECTMUSICOBJECT* ppObject, LPUNKNOWN pUnkOuter)
218 {
219         IDirectMusicBandObject *obj;
220         
221         TRACE("(%p,%p,%p)\n", lpcGUID, ppObject, pUnkOuter);
222         if (IsEqualGUID (lpcGUID, &IID_IDirectMusicObject)) {
223                 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicBandObject));
224                 if (NULL == obj) {
225                         *ppObject = (LPDIRECTMUSICOBJECT) NULL;
226                         return E_OUTOFMEMORY;
227                 }
228                 obj->lpVtbl = &DirectMusicBandObject_Vtbl;
229                 obj->ref = 1;
230                 /* prepare IPersistStream */
231                 obj->pStream = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(IDirectMusicBandObjectStream));
232                 obj->pStream->lpVtbl = &DirectMusicBandObjectStream_Vtbl;
233                 obj->pStream->ref = 1;  
234                 obj->pStream->pParentObject = obj;
235                 /* prepare IDirectMusicBand */
236                 DMUSIC_CreateDirectMusicBand (&IID_IDirectMusicBand, (LPDIRECTMUSICBAND*)&obj->pBand, NULL);
237                 obj->pBand->pObject = obj;
238                 *ppObject = (LPDIRECTMUSICOBJECT) obj;
239                 return S_OK;
240         }
241         WARN("No interface found\n");
242         
243         return E_NOINTERFACE;
244 }
245         
246 /*****************************************************************************
247  * IDirectMusicBandObjectStream implementation
248  */
249 /* IDirectMusicBandObjectStream IUnknown part: */
250 HRESULT WINAPI IDirectMusicBandObjectStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj)
251 {
252         ICOM_THIS(IDirectMusicBandObjectStream,iface);
253
254         if (IsEqualGUID(riid, &IID_IUnknown)
255                 || IsEqualGUID(riid, &IID_IPersistStream)) {
256                 IDirectMusicBandObjectStream_AddRef(iface);
257                 *ppobj = This;
258                 return S_OK;
259         }
260         WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
261         return E_NOINTERFACE;
262 }
263
264 ULONG WINAPI IDirectMusicBandObjectStream_AddRef (LPPERSISTSTREAM iface)
265 {
266         ICOM_THIS(IDirectMusicBandObjectStream,iface);
267         TRACE("(%p) : AddRef from %ld\n", This, This->ref);
268         return ++(This->ref);
269 }
270
271 ULONG WINAPI IDirectMusicBandObjectStream_Release (LPPERSISTSTREAM iface)
272 {
273         ICOM_THIS(IDirectMusicBandObjectStream,iface);
274         ULONG ref = --This->ref;
275         TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
276         if (ref == 0) {
277                 HeapFree(GetProcessHeap(), 0, This);
278         }
279         return ref;
280 }
281
282 /* IDirectMusicBandObjectStream IPersist part: */
283 HRESULT WINAPI IDirectMusicBandObjectStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID)
284 {
285         return E_NOTIMPL;
286 }
287
288 /* IDirectMusicBandObjectStream IPersistStream part: */
289 HRESULT WINAPI IDirectMusicBandObjectStream_IsDirty (LPPERSISTSTREAM iface)
290 {
291         return E_NOTIMPL;
292 }
293
294 HRESULT WINAPI IDirectMusicBandObjectStream_Load (LPPERSISTSTREAM iface, IStream* pStm)
295 {
296         ICOM_THIS(IDirectMusicBandObjectStream,iface);
297         FOURCC chunkID;
298         DWORD chunkSize, StreamSize, StreamCount, ListSize[3], ListCount[3];
299         LARGE_INTEGER liMove; /* used when skipping chunks */
300         DMUS_IO_REFERENCE tempReferenceHeader;
301         DMUS_OBJECTDESC ObjDesc;
302         IDirectMusicBandImpl* pBand = This->pParentObject->pBand; /* that's where we load data to */
303         LPDIRECTMUSICLOADER pLoader;
304         LPDIRECTMUSICGETLOADER pGetLoader;
305         
306         IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
307         IStream_Read (pStm, &chunkSize, sizeof(DWORD), NULL);
308         TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID), chunkSize);
309         switch (chunkID) {      
310                 case FOURCC_RIFF: {
311                         IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);                            
312                         TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(chunkID));
313                         StreamSize = chunkSize - sizeof(FOURCC);
314                         StreamCount = 0;
315                         switch (chunkID) {
316                                 case DMUS_FOURCC_BAND_FORM: {
317                                         TRACE_(dmfile)(": band  form\n");
318                                         do {
319                                                 IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
320                                                 IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
321                                                 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
322                                                 TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID), chunkSize);
323                                                 switch (chunkID) {
324                                                         case DMUS_FOURCC_GUID_CHUNK: {
325                                                                 TRACE_(dmfile)(": GUID chunk\n");
326                                                                 IStream_Read (pStm, pBand->guidID, chunkSize, NULL);
327                                                                 break;
328                                                         }
329                                                         case DMUS_FOURCC_VERSION_CHUNK: {
330                                                                 TRACE_(dmfile)(": version chunk\n");
331                                                                 IStream_Read (pStm, pBand->vVersion, chunkSize, NULL);
332                                                                 break;
333                                                         }
334                                                         case FOURCC_LIST: {
335                                                                 IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);                            
336                                                                 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunkID));
337                                                                 ListSize[0] = chunkSize - sizeof(FOURCC);
338                                                                 ListCount[0] = 0;
339                                                                 switch (chunkID) {
340                                                                         case DMUS_FOURCC_UNFO_LIST: {
341                                                                                 TRACE_(dmfile)(": UNFO list\n");
342                                                                                 do {
343                                                                                         IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
344                                                                                         IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
345                                                                                         ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
346                                                                                         TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID), chunkSize);
347                                                                                         switch (chunkID) {
348                                                                                                 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
349                                               (though strings seem to be valid unicode) */
350                                                                                                 case mmioFOURCC('I','N','A','M'):
351                                                                                                 case DMUS_FOURCC_UNAM_CHUNK: {
352                                                                                                         TRACE_(dmfile)(": name chunk\n");
353                                                                                                         pBand->wzName = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, chunkSize);
354                                                                                                         IStream_Read (pStm, pBand->wzName, chunkSize, NULL);
355                                                                                                         break;
356                                                                                                 }
357                                                                                                 case mmioFOURCC('I','A','R','T'):
358                                                                                                 case DMUS_FOURCC_UART_CHUNK: {
359                                                                                                         TRACE_(dmfile)(": artist chunk\n");
360                                                                                                         pBand->wzArtist = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, chunkSize);
361                                                                                                         IStream_Read (pStm, pBand->wzArtist, chunkSize, NULL);
362                                                                                                         break;
363                                                                                                 }
364                                                                                                 case mmioFOURCC('I','C','O','P'):
365                                                                                                 case DMUS_FOURCC_UCOP_CHUNK: {
366                                                                                                         TRACE_(dmfile)(": copyright chunk\n");
367                                                                                                         pBand->wzCopyright = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, chunkSize);
368                                                                                                         IStream_Read (pStm, pBand->wzCopyright, chunkSize, NULL);
369                                                                                                         break;
370                                                                                                 }
371                                                                                                 case mmioFOURCC('I','S','B','J'):
372                                                                                                 case DMUS_FOURCC_USBJ_CHUNK: {
373                                                                                                         TRACE_(dmfile)(": subject chunk\n");
374                                                                                                         pBand->wzSubject = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, chunkSize);
375                                                                                                         IStream_Read (pStm, pBand->wzSubject, chunkSize, NULL);
376                                                                                                         break;
377                                                                                                 }
378                                                                                                 case mmioFOURCC('I','C','M','T'):
379                                                                                                 case DMUS_FOURCC_UCMT_CHUNK: {
380                                                                                                         TRACE_(dmfile)(": comment chunk\n");
381                                                                                                         pBand->wzComment = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, chunkSize);
382                                                                                                         IStream_Read (pStm, pBand->wzComment, chunkSize, NULL);
383                                                                                                         break;
384                                                                                                 }
385                                                                                                 default: {
386                                                                                                         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
387                                                                                                         liMove.QuadPart = chunkSize;
388                                                                                                         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
389                                                                                                         break;                                          
390                                                                                                 }
391                                                                                         }
392                                                                                         TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
393                                                                                 } while (ListCount[0] < ListSize[0]);
394                                                                                 break;
395                                                                         }
396                                                                         case DMUS_FOURCC_INSTRUMENTS_LIST: {
397                                                                                 TRACE_(dmfile)(": instruments list\n");
398                                                                                 do {
399                                                                                         IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
400                                                                                         IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
401                                                                                         ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
402                                                                                         TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID), chunkSize);
403                                                                                         switch (chunkID) {
404                                                                                                 case FOURCC_LIST: {
405                                                                                                         IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);                            
406                                                                                                         TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunkID));
407                                                                                                         ListSize[1] = chunkSize - sizeof(FOURCC);
408                                                                                                         ListCount[1] = 0;
409                                                                                                         switch (chunkID) {
410                                                                                                                 case DMUS_FOURCC_INSTRUMENT_LIST: {
411                                                                                                                         /* init new instrument list entry */
412                                                                                                                         LPDMUS_PRIVATE_INSTRUMENT pNewInstrument = (LPDMUS_PRIVATE_INSTRUMENT) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_INSTRUMENT));
413                                                                                                                         TRACE_(dmfile)(": instrument list\n");
414                                                                                                                         do {
415                                                                                                                                 IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
416                                                                                                                                 IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
417                                                                                                                                 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
418                                                                                                                                 TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID), chunkSize);
419                                                                                                                                 switch (chunkID) {
420                                                                                                                                         case DMUS_FOURCC_INSTRUMENT_CHUNK: {
421                                                                                                                                                 TRACE_(dmfile)(": band instrument header\n");
422                                                                                                                                                 IStream_Read (pStm, &pNewInstrument->pInstrument, chunkSize, NULL);
423                                                                                                                                                 break;
424                                                                                                                                         }
425                                                                                                                                         case FOURCC_LIST: {
426                                                                                                                                                 IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);                            
427                                                                                                                                                 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunkID));
428                                                                                                                                                 ListSize[2] = chunkSize - sizeof(FOURCC);
429                                                                                                                                                 ListCount[2] = 0;
430                                                                                                                                                 switch (chunkID) {
431                                                                                                                                                         case DMUS_FOURCC_REF_LIST: {
432                                                                                                                                                                 TRACE_(dmfile)(": reference list\n");
433                                                                                                                                                                 ZeroMemory ((LPVOID)&ObjDesc, sizeof(DMUS_OBJECTDESC));
434                                                                                                                                                                 do {
435                                                                                                                                                                         IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
436                                                                                                                                                                         IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
437                                                                                                                                                                         ListCount[2] += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
438                                                                                                                                                                         TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID), chunkSize);
439                                                                                                                                                                         switch (chunkID) {
440                                                                                                                                                                                 case DMUS_FOURCC_REF_CHUNK: {
441                                                                                                                                                                                         TRACE_(dmfile)(": reference header chunk\n");
442                                                                                                                                                                                         IStream_Read (pStm, &tempReferenceHeader, chunkSize, NULL);
443                                                                                                                                                                                         /* copy retrieved data to DMUS_OBJECTDESC */
444                                                                                                                                                                                         ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC);
445                                                                                                                                                                                         ObjDesc.guidClass = tempReferenceHeader.guidClassID;
446                                                                                                                                                                                         ObjDesc.dwValidData = tempReferenceHeader.dwValidData;
447                                                                                                                                                                                         break;                                                                                                                                  
448                                                                                                                                                                                 }
449                                                                                                                                                                                 case DMUS_FOURCC_GUID_CHUNK: {
450                                                                                                                                                                                         TRACE_(dmfile)(": guid chunk\n");
451                                                                                                                                                                                         IStream_Read (pStm, &ObjDesc.guidObject, chunkSize, NULL);
452                                                                                                                                                                                         break;
453                                                                                                                                                                                 }
454                                                                                                                                                                                 case DMUS_FOURCC_DATE_CHUNK: {
455                                                                                                                                                                                         TRACE_(dmfile)(": file date chunk\n");
456                                                                                                                                                                                         IStream_Read (pStm, &ObjDesc.ftDate, chunkSize, NULL);
457                                                                                                                                                                                         break;
458                                                                                                                                                                                 }
459                                                                                                                                                                                 case DMUS_FOURCC_NAME_CHUNK: {
460                                                                                                                                                                                         TRACE_(dmfile)(": name chunk\n");
461                                                                                                                                                                                         IStream_Read (pStm, &ObjDesc.wszName, chunkSize, NULL);
462                                                                                                                                                                                         break;
463                                                                                                                                                                                 }
464                                                                                                                                                                                 case DMUS_FOURCC_FILE_CHUNK: {
465                                                                                                                                                                                         TRACE_(dmfile)(": file name chunk\n");
466                                                                                                                                                                                         IStream_Read (pStm, &ObjDesc.wszFileName, chunkSize, NULL);
467                                                                                                                                                                                         break;
468                                                                                                                                                                                 }
469                                                                                                                                                                                 case DMUS_FOURCC_CATEGORY_CHUNK: {
470                                                                                                                                                                                         TRACE_(dmfile)(": category chunk\n");
471                                                                                                                                                                                         IStream_Read (pStm, &ObjDesc.wszCategory, chunkSize, NULL);
472                                                                                                                                                                                         break;
473                                                                                                                                                                                 }
474                                                                                                                                                                                 case DMUS_FOURCC_VERSION_CHUNK: {
475                                                                                                                                                                                         TRACE_(dmfile)(": version chunk\n");
476                                                                                                                                                                                         IStream_Read (pStm, &ObjDesc.vVersion, chunkSize, NULL);
477                                                                                                                                                                                         break;
478                                                                                                                                                                                 }
479                                                                                                                                                                                 default: {
480                                                                                                                                                                                         TRACE_(dmfile)(": unknown chunk (skipping)\n");
481                                                                                                                                                                                         liMove.QuadPart = chunkSize;
482                                                                                                                                                                                         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip this chunk */
483                                                                                                                                                                                         break;
484                                                                                                                                                                                 }
485                                                                                                                                                                         }
486                                                                                                                                                                         TRACE_(dmfile)(": ListCount[2] = %ld < ListSize[2] = %ld\n", ListCount[2], ListSize[2]);
487                                                                                                                                                                 } while (ListCount[2] < ListSize[2]);
488                                                                                                                                                                 /* let's see what we have */
489                                                                                                                                                                 TRACE_(dmfile)(": (READ): reference: dwSize = %ld; dwValidData = %ld; guidObject = %s; guidClass = %s; \
490 vVersion = %08lx,%08lx; wszName = %s; wszCategory = %s; wszFileName = %s\n", ObjDesc.dwSize, ObjDesc.dwValidData, debugstr_guid(&ObjDesc.guidObject), debugstr_guid(&ObjDesc.guidClass),
491 ObjDesc.vVersion.dwVersionMS, ObjDesc.vVersion.dwVersionLS, debugstr_w(ObjDesc.wszName), debugstr_w(ObjDesc.wszCategory), debugstr_w(ObjDesc.wszFileName));
492                                                                                                                                                                 /* now, let's convience loader to load reference */                                                             
493                                                                                                                                                                 if (IStream_QueryInterface (pStm, &IID_IDirectMusicGetLoader, (LPVOID*)&pGetLoader) == S_OK) {
494                                                                                                                                                                         if (IDirectMusicGetLoader_GetLoader (pGetLoader, &pLoader) == S_OK) {
495                                                                                                                                                                                 /* load referenced object */
496                                                                                                                                                                                 IDirectMusicObject* pObject;
497                                                                                                                                                                                 if(FAILED(IDirectMusicLoader_GetObject (pLoader, &ObjDesc, &IID_IDirectMusicObject, (LPVOID*)&pObject)))
498                                                                                                                                                                                 /* acquire collection from loaded referenced object */
499                                                                                                                                                                                 if(FAILED(IDirectMusicObject_QueryInterface (pObject, &IID_IDirectMusicCollection, (LPVOID*)&pNewInstrument->ppReferenceCollection)))
500                                                                                                                                                                                         IDirectMusicLoader_Release (pLoader);
501                                                                                                                                                                         }
502                                                                                                                                                                         IDirectMusicGetLoader_Release (pGetLoader);                                                                                     
503                                                                                                                                                                 } else {
504                                                                                                                                                                         ERR("Could not get IDirectMusicGetLoader... reference will not be loaded :(\n");
505                                                                                                                                                                         /* E_FAIL */
506                                                                                                                                                                 }
507                                                                                                                                                         break;
508                                                                                                                                                 }
509                                                                                                                                                 default: {
510                                                                                                                                                         TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
511                                                                                                                                                         return E_FAIL;
512                                                                                                                                                 }
513                                                                                                                                         }
514                                                                                                                                         break;
515                                                                                                                                 }
516                                                                                                                                         default: {
517                                                                                                                                                 TRACE_(dmfile)(": unknown chunk (skipping)\n");
518                                                                                                                                                 liMove.QuadPart = chunkSize;
519                                                                                                                                                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip this chunk */
520                                                                                                                                                 break;                                  
521                                                                                                                                         }       
522                                                                                                                                 }
523                                                                                                                                 TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
524                                                                                                                         } while (ListCount[1] < ListSize[1]);
525                                                                                                                         /* hmm... in dxdiag segment's band there aren't any references, but loader still desperatly
526                                                                                                                        loads default collection... does that mean that if there is no reference, use default?
527                                                                                                                     */
528                                                                                                                         if (!pNewInstrument->ppReferenceCollection) {
529                                                                                                                                 TRACE_(dmfile)(": (READ): loading default collection (as no specific reference was made)\n");
530                                                                                                                                 ZeroMemory ((LPVOID)&ObjDesc, sizeof(DMUS_OBJECTDESC));
531                                                                                                                                 ObjDesc.dwSize = sizeof(DMUS_OBJECTDESC);
532                                                                                                                         ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_OBJECT;
533                                                                                                                                 ObjDesc.guidObject = GUID_DefaultGMCollection;
534                                                                                                                                 ObjDesc.guidClass = CLSID_DirectMusicCollection;
535                                                                                                                                 if (SUCCEEDED(IStream_QueryInterface (pStm, &IID_IDirectMusicGetLoader, (LPVOID*)&pGetLoader))) {
536                                                                                                                                         if (SUCCEEDED(IDirectMusicGetLoader_GetLoader (pGetLoader, &pLoader))) {
537                                                                                                                                                 IDirectMusicObject* pObject;
538                                                                                                                                                 if (SUCCEEDED(IDirectMusicLoader_GetObject (pLoader, &ObjDesc, &IID_IDirectMusicObject, (LPVOID*)&pObject))) {
539                                                                                                                                                         IDirectMusicObject_QueryInterface (pObject, &IID_IDirectMusicCollection, (LPVOID*)&pNewInstrument->ppReferenceCollection);
540                                                                                                                                                         IDirectMusicLoader_Release (pLoader);
541                                                                                                                                                 }
542                                                                                                                                         }
543                                                                                                                                         IDirectMusicGetLoader_Release (pGetLoader);                                                                                     
544                                                                                                                                 } else {
545                                                                                                                                         ERR("Could not get IDirectMusicGetLoader... reference will not be loaded :(\n");
546                                                                                                                                         /* E_FAIL */
547                                                                                                                                 }
548                                                                                                                         }
549                                                                                                                         list_add_tail (&This->pParentObject->pBand->Instruments, &pNewInstrument->entry);
550                                                                                                                         break;
551                                                                                                                 }
552                                                                                                                 default: {
553                                                                                                                         TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
554                                                                                                                         return E_FAIL;
555                                                                                                                 }
556                                                                                                         }
557                                                                                                         break;
558                                                                                                 }
559                                                                                                 default: {
560                                                                                                         TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
561                                                                                                         liMove.QuadPart = chunkSize;
562                                                                                                         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
563                                                                                                         break;                                          
564                                                                                                 }
565                                                                                         }
566                                                                                         TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
567                                                                                 } while (ListCount[0] < ListSize[0]);
568                                                                                 break;
569                                                                         }
570                                                                         default: {
571                                                                                 TRACE_(dmfile)(": unknown (skipping)\n");
572                                                                                 liMove.QuadPart = chunkSize - sizeof(FOURCC);
573                                                                                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
574                                                                                 break;                                          
575                                                                         }
576                                                                 }
577                                                                 break;
578                                                         }       
579                                                         default: {
580                                                                 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
581                                                                 liMove.QuadPart = chunkSize;
582                                                                 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
583                                                                 break;                                          
584                                                         }
585                                                 }
586                                                 TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
587                                         } while (StreamCount < StreamSize);
588                                         break;
589                                 }
590                                 default: {
591                                         TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
592                                         liMove.QuadPart = StreamSize;
593                                         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
594                                         return E_FAIL;
595                                 }
596                         }
597                         TRACE_(dmfile)(": reading finished\n");
598                         break;
599                 }
600                 default: {
601                         TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
602                         liMove.QuadPart = chunkSize;
603                         IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
604                         return E_FAIL;
605                 }
606         }
607         
608         /* DEBUG: dumps whole band object tree: */
609         if (TRACE_ON(dmband)) {
610                 int r = 0;
611                 DMUS_PRIVATE_INSTRUMENT *tmpEntry;
612                 struct list *listEntry;
613
614                 TRACE("*** IDirectMusicBand (%p) ***\n", pBand);
615                 if (pBand->guidID)
616                         TRACE(" - GUID = %s\n", debugstr_guid(pBand->guidID));
617                 if (pBand->vVersion)
618                         TRACE(" - Version = %i,%i,%i,%i\n", (pBand->vVersion->dwVersionMS >> 8) && 0x0000FFFF, pBand->vVersion->dwVersionMS && 0x0000FFFF, \
619                                 (pBand->vVersion->dwVersionLS >> 8) && 0x0000FFFF, pBand->vVersion->dwVersionLS && 0x0000FFFF);
620                 if (pBand->wzName)
621                         TRACE(" - Name = %s\n", debugstr_w(pBand->wzName));
622                 if (pBand->wzArtist)            
623                         TRACE(" - Artist = %s\n", debugstr_w(pBand->wzArtist));
624                 if (pBand->wzCopyright)
625                         TRACE(" - Copyright = %s\n", debugstr_w(pBand->wzCopyright));
626                 if (pBand->wzSubject)
627                         TRACE(" - Subject = %s\n", debugstr_w(pBand->wzSubject));
628                 if (pBand->wzComment)
629                         TRACE(" - Comment = %s\n", debugstr_w(pBand->wzComment));
630                 
631                 TRACE(" - Instruments:\n");
632                 
633                 LIST_FOR_EACH (listEntry, &This->pParentObject->pBand->Instruments) {
634                         tmpEntry = LIST_ENTRY( listEntry, DMUS_PRIVATE_INSTRUMENT, entry );
635                         TRACE("    - Instrument[%i]:\n", r);
636                         TRACE("       - Instrument header:\n");
637                         TRACE("          - dwPatch = %ld\n", tmpEntry->pInstrument.dwPatch);
638                         TRACE("          - dwAssignPatch = %ld\n", tmpEntry->pInstrument.dwAssignPatch);
639                         TRACE("          - dwNoteRanges[4] = %ln\n", tmpEntry->pInstrument.dwNoteRanges);
640                         TRACE("          - dwPChannel = %ld\n", tmpEntry->pInstrument.dwPChannel);
641                         TRACE("          - dwFlags = %ld\n", tmpEntry->pInstrument.dwFlags);
642                         TRACE("          - bPan = %i\n", tmpEntry->pInstrument.bPan);
643                         TRACE("          - bVolume = %i\n", tmpEntry->pInstrument.bVolume);
644                         TRACE("          - nTranspose = %i\n", tmpEntry->pInstrument.nTranspose);
645                         TRACE("          - dwChannelPriority = %ld\n", tmpEntry->pInstrument.dwChannelPriority);
646                         TRACE("          - nPitchBendRange = %i\n", tmpEntry->pInstrument.nPitchBendRange);
647                         TRACE("       - Reference collection: %p\n", tmpEntry->ppReferenceCollection);
648                         r++;
649                 }
650         }
651
652         return S_OK;
653 }
654
655 HRESULT WINAPI IDirectMusicBandObjectStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty)
656 {
657         return E_NOTIMPL;
658 }
659
660 HRESULT WINAPI IDirectMusicBandObjectStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize)
661 {
662         return E_NOTIMPL;
663 }
664
665 ICOM_VTABLE(IPersistStream) DirectMusicBandObjectStream_Vtbl =
666 {
667     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
668         IDirectMusicBandObjectStream_QueryInterface,
669         IDirectMusicBandObjectStream_AddRef,
670         IDirectMusicBandObjectStream_Release,
671         IDirectMusicBandObjectStream_GetClassID,
672         IDirectMusicBandObjectStream_IsDirty,
673         IDirectMusicBandObjectStream_Load,
674         IDirectMusicBandObjectStream_Save,
675         IDirectMusicBandObjectStream_GetSizeMax
676 };