graph.c 23.5 KB
Newer Older
1 2
/* IDirectMusicGraph
 *
3
 * Copyright (C) 2003-2004 Rok Mandeljc
4
 *
5 6 7 8
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
9 10 11
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
14
 *
15 16 17
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 19 20 21
 */

#include "dmime_private.h"

22
WINE_DEFAULT_DEBUG_CHANNEL(dmime);
23
WINE_DECLARE_DEBUG_CHANNEL(dmfile);
24

25 26 27 28
/*****************************************************************************
 * IDirectMusicGraphImpl implementation
 */
/* 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);
32 33
	
	if (IsEqualIID (riid, &IID_IUnknown)) {
34
		*ppobj = &This->UnknownVtbl;
35
		IUnknown_AddRef (iface);
36 37
		return S_OK;	
	} else if (IsEqualIID (riid, &IID_IDirectMusicGraph)) {
38
		*ppobj = &This->GraphVtbl;
39
		IUnknown_AddRef (iface);
40 41
		return S_OK;
	} else if (IsEqualIID (riid, &IID_IDirectMusicObject)) {
42
		*ppobj = &This->ObjectVtbl;
43
		IUnknown_AddRef (iface);
44 45
		return S_OK;
	} else if (IsEqualIID (riid, &IID_IPersistStream)) {
46
		*ppobj = &This->PersistStreamVtbl;
47
		IUnknown_AddRef (iface);
48 49
		return S_OK;
	}
50
	
51
	WARN("(%p, %s, %p): not found\n", This, debugstr_guid(riid), ppobj);
52 53 54
	return E_NOINTERFACE;
}

55
static ULONG WINAPI IDirectMusicGraphImpl_IUnknown_AddRef (LPUNKNOWN iface) {
56
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, UnknownVtbl, iface);
57 58
        ULONG ref = InterlockedIncrement(&This->ref);

59
	TRACE("(%p): AddRef from %d\n", This, ref - 1);
60

61 62
	DMIME_LockModule();

63
	return ref;
64 65
}

Mike McCormack's avatar
Mike McCormack committed
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 %d\n", This, ref);
70
	
71
	if (ref == 0) {
72 73
		HeapFree(GetProcessHeap(), 0, This);
	}
74 75 76

	DMIME_UnlockModule();
	
77 78 79
	return ref;
}

80
static const IUnknownVtbl DirectMusicGraph_Unknown_Vtbl = {
81 82 83 84
	IDirectMusicGraphImpl_IUnknown_QueryInterface,
	IDirectMusicGraphImpl_IUnknown_AddRef,
	IDirectMusicGraphImpl_IUnknown_Release
};
85

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);
90 91
}

92
static ULONG WINAPI IDirectMusicGraphImpl_IDirectMusicGraph_AddRef (LPDIRECTMUSICGRAPH iface) {
93
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, GraphVtbl, iface);
94
	return IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
95
}
96

Mike McCormack's avatar
Mike McCormack committed
97
static ULONG WINAPI IDirectMusicGraphImpl_IDirectMusicGraph_Release (LPDIRECTMUSICGRAPH iface) {
98
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, GraphVtbl, iface);
99
	return IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
100 101
}

Mike McCormack's avatar
Mike McCormack committed
102
static HRESULT WINAPI IDirectMusicGraphImpl_IDirectMusicGraph_StampPMsg (LPDIRECTMUSICGRAPH iface, DMUS_PMSG* pPMSG) {
103 104
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, GraphVtbl, iface);
	FIXME("(%p, %p): stub\n", This, pPMSG);
105 106 107
	return S_OK;
}

Mike McCormack's avatar
Mike McCormack committed
108
static HRESULT WINAPI IDirectMusicGraphImpl_IDirectMusicGraph_InsertTool (LPDIRECTMUSICGRAPH iface, IDirectMusicTool* pTool, DWORD* pdwPChannels, DWORD cPChannels, LONG lIndex) {
109 110 111 112 113 114 115 116
  ICOM_THIS_MULTI(IDirectMusicGraphImpl, GraphVtbl, iface);

  struct list* pEntry = NULL;
  struct list* pPrevEntry = NULL;
  LPDMUS_PRIVATE_GRAPH_TOOL pIt = NULL;
  LPDMUS_PRIVATE_GRAPH_TOOL pNewTool = NULL;

  
117
  FIXME("(%p, %p, %p, %d, %i): use of pdwPChannels\n", This, pTool, pdwPChannels, cPChannels, lIndex);
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
  
  if (NULL == pTool) {
    return E_POINTER;
  }

  if (0 > lIndex) {
    lIndex = This->num_tools + lIndex;
  }

  pPrevEntry = &This->Tools;
  LIST_FOR_EACH (pEntry, &This->Tools) {
    pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_GRAPH_TOOL, entry);
    if (pIt->dwIndex == lIndex) {
      return DMUS_E_ALREADY_EXISTS;
    }
    if (pIt->dwIndex > lIndex) {
      break ;
    }
    pPrevEntry = pEntry;
  }

  ++This->num_tools;
  pNewTool = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_GRAPH_TOOL));
  pNewTool->pTool = pTool;
  pNewTool->dwIndex = lIndex;
  IDirectMusicTool8_AddRef(pTool);
144
  IDirectMusicTool8_Init(pTool, iface);
145 146 147 148
  list_add_tail (pPrevEntry->next, &pNewTool->entry);

#if 0
  DWORD dwNum = 0;
149
  IDirectMusicTool8_GetMediaTypes(pTool, &dwNum);
150
#endif
151

152
  return DS_OK;
153 154
}

Mike McCormack's avatar
Mike McCormack committed
155
static HRESULT WINAPI IDirectMusicGraphImpl_IDirectMusicGraph_GetTool (LPDIRECTMUSICGRAPH iface, DWORD dwIndex, IDirectMusicTool** ppTool) {
156 157 158 159
  ICOM_THIS_MULTI(IDirectMusicGraphImpl, GraphVtbl, iface);
  struct list* pEntry = NULL;
  LPDMUS_PRIVATE_GRAPH_TOOL pIt = NULL;
  
160
  FIXME("(%p, %d, %p): stub\n", This, dwIndex, ppTool);
161 162 163 164 165 166

  LIST_FOR_EACH (pEntry, &This->Tools) {
    pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_GRAPH_TOOL, entry);
    if (pIt->dwIndex == dwIndex) {
      *ppTool = pIt->pTool;
      if (NULL != *ppTool) {
167
	IDirectMusicTool8_AddRef((LPDIRECTMUSICTOOL8) *ppTool);
168 169 170 171 172 173 174 175 176
      }
      return S_OK;      
    }
    if (pIt->dwIndex > dwIndex) {
      break ;
    }
  }

  return DMUS_E_NOT_FOUND;
177 178
}

Mike McCormack's avatar
Mike McCormack committed
179
static HRESULT WINAPI IDirectMusicGraphImpl_IDirectMusicGraph_RemoveTool (LPDIRECTMUSICGRAPH iface, IDirectMusicTool* pTool) {
180 181 182
  ICOM_THIS_MULTI(IDirectMusicGraphImpl, GraphVtbl, iface);
  FIXME("(%p, %p): stub\n", This, pTool);
  return S_OK;
183 184
}

185
static const IDirectMusicGraphVtbl DirectMusicGraph_Graph_Vtbl = {
186 187 188 189 190 191 192
  IDirectMusicGraphImpl_IDirectMusicGraph_QueryInterface,
  IDirectMusicGraphImpl_IDirectMusicGraph_AddRef,
  IDirectMusicGraphImpl_IDirectMusicGraph_Release,
  IDirectMusicGraphImpl_IDirectMusicGraph_StampPMsg,
  IDirectMusicGraphImpl_IDirectMusicGraph_InsertTool,
  IDirectMusicGraphImpl_IDirectMusicGraph_GetTool,
  IDirectMusicGraphImpl_IDirectMusicGraph_RemoveTool
193 194
};

195

196
/* IDirectMusicGraphImpl IDirectMusicObject part: */
197
static HRESULT WINAPI IDirectMusicGraphImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj) {
198
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, ObjectVtbl, iface);
199
	return IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
