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 static const DWORD handled_track_flags
= DMUS_TRACKF_START
| DMUS_TRACKF_SEEK
| DMUS_TRACKF_DIRTY
| DMUS_TRACKF_LOOP
;
151 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
152 LONG volume
= This
->header
.lVolume
;
153 IDirectMusicGraph
*graph
;
154 struct wave_part
*part
;
155 struct wave_item
*item
;
158 TRACE("(%p, %p, %ld, %ld, %ld, %#lx, %p, %p, %ld)\n", This
, state_data
, start_time
, end_time
,
159 time_offset
, track_flags
, performance
, segment_state
, track_id
);
161 if (track_flags
& ~handled_track_flags
)
162 FIXME("track_flags %#lx not implemented\n", track_flags
& ~handled_track_flags
);
163 if (!(track_flags
& (DMUS_TRACKF_START
| DMUS_TRACKF_LOOP
))) return S_OK
;
165 if (FAILED(hr
= IDirectMusicSegmentState_QueryInterface(segment_state
,
166 &IID_IDirectMusicGraph
, (void **)&graph
)) &&
167 FAILED(hr
= IDirectMusicPerformance_QueryInterface(performance
,
168 &IID_IDirectMusicGraph
, (void **)&graph
)))
171 LIST_FOR_EACH_ENTRY(part
, &This
->parts
, struct wave_part
, entry
)
173 volume
+= part
->header
.lVolume
;
175 LIST_FOR_EACH_ENTRY(item
, &part
->items
, struct wave_item
, entry
)
179 if (!item
->buffer
) continue;
180 if (item
->header
.rtTime
< start_time
) continue;
181 if (item
->header
.rtTime
>= end_time
) continue;
183 if (FAILED(hr
= IDirectMusicPerformance_AllocPMsg(performance
, sizeof(*msg
),
184 (DMUS_PMSG
**)&msg
)))
187 msg
->mtTime
= item
->header
.rtTime
+ time_offset
;
188 msg
->dwFlags
= DMUS_PMSGF_MUSICTIME
;
189 msg
->dwPChannel
= part
->header
.dwPChannel
;
190 msg
->dwVirtualTrackID
= track_id
;
191 msg
->dwType
= DMUS_PMSGT_WAVE
;
192 msg
->punkUser
= (IUnknown
*)item
->buffer
;
193 IDirectSoundBuffer_AddRef(item
->buffer
);
195 msg
->rtStartOffset
= item
->header
.rtStartOffset
;
196 msg
->rtDuration
= item
->header
.rtDuration
;
197 msg
->lVolume
= volume
+ item
->header
.lVolume
;
198 msg
->lPitch
= item
->header
.lPitch
;
200 if (FAILED(hr
= IDirectMusicGraph_StampPMsg(graph
, (DMUS_PMSG
*)msg
))
201 || FAILED(hr
= IDirectMusicPerformance_SendPMsg(performance
, (DMUS_PMSG
*)msg
)))
203 IDirectMusicPerformance_FreePMsg(performance
, (DMUS_PMSG
*)msg
);
208 volume
-= part
->header
.lVolume
;
211 IDirectMusicGraph_Release(graph
);
215 static HRESULT WINAPI
wave_track_GetParam(IDirectMusicTrack8
*iface
, REFGUID type
, MUSIC_TIME time
,
216 MUSIC_TIME
*next
, void *param
)
218 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
220 TRACE("(%p, %s, %ld, %p, %p): not supported\n", This
, debugstr_dmguid(type
), time
, next
, param
);
221 return DMUS_E_GET_UNSUPPORTED
;
224 static HRESULT WINAPI
wave_track_SetParam(IDirectMusicTrack8
*iface
, REFGUID type
, MUSIC_TIME time
,
227 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
229 TRACE("(%p, %s, %ld, %p)\n", This
, debugstr_dmguid(type
), time
, param
);
231 if (IsEqualGUID(type
, &GUID_Disable_Auto_Download
)) {
232 FIXME("GUID_Disable_Auto_Download not handled yet\n");
235 if (IsEqualGUID(type
, &GUID_Download
)) {
236 FIXME("GUID_Download not handled yet\n");
239 if (IsEqualGUID(type
, &GUID_DownloadToAudioPath
))
241 IDirectMusicPerformance8
*performance
;
242 IDirectMusicAudioPath
*audio_path
;
243 IUnknown
*object
= param
;
244 struct wave_part
*part
;
245 struct wave_item
*item
;
246 IDirectSound
*dsound
;
249 if (FAILED(hr
= IDirectMusicAudioPath_QueryInterface(object
, &IID_IDirectMusicPerformance8
, (void **)&performance
))
250 && SUCCEEDED(hr
= IDirectMusicAudioPath_QueryInterface(object
, &IID_IDirectMusicAudioPath
, (void **)&audio_path
)))
252 hr
= IDirectMusicAudioPath_GetObjectInPath(audio_path
, DMUS_PCHANNEL_ALL
, DMUS_PATH_PERFORMANCE
, 0,
253 &GUID_All_Objects
, 0, &IID_IDirectMusicPerformance8
, (void **)&performance
);
254 IDirectMusicAudioPath_Release(audio_path
);
258 hr
= performance_get_dsound(performance
, &dsound
);
259 IDirectMusicPerformance_Release(performance
);
263 WARN("Failed to get direct sound from param %p, hr %#lx\n", param
, hr
);
267 LIST_FOR_EACH_ENTRY(part
, &This
->parts
, struct wave_part
, entry
)
269 LIST_FOR_EACH_ENTRY(item
, &part
->items
, struct wave_item
, entry
)
271 if (item
->buffer
) continue;
272 if (FAILED(hr
= wave_download_to_dsound(item
->object
, dsound
, &item
->buffer
)))
274 WARN("Failed to download wave %p to direct sound, hr %#lx\n", item
->object
, hr
);
282 if (IsEqualGUID(type
, &GUID_Enable_Auto_Download
)) {
283 FIXME("GUID_Enable_Auto_Download not handled yet\n");
286 if (IsEqualGUID(type
, &GUID_Unload
)) {
287 FIXME("GUID_Unload not handled yet\n");
290 if (IsEqualGUID(type
, &GUID_UnloadFromAudioPath
))
292 struct wave_part
*part
;
293 struct wave_item
*item
;
295 LIST_FOR_EACH_ENTRY(part
, &This
->parts
, struct wave_part
, entry
)
297 LIST_FOR_EACH_ENTRY(item
, &part
->items
, struct wave_item
, entry
)
299 if (!item
->buffer
) continue;
300 IDirectSoundBuffer_Release(item
->buffer
);
308 return DMUS_E_TYPE_UNSUPPORTED
;
311 static HRESULT WINAPI
wave_track_IsParamSupported(IDirectMusicTrack8
*iface
, REFGUID type
)
313 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
314 static const GUID
*valid
[] = {
315 &GUID_Disable_Auto_Download
,
317 &GUID_DownloadToAudioPath
,
318 &GUID_Enable_Auto_Download
,
320 &GUID_UnloadFromAudioPath
324 TRACE("(%p, %s)\n", This
, debugstr_dmguid(type
));
326 for (i
= 0; i
< ARRAY_SIZE(valid
); i
++)
327 if (IsEqualGUID(type
, valid
[i
]))
330 TRACE("param unsupported\n");
331 return DMUS_E_TYPE_UNSUPPORTED
;
334 static HRESULT WINAPI
wave_track_AddNotificationType(IDirectMusicTrack8
*iface
, REFGUID notiftype
)
336 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
338 TRACE("(%p, %s): method not implemented\n", This
, debugstr_dmguid(notiftype
));
342 static HRESULT WINAPI
wave_track_RemoveNotificationType(IDirectMusicTrack8
*iface
,
345 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
347 TRACE("(%p, %s): method not implemented\n", This
, debugstr_dmguid(notiftype
));
351 static HRESULT WINAPI
wave_track_Clone(IDirectMusicTrack8
*iface
, MUSIC_TIME mtStart
,
352 MUSIC_TIME mtEnd
, IDirectMusicTrack
**ppTrack
)
354 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
355 FIXME("(%p, %ld, %ld, %p): stub\n", This
, mtStart
, mtEnd
, ppTrack
);
359 static HRESULT WINAPI
wave_track_PlayEx(IDirectMusicTrack8
*iface
, void *pStateData
,
360 REFERENCE_TIME rtStart
, REFERENCE_TIME rtEnd
, REFERENCE_TIME rtOffset
, DWORD dwFlags
,
361 IDirectMusicPerformance
*pPerf
, IDirectMusicSegmentState
*pSegSt
, DWORD dwVirtualID
)
363 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
364 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %ld, %p, %p, %ld): stub\n", This
, pStateData
,
365 wine_dbgstr_longlong(rtStart
), wine_dbgstr_longlong(rtEnd
),
366 wine_dbgstr_longlong(rtOffset
), dwFlags
, pPerf
, pSegSt
, dwVirtualID
);
370 static HRESULT WINAPI
wave_track_GetParamEx(IDirectMusicTrack8
*iface
, REFGUID rguidType
,
371 REFERENCE_TIME rtTime
, REFERENCE_TIME
*prtNext
, void *pParam
, void *pStateData
,
374 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
375 FIXME("(%p, %s, 0x%s, %p, %p, %p, %ld): stub\n", This
, debugstr_dmguid(rguidType
),
376 wine_dbgstr_longlong(rtTime
), prtNext
, pParam
, pStateData
, dwFlags
);
380 static HRESULT WINAPI
wave_track_SetParamEx(IDirectMusicTrack8
*iface
, REFGUID rguidType
,
381 REFERENCE_TIME rtTime
, void *pParam
, void *pStateData
, DWORD dwFlags
)
383 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
384 FIXME("(%p, %s, 0x%s, %p, %p, %ld): stub\n", This
, debugstr_dmguid(rguidType
),
385 wine_dbgstr_longlong(rtTime
), pParam
, pStateData
, dwFlags
);
389 static HRESULT WINAPI
wave_track_Compose(IDirectMusicTrack8
*iface
, IUnknown
*context
,
390 DWORD trackgroup
, IDirectMusicTrack
**track
)
392 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
394 TRACE("(%p, %p, %ld, %p): method not implemented\n", This
, context
, trackgroup
, track
);
398 static HRESULT WINAPI
wave_track_Join(IDirectMusicTrack8
*iface
, IDirectMusicTrack
*newtrack
,
399 MUSIC_TIME join
, IUnknown
*context
, DWORD trackgroup
, IDirectMusicTrack
**resulttrack
)
401 struct wave_track
*This
= impl_from_IDirectMusicTrack8(iface
);
402 TRACE("(%p, %p, %ld, %p, %ld, %p): method not implemented\n", This
, newtrack
, join
, context
,
403 trackgroup
, resulttrack
);
407 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl
= {
408 wave_track_QueryInterface
,
417 wave_track_IsParamSupported
,
418 wave_track_AddNotificationType
,
419 wave_track_RemoveNotificationType
,
422 wave_track_GetParamEx
,
423 wave_track_SetParamEx
,
428 static HRESULT
parse_wave_item(struct wave_part
*part
, IStream
*stream
, struct chunk_entry
*wavi
)
430 struct chunk_entry wave
= {.parent
= wavi
};
431 struct chunk_entry chunk
= {.parent
= &wave
};
432 struct wave_item
*item
;
435 /* Nested list with two chunks */
436 if (FAILED(hr
= stream_next_chunk(stream
, &wave
)))
438 if (wave
.id
!= FOURCC_LIST
|| wave
.type
!= DMUS_FOURCC_WAVE_LIST
)
439 return DMUS_E_UNSUPPORTED_STREAM
;
441 if (!(item
= calloc(1, sizeof(*item
)))) return E_OUTOFMEMORY
;
443 /* Wave item header chunk */
444 if (FAILED(hr
= stream_next_chunk(stream
, &chunk
)))
446 if (chunk
.id
!= DMUS_FOURCC_WAVEITEM_CHUNK
) {
447 hr
= DMUS_E_UNSUPPORTED_STREAM
;
451 if (FAILED(hr
= stream_chunk_get_data(stream
, &chunk
, &item
->header
, sizeof(item
->header
)))) {
452 WARN("Failed to read data of %s\n", debugstr_chunk(&chunk
));
456 TRACE("Found DMUS_IO_WAVE_ITEM_HEADER\n");
457 TRACE("\tlVolume %ld\n", item
->header
.lVolume
);
458 TRACE("\tdwVariations %ld\n", item
->header
.dwVariations
);
459 TRACE("\trtTime %s\n", wine_dbgstr_longlong(item
->header
.rtTime
));
460 TRACE("\trtStartOffset %s\n", wine_dbgstr_longlong(item
->header
.rtStartOffset
));
461 TRACE("\trtReserved %s\n", wine_dbgstr_longlong(item
->header
.rtReserved
));
462 TRACE("\trtDuration %s\n", wine_dbgstr_longlong(item
->header
.rtDuration
));
463 TRACE("\tdwLoopStart %ld\n", item
->header
.dwLoopStart
);
464 TRACE("\tdwLoopEnd %ld\n", item
->header
.dwLoopEnd
);
465 TRACE("\tdwFlags %#08lx\n", item
->header
.dwFlags
);
466 TRACE("\twVolumeRange %d\n", item
->header
.wVolumeRange
);
467 TRACE("\twPitchRange %d\n", item
->header
.wPitchRange
);
469 /* Second chunk is a reference list */
470 if (stream_next_chunk(stream
, &chunk
) != S_OK
|| chunk
.id
!= FOURCC_LIST
||
471 chunk
.type
!= DMUS_FOURCC_REF_LIST
) {
472 hr
= DMUS_E_UNSUPPORTED_STREAM
;
475 if (FAILED(hr
= dmobj_parsereference(stream
, &chunk
, &item
->object
)))
478 list_add_tail(&part
->items
, &item
->entry
);
487 static HRESULT
parse_wave_part(struct wave_track
*This
, IStream
*stream
, struct chunk_entry
*wavp
)
489 struct chunk_entry chunk
= {.parent
= wavp
};
490 struct wave_part
*part
;
493 /* Wave part header chunk */
494 if (FAILED(hr
= stream_next_chunk(stream
, &chunk
)))
496 if (chunk
.id
!= DMUS_FOURCC_WAVEPART_CHUNK
)
497 return DMUS_E_UNSUPPORTED_STREAM
;
499 if (!(part
= calloc(1, sizeof(*part
)))) return E_OUTOFMEMORY
;
500 list_init(&part
->items
);
502 if (FAILED(hr
= stream_chunk_get_data(stream
, &chunk
, &part
->header
, sizeof(part
->header
)))) {
503 WARN("Failed to read data of %s\n", debugstr_chunk(&chunk
));
507 TRACE("Found DMUS_IO_WAVE_PART_HEADER\n");
508 TRACE("\tlVolume %ld\n", part
->header
.lVolume
);
509 TRACE("\tdwVariations %ld\n", part
->header
.dwVariations
);
510 TRACE("\tdwPChannel %ld\n", part
->header
.dwPChannel
);
511 TRACE("\tdwLockToPart %ld\n", part
->header
.dwLockToPart
);
512 TRACE("\tdwFlags %#08lx\n", part
->header
.dwFlags
);
513 TRACE("\tdwIndex %ld\n", part
->header
.dwIndex
);
515 /* Array of wave items */
516 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
517 if (chunk
.id
== FOURCC_LIST
&& chunk
.type
== DMUS_FOURCC_WAVEITEM_LIST
)
518 if (FAILED(hr
= parse_wave_item(part
, stream
, &chunk
)))
524 list_add_tail(&This
->parts
, &part
->entry
);
533 static HRESULT WINAPI
wave_IPersistStream_Load(IPersistStream
*iface
, IStream
*stream
)
535 struct wave_track
*This
= impl_from_IPersistStream(iface
);
536 struct chunk_entry wavt
= {0};
537 struct chunk_entry chunk
= {.parent
= &wavt
};
540 TRACE("%p, %p\n", This
, stream
);
545 if ((hr
= stream_get_chunk(stream
, &wavt
) != S_OK
))
547 if (wavt
.id
!= FOURCC_LIST
|| wavt
.type
!= DMUS_FOURCC_WAVETRACK_LIST
)
548 return DMUS_E_UNSUPPORTED_STREAM
;
550 TRACE("Parsing segment form in %p: %s\n", stream
, debugstr_chunk(&wavt
));
552 /* Track header chunk */
553 if (FAILED(hr
= stream_next_chunk(stream
, &chunk
)))
555 if (chunk
.id
!= DMUS_FOURCC_WAVETRACK_CHUNK
)
556 return DMUS_E_UNSUPPORTED_STREAM
;
557 if (FAILED(hr
= stream_chunk_get_data(stream
, &chunk
, &This
->header
, sizeof(This
->header
))))
560 TRACE("Found DMUS_IO_WAVE_TRACK_HEADER\n");
561 TRACE("\tlVolume %ld\n", This
->header
.lVolume
);
562 TRACE("\tdwFlags %#08lx\n", This
->header
.dwFlags
);
564 /* Array of wave parts */
565 while ((hr
= stream_next_chunk(stream
, &chunk
)) == S_OK
)
566 if (chunk
.id
== FOURCC_LIST
&& chunk
.type
== DMUS_FOURCC_WAVEPART_LIST
)
567 if (FAILED(hr
= parse_wave_part(This
, stream
, &chunk
)))
570 return SUCCEEDED(hr
) ? S_OK
: hr
;
573 static const IPersistStreamVtbl persiststream_vtbl
= {
574 dmobj_IPersistStream_QueryInterface
,
575 dmobj_IPersistStream_AddRef
,
576 dmobj_IPersistStream_Release
,
577 dmobj_IPersistStream_GetClassID
,
578 unimpl_IPersistStream_IsDirty
,
579 wave_IPersistStream_Load
,
580 unimpl_IPersistStream_Save
,
581 unimpl_IPersistStream_GetSizeMax
584 /* for ClassFactory */
585 HRESULT
create_dmwavetrack(REFIID lpcGUID
, void **ppobj
)
587 struct wave_track
*track
;
591 if (!(track
= calloc(1, sizeof(*track
)))) return E_OUTOFMEMORY
;
592 track
->IDirectMusicTrack8_iface
.lpVtbl
= &dmtrack8_vtbl
;
594 dmobject_init(&track
->dmobj
, &CLSID_DirectMusicWaveTrack
,
595 (IUnknown
*)&track
->IDirectMusicTrack8_iface
);
596 track
->dmobj
.IPersistStream_iface
.lpVtbl
= &persiststream_vtbl
;
597 list_init(&track
->parts
);
599 hr
= IDirectMusicTrack8_QueryInterface(&track
->IDirectMusicTrack8_iface
, lpcGUID
, ppobj
);
600 IDirectMusicTrack8_Release(&track
->IDirectMusicTrack8_iface
);
605 HRESULT
wave_track_create_from_chunk(IStream
*stream
, struct chunk_entry
*parent
,
606 IDirectMusicTrack8
**ret_iface
)
608 IDirectMusicTrack8
*iface
;
609 struct wave_track
*This
;
610 struct wave_item
*item
;
611 struct wave_part
*part
;
614 if (FAILED(hr
= create_dmwavetrack(&IID_IDirectMusicTrack8
, (void **)&iface
))) return hr
;
615 This
= impl_from_IDirectMusicTrack8(iface
);
617 if (!(part
= calloc(1, sizeof(*part
))))
619 IDirectMusicTrack8_Release(iface
);
620 return E_OUTOFMEMORY
;
622 list_init(&part
->items
);
623 list_add_tail(&This
->parts
, &part
->entry
);
625 if (!(item
= calloc(1, sizeof(*item
)))
626 || FAILED(hr
= wave_create_from_chunk(stream
, parent
, &item
->object
)))
628 IDirectMusicTrack8_Release(iface
);
632 if (FAILED(hr
= wave_get_duration(item
->object
, &item
->header
.rtDuration
)))
633 WARN("Failed to get wave duration, hr %#lx\n", hr
);
634 list_add_tail(&part
->items
, &item
->entry
);