regedit: Allow importing strings with escaped NULL.
[wine.git] / dlls / dmime / segment.c
blobd17b341a55635192f48b3277dd273de87fe95e27
1 /* IDirectMusicSegment8 Implementation
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 "dmime_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmime);
24 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
26 /*****************************************************************************
27 * IDirectMusicSegmentImpl implementation
29 typedef struct IDirectMusicSegment8Impl {
30 IDirectMusicSegment8 IDirectMusicSegment8_iface;
31 const IDirectMusicObjectVtbl *ObjectVtbl;
32 const IPersistStreamVtbl *PersistStreamVtbl;
33 LONG ref;
34 DMUS_OBJECTDESC *pDesc;
35 DMUS_IO_SEGMENT_HEADER header;
36 IDirectMusicGraph *pGraph;
37 struct list Tracks;
38 } IDirectMusicSegment8Impl;
40 static inline IDirectMusicSegment8Impl *impl_from_IDirectMusicSegment8(IDirectMusicSegment8 *iface)
42 return CONTAINING_RECORD(iface, IDirectMusicSegment8Impl, IDirectMusicSegment8_iface);
45 static HRESULT WINAPI IDirectMusicSegment8Impl_QueryInterface(IDirectMusicSegment8 *iface,
46 REFIID riid, void **ret_iface)
48 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
50 *ret_iface = NULL;
52 if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IDirectMusicSegment) ||
53 IsEqualIID(riid, &IID_IDirectMusicSegment2) ||
54 IsEqualIID (riid, &IID_IDirectMusicSegment8))
55 *ret_iface = iface;
56 else if (IsEqualIID (riid, &IID_IDirectMusicObject))
57 *ret_iface = &This->ObjectVtbl;
58 else if (IsEqualIID (riid, &IID_IPersistStream))
59 *ret_iface = &This->PersistStreamVtbl;
60 else {
61 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
62 return E_NOINTERFACE;
65 IUnknown_AddRef((IUnknown*)*ret_iface);
66 return S_OK;
69 static ULONG WINAPI IDirectMusicSegment8Impl_AddRef(IDirectMusicSegment8 *iface)
71 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
72 LONG ref = InterlockedIncrement(&This->ref);
74 TRACE("(%p) ref=%d\n", This, ref);
76 return ref;
79 static ULONG WINAPI IDirectMusicSegment8Impl_Release(IDirectMusicSegment8 *iface)
81 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
82 LONG ref = InterlockedDecrement(&This->ref);
84 TRACE("(%p) ref=%d\n", This, ref);
86 if (!ref) {
87 HeapFree(GetProcessHeap(), 0, This);
88 DMIME_UnlockModule();
91 return ref;
94 static HRESULT WINAPI IDirectMusicSegment8Impl_GetLength(IDirectMusicSegment8 *iface,
95 MUSIC_TIME *pmtLength)
97 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
99 TRACE("(%p, %p)\n", This, pmtLength);
100 if (NULL == pmtLength) {
101 return E_POINTER;
103 *pmtLength = This->header.mtLength;
104 return S_OK;
107 static HRESULT WINAPI IDirectMusicSegment8Impl_SetLength(IDirectMusicSegment8 *iface,
108 MUSIC_TIME mtLength)
110 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
112 TRACE("(%p, %d)\n", This, mtLength);
113 This->header.mtLength = mtLength;
114 return S_OK;
117 static HRESULT WINAPI IDirectMusicSegment8Impl_GetRepeats(IDirectMusicSegment8 *iface,
118 DWORD *pdwRepeats)
120 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
122 TRACE("(%p, %p)\n", This, pdwRepeats);
123 if (NULL == pdwRepeats) {
124 return E_POINTER;
126 *pdwRepeats = This->header.dwRepeats;
127 return S_OK;
130 static HRESULT WINAPI IDirectMusicSegment8Impl_SetRepeats(IDirectMusicSegment8 *iface,
131 DWORD dwRepeats)
133 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
135 TRACE("(%p, %d)\n", This, dwRepeats);
136 This->header.dwRepeats = dwRepeats;
137 return S_OK;
140 static HRESULT WINAPI IDirectMusicSegment8Impl_GetDefaultResolution(IDirectMusicSegment8 *iface,
141 DWORD *pdwResolution)
143 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
145 TRACE("(%p, %p)\n", This, pdwResolution);
146 if (NULL == pdwResolution) {
147 return E_POINTER;
149 *pdwResolution = This->header.dwResolution;
150 return S_OK;
153 static HRESULT WINAPI IDirectMusicSegment8Impl_SetDefaultResolution(IDirectMusicSegment8 *iface,
154 DWORD dwResolution)
156 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
158 TRACE("(%p, %d)\n", This, dwResolution);
159 This->header.dwResolution = dwResolution;
160 return S_OK;
163 static HRESULT WINAPI IDirectMusicSegment8Impl_GetTrack(IDirectMusicSegment8 *iface,
164 REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, IDirectMusicTrack **ppTrack)
166 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
167 CLSID pIt_clsid;
168 struct list* pEntry = NULL;
169 LPDMUS_PRIVATE_SEGMENT_TRACK pIt = NULL;
170 IPersistStream* pCLSIDStream = NULL;
171 HRESULT hr = S_OK;
173 TRACE("(%p, %s, %d, 0x%x, %p)\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, ppTrack);
175 if (NULL == ppTrack) {
176 return E_POINTER;
179 LIST_FOR_EACH (pEntry, &This->Tracks) {
180 pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_SEGMENT_TRACK, entry);
181 TRACE(" - %p -> 0x%x,%p\n", pIt, pIt->dwGroupBits, pIt->pTrack);
182 if (0xFFFFFFFF != dwGroupBits && 0 == (pIt->dwGroupBits & dwGroupBits)) continue ;
183 if (FALSE == IsEqualGUID(&GUID_NULL, rguidType)) {
185 * it rguidType is not null we must check if CLSIDs are equal
186 * and the unique way to get it is using IPersistStream Interface
188 hr = IDirectMusicTrack_QueryInterface(pIt->pTrack, &IID_IPersistStream, (void**) &pCLSIDStream);
189 if (FAILED(hr)) {
190 ERR("(%p): object %p don't implement IPersistStream Interface. Expect a crash (critical problem)\n", This, pIt->pTrack);
191 continue ;
193 hr = IPersistStream_GetClassID(pCLSIDStream, &pIt_clsid);
194 IPersistStream_Release(pCLSIDStream); pCLSIDStream = NULL;
195 if (FAILED(hr)) {
196 ERR("(%p): non-implemented GetClassID for object %p\n", This, pIt->pTrack);
197 continue ;
199 TRACE(" - %p -> %s\n", pIt, debugstr_dmguid(&pIt_clsid));
200 if (FALSE == IsEqualGUID(&pIt_clsid, rguidType)) continue ;
202 if (0 == dwIndex) {
203 *ppTrack = pIt->pTrack;
204 IDirectMusicTrack_AddRef(*ppTrack);
205 return S_OK;
207 --dwIndex;
209 return DMUS_E_NOT_FOUND;
212 static HRESULT WINAPI IDirectMusicSegment8Impl_GetTrackGroup(IDirectMusicSegment8 *iface,
213 IDirectMusicTrack *pTrack, DWORD *pdwGroupBits)
215 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
216 struct list* pEntry = NULL;
217 LPDMUS_PRIVATE_SEGMENT_TRACK pIt = NULL;
219 TRACE("(%p, %p, %p)\n", This, pTrack, pdwGroupBits);
221 if (NULL == pdwGroupBits) {
222 return E_POINTER;
225 LIST_FOR_EACH (pEntry, &This->Tracks) {
226 pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_SEGMENT_TRACK, entry);
227 TRACE(" - %p -> %d,%p\n", pIt, pIt->dwGroupBits, pIt->pTrack);
228 if (NULL != pIt && pIt->pTrack == pTrack) {
229 *pdwGroupBits = pIt->dwGroupBits;
230 return S_OK;
234 return DMUS_E_NOT_FOUND;
237 static HRESULT WINAPI IDirectMusicSegment8Impl_InsertTrack(IDirectMusicSegment8 *iface,
238 IDirectMusicTrack *pTrack, DWORD dwGroupBits)
240 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
241 DWORD i = 0;
242 struct list* pEntry = NULL;
243 LPDMUS_PRIVATE_SEGMENT_TRACK pIt = NULL;
244 LPDMUS_PRIVATE_SEGMENT_TRACK pNewSegTrack = NULL;
246 TRACE("(%p, %p, %d)\n", This, pTrack, dwGroupBits);
248 LIST_FOR_EACH (pEntry, &This->Tracks) {
249 i++;
250 pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_SEGMENT_TRACK, entry);
251 TRACE(" - #%u: %p -> %d,%p\n", i, pIt, pIt->dwGroupBits, pIt->pTrack);
252 if (NULL != pIt && pIt->pTrack == pTrack) {
253 ERR("(%p, %p): track is already in list\n", This, pTrack);
254 return E_FAIL;
258 pNewSegTrack = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_SEGMENT_TRACK));
259 if (NULL == pNewSegTrack)
260 return E_OUTOFMEMORY;
262 pNewSegTrack->dwGroupBits = dwGroupBits;
263 pNewSegTrack->pTrack = pTrack;
264 IDirectMusicTrack_Init(pTrack, (IDirectMusicSegment *)iface);
265 IDirectMusicTrack_AddRef(pTrack);
266 list_add_tail (&This->Tracks, &pNewSegTrack->entry);
268 return S_OK;
271 static HRESULT WINAPI IDirectMusicSegment8Impl_RemoveTrack(IDirectMusicSegment8 *iface,
272 IDirectMusicTrack *pTrack)
274 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
275 struct list* pEntry = NULL;
276 LPDMUS_PRIVATE_SEGMENT_TRACK pIt = NULL;
278 TRACE("(%p, %p)\n", This, pTrack);
280 LIST_FOR_EACH (pEntry, &This->Tracks) {
281 pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_SEGMENT_TRACK, entry);
282 if (pIt->pTrack == pTrack) {
283 TRACE("(%p, %p): track in list\n", This, pTrack);
285 list_remove(&pIt->entry);
286 IDirectMusicTrack_Init(pIt->pTrack, NULL);
287 IDirectMusicTrack_Release(pIt->pTrack);
288 HeapFree(GetProcessHeap(), 0, pIt);
290 return S_OK;
294 return S_FALSE;
297 static HRESULT WINAPI IDirectMusicSegment8Impl_InitPlay(IDirectMusicSegment8 *iface,
298 IDirectMusicSegmentState **ppSegState, IDirectMusicPerformance *pPerformance, DWORD dwFlags)
300 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
301 HRESULT hr;
303 FIXME("(%p, %p, %p, %d): semi-stub\n", This, ppSegState, pPerformance, dwFlags);
304 if (NULL == ppSegState) {
305 return E_POINTER;
307 hr = create_dmsegmentstate(&IID_IDirectMusicSegmentState,(void**) ppSegState);
308 if (FAILED(hr)) {
309 return hr;
311 /* TODO: DMUS_SEGF_FLAGS */
312 return S_OK;
315 static HRESULT WINAPI IDirectMusicSegment8Impl_GetGraph(IDirectMusicSegment8 *iface,
316 IDirectMusicGraph **ppGraph)
318 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
320 FIXME("(%p, %p): semi-stub\n", This, ppGraph);
321 if (NULL == ppGraph) {
322 return E_POINTER;
324 if (NULL == This->pGraph) {
325 return DMUS_E_NOT_FOUND;
327 /**
328 * should return This, as seen in msdn
329 * "...The segment object implements IDirectMusicGraph directly..."
331 *ppGraph = This->pGraph;
332 IDirectMusicGraph_AddRef(This->pGraph);
333 return S_OK;
336 static HRESULT WINAPI IDirectMusicSegment8Impl_SetGraph(IDirectMusicSegment8 *iface,
337 IDirectMusicGraph *pGraph)
339 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
341 FIXME("(%p, %p): to complete\n", This, pGraph);
342 if (NULL != This->pGraph) {
343 IDirectMusicGraph_Release(This->pGraph);
345 This->pGraph = pGraph;
346 if (NULL != This->pGraph) {
347 IDirectMusicGraph_AddRef(This->pGraph);
349 return S_OK;
352 static HRESULT WINAPI IDirectMusicSegment8Impl_AddNotificationType(IDirectMusicSegment8 *iface,
353 REFGUID rguidNotificationType)
355 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
356 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
357 return S_OK;
360 static HRESULT WINAPI IDirectMusicSegment8Impl_RemoveNotificationType(IDirectMusicSegment8 *iface,
361 REFGUID rguidNotificationType)
363 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
364 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
365 return S_OK;
368 static HRESULT WINAPI IDirectMusicSegment8Impl_GetParam(IDirectMusicSegment8 *iface,
369 REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, MUSIC_TIME *pmtNext,
370 void *pParam)
372 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
373 CLSID pIt_clsid;
374 struct list* pEntry = NULL;
375 IDirectMusicTrack* pTrack = NULL;
376 IPersistStream* pCLSIDStream = NULL;
377 LPDMUS_PRIVATE_SEGMENT_TRACK pIt = NULL;
378 HRESULT hr = S_OK;
380 FIXME("(%p, %s, 0x%x, %d, %d, %p, %p)\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pmtNext, pParam);
382 if (DMUS_SEG_ANYTRACK == dwIndex) {
384 LIST_FOR_EACH (pEntry, &This->Tracks) {
385 pIt = LIST_ENTRY(pEntry, DMUS_PRIVATE_SEGMENT_TRACK, entry);
387 hr = IDirectMusicTrack_QueryInterface(pIt->pTrack, &IID_IPersistStream, (void**) &pCLSIDStream);
388 if (FAILED(hr)) {
389 ERR("(%p): object %p don't implement IPersistStream Interface. Expect a crash (critical problem)\n", This, pIt->pTrack);
390 continue ;
393 TRACE(" - %p -> 0x%x,%p\n", pIt, pIt->dwGroupBits, pIt->pTrack);
395 if (0xFFFFFFFF != dwGroupBits && 0 == (pIt->dwGroupBits & dwGroupBits)) continue ;
396 hr = IPersistStream_GetClassID(pCLSIDStream, &pIt_clsid);
397 IPersistStream_Release(pCLSIDStream); pCLSIDStream = NULL;
398 if (FAILED(hr)) {
399 ERR("(%p): non-implemented GetClassID for object %p\n", This, pIt->pTrack);
400 continue ;
402 if (FALSE == IsEqualGUID(&pIt_clsid, rguidType)) continue ;
403 if (FAILED(IDirectMusicTrack_IsParamSupported(pIt->pTrack, rguidType))) continue ;
404 hr = IDirectMusicTrack_GetParam(pIt->pTrack, rguidType, mtTime, pmtNext, pParam);
405 if (SUCCEEDED(hr)) return hr;
407 ERR("(%p): not found\n", This);
408 return DMUS_E_TRACK_NOT_FOUND;
411 hr = IDirectMusicSegment8Impl_GetTrack(iface, &GUID_NULL, dwGroupBits, dwIndex, &pTrack);
412 if (FAILED(hr)) {
413 ERR("(%p): not found\n", This);
414 return DMUS_E_TRACK_NOT_FOUND;
417 hr = IDirectMusicTrack_GetParam(pTrack, rguidType, mtTime, pmtNext, pParam);
418 IDirectMusicTrack_Release(pTrack); pTrack = NULL;
420 return hr;
423 static HRESULT WINAPI IDirectMusicSegment8Impl_SetParam(IDirectMusicSegment8 *iface,
424 REFGUID rguidType, DWORD dwGroupBits, DWORD dwIndex, MUSIC_TIME mtTime, void *pParam)
426 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
427 FIXME("(%p, %s, %d, %d, %d, %p): stub\n", This, debugstr_dmguid(rguidType), dwGroupBits, dwIndex, mtTime, pParam);
428 return S_OK;
431 static HRESULT WINAPI IDirectMusicSegment8Impl_Clone(IDirectMusicSegment8 *iface,
432 MUSIC_TIME mtStart, MUSIC_TIME mtEnd, IDirectMusicSegment **ppSegment)
434 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
435 FIXME("(%p, %d, %d, %p): stub\n", This, mtStart, mtEnd, ppSegment);
436 return S_OK;
439 static HRESULT WINAPI IDirectMusicSegment8Impl_SetStartPoint(IDirectMusicSegment8 *iface,
440 MUSIC_TIME mtStart)
442 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
444 TRACE("(%p, %d)\n", This, mtStart);
445 if (mtStart >= This->header.mtLength) {
446 return DMUS_E_OUT_OF_RANGE;
448 This->header.mtPlayStart = mtStart;
449 return S_OK;
452 static HRESULT WINAPI IDirectMusicSegment8Impl_GetStartPoint(IDirectMusicSegment8 *iface,
453 MUSIC_TIME *pmtStart)
455 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
457 TRACE("(%p, %p)\n", This, pmtStart);
458 if (NULL == pmtStart) {
459 return E_POINTER;
461 *pmtStart = This->header.mtPlayStart;
462 return S_OK;
465 static HRESULT WINAPI IDirectMusicSegment8Impl_SetLoopPoints(IDirectMusicSegment8 *iface,
466 MUSIC_TIME mtStart, MUSIC_TIME mtEnd)
468 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
470 TRACE("(%p, %d, %d)\n", This, mtStart, mtEnd);
471 if (mtStart >= This->header.mtLength || mtEnd > This->header.mtLength || mtStart > mtEnd) {
472 return DMUS_E_OUT_OF_RANGE;
474 This->header.mtLoopStart = mtStart;
475 This->header.mtLoopEnd = mtEnd;
476 return S_OK;
479 static HRESULT WINAPI IDirectMusicSegment8Impl_GetLoopPoints(IDirectMusicSegment8 *iface,
480 MUSIC_TIME *pmtStart, MUSIC_TIME *pmtEnd)
482 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
484 TRACE("(%p, %p, %p)\n", This, pmtStart, pmtEnd);
485 if (NULL == pmtStart || NULL == pmtEnd) {
486 return E_POINTER;
488 *pmtStart = This->header.mtLoopStart;
489 *pmtEnd = This->header.mtLoopEnd;
490 return S_OK;
493 static HRESULT WINAPI IDirectMusicSegment8Impl_SetPChannelsUsed(IDirectMusicSegment8 *iface,
494 DWORD dwNumPChannels, DWORD *paPChannels)
496 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
497 FIXME("(%p, %d, %p): stub\n", This, dwNumPChannels, paPChannels);
498 return S_OK;
501 static HRESULT WINAPI IDirectMusicSegment8Impl_SetTrackConfig(IDirectMusicSegment8 *iface,
502 REFGUID rguidTrackClassID, DWORD dwGroupBits, DWORD dwIndex, DWORD dwFlagsOn,
503 DWORD dwFlagsOff)
505 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
506 FIXME("(%p, %s, %d, %d, %d, %d): stub\n", This, debugstr_dmguid(rguidTrackClassID), dwGroupBits, dwIndex, dwFlagsOn, dwFlagsOff);
507 return S_OK;
510 static HRESULT WINAPI IDirectMusicSegment8Impl_GetAudioPathConfig(IDirectMusicSegment8 *iface,
511 IUnknown **ppAudioPathConfig)
513 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
514 FIXME("(%p, %p): stub\n", This, ppAudioPathConfig);
515 return S_OK;
518 static HRESULT WINAPI IDirectMusicSegment8Impl_Compose(IDirectMusicSegment8 *iface,
519 MUSIC_TIME mtTime, IDirectMusicSegment *pFromSegment, IDirectMusicSegment *pToSegment,
520 IDirectMusicSegment **ppComposedSegment)
522 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
523 FIXME("(%p, %d, %p, %p, %p): stub\n", This, mtTime, pFromSegment, pToSegment, ppComposedSegment);
524 return S_OK;
527 static HRESULT WINAPI IDirectMusicSegment8Impl_Download(IDirectMusicSegment8 *iface,
528 IUnknown *pAudioPath)
530 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
531 FIXME("(%p, %p): stub\n", This, pAudioPath);
532 return S_OK;
535 static HRESULT WINAPI IDirectMusicSegment8Impl_Unload(IDirectMusicSegment8 *iface,
536 IUnknown *pAudioPath)
538 IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface);
539 FIXME("(%p, %p): stub\n", This, pAudioPath);
540 return S_OK;
543 static const IDirectMusicSegment8Vtbl dmsegment8_vtbl = {
544 IDirectMusicSegment8Impl_QueryInterface,
545 IDirectMusicSegment8Impl_AddRef,
546 IDirectMusicSegment8Impl_Release,
547 IDirectMusicSegment8Impl_GetLength,
548 IDirectMusicSegment8Impl_SetLength,
549 IDirectMusicSegment8Impl_GetRepeats,
550 IDirectMusicSegment8Impl_SetRepeats,
551 IDirectMusicSegment8Impl_GetDefaultResolution,
552 IDirectMusicSegment8Impl_SetDefaultResolution,
553 IDirectMusicSegment8Impl_GetTrack,
554 IDirectMusicSegment8Impl_GetTrackGroup,
555 IDirectMusicSegment8Impl_InsertTrack,
556 IDirectMusicSegment8Impl_RemoveTrack,
557 IDirectMusicSegment8Impl_InitPlay,
558 IDirectMusicSegment8Impl_GetGraph,
559 IDirectMusicSegment8Impl_SetGraph,
560 IDirectMusicSegment8Impl_AddNotificationType,
561 IDirectMusicSegment8Impl_RemoveNotificationType,
562 IDirectMusicSegment8Impl_GetParam,
563 IDirectMusicSegment8Impl_SetParam,
564 IDirectMusicSegment8Impl_Clone,
565 IDirectMusicSegment8Impl_SetStartPoint,
566 IDirectMusicSegment8Impl_GetStartPoint,
567 IDirectMusicSegment8Impl_SetLoopPoints,
568 IDirectMusicSegment8Impl_GetLoopPoints,
569 IDirectMusicSegment8Impl_SetPChannelsUsed,
570 IDirectMusicSegment8Impl_SetTrackConfig,
571 IDirectMusicSegment8Impl_GetAudioPathConfig,
572 IDirectMusicSegment8Impl_Compose,
573 IDirectMusicSegment8Impl_Download,
574 IDirectMusicSegment8Impl_Unload
577 /* IDirectMusicSegment8Impl IDirectMusicObject part: */
578 static HRESULT WINAPI IDirectMusicSegment8Impl_IDirectMusicObject_QueryInterface (LPDIRECTMUSICOBJECT iface, REFIID riid, LPVOID *ppobj) {
579 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, ObjectVtbl, iface);
580 return IDirectMusicSegment8_QueryInterface(&This->IDirectMusicSegment8_iface, riid, ppobj);
583 static ULONG WINAPI IDirectMusicSegment8Impl_IDirectMusicObject_AddRef (LPDIRECTMUSICOBJECT iface) {
584 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, ObjectVtbl, iface);
585 return IDirectMusicSegment8_AddRef(&This->IDirectMusicSegment8_iface);
588 static ULONG WINAPI IDirectMusicSegment8Impl_IDirectMusicObject_Release (LPDIRECTMUSICOBJECT iface) {
589 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, ObjectVtbl, iface);
590 return IDirectMusicSegment8_Release(&This->IDirectMusicSegment8_iface);
593 static HRESULT WINAPI IDirectMusicSegment8Impl_IDirectMusicObject_GetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
594 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, ObjectVtbl, iface);
595 TRACE("(%p, %p)\n", This, pDesc);
596 /* I think we shouldn't return pointer here since then values can be changed; it'd be a mess */
597 memcpy (pDesc, This->pDesc, This->pDesc->dwSize);
598 return S_OK;
601 static HRESULT WINAPI IDirectMusicSegment8Impl_IDirectMusicObject_SetDescriptor (LPDIRECTMUSICOBJECT iface, LPDMUS_OBJECTDESC pDesc) {
602 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, ObjectVtbl, iface);
603 TRACE("(%p, %p): setting descriptor:\n%s\n", This, pDesc, debugstr_DMUS_OBJECTDESC (pDesc));
605 /* According to MSDN, we should copy only given values, not whole struct */
606 if (pDesc->dwValidData & DMUS_OBJ_OBJECT)
607 This->pDesc->guidObject = pDesc->guidObject;
608 if (pDesc->dwValidData & DMUS_OBJ_CLASS)
609 This->pDesc->guidClass = pDesc->guidClass;
610 if (pDesc->dwValidData & DMUS_OBJ_NAME)
611 lstrcpynW (This->pDesc->wszName, pDesc->wszName, DMUS_MAX_NAME);
612 if (pDesc->dwValidData & DMUS_OBJ_CATEGORY)
613 lstrcpynW (This->pDesc->wszCategory, pDesc->wszCategory, DMUS_MAX_CATEGORY);
614 if (pDesc->dwValidData & DMUS_OBJ_FILENAME)
615 lstrcpynW (This->pDesc->wszFileName, pDesc->wszFileName, DMUS_MAX_FILENAME);
616 if (pDesc->dwValidData & DMUS_OBJ_VERSION)
617 This->pDesc->vVersion = pDesc->vVersion;
618 if (pDesc->dwValidData & DMUS_OBJ_DATE)
619 This->pDesc->ftDate = pDesc->ftDate;
620 if (pDesc->dwValidData & DMUS_OBJ_MEMORY) {
621 This->pDesc->llMemLength = pDesc->llMemLength;
622 memcpy (This->pDesc->pbMemData, pDesc->pbMemData, pDesc->llMemLength);
624 if (pDesc->dwValidData & DMUS_OBJ_STREAM) {
625 /* according to MSDN, we copy the stream */
626 IStream_Clone (pDesc->pStream, &This->pDesc->pStream);
629 /* add new flags */
630 This->pDesc->dwValidData |= pDesc->dwValidData;
632 return S_OK;
635 static HRESULT WINAPI IDirectMusicSegment8Impl_IDirectMusicObject_ParseDescriptor (LPDIRECTMUSICOBJECT iface, LPSTREAM pStream, LPDMUS_OBJECTDESC pDesc) {
636 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, ObjectVtbl, iface);
637 DMUS_PRIVATE_CHUNK Chunk;
638 DWORD StreamSize, StreamCount, ListSize[1], ListCount[1];
639 LARGE_INTEGER liMove; /* used when skipping chunks */
641 TRACE("(%p,%p, %p)\n", This, pStream, pDesc);
643 /* FIXME: should this be determined from stream? */
644 pDesc->dwValidData |= DMUS_OBJ_CLASS;
645 pDesc->guidClass = CLSID_DirectMusicSegment;
647 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
648 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
649 switch (Chunk.fccID) {
650 case FOURCC_RIFF: {
651 IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);
652 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
653 StreamSize = Chunk.dwSize - sizeof(FOURCC);
654 StreamCount = 0;
655 if (Chunk.fccID == DMUS_FOURCC_SEGMENT_FORM) {
656 TRACE_(dmfile)(": segment form\n");
657 do {
658 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
659 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
660 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
661 switch (Chunk.fccID) {
662 case DMUS_FOURCC_GUID_CHUNK: {
663 TRACE_(dmfile)(": GUID chunk\n");
664 pDesc->dwValidData |= DMUS_OBJ_OBJECT;
665 IStream_Read (pStream, &pDesc->guidObject, Chunk.dwSize, NULL);
666 break;
668 case DMUS_FOURCC_VERSION_CHUNK: {
669 TRACE_(dmfile)(": version chunk\n");
670 pDesc->dwValidData |= DMUS_OBJ_VERSION;
671 IStream_Read (pStream, &pDesc->vVersion, Chunk.dwSize, NULL);
672 break;
674 case DMUS_FOURCC_CATEGORY_CHUNK: {
675 TRACE_(dmfile)(": category chunk\n");
676 pDesc->dwValidData |= DMUS_OBJ_CATEGORY;
677 IStream_Read (pStream, pDesc->wszCategory, Chunk.dwSize, NULL);
678 break;
680 case FOURCC_LIST: {
681 IStream_Read (pStream, &Chunk.fccID, sizeof(FOURCC), NULL);
682 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
683 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
684 ListCount[0] = 0;
685 switch (Chunk.fccID) {
686 /* evil M$ UNFO list, which can (!?) contain INFO elements */
687 case DMUS_FOURCC_UNFO_LIST: {
688 TRACE_(dmfile)(": UNFO list\n");
689 do {
690 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
691 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
692 TRACE_(dmfile)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
693 switch (Chunk.fccID) {
694 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
695 (though strings seem to be valid unicode) */
696 case mmioFOURCC('I','N','A','M'):
697 case DMUS_FOURCC_UNAM_CHUNK: {
698 TRACE_(dmfile)(": name chunk\n");
699 pDesc->dwValidData |= DMUS_OBJ_NAME;
700 IStream_Read (pStream, pDesc->wszName, Chunk.dwSize, NULL);
701 break;
703 case mmioFOURCC('I','A','R','T'):
704 case DMUS_FOURCC_UART_CHUNK: {
705 TRACE_(dmfile)(": artist chunk (ignored)\n");
706 liMove.QuadPart = Chunk.dwSize;
707 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
708 break;
710 case mmioFOURCC('I','C','O','P'):
711 case DMUS_FOURCC_UCOP_CHUNK: {
712 TRACE_(dmfile)(": copyright chunk (ignored)\n");
713 liMove.QuadPart = Chunk.dwSize;
714 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
715 break;
717 case mmioFOURCC('I','S','B','J'):
718 case DMUS_FOURCC_USBJ_CHUNK: {
719 TRACE_(dmfile)(": subject chunk (ignored)\n");
720 liMove.QuadPart = Chunk.dwSize;
721 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
722 break;
724 case mmioFOURCC('I','C','M','T'):
725 case DMUS_FOURCC_UCMT_CHUNK: {
726 TRACE_(dmfile)(": comment chunk (ignored)\n");
727 liMove.QuadPart = Chunk.dwSize;
728 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
729 break;
731 default: {
732 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
733 liMove.QuadPart = Chunk.dwSize;
734 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
735 break;
738 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
739 } while (ListCount[0] < ListSize[0]);
740 break;
742 case DMUS_FOURCC_TRACK_LIST: {
743 TRACE_(dmfile)(": TRACK list\n");
744 do {
745 IStream_Read (pStream, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
746 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
747 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
748 switch (Chunk.fccID) {
749 default: {
750 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
751 liMove.QuadPart = Chunk.dwSize;
752 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
753 break;
756 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
757 } while (ListCount[0] < ListSize[0]);
758 break;
760 default: {
761 TRACE_(dmfile)(": unknown (skipping)\n");
762 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
763 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
764 break;
767 break;
769 default: {
770 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
771 liMove.QuadPart = Chunk.dwSize;
772 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL);
773 break;
776 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
777 } while (StreamCount < StreamSize);
778 break;
779 } else if (Chunk.fccID == mmioFOURCC('W','A','V','E')) {
780 TRACE_(dmfile)(": wave form (loading not yet implemented)\n");
781 liMove.QuadPart = StreamSize;
782 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
783 } else {
784 TRACE_(dmfile)(": unexpected chunk (loading failed)\n");
785 liMove.QuadPart = StreamSize;
786 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
787 return E_FAIL;
790 TRACE_(dmfile)(": reading finished\n");
791 break;
793 default: {
794 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
795 liMove.QuadPart = Chunk.dwSize;
796 IStream_Seek (pStream, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
797 return DMUS_E_INVALIDFILE;
801 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc));
803 return S_OK;
806 static const IDirectMusicObjectVtbl DirectMusicSegment8_Object_Vtbl = {
807 IDirectMusicSegment8Impl_IDirectMusicObject_QueryInterface,
808 IDirectMusicSegment8Impl_IDirectMusicObject_AddRef,
809 IDirectMusicSegment8Impl_IDirectMusicObject_Release,
810 IDirectMusicSegment8Impl_IDirectMusicObject_GetDescriptor,
811 IDirectMusicSegment8Impl_IDirectMusicObject_SetDescriptor,
812 IDirectMusicSegment8Impl_IDirectMusicObject_ParseDescriptor
815 /* IDirectMusicSegment8Impl IPersistStream part: */
816 static HRESULT WINAPI IDirectMusicSegment8Impl_IPersistStream_QueryInterface (LPPERSISTSTREAM iface, REFIID riid, LPVOID *ppobj) {
817 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);
818 return IDirectMusicSegment8_QueryInterface(&This->IDirectMusicSegment8_iface, riid, ppobj);
821 static ULONG WINAPI IDirectMusicSegment8Impl_IPersistStream_AddRef (LPPERSISTSTREAM iface) {
822 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);
823 return IDirectMusicSegment8_AddRef(&This->IDirectMusicSegment8_iface);
826 static ULONG WINAPI IDirectMusicSegment8Impl_IPersistStream_Release (LPPERSISTSTREAM iface) {
827 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);
828 return IDirectMusicSegment8_Release(&This->IDirectMusicSegment8_iface);
831 static HRESULT WINAPI IDirectMusicSegment8Impl_IPersistStream_GetClassID (LPPERSISTSTREAM iface, CLSID* pClassID) {
832 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);
833 TRACE("(%p, %p)\n", This, pClassID);
834 *pClassID = CLSID_DirectMusicSegment;
835 return S_OK;
838 static HRESULT WINAPI IDirectMusicSegment8Impl_IPersistStream_IsDirty (LPPERSISTSTREAM iface) {
839 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);
840 FIXME("(%p): stub, always S_FALSE\n", This);
841 return S_FALSE;
844 static HRESULT IDirectMusicSegment8Impl_IPersistStream_LoadTrack (LPPERSISTSTREAM iface, IStream* pClonedStream, IDirectMusicTrack** ppTrack,
845 DMUS_IO_TRACK_HEADER* pTrack_hdr) {
847 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);
848 HRESULT hr = E_FAIL;
849 IPersistStream* pPersistStream = NULL;
851 hr = CoCreateInstance (&pTrack_hdr->guidClassID, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack, (LPVOID*) ppTrack);
852 if (FAILED(hr)) {
853 ERR(": could not create object\n");
854 return hr;
856 /* acquire PersistStream interface */
857 hr = IDirectMusicTrack_QueryInterface (*ppTrack, &IID_IPersistStream, (LPVOID*) &pPersistStream);
858 if (FAILED(hr)) {
859 ERR(": could not acquire IPersistStream\n");
860 return hr;
862 /* load */
863 hr = IPersistStream_Load (pPersistStream, pClonedStream);
864 if (FAILED(hr)) {
865 ERR(": failed to load object\n");
866 return hr;
869 /* release all loading-related stuff */
870 IPersistStream_Release (pPersistStream);
872 hr = IDirectMusicSegment8_InsertTrack(&This->IDirectMusicSegment8_iface, *ppTrack,
873 pTrack_hdr->dwGroup); /* at dsPosition */
874 if (FAILED(hr)) {
875 ERR(": could not insert track\n");
876 return hr;
879 return S_OK;
882 static HRESULT IDirectMusicSegment8Impl_IPersistStream_ParseTrackForm (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm) {
884 /*ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);*/
885 HRESULT hr = E_FAIL;
886 DMUS_PRIVATE_CHUNK Chunk;
887 DWORD StreamSize, StreamCount, ListSize[3];
888 LARGE_INTEGER liMove; /* used when skipping chunks */
890 DMUS_IO_TRACK_HEADER track_hdr;
891 DMUS_IO_TRACK_EXTRAS_HEADER track_xhdr;
892 IDirectMusicTrack* pTrack = NULL;
894 if (pChunk->fccID != DMUS_FOURCC_TRACK_FORM) {
895 ERR_(dmfile)(": %s chunk should be a TRACK form\n", debugstr_fourcc (pChunk->fccID));
896 return E_FAIL;
899 StreamSize = pChunk->dwSize - sizeof(FOURCC);
900 StreamCount = 0;
902 do {
903 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
904 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
905 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
907 switch (Chunk.fccID) {
908 case DMUS_FOURCC_TRACK_CHUNK: {
909 TRACE_(dmfile)(": track chunk\n");
910 IStream_Read (pStm, &track_hdr, sizeof(DMUS_IO_TRACK_HEADER), NULL);
911 TRACE_(dmfile)(" - class: %s\n", debugstr_guid (&track_hdr.guidClassID));
912 TRACE_(dmfile)(" - dwGroup: %d\n", track_hdr.dwGroup);
913 TRACE_(dmfile)(" - ckid: %s\n", debugstr_fourcc (track_hdr.ckid));
914 TRACE_(dmfile)(" - fccType: %s\n", debugstr_fourcc (track_hdr.fccType));
915 break;
917 case DMUS_FOURCC_TRACK_EXTRAS_CHUNK: {
918 TRACE_(dmfile)(": track extras chunk\n");
919 IStream_Read (pStm, &track_xhdr, sizeof(DMUS_IO_TRACK_EXTRAS_HEADER), NULL);
920 break;
923 case DMUS_FOURCC_COMMANDTRACK_CHUNK: {
924 TRACE_(dmfile)(": COMMANDTRACK track\n");
925 liMove.QuadPart = Chunk.dwSize;
926 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
927 break;
930 case FOURCC_LIST: {
931 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
932 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
933 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
934 if (Chunk.fccID == track_hdr.fccType && 0 == track_hdr.ckid) {
935 LPSTREAM pClonedStream = NULL;
937 TRACE_(dmfile)(": TRACK list\n");
939 IStream_Clone (pStm, &pClonedStream);
941 liMove.QuadPart = 0;
942 liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
943 IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
945 hr = IDirectMusicSegment8Impl_IPersistStream_LoadTrack (iface, pClonedStream, &pTrack, &track_hdr);
946 if (FAILED(hr)) {
947 ERR(": could not load track\n");
948 return hr;
950 IStream_Release (pClonedStream);
952 IDirectMusicTrack_Release(pTrack); pTrack = NULL; /* now we can release at as it inserted */
954 liMove.QuadPart = ListSize[0];
955 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
957 } else {
958 TRACE_(dmfile)(": unknown (skipping)\n");
959 liMove.QuadPart = Chunk.dwSize;
960 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
962 break;
965 case FOURCC_RIFF: {
966 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
967 TRACE_(dmfile)(": RIFF chunk of type %s\n", debugstr_fourcc(Chunk.fccID));
969 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
971 if (Chunk.fccID == track_hdr.fccType && 0 == track_hdr.ckid) {
972 LPSTREAM pClonedStream = NULL;
974 TRACE_(dmfile)(": TRACK RIFF\n");
976 IStream_Clone (pStm, &pClonedStream);
978 liMove.QuadPart = 0;
979 liMove.QuadPart -= sizeof(FOURCC) + (sizeof(FOURCC)+sizeof(DWORD));
980 IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
982 hr = IDirectMusicSegment8Impl_IPersistStream_LoadTrack (iface, pClonedStream, &pTrack, &track_hdr);
983 if (FAILED(hr)) {
984 ERR(": could not load track\n");
985 return hr;
987 IStream_Release (pClonedStream);
989 IDirectMusicTrack_Release(pTrack); pTrack = NULL; /* now we can release at as it inserted */
991 /** now safe move the cursor */
992 liMove.QuadPart = ListSize[0];
993 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
995 } else {
996 TRACE_(dmfile)(": unknown RIFF fmt (skipping)\n");
997 liMove.QuadPart = ListSize[0];
998 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1000 break;
1003 default: {
1004 if (0 == track_hdr.fccType && Chunk.fccID == track_hdr.ckid) {
1005 LPSTREAM pClonedStream = NULL;
1007 TRACE_(dmfile)(": TRACK solo\n");
1009 IStream_Clone (pStm, &pClonedStream);
1011 liMove.QuadPart = 0;
1012 liMove.QuadPart -= (sizeof(FOURCC) + sizeof(DWORD));
1013 IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
1015 hr = IDirectMusicSegment8Impl_IPersistStream_LoadTrack (iface, pClonedStream, &pTrack, &track_hdr);
1016 if (FAILED(hr)) {
1017 ERR(": could not load track\n");
1018 return hr;
1020 IStream_Release (pClonedStream);
1022 IDirectMusicTrack_Release(pTrack); pTrack = NULL; /* now we can release at as it inserted */
1024 liMove.QuadPart = Chunk.dwSize;
1025 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1027 break;
1030 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
1031 liMove.QuadPart = Chunk.dwSize;
1032 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1033 break;
1036 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
1037 } while (StreamCount < StreamSize);
1039 return S_OK;
1042 static HRESULT IDirectMusicSegment8Impl_IPersistStream_ParseTrackList (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm, IDirectMusicSegment8Impl* This) {
1044 HRESULT hr = E_FAIL;
1045 DMUS_PRIVATE_CHUNK Chunk;
1046 DWORD StreamSize, ListSize[3], ListCount[3];
1047 LARGE_INTEGER liMove; /* used when skipping chunks */
1049 if (pChunk->fccID != DMUS_FOURCC_TRACK_LIST) {
1050 ERR_(dmfile)(": %s chunk should be a TRACK list\n", debugstr_fourcc (pChunk->fccID));
1051 return E_FAIL;
1054 ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
1055 ListCount[0] = 0;
1057 do {
1058 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
1059 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
1060 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
1061 switch (Chunk.fccID) {
1062 case FOURCC_RIFF: {
1063 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
1064 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
1065 StreamSize = Chunk.dwSize - sizeof(FOURCC);
1066 switch (Chunk.fccID) {
1067 case DMUS_FOURCC_TRACK_FORM: {
1068 TRACE_(dmfile)(": TRACK form\n");
1069 hr = IDirectMusicSegment8Impl_IPersistStream_ParseTrackForm (iface, &Chunk, pStm);
1070 if (FAILED(hr)) return hr;
1071 break;
1073 default: {
1074 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
1075 liMove.QuadPart = StreamSize;
1076 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1077 break;
1080 break;
1082 default: {
1083 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
1084 liMove.QuadPart = Chunk.dwSize;
1085 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1086 break;
1089 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
1090 } while (ListCount[0] < ListSize[0]);
1092 return S_OK;
1095 static HRESULT IDirectMusicSegment8Impl_IPersistStream_ParseSegmentForm (LPPERSISTSTREAM iface, DMUS_PRIVATE_CHUNK* pChunk, IStream* pStm, IDirectMusicSegment8Impl* This) {
1097 HRESULT hr = E_FAIL;
1098 DMUS_PRIVATE_CHUNK Chunk;
1099 DWORD StreamSize, StreamCount, ListSize[3], ListCount[3];
1100 LARGE_INTEGER liMove; /* used when skipping chunks */
1102 if (pChunk->fccID != DMUS_FOURCC_SEGMENT_FORM) {
1103 ERR_(dmfile)(": %s chunk should be a segment form\n", debugstr_fourcc (pChunk->fccID));
1104 return E_FAIL;
1107 StreamSize = pChunk->dwSize - sizeof(FOURCC);
1108 StreamCount = 0;
1110 do {
1111 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
1112 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
1113 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
1115 hr = IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk, pStm, This->pDesc);
1116 if (FAILED(hr)) return hr;
1118 if (hr == S_FALSE) {
1119 switch (Chunk.fccID) {
1120 case DMUS_FOURCC_SEGMENT_CHUNK: {
1121 DWORD checkSz = sizeof(FOURCC);
1122 TRACE_(dmfile)(": segment chunk\n");
1123 /** DX 7 */
1124 IStream_Read (pStm, &This->header.dwRepeats, sizeof(This->header.dwRepeats), NULL);
1125 checkSz += sizeof(This->header.dwRepeats);
1126 IStream_Read (pStm, &This->header.mtLength, sizeof(This->header.mtLength), NULL);
1127 checkSz += sizeof(This->header.mtLength);
1128 IStream_Read (pStm, &This->header.mtPlayStart, sizeof(This->header.mtPlayStart), NULL);
1129 checkSz += sizeof(This->header.mtPlayStart);
1130 IStream_Read (pStm, &This->header.mtLoopStart, sizeof(This->header.mtLoopStart), NULL);
1131 checkSz += sizeof(This->header.mtLoopStart);
1132 IStream_Read (pStm, &This->header.mtLoopEnd, sizeof(This->header.mtLoopEnd), NULL);
1133 checkSz += sizeof(This->header.mtLoopEnd);
1134 IStream_Read (pStm, &This->header.dwResolution, sizeof(This->header.dwResolution), NULL);
1135 checkSz += sizeof(This->header.dwResolution);
1136 TRACE_(dmfile)("dwRepeats: %u\n", This->header.dwRepeats);
1137 TRACE_(dmfile)("mtLength: %u\n", This->header.mtLength);
1138 TRACE_(dmfile)("mtPlayStart: %u\n", This->header.mtPlayStart);
1139 TRACE_(dmfile)("mtLoopStart: %u\n", This->header.mtLoopStart);
1140 TRACE_(dmfile)("mtLoopEnd: %u\n", This->header.mtLoopEnd);
1141 TRACE_(dmfile)("dwResolution: %u\n", This->header.dwResolution);
1142 /** DX 8 */
1143 if (Chunk.dwSize > checkSz) {
1144 IStream_Read (pStm, &This->header.rtLength, sizeof(This->header.rtLength), NULL);
1145 checkSz += sizeof(This->header.rtLength);
1146 IStream_Read (pStm, &This->header.dwFlags, sizeof(This->header.dwFlags), NULL);
1147 checkSz += sizeof(This->header.dwFlags);
1149 /** DX 9 */
1150 if (Chunk.dwSize > checkSz) {
1151 IStream_Read (pStm, &This->header.rtLoopStart, sizeof(This->header.rtLoopStart), NULL);
1152 checkSz += sizeof(This->header.rtLoopStart);
1153 IStream_Read (pStm, &This->header.rtLoopEnd, sizeof(This->header.rtLoopEnd), NULL);
1154 checkSz += sizeof(This->header.rtLoopEnd);
1155 IStream_Read (pStm, &This->header.rtPlayStart, sizeof(This->header.rtPlayStart), NULL);
1156 checkSz += sizeof(This->header.rtPlayStart);
1158 liMove.QuadPart = Chunk.dwSize - checkSz + sizeof(FOURCC);
1159 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1160 break;
1162 case FOURCC_LIST: {
1163 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
1164 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
1165 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
1166 ListCount[0] = 0;
1167 switch (Chunk.fccID) {
1168 case DMUS_FOURCC_UNFO_LIST: {
1169 TRACE_(dmfile)(": UNFO list\n");
1170 do {
1171 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
1172 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
1173 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
1175 hr = IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk, pStm, This->pDesc);
1176 if (FAILED(hr)) return hr;
1178 if (hr == S_FALSE) {
1179 switch (Chunk.fccID) {
1180 default: {
1181 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
1182 liMove.QuadPart = Chunk.dwSize;
1183 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1184 break;
1189 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
1190 } while (ListCount[0] < ListSize[0]);
1191 break;
1193 case DMUS_FOURCC_TRACK_LIST: {
1194 TRACE_(dmfile)(": TRACK list\n");
1195 hr = IDirectMusicSegment8Impl_IPersistStream_ParseTrackList (iface, &Chunk, pStm, This);
1196 if (FAILED(hr)) return hr;
1197 break;
1199 default: {
1200 TRACE_(dmfile)(": unknown (skipping)\n");
1201 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
1202 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1203 break;
1206 break;
1208 default: {
1209 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
1210 liMove.QuadPart = Chunk.dwSize;
1211 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
1212 break;
1216 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
1217 } while (StreamCount < StreamSize);
1219 return S_OK;
1222 static HRESULT IDirectMusicSegment8Impl_IPersistStream_LoadWave (LPPERSISTSTREAM iface, IStream* pClonedStream, IDirectMusicObject** ppWaveObject) {
1224 HRESULT hr = E_FAIL;
1225 IPersistStream* pPersistStream = NULL;
1227 hr = CoCreateInstance (&CLSID_DirectSoundWave, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicObject, (LPVOID*) ppWaveObject);
1228 if (FAILED(hr)) {
1229 ERR(": could not create object\n");
1230 return hr;
1232 /* acquire PersistStream interface */
1233 hr = IDirectMusicObject_QueryInterface (*ppWaveObject, &IID_IPersistStream, (LPVOID*) &pPersistStream);
1234 if (FAILED(hr)) {
1235 ERR(": could not acquire IPersistStream\n");
1236 return hr;
1238 /* load */
1239 hr = IPersistStream_Load (pPersistStream, pClonedStream);
1240 if (FAILED(hr)) {
1241 ERR(": failed to load object\n");
1242 return hr;
1245 /* release all loading-related stuff */
1246 IPersistStream_Release (pPersistStream);
1248 return S_OK;
1251 static HRESULT WINAPI IDirectMusicSegment8Impl_IPersistStream_Load (LPPERSISTSTREAM iface, IStream* pStm) {
1252 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);
1254 HRESULT hr;
1255 DMUS_PRIVATE_CHUNK Chunk;
1256 DWORD StreamSize;
1257 /*DWORD ListSize[3], ListCount[3];*/
1258 LARGE_INTEGER liMove; /* used when skipping chunks */
1260 TRACE("(%p, %p): Loading\n", This, pStm);
1261 hr = IStream_Read (pStm, &Chunk, sizeof(Chunk), NULL);
1262 if(hr != S_OK){
1263 WARN("IStream_Read failed: %08x\n", hr);
1264 return DMUS_E_UNSUPPORTED_STREAM;
1266 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
1267 switch (Chunk.fccID) {
1268 case FOURCC_RIFF: {
1269 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
1270 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(Chunk.fccID));
1271 StreamSize = Chunk.dwSize - sizeof(FOURCC);
1272 switch (Chunk.fccID) {
1273 case DMUS_FOURCC_SEGMENT_FORM: {
1274 TRACE_(dmfile)(": segment form\n");
1275 hr = IDirectMusicSegment8Impl_IPersistStream_ParseSegmentForm (iface, &Chunk, pStm, This);
1276 if (FAILED(hr)) return hr;
1277 break;
1279 case mmioFOURCC('W','A','V','E'): {
1280 LPSTREAM pClonedStream = NULL;
1281 IDirectMusicObject* pWave = NULL;
1283 FIXME_(dmfile)(": WAVE form (loading to be checked)\n");
1285 IStream_Clone (pStm, &pClonedStream);
1287 liMove.QuadPart = - (LONGLONG)(sizeof(FOURCC) * 2 + sizeof(DWORD));
1288 IStream_Seek (pClonedStream, liMove, STREAM_SEEK_CUR, NULL);
1290 hr = IDirectMusicSegment8Impl_IPersistStream_LoadWave (iface, pClonedStream, &pWave);
1291 if (FAILED(hr)) {
1292 ERR(": could not load track\n");
1293 return hr;
1295 IStream_Release (pClonedStream);
1297 IDirectMusicTrack_Release(pWave); pWave = NULL; /* now we can release at as it inserted */
1299 liMove.QuadPart = StreamSize;
1300 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
1301 break;
1303 default: {
1304 TRACE_(dmfile)(": unexpected chunk (loading failed)\n");
1305 liMove.QuadPart = StreamSize;
1306 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
1307 return DMUS_E_UNSUPPORTED_STREAM;
1310 TRACE_(dmfile)(": reading finished\n");
1311 break;
1313 default: {
1314 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
1315 return DMUS_E_UNSUPPORTED_STREAM;
1319 return S_OK;
1322 static HRESULT WINAPI IDirectMusicSegment8Impl_IPersistStream_Save (LPPERSISTSTREAM iface, IStream* pStm, BOOL fClearDirty) {
1323 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);
1324 FIXME("(%p): Saving not implemented yet\n", This);
1325 return E_NOTIMPL;
1328 static HRESULT WINAPI IDirectMusicSegment8Impl_IPersistStream_GetSizeMax (LPPERSISTSTREAM iface, ULARGE_INTEGER* pcbSize) {
1329 ICOM_THIS_MULTI(IDirectMusicSegment8Impl, PersistStreamVtbl, iface);
1330 FIXME("(%p, %p): stub\n", This, pcbSize);
1331 return E_NOTIMPL;
1334 static const IPersistStreamVtbl DirectMusicSegment8_PersistStream_Vtbl = {
1335 IDirectMusicSegment8Impl_IPersistStream_QueryInterface,
1336 IDirectMusicSegment8Impl_IPersistStream_AddRef,
1337 IDirectMusicSegment8Impl_IPersistStream_Release,
1338 IDirectMusicSegment8Impl_IPersistStream_GetClassID,
1339 IDirectMusicSegment8Impl_IPersistStream_IsDirty,
1340 IDirectMusicSegment8Impl_IPersistStream_Load,
1341 IDirectMusicSegment8Impl_IPersistStream_Save,
1342 IDirectMusicSegment8Impl_IPersistStream_GetSizeMax
1345 /* for ClassFactory */
1346 HRESULT WINAPI create_dmsegment(REFIID lpcGUID, void **ppobj)
1348 IDirectMusicSegment8Impl* obj;
1349 HRESULT hr;
1351 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicSegment8Impl));
1352 if (NULL == obj) {
1353 *ppobj = NULL;
1354 return E_OUTOFMEMORY;
1356 obj->IDirectMusicSegment8_iface.lpVtbl = &dmsegment8_vtbl;
1357 obj->ObjectVtbl = &DirectMusicSegment8_Object_Vtbl;
1358 obj->PersistStreamVtbl = &DirectMusicSegment8_PersistStream_Vtbl;
1359 obj->pDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DMUS_OBJECTDESC));
1360 DM_STRUCT_INIT(obj->pDesc);
1361 obj->pDesc->dwValidData |= DMUS_OBJ_CLASS;
1362 obj->pDesc->guidClass = CLSID_DirectMusicSegment;
1363 obj->ref = 1;
1364 list_init (&obj->Tracks);
1366 DMIME_LockModule();
1367 hr = IDirectMusicSegment8_QueryInterface(&obj->IDirectMusicSegment8_iface, lpcGUID, ppobj);
1368 IDirectMusicSegment8_Release(&obj->IDirectMusicSegment8_iface);
1370 return hr;