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"
21 WINE_DEFAULT_DEBUG_CHANNEL(dmime
);
23 static DWORD next_track_id
;
29 IDirectMusicTrack
*track
;
34 static void track_entry_destroy(struct track_entry
*entry
)
38 if (FAILED(hr
= IDirectMusicTrack_EndPlay(entry
->track
, entry
->state_data
)))
39 WARN("track %p EndPlay failed, hr %#lx\n", entry
->track
, hr
);
41 IDirectMusicTrack_Release(entry
->track
);
47 IDirectMusicSegmentState8 IDirectMusicSegmentState8_iface
;
50 IDirectMusicSegment
*segment
;
51 MUSIC_TIME start_time
;
52 MUSIC_TIME start_point
;
59 static inline struct segment_state
*impl_from_IDirectMusicSegmentState8(IDirectMusicSegmentState8
*iface
)
61 return CONTAINING_RECORD(iface
, struct segment_state
, IDirectMusicSegmentState8_iface
);
64 static HRESULT WINAPI
segment_state_QueryInterface(IDirectMusicSegmentState8
*iface
, REFIID riid
, void **ppobj
)
66 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
68 TRACE("(%p, %s, %p)\n", This
, debugstr_dmguid(riid
), ppobj
);
75 if (IsEqualIID(riid
, &IID_IUnknown
) ||
76 IsEqualIID(riid
, &IID_IDirectMusicSegmentState
) ||
77 IsEqualIID(riid
, &IID_IDirectMusicSegmentState8
))
79 IDirectMusicSegmentState8_AddRef(iface
);
80 *ppobj
= &This
->IDirectMusicSegmentState8_iface
;
84 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ppobj
);
88 static ULONG WINAPI
segment_state_AddRef(IDirectMusicSegmentState8
*iface
)
90 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
91 ULONG ref
= InterlockedIncrement(&This
->ref
);
93 TRACE("(%p): %ld\n", This
, ref
);
98 static ULONG WINAPI
segment_state_Release(IDirectMusicSegmentState8
*iface
)
100 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
101 ULONG ref
= InterlockedDecrement(&This
->ref
);
103 TRACE("(%p): %ld\n", This
, ref
);
107 segment_state_end_play((IDirectMusicSegmentState
*)iface
, NULL
);
108 if (This
->segment
) IDirectMusicSegment_Release(This
->segment
);
115 static HRESULT WINAPI
segment_state_GetRepeats(IDirectMusicSegmentState8
*iface
, DWORD
*repeats
)
117 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
118 FIXME("(%p, %p): semi-stub\n", This
, repeats
);
122 static HRESULT WINAPI
segment_state_GetSegment(IDirectMusicSegmentState8
*iface
, IDirectMusicSegment
**segment
)
124 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
126 TRACE("(%p, %p)\n", This
, segment
);
128 if (!(*segment
= This
->segment
)) return DMUS_E_NOT_FOUND
;
130 IDirectMusicSegment_AddRef(This
->segment
);
134 static HRESULT WINAPI
segment_state_GetStartTime(IDirectMusicSegmentState8
*iface
, MUSIC_TIME
*start_time
)
136 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
138 TRACE("(%p, %p)\n", This
, start_time
);
140 *start_time
= This
->start_time
;
144 static HRESULT WINAPI
segment_state_GetSeek(IDirectMusicSegmentState8
*iface
, MUSIC_TIME
*seek_time
)
146 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
147 FIXME("(%p, %p): semi-stub\n", This
, seek_time
);
152 static HRESULT WINAPI
segment_state_GetStartPoint(IDirectMusicSegmentState8
*iface
, MUSIC_TIME
*start_point
)
154 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
156 TRACE("(%p, %p)\n", This
, start_point
);
158 *start_point
= This
->start_point
;
162 static HRESULT WINAPI
segment_state_SetTrackConfig(IDirectMusicSegmentState8
*iface
,
163 REFGUID rguidTrackClassID
, DWORD dwGroupBits
, DWORD dwIndex
, DWORD dwFlagsOn
, DWORD dwFlagsOff
)
165 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
166 FIXME("(%p, %s, %ld, %ld, %ld, %ld): stub\n", This
, debugstr_dmguid(rguidTrackClassID
), dwGroupBits
, dwIndex
, dwFlagsOn
, dwFlagsOff
);
170 static HRESULT WINAPI
segment_state_GetObjectInPath(IDirectMusicSegmentState8
*iface
, DWORD dwPChannel
,
171 DWORD dwStage
, DWORD dwBuffer
, REFGUID guidObject
, DWORD dwIndex
, REFGUID iidInterface
, void **ppObject
)
173 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8(iface
);
174 FIXME("(%p, %ld, %ld, %ld, %s, %ld, %s, %p): stub\n", This
, dwPChannel
, dwStage
, dwBuffer
, debugstr_dmguid(guidObject
), dwIndex
, debugstr_dmguid(iidInterface
), ppObject
);
178 static const IDirectMusicSegmentState8Vtbl segment_state_vtbl
=
180 segment_state_QueryInterface
,
181 segment_state_AddRef
,
182 segment_state_Release
,
183 segment_state_GetRepeats
,
184 segment_state_GetSegment
,
185 segment_state_GetStartTime
,
186 segment_state_GetSeek
,
187 segment_state_GetStartPoint
,
188 segment_state_SetTrackConfig
,
189 segment_state_GetObjectInPath
,
192 /* for ClassFactory */
193 HRESULT
create_dmsegmentstate(REFIID riid
, void **ret_iface
)
195 struct segment_state
*obj
;
199 if (!(obj
= calloc(1, sizeof(*obj
)))) return E_OUTOFMEMORY
;
200 obj
->IDirectMusicSegmentState8_iface
.lpVtbl
= &segment_state_vtbl
;
202 obj
->start_time
= -1;
203 list_init(&obj
->tracks
);
205 TRACE("Created IDirectMusicSegmentState %p\n", obj
);
206 hr
= IDirectMusicSegmentState8_QueryInterface(&obj
->IDirectMusicSegmentState8_iface
, riid
, ret_iface
);
207 IDirectMusicSegmentState8_Release(&obj
->IDirectMusicSegmentState8_iface
);
211 HRESULT
segment_state_create(IDirectMusicSegment
*segment
, MUSIC_TIME start_time
,
212 IDirectMusicPerformance8
*performance
, IDirectMusicSegmentState
**ret_iface
)
214 IDirectMusicSegmentState
*iface
;
215 struct segment_state
*This
;
216 IDirectMusicTrack
*track
;
220 TRACE("(%p, %lu, %p)\n", segment
, start_time
, ret_iface
);
222 if (FAILED(hr
= create_dmsegmentstate(&IID_IDirectMusicSegmentState
, (void **)&iface
))) return hr
;
223 This
= impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8
*)iface
);
225 This
->segment
= segment
;
226 IDirectMusicSegment_AddRef(This
->segment
);
228 if (SUCCEEDED(hr
= IDirectMusicPerformance8_GetGlobalParam(performance
, &GUID_PerfAutoDownload
,
229 &This
->auto_download
, sizeof(This
->auto_download
))) && This
->auto_download
)
230 hr
= IDirectMusicSegment_SetParam(segment
, &GUID_DownloadToAudioPath
, -1,
231 DMUS_SEG_ALLTRACKS
, 0, performance
);
233 This
->start_time
= start_time
;
234 if (SUCCEEDED(hr
)) hr
= IDirectMusicSegment_GetStartPoint(segment
, &This
->start_point
);
235 if (SUCCEEDED(hr
)) hr
= IDirectMusicSegment_GetLength(segment
, &This
->end_point
);
237 for (i
= 0; SUCCEEDED(hr
); i
++)
239 DWORD track_id
= ++next_track_id
;
240 struct track_entry
*entry
;
242 if ((hr
= IDirectMusicSegment_GetTrack(segment
, &GUID_NULL
, -1, i
, &track
)) != S_OK
)
244 if (hr
== DMUS_E_NOT_FOUND
) hr
= S_OK
;
248 if (!(entry
= malloc(sizeof(*entry
))))
250 else if (SUCCEEDED(hr
= IDirectMusicTrack_InitPlay(track
, iface
, (IDirectMusicPerformance
*)performance
,
251 &entry
->state_data
, track_id
, 0)))
253 entry
->track
= track
;
254 entry
->track_id
= track_id
;
255 list_add_tail(&This
->tracks
, &entry
->entry
);
260 WARN("Failed to initialize track %p, hr %#lx\n", track
, hr
);
261 IDirectMusicTrack_Release(track
);
266 duration
= This
->end_point
- This
->start_point
;
267 if (SUCCEEDED(hr
)) hr
= performance_send_segment_end(performance
, start_time
+ duration
, iface
);
269 if (SUCCEEDED(hr
)) *ret_iface
= iface
;
270 else IDirectMusicSegmentState_Release(iface
);
274 HRESULT
segment_state_play(IDirectMusicSegmentState
*iface
, IDirectMusicPerformance8
*performance
)
276 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8
*)iface
);
277 DWORD track_flags
= DMUS_TRACKF_DIRTY
| DMUS_TRACKF_START
| DMUS_TRACKF_SEEK
;
278 MUSIC_TIME start_time
= This
->start_point
, end_time
= This
->end_point
;
279 struct track_entry
*entry
;
282 LIST_FOR_EACH_ENTRY(entry
, &This
->tracks
, struct track_entry
, entry
)
284 if (FAILED(hr
= IDirectMusicTrack_Play(entry
->track
, entry
->state_data
, start_time
, end_time
,
285 This
->start_time
, track_flags
, (IDirectMusicPerformance
*)performance
, iface
, entry
->track_id
)))
287 WARN("Failed to play track %p, hr %#lx\n", entry
->track
, hr
);
295 HRESULT
segment_state_end_play(IDirectMusicSegmentState
*iface
, IDirectMusicPerformance8
*performance
)
297 struct segment_state
*This
= impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8
*)iface
);
298 struct track_entry
*entry
, *next
;
301 LIST_FOR_EACH_ENTRY_SAFE(entry
, next
, &This
->tracks
, struct track_entry
, entry
)
303 list_remove(&entry
->entry
);
304 track_entry_destroy(entry
);
307 if (performance
&& This
->auto_download
&& FAILED(hr
= IDirectMusicSegment_SetParam(This
->segment
,
308 &GUID_UnloadFromAudioPath
, -1, DMUS_SEG_ALLTRACKS
, 0, performance
)))
309 ERR("Failed to unload segment from performance, hr %#lx\n", hr
);