audiopath.c 25.3 KB
Newer Older
1 2
/* IDirectMusicAudioPath Implementation
 *
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
/*****************************************************************************
 * IDirectMusicAudioPathImpl implementation
 */
28
/* IDirectMusicAudioPath IUnknown part: */
29
static HRESULT WINAPI IDirectMusicAudioPathImpl_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
30
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, UnknownVtbl, iface);
31
	TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(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_IDirectMusicAudioPath)) {
38
		*ppobj = &This->AudioPathVtbl;
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_dmguid(riid), ppobj);
52 53 54
	return E_NOINTERFACE;
}

55
static ULONG WINAPI IDirectMusicAudioPathImpl_IUnknown_AddRef (LPUNKNOWN iface) {
56
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, 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 IDirectMusicAudioPathImpl_IUnknown_Release (LPUNKNOWN iface) {
67
  ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, UnknownVtbl, iface);
68
  ULONG ref = InterlockedDecrement(&This->ref);
69
  TRACE("(%p): ReleaseRef to %d\n", This, ref);
70
  
71 72 73 74 75 76
  if (ref == 0) {
    if (This->pDSBuffer) {
      IDirectSoundBuffer8_Release(This->pDSBuffer);
    }
    HeapFree(GetProcessHeap(), 0, This);
  }
77 78 79

  DMIME_UnlockModule();
  
80
  return ref;
81 82
}

83
static const IUnknownVtbl DirectMusicAudioPath_Unknown_Vtbl = {
84 85 86 87 88 89
	IDirectMusicAudioPathImpl_IUnknown_QueryInterface,
	IDirectMusicAudioPathImpl_IUnknown_AddRef,
	IDirectMusicAudioPathImpl_IUnknown_Release
};

/* IDirectMusicAudioPathImpl IDirectMusicAudioPath part: */
90
static HRESULT WINAPI IDirectMusicAudioPathImpl_IDirectMusicAudioPath_QueryInterface (LPDIRECTMUSICAUDIOPATH iface, REFIID riid, LPVOID *ppobj) {
91
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, AudioPathVtbl, iface);
92
	return IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
93 94
}

95
static ULONG WINAPI IDirectMusicAudioPathImpl_IDirectMusicAudioPath_AddRef (LPDIRECTMUSICAUDIOPATH iface) {
96
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, AudioPathVtbl, iface);
97
	return IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
98 99
}

Mike McCormack's avatar
Mike McCormack committed
100
static ULONG WINAPI IDirectMusicAudioPathImpl_IDirectMusicAudioPath_Release (LPDIRECTMUSICAUDIOPATH iface) {
101
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, AudioPathVtbl, iface);
102
	return IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
103 104
}

Mike McCormack's avatar
Mike McCormack committed
105
static HRESULT WINAPI IDirectMusicAudioPathImpl_IDirectMusicAudioPath_GetObjectInPath (LPDIRECTMUSICAUDIOPATH iface, DWORD dwPChannel, DWORD dwStage, DWORD dwBuffer, REFGUID guidObject, WORD dwIndex, REFGUID iidInterface, void** ppObject) {
106
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, AudioPathVtbl, iface);
107

108
	FIXME("(%p, %d, %d, %d, %s, %d, %s, %p): stub\n", This, dwPChannel, dwStage, dwBuffer, debugstr_dmguid(guidObject), dwIndex, debugstr_dmguid(iidInterface), ppObject);
109
	    
