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
);
26 /*****************************************************************************
27 * IDirectMusicSegmentImpl implementation
29 typedef struct IDirectMusicSegment8Impl
{
30 IDirectMusicSegment8 IDirectMusicSegment8_iface
;
31 struct dmobject dmobj
;
33 DMUS_IO_SEGMENT_HEADER header
;
34 IDirectMusicGraph
*pGraph
;
36 } IDirectMusicSegment8Impl
;
38 static inline IDirectMusicSegment8Impl
*impl_from_IDirectMusicSegment8(IDirectMusicSegment8
*iface
)
40 return CONTAINING_RECORD(iface
, IDirectMusicSegment8Impl
, IDirectMusicSegment8_iface
);
43 static HRESULT WINAPI
IDirectMusicSegment8Impl_QueryInterface(IDirectMusicSegment8
*iface
,
44 REFIID riid
, void **ret_iface
)
46 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
48 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ret_iface
);
52 if (IsEqualIID (riid
, &IID_IUnknown
) || IsEqualIID (riid
, &IID_IDirectMusicSegment
) ||
53 IsEqualIID(riid
, &IID_IDirectMusicSegment2
) ||
54 IsEqualIID (riid
, &IID_IDirectMusicSegment8
))
56 else if (IsEqualIID (riid
, &IID_IDirectMusicObject
))
57 *ret_iface
= &This
->dmobj
.IDirectMusicObject_iface
;
58 else if (IsEqualIID (riid
, &IID_IPersistStream
))
59 *ret_iface
= &This
->dmobj
.IPersistStream_iface
;
61 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ret_iface
);
65 IUnknown_AddRef((IUnknown
*)*ret_iface
);
69 static ULONG WINAPI
IDirectMusicSegment8Impl_AddRef(IDirectMusicSegment8
*iface
)
71 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
72 LONG ref
= InterlockedIncrement(&This
->ref
);
74 TRACE("(%p) ref=%d\n", This
, ref
);
79 static ULONG WINAPI
IDirectMusicSegment8Impl_Release(IDirectMusicSegment8
*iface
)
81 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
82 LONG ref
= InterlockedDecrement(&This
->ref
);
84 TRACE("(%p) ref=%d\n", This
, ref
);
87 HeapFree(GetProcessHeap(), 0, This
);
94 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetLength(IDirectMusicSegment8
*iface
,
95 MUSIC_TIME
*pmtLength
)
97 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
99 TRACE("(%p, %p)\n", This
, pmtLength
);
100 if (NULL
== pmtLength
) {
103 *pmtLength
= This
->header
.mtLength
;
107 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetLength(IDirectMusicSegment8
*iface
,
110 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
112 TRACE("(%p, %d)\n", This
, mtLength
);
113 This
->header
.mtLength
= mtLength
;
117 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetRepeats(IDirectMusicSegment8
*iface
,
120 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
122 TRACE("(%p, %p)\n", This
, pdwRepeats
);
123 if (NULL
== pdwRepeats
) {
126 *pdwRepeats
= This
->header
.dwRepeats
;
130 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetRepeats(IDirectMusicSegment8
*iface
,
133 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
135 TRACE("(%p, %d)\n", This
, dwRepeats
);
136 This
->header
.dwRepeats
= dwRepeats
;
140 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetDefaultResolution(IDirectMusicSegment8
*iface
,
141 DWORD
*pdwResolution
)
143 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
145 TRACE("(%p, %p)\n", This
, pdwResolution
);
146 if (NULL
== pdwResolution
) {
149 *pdwResolution
= This
->header
.dwResolution
;
153 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetDefaultResolution(IDirectMusicSegment8
*iface
,
156 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
158 TRACE("(%p, %d)\n", This
, dwResolution
);
159 This
->header
.dwResolution
= dwResolution
;
163 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetTrack(IDirectMusicSegment8
*iface
,
164 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, IDirectMusicTrack
**ppTrack
)
166 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
168 struct list
* pEntry
= NULL
;
169 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
170 IPersistStream
* pCLSIDStream
= NULL
;
173 TRACE("(%p, %s, %d, 0x%x, %p)\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, ppTrack
);
175 if (NULL
== ppTrack
) {
179 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
180 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
181 TRACE(" - %p -> 0x%x,%p\n", pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
182 if (0xFFFFFFFF != dwGroupBits
&& 0 == (pIt
->dwGroupBits
& dwGroupBits
)) continue ;
183 if (FALSE
== IsEqualGUID(&GUID_NULL
, rguidType
)) {
185 * it rguidType is not null we must check if CLSIDs are equal
186 * and the unique way to get it is using IPersistStream Interface
188 hr
= IDirectMusicTrack_QueryInterface(pIt
->pTrack
, &IID_IPersistStream
, (void**) &pCLSIDStream
);
190 ERR("(%p): object %p don't implement IPersistStream Interface. Expect a crash (critical problem)\n", This
, pIt
->pTrack
);
193 hr
= IPersistStream_GetClassID(pCLSIDStream
, &pIt_clsid
);
194 IPersistStream_Release(pCLSIDStream
); pCLSIDStream
= NULL
;
196 ERR("(%p): non-implemented GetClassID for object %p\n", This
, pIt
->pTrack
);
199 TRACE(" - %p -> %s\n", pIt
, debugstr_dmguid(&pIt_clsid
));
200 if (FALSE
== IsEqualGUID(&pIt_clsid
, rguidType
)) continue ;
203 *ppTrack
= pIt
->pTrack
;
204 IDirectMusicTrack_AddRef(*ppTrack
);
209 return DMUS_E_NOT_FOUND
;
212 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetTrackGroup(IDirectMusicSegment8
*iface
,
213 IDirectMusicTrack
*pTrack
, DWORD
*pdwGroupBits
)
215 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
216 struct list
* pEntry
= NULL
;
217 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
219 TRACE("(%p, %p, %p)\n", This
, pTrack
, pdwGroupBits
);
221 if (NULL
== pdwGroupBits
) {
225 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
226 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
227 TRACE(" - %p -> %d,%p\n", pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
228 if (NULL
!= pIt
&& pIt
->pTrack
== pTrack
) {
229 *pdwGroupBits
= pIt
->dwGroupBits
;
234 return DMUS_E_NOT_FOUND
;
237 static HRESULT WINAPI
IDirectMusicSegment8Impl_InsertTrack(IDirectMusicSegment8
*iface
,
238 IDirectMusicTrack
*pTrack
, DWORD dwGroupBits
)
240 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
242 struct list
* pEntry
= NULL
;
243 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
244 LPDMUS_PRIVATE_SEGMENT_TRACK pNewSegTrack
= NULL
;
246 TRACE("(%p, %p, %d)\n", This
, pTrack
, dwGroupBits
);
248 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
250 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
251 TRACE(" - #%u: %p -> %d,%p\n", i
, pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
252 if (NULL
!= pIt
&& pIt
->pTrack
== pTrack
) {
253 ERR("(%p, %p): track is already in list\n", This
, pTrack
);
258 pNewSegTrack
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, sizeof(DMUS_PRIVATE_SEGMENT_TRACK
));
259 if (NULL
== pNewSegTrack
)
260 return E_OUTOFMEMORY
;
262 pNewSegTrack
->dwGroupBits
= dwGroupBits
;
263 pNewSegTrack
->pTrack
= pTrack
;
264 IDirectMusicTrack_Init(pTrack
, (IDirectMusicSegment
*)iface
);
265 IDirectMusicTrack_AddRef(pTrack
);
266 list_add_tail (&This
->Tracks
, &pNewSegTrack
->entry
);
271 static HRESULT WINAPI
IDirectMusicSegment8Impl_RemoveTrack(IDirectMusicSegment8
*iface
,
272 IDirectMusicTrack
*pTrack
)
274 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
275 struct list
* pEntry
= NULL
;
276 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
278 TRACE("(%p, %p)\n", This
, pTrack
);
280 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
281 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
282 if (pIt
->pTrack
== pTrack
) {
283 TRACE("(%p, %p): track in list\n", This
, pTrack
);
285 list_remove(&pIt
->entry
);
286 IDirectMusicTrack_Init(pIt
->pTrack
, NULL
);
287 IDirectMusicTrack_Release(pIt
->pTrack
);
288 HeapFree(GetProcessHeap(), 0, pIt
);
297 static HRESULT WINAPI
IDirectMusicSegment8Impl_InitPlay(IDirectMusicSegment8
*iface
,
298 IDirectMusicSegmentState
**ppSegState
, IDirectMusicPerformance
*pPerformance
, DWORD dwFlags
)
300 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
303 FIXME("(%p, %p, %p, %d): semi-stub\n", This
, ppSegState
, pPerformance
, dwFlags
);
304 if (NULL
== ppSegState
) {
307 hr
= create_dmsegmentstate(&IID_IDirectMusicSegmentState
,(void**) ppSegState
);
311 /* TODO: DMUS_SEGF_FLAGS */
315 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetGraph(IDirectMusicSegment8
*iface
,
316 IDirectMusicGraph
**ppGraph
)
318 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
320 FIXME("(%p, %p): semi-stub\n", This
, ppGraph
);
321 if (NULL
== ppGraph
) {
324 if (NULL
== This
->pGraph
) {
325 return DMUS_E_NOT_FOUND
;
328 * should return This, as seen in msdn
329 * "...The segment object implements IDirectMusicGraph directly..."
331 *ppGraph
= This
->pGraph
;
332 IDirectMusicGraph_AddRef(This
->pGraph
);
336 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetGraph(IDirectMusicSegment8
*iface
,
337 IDirectMusicGraph
*pGraph
)
339 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
341 FIXME("(%p, %p): to complete\n", This
, pGraph
);
342 if (NULL
!= This
->pGraph
) {
343 IDirectMusicGraph_Release(This
->pGraph
);
345 This
->pGraph
= pGraph
;
346 if (NULL
!= This
->pGraph
) {
347 IDirectMusicGraph_AddRef(This
->pGraph
);
352 static HRESULT WINAPI
IDirectMusicSegment8Impl_AddNotificationType(IDirectMusicSegment8
*iface
,
353 REFGUID rguidNotificationType
)
355 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
356 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidNotificationType
));
360 static HRESULT WINAPI
IDirectMusicSegment8Impl_RemoveNotificationType(IDirectMusicSegment8
*iface
,
361 REFGUID rguidNotificationType
)
363 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
364 FIXME("(%p, %s): stub\n", This
, debugstr_dmguid(rguidNotificationType
));
368 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetParam(IDirectMusicSegment8
*iface
,
369 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
, MUSIC_TIME
*pmtNext
,
372 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
374 struct list
* pEntry
= NULL
;
375 IDirectMusicTrack
* pTrack
= NULL
;
376 IPersistStream
* pCLSIDStream
= NULL
;
377 LPDMUS_PRIVATE_SEGMENT_TRACK pIt
= NULL
;
380 FIXME("(%p, %s, 0x%x, %d, %d, %p, %p)\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pmtNext
, pParam
);
382 if (DMUS_SEG_ANYTRACK
== dwIndex
) {
384 LIST_FOR_EACH (pEntry
, &This
->Tracks
) {
385 pIt
= LIST_ENTRY(pEntry
, DMUS_PRIVATE_SEGMENT_TRACK
, entry
);
387 hr
= IDirectMusicTrack_QueryInterface(pIt
->pTrack
, &IID_IPersistStream
, (void**) &pCLSIDStream
);
389 ERR("(%p): object %p don't implement IPersistStream Interface. Expect a crash (critical problem)\n", This
, pIt
->pTrack
);
393 TRACE(" - %p -> 0x%x,%p\n", pIt
, pIt
->dwGroupBits
, pIt
->pTrack
);
395 if (0xFFFFFFFF != dwGroupBits
&& 0 == (pIt
->dwGroupBits
& dwGroupBits
)) continue ;
396 hr
= IPersistStream_GetClassID(pCLSIDStream
, &pIt_clsid
);
397 IPersistStream_Release(pCLSIDStream
); pCLSIDStream
= NULL
;
399 ERR("(%p): non-implemented GetClassID for object %p\n", This
, pIt
->pTrack
);
402 if (FALSE
== IsEqualGUID(&pIt_clsid
, rguidType
)) continue ;
403 if (FAILED(IDirectMusicTrack_IsParamSupported(pIt
->pTrack
, rguidType
))) continue ;
404 hr
= IDirectMusicTrack_GetParam(pIt
->pTrack
, rguidType
, mtTime
, pmtNext
, pParam
);
405 if (SUCCEEDED(hr
)) return hr
;
407 ERR("(%p): not found\n", This
);
408 return DMUS_E_TRACK_NOT_FOUND
;
411 hr
= IDirectMusicSegment8Impl_GetTrack(iface
, &GUID_NULL
, dwGroupBits
, dwIndex
, &pTrack
);
413 ERR("(%p): not found\n", This
);
414 return DMUS_E_TRACK_NOT_FOUND
;
417 hr
= IDirectMusicTrack_GetParam(pTrack
, rguidType
, mtTime
, pmtNext
, pParam
);
418 IDirectMusicTrack_Release(pTrack
); pTrack
= NULL
;
423 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetParam(IDirectMusicSegment8
*iface
,
424 REFGUID rguidType
, DWORD dwGroupBits
, DWORD dwIndex
, MUSIC_TIME mtTime
, void *pParam
)
426 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
427 FIXME("(%p, %s, %d, %d, %d, %p): stub\n", This
, debugstr_dmguid(rguidType
), dwGroupBits
, dwIndex
, mtTime
, pParam
);
431 static HRESULT WINAPI
IDirectMusicSegment8Impl_Clone(IDirectMusicSegment8
*iface
,
432 MUSIC_TIME mtStart
, MUSIC_TIME mtEnd
, IDirectMusicSegment
**ppSegment
)
434 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
435 FIXME("(%p, %d, %d, %p): stub\n", This
, mtStart
, mtEnd
, ppSegment
);
439 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetStartPoint(IDirectMusicSegment8
*iface
,
442 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
444 TRACE("(%p, %d)\n", This
, mtStart
);
445 if (mtStart
>= This
->header
.mtLength
) {
446 return DMUS_E_OUT_OF_RANGE
;
448 This
->header
.mtPlayStart
= mtStart
;
452 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetStartPoint(IDirectMusicSegment8
*iface
,
453 MUSIC_TIME
*pmtStart
)
455 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
457 TRACE("(%p, %p)\n", This
, pmtStart
);
458 if (NULL
== pmtStart
) {
461 *pmtStart
= This
->header
.mtPlayStart
;
465 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetLoopPoints(IDirectMusicSegment8
*iface
,
466 MUSIC_TIME mtStart
, MUSIC_TIME mtEnd
)
468 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
470 TRACE("(%p, %d, %d)\n", This
, mtStart
, mtEnd
);
471 if (mtStart
>= This
->header
.mtLength
|| mtEnd
> This
->header
.mtLength
|| mtStart
> mtEnd
) {
472 return DMUS_E_OUT_OF_RANGE
;
474 This
->header
.mtLoopStart
= mtStart
;
475 This
->header
.mtLoopEnd
= mtEnd
;
479 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetLoopPoints(IDirectMusicSegment8
*iface
,
480 MUSIC_TIME
*pmtStart
, MUSIC_TIME
*pmtEnd
)
482 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
484 TRACE("(%p, %p, %p)\n", This
, pmtStart
, pmtEnd
);
485 if (NULL
== pmtStart
|| NULL
== pmtEnd
) {
488 *pmtStart
= This
->header
.mtLoopStart
;
489 *pmtEnd
= This
->header
.mtLoopEnd
;
493 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetPChannelsUsed(IDirectMusicSegment8
*iface
,
494 DWORD dwNumPChannels
, DWORD
*paPChannels
)
496 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
497 FIXME("(%p, %d, %p): stub\n", This
, dwNumPChannels
, paPChannels
);
501 static HRESULT WINAPI
IDirectMusicSegment8Impl_SetTrackConfig(IDirectMusicSegment8
*iface
,
502 REFGUID rguidTrackClassID
, DWORD dwGroupBits
, DWORD dwIndex
, DWORD dwFlagsOn
,
505 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
506 FIXME("(%p, %s, %d, %d, %d, %d): stub\n", This
, debugstr_dmguid(rguidTrackClassID
), dwGroupBits
, dwIndex
, dwFlagsOn
, dwFlagsOff
);
510 static HRESULT WINAPI
IDirectMusicSegment8Impl_GetAudioPathConfig(IDirectMusicSegment8
*iface
,
511 IUnknown
**ppAudioPathConfig
)
513 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
514 FIXME("(%p, %p): stub\n", This
, ppAudioPathConfig
);
518 static HRESULT WINAPI
IDirectMusicSegment8Impl_Compose(IDirectMusicSegment8
*iface
,
519 MUSIC_TIME mtTime
, IDirectMusicSegment
*pFromSegment
, IDirectMusicSegment
*pToSegment
,
520 IDirectMusicSegment
**ppComposedSegment
)
522 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
523 FIXME("(%p, %d, %p, %p, %p): stub\n", This
, mtTime
, pFromSegment
, pToSegment
, ppComposedSegment
);
527 static HRESULT WINAPI
IDirectMusicSegment8Impl_Download(IDirectMusicSegment8
*iface
,
528 IUnknown
*pAudioPath
)
530 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
531 FIXME("(%p, %p): stub\n", This
, pAudioPath
);
535 static HRESULT WINAPI
IDirectMusicSegment8Impl_Unload(IDirectMusicSegment8
*iface
,
536 IUnknown
*pAudioPath
)
538 IDirectMusicSegment8Impl
*This
= impl_from_IDirectMusicSegment8(iface
);
539 FIXME("(%p, %p): stub\n", This
, pAudioPath
);
543 static const IDirectMusicSegment8Vtbl dmsegment8_vtbl
= {
544 IDirectMusicSegment8Impl_QueryInterface
,
545 IDirectMusicSegment8Impl_AddRef
,
546 IDirectMusicSegment8Impl_Release
,
547 IDirectMusicSegment8Impl_GetLength
,
548 IDirectMusicSegment8Impl_SetLength
,
549 IDirectMusicSegment8Impl_GetRepeats
,
550 IDirectMusicSegment8Impl_SetRepeats
,
551 IDirectMusicSegment8Impl_GetDefaultResolution
,
552 IDirectMusicSegment8Impl_SetDefaultResolution
,
553 IDirectMusicSegment8Impl_GetTrack
,
554 IDirectMusicSegment8Impl_GetTrackGroup
,
555 IDirectMusicSegment8Impl_InsertTrack
,
556 IDirectMusicSegment8Impl_RemoveTrack
,
557 IDirectMusicSegment8Impl_InitPlay
,
558 IDirectMusicSegment8Impl_GetGraph
,
559 IDirectMusicSegment8Impl_SetGraph
,
560 IDirectMusicSegment8Impl_AddNotificationType
,
561 IDirectMusicSegment8Impl_RemoveNotificationType
,
562 IDirectMusicSegment8Impl_GetParam
,
563 IDirectMusicSegment8Impl_SetParam
,
564 IDirectMusicSegment8Impl_Clone
,
565 IDirectMusicSegment8Impl_SetStartPoint
,
566 IDirectMusicSegment8Impl_GetStartPoint
,
567 IDirectMusicSegment8Impl_SetLoopPoints
,
568 IDirectMusicSegment8Impl_GetLoopPoints
,
569 IDirectMusicSegment8Impl_SetPChannelsUsed
,
570 IDirectMusicSegment8Impl_SetTrackConfig
,
571 IDirectMusicSegment8Impl_GetAudioPathConfig
,
572 IDirectMusicSegment8Impl_Compose
,
573 IDirectMusicSegment8Impl_Download
,
574 IDirectMusicSegment8Impl_Unload
577 /* IDirectMusicSegment8Impl IDirectMusicObject part: */
578 static HRESULT WINAPI
seg_IDirectMusicObject_ParseDescriptor(IDirectMusicObject
*iface
,
579 IStream
*stream
, DMUS_OBJECTDESC
*desc
)
581 struct chunk_entry riff
= {0};
582 DWORD supported
= DMUS_OBJ_OBJECT
| DMUS_OBJ_VERSION
;
585 TRACE("(%p, %p, %p)\n", iface
, stream
, desc
);
587 if (!stream
|| !desc
)
590 if ((hr
= stream_get_chunk(stream
, &riff
)) != S_OK
)
592 if (riff
.id
!= FOURCC_RIFF
|| !(riff
.type
== DMUS_FOURCC_SEGMENT_FORM
||
593 riff
.type
== mmioFOURCC('W','A','V','E'))) {
594 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff
));
595 stream_skip_chunk(stream
, &riff
);
599 if (riff
.type
== DMUS_FOURCC_SEGMENT_FORM
)
600 supported
|= DMUS_OBJ_NAME
| DMUS_OBJ_CATEGORY
;
602 supported
|= DMUS_OBJ_NAME_INFO
;
603 hr
= dmobj_parsedescriptor(stream
, &riff
, desc
, supported
);
607 desc
->guidClass
= CLSID_DirectMusicSegment
;
608 desc
->dwValidData
|= DMUS_OBJ_CLASS
;
610 TRACE("returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (desc
));
614 static const IDirectMusicObjectVtbl dmobject_vtbl
= {
615 dmobj_IDirectMusicObject_QueryInterface
,
616 dmobj_IDirectMusicObject_AddRef
,
617 dmobj_IDirectMusicObject_Release
,
618 dmobj_IDirectMusicObject_GetDescriptor
,
619 dmobj_IDirectMusicObject_SetDescriptor
,
620 seg_IDirectMusicObject_ParseDescriptor
623 /* IDirectMusicSegment8Impl IPersistStream part: */
624 static HRESULT
parse_track_form(IDirectMusicSegment8Impl
*This
, IStream
*stream
,
625 const struct chunk_entry
*riff
)
627 struct chunk_entry chunk
= {.parent
= riff
};
628 IDirectMusicTrack
*track
= NULL
;
629 IPersistStream
*ps
= NULL
;
631 DMUS_IO_TRACK_HEADER thdr
;
634 TRACE("Parsing track form in %p: %s\n", stream
, debugstr_chunk(riff
));
636 /* First chunk must be the track header */
637 if (FAILED(hr
= stream_get_chunk(stream
, &chunk
)))
639 if (chunk
.id
!= DMUS_FOURCC_TRACK_CHUNK
)
640 return DMUS_E_TRACK_HDR_NOT_FIRST_CK
;
641 if (FAILED(hr
= stream_chunk_get_data(stream
, &chunk
, &thdr
, sizeof(thdr
))))
643 TRACE("Found DMUS_IO_TRACK_HEADER\n");
644 TRACE("\tclass: %s\n", debugstr_guid (&thdr
.guidClassID
));
645 TRACE("\tdwGroup: %d\n", thdr
.dwGroup
);
646 TRACE("\tckid: %s\n", debugstr_fourcc (thdr
.ckid
));
647 TRACE("\tfccType: %s\n", debugstr_fourcc (thdr
.fccType
));
649 if (!!thdr
.ckid
== !!thdr
.fccType
) {
650 WARN("One and only one of the ckid (%s) and fccType (%s) need to be set\n",
651 debugstr_fourcc(thdr
.ckid
), debugstr_fourcc(thdr
.fccType
));
652 return DMUS_E_INVALID_TRACK_HDR
;
655 /* Optional chunks */
656 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
) {
657 if ((thdr
.ckid
&& chunk
.id
== thdr
.ckid
) ||
658 (!thdr
.ckid
&& (chunk
.id
== FOURCC_LIST
|| chunk
.id
== FOURCC_RIFF
) &&
659 chunk
.type
== thdr
.fccType
))
662 if (chunk
.id
== DMUS_FOURCC_TRACK_EXTRAS_CHUNK
)
663 FIXME("DMUS_IO_TRACK_EXTRAS_HEADER chunk not handled\n");
666 return hr
== S_FALSE
? DMUS_E_TRACK_NOT_FOUND
: hr
;
668 /* Some DirectMusicTrack implementation expect the stream to start with their data chunk */
669 if (FAILED(hr
= IStream_Clone(stream
, &clone
)))
671 stream_reset_chunk_start(clone
, &chunk
);
674 hr
= CoCreateInstance(&thdr
.guidClassID
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IDirectMusicTrack
,
678 hr
= IDirectMusicTrack_QueryInterface(track
, &IID_IPersistStream
, (void **)&ps
);
681 hr
= IPersistStream_Load(ps
, clone
);
685 hr
= IDirectMusicSegment8_InsertTrack(&This
->IDirectMusicSegment8_iface
, track
, thdr
.dwGroup
);
689 IPersistStream_Release(ps
);
691 IDirectMusicTrack_Release(track
);
692 IStream_Release(clone
);
697 static HRESULT
parse_track_list(IDirectMusicSegment8Impl
*This
, IStream
*stream
,
698 const struct chunk_entry
*trkl
)
700 struct chunk_entry chunk
= {.parent
= trkl
};
703 TRACE("Parsing track list in %p: %s\n", stream
, debugstr_chunk(trkl
));
705 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
706 if (chunk
.id
== FOURCC_RIFF
&& chunk
.type
== DMUS_FOURCC_TRACK_FORM
)
707 hr
= parse_track_form(This
, stream
, &chunk
);
709 return SUCCEEDED(hr
) ? S_OK
: hr
;
712 static inline void dump_segment_header(DMUS_IO_SEGMENT_HEADER
*h
, DWORD size
)
716 if (size
== offsetof(DMUS_IO_SEGMENT_HEADER
, rtLength
))
718 else if (size
== offsetof(DMUS_IO_SEGMENT_HEADER
, rtLoopStart
))
720 TRACE("Found DirectX%d DMUS_IO_SEGMENT_HEADER\n", dx
);
721 TRACE("\tdwRepeats: %u\n", h
->dwRepeats
);
722 TRACE("\tmtLength: %u\n", h
->mtLength
);
723 TRACE("\tmtPlayStart: %u\n", h
->mtPlayStart
);
724 TRACE("\tmtLoopStart: %u\n", h
->mtLoopStart
);
725 TRACE("\tmtLoopEnd: %u\n", h
->mtLoopEnd
);
726 TRACE("\tdwResolution: %u\n", h
->dwResolution
);
728 TRACE("\trtLength: %s\n", wine_dbgstr_longlong(h
->rtLength
));
729 TRACE("\tdwFlags: %u\n", h
->dwFlags
);
730 TRACE("\tdwReserved: %u\n", h
->dwReserved
);
733 TRACE("\trtLoopStart: %s\n", wine_dbgstr_longlong(h
->rtLoopStart
));
734 TRACE("\trtLoopEnd: %s\n", wine_dbgstr_longlong(h
->rtLoopEnd
));
735 TRACE("\trtPlayStart: %s\n", wine_dbgstr_longlong(h
->rtPlayStart
));
739 static HRESULT
parse_segment_form(IDirectMusicSegment8Impl
*This
, IStream
*stream
,
740 const struct chunk_entry
*riff
)
742 struct chunk_entry chunk
= {.parent
= riff
};
745 TRACE("Parsing segment form in %p: %s\n", stream
, debugstr_chunk(riff
));
747 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
) {
749 case DMUS_FOURCC_SEGMENT_CHUNK
:
750 /* DX7, DX8 and DX9 structure sizes */
751 if (chunk
.size
!= offsetof(DMUS_IO_SEGMENT_HEADER
, rtLength
) &&
752 chunk
.size
!= offsetof(DMUS_IO_SEGMENT_HEADER
, rtLoopStart
) &&
753 chunk
.size
!= sizeof(DMUS_IO_SEGMENT_HEADER
)) {
754 WARN("Invalid size of %s\n", debugstr_chunk(&chunk
));
757 if (FAILED(hr
= stream_chunk_get_data(stream
, &chunk
, &This
->header
, chunk
.size
))) {
758 WARN("Failed to read data of %s\n", debugstr_chunk(&chunk
));
761 dump_segment_header(&This
->header
, chunk
.size
);
764 if (chunk
.type
== DMUS_FOURCC_TRACK_LIST
)
765 if (FAILED(hr
= parse_track_list(This
, stream
, &chunk
)))
769 FIXME("Loading of embedded RIFF form %s\n", debugstr_fourcc(chunk
.type
));
774 return SUCCEEDED(hr
) ? S_OK
: hr
;
777 static inline IDirectMusicSegment8Impl
*impl_from_IPersistStream(IPersistStream
*iface
)
779 return CONTAINING_RECORD(iface
, IDirectMusicSegment8Impl
, dmobj
.IPersistStream_iface
);
782 static HRESULT WINAPI
seg_IPersistStream_Load(IPersistStream
*iface
, IStream
*stream
)
784 IDirectMusicSegment8Impl
*This
= impl_from_IPersistStream(iface
);
785 struct chunk_entry riff
= {0};
788 TRACE("(%p, %p): Loading\n", This
, stream
);
793 if (stream_get_chunk(stream
, &riff
) != S_OK
||
794 (riff
.id
!= FOURCC_RIFF
&& riff
.id
!= mmioFOURCC('M','T','h','d')))
795 return DMUS_E_UNSUPPORTED_STREAM
;
796 stream_reset_chunk_start(stream
, &riff
);
798 if (riff
.id
== mmioFOURCC('M','T','h','d')) {
799 FIXME("MIDI file loading not supported\n");
803 hr
= IDirectMusicObject_ParseDescriptor(&This
->dmobj
.IDirectMusicObject_iface
, stream
,
807 stream_reset_chunk_data(stream
, &riff
);
809 if (riff
.type
== DMUS_FOURCC_SEGMENT_FORM
)
810 hr
= parse_segment_form(This
, stream
, &riff
);
812 FIXME("WAVE form loading not implemented\n");
819 static const IPersistStreamVtbl persiststream_vtbl
= {
820 dmobj_IPersistStream_QueryInterface
,
821 dmobj_IPersistStream_AddRef
,
822 dmobj_IPersistStream_Release
,
823 dmobj_IPersistStream_GetClassID
,
824 unimpl_IPersistStream_IsDirty
,
825 seg_IPersistStream_Load
,
826 unimpl_IPersistStream_Save
,
827 unimpl_IPersistStream_GetSizeMax
830 /* for ClassFactory */
831 HRESULT WINAPI
create_dmsegment(REFIID lpcGUID
, void **ppobj
)
833 IDirectMusicSegment8Impl
* obj
;
836 obj
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicSegment8Impl
));
839 return E_OUTOFMEMORY
;
841 obj
->IDirectMusicSegment8_iface
.lpVtbl
= &dmsegment8_vtbl
;
843 dmobject_init(&obj
->dmobj
, &CLSID_DirectMusicSegment
,
844 (IUnknown
*)&obj
->IDirectMusicSegment8_iface
);
845 obj
->dmobj
.IDirectMusicObject_iface
.lpVtbl
= &dmobject_vtbl
;
846 obj
->dmobj
.IPersistStream_iface
.lpVtbl
= &persiststream_vtbl
;
847 list_init (&obj
->Tracks
);
850 hr
= IDirectMusicSegment8_QueryInterface(&obj
->IDirectMusicSegment8_iface
, lpcGUID
, ppobj
);
851 IDirectMusicSegment8_Release(&obj
->IDirectMusicSegment8_iface
);