200 201
}

202
static ULONG WINAPI IDirectMusicGraphImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface) {
203
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, ObjectVtbl, iface);
204
	return IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
205 206
}

Mike McCormack's avatar
Mike McCormack committed
207
static ULONG WINAPI IDirectMusicGraphImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface) {
208
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, ObjectVtbl, iface);
209
	return IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
210 211
}

Mike McCormack's avatar
Mike McCormack committed
212
static HRESULT WINAPI IDirectMusicGraphImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
213
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, ObjectVtbl, iface);
214
	TRACE("(%p, %p)\n", This, pDesc);
215 216
	/* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
	memcpy (pDesc, This->pDesc, This->pDesc->dwSize);
217 218 219
	return S_OK;
}

Mike McCormack's avatar
Mike McCormack committed
220
static HRESULT WINAPI IDirectMusicGraphImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
221
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, ObjectVtbl, iface);
222
	TRACE("(%p, %p): setting descriptor:\n%s\n", This, pDesc, debugstr_DMUS_OBJECTDESC (pDesc));
223

224 225
	/* According to MSDN, we should copy only given values, not whole struct */	
	if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
226
		This->pDesc->guidObject = pDesc->guidObject;
227
	if (pDesc->dwValidData & DMUS_OBJ_CLASS)