110 111 112
	switch (dwStage) {
	case DMUS_PATH_BUFFER:
	  {
113 114
	    if (IsEqualIID (iidInterface, &IID_IDirectSoundBuffer8)) {
	      IDirectSoundBuffer8_QueryInterface (This->pDSBuffer, &IID_IDirectSoundBuffer8, ppObject);
115 116
	      TRACE("returning %p\n",*ppObject);
	      return S_OK;
117 118
	    } else if (IsEqualIID (iidInterface, &IID_IDirectSound3DBuffer)) {
	      IDirectSoundBuffer8_QueryInterface (This->pDSBuffer, &IID_IDirectSound3DBuffer, ppObject);
119 120 121 122 123 124 125 126 127
	      TRACE("returning %p\n",*ppObject);
	      return S_OK;
	    } else {
	      FIXME("Bad iid\n");
	    }
	  }
	  break;

	case DMUS_PATH_PRIMARY_BUFFER: {
128 129
	  if (IsEqualIID (iidInterface, &IID_IDirectSound3DListener)) {
	    IDirectSoundBuffer8_QueryInterface (This->pPrimary, &IID_IDirectSound3DListener, ppObject);
130
	    return S_OK;
131
	  } else {
132 133 134 135 136 137 138
	    FIXME("bad iid...\n");
	  }
	}
	break;

	case DMUS_PATH_AUDIOPATH_GRAPH:
	  {
139
	    if (IsEqualIID (iidInterface, &IID_IDirectMusicGraph)) {
140 141
	      if (NULL == This->pToolGraph) {
		IDirectMusicGraphImpl* pGraph;
142
		DMUSIC_CreateDirectMusicGraphImpl (&IID_IDirectMusicGraph, (LPVOID*)&pGraph, NULL);
143 144
		This->pToolGraph = (IDirectMusicGraph*) pGraph;
	      }
145
	      *ppObject = This->pToolGraph;
146
	      IDirectMusicGraph_AddRef((LPDIRECTMUSICGRAPH) *ppObject);
147 148 149 150 151 152 153 154 155 156 157 158 159 160
	      return S_OK;
	    }
	  }
	  break;

	case DMUS_PATH_AUDIOPATH_TOOL:
	  {
	    /* TODO */
	  }
	  break;

	case DMUS_PATH_PERFORMANCE:
	  {
	    /* TODO check wanted GUID */
161
	    *ppObject = This->pPerf;
162
	    IUnknown_AddRef((LPUNKNOWN) *ppObject);
163 164 165 166 167 168 169
	    return S_OK;
	  }
	  break;

	case DMUS_PATH_PERFORMANCE_GRAPH:
	  {
	    IDirectMusicGraph* pPerfoGraph = NULL; 
170
	    IDirectMusicPerformance8_GetGraph(This->pPerf, &pPerfoGraph);
171 172
	    if (NULL == pPerfoGraph) {
	      IDirectMusicGraphImpl* pGraph = NULL; 
173
	      DMUSIC_CreateDirectMusicGraphImpl (&IID_IDirectMusicGraph, (LPVOID*)&pGraph, NULL);			
174
	      IDirectMusicPerformance8_SetGraph(This->pPerf, (IDirectMusicGraph*) pGraph);
175
	      /* we need release as SetGraph do an AddRef */
176
	      IDirectMusicGraph_Release((LPDIRECTMUSICGRAPH) pGraph);
177 178
	      pPerfoGraph = (LPDIRECTMUSICGRAPH) pGraph;
	    }
179
	    *ppObject = pPerfoGraph;
180 181 182 183 184 185 186 187 188 189 190 191 192
	    return S_OK;
	  }
	  break;

	case DMUS_PATH_PERFORMANCE_TOOL:
	default:
	  break;
	}

	*ppObject = NULL;
	return E_INVALIDARG;
}

193
static HRESULT WINAPI IDirectMusicAudioPathImpl_IDirectMusicAudioPath_Activate (LPDIRECTMUSICAUDIOPATH iface, BOOL fActivate) {
194 195 196 197 198 199 200 201
  ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, AudioPathVtbl, iface);
  FIXME("(%p, %d): stub\n", This, fActivate);
  if (!fActivate) {
    if (!This->fActive) return S_OK;
    This->fActive = FALSE;
  } else {
    if (This->fActive) return S_OK;
    This->fActive = TRUE;
202 203 204
    if (NULL != This->pDSBuffer) {
      IDirectSoundBuffer_Stop(This->pDSBuffer);
    }
205 206
  }
  return S_OK;
207 208
}

209
static HRESULT WINAPI IDirectMusicAudioPathImpl_IDirectMusicAudioPath_SetVolume (LPDIRECTMUSICAUDIOPATH iface, LONG lVolume, DWORD dwDuration) {
210
  ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, AudioPathVtbl, iface);
211
  FIXME("(%p, %i, %d): stub\n", This, lVolume, dwDuration);
212
  return S_OK;
213 214
}

Mike McCormack's avatar
Mike McCormack committed
215
static HRESULT WINAPI IDirectMusicAudioPathImpl_IDirectMusicAudioPath_ConvertPChannel (LPDIRECTMUSICAUDIOPATH iface, DWORD dwPChannelIn, DWORD* pdwPChannelOut) {
216
  ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, AudioPathVtbl, iface);
217
  FIXME("(%p, %d, %p): stub\n", This, dwPChannelIn, pdwPChannelOut);
218
  return S_OK;
219 220
}

