dmime: Pass IDirectMusicPerformance8 to segment state functions.
[wine.git] / dlls / dmime / segmentstate.c
blob89534f7342d658532b4147ebf938282c5d687715
1 /*
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;
25 struct track_entry
27 struct list entry;
29 IDirectMusicTrack *track;
30 void *state_data;
31 DWORD track_id;
34 static void track_entry_destroy(struct track_entry *entry)
36 HRESULT hr;
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);
42 free(entry);
45 struct segment_state
47 IDirectMusicSegmentState8 IDirectMusicSegmentState8_iface;
48 LONG ref;
50 IDirectMusicSegment *segment;
51 MUSIC_TIME start_time;
52 MUSIC_TIME start_point;
53 MUSIC_TIME end_point;
54 BOOL auto_download;
56 struct list tracks;
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);
70 if (!ppobj)
71 return E_POINTER;
73 *ppobj = NULL;
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;
81 return S_OK;
84 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
85 return E_NOINTERFACE;
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);
95 return 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);
105 if (!ref)
107 segment_state_end_play((IDirectMusicSegmentState *)iface, NULL);
108 if (This->segment) IDirectMusicSegment_Release(This->segment);
109 free(This);
112 return ref;
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);
119 return S_OK;
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);
131 return S_OK;
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;
141 return S_OK;
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);
148 *seek_time = 0;
149 return S_OK;
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;
159 return S_OK;
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);
167 return S_OK;
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);
175 return S_OK;
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;
196 HRESULT hr;
198 *ret_iface = NULL;
199 if (!(obj = calloc(1, sizeof(*obj)))) return E_OUTOFMEMORY;
200 obj->IDirectMusicSegmentState8_iface.lpVtbl = &segment_state_vtbl;
201 obj->ref = 1;
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);
208 return hr;
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;
217 HRESULT hr;
218 UINT i;
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;
245 break;
248 if (!(entry = malloc(sizeof(*entry))))
249 hr = E_OUTOFMEMORY;
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);
258 if (FAILED(hr))
260 WARN("Failed to initialize track %p, hr %#lx\n", track, hr);
261 IDirectMusicTrack_Release(track);
262 free(entry);
266 if (SUCCEEDED(hr)) *ret_iface = iface;
267 else IDirectMusicSegmentState_Release(iface);
268 return hr;
271 HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance)
273 struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface);
274 DWORD track_flags = DMUS_TRACKF_DIRTY | DMUS_TRACKF_START | DMUS_TRACKF_SEEK;
275 MUSIC_TIME start_time = This->start_point, end_time = This->end_point;
276 struct track_entry *entry;
277 HRESULT hr = S_OK;
279 LIST_FOR_EACH_ENTRY(entry, &This->tracks, struct track_entry, entry)
281 if (FAILED(hr = IDirectMusicTrack_Play(entry->track, entry->state_data, start_time,
282 end_time, 0, track_flags, (IDirectMusicPerformance *)performance, iface, entry->track_id)))
284 WARN("Failed to play track %p, hr %#lx\n", entry->track, hr);
285 break;
289 return hr;
292 HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance)
294 struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface);
295 struct track_entry *entry, *next;
296 HRESULT hr;
298 LIST_FOR_EACH_ENTRY_SAFE(entry, next, &This->tracks, struct track_entry, entry)
300 list_remove(&entry->entry);
301 track_entry_destroy(entry);
304 if (performance && This->auto_download && FAILED(hr = IDirectMusicSegment_SetParam(This->segment,
305 &GUID_UnloadFromAudioPath, -1, DMUS_SEG_ALLTRACKS, 0, performance)))
306 ERR("Failed to unload segment from performance, hr %#lx\n", hr);
308 return S_OK;