dplayx: Code to forward player creation
[wine/gsoc_dplay.git] / dlls / dmscript / script.c
blobd7c696b02ec72504c15a0da952de634f6e1f2cea
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 static ULONG WINAPI IDirectMusicScriptImpl_IUnknown_AddRef (LPUNKNOWN iface);
35 static ULONG WINAPI IDirectMusicScriptImpl_IDirectMusicScript_AddRef (LPDIRECTMUSICSCRIPT iface);
36 static ULONG WINAPI IDirectMusicScriptImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface);
37 static ULONG WINAPI IDirectMusicScriptImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface);
39 /*****************************************************************************
40 * IDirectMusicScriptImpl implementation
42 /* IDirectMusicScriptImpl IUnknown part: */
43 static HRESULT WINAPI IDirectMusicScriptImpl_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
44 ICOM_THIS_MULTI(IDirectMusicScriptImpl, UnknownVtbl, iface);
45 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
47 if (IsEqualIID (riid, &IID_IUnknown)) {
48 *ppobj = &This->UnknownVtbl;
49 IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
50 return S_OK;
51 } else if (IsEqualIID (riid, &IID_IDirectMusicScript)) {
52 *ppobj = &This->ScriptVtbl;
53 IDirectMusicScriptImpl_IDirectMusicScript_AddRef ((LPDIRECTMUSICSCRIPT)&This->ScriptVtbl);
54 return S_OK;
55 } else if (IsEqualIID (riid, &IID_IDirectMusicObject)) {
56 *ppobj = &This->ObjectVtbl;
57 IDirectMusicScriptImpl_IDirectMusicObject_AddRef ((LPDIRECTMUSICOBJECT)&This->ObjectVtbl);
58 return S_OK;
59 } else if (IsEqualIID (riid, &IID_IPersistStream)) {
60 *ppobj = &This->PersistStreamVtbl;
61 IDirectMusicScriptImpl_IPersistStream_AddRef ((LPPERSISTSTREAM)&This->PersistStreamVtbl);
62 return S_OK;
65 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
66 return E_NOINTERFACE;
69 static ULONG WINAPI IDirectMusicScriptImpl_IUnknown_AddRef (LPUNKNOWN iface) {
70 ICOM_THIS_MULTI(IDirectMusicScriptImpl, UnknownVtbl, iface);
71 ULONG ref = InterlockedIncrement(&This->ref);
73 TRACE("(%p): AddRef from %d\n", This, ref - 1);
75 DMSCRIPT_LockModule();
77 return ref;
80 static ULONG WINAPI IDirectMusicScriptImpl_IUnknown_Release (LPUNKNOWN iface) {
81 ICOM_THIS_MULTI(IDirectMusicScriptImpl, UnknownVtbl, iface);
82 ULONG ref = InterlockedDecrement(&This->ref);
84 TRACE("(%p): ReleaseRef to %d\n", This, ref);
86 if (ref == 0) {
87 HeapFree(GetProcessHeap(), 0, This->pHeader);
88 HeapFree(GetProcessHeap(), 0, This->pVersion);
89 HeapFree(GetProcessHeap(), 0, This->pwzLanguage);
90 HeapFree(GetProcessHeap(), 0, This->pwzSource);
91 HeapFree(GetProcessHeap(), 0, This);
94 DMSCRIPT_UnlockModule();
96 return ref;
99 static const IUnknownVtbl DirectMusicScript_Unknown_Vtbl = {
100 IDirectMusicScriptImpl_IUnknown_QueryInterface,
101 IDirectMusicScriptImpl_IUnknown_AddRef,
102 IDirectMusicScriptImpl_IUnknown_Release
105 /* IDirectMusicScriptImpl IDirectMusicScript part: */
106 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_QueryInterface (LPDIRECTMUSICSCRIPT iface, REFIID riid, LPVOID *ppobj) {
107 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
108 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
111 static ULONG WINAPI IDirectMusicScriptImpl_IDirectMusicScript_AddRef (LPDIRECTMUSICSCRIPT iface) {
112 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
113 return IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
116 static ULONG WINAPI IDirectMusicScriptImpl_IDirectMusicScript_Release (LPDIRECTMUSICSCRIPT iface) {
117 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
118 return IDirectMusicScriptImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
121 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_Init (LPDIRECTMUSICSCRIPT iface, IDirectMusicPerformance* pPerformance, DMUS_SCRIPT_ERRORINFO* pErrorInfo) {
122 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
123 FIXME("(%p, %p, %p): stub\n", This, pPerformance, pErrorInfo);
124 This->pPerformance = pPerformance;
125 return S_OK;
128 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_CallRoutine (LPDIRECTMUSICSCRIPT iface, WCHAR* pwszRoutineName, DMUS_SCRIPT_ERRORINFO* pErrorInfo) {
129 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
130 FIXME("(%p, %s, %p): stub\n", This, debugstr_w(pwszRoutineName), pErrorInfo);
131 /*return E_NOTIMPL;*/
132 return S_OK;
133 /*return E_FAIL;*/
136 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_SetVariableVariant (LPDIRECTMUSICSCRIPT iface, WCHAR* pwszVariableName, VARIANT varValue, BOOL fSetRef, DMUS_SCRIPT_ERRORINFO* pErrorInfo) {
137 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
138 FIXME("(%p, %s, FIXME, %d, %p): stub\n", This, debugstr_w(pwszVariableName),/* varValue,*/ fSetRef, pErrorInfo);
139 return S_OK;
142 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_GetVariableVariant (LPDIRECTMUSICSCRIPT iface, WCHAR* pwszVariableName, VARIANT* pvarValue, DMUS_SCRIPT_ERRORINFO* pErrorInfo) {
143 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
144 FIXME("(%p, %s, %p, %p): stub\n", This, debugstr_w(pwszVariableName), pvarValue, pErrorInfo);
145 return S_OK;
148 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_SetVariableNumber (LPDIRECTMUSICSCRIPT iface, WCHAR* pwszVariableName, LONG lValue, DMUS_SCRIPT_ERRORINFO* pErrorInfo) {
149 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
150 FIXME("(%p, %s, %i, %p): stub\n", This, debugstr_w(pwszVariableName), lValue, pErrorInfo);
151 return S_OK;
154 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_GetVariableNumber (LPDIRECTMUSICSCRIPT iface, WCHAR* pwszVariableName, LONG* plValue, DMUS_SCRIPT_ERRORINFO* pErrorInfo) {
155 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
156 FIXME("(%p, %s, %p, %p): stub\n", This, debugstr_w(pwszVariableName), plValue, pErrorInfo);
157 return S_OK;
160 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_SetVariableObject (LPDIRECTMUSICSCRIPT iface, WCHAR* pwszVariableName, IUnknown* punkValue, DMUS_SCRIPT_ERRORINFO* pErrorInfo) {
161 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
162 FIXME("(%p, %s, %p, %p): stub\n", This, debugstr_w(pwszVariableName), punkValue, pErrorInfo);
163 return S_OK;
166 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_GetVariableObject (LPDIRECTMUSICSCRIPT iface, WCHAR* pwszVariableName, REFIID riid, LPVOID* ppv, DMUS_SCRIPT_ERRORINFO* pErrorInfo) {
167 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
168 FIXME("(%p, %s, %s, %p, %p): stub\n", This, debugstr_w(pwszVariableName), debugstr_dmguid(riid), ppv, pErrorInfo);
169 return S_OK;
172 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_EnumRoutine (LPDIRECTMUSICSCRIPT iface, DWORD dwIndex, WCHAR* pwszName) {
173 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
174 FIXME("(%p, %d, %p): stub\n", This, dwIndex, pwszName);
175 return S_OK;
178 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicScript_EnumVariable (LPDIRECTMUSICSCRIPT iface, DWORD dwIndex, WCHAR* pwszName) {
179 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ScriptVtbl, iface);
180 FIXME("(%p, %d, %p): stub\n", This, dwIndex, pwszName);
181 return S_OK;
184 static const IDirectMusicScriptVtbl DirectMusicScript_Script_Vtbl = {
185 IDirectMusicScriptImpl_IDirectMusicScript_QueryInterface,
186 IDirectMusicScriptImpl_IDirectMusicScript_AddRef,
187 IDirectMusicScriptImpl_IDirectMusicScript_Release,
188 IDirectMusicScriptImpl_IDirectMusicScript_Init,
189 IDirectMusicScriptImpl_IDirectMusicScript_CallRoutine,
190 IDirectMusicScriptImpl_IDirectMusicScript_SetVariableVariant,
191 IDirectMusicScriptImpl_IDirectMusicScript_GetVariableVariant,
192 IDirectMusicScriptImpl_IDirectMusicScript_SetVariableNumber,
193 IDirectMusicScriptImpl_IDirectMusicScript_GetVariableNumber,
194 IDirectMusicScriptImpl_IDirectMusicScript_SetVariableObject,
195 IDirectMusicScriptImpl_IDirectMusicScript_GetVariableObject,
196 IDirectMusicScriptImpl_IDirectMusicScript_EnumRoutine,
197 IDirectMusicScriptImpl_IDirectMusicScript_EnumVariable
200 /* IDirectMusicScriptImpl IDirectMusicObject part: */
201 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj) {
202 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
203 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
206 static ULONG WINAPI IDirectMusicScriptImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface) {
207 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
208 return IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
211 static ULONG WINAPI IDirectMusicScriptImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface) {
212 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
213 return IDirectMusicScriptImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
216 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
217 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
218 TRACE("(%p, %p)\n", This, pDesc);
219 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
220 memcpy (pDesc, This->pDesc, This->pDesc->dwSize);
221 return S_OK;
224 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
225 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
226 TRACE("(%p, %p): setting descriptor:\n%s\n", This, pDesc, debugstr_DMUS_OBJECTDESC (pDesc));
228 /* According to MSDN, we should copy only given values, not whole struct */
229 if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
230 This->pDesc->guidObject = pDesc->guidObject;
231 if (pDesc->dwValidData & DMUS_OBJ_CLASS)
232 This->pDesc->guidClass = pDesc->guidClass;
233 if (pDesc->dwValidData & DMUS_OBJ_NAME)
234 lstrcpynW (This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
235 if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
236 lstrcpynW (This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);
237 if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
238 lstrcpynW (This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);
239 if (pDesc->dwValidData & DMUS_OBJ_VERSION)
240 This->pDesc->vVersion = pDesc->vVersion;
241 if (pDesc->dwValidData & DMUS_OBJ_DATE)
242 This->pDesc->ftDate = pDesc->ftDate;
243 if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
244 memcpy (&This->pDesc->llMemLength, &pDesc->llMemLength, sizeof (pDesc->llMemLength));
245 memcpy (This->pDesc->pbMemData, pDesc->pbMemData, sizeof (pDesc->pbMemData));
247 if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
248 /* according to MSDN, we copy the stream */
249 IStream_Clone (pDesc->pStream, &This->pDesc->pStream);
252 /* add new flags */
253 This->pDesc->dwValidData |= pDesc->dwValidData;
255 return S_OK;
258 static HRESULT WINAPI IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) {
259 ICOM_THIS_MULTI(IDirectMusicScriptImpl, ObjectVtbl, iface);
260 DMUS_PRIVATE_CHUNK Chunk;
261 DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
262 LARGE_INTEGER liMove; /* used when skipping chunks */
264 TRACE("(%p, %p, %p)\n", This, pStream, pDesc);
266 /* FIXME: should this be determined from stream? */
267 pDesc->dwValidData |= DMUS_OBJ_CLASS;
268 pDesc->guidClass = CLSID_DirectMusicScript;
270 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
271 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
272 switch (Chunk.fccID) {
273 case FOURCC_RIFF: {
274 IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);
275 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
276 StreamSize = Chunk.dwSize - sizeof(FOURCC);
277 StreamCount = 0;
278 if (Chunk.fccID == DMUS_FOURCC_SCRIPT_FORM) {
279 TRACE_(dmfile)(": script form\n");
280 do {
281 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
282 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
283 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
284 switch (Chunk.fccID) {
285 case DMUS_FOURCC_GUID_CHUNK: {
286 TRACE_(dmfile)(": GUID chunk\n");
287 pDesc->dwValidData |= DMUS_OBJ_OBJECT;
288 IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL);
289 break;
291 case DMUS_FOURCC_VERSION_CHUNK: {
292 TRACE_(dmfile)(": version chunk\n");
293 pDesc->dwValidData |= DMUS_OBJ_VERSION;
294 IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL);
295 break;
297 case DMUS_FOURCC_CATEGORY_CHUNK: {
298 TRACE_(dmfile)(": category chunk\n");
299 pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
300 IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL);
301 break;
303 case FOURCC_LIST: {
304 IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);
305 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
306 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
307 ListCount[0] = 0;
308 switch (Chunk.fccID) {
309 /* evil M$ UNFO list, which can (!?) contain INFO elements */
310 case DMUS_FOURCC_UNFO_LIST: {
311 TRACE_(dmfile)(": UNFO list\n");
312 do {
313 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
314 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
315 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
316 switch (Chunk.fccID) {
317 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
318 (though strings seem to be valid unicode) */
319 case mmioFOURCC('I','N','A','M'):
320 case DMUS_FOURCC_UNAM_CHUNK: {
321 TRACE_(dmfile)(": name chunk\n");
322 pDesc->dwValidData |= DMUS_OBJ_NAME;
323 IStream_Read (pStream, pDesc->wszName, Chunk.dwSize, NULL);
324 break;
326 case mmioFOURCC('I','A','R','T'):
327 case DMUS_FOURCC_UART_CHUNK: {
328 TRACE_(dmfile)(": artist chunk (ignored)\n");
329 liMove.QuadPart = Chunk.dwSize;
330 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
331 break;
333 case mmioFOURCC('I','C','O','P'):
334 case DMUS_FOURCC_UCOP_CHUNK: {
335 TRACE_(dmfile)(": copyright chunk (ignored)\n");
336 liMove.QuadPart = Chunk.dwSize;
337 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
338 break;
340 case mmioFOURCC('I','S','B','J'):
341 case DMUS_FOURCC_USBJ_CHUNK: {
342 TRACE_(dmfile)(": subject chunk (ignored)\n");
343 liMove.QuadPart = Chunk.dwSize;
344 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
345 break;
347 case mmioFOURCC('I','C','M','T'):
348 case DMUS_FOURCC_UCMT_CHUNK: {
349 TRACE_(dmfile)(": comment chunk (ignored)\n");
350 liMove.QuadPart = Chunk.dwSize;
351 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
352 break;
354 default: {
355 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
356 liMove.QuadPart = Chunk.dwSize;
357 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
358 break;
361 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
362 } while (ListCount[0] < ListSize[0]);
363 break;
365 default: {
366 TRACE_(dmfile)(": unknown (skipping)\n");
367 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
368 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
369 break;
372 break;
374 default: {
375 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
376 liMove.QuadPart = Chunk.dwSize;
377 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
378 break;
381 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
382 } while (StreamCount < StreamSize);
383 } else {
384 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
385 liMove.QuadPart = StreamSize;
386 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
387 return E_FAIL;
390 TRACE_(dmfile)(": reading finished\n");
391 break;
393 default: {
394 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
395 liMove.QuadPart = Chunk.dwSize;
396 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
397 return DMUS_E_INVALIDFILE;
401 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc));
403 return S_OK;
406 static const IDirectMusicObjectVtbl DirectMusicScript_Object_Vtbl = {
407 IDirectMusicScriptImpl_IDirectMusicObject_QueryInterface,
408 IDirectMusicScriptImpl_IDirectMusicObject_AddRef,
409 IDirectMusicScriptImpl_IDirectMusicObject_Release,
410 IDirectMusicScriptImpl_IDirectMusicObject_GetDescriptor,
411 IDirectMusicScriptImpl_IDirectMusicObject_SetDescriptor,
412 IDirectMusicScriptImpl_IDirectMusicObject_ParseDescriptor
415 /* IDirectMusicScriptImpl IPersistStream part: */
416 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
417 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
418 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
421 static ULONG WINAPI IDirectMusicScriptImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
422 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
423 return IDirectMusicScriptImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
426 static ULONG WINAPI IDirectMusicScriptImpl_IPersistStream_Release (LPPERSISTSTREAM iface) {
427 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
428 return IDirectMusicScriptImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
431 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
432 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
433 TRACE("(%p, %p)\n", This, pClassID);
434 *pClassID = CLSID_DirectMusicScript;
435 return S_OK;
438 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
439 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
440 FIXME("(%p): stub, always S_FALSE\n", This);
441 return S_FALSE;
444 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
445 ICOM_THIS_MULTI(IDirectMusicScriptImpl, PersistStreamVtbl, iface);
447 DMUS_PRIVATE_CHUNK Chunk;
448 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
449 LARGE_INTEGER liMove; /* used when skipping chunks */
450 LPDIRECTMUSICGETLOADER pGetLoader = NULL;
451 LPDIRECTMUSICLOADER pLoader = NULL;
453 FIXME("(%p, %p): Loading not implemented yet\n", This, pStm);
454 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
455 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
456 switch (Chunk.fccID) {
457 case FOURCC_RIFF: {
458 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
459 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
460 StreamSize = Chunk.dwSize - sizeof(FOURCC);
461 StreamCount = 0;
462 switch (Chunk.fccID) {
463 case DMUS_FOURCC_SCRIPT_FORM: {
464 TRACE_(dmfile)(": script form\n");
465 do {
466 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
467 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
468 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
469 switch (Chunk.fccID) {
470 case DMUS_FOURCC_SCRIPT_CHUNK: {
471 TRACE_(dmfile)(": script header chunk\n");
472 This->pHeader = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
473 IStream_Read (pStm, This->pHeader, Chunk.dwSize, NULL);
474 break;
476 case DMUS_FOURCC_SCRIPTVERSION_CHUNK: {
477 TRACE_(dmfile)(": script version chunk\n");
478 This->pVersion = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
479 IStream_Read (pStm, This->pVersion, Chunk.dwSize, NULL);
480 TRACE_(dmfile)("version: 0x%08x.0x%08x\n", This->pVersion->dwVersionMS, This->pVersion->dwVersionLS);
481 break;
483 case DMUS_FOURCC_SCRIPTLANGUAGE_CHUNK: {
484 TRACE_(dmfile)(": script language chunk\n");
485 This->pwzLanguage = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
486 IStream_Read (pStm, This->pwzLanguage, Chunk.dwSize, NULL);
487 TRACE_(dmfile)("using language: %s\n", debugstr_w(This->pwzLanguage));
488 break;
490 case DMUS_FOURCC_SCRIPTSOURCE_CHUNK: {
491 TRACE_(dmfile)(": script source chunk\n");
492 This->pwzSource = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, Chunk.dwSize);
493 IStream_Read (pStm, This->pwzSource, Chunk.dwSize, NULL);
494 if (TRACE_ON(dmscript)) {
495 int count = WideCharToMultiByte(CP_ACP, 0, This->pwzSource, -1, NULL, 0, NULL, NULL);
496 LPSTR str = HeapAlloc(GetProcessHeap (), 0, count);
497 WideCharToMultiByte(CP_ACP, 0, This->pwzSource, -1, str, count, NULL, NULL);
498 str[count-1] = '\n';
499 TRACE("source:\n");
500 write( 2, str, count );
501 HeapFree(GetProcessHeap(), 0, str);
503 break;
505 case DMUS_FOURCC_GUID_CHUNK: {
506 TRACE_(dmfile)(": GUID chunk\n");
507 This->pDesc->dwValidData |= DMUS_OBJ_OBJECT;
508 IStream_Read (pStm, &This->pDesc->guidObject, Chunk.dwSize, NULL);
509 break;
511 case DMUS_FOURCC_VERSION_CHUNK: {
512 TRACE_(dmfile)(": version chunk\n");
513 This->pDesc->dwValidData |= DMUS_OBJ_VERSION;
514 IStream_Read (pStm, &This->pDesc->vVersion, Chunk.dwSize, NULL);
515 break;
517 case DMUS_FOURCC_CATEGORY_CHUNK: {
518 TRACE_(dmfile)(": category chunk\n");
519 This->pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
520 IStream_Read (pStm, This->pDesc->wszCategory, Chunk.dwSize, NULL);
521 break;
523 case FOURCC_RIFF: {
524 IDirectMusicObject* pObject = NULL;
525 DMUS_OBJECTDESC desc;
527 ZeroMemory (&desc, sizeof(DMUS_OBJECTDESC));
528 desc.dwSize = sizeof(DMUS_OBJECTDESC);
529 desc.dwValidData = DMUS_OBJ_STREAM | DMUS_OBJ_CLASS;
530 desc.guidClass = CLSID_DirectMusicContainer;
531 desc.pStream = NULL;
532 IStream_Clone (pStm, &desc.pStream);
534 liMove.QuadPart = 0;
535 liMove.QuadPart -= (sizeof(FOURCC) + sizeof(DWORD));
536 IStream_Seek (desc.pStream, liMove, STREAM_SEEK_CUR, NULL);
538 IStream_QueryInterface (pStm, &IID_IDirectMusicGetLoader, (LPVOID*)&pGetLoader);
539 IDirectMusicGetLoader_GetLoader (pGetLoader, &pLoader);
540 IDirectMusicGetLoader_Release (pGetLoader);
542 if (SUCCEEDED(IDirectMusicLoader_GetObject (pLoader, &desc, &IID_IDirectMusicObject, (LPVOID*) &pObject))) {
543 IDirectMusicObject_Release (pObject);
544 } else {
545 ERR_(dmfile)("Error on GetObject while trying to load Scrip SubContainer\n");
548 IDirectMusicLoader_Release (pLoader); pLoader = NULL; /* release loader */
549 IStream_Release(desc.pStream); desc.pStream = NULL; /* release cloned stream */
551 liMove.QuadPart = Chunk.dwSize;
552 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
554 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
555 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
556 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
557 ListCount[0] = 0;
559 switch (Chunk.fccID) {
560 default: {
561 TRACE_(dmfile)(": unknown (skipping)\n");
562 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
563 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
564 break;
568 break;
570 case FOURCC_LIST: {
571 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
572 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
573 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
574 ListCount[0] = 0;
575 switch (Chunk.fccID) {
576 case DMUS_FOURCC_UNFO_LIST: {
577 TRACE_(dmfile)(": UNFO list\n");
578 do {
579 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
580 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
581 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
582 switch (Chunk.fccID) {
583 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
584 (though strings seem to be valid unicode) */
585 case mmioFOURCC('I','N','A','M'):
586 case DMUS_FOURCC_UNAM_CHUNK: {
587 TRACE_(dmfile)(": name chunk\n");
588 This->pDesc->dwValidData |= DMUS_OBJ_NAME;
589 IStream_Read (pStm, This->pDesc->wszName, Chunk.dwSize, NULL);
590 break;
592 case mmioFOURCC('I','A','R','T'):
593 case DMUS_FOURCC_UART_CHUNK: {
594 TRACE_(dmfile)(": artist chunk (ignored)\n");
595 liMove.QuadPart = Chunk.dwSize;
596 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
597 break;
599 case mmioFOURCC('I','C','O','P'):
600 case DMUS_FOURCC_UCOP_CHUNK: {
601 TRACE_(dmfile)(": copyright chunk (ignored)\n");
602 liMove.QuadPart = Chunk.dwSize;
603 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
604 break;
606 case mmioFOURCC('I','S','B','J'):
607 case DMUS_FOURCC_USBJ_CHUNK: {
608 TRACE_(dmfile)(": subject chunk (ignored)\n");
609 liMove.QuadPart = Chunk.dwSize;
610 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
611 break;
613 case mmioFOURCC('I','C','M','T'):
614 case DMUS_FOURCC_UCMT_CHUNK: {
615 TRACE_(dmfile)(": comment chunk (ignored)\n");
616 liMove.QuadPart = Chunk.dwSize;
617 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
618 break;
620 default: {
621 TRACE_(dmfile)(": unknown sub-chunk (irrevelant & skipping)\n");
622 liMove.QuadPart = Chunk.dwSize;
623 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
624 break;
627 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
628 } while (ListCount[0] < ListSize[0]);
629 break;
631 default: {
632 TRACE_(dmfile)(": unknown (skipping)\n");
633 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
634 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
635 break;
638 break;
640 default: {
641 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
642 liMove.QuadPart = Chunk.dwSize;
643 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
644 break;
647 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
648 } while (StreamCount < StreamSize);
649 break;
651 default: {
652 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
653 liMove.QuadPart = StreamSize;
654 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
655 return E_FAIL;
658 TRACE_(dmfile)(": reading finished\n");
659 break;
661 default: {
662 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
663 liMove.QuadPart = Chunk.dwSize;
664 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
665 return E_FAIL;
669 return S_OK;
672 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
673 return E_NOTIMPL;
676 static HRESULT WINAPI IDirectMusicScriptImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
677 return E_NOTIMPL;
680 static const IPersistStreamVtbl DirectMusicScript_PersistStream_Vtbl = {
681 IDirectMusicScriptImpl_IPersistStream_QueryInterface,
682 IDirectMusicScriptImpl_IPersistStream_AddRef,
683 IDirectMusicScriptImpl_IPersistStream_Release,
684 IDirectMusicScriptImpl_IPersistStream_GetClassID,
685 IDirectMusicScriptImpl_IPersistStream_IsDirty,
686 IDirectMusicScriptImpl_IPersistStream_Load,
687 IDirectMusicScriptImpl_IPersistStream_Save,
688 IDirectMusicScriptImpl_IPersistStream_GetSizeMax
691 /* for ClassFactory */
692 HRESULT WINAPI DMUSIC_CreateDirectMusicScriptImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter) {
693 IDirectMusicScriptImpl* obj;
695 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicScriptImpl));
696 if (NULL == obj) {
697 *ppobj = NULL;
698 return E_OUTOFMEMORY;
700 obj->UnknownVtbl = &DirectMusicScript_Unknown_Vtbl;
701 obj->ScriptVtbl = &DirectMusicScript_Script_Vtbl;
702 obj->ObjectVtbl = &DirectMusicScript_Object_Vtbl;
703 obj->PersistStreamVtbl = &DirectMusicScript_PersistStream_Vtbl;
704 obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
705 DM_STRUCT_INIT(obj->pDesc);
706 obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
707 obj->pDesc->guidClass = CLSID_DirectMusicScript;
708 obj->ref = 0; /* will be inited by QueryInterface */
710 return IDirectMusicScriptImpl_IUnknown_QueryInterface ((LPUNKNOWN)&obj->UnknownVtbl, lpcGUID, ppobj);