228
		This->pDesc->guidClass = pDesc->guidClass;
229
	if (pDesc->dwValidData & DMUS_OBJ_NAME)
230
		lstrcpynW (This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
231
	if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
232
		lstrcpynW (This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);
233
	if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
234
		lstrcpynW (This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);
235
	if (pDesc->dwValidData & DMUS_OBJ_VERSION)
236
		This->pDesc->vVersion = pDesc->vVersion;
237
	if (pDesc->dwValidData & DMUS_OBJ_DATE)
238
		This->pDesc->ftDate = pDesc->ftDate;
239 240 241 242 243 244 245 246 247 248 249
	if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
		memcpy (&This->pDesc->llMemLength, &pDesc->llMemLength, sizeof (pDesc->llMemLength));				
		memcpy (This->pDesc->pbMemData, pDesc->pbMemData, sizeof (pDesc->pbMemData));
	}
	if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
		/* according to MSDN, we copy the stream */
		IStream_Clone (pDesc->pStream, &This->pDesc->pStream);	
	}
	
	/* add new flags */
	This->pDesc->dwValidData |= pDesc->dwValidData;
250 251 252 253

	return S_OK;
}

Mike McCormack's avatar
Mike McCormack committed
254
static HRESULT WINAPI IDirectMusicGraphImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) {
255 256 257 258
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, ObjectVtbl, iface);
	DMUS_PRIVATE_CHUNK Chunk;
	DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
	LARGE_INTEGER liMove; /* used when skipping chunks */
259

260
	TRACE("(%p, %p, %p)\n", This, pStream, pDesc);
261

262 263
	/* FIXME: should this be determined from stream? */
	pDesc->dwValidData |= DMUS_OBJ_CLASS;
264 265
	pDesc->guidClass = CLSID_DirectMusicGraph;

266
	IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
267
	TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
