msvcrt: Make error strings static.
[wine/wine-gecko.git] / dlls / dmband / bandtrack.c
blob32aca1afbd8d5b6630d1958bcbc39cf99e6d7c80
1 /* IDirectMusicBandTrack Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "dmband_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(dmband);
23 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
25 /*****************************************************************************
26 * IDirectMusicBandTrack implementation
28 /* IDirectMusicBandTrack IUnknown part: */
29 static HRESULT WINAPI IDirectMusicBandTrack_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
30 ICOM_THIS_MULTI(IDirectMusicBandTrack, UnknownVtbl, iface);
31 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
33 if (IsEqualIID (riid, &IID_IUnknown)) {
34 *ppobj = (LPUNKNOWN)&This->UnknownVtbl;
35 IUnknown_AddRef (iface);
36 return S_OK;
37 } else if (IsEqualIID (riid, &IID_IDirectMusicTrack)
38 || IsEqualIID (riid, &IID_IDirectMusicTrack8)) {
39 *ppobj = (LPDIRECTMUSICTRACK8)&This->TrackVtbl;
40 IUnknown_AddRef (iface);
41 return S_OK;
42 } else if (IsEqualIID (riid, &IID_IPersistStream)) {
43 *ppobj = (LPPERSISTSTREAM)&This->PersistStreamVtbl;
44 IUnknown_AddRef (iface);
45 return S_OK;
48 WARN("(%p, %s,%p): not found\n", This, debugstr_dmguid(riid), ppobj);
49 return E_NOINTERFACE;
52 static ULONG WINAPI IDirectMusicBandTrack_IUnknown_AddRef (LPUNKNOWN iface) {
53 ICOM_THIS_MULTI(IDirectMusicBandTrack, UnknownVtbl, iface);
54 ULONG ref = InterlockedIncrement(&This->ref);
56 TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
58 DMBAND_LockModule();
60 return ref;
63 static ULONG WINAPI IDirectMusicBandTrack_IUnknown_Release (LPUNKNOWN iface) {
64 ICOM_THIS_MULTI(IDirectMusicBandTrack, UnknownVtbl, iface);
65 ULONG ref = InterlockedDecrement(&This->ref);
67 TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
69 if (ref == 0) {
70 HeapFree(GetProcessHeap(), 0, This);
73 DMBAND_UnlockModule();
75 return ref;
78 static const IUnknownVtbl DirectMusicBandTrack_Unknown_Vtbl = {
79 IDirectMusicBandTrack_IUnknown_QueryInterface,
80 IDirectMusicBandTrack_IUnknown_AddRef,
81 IDirectMusicBandTrack_IUnknown_Release
84 /* IDirectMusicBandTrack IDirectMusicTrack8 part: */
85 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_QueryInterface (LPDIRECTMUSICTRACK8 iface, REFIID riid, LPVOID *ppobj) {
86 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
87 return IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
90 static ULONG WINAPI IDirectMusicBandTrack_IDirectMusicTrack_AddRef (LPDIRECTMUSICTRACK8 iface) {
91 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
92 return IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
95 static ULONG WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Release (LPDIRECTMUSICTRACK8 iface) {
96 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
97 return IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
100 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Init (LPDIRECTMUSICTRACK8 iface, IDirectMusicSegment* pSegment) {
101 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
102 FIXME("(%p, %p): stub\n", This, pSegment);
103 return S_OK;
106 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_InitPlay (LPDIRECTMUSICTRACK8 iface, IDirectMusicSegmentState* pSegmentState, IDirectMusicPerformance* pPerformance, void** ppStateData, DWORD dwVirtualTrack8ID, DWORD dwFlags) {
107 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
108 FIXME("(%p, %p, %p, %p, %ld, %ld): stub\n", This, pSegmentState, pPerformance, ppStateData, dwVirtualTrack8ID, dwFlags);
109 return S_OK;
112 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_EndPlay (LPDIRECTMUSICTRACK8 iface, void* pStateData) {
113 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
114 FIXME("(%p, %p): stub\n", This, pStateData);
115 return S_OK;
118 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Play (LPDIRECTMUSICTRACK8 iface, void* pStateData, MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, DWORD dwFlags, IDirectMusicPerformance* pPerf, IDirectMusicSegmentState* pSegSt, DWORD dwVirtualID) {
119 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
121 FIXME("(%p, %p, %ld, %ld, %ld, %ld, %p, %p, %ld): semi-stub\n", This, pStateData, mtStart, mtEnd, mtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
122 /* Sends following pMSG:
123 - DMUS_PATCH_PMSG
124 - DMUS_TRANSPOSE_PMSG
125 - DMUS_CHANNEL_PRIORITY_PMSG
126 - DMUS_MIDI_PMSG
129 return S_OK;
132 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_GetParam (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, MUSIC_TIME mtTime, MUSIC_TIME* pmtNext, void* pParam) {
133 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
134 FIXME("(%p, %s, %ld, %p, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pmtNext, pParam);
135 return S_OK;
138 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_SetParam (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, MUSIC_TIME mtTime, void* pParam) {
139 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
140 FIXME("(%p, %s, %ld, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pParam);
141 return S_OK;
144 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_IsParamSupported (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType) {
145 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
147 TRACE("(%p, %s): ", This, debugstr_dmguid(rguidType));
148 if (IsEqualGUID (rguidType, &GUID_BandParam)
149 || IsEqualGUID (rguidType, &GUID_Clear_All_Bands)
150 || IsEqualGUID (rguidType, &GUID_ConnectToDLSCollection)
151 || IsEqualGUID (rguidType, &GUID_Disable_Auto_Download)
152 || IsEqualGUID (rguidType, &GUID_Download)
153 || IsEqualGUID (rguidType, &GUID_DownloadToAudioPath)
154 || IsEqualGUID (rguidType, &GUID_Enable_Auto_Download)
155 || IsEqualGUID (rguidType, &GUID_IDirectMusicBand)
156 || IsEqualGUID (rguidType, &GUID_StandardMIDIFile)
157 || IsEqualGUID (rguidType, &GUID_Unload)
158 || IsEqualGUID (rguidType, &GUID_UnloadFromAudioPath)) {
159 TRACE("param supported\n");
160 return S_OK;
163 TRACE("param unsupported\n");
164 return DMUS_E_TYPE_UNSUPPORTED;
167 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_AddNotificationType (LPDIRECTMUSICTRACK8 iface, REFGUID rguidNotificationType) {
168 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
169 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
170 return S_OK;
173 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_RemoveNotificationType (LPDIRECTMUSICTRACK8 iface, REFGUID rguidNotificationType) {
174 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
175 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
176 return S_OK;
179 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Clone (LPDIRECTMUSICTRACK8 iface, MUSIC_TIME mtStart, MUSIC_TIME mtEnd, IDirectMusicTrack** ppTrack) {
180 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
181 FIXME("(%p, %ld, %ld, %p): stub\n", This, mtStart, mtEnd, ppTrack);
182 return S_OK;
185 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_PlayEx (LPDIRECTMUSICTRACK8 iface, void* pStateData, REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD dwFlags, IDirectMusicPerformance* pPerf, IDirectMusicSegmentState* pSegSt, DWORD dwVirtualID) {
186 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
187 FIXME("(%p, %p, %lli, %lli, %lli, %ld, %p, %p, %ld): stub\n", This, pStateData, rtStart, rtEnd, rtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
188 return S_OK;
191 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_GetParamEx (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, REFERENCE_TIME rtTime, REFERENCE_TIME* prtNext, void* pParam, void* pStateData, DWORD dwFlags) {
192 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
193 FIXME("(%p, %s, %lli, %p, %p, %p, %ld): stub\n", This, debugstr_dmguid(rguidType), rtTime, prtNext, pParam, pStateData, dwFlags);
194 return S_OK;
197 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_SetParamEx (LPDIRECTMUSICTRACK8 iface, REFGUID rguidType, REFERENCE_TIME rtTime, void* pParam, void* pStateData, DWORD dwFlags) {
198 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
199 FIXME("(%p, %s, %lli, %p, %p, %ld): stub\n", This, debugstr_dmguid(rguidType), rtTime, pParam, pStateData, dwFlags);
200 return S_OK;
203 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Compose (LPDIRECTMUSICTRACK8 iface, IUnknown* pContext, DWORD dwTrackGroup, IDirectMusicTrack** ppResultTrack) {
204 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
205 FIXME("(%p, %p, %ld, %p): stub\n", This, pContext, dwTrackGroup, ppResultTrack);
206 return S_OK;
209 static HRESULT WINAPI IDirectMusicBandTrack_IDirectMusicTrack_Join (LPDIRECTMUSICTRACK8 iface, IDirectMusicTrack* pNewTrack, MUSIC_TIME mtJoin, IUnknown* pContext, DWORD dwTrackGroup, IDirectMusicTrack** ppResultTrack) {
210 ICOM_THIS_MULTI(IDirectMusicBandTrack, TrackVtbl, iface);
211 FIXME("(%p, %p, %ld, %p, %ld, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
212 return S_OK;
215 static const IDirectMusicTrack8Vtbl DirectMusicBandTrack_DirectMusicTrack_Vtbl = {
216 IDirectMusicBandTrack_IDirectMusicTrack_QueryInterface,
217 IDirectMusicBandTrack_IDirectMusicTrack_AddRef,
218 IDirectMusicBandTrack_IDirectMusicTrack_Release,
219 IDirectMusicBandTrack_IDirectMusicTrack_Init,
220 IDirectMusicBandTrack_IDirectMusicTrack_InitPlay,
221 IDirectMusicBandTrack_IDirectMusicTrack_EndPlay,
222 IDirectMusicBandTrack_IDirectMusicTrack_Play,
223 IDirectMusicBandTrack_IDirectMusicTrack_GetParam,
224 IDirectMusicBandTrack_IDirectMusicTrack_SetParam,
225 IDirectMusicBandTrack_IDirectMusicTrack_IsParamSupported,
226 IDirectMusicBandTrack_IDirectMusicTrack_AddNotificationType,
227 IDirectMusicBandTrack_IDirectMusicTrack_RemoveNotificationType,
228 IDirectMusicBandTrack_IDirectMusicTrack_Clone,
229 IDirectMusicBandTrack_IDirectMusicTrack_PlayEx,
230 IDirectMusicBandTrack_IDirectMusicTrack_GetParamEx,
231 IDirectMusicBandTrack_IDirectMusicTrack_SetParamEx,
232 IDirectMusicBandTrack_IDirectMusicTrack_Compose,
233 IDirectMusicBandTrack_IDirectMusicTrack_Join
236 /* IDirectMusicBandTrack IPersistStream part: */
237 static HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
238 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
239 return IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
242 static ULONG WINAPI IDirectMusicBandTrack_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
243 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
244 return IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
247 static ULONG WINAPI IDirectMusicBandTrack_IPersistStream_Release (LPPERSISTSTREAM iface) {
248 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
249 return IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
252 static HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
253 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
254 TRACE("(%p, %p)\n", This, pClassID);
255 memcpy(pClassID, &CLSID_DirectMusicBandTrack, sizeof(CLSID));
256 return S_OK;
259 static HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
260 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
261 FIXME("(%p): stub, always S_FALSE\n", This);
262 return S_FALSE;
265 static HRESULT IDirectMusicBandTrack_IPersistStream_LoadBand (LPPERSISTSTREAM iface, IStream* pClonedStream, IDirectMusicBand** ppBand,
266 DMUS_PRIVATE_BAND_ITEM_HEADER* pHeader) {
268 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
269 HRESULT hr = E_FAIL;
270 IPersistStream* pPersistStream = NULL;
272 hr = CoCreateInstance (&CLSID_DirectMusicBand, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicBand, (LPVOID*) ppBand);
273 if (FAILED(hr)) {
274 ERR(": could not create object\n");
275 return hr;
277 /* acquire PersistStream interface */
278 hr = IDirectMusicBand_QueryInterface (*ppBand, &IID_IPersistStream, (LPVOID*) &pPersistStream);
279 if (FAILED(hr)) {
280 ERR(": could not acquire IPersistStream\n");
281 return hr;
283 /* load */
284 hr = IPersistStream_Load (pPersistStream, pClonedStream);
285 if (FAILED(hr)) {
286 ERR(": failed to load object\n");
287 return hr;
290 /* release all loading-related stuff */
291 IPersistStream_Release (pPersistStream);
294 * @TODO insert pBand into This
296 if (SUCCEEDED(hr)) {
297 LPDMUS_PRIVATE_BAND pNewBand = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_BAND));
298 if (NULL == pNewBand) {
299 ERR(": no more memory\n");
300 return E_OUTOFMEMORY;
302 memcpy(&pNewBand->pBandHeader, pHeader, sizeof(DMUS_PRIVATE_BAND_ITEM_HEADER));
303 pNewBand->ppBand = (IDirectMusicBandImpl*)((char*)(*ppBand) - offsetof(IDirectMusicBandImpl,BandVtbl));
304 IDirectMusicBand_AddRef(*ppBand);
305 list_add_tail (&This->Bands, &pNewBand->entry);
308 return S_OK;
311 static HRESULT IDirectMusicBandTrack_IPersistStream_ParseBandsList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
313 /*ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);*/
314 HRESULT hr = E_FAIL;
315 DMUS_PRIVATE_CHUNK Chunk;
316 DWORD StreamSize, ListSize[3], ListCount[3];
317 LARGE_INTEGER liMove; /* used when skipping chunks */
319 IDirectMusicBand* pBand = NULL;
320 DMUS_PRIVATE_BAND_ITEM_HEADER header;
322 if (pChunk->fccID != DMUS_FOURCC_BANDS_LIST) {
323 ERR_(dmfile)(": %s chunk should be a BANDS list\n", debugstr_fourcc (pChunk->fccID));
324 return E_FAIL;
327 ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
328 ListCount[0] = 0;
330 do {
331 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
332 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
333 TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
334 switch (Chunk.fccID) {
335 case FOURCC_LIST: {
336 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
337 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
338 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
339 ListCount[1] = 0;
340 do {
341 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
342 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
343 TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
344 switch (Chunk.fccID) {
345 case DMUS_FOURCC_BANDITEM_CHUNK: {
346 DMUS_IO_BAND_ITEM_HEADER tmp_header;
347 TRACE_(dmfile)(": Band Item chunk v1\n");
349 IStream_Read (pStm, &tmp_header, sizeof(DMUS_IO_BAND_ITEM_HEADER), NULL);
350 TRACE_(dmfile)(" - lBandTime: %lu\n", tmp_header.lBandTime);
352 header.dwVersion = 1;
353 header.lBandTime = tmp_header.lBandTime;
354 break;
356 case DMUS_FOURCC_BANDITEM_CHUNK2: {
357 DMUS_IO_BAND_ITEM_HEADER2 tmp_header2;
358 TRACE_(dmfile)(": Band Item chunk v2\n");
360 IStream_Read (pStm, &tmp_header2, sizeof(DMUS_IO_BAND_ITEM_HEADER2), NULL);
361 TRACE_(dmfile)(" - lBandTimeLogical: %lu\n", tmp_header2.lBandTimeLogical);
362 TRACE_(dmfile)(" - lBandTimePhysical: %lu\n", tmp_header2.lBandTimePhysical);
364 header.dwVersion = 2;
365 header.lBandTimeLogical = tmp_header2.lBandTimeLogical;
366 header.lBandTimePhysical = tmp_header2.lBandTimePhysical;
367 break;
369 case FOURCC_RIFF: {
370 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
371 TRACE_(dmfile)(": RIFF chunk of type %s\n", debugstr_fourcc(Chunk.fccID));
372 StreamSize = Chunk.dwSize - sizeof(FOURCC);
373 switch (Chunk.fccID) {
374 case DMUS_FOURCC_BAND_FORM: {
375 LPSTREAM pClonedStream = NULL;
376 TRACE_(dmfile)(": BAND RIFF\n");
378 IStream_Clone (pStm, &pClonedStream);
380 liMove.QuadPart = 0;
381 liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
382 IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
384 hr = IDirectMusicBandTrack_IPersistStream_LoadBand (iface, pClonedStream, &pBand, &header);
385 if (FAILED(hr)) {
386 ERR(": could not load track\n");
387 return hr;
389 IStream_Release (pClonedStream);
391 IDirectMusicTrack_Release(pBand); pBand = NULL; /* now we can release at as it inserted */
393 /** now safe move the cursor */
394 liMove.QuadPart = StreamSize;
395 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
396 break;
398 default: {
399 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
400 liMove.QuadPart = StreamSize;
401 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
402 break;
405 break;
407 default: {
408 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
409 liMove.QuadPart = Chunk.dwSize;
410 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
411 break;
414 TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
415 } while (ListCount[1] < ListSize[1]);
416 break;
418 default: {
419 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
420 liMove.QuadPart = Chunk.dwSize;
421 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
422 break;
425 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
426 } while (ListCount[0] < ListSize[0]);
428 return S_OK;
431 static HRESULT IDirectMusicBandTrack_IPersistStream_ParseBandTrackForm (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
433 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
434 HRESULT hr = E_FAIL;
435 DMUS_PRIVATE_CHUNK Chunk;
436 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
437 LARGE_INTEGER liMove; /* used when skipping chunks */
439 if (pChunk->fccID != DMUS_FOURCC_BANDTRACK_FORM) {
440 ERR_(dmfile)(": %s chunk should be a BANDTRACK form\n", debugstr_fourcc (pChunk->fccID));
441 return E_FAIL;
444 StreamSize = pChunk->dwSize - sizeof(FOURCC);
445 StreamCount = 0;
447 do {
448 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
449 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
450 TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
452 hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, This->pDesc);
453 if (FAILED(hr)) return hr;
455 if (hr == S_FALSE) {
456 switch (Chunk.fccID) {
457 case DMUS_FOURCC_BANDTRACK_CHUNK: {
458 TRACE_(dmfile)(": BandTrack chunk\n");
459 IStream_Read (pStm, &This->header, sizeof(DMUS_IO_BAND_TRACK_HEADER), NULL);
460 TRACE_(dmfile)(" - bAutoDownload: %u\n", This->header.bAutoDownload);
461 break;
463 case FOURCC_LIST: {
464 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
465 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
466 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
467 ListCount[0] = 0;
468 switch (Chunk.fccID) {
469 case DMUS_FOURCC_UNFO_LIST: {
470 TRACE_(dmfile)(": UNFO list\n");
471 do {
472 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
473 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
474 TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
476 hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, This->pDesc);
477 if (FAILED(hr)) return hr;
479 if (hr == S_FALSE) {
480 switch (Chunk.fccID) {
481 default: {
482 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
483 liMove.QuadPart = Chunk.dwSize;
484 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
485 break;
489 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
490 } while (ListCount[0] < ListSize[0]);
491 break;
493 case DMUS_FOURCC_BANDS_LIST: {
494 TRACE_(dmfile)(": TRACK list\n");
495 hr = IDirectMusicBandTrack_IPersistStream_ParseBandsList (iface, &Chunk, pStm);
496 if (FAILED(hr)) return hr;
497 break;
499 default: {
500 TRACE_(dmfile)(": unknown (skipping)\n");
501 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
502 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
503 break;
506 break;
508 default: {
509 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
510 liMove.QuadPart = Chunk.dwSize;
511 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
512 break;
516 TRACE_(dmfile)(": StreamCount[0] = %ld < StreamSize[0] = %ld\n", StreamCount, StreamSize);
517 } while (StreamCount < StreamSize);
519 return S_OK;
523 static HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
524 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
526 DMUS_PRIVATE_CHUNK Chunk;
527 LARGE_INTEGER liMove;
528 HRESULT hr;
530 TRACE("(%p, %p): Loading\n", This, pStm);
532 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
533 TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
534 switch (Chunk.fccID) {
535 case FOURCC_RIFF: {
536 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
537 TRACE_(dmfile)(": %s chunk (size = %ld)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
538 switch (Chunk.fccID) {
539 case DMUS_FOURCC_BANDTRACK_FORM: {
540 TRACE_(dmfile)(": Band track form\n");
541 hr = IDirectMusicBandTrack_IPersistStream_ParseBandTrackForm (iface, &Chunk, pStm);
542 if (FAILED(hr)) return hr;
543 break;
545 default: {
546 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
547 liMove.QuadPart = Chunk.dwSize;
548 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
549 return E_FAIL;
552 TRACE_(dmfile)(": reading finished\n");
553 break;
555 default: {
556 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
557 liMove.QuadPart = Chunk.dwSize;
558 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
559 return E_FAIL;
563 return S_OK;
566 static HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
567 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
568 FIXME("(%p): Saving not implemented yet\n", This);
569 return E_NOTIMPL;
572 static HRESULT WINAPI IDirectMusicBandTrack_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
573 ICOM_THIS_MULTI(IDirectMusicBandTrack, PersistStreamVtbl, iface);
574 FIXME("(%p, %p): stub\n", This, pcbSize);
575 return E_NOTIMPL;
578 static const IPersistStreamVtbl DirectMusicBandTrack_PerststStream_Vtbl = {
579 IDirectMusicBandTrack_IPersistStream_QueryInterface,
580 IDirectMusicBandTrack_IPersistStream_AddRef,
581 IDirectMusicBandTrack_IPersistStream_Release,
582 IDirectMusicBandTrack_IPersistStream_GetClassID,
583 IDirectMusicBandTrack_IPersistStream_IsDirty,
584 IDirectMusicBandTrack_IPersistStream_Load,
585 IDirectMusicBandTrack_IPersistStream_Save,
586 IDirectMusicBandTrack_IPersistStream_GetSizeMax
589 /* for ClassFactory */
590 HRESULT WINAPI DMUSIC_CreateDirectMusicBandTrack (LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter) {
591 IDirectMusicBandTrack* track;
593 track = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicBandTrack));
594 if (NULL == track) {
595 *ppobj = NULL;
596 return E_OUTOFMEMORY;
598 track->UnknownVtbl = &DirectMusicBandTrack_Unknown_Vtbl;
599 track->TrackVtbl = &DirectMusicBandTrack_DirectMusicTrack_Vtbl;
600 track->PersistStreamVtbl = &DirectMusicBandTrack_PerststStream_Vtbl;
601 track->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
602 DM_STRUCT_INIT(track->pDesc);
603 track->pDesc->dwValidData |= DMUS_OBJ_CLASS;
604 memcpy (&track->pDesc->guidClass, &CLSID_DirectMusicBandTrack, sizeof (CLSID));
605 track->ref = 0; /* will be inited by QueryInterface */
606 list_init (&track->Bands);
608 return IDirectMusicBandTrack_IUnknown_QueryInterface ((LPUNKNOWN)&track->UnknownVtbl, lpcGUID, ppobj);