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"
24 WINE_DEFAULT_DEBUG_CHANNEL(dmime
);
25 WINE_DECLARE_DEBUG_CHANNEL(dmfile
);
27 /*****************************************************************************
28 * IDirectMusicSegmentImpl implementation
30 typedef struct IDirectMusicSegment8Impl
{
31 IDirectMusicSegment8 IDirectMusicSegment8_iface
;
32 struct dmobject dmobj
;
34 DMUS_IO_SEGMENT_HEADER header
;
35 IDirectMusicGraph
*pGraph
;
37 } IDirectMusicSegment8Impl
;
39 static inline IDirectMusicSegment8Impl
*impl_from_IDirectMusicSegment8(IDirectMusicSegment8
*iface
)
41 return CONTAINING_RECORD(iface
, IDirectMusicSegment8Impl
, IDirectMusicSegment8_iface
);
44 static HRESULT WINAPI
IDirectMusicSegment8Impl_QueryInterface(IDirectMusicSegment8
*iface
,
45 REFIID riid
, void **ret_iface
)
47 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
49 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ret_iface
);
53 if (IsEqualIID (riid
, &IID_IUnknown
) || IsEqualIID (riid
, &IID_IDirectMusicSegment
) ||
54 IsEqualIID(riid
, &IID_IDirectMusicSegment2
) ||
55 IsEqualIID (riid
, &IID_IDirectMusicSegment8
))
57 else if (IsEqualIID (riid
, &IID_IDirectMusicObject
))
58 *ret_iface
= &This
->dmobj
.IDirectMusicObject_iface
;
59 else if (IsEqualIID (riid
, &IID_IPersistStream
))
60 *ret_iface
= &This
->dmobj
.IPersistStream_iface
;
62 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ret_iface
);
66 IUnknown_AddRef((IUnknown
*)*ret_iface
);
70 static ULONG WINAPI
IDirectMusicSegment8Impl_AddRef(IDirectMusicSegment8
*iface
)
72 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
73 LONG ref
= InterlockedIncrement(&This
->ref
);
75 TRACE("(%p) ref=%d\n", This
, ref
);
80 static ULONG WINAPI
IDirectMusicSegment8Impl_Release(IDirectMusicSegment8
*iface
)
82 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
83 LONG ref
= InterlockedDecrement(&This
->ref
);
85 TRACE("(%p) ref=%d\n", This
, ref
);
88 HeapFree(GetProcessHeap(), 0, This
);
95 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetLength(IDirectMusicSegment8
*iface
,
96 MUSIC_TIME
*pmtLength
)
98 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
100 TRACE("(%p, %p)\n", This
, pmtLength
);
101 if (NULL
== pmtLength
) {
104 *pmtLength
= This
->header
.mtLength
;
108 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetLength(IDirectMusicSegment8
*iface
,
111 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
113 TRACE("(%p, %d)\n", This
, mtLength
);
114 This
->header
.mtLength
= mtLength
;
118 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetRepeats(IDirectMusicSegment8
*iface
,
121 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
123 TRACE("(%p, %p)\n", This
, pdwRepeats
);
124 if (NULL
== pdwRepeats
) {
127 *pdwRepeats
= This
->header
.dwRepeats
;
131 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetRepeats(IDirectMusicSegment8
*iface
,
134 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
136 TRACE("(%p, %d)\n", This
, dwRepeats
);
137 This
->header
.dwRepeats
= dwRepeats
;
141 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetDefaultResolution(IDirectMusicSegment8
*iface
,
142 DWORD
*pdwResolution
)
144 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
146 TRACE("(%p, %p)\n", This
, pdwResolution
);
147 if (NULL
== pdwResolution
) {
150 *pdwResolution
= This
->header
.dwResolution
;
154 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetDefaultResolution(IDirectMusicSegment8
*iface
,
157 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
159 TRACE("(%p, %d)\n", This
, dwResolution
);
160 This
->header
.dwResolution
= dwResolution
;
164 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetTrack(IDirectMusicSegment8
*iface
,
165 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, IDirectMusicTrack
**ppTrack
)
167 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
169 struct list
* pEntry
= NULL
;
170 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
171 IPersistStream
* pCLSIDStream
= NULL
;
174 TRACE("(%p, %s, %d, 0x%x, %p)\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, ppTrack
);
176 if (NULL
== ppTrack
) {
180 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
181 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
182 TRACE(" - %p -> 0x%x,%p\n", pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
183 if (0xFFFFFFFF != dwGroupBits
&& 0 == (pIt
->dwGroupBits
& dwGroupBits
)) continue ;
184 if (FALSE
== IsEqualGUID(&GUID_NULL
, rguidType
)) {
186 * it rguidType is not null we must check if CLSIDs are equal
187 * and the unique way to get it is using IPersistStream Interface
189 hr
= IDirectMusicTrack_QueryInterface(pIt
->pTrack
, &IID_IPersistStream
, (void**) &pCLSIDStream
);
191 ERR("(%p): object %p don't implement IPersistStream Interface. Expect a crash (critical problem)\n", This
, pIt
->pTrack
);
194 hr
= IPersistStream_GetClassID(pCLSIDStream
, &pIt_clsid
);
195 IPersistStream_Release(pCLSIDStream
); pCLSIDStream
= NULL
;
197 ERR("(%p): non-implemented GetClassID for object %p\n", This
, pIt
->pTrack
);
200 TRACE(" - %p -> %s\n", pIt
, debugstr_dmguid(&pIt_clsid
));
201 if (FALSE
== IsEqualGUID(&pIt_clsid
, rguidType
)) continue ;
204 *ppTrack
= pIt
->pTrack
;
205 IDirectMusicTrack_AddRef(*ppTrack
);
210 return DMUS_E_NOT_FOUND
;
213 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetTrackGroup(IDirectMusicSegment8
*iface
,
214 IDirectMusicTrack
*pTrack
, DWORD
*pdwGroupBits
)
216 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
217 struct list
* pEntry
= NULL
;
218 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
220 TRACE("(%p, %p, %p)\n", This
, pTrack
, pdwGroupBits
);
222 if (NULL
== pdwGroupBits
) {
226 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
227 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
228 TRACE(" - %p -> %d,%p\n", pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
229 if (NULL
!= pIt
&& pIt
->pTrack
== pTrack
) {
230 *pdwGroupBits
= pIt
->dwGroupBits
;
235 return DMUS_E_NOT_FOUND
;
238 static HRESULT WINAPI
IDirectMusicSegment8Impl_InsertTrack(IDirectMusicSegment8
*iface
,
239 IDirectMusicTrack
*pTrack
, DWORD dwGroupBits
)
241 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
243 struct list
* pEntry
= NULL
;
244 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
245 LPDMUS_PRIVATE_SEGMENT_TRACK pNewSegTrack
= NULL
;
247 TRACE("(%p, %p, %d)\n", This
, pTrack
, dwGroupBits
);
249 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
251 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
252 TRACE(" - #%u: %p -> %d,%p\n", i
, pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
253 if (NULL
!= pIt
&& pIt
->pTrack
== pTrack
) {
254 ERR("(%p, %p): track is already in list\n", This
, pTrack
);
259 pNewSegTrack
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(DMUS_PRIVATE_SEGMENT_TRACK
));
260 if (NULL
== pNewSegTrack
)
261 return E_OUTOFMEMORY
;
263 pNewSegTrack
->dwGroupBits
= dwGroupBits
;
264 pNewSegTrack
->pTrack
= pTrack
;
265 IDirectMusicTrack_Init(pTrack
, (IDirectMusicSegment
*)iface
);
266 IDirectMusicTrack_AddRef(pTrack
);
267 list_add_tail (&This
->Tracks
, &pNewSegTrack
->entry
);
272 static HRESULT WINAPI
IDirectMusicSegment8Impl_RemoveTrack(IDirectMusicSegment8
*iface
,
273 IDirectMusicTrack
*pTrack
)
275 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
276 struct list
* pEntry
= NULL
;
277 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
279 TRACE("(%p, %p)\n", This
, pTrack
);
281 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
282 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
283 if (pIt
->pTrack
== pTrack
) {
284 TRACE("(%p, %p): track in list\n", This
, pTrack
);
286 list_remove(&pIt
->entry
);
287 IDirectMusicTrack_Init(pIt
->pTrack
, NULL
);
288 IDirectMusicTrack_Release(pIt
->pTrack
);
289 HeapFree(GetProcessHeap(), 0, pIt
);
298 static HRESULT WINAPI
IDirectMusicSegment8Impl_InitPlay(IDirectMusicSegment8
*iface
,
299 IDirectMusicSegmentState
**ppSegState
, IDirectMusicPerformance
*pPerformance
, DWORD dwFlags
)
301 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
304 FIXME("(%p, %p, %p, %d): semi-stub\n", This
, ppSegState
, pPerformance
, dwFlags
);
305 if (NULL
== ppSegState
) {
308 hr
= create_dmsegmentstate(&IID_IDirectMusicSegmentState
,(void**) ppSegState
);
312 /* TODO: DMUS_SEGF_FLAGS */
316 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetGraph(IDirectMusicSegment8
*iface
,
317 IDirectMusicGraph
**ppGraph
)
319 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
321 FIXME("(%p, %p): semi-stub\n", This
, ppGraph
);
322 if (NULL
== ppGraph
) {
325 if (NULL
== This
->pGraph
) {
326 return DMUS_E_NOT_FOUND
;
329 * should return This, as seen in msdn
330 * "...The segment object implements IDirectMusicGraph directly..."
332 *ppGraph
= This
->pGraph
;
333 IDirectMusicGraph_AddRef(This
->pGraph
);
337 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetGraph(IDirectMusicSegment8
*iface
,
338 IDirectMusicGraph
*pGraph
)
340 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
342 FIXME("(%p, %p): to complete\n", This
, pGraph
);
343 if (NULL
!= This
->pGraph
) {
344 IDirectMusicGraph_Release(This
->pGraph
);
346 This
->pGraph
= pGraph
;
347 if (NULL
!= This
->pGraph
) {
348 IDirectMusicGraph_AddRef(This
->pGraph
);
353 static HRESULT WINAPI
IDirectMusicSegment8Impl_AddNotificationType(IDirectMusicSegment8
*iface
,
354 REFGUID rguidNotificationType
)
356 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
357 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidNotificationType
));
361 static HRESULT WINAPI
IDirectMusicSegment8Impl_RemoveNotificationType(IDirectMusicSegment8
*iface
,
362 REFGUID rguidNotificationType
)
364 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
365 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidNotificationType
));
369 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetParam(IDirectMusicSegment8
*iface
,
370 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
, MUSIC_TIME
*pmtNext
,
373 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
375 struct list
* pEntry
= NULL
;
376 IDirectMusicTrack
* pTrack
= NULL
;
377 IPersistStream
* pCLSIDStream
= NULL
;
378 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
381 FIXME("(%p, %s, 0x%x, %d, %d, %p, %p)\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pmtNext
, pParam
);
383 if (DMUS_SEG_ANYTRACK
== dwIndex
) {
385 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
386 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
388 hr
= IDirectMusicTrack_QueryInterface(pIt
->pTrack
, &IID_IPersistStream
, (void**) &pCLSIDStream
);
390 ERR("(%p): object %p don't implement IPersistStream Interface. Expect a crash (critical problem)\n", This
, pIt
->pTrack
);
394 TRACE(" - %p -> 0x%x,%p\n", pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
396 if (0xFFFFFFFF != dwGroupBits
&& 0 == (pIt
->dwGroupBits
& dwGroupBits
)) continue ;
397 hr
= IPersistStream_GetClassID(pCLSIDStream
, &pIt_clsid
);
398 IPersistStream_Release(pCLSIDStream
); pCLSIDStream
= NULL
;
400 ERR("(%p): non-implemented GetClassID for object %p\n", This
, pIt
->pTrack
);
403 if (FALSE
== IsEqualGUID(&pIt_clsid
, rguidType
)) continue ;
404 if (FAILED(IDirectMusicTrack_IsParamSupported(pIt
->pTrack
, rguidType
))) continue ;
405 hr
= IDirectMusicTrack_GetParam(pIt
->pTrack
, rguidType
, mtTime
, pmtNext
, pParam
);
406 if (SUCCEEDED(hr
)) return hr
;
408 ERR("(%p): not found\n", This
);
409 return DMUS_E_TRACK_NOT_FOUND
;
412 hr
= IDirectMusicSegment8Impl_GetTrack(iface
, &GUID_NULL
, dwGroupBits
, dwIndex
, &pTrack
);
414 ERR("(%p): not found\n", This
);
415 return DMUS_E_TRACK_NOT_FOUND
;
418 hr
= IDirectMusicTrack_GetParam(pTrack
, rguidType
, mtTime
, pmtNext
, pParam
);
419 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
;
424 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetParam(IDirectMusicSegment8
*iface
,
425 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
, void *pParam
)
427 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
428 FIXME("(%p, %s, %d, %d, %d, %p): stub\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pParam
);
432 static HRESULT WINAPI
IDirectMusicSegment8Impl_Clone(IDirectMusicSegment8
*iface
,
433 MUSIC_TIME mtStart
, MUSIC_TIME mtEnd
, IDirectMusicSegment
**ppSegment
)
435 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
436 FIXME("(%p, %d, %d, %p): stub\n", This
, mtStart
, mtEnd
, ppSegment
);
440 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetStartPoint(IDirectMusicSegment8
*iface
,
443 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
445 TRACE("(%p, %d)\n", This
, mtStart
);
446 if (mtStart
>= This
->header
.mtLength
) {
447 return DMUS_E_OUT_OF_RANGE
;
449 This
->header
.mtPlayStart
= mtStart
;
453 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetStartPoint(IDirectMusicSegment8
*iface
,
454 MUSIC_TIME
*pmtStart
)
456 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
458 TRACE("(%p, %p)\n", This
, pmtStart
);
459 if (NULL
== pmtStart
) {
462 *pmtStart
= This
->header
.mtPlayStart
;
466 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetLoopPoints(IDirectMusicSegment8
*iface
,
467 MUSIC_TIME mtStart
, MUSIC_TIME mtEnd
)
469 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
471 TRACE("(%p, %d, %d)\n", This
, mtStart
, mtEnd
);
472 if (mtStart
>= This
->header
.mtLength
|| mtEnd
> This
->header
.mtLength
|| mtStart
> mtEnd
) {
473 return DMUS_E_OUT_OF_RANGE
;
475 This
->header
.mtLoopStart
= mtStart
;
476 This
->header
.mtLoopEnd
= mtEnd
;
480 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetLoopPoints(IDirectMusicSegment8
*iface
,
481 MUSIC_TIME
*pmtStart
, MUSIC_TIME
*pmtEnd
)
483 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
485 TRACE("(%p, %p, %p)\n", This
, pmtStart
, pmtEnd
);
486 if (NULL
== pmtStart
|| NULL
== pmtEnd
) {
489 *pmtStart
= This
->header
.mtLoopStart
;
490 *pmtEnd
= This
->header
.mtLoopEnd
;
494 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetPChannelsUsed(IDirectMusicSegment8
*iface
,
495 DWORD dwNumPChannels
, DWORD
*paPChannels
)
497 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
498 FIXME("(%p, %d, %p): stub\n", This
, dwNumPChannels
, paPChannels
);
502 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetTrackConfig(IDirectMusicSegment8
*iface
,
503 REFGUID rguidTrackClassID
, DWORD dwGroupBits
, DWORD dwIndex
, DWORD dwFlagsOn
,
506 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
507 FIXME("(%p, %s, %d, %d, %d, %d): stub\n", This
, debugstr_dmguid(rguidTrackClassID
), dwGroupBits
, dwIndex
, dwFlagsOn
, dwFlagsOff
);
511 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetAudioPathConfig(IDirectMusicSegment8
*iface
,
512 IUnknown
**ppAudioPathConfig
)
514 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
515 FIXME("(%p, %p): stub\n", This
, ppAudioPathConfig
);
519 static HRESULT WINAPI
IDirectMusicSegment8Impl_Compose(IDirectMusicSegment8
*iface
,
520 MUSIC_TIME mtTime
, IDirectMusicSegment
*pFromSegment
, IDirectMusicSegment
*pToSegment
,
521 IDirectMusicSegment
**ppComposedSegment
)
523 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
524 FIXME("(%p, %d, %p, %p, %p): stub\n", This
, mtTime
, pFromSegment
, pToSegment
, ppComposedSegment
);
528 static HRESULT WINAPI
IDirectMusicSegment8Impl_Download(IDirectMusicSegment8
*iface
,
529 IUnknown
*pAudioPath
)
531 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
532 FIXME("(%p, %p): stub\n", This
, pAudioPath
);
536 static HRESULT WINAPI
IDirectMusicSegment8Impl_Unload(IDirectMusicSegment8
*iface
,
537 IUnknown
*pAudioPath
)
539 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
540 FIXME("(%p, %p): stub\n", This
, pAudioPath
);
544 static const IDirectMusicSegment8Vtbl dmsegment8_vtbl
= {
545 IDirectMusicSegment8Impl_QueryInterface
,
546 IDirectMusicSegment8Impl_AddRef
,
547 IDirectMusicSegment8Impl_Release
,
548 IDirectMusicSegment8Impl_GetLength
,
549 IDirectMusicSegment8Impl_SetLength
,
550 IDirectMusicSegment8Impl_GetRepeats
,
551 IDirectMusicSegment8Impl_SetRepeats
,
552 IDirectMusicSegment8Impl_GetDefaultResolution
,
553 IDirectMusicSegment8Impl_SetDefaultResolution
,
554 IDirectMusicSegment8Impl_GetTrack
,
555 IDirectMusicSegment8Impl_GetTrackGroup
,
556 IDirectMusicSegment8Impl_InsertTrack
,
557 IDirectMusicSegment8Impl_RemoveTrack
,
558 IDirectMusicSegment8Impl_InitPlay
,
559 IDirectMusicSegment8Impl_GetGraph
,
560 IDirectMusicSegment8Impl_SetGraph
,
561 IDirectMusicSegment8Impl_AddNotificationType
,
562 IDirectMusicSegment8Impl_RemoveNotificationType
,
563 IDirectMusicSegment8Impl_GetParam
,
564 IDirectMusicSegment8Impl_SetParam
,
565 IDirectMusicSegment8Impl_Clone
,
566 IDirectMusicSegment8Impl_SetStartPoint
,
567 IDirectMusicSegment8Impl_GetStartPoint
,
568 IDirectMusicSegment8Impl_SetLoopPoints
,
569 IDirectMusicSegment8Impl_GetLoopPoints
,
570 IDirectMusicSegment8Impl_SetPChannelsUsed
,
571 IDirectMusicSegment8Impl_SetTrackConfig
,
572 IDirectMusicSegment8Impl_GetAudioPathConfig
,
573 IDirectMusicSegment8Impl_Compose
,
574 IDirectMusicSegment8Impl_Download
,
575 IDirectMusicSegment8Impl_Unload
578 /* IDirectMusicSegment8Impl IDirectMusicObject part: */
579 static HRESULT WINAPI
IDirectMusicObjectImpl_ParseDescriptor(IDirectMusicObject
*iface
,
580 IStream
*pStream
, DMUS_OBJECTDESC
*pDesc
)
582 DMUS_PRIVATE_CHUNK Chunk
;
583 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
584 LARGE_INTEGER liMove
; /* used when skipping chunks */
586 TRACE("(%p,%p, %p)\n", iface
, pStream
, pDesc
);
588 /* FIXME: should this be determined from stream? */
589 pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
590 pDesc
->guidClass
= CLSID_DirectMusicSegment
;
592 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
593 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
594 switch (Chunk
.fccID
) {
596 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
597 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
598 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
600 if (Chunk
.fccID
== DMUS_FOURCC_SEGMENT_FORM
) {
601 TRACE_(dmfile
)(": segment form\n");
603 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
604 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
605 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
606 switch (Chunk
.fccID
) {
607 case DMUS_FOURCC_GUID_CHUNK
: {
608 TRACE_(dmfile
)(": GUID chunk\n");
609 pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
610 IStream_Read (pStream
, &pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
613 case DMUS_FOURCC_VERSION_CHUNK
: {
614 TRACE_(dmfile
)(": version chunk\n");
615 pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
616 IStream_Read (pStream
, &pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
619 case DMUS_FOURCC_CATEGORY_CHUNK
: {
620 TRACE_(dmfile
)(": category chunk\n");
621 pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
622 IStream_Read (pStream
, pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
626 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
627 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
628 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
630 switch (Chunk
.fccID
) {
631 /* evil M$ UNFO list, which can (!?) contain INFO elements */
632 case DMUS_FOURCC_UNFO_LIST
: {
633 TRACE_(dmfile
)(": UNFO list\n");
635 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
636 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
637 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
638 switch (Chunk
.fccID
) {
639 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
640 (though strings seem to be valid unicode) */
641 case mmioFOURCC('I','N','A','M'):
642 case DMUS_FOURCC_UNAM_CHUNK
: {
643 TRACE_(dmfile
)(": name chunk\n");
644 pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
645 IStream_Read (pStream
, pDesc
->wszName
, Chunk
.dwSize
, NULL
);
648 case mmioFOURCC('I','A','R','T'):
649 case DMUS_FOURCC_UART_CHUNK
: {
650 TRACE_(dmfile
)(": artist chunk (ignored)\n");
651 liMove
.QuadPart
= Chunk
.dwSize
;
652 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
655 case mmioFOURCC('I','C','O','P'):
656 case DMUS_FOURCC_UCOP_CHUNK
: {
657 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
658 liMove
.QuadPart
= Chunk
.dwSize
;
659 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
662 case mmioFOURCC('I','S','B','J'):
663 case DMUS_FOURCC_USBJ_CHUNK
: {
664 TRACE_(dmfile
)(": subject chunk (ignored)\n");
665 liMove
.QuadPart
= Chunk
.dwSize
;
666 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
669 case mmioFOURCC('I','C','M','T'):
670 case DMUS_FOURCC_UCMT_CHUNK
: {
671 TRACE_(dmfile
)(": comment chunk (ignored)\n");
672 liMove
.QuadPart
= Chunk
.dwSize
;
673 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
677 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
678 liMove
.QuadPart
= Chunk
.dwSize
;
679 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
683 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
684 } while (ListCount
[0] < ListSize
[0]);
687 case DMUS_FOURCC_TRACK_LIST
: {
688 TRACE_(dmfile
)(": TRACK list\n");
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 = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
693 switch (Chunk
.fccID
) {
695 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
696 liMove
.QuadPart
= Chunk
.dwSize
;
697 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
701 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
702 } while (ListCount
[0] < ListSize
[0]);
706 TRACE_(dmfile
)(": unknown (skipping)\n");
707 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
708 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
715 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
716 liMove
.QuadPart
= Chunk
.dwSize
;
717 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
721 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
722 } while (StreamCount
< StreamSize
);
724 } else if (Chunk
.fccID
== mmioFOURCC('W','A','V','E')) {
725 TRACE_(dmfile
)(": wave form (loading not yet implemented)\n");
726 liMove
.QuadPart
= StreamSize
;
727 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
729 TRACE_(dmfile
)(": unexpected chunk (loading failed)\n");
730 liMove
.QuadPart
= StreamSize
;
731 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
735 TRACE_(dmfile
)(": reading finished\n");
739 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
740 liMove
.QuadPart
= Chunk
.dwSize
;
741 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
742 return DMUS_E_INVALIDFILE
;
746 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc
));
751 static const IDirectMusicObjectVtbl dmobject_vtbl
= {
752 dmobj_IDirectMusicObject_QueryInterface
,
753 dmobj_IDirectMusicObject_AddRef
,
754 dmobj_IDirectMusicObject_Release
,
755 dmobj_IDirectMusicObject_GetDescriptor
,
756 dmobj_IDirectMusicObject_SetDescriptor
,
757 IDirectMusicObjectImpl_ParseDescriptor
760 /* IDirectMusicSegment8Impl IPersistStream part: */
761 static HRESULT
load_track(IDirectMusicSegment8Impl
*This
, IStream
*pClonedStream
,
762 IDirectMusicTrack
**ppTrack
, DMUS_IO_TRACK_HEADER
*pTrack_hdr
)
765 IPersistStream
* pPersistStream
= NULL
;
767 hr
= CoCreateInstance (&pTrack_hdr
->guidClassID
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicTrack
, (LPVOID
*) ppTrack
);
769 ERR(": could not create object\n");
772 /* acquire PersistStream interface */
773 hr
= IDirectMusicTrack_QueryInterface (*ppTrack
, &IID_IPersistStream
, (LPVOID
*) &pPersistStream
);
775 ERR(": could not acquire IPersistStream\n");
779 hr
= IPersistStream_Load (pPersistStream
, pClonedStream
);
781 ERR(": failed to load object\n");
785 /* release all loading-related stuff */
786 IPersistStream_Release (pPersistStream
);
788 hr
= IDirectMusicSegment8_InsertTrack(&This
->IDirectMusicSegment8_iface
, *ppTrack
,
789 pTrack_hdr
->dwGroup
); /* at dsPosition */
791 ERR(": could not insert track\n");
798 static HRESULT
parse_track_form(IDirectMusicSegment8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
802 DMUS_PRIVATE_CHUNK Chunk
;
803 DWORD StreamSize
, StreamCount
, ListSize
[3];
804 LARGE_INTEGER liMove
; /* used when skipping chunks */
806 DMUS_IO_TRACK_HEADER track_hdr
;
807 DMUS_IO_TRACK_EXTRAS_HEADER track_xhdr
;
808 IDirectMusicTrack
* pTrack
= NULL
;
810 if (pChunk
->fccID
!= DMUS_FOURCC_TRACK_FORM
) {
811 ERR_(dmfile
)(": %s chunk should be a TRACK form\n", debugstr_fourcc (pChunk
->fccID
));
815 StreamSize
= pChunk
->dwSize
- sizeof(FOURCC
);
819 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
820 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
821 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
823 switch (Chunk
.fccID
) {
824 case DMUS_FOURCC_TRACK_CHUNK
: {
825 TRACE_(dmfile
)(": track chunk\n");
826 IStream_Read (pStm
, &track_hdr
, sizeof(DMUS_IO_TRACK_HEADER
), NULL
);
827 TRACE_(dmfile
)(" - class: %s\n", debugstr_guid (&track_hdr
.guidClassID
));
828 TRACE_(dmfile
)(" - dwGroup: %d\n", track_hdr
.dwGroup
);
829 TRACE_(dmfile
)(" - ckid: %s\n", debugstr_fourcc (track_hdr
.ckid
));
830 TRACE_(dmfile
)(" - fccType: %s\n", debugstr_fourcc (track_hdr
.fccType
));
833 case DMUS_FOURCC_TRACK_EXTRAS_CHUNK
: {
834 TRACE_(dmfile
)(": track extras chunk\n");
835 IStream_Read (pStm
, &track_xhdr
, sizeof(DMUS_IO_TRACK_EXTRAS_HEADER
), NULL
);
839 case DMUS_FOURCC_COMMANDTRACK_CHUNK
: {
840 TRACE_(dmfile
)(": COMMANDTRACK track\n");
841 liMove
.QuadPart
= Chunk
.dwSize
;
842 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
847 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
848 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
849 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
850 if (Chunk
.fccID
== track_hdr
.fccType
&& 0 == track_hdr
.ckid
) {
851 LPSTREAM pClonedStream
= NULL
;
853 TRACE_(dmfile
)(": TRACK list\n");
855 IStream_Clone (pStm
, &pClonedStream
);
858 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
859 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
861 hr
= load_track(This
, pClonedStream
, &pTrack
, &track_hdr
);
863 ERR(": could not load track\n");
866 IStream_Release (pClonedStream
);
868 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
; /* now we can release at as it inserted */
870 liMove
.QuadPart
= ListSize
[0];
871 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
874 TRACE_(dmfile
)(": unknown (skipping)\n");
875 liMove
.QuadPart
= Chunk
.dwSize
;
876 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
882 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
883 TRACE_(dmfile
)(": RIFF chunk of type %s\n", debugstr_fourcc(Chunk
.fccID
));
885 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
887 if (Chunk
.fccID
== track_hdr
.fccType
&& 0 == track_hdr
.ckid
) {
888 LPSTREAM pClonedStream
= NULL
;
890 TRACE_(dmfile
)(": TRACK RIFF\n");
892 IStream_Clone (pStm
, &pClonedStream
);
895 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
896 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
898 hr
= load_track(This
, pClonedStream
, &pTrack
, &track_hdr
);
900 ERR(": could not load track\n");
903 IStream_Release (pClonedStream
);
905 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
; /* now we can release at as it inserted */
907 /** now safe move the cursor */
908 liMove
.QuadPart
= ListSize
[0];
909 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
912 TRACE_(dmfile
)(": unknown RIFF fmt (skipping)\n");
913 liMove
.QuadPart
= ListSize
[0];
914 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
920 if (0 == track_hdr
.fccType
&& Chunk
.fccID
== track_hdr
.ckid
) {
921 LPSTREAM pClonedStream
= NULL
;
923 TRACE_(dmfile
)(": TRACK solo\n");
925 IStream_Clone (pStm
, &pClonedStream
);
928 liMove
.QuadPart
-= (sizeof(FOURCC
) + sizeof(DWORD
));
929 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
931 hr
= load_track(This
, pClonedStream
, &pTrack
, &track_hdr
);
933 ERR(": could not load track\n");
936 IStream_Release (pClonedStream
);
938 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
; /* now we can release at as it inserted */
940 liMove
.QuadPart
= Chunk
.dwSize
;
941 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
946 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
947 liMove
.QuadPart
= Chunk
.dwSize
;
948 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
952 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
953 } while (StreamCount
< StreamSize
);
958 static HRESULT
parse_track_list(IDirectMusicSegment8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
962 DMUS_PRIVATE_CHUNK Chunk
;
963 DWORD StreamSize
, ListSize
[3], ListCount
[3];
964 LARGE_INTEGER liMove
; /* used when skipping chunks */
966 if (pChunk
->fccID
!= DMUS_FOURCC_TRACK_LIST
) {
967 ERR_(dmfile
)(": %s chunk should be a TRACK list\n", debugstr_fourcc (pChunk
->fccID
));
971 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
975 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
976 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
977 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
978 switch (Chunk
.fccID
) {
980 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
981 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
982 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
983 switch (Chunk
.fccID
) {
984 case DMUS_FOURCC_TRACK_FORM
: {
985 TRACE_(dmfile
)(": TRACK form\n");
986 hr
= parse_track_form(This
, &Chunk
, pStm
);
987 if (FAILED(hr
)) return hr
;
991 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
992 liMove
.QuadPart
= StreamSize
;
993 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1000 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
1001 liMove
.QuadPart
= Chunk
.dwSize
;
1002 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1006 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
1007 } while (ListCount
[0] < ListSize
[0]);
1012 static HRESULT
parse_segment_form(IDirectMusicSegment8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
1015 HRESULT hr
= E_FAIL
;
1016 DMUS_PRIVATE_CHUNK Chunk
;
1017 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
1018 LARGE_INTEGER liMove
; /* used when skipping chunks */
1020 if (pChunk
->fccID
!= DMUS_FOURCC_SEGMENT_FORM
) {
1021 ERR_(dmfile
)(": %s chunk should be a segment form\n", debugstr_fourcc (pChunk
->fccID
));
1025 StreamSize
= pChunk
->dwSize
- sizeof(FOURCC
);
1029 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
1030 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
1031 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
1033 hr
= IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
1034 if (FAILED(hr
)) return hr
;
1036 if (hr
== S_FALSE
) {
1037 switch (Chunk
.fccID
) {
1038 case DMUS_FOURCC_SEGMENT_CHUNK
: {
1039 DWORD checkSz
= sizeof(FOURCC
);
1040 TRACE_(dmfile
)(": segment chunk\n");
1042 IStream_Read (pStm
, &This
->header
.dwRepeats
, sizeof(This
->header
.dwRepeats
), NULL
);
1043 checkSz
+= sizeof(This
->header
.dwRepeats
);
1044 IStream_Read (pStm
, &This
->header
.mtLength
, sizeof(This
->header
.mtLength
), NULL
);
1045 checkSz
+= sizeof(This
->header
.mtLength
);
1046 IStream_Read (pStm
, &This
->header
.mtPlayStart
, sizeof(This
->header
.mtPlayStart
), NULL
);
1047 checkSz
+= sizeof(This
->header
.mtPlayStart
);
1048 IStream_Read (pStm
, &This
->header
.mtLoopStart
, sizeof(This
->header
.mtLoopStart
), NULL
);
1049 checkSz
+= sizeof(This
->header
.mtLoopStart
);
1050 IStream_Read (pStm
, &This
->header
.mtLoopEnd
, sizeof(This
->header
.mtLoopEnd
), NULL
);
1051 checkSz
+= sizeof(This
->header
.mtLoopEnd
);
1052 IStream_Read (pStm
, &This
->header
.dwResolution
, sizeof(This
->header
.dwResolution
), NULL
);
1053 checkSz
+= sizeof(This
->header
.dwResolution
);
1054 TRACE_(dmfile
)("dwRepeats: %u\n", This
->header
.dwRepeats
);
1055 TRACE_(dmfile
)("mtLength: %u\n", This
->header
.mtLength
);
1056 TRACE_(dmfile
)("mtPlayStart: %u\n", This
->header
.mtPlayStart
);
1057 TRACE_(dmfile
)("mtLoopStart: %u\n", This
->header
.mtLoopStart
);
1058 TRACE_(dmfile
)("mtLoopEnd: %u\n", This
->header
.mtLoopEnd
);
1059 TRACE_(dmfile
)("dwResolution: %u\n", This
->header
.dwResolution
);
1061 if (Chunk
.dwSize
> checkSz
) {
1062 IStream_Read (pStm
, &This
->header
.rtLength
, sizeof(This
->header
.rtLength
), NULL
);
1063 checkSz
+= sizeof(This
->header
.rtLength
);
1064 IStream_Read (pStm
, &This
->header
.dwFlags
, sizeof(This
->header
.dwFlags
), NULL
);
1065 checkSz
+= sizeof(This
->header
.dwFlags
);
1068 if (Chunk
.dwSize
> checkSz
) {
1069 IStream_Read (pStm
, &This
->header
.rtLoopStart
, sizeof(This
->header
.rtLoopStart
), NULL
);
1070 checkSz
+= sizeof(This
->header
.rtLoopStart
);
1071 IStream_Read (pStm
, &This
->header
.rtLoopEnd
, sizeof(This
->header
.rtLoopEnd
), NULL
);
1072 checkSz
+= sizeof(This
->header
.rtLoopEnd
);
1073 IStream_Read (pStm
, &This
->header
.rtPlayStart
, sizeof(This
->header
.rtPlayStart
), NULL
);
1074 checkSz
+= sizeof(This
->header
.rtPlayStart
);
1076 liMove
.QuadPart
= Chunk
.dwSize
- checkSz
+ sizeof(FOURCC
);
1077 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1081 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
1082 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
1083 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
1085 switch (Chunk
.fccID
) {
1086 case DMUS_FOURCC_UNFO_LIST
: {
1087 TRACE_(dmfile
)(": UNFO list\n");
1089 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
1090 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
1091 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
1093 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
1094 if (FAILED(hr
)) return hr
;
1096 if (hr
== S_FALSE
) {
1097 switch (Chunk
.fccID
) {
1099 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
1100 liMove
.QuadPart
= Chunk
.dwSize
;
1101 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1107 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
1108 } while (ListCount
[0] < ListSize
[0]);
1111 case DMUS_FOURCC_TRACK_LIST
: {
1112 TRACE_(dmfile
)(": TRACK list\n");
1113 hr
= parse_track_list(This
, &Chunk
, pStm
);
1114 if (FAILED(hr
)) return hr
;
1118 TRACE_(dmfile
)(": unknown (skipping)\n");
1119 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
1120 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1127 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
1128 liMove
.QuadPart
= Chunk
.dwSize
;
1129 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1134 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
1135 } while (StreamCount
< StreamSize
);
1140 static HRESULT
load_wave(IStream
*pClonedStream
, IDirectMusicObject
**ppWaveObject
)
1142 HRESULT hr
= E_FAIL
;
1143 IPersistStream
* pPersistStream
= NULL
;
1145 hr
= CoCreateInstance (&CLSID_DirectSoundWave
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
, (LPVOID
*) ppWaveObject
);
1147 ERR(": could not create object\n");
1150 /* acquire PersistStream interface */
1151 hr
= IDirectMusicObject_QueryInterface (*ppWaveObject
, &IID_IPersistStream
, (LPVOID
*) &pPersistStream
);
1153 ERR(": could not acquire IPersistStream\n");
1157 hr
= IPersistStream_Load (pPersistStream
, pClonedStream
);
1159 ERR(": failed to load object\n");
1163 /* release all loading-related stuff */
1164 IPersistStream_Release (pPersistStream
);
1169 static inline IDirectMusicSegment8Impl
*impl_from_IPersistStream(IPersistStream
*iface
)
1171 return CONTAINING_RECORD(iface
, IDirectMusicSegment8Impl
, dmobj
.IPersistStream_iface
);
1174 static HRESULT WINAPI
seg_IPersistStream_Load(IPersistStream
*iface
, IStream
*pStm
)
1176 IDirectMusicSegment8Impl
*This
= impl_from_IPersistStream(iface
);
1178 DMUS_PRIVATE_CHUNK Chunk
;
1180 /*DWORD ListSize[3], ListCount[3];*/
1181 LARGE_INTEGER liMove
; /* used when skipping chunks */
1183 TRACE("(%p, %p): Loading\n", This
, pStm
);
1184 hr
= IStream_Read (pStm
, &Chunk
, sizeof(Chunk
), NULL
);
1186 WARN("IStream_Read failed: %08x\n", hr
);
1187 return DMUS_E_UNSUPPORTED_STREAM
;
1189 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
1190 switch (Chunk
.fccID
) {
1192 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
1193 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
1194 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
1195 switch (Chunk
.fccID
) {
1196 case DMUS_FOURCC_SEGMENT_FORM
: {
1197 TRACE_(dmfile
)(": segment form\n");
1198 hr
= parse_segment_form(This
, &Chunk
, pStm
);
1199 if (FAILED(hr
)) return hr
;
1202 case mmioFOURCC('W','A','V','E'): {
1203 LPSTREAM pClonedStream
= NULL
;
1204 IDirectMusicObject
* pWave
= NULL
;
1206 FIXME_(dmfile
)(": WAVE form (loading to be checked)\n");
1208 IStream_Clone (pStm
, &pClonedStream
);
1210 liMove
.QuadPart
= - (LONGLONG
)(sizeof(FOURCC
) * 2 + sizeof(DWORD
));
1211 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
1213 hr
= load_wave(pClonedStream
, &pWave
);
1215 ERR(": could not load track\n");
1218 IStream_Release (pClonedStream
);
1220 IDirectMusicTrack_Release(pWave
); pWave
= NULL
; /* now we can release at as it inserted */
1222 liMove
.QuadPart
= StreamSize
;
1223 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
1227 TRACE_(dmfile
)(": unexpected chunk (loading failed)\n");
1228 liMove
.QuadPart
= StreamSize
;
1229 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
1230 return DMUS_E_UNSUPPORTED_STREAM
;
1233 TRACE_(dmfile
)(": reading finished\n");
1237 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
1238 return DMUS_E_UNSUPPORTED_STREAM
;
1245 static const IPersistStreamVtbl persiststream_vtbl
= {
1246 dmobj_IPersistStream_QueryInterface
,
1247 dmobj_IPersistStream_AddRef
,
1248 dmobj_IPersistStream_Release
,
1249 dmobj_IPersistStream_GetClassID
,
1250 unimpl_IPersistStream_IsDirty
,
1251 seg_IPersistStream_Load
,
1252 unimpl_IPersistStream_Save
,
1253 unimpl_IPersistStream_GetSizeMax
1256 /* for ClassFactory */
1257 HRESULT WINAPI
create_dmsegment(REFIID lpcGUID
, void **ppobj
)
1259 IDirectMusicSegment8Impl
* obj
;
1262 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicSegment8Impl
));
1265 return E_OUTOFMEMORY
;
1267 obj
->IDirectMusicSegment8_iface
.lpVtbl
= &dmsegment8_vtbl
;
1269 dmobject_init(&obj
->dmobj
, &CLSID_DirectMusicSegment
,
1270 (IUnknown
*)&obj
->IDirectMusicSegment8_iface
);
1271 obj
->dmobj
.IDirectMusicObject_iface
.lpVtbl
= &dmobject_vtbl
;
1272 obj
->dmobj
.IPersistStream_iface
.lpVtbl
= &persiststream_vtbl
;
1273 list_init (&obj
->Tracks
);
1276 hr
= IDirectMusicSegment8_QueryInterface(&obj
->IDirectMusicSegment8_iface
, lpcGUID
, ppobj
);
1277 IDirectMusicSegment8_Release(&obj
->IDirectMusicSegment8_iface
);