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
);
51 if (IsEqualIID (riid
, &IID_IUnknown
) || IsEqualIID (riid
, &IID_IDirectMusicSegment
) ||
52 IsEqualIID(riid
, &IID_IDirectMusicSegment2
) ||
53 IsEqualIID (riid
, &IID_IDirectMusicSegment8
))
55 else if (IsEqualIID (riid
, &IID_IDirectMusicObject
))
56 *ret_iface
= &This
->dmobj
.IDirectMusicObject_iface
;
57 else if (IsEqualIID (riid
, &IID_IPersistStream
))
58 *ret_iface
= &This
->dmobj
.IPersistStream_iface
;
60 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ret_iface
);
64 IUnknown_AddRef((IUnknown
*)*ret_iface
);
68 static ULONG WINAPI
IDirectMusicSegment8Impl_AddRef(IDirectMusicSegment8
*iface
)
70 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
71 LONG ref
= InterlockedIncrement(&This
->ref
);
73 TRACE("(%p) ref=%d\n", This
, ref
);
78 static ULONG WINAPI
IDirectMusicSegment8Impl_Release(IDirectMusicSegment8
*iface
)
80 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
81 LONG ref
= InterlockedDecrement(&This
->ref
);
83 TRACE("(%p) ref=%d\n", This
, ref
);
86 HeapFree(GetProcessHeap(), 0, This
);
93 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetLength(IDirectMusicSegment8
*iface
,
94 MUSIC_TIME
*pmtLength
)
96 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
98 TRACE("(%p, %p)\n", This
, pmtLength
);
99 if (NULL
== pmtLength
) {
102 *pmtLength
= This
->header
.mtLength
;
106 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetLength(IDirectMusicSegment8
*iface
,
109 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
111 TRACE("(%p, %d)\n", This
, mtLength
);
112 This
->header
.mtLength
= mtLength
;
116 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetRepeats(IDirectMusicSegment8
*iface
,
119 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
121 TRACE("(%p, %p)\n", This
, pdwRepeats
);
122 if (NULL
== pdwRepeats
) {
125 *pdwRepeats
= This
->header
.dwRepeats
;
129 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetRepeats(IDirectMusicSegment8
*iface
,
132 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
134 TRACE("(%p, %d)\n", This
, dwRepeats
);
135 This
->header
.dwRepeats
= dwRepeats
;
139 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetDefaultResolution(IDirectMusicSegment8
*iface
,
140 DWORD
*pdwResolution
)
142 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
144 TRACE("(%p, %p)\n", This
, pdwResolution
);
145 if (NULL
== pdwResolution
) {
148 *pdwResolution
= This
->header
.dwResolution
;
152 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetDefaultResolution(IDirectMusicSegment8
*iface
,
155 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
157 TRACE("(%p, %d)\n", This
, dwResolution
);
158 This
->header
.dwResolution
= dwResolution
;
162 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetTrack(IDirectMusicSegment8
*iface
,
163 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, IDirectMusicTrack
**ppTrack
)
165 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
167 struct list
* pEntry
= NULL
;
168 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
169 IPersistStream
* pCLSIDStream
= NULL
;
172 TRACE("(%p, %s, %d, 0x%x, %p)\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, ppTrack
);
174 if (NULL
== ppTrack
) {
178 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
179 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
180 TRACE(" - %p -> 0x%x,%p\n", pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
181 if (0xFFFFFFFF != dwGroupBits
&& 0 == (pIt
->dwGroupBits
& dwGroupBits
)) continue ;
182 if (FALSE
== IsEqualGUID(&GUID_NULL
, rguidType
)) {
184 * it rguidType is not null we must check if CLSIDs are equal
185 * and the unique way to get it is using IPersistStream Interface
187 hr
= IDirectMusicTrack_QueryInterface(pIt
->pTrack
, &IID_IPersistStream
, (void**) &pCLSIDStream
);
189 ERR("(%p): object %p don't implement IPersistStream Interface. Expect a crash (critical problem)\n", This
, pIt
->pTrack
);
192 hr
= IPersistStream_GetClassID(pCLSIDStream
, &pIt_clsid
);
193 IPersistStream_Release(pCLSIDStream
); pCLSIDStream
= NULL
;
195 ERR("(%p): non-implemented GetClassID for object %p\n", This
, pIt
->pTrack
);
198 TRACE(" - %p -> %s\n", pIt
, debugstr_dmguid(&pIt_clsid
));
199 if (FALSE
== IsEqualGUID(&pIt_clsid
, rguidType
)) continue ;
202 *ppTrack
= pIt
->pTrack
;
203 IDirectMusicTrack_AddRef(*ppTrack
);
208 return DMUS_E_NOT_FOUND
;
211 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetTrackGroup(IDirectMusicSegment8
*iface
,
212 IDirectMusicTrack
*pTrack
, DWORD
*pdwGroupBits
)
214 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
215 struct list
* pEntry
= NULL
;
216 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
218 TRACE("(%p, %p, %p)\n", This
, pTrack
, pdwGroupBits
);
220 if (NULL
== pdwGroupBits
) {
224 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
225 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
226 TRACE(" - %p -> %d,%p\n", pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
227 if (NULL
!= pIt
&& pIt
->pTrack
== pTrack
) {
228 *pdwGroupBits
= pIt
->dwGroupBits
;
233 return DMUS_E_NOT_FOUND
;
236 static HRESULT WINAPI
IDirectMusicSegment8Impl_InsertTrack(IDirectMusicSegment8
*iface
,
237 IDirectMusicTrack
*pTrack
, DWORD dwGroupBits
)
239 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
241 struct list
* pEntry
= NULL
;
242 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
243 LPDMUS_PRIVATE_SEGMENT_TRACK pNewSegTrack
= NULL
;
245 TRACE("(%p, %p, %d)\n", This
, pTrack
, dwGroupBits
);
247 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
249 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
250 TRACE(" - #%u: %p -> %d,%p\n", i
, pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
251 if (NULL
!= pIt
&& pIt
->pTrack
== pTrack
) {
252 ERR("(%p, %p): track is already in list\n", This
, pTrack
);
257 pNewSegTrack
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(DMUS_PRIVATE_SEGMENT_TRACK
));
258 if (NULL
== pNewSegTrack
)
259 return E_OUTOFMEMORY
;
261 pNewSegTrack
->dwGroupBits
= dwGroupBits
;
262 pNewSegTrack
->pTrack
= pTrack
;
263 IDirectMusicTrack_Init(pTrack
, (IDirectMusicSegment
*)iface
);
264 IDirectMusicTrack_AddRef(pTrack
);
265 list_add_tail (&This
->Tracks
, &pNewSegTrack
->entry
);
270 static HRESULT WINAPI
IDirectMusicSegment8Impl_RemoveTrack(IDirectMusicSegment8
*iface
,
271 IDirectMusicTrack
*pTrack
)
273 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
274 struct list
* pEntry
= NULL
;
275 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
277 TRACE("(%p, %p)\n", This
, pTrack
);
279 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
280 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
281 if (pIt
->pTrack
== pTrack
) {
282 TRACE("(%p, %p): track in list\n", This
, pTrack
);
284 list_remove(&pIt
->entry
);
285 IDirectMusicTrack_Init(pIt
->pTrack
, NULL
);
286 IDirectMusicTrack_Release(pIt
->pTrack
);
287 HeapFree(GetProcessHeap(), 0, pIt
);
296 static HRESULT WINAPI
IDirectMusicSegment8Impl_InitPlay(IDirectMusicSegment8
*iface
,
297 IDirectMusicSegmentState
**ppSegState
, IDirectMusicPerformance
*pPerformance
, DWORD dwFlags
)
299 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
302 FIXME("(%p, %p, %p, %d): semi-stub\n", This
, ppSegState
, pPerformance
, dwFlags
);
303 if (NULL
== ppSegState
) {
306 hr
= create_dmsegmentstate(&IID_IDirectMusicSegmentState
,(void**) ppSegState
);
310 /* TODO: DMUS_SEGF_FLAGS */
314 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetGraph(IDirectMusicSegment8
*iface
,
315 IDirectMusicGraph
**ppGraph
)
317 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
319 FIXME("(%p, %p): semi-stub\n", This
, ppGraph
);
320 if (NULL
== ppGraph
) {
323 if (NULL
== This
->pGraph
) {
324 return DMUS_E_NOT_FOUND
;
327 * should return This, as seen in msdn
328 * "...The segment object implements IDirectMusicGraph directly..."
330 *ppGraph
= This
->pGraph
;
331 IDirectMusicGraph_AddRef(This
->pGraph
);
335 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetGraph(IDirectMusicSegment8
*iface
,
336 IDirectMusicGraph
*pGraph
)
338 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
340 FIXME("(%p, %p): to complete\n", This
, pGraph
);
341 if (NULL
!= This
->pGraph
) {
342 IDirectMusicGraph_Release(This
->pGraph
);
344 This
->pGraph
= pGraph
;
345 if (NULL
!= This
->pGraph
) {
346 IDirectMusicGraph_AddRef(This
->pGraph
);
351 static HRESULT WINAPI
IDirectMusicSegment8Impl_AddNotificationType(IDirectMusicSegment8
*iface
,
352 REFGUID rguidNotificationType
)
354 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
355 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidNotificationType
));
359 static HRESULT WINAPI
IDirectMusicSegment8Impl_RemoveNotificationType(IDirectMusicSegment8
*iface
,
360 REFGUID rguidNotificationType
)
362 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
363 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidNotificationType
));
367 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetParam(IDirectMusicSegment8
*iface
,
368 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
, MUSIC_TIME
*pmtNext
,
371 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
373 struct list
* pEntry
= NULL
;
374 IDirectMusicTrack
* pTrack
= NULL
;
375 IPersistStream
* pCLSIDStream
= NULL
;
376 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
379 FIXME("(%p, %s, 0x%x, %d, %d, %p, %p)\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pmtNext
, pParam
);
381 if (DMUS_SEG_ANYTRACK
== dwIndex
) {
383 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
384 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
386 hr
= IDirectMusicTrack_QueryInterface(pIt
->pTrack
, &IID_IPersistStream
, (void**) &pCLSIDStream
);
388 ERR("(%p): object %p don't implement IPersistStream Interface. Expect a crash (critical problem)\n", This
, pIt
->pTrack
);
392 TRACE(" - %p -> 0x%x,%p\n", pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
394 if (0xFFFFFFFF != dwGroupBits
&& 0 == (pIt
->dwGroupBits
& dwGroupBits
)) continue ;
395 hr
= IPersistStream_GetClassID(pCLSIDStream
, &pIt_clsid
);
396 IPersistStream_Release(pCLSIDStream
); pCLSIDStream
= NULL
;
398 ERR("(%p): non-implemented GetClassID for object %p\n", This
, pIt
->pTrack
);
401 if (FALSE
== IsEqualGUID(&pIt_clsid
, rguidType
)) continue ;
402 if (FAILED(IDirectMusicTrack_IsParamSupported(pIt
->pTrack
, rguidType
))) continue ;
403 hr
= IDirectMusicTrack_GetParam(pIt
->pTrack
, rguidType
, mtTime
, pmtNext
, pParam
);
404 if (SUCCEEDED(hr
)) return hr
;
406 ERR("(%p): not found\n", This
);
407 return DMUS_E_TRACK_NOT_FOUND
;
410 hr
= IDirectMusicSegment8Impl_GetTrack(iface
, &GUID_NULL
, dwGroupBits
, dwIndex
, &pTrack
);
412 ERR("(%p): not found\n", This
);
413 return DMUS_E_TRACK_NOT_FOUND
;
416 hr
= IDirectMusicTrack_GetParam(pTrack
, rguidType
, mtTime
, pmtNext
, pParam
);
417 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
;
422 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetParam(IDirectMusicSegment8
*iface
,
423 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
, void *pParam
)
425 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
426 FIXME("(%p, %s, %d, %d, %d, %p): stub\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pParam
);
430 static HRESULT WINAPI
IDirectMusicSegment8Impl_Clone(IDirectMusicSegment8
*iface
,
431 MUSIC_TIME mtStart
, MUSIC_TIME mtEnd
, IDirectMusicSegment
**ppSegment
)
433 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
434 FIXME("(%p, %d, %d, %p): stub\n", This
, mtStart
, mtEnd
, ppSegment
);
438 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetStartPoint(IDirectMusicSegment8
*iface
,
441 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
443 TRACE("(%p, %d)\n", This
, mtStart
);
444 if (mtStart
>= This
->header
.mtLength
) {
445 return DMUS_E_OUT_OF_RANGE
;
447 This
->header
.mtPlayStart
= mtStart
;
451 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetStartPoint(IDirectMusicSegment8
*iface
,
452 MUSIC_TIME
*pmtStart
)
454 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
456 TRACE("(%p, %p)\n", This
, pmtStart
);
457 if (NULL
== pmtStart
) {
460 *pmtStart
= This
->header
.mtPlayStart
;
464 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetLoopPoints(IDirectMusicSegment8
*iface
,
465 MUSIC_TIME mtStart
, MUSIC_TIME mtEnd
)
467 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
469 TRACE("(%p, %d, %d)\n", This
, mtStart
, mtEnd
);
470 if (mtStart
>= This
->header
.mtLength
|| mtEnd
> This
->header
.mtLength
|| mtStart
> mtEnd
) {
471 return DMUS_E_OUT_OF_RANGE
;
473 This
->header
.mtLoopStart
= mtStart
;
474 This
->header
.mtLoopEnd
= mtEnd
;
478 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetLoopPoints(IDirectMusicSegment8
*iface
,
479 MUSIC_TIME
*pmtStart
, MUSIC_TIME
*pmtEnd
)
481 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
483 TRACE("(%p, %p, %p)\n", This
, pmtStart
, pmtEnd
);
484 if (NULL
== pmtStart
|| NULL
== pmtEnd
) {
487 *pmtStart
= This
->header
.mtLoopStart
;
488 *pmtEnd
= This
->header
.mtLoopEnd
;
492 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetPChannelsUsed(IDirectMusicSegment8
*iface
,
493 DWORD dwNumPChannels
, DWORD
*paPChannels
)
495 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
496 FIXME("(%p, %d, %p): stub\n", This
, dwNumPChannels
, paPChannels
);
500 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetTrackConfig(IDirectMusicSegment8
*iface
,
501 REFGUID rguidTrackClassID
, DWORD dwGroupBits
, DWORD dwIndex
, DWORD dwFlagsOn
,
504 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
505 FIXME("(%p, %s, %d, %d, %d, %d): stub\n", This
, debugstr_dmguid(rguidTrackClassID
), dwGroupBits
, dwIndex
, dwFlagsOn
, dwFlagsOff
);
509 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetAudioPathConfig(IDirectMusicSegment8
*iface
,
510 IUnknown
**ppAudioPathConfig
)
512 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
513 FIXME("(%p, %p): stub\n", This
, ppAudioPathConfig
);
517 static HRESULT WINAPI
IDirectMusicSegment8Impl_Compose(IDirectMusicSegment8
*iface
,
518 MUSIC_TIME mtTime
, IDirectMusicSegment
*pFromSegment
, IDirectMusicSegment
*pToSegment
,
519 IDirectMusicSegment
**ppComposedSegment
)
521 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
522 FIXME("(%p, %d, %p, %p, %p): stub\n", This
, mtTime
, pFromSegment
, pToSegment
, ppComposedSegment
);
526 static HRESULT WINAPI
IDirectMusicSegment8Impl_Download(IDirectMusicSegment8
*iface
,
527 IUnknown
*pAudioPath
)
529 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
530 FIXME("(%p, %p): stub\n", This
, pAudioPath
);
534 static HRESULT WINAPI
IDirectMusicSegment8Impl_Unload(IDirectMusicSegment8
*iface
,
535 IUnknown
*pAudioPath
)
537 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
538 FIXME("(%p, %p): stub\n", This
, pAudioPath
);
542 static const IDirectMusicSegment8Vtbl dmsegment8_vtbl
= {
543 IDirectMusicSegment8Impl_QueryInterface
,
544 IDirectMusicSegment8Impl_AddRef
,
545 IDirectMusicSegment8Impl_Release
,
546 IDirectMusicSegment8Impl_GetLength
,
547 IDirectMusicSegment8Impl_SetLength
,
548 IDirectMusicSegment8Impl_GetRepeats
,
549 IDirectMusicSegment8Impl_SetRepeats
,
550 IDirectMusicSegment8Impl_GetDefaultResolution
,
551 IDirectMusicSegment8Impl_SetDefaultResolution
,
552 IDirectMusicSegment8Impl_GetTrack
,
553 IDirectMusicSegment8Impl_GetTrackGroup
,
554 IDirectMusicSegment8Impl_InsertTrack
,
555 IDirectMusicSegment8Impl_RemoveTrack
,
556 IDirectMusicSegment8Impl_InitPlay
,
557 IDirectMusicSegment8Impl_GetGraph
,
558 IDirectMusicSegment8Impl_SetGraph
,
559 IDirectMusicSegment8Impl_AddNotificationType
,
560 IDirectMusicSegment8Impl_RemoveNotificationType
,
561 IDirectMusicSegment8Impl_GetParam
,
562 IDirectMusicSegment8Impl_SetParam
,
563 IDirectMusicSegment8Impl_Clone
,
564 IDirectMusicSegment8Impl_SetStartPoint
,
565 IDirectMusicSegment8Impl_GetStartPoint
,
566 IDirectMusicSegment8Impl_SetLoopPoints
,
567 IDirectMusicSegment8Impl_GetLoopPoints
,
568 IDirectMusicSegment8Impl_SetPChannelsUsed
,
569 IDirectMusicSegment8Impl_SetTrackConfig
,
570 IDirectMusicSegment8Impl_GetAudioPathConfig
,
571 IDirectMusicSegment8Impl_Compose
,
572 IDirectMusicSegment8Impl_Download
,
573 IDirectMusicSegment8Impl_Unload
576 /* IDirectMusicSegment8Impl IDirectMusicObject part: */
577 static HRESULT WINAPI
IDirectMusicObjectImpl_ParseDescriptor(IDirectMusicObject
*iface
,
578 IStream
*pStream
, DMUS_OBJECTDESC
*pDesc
)
580 DMUS_PRIVATE_CHUNK Chunk
;
581 DWORD StreamSize
, StreamCount
, ListSize
[1], ListCount
[1];
582 LARGE_INTEGER liMove
; /* used when skipping chunks */
584 TRACE("(%p,%p, %p)\n", iface
, pStream
, pDesc
);
586 /* FIXME: should this be determined from stream? */
587 pDesc
->dwValidData
|= DMUS_OBJ_CLASS
;
588 pDesc
->guidClass
= CLSID_DirectMusicSegment
;
590 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
591 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
592 switch (Chunk
.fccID
) {
594 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
595 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
596 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
598 if (Chunk
.fccID
== DMUS_FOURCC_SEGMENT_FORM
) {
599 TRACE_(dmfile
)(": segment form\n");
601 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
602 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
603 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
604 switch (Chunk
.fccID
) {
605 case DMUS_FOURCC_GUID_CHUNK
: {
606 TRACE_(dmfile
)(": GUID chunk\n");
607 pDesc
->dwValidData
|= DMUS_OBJ_OBJECT
;
608 IStream_Read (pStream
, &pDesc
->guidObject
, Chunk
.dwSize
, NULL
);
611 case DMUS_FOURCC_VERSION_CHUNK
: {
612 TRACE_(dmfile
)(": version chunk\n");
613 pDesc
->dwValidData
|= DMUS_OBJ_VERSION
;
614 IStream_Read (pStream
, &pDesc
->vVersion
, Chunk
.dwSize
, NULL
);
617 case DMUS_FOURCC_CATEGORY_CHUNK
: {
618 TRACE_(dmfile
)(": category chunk\n");
619 pDesc
->dwValidData
|= DMUS_OBJ_CATEGORY
;
620 IStream_Read (pStream
, pDesc
->wszCategory
, Chunk
.dwSize
, NULL
);
624 IStream_Read (pStream
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
625 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
626 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
628 switch (Chunk
.fccID
) {
629 /* evil M$ UNFO list, which can (!?) contain INFO elements */
630 case DMUS_FOURCC_UNFO_LIST
: {
631 TRACE_(dmfile
)(": UNFO list\n");
633 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
634 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
635 TRACE_(dmfile
)(": %s chunk (size = 0x%04x)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
636 switch (Chunk
.fccID
) {
637 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
638 (though strings seem to be valid unicode) */
639 case mmioFOURCC('I','N','A','M'):
640 case DMUS_FOURCC_UNAM_CHUNK
: {
641 TRACE_(dmfile
)(": name chunk\n");
642 pDesc
->dwValidData
|= DMUS_OBJ_NAME
;
643 IStream_Read (pStream
, pDesc
->wszName
, Chunk
.dwSize
, NULL
);
646 case mmioFOURCC('I','A','R','T'):
647 case DMUS_FOURCC_UART_CHUNK
: {
648 TRACE_(dmfile
)(": artist chunk (ignored)\n");
649 liMove
.QuadPart
= Chunk
.dwSize
;
650 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
653 case mmioFOURCC('I','C','O','P'):
654 case DMUS_FOURCC_UCOP_CHUNK
: {
655 TRACE_(dmfile
)(": copyright chunk (ignored)\n");
656 liMove
.QuadPart
= Chunk
.dwSize
;
657 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
660 case mmioFOURCC('I','S','B','J'):
661 case DMUS_FOURCC_USBJ_CHUNK
: {
662 TRACE_(dmfile
)(": subject chunk (ignored)\n");
663 liMove
.QuadPart
= Chunk
.dwSize
;
664 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
667 case mmioFOURCC('I','C','M','T'):
668 case DMUS_FOURCC_UCMT_CHUNK
: {
669 TRACE_(dmfile
)(": comment chunk (ignored)\n");
670 liMove
.QuadPart
= Chunk
.dwSize
;
671 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
675 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
676 liMove
.QuadPart
= Chunk
.dwSize
;
677 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
681 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
682 } while (ListCount
[0] < ListSize
[0]);
685 case DMUS_FOURCC_TRACK_LIST
: {
686 TRACE_(dmfile
)(": TRACK list\n");
688 IStream_Read (pStream
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
689 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
690 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
691 switch (Chunk
.fccID
) {
693 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
694 liMove
.QuadPart
= Chunk
.dwSize
;
695 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
699 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
700 } while (ListCount
[0] < ListSize
[0]);
704 TRACE_(dmfile
)(": unknown (skipping)\n");
705 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
706 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
713 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
714 liMove
.QuadPart
= Chunk
.dwSize
;
715 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
719 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
720 } while (StreamCount
< StreamSize
);
722 } else if (Chunk
.fccID
== mmioFOURCC('W','A','V','E')) {
723 TRACE_(dmfile
)(": wave form (loading not yet implemented)\n");
724 liMove
.QuadPart
= StreamSize
;
725 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
727 TRACE_(dmfile
)(": unexpected chunk (loading failed)\n");
728 liMove
.QuadPart
= StreamSize
;
729 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
733 TRACE_(dmfile
)(": reading finished\n");
737 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
738 liMove
.QuadPart
= Chunk
.dwSize
;
739 IStream_Seek (pStream
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
740 return DMUS_E_INVALIDFILE
;
744 TRACE(": returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (pDesc
));
749 static const IDirectMusicObjectVtbl dmobject_vtbl
= {
750 dmobj_IDirectMusicObject_QueryInterface
,
751 dmobj_IDirectMusicObject_AddRef
,
752 dmobj_IDirectMusicObject_Release
,
753 dmobj_IDirectMusicObject_GetDescriptor
,
754 dmobj_IDirectMusicObject_SetDescriptor
,
755 IDirectMusicObjectImpl_ParseDescriptor
758 /* IDirectMusicSegment8Impl IPersistStream part: */
759 static HRESULT
load_track(IDirectMusicSegment8Impl
*This
, IStream
*pClonedStream
,
760 IDirectMusicTrack
**ppTrack
, DMUS_IO_TRACK_HEADER
*pTrack_hdr
)
763 IPersistStream
* pPersistStream
= NULL
;
765 hr
= CoCreateInstance (&pTrack_hdr
->guidClassID
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicTrack
, (LPVOID
*) ppTrack
);
767 ERR(": could not create object\n");
770 /* acquire PersistStream interface */
771 hr
= IDirectMusicTrack_QueryInterface (*ppTrack
, &IID_IPersistStream
, (LPVOID
*) &pPersistStream
);
773 ERR(": could not acquire IPersistStream\n");
777 hr
= IPersistStream_Load (pPersistStream
, pClonedStream
);
779 ERR(": failed to load object\n");
783 /* release all loading-related stuff */
784 IPersistStream_Release (pPersistStream
);
786 hr
= IDirectMusicSegment8_InsertTrack(&This
->IDirectMusicSegment8_iface
, *ppTrack
,
787 pTrack_hdr
->dwGroup
); /* at dsPosition */
789 ERR(": could not insert track\n");
796 static HRESULT
parse_track_form(IDirectMusicSegment8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
800 DMUS_PRIVATE_CHUNK Chunk
;
801 DWORD StreamSize
, StreamCount
, ListSize
[3];
802 LARGE_INTEGER liMove
; /* used when skipping chunks */
804 DMUS_IO_TRACK_HEADER track_hdr
;
805 DMUS_IO_TRACK_EXTRAS_HEADER track_xhdr
;
806 IDirectMusicTrack
* pTrack
= NULL
;
808 if (pChunk
->fccID
!= DMUS_FOURCC_TRACK_FORM
) {
809 ERR_(dmfile
)(": %s chunk should be a TRACK form\n", debugstr_fourcc (pChunk
->fccID
));
813 StreamSize
= pChunk
->dwSize
- sizeof(FOURCC
);
817 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
818 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
819 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
821 switch (Chunk
.fccID
) {
822 case DMUS_FOURCC_TRACK_CHUNK
: {
823 TRACE_(dmfile
)(": track chunk\n");
824 IStream_Read (pStm
, &track_hdr
, sizeof(DMUS_IO_TRACK_HEADER
), NULL
);
825 TRACE_(dmfile
)(" - class: %s\n", debugstr_guid (&track_hdr
.guidClassID
));
826 TRACE_(dmfile
)(" - dwGroup: %d\n", track_hdr
.dwGroup
);
827 TRACE_(dmfile
)(" - ckid: %s\n", debugstr_fourcc (track_hdr
.ckid
));
828 TRACE_(dmfile
)(" - fccType: %s\n", debugstr_fourcc (track_hdr
.fccType
));
831 case DMUS_FOURCC_TRACK_EXTRAS_CHUNK
: {
832 TRACE_(dmfile
)(": track extras chunk\n");
833 IStream_Read (pStm
, &track_xhdr
, sizeof(DMUS_IO_TRACK_EXTRAS_HEADER
), NULL
);
837 case DMUS_FOURCC_COMMANDTRACK_CHUNK
: {
838 TRACE_(dmfile
)(": COMMANDTRACK track\n");
839 liMove
.QuadPart
= Chunk
.dwSize
;
840 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
845 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
846 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
847 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
848 if (Chunk
.fccID
== track_hdr
.fccType
&& 0 == track_hdr
.ckid
) {
849 LPSTREAM pClonedStream
= NULL
;
851 TRACE_(dmfile
)(": TRACK list\n");
853 IStream_Clone (pStm
, &pClonedStream
);
856 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
857 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
859 hr
= load_track(This
, pClonedStream
, &pTrack
, &track_hdr
);
861 ERR(": could not load track\n");
864 IStream_Release (pClonedStream
);
866 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
; /* now we can release at as it inserted */
868 liMove
.QuadPart
= ListSize
[0];
869 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
872 TRACE_(dmfile
)(": unknown (skipping)\n");
873 liMove
.QuadPart
= Chunk
.dwSize
;
874 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
880 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
881 TRACE_(dmfile
)(": RIFF chunk of type %s\n", debugstr_fourcc(Chunk
.fccID
));
883 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
885 if (Chunk
.fccID
== track_hdr
.fccType
&& 0 == track_hdr
.ckid
) {
886 LPSTREAM pClonedStream
= NULL
;
888 TRACE_(dmfile
)(": TRACK RIFF\n");
890 IStream_Clone (pStm
, &pClonedStream
);
893 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
894 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
896 hr
= load_track(This
, pClonedStream
, &pTrack
, &track_hdr
);
898 ERR(": could not load track\n");
901 IStream_Release (pClonedStream
);
903 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
; /* now we can release at as it inserted */
905 /** now safe move the cursor */
906 liMove
.QuadPart
= ListSize
[0];
907 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
910 TRACE_(dmfile
)(": unknown RIFF fmt (skipping)\n");
911 liMove
.QuadPart
= ListSize
[0];
912 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
918 if (0 == track_hdr
.fccType
&& Chunk
.fccID
== track_hdr
.ckid
) {
919 LPSTREAM pClonedStream
= NULL
;
921 TRACE_(dmfile
)(": TRACK solo\n");
923 IStream_Clone (pStm
, &pClonedStream
);
926 liMove
.QuadPart
-= (sizeof(FOURCC
) + sizeof(DWORD
));
927 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
929 hr
= load_track(This
, pClonedStream
, &pTrack
, &track_hdr
);
931 ERR(": could not load track\n");
934 IStream_Release (pClonedStream
);
936 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
; /* now we can release at as it inserted */
938 liMove
.QuadPart
= Chunk
.dwSize
;
939 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
944 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
945 liMove
.QuadPart
= Chunk
.dwSize
;
946 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
950 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
951 } while (StreamCount
< StreamSize
);
956 static HRESULT
parse_track_list(IDirectMusicSegment8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
960 DMUS_PRIVATE_CHUNK Chunk
;
961 DWORD StreamSize
, ListSize
[3], ListCount
[3];
962 LARGE_INTEGER liMove
; /* used when skipping chunks */
964 if (pChunk
->fccID
!= DMUS_FOURCC_TRACK_LIST
) {
965 ERR_(dmfile
)(": %s chunk should be a TRACK list\n", debugstr_fourcc (pChunk
->fccID
));
969 ListSize
[0] = pChunk
->dwSize
- sizeof(FOURCC
);
973 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
974 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
975 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
976 switch (Chunk
.fccID
) {
978 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
979 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
980 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
981 switch (Chunk
.fccID
) {
982 case DMUS_FOURCC_TRACK_FORM
: {
983 TRACE_(dmfile
)(": TRACK form\n");
984 hr
= parse_track_form(This
, &Chunk
, pStm
);
985 if (FAILED(hr
)) return hr
;
989 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
990 liMove
.QuadPart
= StreamSize
;
991 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
998 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
999 liMove
.QuadPart
= Chunk
.dwSize
;
1000 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1004 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
1005 } while (ListCount
[0] < ListSize
[0]);
1010 static HRESULT
parse_segment_form(IDirectMusicSegment8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
1013 HRESULT hr
= E_FAIL
;
1014 DMUS_PRIVATE_CHUNK Chunk
;
1015 DWORD StreamSize
, StreamCount
, ListSize
[3], ListCount
[3];
1016 LARGE_INTEGER liMove
; /* used when skipping chunks */
1018 if (pChunk
->fccID
!= DMUS_FOURCC_SEGMENT_FORM
) {
1019 ERR_(dmfile
)(": %s chunk should be a segment form\n", debugstr_fourcc (pChunk
->fccID
));
1023 StreamSize
= pChunk
->dwSize
- sizeof(FOURCC
);
1027 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
1028 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
1029 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
1031 hr
= IDirectMusicUtils_IPersistStream_ParseDescGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
1032 if (FAILED(hr
)) return hr
;
1034 if (hr
== S_FALSE
) {
1035 switch (Chunk
.fccID
) {
1036 case DMUS_FOURCC_SEGMENT_CHUNK
: {
1037 DWORD checkSz
= sizeof(FOURCC
);
1038 TRACE_(dmfile
)(": segment chunk\n");
1040 IStream_Read (pStm
, &This
->header
.dwRepeats
, sizeof(This
->header
.dwRepeats
), NULL
);
1041 checkSz
+= sizeof(This
->header
.dwRepeats
);
1042 IStream_Read (pStm
, &This
->header
.mtLength
, sizeof(This
->header
.mtLength
), NULL
);
1043 checkSz
+= sizeof(This
->header
.mtLength
);
1044 IStream_Read (pStm
, &This
->header
.mtPlayStart
, sizeof(This
->header
.mtPlayStart
), NULL
);
1045 checkSz
+= sizeof(This
->header
.mtPlayStart
);
1046 IStream_Read (pStm
, &This
->header
.mtLoopStart
, sizeof(This
->header
.mtLoopStart
), NULL
);
1047 checkSz
+= sizeof(This
->header
.mtLoopStart
);
1048 IStream_Read (pStm
, &This
->header
.mtLoopEnd
, sizeof(This
->header
.mtLoopEnd
), NULL
);
1049 checkSz
+= sizeof(This
->header
.mtLoopEnd
);
1050 IStream_Read (pStm
, &This
->header
.dwResolution
, sizeof(This
->header
.dwResolution
), NULL
);
1051 checkSz
+= sizeof(This
->header
.dwResolution
);
1052 TRACE_(dmfile
)("dwRepeats: %u\n", This
->header
.dwRepeats
);
1053 TRACE_(dmfile
)("mtLength: %u\n", This
->header
.mtLength
);
1054 TRACE_(dmfile
)("mtPlayStart: %u\n", This
->header
.mtPlayStart
);
1055 TRACE_(dmfile
)("mtLoopStart: %u\n", This
->header
.mtLoopStart
);
1056 TRACE_(dmfile
)("mtLoopEnd: %u\n", This
->header
.mtLoopEnd
);
1057 TRACE_(dmfile
)("dwResolution: %u\n", This
->header
.dwResolution
);
1059 if (Chunk
.dwSize
> checkSz
) {
1060 IStream_Read (pStm
, &This
->header
.rtLength
, sizeof(This
->header
.rtLength
), NULL
);
1061 checkSz
+= sizeof(This
->header
.rtLength
);
1062 IStream_Read (pStm
, &This
->header
.dwFlags
, sizeof(This
->header
.dwFlags
), NULL
);
1063 checkSz
+= sizeof(This
->header
.dwFlags
);
1066 if (Chunk
.dwSize
> checkSz
) {
1067 IStream_Read (pStm
, &This
->header
.rtLoopStart
, sizeof(This
->header
.rtLoopStart
), NULL
);
1068 checkSz
+= sizeof(This
->header
.rtLoopStart
);
1069 IStream_Read (pStm
, &This
->header
.rtLoopEnd
, sizeof(This
->header
.rtLoopEnd
), NULL
);
1070 checkSz
+= sizeof(This
->header
.rtLoopEnd
);
1071 IStream_Read (pStm
, &This
->header
.rtPlayStart
, sizeof(This
->header
.rtPlayStart
), NULL
);
1072 checkSz
+= sizeof(This
->header
.rtPlayStart
);
1074 liMove
.QuadPart
= Chunk
.dwSize
- checkSz
+ sizeof(FOURCC
);
1075 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1079 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
1080 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
1081 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
1083 switch (Chunk
.fccID
) {
1084 case DMUS_FOURCC_UNFO_LIST
: {
1085 TRACE_(dmfile
)(": UNFO list\n");
1087 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
1088 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
1089 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
1091 hr
= IDirectMusicUtils_IPersistStream_ParseUNFOGeneric(&Chunk
, pStm
, &This
->dmobj
.desc
);
1092 if (FAILED(hr
)) return hr
;
1094 if (hr
== S_FALSE
) {
1095 switch (Chunk
.fccID
) {
1097 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
1098 liMove
.QuadPart
= Chunk
.dwSize
;
1099 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1105 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
1106 } while (ListCount
[0] < ListSize
[0]);
1109 case DMUS_FOURCC_TRACK_LIST
: {
1110 TRACE_(dmfile
)(": TRACK list\n");
1111 hr
= parse_track_list(This
, &Chunk
, pStm
);
1112 if (FAILED(hr
)) return hr
;
1116 TRACE_(dmfile
)(": unknown (skipping)\n");
1117 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
1118 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1125 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
1126 liMove
.QuadPart
= Chunk
.dwSize
;
1127 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
1132 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
1133 } while (StreamCount
< StreamSize
);
1138 static HRESULT
load_wave(IStream
*pClonedStream
, IDirectMusicObject
**ppWaveObject
)
1140 HRESULT hr
= E_FAIL
;
1141 IPersistStream
* pPersistStream
= NULL
;
1143 hr
= CoCreateInstance (&CLSID_DirectSoundWave
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicObject
, (LPVOID
*) ppWaveObject
);
1145 ERR(": could not create object\n");
1148 /* acquire PersistStream interface */
1149 hr
= IDirectMusicObject_QueryInterface (*ppWaveObject
, &IID_IPersistStream
, (LPVOID
*) &pPersistStream
);
1151 ERR(": could not acquire IPersistStream\n");
1155 hr
= IPersistStream_Load (pPersistStream
, pClonedStream
);
1157 ERR(": failed to load object\n");
1161 /* release all loading-related stuff */
1162 IPersistStream_Release (pPersistStream
);
1167 static inline IDirectMusicSegment8Impl
*impl_from_IPersistStream(IPersistStream
*iface
)
1169 return CONTAINING_RECORD(iface
, IDirectMusicSegment8Impl
, dmobj
.IPersistStream_iface
);
1172 static HRESULT WINAPI
IPersistStreamImpl_Load(IPersistStream
*iface
, IStream
*pStm
)
1174 IDirectMusicSegment8Impl
*This
= impl_from_IPersistStream(iface
);
1176 DMUS_PRIVATE_CHUNK Chunk
;
1178 /*DWORD ListSize[3], ListCount[3];*/
1179 LARGE_INTEGER liMove
; /* used when skipping chunks */
1181 TRACE("(%p, %p): Loading\n", This
, pStm
);
1182 hr
= IStream_Read (pStm
, &Chunk
, sizeof(Chunk
), NULL
);
1184 WARN("IStream_Read failed: %08x\n", hr
);
1185 return DMUS_E_UNSUPPORTED_STREAM
;
1187 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
1188 switch (Chunk
.fccID
) {
1190 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
1191 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
1192 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
1193 switch (Chunk
.fccID
) {
1194 case DMUS_FOURCC_SEGMENT_FORM
: {
1195 TRACE_(dmfile
)(": segment form\n");
1196 hr
= parse_segment_form(This
, &Chunk
, pStm
);
1197 if (FAILED(hr
)) return hr
;
1200 case mmioFOURCC('W','A','V','E'): {
1201 LPSTREAM pClonedStream
= NULL
;
1202 IDirectMusicObject
* pWave
= NULL
;
1204 FIXME_(dmfile
)(": WAVE form (loading to be checked)\n");
1206 IStream_Clone (pStm
, &pClonedStream
);
1208 liMove
.QuadPart
= - (LONGLONG
)(sizeof(FOURCC
) * 2 + sizeof(DWORD
));
1209 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
1211 hr
= load_wave(pClonedStream
, &pWave
);
1213 ERR(": could not load track\n");
1216 IStream_Release (pClonedStream
);
1218 IDirectMusicTrack_Release(pWave
); pWave
= NULL
; /* now we can release at as it inserted */
1220 liMove
.QuadPart
= StreamSize
;
1221 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
1225 TRACE_(dmfile
)(": unexpected chunk (loading failed)\n");
1226 liMove
.QuadPart
= StreamSize
;
1227 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
); /* skip the rest of the chunk */
1228 return DMUS_E_UNSUPPORTED_STREAM
;
1231 TRACE_(dmfile
)(": reading finished\n");
1235 TRACE_(dmfile
)(": unexpected chunk; loading failed)\n");
1236 return DMUS_E_UNSUPPORTED_STREAM
;
1243 static const IPersistStreamVtbl persiststream_vtbl
= {
1244 dmobj_IPersistStream_QueryInterface
,
1245 dmobj_IPersistStream_AddRef
,
1246 dmobj_IPersistStream_Release
,
1247 dmobj_IPersistStream_GetClassID
,
1248 unimpl_IPersistStream_IsDirty
,
1249 IPersistStreamImpl_Load
,
1250 unimpl_IPersistStream_Save
,
1251 unimpl_IPersistStream_GetSizeMax
1254 /* for ClassFactory */
1255 HRESULT WINAPI
create_dmsegment(REFIID lpcGUID
, void **ppobj
)
1257 IDirectMusicSegment8Impl
* obj
;
1260 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicSegment8Impl
));
1263 return E_OUTOFMEMORY
;
1265 obj
->IDirectMusicSegment8_iface
.lpVtbl
= &dmsegment8_vtbl
;
1267 dmobject_init(&obj
->dmobj
, &CLSID_DirectMusicSegment
,
1268 (IUnknown
*)&obj
->IDirectMusicSegment8_iface
);
1269 obj
->dmobj
.IDirectMusicObject_iface
.lpVtbl
= &dmobject_vtbl
;
1270 obj
->dmobj
.IPersistStream_iface
.lpVtbl
= &persiststream_vtbl
;
1271 list_init (&obj
->Tracks
);
1274 hr
= IDirectMusicSegment8_QueryInterface(&obj
->IDirectMusicSegment8_iface
, lpcGUID
, ppobj
);
1275 IDirectMusicSegment8_Release(&obj
->IDirectMusicSegment8_iface
);