221
static const IDirectMusicAudioPathVtbl DirectMusicAudioPath_AudioPath_Vtbl = {
222 223 224 225 226 227 228
  IDirectMusicAudioPathImpl_IDirectMusicAudioPath_QueryInterface,
  IDirectMusicAudioPathImpl_IDirectMusicAudioPath_AddRef,
  IDirectMusicAudioPathImpl_IDirectMusicAudioPath_Release,
  IDirectMusicAudioPathImpl_IDirectMusicAudioPath_GetObjectInPath,
  IDirectMusicAudioPathImpl_IDirectMusicAudioPath_Activate,
  IDirectMusicAudioPathImpl_IDirectMusicAudioPath_SetVolume,
  IDirectMusicAudioPathImpl_IDirectMusicAudioPath_ConvertPChannel
229 230
};

231
/* IDirectMusicAudioPathImpl IDirectMusicObject part: */
232
static HRESULT WINAPI IDirectMusicAudioPathImpl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj) {
233
  ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, ObjectVtbl, iface);
234
  return IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
235 236
}

237
static ULONG WINAPI IDirectMusicAudioPathImpl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface) {
238
  ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, ObjectVtbl, iface);
239
  return IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
240 241
}

Mike McCormack's avatar
Mike McCormack committed
242
static ULONG WINAPI IDirectMusicAudioPathImpl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface) {
243
  ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, ObjectVtbl, iface);
244
  return IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
245 246
}

Mike McCormack's avatar
Mike McCormack committed
247
static HRESULT WINAPI IDirectMusicAudioPathImpl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
248 249 250 251 252
  ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, ObjectVtbl, iface);
  TRACE("(%p, %p)\n", This, pDesc);
  /* 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);
  return S_OK;
253 254
}

Mike McCormack's avatar
Mike McCormack committed
255
static HRESULT WINAPI IDirectMusicAudioPathImpl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
256
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, ObjectVtbl, iface);
257
	TRACE("(%p, %p): setting descriptor:\n%s\n", This, pDesc, debugstr_DMUS_OBJECTDESC (pDesc));
258

259 260
	/* According to MSDN, we should copy only given values, not whole struct */	
	if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
261
		This->pDesc->guidObject = pDesc->guidObject;
262
	if (pDesc->dwValidData & DMUS_OBJ_CLASS)
263
		This->pDesc->guidClass = pDesc->guidClass;
264
	if (pDesc->dwValidData & DMUS_OBJ_NAME)
265
		lstrcpynW (This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
266
	if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
267
		lstrcpynW (This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);
268
	if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
269
		lstrcpynW (This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);
270
	if (pDesc->dwValidData & DMUS_OBJ_VERSION)
271
		This->pDesc->vVersion = pDesc->vVersion;
272
	if (pDesc->dwValidData & DMUS_OBJ_DATE)
273
		This->pDesc->ftDate = pDesc->ftDate;
274
	if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
275 276
		This->pDesc->llMemLength = pDesc->llMemLength;
		memcpy (This->pDesc->pbMemData, pDesc->pbMemData, pDesc->llMemLength);
277 278 279 280 281 282 283 284
	}
	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;
285 286 287 288

	return S_OK;
}

Mike McCormack's avatar
Mike McCormack committed
289
static HRESULT WINAPI IDirectMusicAudioPathImpl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) {
290 291 292 293
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, ObjectVtbl, iface);
	DMUS_PRIVATE_CHUNK Chunk;
	DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
	LARGE_INTEGER liMove; /* used when skipping chunks */
294

295
	TRACE("(%p, %p, %p)\n", This, pStream, pDesc);
296

297 298
	/* FIXME: should this be determined from stream? */
	pDesc->dwValidData |= DMUS_OBJ_CLASS;
299 300
	pDesc->guidClass = CLSID_DirectMusicAudioPath;

301
	IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
302
	TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
303 304 305 306 307 308 309 310 311 312 313
	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_AUDIOPATH_FORM) {
				TRACE_(dmfile)(": audio path form\n");
				do {
					IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
					StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
314
					TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
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
					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;
346
										TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
										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: {
386
												TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
387 388 389 390 391
												liMove.QuadPart = Chunk.dwSize;
												IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
												break;						
											}
										}
392
										TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
393 394 395 396 397 398 399 400 401 402 403 404 405
									} 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: {
406
							TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
407 408 409 410 411
							liMove.QuadPart = Chunk.dwSize;
							IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
							break;						
						}
					}
412
					TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
				} 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;
		}
	}	
	
432
	TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc));
433
	
434 435 436
	return S_OK;
}

437
static const IDirectMusicObjectVtbl DirectMusicAudioPath_Object_Vtbl = {
438 439 440 441 442 443
	IDirectMusicAudioPathImpl_IDirectMusicObject_QueryInterface,
	IDirectMusicAudioPathImpl_IDirectMusicObject_AddRef,
	IDirectMusicAudioPathImpl_IDirectMusicObject_Release,
	IDirectMusicAudioPathImpl_IDirectMusicObject_GetDescriptor,
	IDirectMusicAudioPathImpl_IDirectMusicObject_SetDescriptor,
	IDirectMusicAudioPathImpl_IDirectMusicObject_ParseDescriptor
444 445
};