268 269 270 271 272 273 274 275 276 277 278
	switch (Chunk.fccID) {	
		case FOURCC_RIFF: {
			IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);				
			TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
			StreamSize = Chunk.dwSize - sizeof(FOURCC);
			StreamCount = 0;
			if (Chunk.fccID == DMUS_FOURCC_TOOLGRAPH_FORM) {
				TRACE_(dmfile)(": graph form\n");
				do {
					IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
					StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
279
					TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
					switch (Chunk.fccID) {
						case DMUS_FOURCC_GUID_CHUNK: {
							TRACE_(dmfile)(": GUID chunk\n");
							pDesc->dwValidData |= DMUS_OBJ_OBJECT;
							IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL);
							break;
						}
						case DMUS_FOURCC_VERSION_CHUNK: {
							TRACE_(dmfile)(": version chunk\n");
							pDesc->dwValidData |= DMUS_OBJ_VERSION;
							IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL);
							break;
						}
						case DMUS_FOURCC_CATEGORY_CHUNK: {
							TRACE_(dmfile)(": category chunk\n");
							pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
							IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL);
							break;
						}
						case FOURCC_LIST: {
							IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);				
							TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
							ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
							ListCount[0] = 0;
							switch (Chunk.fccID) {
								/* evil M$ UNFO list, which can (!?) contain INFO elements */
								case DMUS_FOURCC_UNFO_LIST: {
									TRACE_(dmfile)(": UNFO list\n");
									do {
										IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
										ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
311
										TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
										switch (Chunk.fccID) {
											/* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
                                             (though strings seem to be valid unicode) */
											case mmioFOURCC('I','N','A','M'):
											case DMUS_FOURCC_UNAM_CHUNK: {
												TRACE_(dmfile)(": name chunk\n");
												pDesc->dwValidData |= DMUS_OBJ_NAME;
												IStream_Read (pStream, pDesc->wszName, Chunk.dwSize, NULL);
												break;
											}
											case mmioFOURCC('I','A','R','T'):
											case DMUS_FOURCC_UART_CHUNK: {
												TRACE_(dmfile)(": artist chunk (ignored)\n");
												liMove.QuadPart = Chunk.dwSize;
												IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
												break;
											}
											case mmioFOURCC('I','C','O','P'):
											case DMUS_FOURCC_UCOP_CHUNK: {
												TRACE_(dmfile)(": copyright chunk (ignored)\n");
												liMove.QuadPart = Chunk.dwSize;
												IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
												break;
											}
											case mmioFOURCC('I','S','B','J'):
											case DMUS_FOURCC_USBJ_CHUNK: {
												TRACE_(dmfile)(": subject chunk (ignored)\n");
												liMove.QuadPart = Chunk.dwSize;
												IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
												break;
											}
											case mmioFOURCC('I','C','M','T'):
											case DMUS_FOURCC_UCMT_CHUNK: {
												TRACE_(dmfile)(": comment chunk (ignored)\n");
												liMove.QuadPart = Chunk.dwSize;
												IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
												break;
											}
											default: {
												TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
												liMove.QuadPart = Chunk.dwSize;
												IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
												break;						
											}
										}
357
										TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
									} while (ListCount[0] < ListSize[0]);
									break;
								}
								default: {
									TRACE_(dmfile)(": unknown (skipping)\n");
									liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
									IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
									break;						
								}
							}
							break;
						}	
						default: {
							TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
							liMove.QuadPart = Chunk.dwSize;
							IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
							break;						
						}
					}
377
					TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
				} while (StreamCount < StreamSize);
			} else {
				TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
				liMove.QuadPart = StreamSize;
				IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
				return E_FAIL;
			}
		
			TRACE_(dmfile)(": reading finished\n");
			break;
		}
		default: {
			TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
			liMove.QuadPart = Chunk.dwSize;
			IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
			return DMUS_E_INVALIDFILE;
		}
	}	
	
397
	TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc));
398
	
399 400 401
	return S_OK;
}

402
static const IDirectMusicObjectVtbl DirectMusicGraph_Object_Vtbl = {
403 404 405 406 407 408
	IDirectMusicGraphImpl_IDirectMusicObject_QueryInterface,
	IDirectMusicGraphImpl_IDirectMusicObject_AddRef,
	IDirectMusicGraphImpl_IDirectMusicObject_Release,
	IDirectMusicGraphImpl_IDirectMusicObject_GetDescriptor,
	IDirectMusicGraphImpl_IDirectMusicObject_SetDescriptor,
	IDirectMusicGraphImpl_IDirectMusicObject_ParseDescriptor
409 410
};

411
/* IDirectMusicGraphImpl IPersistStream part: */
412
static HRESULT WINAPI IDirectMusicGraphImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
413 414
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, PersistStreamVtbl, iface);
	return IDirectMusicGraphImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
