d3d8: Get rid of the format switching code in d3d8_device_CopyRects().
[wine.git] / dlls / dmscript / script.c
blob50394bc07a25354385bb31140888e0434a3ec17d
1 /* IDirectMusicScript
3 * Copyright (C) 2003-2004 Rok Mandeljc
4 * Copyright (C) 2003-2004 Raphael Junqueira
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
28 #include "dmscript_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dmscript);
31 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
34 /*****************************************************************************
35 * IDirectMusicScriptImpl implementation
37 typedef struct IDirectMusicScriptImpl {
38 IDirectMusicScript IDirectMusicScript_iface;
39 const IDirectMusicObjectVtbl *ObjectVtbl;
40 const IPersistStreamVtbl *PersistStreamVtbl;
41 LONG ref;
42 IDirectMusicPerformance *pPerformance;
43 DMUS_OBJECTDESC *pDesc;
44 DMUS_IO_SCRIPT_HEADER *pHeader;
45 DMUS_IO_VERSION *pVersion;
46 WCHAR *pwzLanguage;
47 WCHAR *pwzSource;
48 } IDirectMusicScriptImpl;
50 static inline IDirectMusicScriptImpl *impl_from_IDirectMusicScript(IDirectMusicScript *iface)
52 return CONTAINING_RECORD(iface, IDirectMusicScriptImpl, IDirectMusicScript_iface);
55 static HRESULT WINAPI IDirectMusicScriptImpl_QueryInterface(IDirectMusicScript *iface, REFIID riid,
56 void **ret_iface)
58 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
60 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
62 *ret_iface = NULL;
64 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicScript))
65 *ret_iface = iface;
66 else if (IsEqualIID(riid, &IID_IDirectMusicObject))
67 *ret_iface = &This->ObjectVtbl;
68 else if (IsEqualIID(riid, &IID_IPersistStream))
69 *ret_iface = &This->PersistStreamVtbl;
70 else {
71 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
72 return E_NOINTERFACE;
75 IUnknown_AddRef((IUnknown*)*ret_iface);
76 return S_OK;
79 static ULONG WINAPI IDirectMusicScriptImpl_AddRef(IDirectMusicScript *iface)
81 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
82 LONG ref = InterlockedIncrement(&This->ref);
84 TRACE("(%p) ref=%d\n", This, ref);
86 return ref;
89 static ULONG WINAPI IDirectMusicScriptImpl_Release(IDirectMusicScript *iface)
91 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
92 LONG ref = InterlockedDecrement(&This->ref);
94 TRACE("(%p) ref=%d\n", This, ref);
96 if (!ref) {
97 HeapFree(GetProcessHeap(), 0, This->pHeader);
98 HeapFree(GetProcessHeap(), 0, This->pVersion);
99 HeapFree(GetProcessHeap(), 0, This->pwzLanguage);
100 HeapFree(GetProcessHeap(), 0, This->pwzSource);
101 HeapFree(GetProcessHeap(), 0, This->pDesc);
102 HeapFree(GetProcessHeap(), 0, This);
103 DMSCRIPT_UnlockModule();
106 return ref;
109 static HRESULT WINAPI IDirectMusicScriptImpl_Init(IDirectMusicScript *iface,
110 IDirectMusicPerformance *pPerformance, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
112 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
113 FIXME("(%p, %p, %p): stub\n", This, pPerformance, pErrorInfo);
114 This->pPerformance = pPerformance;
115 return S_OK;
118 static HRESULT WINAPI IDirectMusicScriptImpl_CallRoutine(IDirectMusicScript *iface,
119 WCHAR *pwszRoutineName, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
121 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
122 FIXME("(%p, %s, %p): stub\n", This, debugstr_w(pwszRoutineName), pErrorInfo);
123 /*return E_NOTIMPL;*/
124 return S_OK;
125 /*return E_FAIL;*/
128 static HRESULT WINAPI IDirectMusicScriptImpl_SetVariableVariant(IDirectMusicScript *iface,
129 WCHAR *pwszVariableName, VARIANT varValue, BOOL fSetRef, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
131 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
132 FIXME("(%p, %s, FIXME, %d, %p): stub\n", This, debugstr_w(pwszVariableName),/* varValue,*/ fSetRef, pErrorInfo);
133 return S_OK;
136 static HRESULT WINAPI IDirectMusicScriptImpl_GetVariableVariant(IDirectMusicScript *iface,
137 WCHAR *pwszVariableName, VARIANT *pvarValue, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
139 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
140 FIXME("(%p, %s, %p, %p): stub\n", This, debugstr_w(pwszVariableName), pvarValue, pErrorInfo);
141 return S_OK;
144 static HRESULT WINAPI IDirectMusicScriptImpl_SetVariableNumber(IDirectMusicScript *iface,
145 WCHAR *pwszVariableName, LONG lValue, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
147 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
148 FIXME("(%p, %s, %i, %p): stub\n", This, debugstr_w(pwszVariableName), lValue, pErrorInfo);
149 return S_OK;
152 static HRESULT WINAPI IDirectMusicScriptImpl_GetVariableNumber(IDirectMusicScript *iface,
153 WCHAR *pwszVariableName, LONG *plValue, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
155 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
156 FIXME("(%p, %s, %p, %p): stub\n", This, debugstr_w(pwszVariableName), plValue, pErrorInfo);
157 return S_OK;
160 static HRESULT WINAPI IDirectMusicScriptImpl_SetVariableObject(IDirectMusicScript *iface,
161 WCHAR *pwszVariableName, IUnknown *punkValue, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
163 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
164 FIXME("(%p, %s, %p, %p): stub\n", This, debugstr_w(pwszVariableName), punkValue, pErrorInfo);
165 return S_OK;
168 static HRESULT WINAPI IDirectMusicScriptImpl_GetVariableObject(IDirectMusicScript *iface,
169 WCHAR *pwszVariableName, REFIID riid, void **ppv, DMUS_SCRIPT_ERRORINFO *pErrorInfo)
171 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
172 FIXME("(%p, %s, %s, %p, %p): stub\n", This, debugstr_w(pwszVariableName), debugstr_dmguid(riid), ppv, pErrorInfo);
173 return S_OK;
176 static HRESULT WINAPI IDirectMusicScriptImpl_EnumRoutine(IDirectMusicScript *iface, DWORD dwIndex,
177 WCHAR *pwszName)
179 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
180 FIXME("(%p, %d, %p): stub\n", This, dwIndex, pwszName);
181 return S_OK;
184 static HRESULT WINAPI IDirectMusicScriptImpl_EnumVariable(IDirectMusicScript *iface, DWORD dwIndex,
185 WCHAR *pwszName)
187 IDirectMusicScriptImpl *This = impl_from_IDirectMusicScript(iface);
188 FIXME("(%p, %d, %p): stub\n", This, dwIndex, pwszName);
189 return S_OK;
192 static const IDirectMusicScriptVtbl dmscript_vtbl = {
193 IDirectMusicScriptImpl_QueryInterface,
194 IDirectMusicScriptImpl_AddRef,
195 IDirectMusicScriptImpl_Release,
196 IDirectMusicScriptImpl_Init,
197 IDirectMusicScriptImpl_CallRoutine,
198 IDirectMusicScriptImpl_SetVariableVariant,
199 IDirectMusicScriptImpl_GetVariableVariant,
200 IDirectMusicScriptImpl_SetVariableNumber,
201 IDirectMusicScriptImpl_GetVariableNumber,
202 IDirectMusicScriptImpl_SetVariableObject,
203 IDirectMusicScriptImpl_GetVariableObject,
204 IDirectMusicScriptImpl_EnumRoutine,
205 IDirectMusicScriptImpl_EnumVariable
208 /* IDirectMusicScriptImpl IDirectMusicObject part: */
209 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj) {
210 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
211 return IDirectMusicScript_QueryInterface(&This->IDirectMusicScript_iface, riid, ppobj);
214 static ULONG WINAPI IDirectMusicScriptImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface) {
215 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
216 return IDirectMusicScript_AddRef (&This->IDirectMusicScript_iface);
219 static ULONG WINAPI IDirectMusicScriptImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface) {
220 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
221 return IDirectMusicScript_Release (&This->IDirectMusicScript_iface);
224 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
225 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
226 TRACE("(%p, %p)\n", This, pDesc);
227 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
228 memcpy (pDesc, This->pDesc, This->pDesc->dwSize);
229 return S_OK;
232 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
233 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
234 TRACE("(%p, %p): setting descriptor:\n%s\n", This, pDesc, debugstr_DMUS_OBJECTDESC (pDesc));
236 /* According to MSDN, we should copy only given values, not whole struct */
237 if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
238 This->pDesc->guidObject = pDesc->guidObject;
239 if (pDesc->dwValidData & DMUS_OBJ_CLASS)
240 This->pDesc->guidClass = pDesc->guidClass;
241 if (pDesc->dwValidData & DMUS_OBJ_NAME)
242 lstrcpynW (This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
243 if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
244 lstrcpynW (This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);
245 if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
246 lstrcpynW (This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);
247 if (pDesc->dwValidData & DMUS_OBJ_VERSION)
248 This->pDesc->vVersion = pDesc->vVersion;
249 if (pDesc->dwValidData & DMUS_OBJ_DATE)
250 This->pDesc->ftDate = pDesc->ftDate;
251 if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
252 This->pDesc->llMemLength = pDesc->llMemLength;
253 memcpy (This->pDesc->pbMemData, pDesc->pbMemData, pDesc->llMemLength);
255 if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
256 /* according to MSDN, we copy the stream */
257 IStream_Clone (pDesc->pStream, &This->pDesc->pStream);
260 /* add new flags */
261 This->pDesc->dwValidData |= pDesc->dwValidData;
263 return S_OK;
266 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) {
267 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
268 DMUS_PRIVATE_CHUNK Chunk;
269 DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
270 LARGE_INTEGER liMove; /* used when skipping chunks */
272 TRACE("(%p, %p, %p)\n", This, pStream, pDesc);
274 /* FIXME: should this be determined from stream? */
275 pDesc->dwValidData |= DMUS_OBJ_CLASS;
276 pDesc->guidClass = CLSID_DirectMusicScript;
278 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
279 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
280 switch (Chunk.fccID) {
281 case FOURCC_RIFF: {
282 IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);
283 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
284 StreamSize = Chunk.dwSize - sizeof(FOURCC);
285 StreamCount = 0;
286 if (Chunk.fccID == DMUS_FOURCC_SCRIPT_FORM) {
287 TRACE_(dmfile)(": script form\n");
288 do {
289 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
290 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
291 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
292 switch (Chunk.fccID) {
293 case DMUS_FOURCC_GUID_CHUNK: {
294 TRACE_(dmfile)(": GUID chunk\n");
295 pDesc->dwValidData |= DMUS_OBJ_OBJECT;
296 IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL);
297 break;
299 case DMUS_FOURCC_VERSION_CHUNK: {
300 TRACE_(dmfile)(": version chunk\n");
301 pDesc->dwValidData |= DMUS_OBJ_VERSION;
302 IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL);
303 break;
305 case DMUS_FOURCC_CATEGORY_CHUNK: {
306 TRACE_(dmfile)(": category chunk\n");
307 pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
308 IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL);
309 break;
311 case FOURCC_LIST: {
312 IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);
313 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
314 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
315 ListCount[0] = 0;
316 switch (Chunk.fccID) {
317 /* evil M$ UNFO list, which can (!?) contain INFO elements */
318 case DMUS_FOURCC_UNFO_LIST: {
319 TRACE_(dmfile)(": UNFO list\n");
320 do {
321 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
322 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
323 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
324 switch (Chunk.fccID) {
325 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
326 (though strings seem to be valid unicode) */
327 case mmioFOURCC('I','N','A','M'):
328 case DMUS_FOURCC_UNAM_CHUNK: {
329 TRACE_(dmfile)(": name chunk\n");
330 pDesc->dwValidData |= DMUS_OBJ_NAME;
331 IStream_Read (pStream, pDesc->wszName, Chunk.dwSize, NULL);
332 break;
334 case mmioFOURCC('I','A','R','T'):
335 case DMUS_FOURCC_UART_CHUNK: {
336 TRACE_(dmfile)(": artist chunk (ignored)\n");
337 liMove.QuadPart = Chunk.dwSize;
338 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
339 break;
341 case mmioFOURCC('I','C','O','P'):
342 case DMUS_FOURCC_UCOP_CHUNK: {
343 TRACE_(dmfile)(": copyright chunk (ignored)\n");
344 liMove.QuadPart = Chunk.dwSize;
345 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
346 break;
348 case mmioFOURCC('I','S','B','J'):
349 case DMUS_FOURCC_USBJ_CHUNK: {
350 TRACE_(dmfile)(": subject chunk (ignored)\n");
351 liMove.QuadPart = Chunk.dwSize;
352 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
353 break;
355 case mmioFOURCC('I','C','M','T'):
356 case DMUS_FOURCC_UCMT_CHUNK: {
357 TRACE_(dmfile)(": comment chunk (ignored)\n");
358 liMove.QuadPart = Chunk.dwSize;
359 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
360 break;
362 default: {
363 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
364 liMove.QuadPart = Chunk.dwSize;
365 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
366 break;
369 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
370 } while (ListCount[0] < ListSize[0]);
371 break;
373 default: {
374 TRACE_(dmfile)(": unknown (skipping)\n");
375 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
376 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
377 break;
380 break;
382 default: {
383 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
384 liMove.QuadPart = Chunk.dwSize;
385 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
386 break;
389 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
390 } while (StreamCount < StreamSize);
391 } else {
392 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
393 liMove.QuadPart = StreamSize;
394 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
395 return E_FAIL;
398 TRACE_(dmfile)(": reading finished\n");
399 break;
401 default: {
402 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
403 liMove.QuadPart = Chunk.dwSize;
404 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
405 return DMUS_E_INVALIDFILE;
409 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc));
411 return S_OK;
414 static const IDirectMusicObjectVtbl DirectMusicScript_Object_Vtbl = {
415 IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface,
416 IDirectMusicScriptImpl_IDirectMusicObject_AddRef,
417 IDirectMusicScriptImpl_IDirectMusicObject_Release,
418 IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor,
419 IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor,
420 IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor
423 /* IDirectMusicScriptImpl IPersistStream part: */
424 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
425 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
426 return IDirectMusicScript_QueryInterface(&This->IDirectMusicScript_iface, riid, ppobj);
429 static ULONG WINAPI IDirectMusicScriptImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
430 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
431 return IDirectMusicScript_AddRef(&This->IDirectMusicScript_iface);
434 static ULONG WINAPI IDirectMusicScriptImpl_IPersistStream_Release (LPPERSISTSTREAM iface) {
435 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
436 return IDirectMusicScript_Release(&This->IDirectMusicScript_iface);
439 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
440 TRACE("(%p, %p) method not implemented\n", iface, pClassID);
442 return E_NOTIMPL;
445 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
446 return S_FALSE;
449 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
450 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
452 DMUS_PRIVATE_CHUNK Chunk;
453 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
454 LARGE_INTEGER liMove; /* used when skipping chunks */
455 LPDIRECTMUSICGETLOADER pGetLoader = NULL;
456 LPDIRECTMUSICLOADER pLoader = NULL;
458 FIXME("(%p, %p): Loading not implemented yet\n", This, pStm);
459 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
460 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
461 switch (Chunk.fccID) {
462 case FOURCC_RIFF: {
463 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
464 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
465 StreamSize = Chunk.dwSize - sizeof(FOURCC);
466 StreamCount = 0;
467 switch (Chunk.fccID) {
468 case DMUS_FOURCC_SCRIPT_FORM: {
469 TRACE_(dmfile)(": script form\n");
470 do {
471 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
472 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
473 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
474 switch (Chunk.fccID) {
475 case DMUS_FOURCC_SCRIPT_CHUNK: {
476 TRACE_(dmfile)(": script header chunk\n");
477 This->pHeader = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
478 IStream_Read (pStm, This->pHeader, Chunk.dwSize, NULL);
479 break;
481 case DMUS_FOURCC_SCRIPTVERSION_CHUNK: {
482 TRACE_(dmfile)(": script version chunk\n");
483 This->pVersion = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
484 IStream_Read (pStm, This->pVersion, Chunk.dwSize, NULL);
485 TRACE_(dmfile)("version: 0x%08x.0x%08x\n", This->pVersion->dwVersionMS, This->pVersion->dwVersionLS);
486 break;
488 case DMUS_FOURCC_SCRIPTLANGUAGE_CHUNK: {
489 TRACE_(dmfile)(": script language chunk\n");
490 This->pwzLanguage = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
491 IStream_Read (pStm, This->pwzLanguage, Chunk.dwSize, NULL);
492 TRACE_(dmfile)("using language: %s\n", debugstr_w(This->pwzLanguage));
493 break;
495 case DMUS_FOURCC_SCRIPTSOURCE_CHUNK: {
496 TRACE_(dmfile)(": script source chunk\n");
497 This->pwzSource = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
498 IStream_Read (pStm, This->pwzSource, Chunk.dwSize, NULL);
499 if (TRACE_ON(dmscript)) {
500 int count = WideCharToMultiByte(CP_ACP, 0, This->pwzSource, -1, NULL, 0, NULL, NULL);
501 LPSTR str = HeapAlloc(GetProcessHeap (), 0, count);
502 WideCharToMultiByte(CP_ACP, 0, This->pwzSource, -1, str, count, NULL, NULL);
503 str[count-1] = '\n';
504 TRACE("source:\n");
505 write( 2, str, count );
506 HeapFree(GetProcessHeap(), 0, str);
508 break;
510 case DMUS_FOURCC_GUID_CHUNK: {
511 TRACE_(dmfile)(": GUID chunk\n");
512 This->pDesc->dwValidData |= DMUS_OBJ_OBJECT;
513 IStream_Read (pStm, &This->pDesc->guidObject, Chunk.dwSize, NULL);
514 break;
516 case DMUS_FOURCC_VERSION_CHUNK: {
517 TRACE_(dmfile)(": version chunk\n");
518 This->pDesc->dwValidData |= DMUS_OBJ_VERSION;
519 IStream_Read (pStm, &This->pDesc->vVersion, Chunk.dwSize, NULL);
520 break;
522 case DMUS_FOURCC_CATEGORY_CHUNK: {
523 TRACE_(dmfile)(": category chunk\n");
524 This->pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
525 IStream_Read (pStm, This->pDesc->wszCategory, Chunk.dwSize, NULL);
526 break;
528 case FOURCC_RIFF: {
529 IDirectMusicObject* pObject = NULL;
530 DMUS_OBJECTDESC desc;
532 ZeroMemory (&desc, sizeof(DMUS_OBJECTDESC));
533 desc.dwSize = sizeof(DMUS_OBJECTDESC);
534 desc.dwValidData = DMUS_OBJ_STREAM | DMUS_OBJ_CLASS;
535 desc.guidClass = CLSID_DirectMusicContainer;
536 desc.pStream = NULL;
537 IStream_Clone (pStm, &desc.pStream);
539 liMove.QuadPart = 0;
540 liMove.QuadPart -= (sizeof(FOURCC) + sizeof(DWORD));
541 IStream_Seek (desc.pStream, liMove, STREAM_SEEK_CUR, NULL);
543 IStream_QueryInterface (pStm, &IID_IDirectMusicGetLoader, (LPVOID*)&pGetLoader);
544 IDirectMusicGetLoader_GetLoader (pGetLoader, &pLoader);
545 IDirectMusicGetLoader_Release (pGetLoader);
547 if (SUCCEEDED(IDirectMusicLoader_GetObject (pLoader, &desc, &IID_IDirectMusicObject, (LPVOID*) &pObject))) {
548 IDirectMusicObject_Release (pObject);
549 } else {
550 ERR_(dmfile)("Error on GetObject while trying to load Scrip SubContainer\n");
553 IDirectMusicLoader_Release (pLoader); pLoader = NULL; /* release loader */
554 IStream_Release(desc.pStream); desc.pStream = NULL; /* release cloned stream */
556 liMove.QuadPart = Chunk.dwSize;
557 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
559 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
560 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
561 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
562 ListCount[0] = 0;
564 switch (Chunk.fccID) {
565 default: {
566 TRACE_(dmfile)(": unknown (skipping)\n");
567 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
568 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
569 break;
573 break;
575 case FOURCC_LIST: {
576 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
577 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
578 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
579 ListCount[0] = 0;
580 switch (Chunk.fccID) {
581 case DMUS_FOURCC_UNFO_LIST: {
582 TRACE_(dmfile)(": UNFO list\n");
583 do {
584 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
585 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
586 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
587 switch (Chunk.fccID) {
588 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
589 (though strings seem to be valid unicode) */
590 case mmioFOURCC('I','N','A','M'):
591 case DMUS_FOURCC_UNAM_CHUNK: {
592 TRACE_(dmfile)(": name chunk\n");
593 This->pDesc->dwValidData |= DMUS_OBJ_NAME;
594 IStream_Read (pStm, This->pDesc->wszName, Chunk.dwSize, NULL);
595 break;
597 case mmioFOURCC('I','A','R','T'):
598 case DMUS_FOURCC_UART_CHUNK: {
599 TRACE_(dmfile)(": artist chunk (ignored)\n");
600 liMove.QuadPart = Chunk.dwSize;
601 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
602 break;
604 case mmioFOURCC('I','C','O','P'):
605 case DMUS_FOURCC_UCOP_CHUNK: {
606 TRACE_(dmfile)(": copyright chunk (ignored)\n");
607 liMove.QuadPart = Chunk.dwSize;
608 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
609 break;
611 case mmioFOURCC('I','S','B','J'):
612 case DMUS_FOURCC_USBJ_CHUNK: {
613 TRACE_(dmfile)(": subject chunk (ignored)\n");
614 liMove.QuadPart = Chunk.dwSize;
615 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
616 break;
618 case mmioFOURCC('I','C','M','T'):
619 case DMUS_FOURCC_UCMT_CHUNK: {
620 TRACE_(dmfile)(": comment chunk (ignored)\n");
621 liMove.QuadPart = Chunk.dwSize;
622 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
623 break;
625 default: {
626 TRACE_(dmfile)(": unknown sub-chunk (irrelevant & skipping)\n");
627 liMove.QuadPart = Chunk.dwSize;
628 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
629 break;
632 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
633 } while (ListCount[0] < ListSize[0]);
634 break;
636 default: {
637 TRACE_(dmfile)(": unknown (skipping)\n");
638 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
639 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
640 break;
643 break;
645 default: {
646 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
647 liMove.QuadPart = Chunk.dwSize;
648 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
649 break;
652 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
653 } while (StreamCount < StreamSize);
654 break;
656 default: {
657 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
658 liMove.QuadPart = StreamSize;
659 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
660 return E_FAIL;
663 TRACE_(dmfile)(": reading finished\n");
664 break;
666 default: {
667 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
668 liMove.QuadPart = Chunk.dwSize;
669 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
670 return E_FAIL;
674 return S_OK;
677 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
678 return E_NOTIMPL;
681 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
682 return E_NOTIMPL;
685 static const IPersistStreamVtbl DirectMusicScript_PersistStream_Vtbl = {
686 IDirectMusicScriptImpl_IPersistStream_QueryInterface,
687 IDirectMusicScriptImpl_IPersistStream_AddRef,
688 IDirectMusicScriptImpl_IPersistStream_Release,
689 IDirectMusicScriptImpl_IPersistStream_GetClassID,
690 IDirectMusicScriptImpl_IPersistStream_IsDirty,
691 IDirectMusicScriptImpl_IPersistStream_Load,
692 IDirectMusicScriptImpl_IPersistStream_Save,
693 IDirectMusicScriptImpl_IPersistStream_GetSizeMax
696 /* for ClassFactory */
697 HRESULT WINAPI DMUSIC_CreateDirectMusicScriptImpl(REFIID lpcGUID, void **ppobj, IUnknown *pUnkOuter)
699 IDirectMusicScriptImpl *obj;
700 HRESULT hr;
702 *ppobj = NULL;
704 if (pUnkOuter)
705 return CLASS_E_NOAGGREGATION;
707 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicScriptImpl));
708 if (!obj)
709 return E_OUTOFMEMORY;
711 obj->IDirectMusicScript_iface.lpVtbl = &dmscript_vtbl;
712 obj->ObjectVtbl = &DirectMusicScript_Object_Vtbl;
713 obj->PersistStreamVtbl = &DirectMusicScript_PersistStream_Vtbl;
714 obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
715 DM_STRUCT_INIT(obj->pDesc);
716 obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
717 obj->pDesc->guidClass = CLSID_DirectMusicScript;
718 obj->ref = 1;
720 DMSCRIPT_LockModule();
721 hr = IDirectMusicScript_QueryInterface(&obj->IDirectMusicScript_iface, lpcGUID, ppobj);
722 IDirectMusicScript_Release(&obj->IDirectMusicScript_iface);
724 return hr;