2 * Copyright (C) 2003-2004 Rok Mandeljc
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "dmime_private.h"
20 #include "dmusic_wave.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(dmime
);
26 DMUS_IO_WAVE_ITEM_HEADER header
;
27 IDirectMusicObject
*object
;
28 IDirectSoundBuffer
*buffer
;
33 DMUS_IO_WAVE_PART_HEADER header
;
39 IDirectMusicTrack8 IDirectMusicTrack8_iface
;
40 struct dmobject dmobj
; /* IPersistStream only */
42 DMUS_IO_WAVE_TRACK_HEADER header
;
46 /* struct wave_track IDirectMusicTrack8 part: */
47 static inline struct wave_track
*impl_from_IDirectMusicTrack8(IDirectMusicTrack8
*iface
)
49 return CONTAINING_RECORD(iface
, struct wave_track
, IDirectMusicTrack8_iface
);
52 static inline struct wave_track
*impl_from_IPersistStream(IPersistStream
*iface
)
54 return CONTAINING_RECORD(iface
, struct wave_track
, dmobj
.IPersistStream_iface
);
57 static HRESULT WINAPI
wave_track_QueryInterface(IDirectMusicTrack8
*iface
, REFIID riid
,
60 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
62 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ret_iface
);
66 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDirectMusicTrack
) ||
67 IsEqualIID(riid
, &IID_IDirectMusicTrack8
))
69 else if (IsEqualIID(riid
, &IID_IPersistStream
))
70 *ret_iface
= &This
->dmobj
.IPersistStream_iface
;
72 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ret_iface
);
76 IUnknown_AddRef((IUnknown
*)*ret_iface
);
80 static ULONG WINAPI
wave_track_AddRef(IDirectMusicTrack8
*iface
)
82 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
83 LONG ref
= InterlockedIncrement(&This
->ref
);
85 TRACE("(%p) ref=%ld\n", This
, ref
);
90 static ULONG WINAPI
wave_track_Release(IDirectMusicTrack8
*iface
)
92 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
93 LONG ref
= InterlockedDecrement(&This
->ref
);
95 TRACE("(%p) ref=%ld\n", This
, ref
);
98 struct wave_item
*item
, *item2
;
99 struct wave_part
*part
, *part2
;
101 LIST_FOR_EACH_ENTRY_SAFE(part
, part2
, &This
->parts
, struct wave_part
, entry
)
103 list_remove(&part
->entry
);
105 LIST_FOR_EACH_ENTRY_SAFE(item
, item2
, &part
->items
, struct wave_item
, entry
)
107 list_remove(&item
->entry
);
108 if (item
->buffer
) IDirectSoundBuffer_Release(item
->buffer
);
109 if (item
->object
) IDirectMusicObject_Release(item
->object
);
122 static HRESULT WINAPI
wave_track_Init(IDirectMusicTrack8
*iface
, IDirectMusicSegment
*pSegment
)
124 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
125 FIXME("(%p, %p): stub\n", This
, pSegment
);
129 static HRESULT WINAPI
wave_track_InitPlay(IDirectMusicTrack8
*iface
,
130 IDirectMusicSegmentState
*pSegmentState
, IDirectMusicPerformance
*pPerformance
,
131 void **ppStateData
, DWORD dwVirtualTrack8ID
, DWORD dwFlags
)
133 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
134 FIXME("(%p, %p, %p, %p, %ld, %ld): stub\n", This
, pSegmentState
, pPerformance
, ppStateData
,
135 dwVirtualTrack8ID
, dwFlags
);
139 static HRESULT WINAPI
wave_track_EndPlay(IDirectMusicTrack8
*iface
, void *pStateData
)
141 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
142 FIXME("(%p, %p): stub\n", This
, pStateData
);
146 static HRESULT WINAPI
wave_track_Play(IDirectMusicTrack8
*iface
, void *state_data
,
147 MUSIC_TIME start_time
, MUSIC_TIME end_time
, MUSIC_TIME time_offset
, DWORD track_flags
,
148 IDirectMusicPerformance
*performance
, IDirectMusicSegmentState
*segment_state
, DWORD track_id
)
150 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
151 LONG volume
= This
->header
.lVolume
;
152 IDirectMusicGraph
*graph
;
153 struct wave_part
*part
;
154 struct wave_item
*item
;
157 TRACE("(%p, %p, %ld, %ld, %ld, %#lx, %p, %p, %ld)\n", This
, state_data
, start_time
, end_time
,
158 time_offset
, track_flags
, performance
, segment_state
, track_id
);
160 if (track_flags
) FIXME("track_flags %#lx not implemented\n", track_flags
);
161 if (segment_state
) FIXME("segment_state %p not implemented\n", segment_state
);
162 if (!(track_flags
& DMUS_TRACKF_START
)) return S_OK
;
164 if (FAILED(hr
= IDirectMusicPerformance_QueryInterface(performance
,
165 &IID_IDirectMusicGraph
, (void **)&graph
)))
168 LIST_FOR_EACH_ENTRY(part
, &This
->parts
, struct wave_part
, entry
)
170 volume
+= part
->header
.lVolume
;
172 LIST_FOR_EACH_ENTRY(item
, &part
->items
, struct wave_item
, entry
)
176 if (!item
->buffer
) continue;
177 if (item
->header
.rtTime
< start_time
) continue;
178 if (item
->header
.rtTime
>= end_time
) continue;
180 if (FAILED(hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(*msg
),
181 (DMUS_PMSG
**)&msg
)))
184 msg
->mtTime
= item
->header
.rtTime
+ time_offset
;
185 msg
->dwFlags
= DMUS_PMSGF_MUSICTIME
;
186 msg
->dwPChannel
= part
->header
.dwPChannel
;
187 msg
->dwVirtualTrackID
= track_id
;
188 msg
->dwType
= DMUS_PMSGT_WAVE
;
189 msg
->punkUser
= (IUnknown
*)item
->buffer
;
190 IDirectSoundBuffer_AddRef(item
->buffer
);
192 msg
->rtStartOffset
= item
->header
.rtStartOffset
;
193 msg
->rtDuration
= item
->header
.rtDuration
;
194 msg
->lVolume
= volume
+ item
->header
.lVolume
;
195 msg
->lPitch
= item
->header
.lPitch
;
197 if (FAILED(hr
= IDirectMusicGraph_StampPMsg(graph
, (DMUS_PMSG
*)msg
))
198 || FAILED(hr
= IDirectMusicPerformance_SendPMsg(performance
, (DMUS_PMSG
*)msg
)))
200 IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)msg
);
205 volume
-= part
->header
.lVolume
;
208 IDirectMusicGraph_Release(graph
);
212 static HRESULT WINAPI
wave_track_GetParam(IDirectMusicTrack8
*iface
, REFGUID type
, MUSIC_TIME time
,
213 MUSIC_TIME
*next
, void *param
)
215 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
217 TRACE("(%p, %s, %ld, %p, %p): not supported\n", This
, debugstr_dmguid(type
), time
, next
, param
);
218 return DMUS_E_GET_UNSUPPORTED
;
221 static HRESULT WINAPI
wave_track_SetParam(IDirectMusicTrack8
*iface
, REFGUID type
, MUSIC_TIME time
,
224 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
226 TRACE("(%p, %s, %ld, %p)\n", This
, debugstr_dmguid(type
), time
, param
);
228 if (IsEqualGUID(type
, &GUID_Disable_Auto_Download
)) {
229 FIXME("GUID_Disable_Auto_Download not handled yet\n");
232 if (IsEqualGUID(type
, &GUID_Download
)) {
233 FIXME("GUID_Download not handled yet\n");
236 if (IsEqualGUID(type
, &GUID_DownloadToAudioPath
))
238 IDirectMusicPerformance8
*performance
;
239 IDirectMusicAudioPath
*audio_path
;
240 IUnknown
*object
= param
;
241 struct wave_part
*part
;
242 struct wave_item
*item
;
243 IDirectSound
*dsound
;
246 if (FAILED(hr
= IDirectMusicAudioPath_QueryInterface(object
, &IID_IDirectMusicPerformance8
, (void **)&performance
))
247 && SUCCEEDED(hr
= IDirectMusicAudioPath_QueryInterface(object
, &IID_IDirectMusicAudioPath
, (void **)&audio_path
)))
249 hr
= IDirectMusicAudioPath_GetObjectInPath(audio_path
, DMUS_PCHANNEL_ALL
, DMUS_PATH_PERFORMANCE
, 0,
250 &GUID_All_Objects
, 0, &IID_IDirectMusicPerformance8
, (void **)&performance
);
251 IDirectMusicAudioPath_Release(audio_path
);
255 hr
= performance_get_dsound(performance
, &dsound
);
256 IDirectMusicPerformance_Release(performance
);
260 WARN("Failed to get direct sound from param %p, hr %#lx\n", param
, hr
);
264 LIST_FOR_EACH_ENTRY(part
, &This
->parts
, struct wave_part
, entry
)
266 LIST_FOR_EACH_ENTRY(item
, &part
->items
, struct wave_item
, entry
)
268 if (item
->buffer
) continue;
269 if (FAILED(hr
= wave_download_to_dsound(item
->object
, dsound
, &item
->buffer
)))
271 WARN("Failed to download wave %p to direct sound, hr %#lx\n", item
->object
, hr
);
279 if (IsEqualGUID(type
, &GUID_Enable_Auto_Download
)) {
280 FIXME("GUID_Enable_Auto_Download not handled yet\n");
283 if (IsEqualGUID(type
, &GUID_Unload
)) {
284 FIXME("GUID_Unload not handled yet\n");
287 if (IsEqualGUID(type
, &GUID_UnloadFromAudioPath
))
289 struct wave_part
*part
;
290 struct wave_item
*item
;
292 LIST_FOR_EACH_ENTRY(part
, &This
->parts
, struct wave_part
, entry
)
294 LIST_FOR_EACH_ENTRY(item
, &part
->items
, struct wave_item
, entry
)
296 if (!item
->buffer
) continue;
297 IDirectSoundBuffer_Release(item
->buffer
);
305 return DMUS_E_TYPE_UNSUPPORTED
;
308 static HRESULT WINAPI
wave_track_IsParamSupported(IDirectMusicTrack8
*iface
, REFGUID type
)
310 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
311 static const GUID
*valid
[] = {
312 &GUID_Disable_Auto_Download
,
314 &GUID_DownloadToAudioPath
,
315 &GUID_Enable_Auto_Download
,
317 &GUID_UnloadFromAudioPath
321 TRACE("(%p, %s)\n", This
, debugstr_dmguid(type
));
323 for (i
= 0; i
< ARRAY_SIZE(valid
); i
++)
324 if (IsEqualGUID(type
, valid
[i
]))
327 TRACE("param unsupported\n");
328 return DMUS_E_TYPE_UNSUPPORTED
;
331 static HRESULT WINAPI
wave_track_AddNotificationType(IDirectMusicTrack8
*iface
, REFGUID notiftype
)
333 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
335 TRACE("(%p, %s): method not implemented\n", This
, debugstr_dmguid(notiftype
));
339 static HRESULT WINAPI
wave_track_RemoveNotificationType(IDirectMusicTrack8
*iface
,
342 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
344 TRACE("(%p, %s): method not implemented\n", This
, debugstr_dmguid(notiftype
));
348 static HRESULT WINAPI
wave_track_Clone(IDirectMusicTrack8
*iface
, MUSIC_TIME mtStart
,
349 MUSIC_TIME mtEnd
, IDirectMusicTrack
**ppTrack
)
351 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
352 FIXME("(%p, %ld, %ld, %p): stub\n", This
, mtStart
, mtEnd
, ppTrack
);
356 static HRESULT WINAPI
wave_track_PlayEx(IDirectMusicTrack8
*iface
, void *pStateData
,
357 REFERENCE_TIME rtStart
, REFERENCE_TIME rtEnd
, REFERENCE_TIME rtOffset
, DWORD dwFlags
,
358 IDirectMusicPerformance
*pPerf
, IDirectMusicSegmentState
*pSegSt
, DWORD dwVirtualID
)
360 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
361 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %ld, %p, %p, %ld): stub\n", This
, pStateData
,
362 wine_dbgstr_longlong(rtStart
), wine_dbgstr_longlong(rtEnd
),
363 wine_dbgstr_longlong(rtOffset
), dwFlags
, pPerf
, pSegSt
, dwVirtualID
);
367 static HRESULT WINAPI
wave_track_GetParamEx(IDirectMusicTrack8
*iface
, REFGUID rguidType
,
368 REFERENCE_TIME rtTime
, REFERENCE_TIME
*prtNext
, void *pParam
, void *pStateData
,
371 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
372 FIXME("(%p, %s, 0x%s, %p, %p, %p, %ld): stub\n", This
, debugstr_dmguid(rguidType
),
373 wine_dbgstr_longlong(rtTime
), prtNext
, pParam
, pStateData
, dwFlags
);
377 static HRESULT WINAPI
wave_track_SetParamEx(IDirectMusicTrack8
*iface
, REFGUID rguidType
,
378 REFERENCE_TIME rtTime
, void *pParam
, void *pStateData
, DWORD dwFlags
)
380 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
381 FIXME("(%p, %s, 0x%s, %p, %p, %ld): stub\n", This
, debugstr_dmguid(rguidType
),
382 wine_dbgstr_longlong(rtTime
), pParam
, pStateData
, dwFlags
);
386 static HRESULT WINAPI
wave_track_Compose(IDirectMusicTrack8
*iface
, IUnknown
*context
,
387 DWORD trackgroup
, IDirectMusicTrack
**track
)
389 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
391 TRACE("(%p, %p, %ld, %p): method not implemented\n", This
, context
, trackgroup
, track
);
395 static HRESULT WINAPI
wave_track_Join(IDirectMusicTrack8
*iface
, IDirectMusicTrack
*newtrack
,
396 MUSIC_TIME join
, IUnknown
*context
, DWORD trackgroup
, IDirectMusicTrack
**resulttrack
)
398 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
399 TRACE("(%p, %p, %ld, %p, %ld, %p): method not implemented\n", This
, newtrack
, join
, context
,
400 trackgroup
, resulttrack
);
404 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl
= {
405 wave_track_QueryInterface
,
414 wave_track_IsParamSupported
,
415 wave_track_AddNotificationType
,
416 wave_track_RemoveNotificationType
,
419 wave_track_GetParamEx
,
420 wave_track_SetParamEx
,
425 static HRESULT
parse_wave_item(struct wave_part
*part
, IStream
*stream
, struct chunk_entry
*wavi
)
427 struct chunk_entry wave
= {.parent
= wavi
};
428 struct chunk_entry chunk
= {.parent
= &wave
};
429 struct wave_item
*item
;
432 /* Nested list with two chunks */
433 if (FAILED(hr
= stream_next_chunk(stream
, &wave
)))
435 if (wave
.id
!= FOURCC_LIST
|| wave
.type
!= DMUS_FOURCC_WAVE_LIST
)
436 return DMUS_E_UNSUPPORTED_STREAM
;
438 if (!(item
= calloc(1, sizeof(*item
)))) return E_OUTOFMEMORY
;
440 /* Wave item header chunk */
441 if (FAILED(hr
= stream_next_chunk(stream
, &chunk
)))
443 if (chunk
.id
!= DMUS_FOURCC_WAVEITEM_CHUNK
) {
444 hr
= DMUS_E_UNSUPPORTED_STREAM
;
448 if (FAILED(hr
= stream_chunk_get_data(stream
, &chunk
, &item
->header
, sizeof(item
->header
)))) {
449 WARN("Failed to read data of %s\n", debugstr_chunk(&chunk
));
453 TRACE("Found DMUS_IO_WAVE_ITEM_HEADER\n");
454 TRACE("\tlVolume %ld\n", item
->header
.lVolume
);
455 TRACE("\tdwVariations %ld\n", item
->header
.dwVariations
);
456 TRACE("\trtTime %s\n", wine_dbgstr_longlong(item
->header
.rtTime
));
457 TRACE("\trtStartOffset %s\n", wine_dbgstr_longlong(item
->header
.rtStartOffset
));
458 TRACE("\trtReserved %s\n", wine_dbgstr_longlong(item
->header
.rtReserved
));
459 TRACE("\trtDuration %s\n", wine_dbgstr_longlong(item
->header
.rtDuration
));
460 TRACE("\tdwLoopStart %ld\n", item
->header
.dwLoopStart
);
461 TRACE("\tdwLoopEnd %ld\n", item
->header
.dwLoopEnd
);
462 TRACE("\tdwFlags %#08lx\n", item
->header
.dwFlags
);
463 TRACE("\twVolumeRange %d\n", item
->header
.wVolumeRange
);
464 TRACE("\twPitchRange %d\n", item
->header
.wPitchRange
);
466 /* Second chunk is a reference list */
467 if (stream_next_chunk(stream
, &chunk
) != S_OK
|| chunk
.id
!= FOURCC_LIST
||
468 chunk
.type
!= DMUS_FOURCC_REF_LIST
) {
469 hr
= DMUS_E_UNSUPPORTED_STREAM
;
472 if (FAILED(hr
= dmobj_parsereference(stream
, &chunk
, &item
->object
)))
475 list_add_tail(&part
->items
, &item
->entry
);
484 static HRESULT
parse_wave_part(struct wave_track
*This
, IStream
*stream
, struct chunk_entry
*wavp
)
486 struct chunk_entry chunk
= {.parent
= wavp
};
487 struct wave_part
*part
;
490 /* Wave part header chunk */
491 if (FAILED(hr
= stream_next_chunk(stream
, &chunk
)))
493 if (chunk
.id
!= DMUS_FOURCC_WAVEPART_CHUNK
)
494 return DMUS_E_UNSUPPORTED_STREAM
;
496 if (!(part
= calloc(1, sizeof(*part
)))) return E_OUTOFMEMORY
;
497 list_init(&part
->items
);
499 if (FAILED(hr
= stream_chunk_get_data(stream
, &chunk
, &part
->header
, sizeof(part
->header
)))) {
500 WARN("Failed to read data of %s\n", debugstr_chunk(&chunk
));
504 TRACE("Found DMUS_IO_WAVE_PART_HEADER\n");
505 TRACE("\tlVolume %ld\n", part
->header
.lVolume
);
506 TRACE("\tdwVariations %ld\n", part
->header
.dwVariations
);
507 TRACE("\tdwPChannel %ld\n", part
->header
.dwPChannel
);
508 TRACE("\tdwLockToPart %ld\n", part
->header
.dwLockToPart
);
509 TRACE("\tdwFlags %#08lx\n", part
->header
.dwFlags
);
510 TRACE("\tdwIndex %ld\n", part
->header
.dwIndex
);
512 /* Array of wave items */
513 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
514 if (chunk
.id
== FOURCC_LIST
&& chunk
.type
== DMUS_FOURCC_WAVEITEM_LIST
)
515 if (FAILED(hr
= parse_wave_item(part
, stream
, &chunk
)))
521 list_add_tail(&This
->parts
, &part
->entry
);
530 static HRESULT WINAPI
wave_IPersistStream_Load(IPersistStream
*iface
, IStream
*stream
)
532 struct wave_track
*This
= impl_from_IPersistStream(iface
);
533 struct chunk_entry wavt
= {0};
534 struct chunk_entry chunk
= {.parent
= &wavt
};
537 TRACE("%p, %p\n", This
, stream
);
542 if ((hr
= stream_get_chunk(stream
, &wavt
) != S_OK
))
544 if (wavt
.id
!= FOURCC_LIST
|| wavt
.type
!= DMUS_FOURCC_WAVETRACK_LIST
)
545 return DMUS_E_UNSUPPORTED_STREAM
;
547 TRACE("Parsing segment form in %p: %s\n", stream
, debugstr_chunk(&wavt
));
549 /* Track header chunk */
550 if (FAILED(hr
= stream_next_chunk(stream
, &chunk
)))
552 if (chunk
.id
!= DMUS_FOURCC_WAVETRACK_CHUNK
)
553 return DMUS_E_UNSUPPORTED_STREAM
;
554 if (FAILED(hr
= stream_chunk_get_data(stream
, &chunk
, &This
->header
, sizeof(This
->header
))))
557 TRACE("Found DMUS_IO_WAVE_TRACK_HEADER\n");
558 TRACE("\tlVolume %ld\n", This
->header
.lVolume
);
559 TRACE("\tdwFlags %#08lx\n", This
->header
.dwFlags
);
561 /* Array of wave parts */
562 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
563 if (chunk
.id
== FOURCC_LIST
&& chunk
.type
== DMUS_FOURCC_WAVEPART_LIST
)
564 if (FAILED(hr
= parse_wave_part(This
, stream
, &chunk
)))
567 return SUCCEEDED(hr
) ? S_OK
: hr
;
570 static const IPersistStreamVtbl persiststream_vtbl
= {
571 dmobj_IPersistStream_QueryInterface
,
572 dmobj_IPersistStream_AddRef
,
573 dmobj_IPersistStream_Release
,
574 dmobj_IPersistStream_GetClassID
,
575 unimpl_IPersistStream_IsDirty
,
576 wave_IPersistStream_Load
,
577 unimpl_IPersistStream_Save
,
578 unimpl_IPersistStream_GetSizeMax
581 /* for ClassFactory */
582 HRESULT
create_dmwavetrack(REFIID lpcGUID
, void **ppobj
)
584 struct wave_track
*track
;
588 if (!(track
= calloc(1, sizeof(*track
)))) return E_OUTOFMEMORY
;
589 track
->IDirectMusicTrack8_iface
.lpVtbl
= &dmtrack8_vtbl
;
591 dmobject_init(&track
->dmobj
, &CLSID_DirectMusicWaveTrack
,
592 (IUnknown
*)&track
->IDirectMusicTrack8_iface
);
593 track
->dmobj
.IPersistStream_iface
.lpVtbl
= &persiststream_vtbl
;
594 list_init(&track
->parts
);
596 hr
= IDirectMusicTrack8_QueryInterface(&track
->IDirectMusicTrack8_iface
, lpcGUID
, ppobj
);
597 IDirectMusicTrack8_Release(&track
->IDirectMusicTrack8_iface
);
602 HRESULT
wave_track_create_from_chunk(IStream
*stream
, struct chunk_entry
*parent
,
603 IDirectMusicTrack8
**ret_iface
)
605 IDirectMusicTrack8
*iface
;
606 struct wave_track
*This
;
607 struct wave_item
*item
;
608 struct wave_part
*part
;
611 if (FAILED(hr
= create_dmwavetrack(&IID_IDirectMusicTrack8
, (void **)&iface
))) return hr
;
612 This
= impl_from_IDirectMusicTrack8(iface
);
614 if (!(part
= calloc(1, sizeof(*part
))))
616 IDirectMusicTrack8_Release(iface
);
617 return E_OUTOFMEMORY
;
619 list_init(&part
->items
);
620 list_add_tail(&This
->parts
, &part
->entry
);
622 if (!(item
= calloc(1, sizeof(*item
)))
623 || FAILED(hr
= wave_create_from_chunk(stream
, parent
, &item
->object
)))
625 IDirectMusicTrack8_Release(iface
);
629 if (FAILED(hr
= wave_get_duration(item
->object
, &item
->header
.rtDuration
)))
630 WARN("Failed to get wave duration, hr %#lx\n", hr
);
631 list_add_tail(&part
->items
, &item
->entry
);