415 416
}

417
static ULONG WINAPI IDirectMusicGraphImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
418 419
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, PersistStreamVtbl, iface);
	return IDirectMusicGraphImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
420 421
}

Mike McCormack's avatar
Mike McCormack committed
422
static ULONG WINAPI IDirectMusicGraphImpl_IPersistStream_Release (LPPERSISTSTREAM iface) {
423 424
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, PersistStreamVtbl, iface);
	return IDirectMusicGraphImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
425 426
}

Mike McCormack's avatar
Mike McCormack committed
427
static HRESULT WINAPI IDirectMusicGraphImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
428 429 430
	return E_NOTIMPL;
}

Mike McCormack's avatar
Mike McCormack committed
431
static HRESULT WINAPI IDirectMusicGraphImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
432 433 434
	return E_NOTIMPL;
}

Mike McCormack's avatar
Mike McCormack committed
435
static HRESULT WINAPI IDirectMusicGraphImpl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
436 437 438 439 440 441 442 443
	ICOM_THIS_MULTI(IDirectMusicGraphImpl, PersistStreamVtbl, iface);
	FOURCC chunkID;
	DWORD chunkSize, StreamSize, StreamCount, ListSize[3], ListCount[3];
	LARGE_INTEGER liMove; /* used when skipping chunks */

	FIXME("(%p, %p): Loading not implemented yet\n", This, pStm);
	IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
	IStream_Read (pStm, &chunkSize, sizeof(DWORD), NULL);
444
	TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
445 446 447 448 449 450 451 452 453 454 455 456 457
	switch (chunkID) {	
		case FOURCC_RIFF: {
			IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);				
			TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(chunkID));
			StreamSize = chunkSize - sizeof(FOURCC);
			StreamCount = 0;
			switch (chunkID) {
				case DMUS_FOURCC_TOOLGRAPH_FORM: {
					TRACE_(dmfile)(": graph form\n");
					do {
						IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
						IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
						StreamCount += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
458
						TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
						switch (chunkID) {
							case DMUS_FOURCC_GUID_CHUNK: {
								TRACE_(dmfile)(": GUID chunk\n");
								This->pDesc->dwValidData |= DMUS_OBJ_OBJECT;
								IStream_Read (pStm, &This->pDesc->guidObject, chunkSize, NULL);
								break;
							}
							case DMUS_FOURCC_VERSION_CHUNK: {
								TRACE_(dmfile)(": version chunk\n");
								This->pDesc->dwValidData |= DMUS_OBJ_VERSION;
								IStream_Read (pStm, &This->pDesc->vVersion, chunkSize, NULL);
								break;
							}
							case DMUS_FOURCC_CATEGORY_CHUNK: {
								TRACE_(dmfile)(": category chunk\n");
								This->pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
								IStream_Read (pStm, This->pDesc->wszCategory, chunkSize, NULL);
								break;
							}
							case FOURCC_LIST: {
								IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);				
								TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunkID));
								ListSize[0] = chunkSize - sizeof(FOURCC);
								ListCount[0] = 0;
								switch (chunkID) {
									case DMUS_FOURCC_UNFO_LIST: {
										TRACE_(dmfile)(": UNFO list\n");
										do {
											IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
											IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
											ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
490
											TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
											switch (chunkID) {
												/* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
                                              (though strings seem to be valid unicode) */
												case mmioFOURCC('I','N','A','M'):
												case DMUS_FOURCC_UNAM_CHUNK: {
													TRACE_(dmfile)(": name chunk\n");
													This->pDesc->dwValidData |= DMUS_OBJ_NAME;
													IStream_Read (pStm, This->pDesc->wszName, chunkSize, NULL);
													break;
												}
												case mmioFOURCC('I','A','R','T'):
												case DMUS_FOURCC_UART_CHUNK: {
													TRACE_(dmfile)(": artist chunk (ignored)\n");
													liMove.QuadPart = chunkSize;
													IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
													break;
												}
												case mmioFOURCC('I','C','O','P'):
												case DMUS_FOURCC_UCOP_CHUNK: {
													TRACE_(dmfile)(": copyright chunk (ignored)\n");
													liMove.QuadPart = chunkSize;
													IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
													break;
												}
												case mmioFOURCC('I','S','B','J'):
												case DMUS_FOURCC_USBJ_CHUNK: {
													TRACE_(dmfile)(": subject chunk (ignored)\n");
													liMove.QuadPart = chunkSize;
													IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
													break;
												}
												case mmioFOURCC('I','C','M','T'):
												case DMUS_FOURCC_UCMT_CHUNK: {
													TRACE_(dmfile)(": comment chunk (ignored)\n");
													liMove.QuadPart = chunkSize;
													IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
													break;
												}
												default: {
													TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
													liMove.QuadPart = chunkSize;
													IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
													break;						
												}
											}
536
											TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
										} while (ListCount[0] < ListSize[0]);
										break;
									}
									default: {
										TRACE_(dmfile)(": unknown (skipping)\n");
										liMove.QuadPart = chunkSize - sizeof(FOURCC);
										IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
										break;						
									}
								}
								break;
							}	
							default: {
								TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
								liMove.QuadPart = chunkSize;
								IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
								break;						
							}
						}
