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
seg_IDirectMusicObject_ParseDescriptor(IDirectMusicObject
*iface
,
580 IStream
*stream
, DMUS_OBJECTDESC
*desc
)
582 struct chunk_entry riff
= {0};
583 DWORD supported
= DMUS_OBJ_OBJECT
| DMUS_OBJ_VERSION
;
586 TRACE("(%p, %p, %p)\n", iface
, stream
, desc
);
588 if (!stream
|| !desc
)
591 if ((hr
= stream_get_chunk(stream
, &riff
)) != S_OK
)
593 if (riff
.id
!= FOURCC_RIFF
|| !(riff
.type
== DMUS_FOURCC_SEGMENT_FORM
||
594 riff
.type
== mmioFOURCC('W','A','V','E'))) {
595 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff
));
596 stream_skip_chunk(stream
, &riff
);
600 if (riff
.type
== DMUS_FOURCC_SEGMENT_FORM
)
601 supported
|= DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
;
603 supported
|= DMUS_OBJ_NAME_INFO
;
604 hr
= dmobj_parsedescriptor(stream
, &riff
, desc
, supported
);
608 desc
->guidClass
= CLSID_DirectMusicSegment
;
609 desc
->dwValidData
|= DMUS_OBJ_CLASS
;
611 TRACE("returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (desc
));
615 static const IDirectMusicObjectVtbl dmobject_vtbl
= {
616 dmobj_IDirectMusicObject_QueryInterface
,
617 dmobj_IDirectMusicObject_AddRef
,
618 dmobj_IDirectMusicObject_Release
,
619 dmobj_IDirectMusicObject_GetDescriptor
,
620 dmobj_IDirectMusicObject_SetDescriptor
,
621 seg_IDirectMusicObject_ParseDescriptor
624 /* IDirectMusicSegment8Impl IPersistStream part: */
625 static HRESULT
load_track(IDirectMusicSegment8Impl
*This
, IStream
*pClonedStream
,
626 IDirectMusicTrack
**ppTrack
, DMUS_IO_TRACK_HEADER
*pTrack_hdr
)
629 IPersistStream
* pPersistStream
= NULL
;
631 hr
= CoCreateInstance (&pTrack_hdr
->guidClassID
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicTrack
, (LPVOID
*) ppTrack
);
633 ERR(": could not create object\n");
636 /* acquire PersistStream interface */
637 hr
= IDirectMusicTrack_QueryInterface (*ppTrack
, &IID_IPersistStream
, (LPVOID
*) &pPersistStream
);
639 ERR(": could not acquire IPersistStream\n");
643 hr
= IPersistStream_Load (pPersistStream
, pClonedStream
);
645 ERR(": failed to load object\n");
649 /* release all loading-related stuff */
650 IPersistStream_Release (pPersistStream
);
652 hr
= IDirectMusicSegment8_InsertTrack(&This
->IDirectMusicSegment8_iface
, *ppTrack
,
653 pTrack_hdr
->dwGroup
); /* at dsPosition */
655 ERR(": could not insert track\n");
662 static HRESULT
parse_track_form(IDirectMusicSegment8Impl
*This
, DMUS_PRIVATE_CHUNK
*pChunk
,
666 DMUS_PRIVATE_CHUNK Chunk
;
667 DWORD StreamSize
, StreamCount
, ListSize
[3];
668 LARGE_INTEGER liMove
; /* used when skipping chunks */
670 DMUS_IO_TRACK_HEADER track_hdr
;
671 DMUS_IO_TRACK_EXTRAS_HEADER track_xhdr
;
672 IDirectMusicTrack
* pTrack
= NULL
;
674 if (pChunk
->fccID
!= DMUS_FOURCC_TRACK_FORM
) {
675 ERR_(dmfile
)(": %s chunk should be a TRACK form\n", debugstr_fourcc (pChunk
->fccID
));
679 StreamSize
= pChunk
->dwSize
- sizeof(FOURCC
);
683 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
684 StreamCount
+= sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
685 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
687 switch (Chunk
.fccID
) {
688 case DMUS_FOURCC_TRACK_CHUNK
: {
689 TRACE_(dmfile
)(": track chunk\n");
690 IStream_Read (pStm
, &track_hdr
, sizeof(DMUS_IO_TRACK_HEADER
), NULL
);
691 TRACE_(dmfile
)(" - class: %s\n", debugstr_guid (&track_hdr
.guidClassID
));
692 TRACE_(dmfile
)(" - dwGroup: %d\n", track_hdr
.dwGroup
);
693 TRACE_(dmfile
)(" - ckid: %s\n", debugstr_fourcc (track_hdr
.ckid
));
694 TRACE_(dmfile
)(" - fccType: %s\n", debugstr_fourcc (track_hdr
.fccType
));
697 case DMUS_FOURCC_TRACK_EXTRAS_CHUNK
: {
698 TRACE_(dmfile
)(": track extras chunk\n");
699 IStream_Read (pStm
, &track_xhdr
, sizeof(DMUS_IO_TRACK_EXTRAS_HEADER
), NULL
);
703 case DMUS_FOURCC_COMMANDTRACK_CHUNK
: {
704 TRACE_(dmfile
)(": COMMANDTRACK track\n");
705 liMove
.QuadPart
= Chunk
.dwSize
;
706 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
711 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
712 TRACE_(dmfile
)(": LIST chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
713 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
714 if (Chunk
.fccID
== track_hdr
.fccType
&& 0 == track_hdr
.ckid
) {
715 LPSTREAM pClonedStream
= NULL
;
717 TRACE_(dmfile
)(": TRACK list\n");
719 IStream_Clone (pStm
, &pClonedStream
);
722 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
723 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
725 hr
= load_track(This
, pClonedStream
, &pTrack
, &track_hdr
);
727 ERR(": could not load track\n");
730 IStream_Release (pClonedStream
);
732 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
; /* now we can release at as it inserted */
734 liMove
.QuadPart
= ListSize
[0];
735 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
738 TRACE_(dmfile
)(": unknown (skipping)\n");
739 liMove
.QuadPart
= Chunk
.dwSize
;
740 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
746 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
747 TRACE_(dmfile
)(": RIFF chunk of type %s\n", debugstr_fourcc(Chunk
.fccID
));
749 ListSize
[0] = Chunk
.dwSize
- sizeof(FOURCC
);
751 if (Chunk
.fccID
== track_hdr
.fccType
&& 0 == track_hdr
.ckid
) {
752 LPSTREAM pClonedStream
= NULL
;
754 TRACE_(dmfile
)(": TRACK RIFF\n");
756 IStream_Clone (pStm
, &pClonedStream
);
759 liMove
.QuadPart
-= sizeof(FOURCC
) + (sizeof(FOURCC
)+sizeof(DWORD
));
760 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
762 hr
= load_track(This
, pClonedStream
, &pTrack
, &track_hdr
);
764 ERR(": could not load track\n");
767 IStream_Release (pClonedStream
);
769 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
; /* now we can release at as it inserted */
771 /** now safe move the cursor */
772 liMove
.QuadPart
= ListSize
[0];
773 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
776 TRACE_(dmfile
)(": unknown RIFF fmt (skipping)\n");
777 liMove
.QuadPart
= ListSize
[0];
778 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
784 if (0 == track_hdr
.fccType
&& Chunk
.fccID
== track_hdr
.ckid
) {
785 LPSTREAM pClonedStream
= NULL
;
787 TRACE_(dmfile
)(": TRACK solo\n");
789 IStream_Clone (pStm
, &pClonedStream
);
792 liMove
.QuadPart
-= (sizeof(FOURCC
) + sizeof(DWORD
));
793 IStream_Seek (pClonedStream
, liMove
, STREAM_SEEK_CUR
, NULL
);
795 hr
= load_track(This
, pClonedStream
, &pTrack
, &track_hdr
);
797 ERR(": could not load track\n");
800 IStream_Release (pClonedStream
);
802 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
; /* now we can release at as it inserted */
804 liMove
.QuadPart
= Chunk
.dwSize
;
805 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
810 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
811 liMove
.QuadPart
= Chunk
.dwSize
;
812 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
816 TRACE_(dmfile
)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount
, StreamSize
);
817 } while (StreamCount
< StreamSize
);
822 static HRESULT
parse_track_list(IDirectMusicSegment8Impl
*This
, DWORD StreamSize
, IStream
*pStm
)
825 DMUS_PRIVATE_CHUNK Chunk
;
826 DWORD ListSize
[3], ListCount
[3];
827 LARGE_INTEGER liMove
; /* used when skipping chunks */
829 ListSize
[0] = StreamSize
- sizeof(FOURCC
);
833 IStream_Read (pStm
, &Chunk
, sizeof(FOURCC
)+sizeof(DWORD
), NULL
);
834 ListCount
[0] += sizeof(FOURCC
) + sizeof(DWORD
) + Chunk
.dwSize
;
835 TRACE_(dmfile
)(": %s chunk (size = %d)", debugstr_fourcc (Chunk
.fccID
), Chunk
.dwSize
);
836 switch (Chunk
.fccID
) {
838 IStream_Read (pStm
, &Chunk
.fccID
, sizeof(FOURCC
), NULL
);
839 TRACE_(dmfile
)(": RIFF chunk of type %s", debugstr_fourcc(Chunk
.fccID
));
840 StreamSize
= Chunk
.dwSize
- sizeof(FOURCC
);
841 switch (Chunk
.fccID
) {
842 case DMUS_FOURCC_TRACK_FORM
: {
843 TRACE_(dmfile
)(": TRACK form\n");
844 hr
= parse_track_form(This
, &Chunk
, pStm
);
845 if (FAILED(hr
)) return hr
;
849 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
850 liMove
.QuadPart
= StreamSize
;
851 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
858 TRACE_(dmfile
)(": unknown chunk (irrelevant & skipping)\n");
859 liMove
.QuadPart
= Chunk
.dwSize
;
860 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
864 TRACE_(dmfile
)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount
[0], ListSize
[0]);
865 } while (ListCount
[0] < ListSize
[0]);
870 static inline void dump_segment_header(DMUS_IO_SEGMENT_HEADER
*h
, DWORD size
)
874 if (size
== offsetof(DMUS_IO_SEGMENT_HEADER
, rtLength
))
876 else if (size
== offsetof(DMUS_IO_SEGMENT_HEADER
, rtLoopStart
))
878 TRACE("Found DirectX%d DMUS_IO_SEGMENT_HEADER\n", dx
);
879 TRACE("\tdwRepeats: %u\n", h
->dwRepeats
);
880 TRACE("\tmtLength: %u\n", h
->mtLength
);
881 TRACE("\tmtPlayStart: %u\n", h
->mtPlayStart
);
882 TRACE("\tmtLoopStart: %u\n", h
->mtLoopStart
);
883 TRACE("\tmtLoopEnd: %u\n", h
->mtLoopEnd
);
884 TRACE("\tdwResolution: %u\n", h
->dwResolution
);
886 TRACE("\trtLength: %s\n", wine_dbgstr_longlong(h
->rtLength
));
887 TRACE("\tdwFlags: %u\n", h
->dwFlags
);
888 TRACE("\tdwReserved: %u\n", h
->dwReserved
);
891 TRACE("\trtLoopStart: %s\n", wine_dbgstr_longlong(h
->rtLoopStart
));
892 TRACE("\trtLoopEnd: %s\n", wine_dbgstr_longlong(h
->rtLoopEnd
));
893 TRACE("\trtPlayStart: %s\n", wine_dbgstr_longlong(h
->rtPlayStart
));
897 static HRESULT
parse_segment_form(IDirectMusicSegment8Impl
*This
, IStream
*stream
,
898 const struct chunk_entry
*riff
)
900 struct chunk_entry chunk
= {.parent
= riff
};
903 TRACE("Parsing segment form in %p: %s\n", stream
, debugstr_chunk(riff
));
905 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
) {
907 case DMUS_FOURCC_SEGMENT_CHUNK
:
908 /* DX7, DX8 and DX9 structure sizes */
909 if (chunk
.size
!= offsetof(DMUS_IO_SEGMENT_HEADER
, rtLength
) &&
910 chunk
.size
!= offsetof(DMUS_IO_SEGMENT_HEADER
, rtLoopStart
) &&
911 chunk
.size
!= sizeof(DMUS_IO_SEGMENT_HEADER
)) {
912 WARN("Invalid size of %s\n", debugstr_chunk(&chunk
));
915 if (FAILED(hr
= stream_chunk_get_data(stream
, &chunk
, &This
->header
, chunk
.size
))) {
916 WARN("Failed to read data of %s\n", debugstr_chunk(&chunk
));
919 dump_segment_header(&This
->header
, chunk
.size
);
922 if (chunk
.type
== DMUS_FOURCC_TRACK_LIST
)
923 if (FAILED(hr
= parse_track_list(This
, chunk
.size
, stream
)))
927 FIXME("Loading of embedded RIFF form %s\n", debugstr_fourcc(chunk
.type
));
932 return SUCCEEDED(hr
) ? S_OK
: hr
;
935 static inline IDirectMusicSegment8Impl
*impl_from_IPersistStream(IPersistStream
*iface
)
937 return CONTAINING_RECORD(iface
, IDirectMusicSegment8Impl
, dmobj
.IPersistStream_iface
);
940 static HRESULT WINAPI
seg_IPersistStream_Load(IPersistStream
*iface
, IStream
*stream
)
942 IDirectMusicSegment8Impl
*This
= impl_from_IPersistStream(iface
);
943 struct chunk_entry riff
= {0};
946 TRACE("(%p, %p): Loading\n", This
, stream
);
951 if (stream_get_chunk(stream
, &riff
) != S_OK
|| riff
.id
!= FOURCC_RIFF
)
952 return DMUS_E_UNSUPPORTED_STREAM
;
954 stream_reset_chunk_start(stream
, &riff
);
955 hr
= IDirectMusicObject_ParseDescriptor(&This
->dmobj
.IDirectMusicObject_iface
, stream
,
959 stream_reset_chunk_data(stream
, &riff
);
961 if (riff
.type
== DMUS_FOURCC_SEGMENT_FORM
)
962 hr
= parse_segment_form(This
, stream
, &riff
);
964 FIXME("WAVE form loading not implemented\n");
971 static const IPersistStreamVtbl persiststream_vtbl
= {
972 dmobj_IPersistStream_QueryInterface
,
973 dmobj_IPersistStream_AddRef
,
974 dmobj_IPersistStream_Release
,
975 dmobj_IPersistStream_GetClassID
,
976 unimpl_IPersistStream_IsDirty
,
977 seg_IPersistStream_Load
,
978 unimpl_IPersistStream_Save
,
979 unimpl_IPersistStream_GetSizeMax
982 /* for ClassFactory */
983 HRESULT WINAPI
create_dmsegment(REFIID lpcGUID
, void **ppobj
)
985 IDirectMusicSegment8Impl
* obj
;
988 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicSegment8Impl
));
991 return E_OUTOFMEMORY
;
993 obj
->IDirectMusicSegment8_iface
.lpVtbl
= &dmsegment8_vtbl
;
995 dmobject_init(&obj
->dmobj
, &CLSID_DirectMusicSegment
,
996 (IUnknown
*)&obj
->IDirectMusicSegment8_iface
);
997 obj
->dmobj
.IDirectMusicObject_iface
.lpVtbl
= &dmobject_vtbl
;
998 obj
->dmobj
.IPersistStream_iface
.lpVtbl
= &persiststream_vtbl
;
999 list_init (&obj
->Tracks
);
1002 hr
= IDirectMusicSegment8_QueryInterface(&obj
->IDirectMusicSegment8_iface
, lpcGUID
, ppobj
);
1003 IDirectMusicSegment8_Release(&obj
->IDirectMusicSegment8_iface
);