3 * Copyright (C) 2003-2004 Rok Mandeljc
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "dmime_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(dmime
);
23 WINE_DECLARE_DEBUG_CHANNEL(dmfile
);
25 /*****************************************************************************
26 * IDirectMusicGraphImpl implementation
28 /* IDirectMusicGraphImpl IUnknown part: */
29 static HRESULT WINAPI
IDirectMusicGraphImpl_IUnknown_QueryInterface (LPUNKNOWN iface
, REFIID riid
, LPVOID
*ppobj
) {
30 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, UnknownVtbl
, iface
);
31 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), ppobj
);
33 if (IsEqualIID (riid
, &IID_IUnknown
)) {
34 *ppobj
= (LPVOID
)&This
->UnknownVtbl
;
35 IUnknown_AddRef (iface
);
37 } else if (IsEqualIID (riid
, &IID_IDirectMusicGraph
)) {
38 *ppobj
= (LPVOID
)&This
->GraphVtbl
;
39 IUnknown_AddRef (iface
);
41 } else if (IsEqualIID (riid
, &IID_IDirectMusicObject
)) {
42 *ppobj
= (LPVOID
)&This
->ObjectVtbl
;
43 IUnknown_AddRef (iface
);
45 } else if (IsEqualIID (riid
, &IID_IPersistStream
)) {
46 *ppobj
= (LPVOID
)&This
->PersistStreamVtbl
;
47 IUnknown_AddRef (iface
);
51 WARN("(%p, %s, %p): not found\n", This
, debugstr_guid(riid
), ppobj
);
55 static ULONG WINAPI
IDirectMusicGraphImpl_IUnknown_AddRef (LPUNKNOWN iface
) {
56 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, UnknownVtbl
, iface
);
57 ULONG ref
= InterlockedIncrement(&This
->ref
);
59 TRACE("(%p): AddRef from %ld\n", This
, ref
- 1);
66 static ULONG WINAPI
IDirectMusicGraphImpl_IUnknown_Release (LPUNKNOWN iface
) {
67 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, UnknownVtbl
, iface
);
68 ULONG ref
= InterlockedDecrement(&This
->ref
);
69 TRACE("(%p): ReleaseRef to %ld\n", This
, ref
);
72 HeapFree(GetProcessHeap(), 0, This
);
80 static const IUnknownVtbl DirectMusicGraph_Unknown_Vtbl
= {
81 IDirectMusicGraphImpl_IUnknown_QueryInterface
,
82 IDirectMusicGraphImpl_IUnknown_AddRef
,
83 IDirectMusicGraphImpl_IUnknown_Release
86 /* IDirectMusicGraphImpl IDirectMusicGraph part: */
87 static HRESULT WINAPI
IDirectMusicGraphImpl_IDirectMusicGraph_QueryInterface (LPDIRECTMUSICGRAPH iface
, REFIID riid
, LPVOID
*ppobj
) {
88 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, GraphVtbl
, iface
);
89 return IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
92 static ULONG WINAPI
IDirectMusicGraphImpl_IDirectMusicGraph_AddRef (LPDIRECTMUSICGRAPH iface
) {
93 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, GraphVtbl
, iface
);
94 return IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
97 static ULONG WINAPI
IDirectMusicGraphImpl_IDirectMusicGraph_Release (LPDIRECTMUSICGRAPH iface
) {
98 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, GraphVtbl
, iface
);
99 return IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
102 static HRESULT WINAPI
IDirectMusicGraphImpl_IDirectMusicGraph_StampPMsg (LPDIRECTMUSICGRAPH iface
, DMUS_PMSG
* pPMSG
) {
103 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, GraphVtbl
, iface
);
104 FIXME("(%p, %p): stub\n", This
, pPMSG
);
108 static HRESULT WINAPI
IDirectMusicGraphImpl_IDirectMusicGraph_InsertTool (LPDIRECTMUSICGRAPH iface
, IDirectMusicTool
* pTool
, DWORD
* pdwPChannels
, DWORD cPChannels
, LONG lIndex
) {
109 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, GraphVtbl
, iface
);
112 struct list
* pEntry
= NULL
;
113 struct list
* pPrevEntry
= NULL
;
114 LPDMUS_PRIVATE_GRAPH_TOOL pIt
= NULL
;
115 LPDMUS_PRIVATE_GRAPH_TOOL pNewTool
= NULL
;
118 FIXME("(%p, %p, %p, %ld, %li): use of pdwPChannels\n", This
, pTool
, pdwPChannels
, cPChannels
, lIndex
);
125 lIndex
= This
->num_tools
+ lIndex
;
128 pPrevEntry
= &This
->Tools
;
129 LIST_FOR_EACH (pEntry
, &This
->Tools
) {
130 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_GRAPH_TOOL
, entry
);
131 if (pIt
->dwIndex
== lIndex
) {
132 return DMUS_E_ALREADY_EXISTS
;
134 if (pIt
->dwIndex
> lIndex
) {
141 pNewTool
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(DMUS_PRIVATE_GRAPH_TOOL
));
142 pNewTool
->pTool
= pTool
;
143 pNewTool
->dwIndex
= lIndex
;
144 IDirectMusicTool8_AddRef(pTool
);
145 hr
= IDirectMusicTool8_Init(pTool
, iface
);
146 list_add_tail (pPrevEntry
->next
, &pNewTool
->entry
);
150 hr
= IDirectMusicTool8_GetMediaTypes(pTool
, &dwNum
);
156 static HRESULT WINAPI
IDirectMusicGraphImpl_IDirectMusicGraph_GetTool (LPDIRECTMUSICGRAPH iface
, DWORD dwIndex
, IDirectMusicTool
** ppTool
) {
157 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, GraphVtbl
, iface
);
158 struct list
* pEntry
= NULL
;
159 LPDMUS_PRIVATE_GRAPH_TOOL pIt
= NULL
;
161 FIXME("(%p, %ld, %p): stub\n", This
, dwIndex
, ppTool
);
163 LIST_FOR_EACH (pEntry
, &This
->Tools
) {
164 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_GRAPH_TOOL
, entry
);
165 if (pIt
->dwIndex
== dwIndex
) {
166 *ppTool
= pIt
->pTool
;
167 if (NULL
!= *ppTool
) {
168 IDirectMusicTool8_AddRef((LPDIRECTMUSICTOOL8
) *ppTool
);
172 if (pIt
->dwIndex
> dwIndex
) {
177 return DMUS_E_NOT_FOUND
;
180 static HRESULT WINAPI
IDirectMusicGraphImpl_IDirectMusicGraph_RemoveTool (LPDIRECTMUSICGRAPH iface
, IDirectMusicTool
* pTool
) {
181 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, GraphVtbl
, iface
);
182 FIXME("(%p, %p): stub\n", This
, pTool
);
186 static const IDirectMusicGraphVtbl DirectMusicGraph_Graph_Vtbl
= {
187 IDirectMusicGraphImpl_IDirectMusicGraph_QueryInterface
,
188 IDirectMusicGraphImpl_IDirectMusicGraph_AddRef
,
189 IDirectMusicGraphImpl_IDirectMusicGraph_Release
,
190 IDirectMusicGraphImpl_IDirectMusicGraph_StampPMsg
,
191 IDirectMusicGraphImpl_IDirectMusicGraph_InsertTool
,
192 IDirectMusicGraphImpl_IDirectMusicGraph_GetTool
,
193 IDirectMusicGraphImpl_IDirectMusicGraph_RemoveTool
197 /* IDirectMusicGraphImpl IDirectMusicObject part: */
198 static HRESULT WINAPI
IDirectMusicGraphImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface
, REFIID riid
, LPVOID
*ppobj
) {
199 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, ObjectVtbl
, iface
);
200 return IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
203 static ULONG WINAPI
IDirectMusicGraphImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface
) {
204 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, ObjectVtbl
, iface
);
205 return IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
208 static ULONG WINAPI
IDirectMusicGraphImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface
) {
209 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, ObjectVtbl
, iface
);
210 return IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
213 static HRESULT WINAPI
IDirectMusicGraphImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
214 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, ObjectVtbl
, iface
);
215 TRACE("(%p, %p)\n", This
, pDesc
);
216 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
217 memcpy (pDesc
, This
->pDesc
, This
->pDesc
->dwSize
);
221 static HRESULT WINAPI
IDirectMusicGraphImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface
, LPDMUS_OBJECTDESC pDesc
) {
222 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, ObjectVtbl
, iface
);
223 TRACE("(%p, %p): setting descriptor:\n%s\n", This
, pDesc
, debugstr_DMUS_OBJECTDESC (pDesc
));
225 /* According to MSDN, we should copy only given values, not whole struct */
226 if (pDesc
->dwValidData
& DMUS_OBJ_OBJECT
)
227 memcpy (&This
->pDesc
->guidObject
, &pDesc
->guidObject
, sizeof (pDesc
->guidObject
));
228 if (pDesc
->dwValidData
& DMUS_OBJ_CLASS
)
229 memcpy (&This
->pDesc
->guidClass
, &pDesc
->guidClass
, sizeof (pDesc
->guidClass
));
230 if (pDesc
->dwValidData
& DMUS_OBJ_NAME
)
231 lstrcpynW (This
->pDesc
->wszName
, pDesc
->wszName
, DMUS_MAX_NAME
);
232 if (pDesc
->dwValidData
& DMUS_OBJ_CATEGORY
)
233 lstrcpynW (This
->pDesc
->wszCategory
, pDesc
->wszCategory
, DMUS_MAX_CATEGORY
);
234 if (pDesc
->dwValidData
& DMUS_OBJ_FILENAME
)
235 lstrcpynW (This
->pDesc
->wszFileName
, pDesc
->wszFileName
, DMUS_MAX_FILENAME
);
236 if (pDesc
->dwValidData
& DMUS_OBJ_VERSION
)
237 memcpy (&This
->pDesc
->vVersion
, &pDesc
->vVersion
, sizeof (pDesc
->vVersion
));
238 if (pDesc
->dwValidData
& DMUS_OBJ_DATE
)
239 memcpy (&This
->pDesc
->ftDate
, &pDesc
->ftDate
, sizeof (pDesc
->ftDate
));
240 if (pDesc
->dwValidData
& DMUS_OBJ_MEMORY
) {
241 memcpy (&This
->pDesc
->llMemLength
, &pDesc
->llMemLength
, sizeof (pDesc
->llMemLength
));
242 memcpy (This
->pDesc
->pbMemData
, pDesc
->pbMemData
, sizeof (pDesc
->pbMemData
));
244 if (pDesc
->dwValidData
& DMUS_OBJ_STREAM
) {
245 /* according to MSDN, we copy the stream */
246 IStream_Clone (pDesc
->pStream
, &This
->pDesc
->pStream
);
250 This
->pDesc
->dwValidData
|= pDesc
->dwValidData
;
255 static HRESULT WINAPI
IDirectMusicGraphImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface
, LPSTREAM pStream
, LPDMUS_OBJECTDESC pDesc
) {
256 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, ObjectVtbl
, iface
);
257 DMUS_PRIVATE_CHUNK Chunk
;
258 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
259 LARGE_INTEGER liMove
; /* used when skipping chunks */
261 TRACE("(%p, %p, %p)\n", This
, pStream
, pDesc
);
263 /* FIXME: should this be determined from stream? */
264 pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
265 memcpy (&pDesc
->guidClass
, &CLSID_DirectMusicGraph
, sizeof(CLSID
));
267 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
268 TRACE_(dmfile
)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
269 switch (Chunk
.fccID
) {
271 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
272 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
273 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
275 if (Chunk
.fccID
== DMUS_FOURCC_TOOLGRAPH_FORM
) {
276 TRACE_(dmfile
)(": graph form\n");
278 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
279 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
280 TRACE_(dmfile
)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
281 switch (Chunk
.fccID
) {
282 case DMUS_FOURCC_GUID_CHUNK
: {
283 TRACE_(dmfile
)(": GUID chunk\n");
284 pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
285 IStream_Read (pStream
, &pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
288 case DMUS_FOURCC_VERSION_CHUNK
: {
289 TRACE_(dmfile
)(": version chunk\n");
290 pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
291 IStream_Read (pStream
, &pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
294 case DMUS_FOURCC_CATEGORY_CHUNK
: {
295 TRACE_(dmfile
)(": category chunk\n");
296 pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
297 IStream_Read (pStream
, pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
301 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
302 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
303 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
305 switch (Chunk
.fccID
) {
306 /* evil M$ UNFO list, which can (!?) contain INFO elements */
307 case DMUS_FOURCC_UNFO_LIST
: {
308 TRACE_(dmfile
)(": UNFO list\n");
310 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
311 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
312 TRACE_(dmfile
)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
313 switch (Chunk
.fccID
) {
314 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
315 (though strings seem to be valid unicode) */
316 case mmioFOURCC('I','N','A','M'):
317 case DMUS_FOURCC_UNAM_CHUNK
: {
318 TRACE_(dmfile
)(": name chunk\n");
319 pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
320 IStream_Read (pStream
, pDesc
->wszName
, Chunk
.dwSize
, NULL
);
323 case mmioFOURCC('I','A','R','T'):
324 case DMUS_FOURCC_UART_CHUNK
: {
325 TRACE_(dmfile
)(": artist chunk (ignored)\n");
326 liMove
.QuadPart
= Chunk
.dwSize
;
327 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
330 case mmioFOURCC('I','C','O','P'):
331 case DMUS_FOURCC_UCOP_CHUNK
: {
332 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
333 liMove
.QuadPart
= Chunk
.dwSize
;
334 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
337 case mmioFOURCC('I','S','B','J'):
338 case DMUS_FOURCC_USBJ_CHUNK
: {
339 TRACE_(dmfile
)(": subject chunk (ignored)\n");
340 liMove
.QuadPart
= Chunk
.dwSize
;
341 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
344 case mmioFOURCC('I','C','M','T'):
345 case DMUS_FOURCC_UCMT_CHUNK
: {
346 TRACE_(dmfile
)(": comment chunk (ignored)\n");
347 liMove
.QuadPart
= Chunk
.dwSize
;
348 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
352 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
353 liMove
.QuadPart
= Chunk
.dwSize
;
354 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
358 TRACE_(dmfile
)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount
[0], ListSize
[0]);
359 } while (ListCount
[0] < ListSize
[0]);
363 TRACE_(dmfile
)(": unknown (skipping)\n");
364 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
365 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
372 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
373 liMove
.QuadPart
= Chunk
.dwSize
;
374 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
378 TRACE_(dmfile
)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount
, StreamSize
);
379 } while (StreamCount
< StreamSize
);
381 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
382 liMove
.QuadPart
= StreamSize
;
383 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
387 TRACE_(dmfile
)(": reading finished\n");
391 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
392 liMove
.QuadPart
= Chunk
.dwSize
;
393 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
394 return DMUS_E_INVALIDFILE
;
398 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc
));
403 static const IDirectMusicObjectVtbl DirectMusicGraph_Object_Vtbl
= {
404 IDirectMusicGraphImpl_IDirectMusicObject_QueryInterface
,
405 IDirectMusicGraphImpl_IDirectMusicObject_AddRef
,
406 IDirectMusicGraphImpl_IDirectMusicObject_Release
,
407 IDirectMusicGraphImpl_IDirectMusicObject_GetDescriptor
,
408 IDirectMusicGraphImpl_IDirectMusicObject_SetDescriptor
,
409 IDirectMusicGraphImpl_IDirectMusicObject_ParseDescriptor
412 /* IDirectMusicGraphImpl IPersistStream part: */
413 static HRESULT WINAPI
IDirectMusicGraphImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface
, REFIID riid
, LPVOID
*ppobj
) {
414 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, PersistStreamVtbl
, iface
);
415 return IDirectMusicGraphImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&This
->UnknownVtbl
, riid
, ppobj
);
418 static ULONG WINAPI
IDirectMusicGraphImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface
) {
419 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, PersistStreamVtbl
, iface
);
420 return IDirectMusicGraphImpl_IUnknown_AddRef ((LPUNKNOWN
)&This
->UnknownVtbl
);
423 static ULONG WINAPI
IDirectMusicGraphImpl_IPersistStream_Release (LPPERSISTSTREAM iface
) {
424 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, PersistStreamVtbl
, iface
);
425 return IDirectMusicGraphImpl_IUnknown_Release ((LPUNKNOWN
)&This
->UnknownVtbl
);
428 static HRESULT WINAPI
IDirectMusicGraphImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface
, CLSID
* pClassID
) {
432 static HRESULT WINAPI
IDirectMusicGraphImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface
) {
436 static HRESULT WINAPI
IDirectMusicGraphImpl_IPersistStream_Load (LPPERSISTSTREAM iface
, IStream
* pStm
) {
437 ICOM_THIS_MULTI(IDirectMusicGraphImpl
, PersistStreamVtbl
, iface
);
439 DWORD chunkSize
, StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
440 LARGE_INTEGER liMove
; /* used when skipping chunks */
442 FIXME("(%p, %p): Loading not implemented yet\n", This
, pStm
);
443 IStream_Read (pStm
, &chunkID
, sizeof(FOURCC
), NULL
);
444 IStream_Read (pStm
, &chunkSize
, sizeof(DWORD
), NULL
);
445 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID
), chunkSize
);
448 IStream_Read (pStm
, &chunkID
, sizeof(FOURCC
), NULL
);
449 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(chunkID
));
450 StreamSize
= chunkSize
- sizeof(FOURCC
);
453 case DMUS_FOURCC_TOOLGRAPH_FORM
: {
454 TRACE_(dmfile
)(": graph form\n");
456 IStream_Read (pStm
, &chunkID
, sizeof(FOURCC
), NULL
);
457 IStream_Read (pStm
, &chunkSize
, sizeof(FOURCC
), NULL
);
458 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + chunkSize
;
459 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID
), chunkSize
);
461 case DMUS_FOURCC_GUID_CHUNK
: {
462 TRACE_(dmfile
)(": GUID chunk\n");
463 This
->pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
464 IStream_Read (pStm
, &This
->pDesc
->guidObject
, chunkSize
, NULL
);
467 case DMUS_FOURCC_VERSION_CHUNK
: {
468 TRACE_(dmfile
)(": version chunk\n");
469 This
->pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
470 IStream_Read (pStm
, &This
->pDesc
->vVersion
, chunkSize
, NULL
);
473 case DMUS_FOURCC_CATEGORY_CHUNK
: {
474 TRACE_(dmfile
)(": category chunk\n");
475 This
->pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
476 IStream_Read (pStm
, This
->pDesc
->wszCategory
, chunkSize
, NULL
);
480 IStream_Read (pStm
, &chunkID
, sizeof(FOURCC
), NULL
);
481 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(chunkID
));
482 ListSize
[0] = chunkSize
- sizeof(FOURCC
);
485 case DMUS_FOURCC_UNFO_LIST
: {
486 TRACE_(dmfile
)(": UNFO list\n");
488 IStream_Read (pStm
, &chunkID
, sizeof(FOURCC
), NULL
);
489 IStream_Read (pStm
, &chunkSize
, sizeof(FOURCC
), NULL
);
490 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + chunkSize
;
491 TRACE_(dmfile
)(": %s chunk (size = %ld)", debugstr_fourcc (chunkID
), chunkSize
);
493 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
494 (though strings seem to be valid unicode) */
495 case mmioFOURCC('I','N','A','M'):
496 case DMUS_FOURCC_UNAM_CHUNK
: {
497 TRACE_(dmfile
)(": name chunk\n");
498 This
->pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
499 IStream_Read (pStm
, This
->pDesc
->wszName
, chunkSize
, NULL
);
502 case mmioFOURCC('I','A','R','T'):
503 case DMUS_FOURCC_UART_CHUNK
: {
504 TRACE_(dmfile
)(": artist chunk (ignored)\n");
505 liMove
.QuadPart
= chunkSize
;
506 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
509 case mmioFOURCC('I','C','O','P'):
510 case DMUS_FOURCC_UCOP_CHUNK
: {
511 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
512 liMove
.QuadPart
= chunkSize
;
513 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
516 case mmioFOURCC('I','S','B','J'):
517 case DMUS_FOURCC_USBJ_CHUNK
: {
518 TRACE_(dmfile
)(": subject chunk (ignored)\n");
519 liMove
.QuadPart
= chunkSize
;
520 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
523 case mmioFOURCC('I','C','M','T'):
524 case DMUS_FOURCC_UCMT_CHUNK
: {
525 TRACE_(dmfile
)(": comment chunk (ignored)\n");
526 liMove
.QuadPart
= chunkSize
;
527 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
531 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
532 liMove
.QuadPart
= chunkSize
;
533 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
537 TRACE_(dmfile
)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount
[0], ListSize
[0]);
538 } while (ListCount
[0] < ListSize
[0]);
542 TRACE_(dmfile
)(": unknown (skipping)\n");
543 liMove
.QuadPart
= chunkSize
- sizeof(FOURCC
);
544 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
551 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
552 liMove
.QuadPart
= chunkSize
;
553 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
557 TRACE_(dmfile
)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount
, StreamSize
);
558 } while (StreamCount
< StreamSize
);
562 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
563 liMove
.QuadPart
= StreamSize
;
564 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
568 TRACE_(dmfile
)(": reading finished\n");
572 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
573 liMove
.QuadPart
= chunkSize
;
574 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
582 static HRESULT WINAPI
IDirectMusicGraphImpl_IPersistStream_Save (LPPERSISTSTREAM iface
, IStream
* pStm
, BOOL fClearDirty
) {
586 static HRESULT WINAPI
IDirectMusicGraphImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface
, ULARGE_INTEGER
* pcbSize
) {
590 static const IPersistStreamVtbl DirectMusicGraph_PersistStream_Vtbl
= {
591 IDirectMusicGraphImpl_IPersistStream_QueryInterface
,
592 IDirectMusicGraphImpl_IPersistStream_AddRef
,
593 IDirectMusicGraphImpl_IPersistStream_Release
,
594 IDirectMusicGraphImpl_IPersistStream_GetClassID
,
595 IDirectMusicGraphImpl_IPersistStream_IsDirty
,
596 IDirectMusicGraphImpl_IPersistStream_Load
,
597 IDirectMusicGraphImpl_IPersistStream_Save
,
598 IDirectMusicGraphImpl_IPersistStream_GetSizeMax
601 /* for ClassFactory */
602 HRESULT WINAPI
DMUSIC_CreateDirectMusicGraphImpl (LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
) {
603 IDirectMusicGraphImpl
* obj
;
605 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicGraphImpl
));
608 return E_OUTOFMEMORY
;
610 obj
->UnknownVtbl
= &DirectMusicGraph_Unknown_Vtbl
;
611 obj
->GraphVtbl
= &DirectMusicGraph_Graph_Vtbl
;
612 obj
->ObjectVtbl
= &DirectMusicGraph_Object_Vtbl
;
613 obj
->PersistStreamVtbl
= &DirectMusicGraph_PersistStream_Vtbl
;
614 obj
->pDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(DMUS_OBJECTDESC
));
615 DM_STRUCT_INIT(obj
->pDesc
);
616 obj
->pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
617 memcpy (&obj
->pDesc
->guidClass
, &CLSID_DirectMusicGraph
, sizeof (CLSID
));
618 obj
->ref
= 0; /* will be inited by QueryInterface */
619 list_init (&obj
->Tools
);
621 return IDirectMusicGraphImpl_IUnknown_QueryInterface ((LPUNKNOWN
)&obj
->UnknownVtbl
, lpcGUID
, ppobj
);