556
						TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
					} while (StreamCount < StreamSize);
					break;
				}
				default: {
					TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
					liMove.QuadPart = StreamSize;
					IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
					return E_FAIL;
				}
			}
			TRACE_(dmfile)(": reading finished\n");
			break;
		}
		default: {
			TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
			liMove.QuadPart = chunkSize;
			IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
			return E_FAIL;
		}
	}

578 579 580
	return S_OK;
}

Mike McCormack's avatar
Mike McCormack committed
581
static HRESULT WINAPI IDirectMusicGraphImpl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
582 583 584
	return E_NOTIMPL;
}

Mike McCormack's avatar
Mike McCormack committed
585
static HRESULT WINAPI IDirectMusicGraphImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
586 587 588
	return E_NOTIMPL;
}

589
static const IPersistStreamVtbl DirectMusicGraph_PersistStream_Vtbl = {
590 591 592 593 594 595 596 597
	IDirectMusicGraphImpl_IPersistStream_QueryInterface,
	IDirectMusicGraphImpl_IPersistStream_AddRef,
	IDirectMusicGraphImpl_IPersistStream_Release,
	IDirectMusicGraphImpl_IPersistStream_GetClassID,
	IDirectMusicGraphImpl_IPersistStream_IsDirty,
	IDirectMusicGraphImpl_IPersistStream_Load,
	IDirectMusicGraphImpl_IPersistStream_Save,
	IDirectMusicGraphImpl_IPersistStream_GetSizeMax
598
};
599 600 601

/* for ClassFactory */
HRESULT WINAPI DMUSIC_CreateDirectMusicGraphImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter) {
602 603 604 605
  IDirectMusicGraphImpl* obj;
  
  obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicGraphImpl));
  if (NULL == obj) {
606
    *ppobj = NULL;
607 608 609 610 611 612 613 614 615
    return E_OUTOFMEMORY;
  }
  obj->UnknownVtbl = &DirectMusicGraph_Unknown_Vtbl;
  obj->GraphVtbl = &DirectMusicGraph_Graph_Vtbl;
  obj->ObjectVtbl = &DirectMusicGraph_Object_Vtbl;
  obj->PersistStreamVtbl = &DirectMusicGraph_PersistStream_Vtbl;
  obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
  DM_STRUCT_INIT(obj->pDesc);
  obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
616
  obj->pDesc->guidClass = CLSID_DirectMusicGraph;
617 618
  obj->ref = 0; /* will be inited by QueryInterface */
  list_init (&obj->Tools);
619

620
  return IDirectMusicGraphImpl_IUnknown_QueryInterface ((LPUNKNOWN)&obj->UnknownVtbl, lpcGUID, ppobj);
621
}