446
/* IDirectMusicAudioPathImpl IPersistStream part: */
447
static HRESULT WINAPI IDirectMusicAudioPathImpl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
448
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, PersistStreamVtbl, iface);
449
	return IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
450 451
}

452
static ULONG WINAPI IDirectMusicAudioPathImpl_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
453
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, PersistStreamVtbl, iface);
454
	return IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
455 456
}

Mike McCormack's avatar
Mike McCormack committed
457
static ULONG WINAPI IDirectMusicAudioPathImpl_IPersistStream_Release (LPPERSISTSTREAM iface) {
458
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, PersistStreamVtbl, iface);
459
	return IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
460 461
}

Mike McCormack's avatar
Mike McCormack committed
462
static HRESULT WINAPI IDirectMusicAudioPathImpl_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
463 464 465
	return E_NOTIMPL;
}

Mike McCormack's avatar
Mike McCormack committed
466
static HRESULT WINAPI IDirectMusicAudioPathImpl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
467 468 469
	return E_NOTIMPL;
}

Mike McCormack's avatar
Mike McCormack committed
470
static HRESULT WINAPI IDirectMusicAudioPathImpl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
471 472 473 474 475 476 477 478 479
	ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, 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);
480
	TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
481 482 483 484 485 486 487 488 489 490 491 492 493
	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_AUDIOPATH_FORM: {
					TRACE_(dmfile)(": audio path form\n");
					do {
						IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
						IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
						StreamCount += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
494
						TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
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
						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;
526
											TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
											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: {
566
													TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
567 568 569 570 571
													liMove.QuadPart = chunkSize;
													IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
													break;						
												}
											}
572
											TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
573 574 575 576 577 578 579 580 581 582 583 584 585
										} 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: {
586
								TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
587 588 589 590 591
								liMove.QuadPart = chunkSize;
								IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
								break;						
							}
						}
592
						TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
					} 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;
		}
	}

614
	return S_OK;
615
}
616

Mike McCormack's avatar
Mike McCormack committed
617
static HRESULT WINAPI IDirectMusicAudioPathImpl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
618 619 620
	return E_NOTIMPL;
}

Mike McCormack's avatar
Mike McCormack committed
621
static HRESULT WINAPI IDirectMusicAudioPathImpl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
622 623 624
	return E_NOTIMPL;
}

625
static const IPersistStreamVtbl DirectMusicAudioPath_PersistStream_Vtbl = {
626 627 628 629 630 631 632 633
	IDirectMusicAudioPathImpl_IPersistStream_QueryInterface,
	IDirectMusicAudioPathImpl_IPersistStream_AddRef,
	IDirectMusicAudioPathImpl_IPersistStream_Release,
	IDirectMusicAudioPathImpl_IPersistStream_GetClassID,
	IDirectMusicAudioPathImpl_IPersistStream_IsDirty,
	IDirectMusicAudioPathImpl_IPersistStream_Load,
	IDirectMusicAudioPathImpl_IPersistStream_Save,
	IDirectMusicAudioPathImpl_IPersistStream_GetSizeMax
634
};
635 636 637 638 639 640 641

/* for ClassFactory */
HRESULT WINAPI DMUSIC_CreateDirectMusicAudioPathImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter) {
	IDirectMusicAudioPathImpl* obj;
	
	obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicAudioPathImpl));
	if (NULL == obj) {
642
		*ppobj = NULL;
643 644 645 646 647 648 649 650 651
		return E_OUTOFMEMORY;
	}
	obj->UnknownVtbl = &DirectMusicAudioPath_Unknown_Vtbl;
	obj->AudioPathVtbl = &DirectMusicAudioPath_AudioPath_Vtbl;
	obj->ObjectVtbl = &DirectMusicAudioPath_Object_Vtbl;
	obj->PersistStreamVtbl = &DirectMusicAudioPath_PersistStream_Vtbl;
	obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
	DM_STRUCT_INIT(obj->pDesc);
	obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
652
	obj->pDesc->guidClass = CLSID_DirectMusicAudioPath;
653
	obj->ref = 0; /* will be inited by QueryInterface */
654

655 656
	return IDirectMusicAudioPathImpl_IUnknown_QueryInterface ((LPUNKNOWN)&obj->UnknownVtbl, lpcGUID, ppobj);
}