wined3d: Implement SM5 deriv_rtx_fine instruction.
[wine.git] / dlls / dmstyle / styletrack.c
blob79b4787ca04db694354c57a704a9bac06494c013
1 /* IDirectMusicStyleTrack Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "dmstyle_private.h"
21 #include "dmobject.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmstyle);
24 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
26 /*****************************************************************************
27 * IDirectMusicStyleTrack implementation
29 typedef struct IDirectMusicStyleTrack {
30 IDirectMusicTrack8 IDirectMusicTrack8_iface;
31 struct dmobject dmobj; /* IPersistStream only */
32 LONG ref;
33 struct list Items;
34 } IDirectMusicStyleTrack;
36 /* IDirectMusicStyleTrack IDirectMusicTrack8 part: */
37 static inline IDirectMusicStyleTrack *impl_from_IDirectMusicTrack8(IDirectMusicTrack8 *iface)
39 return CONTAINING_RECORD(iface, IDirectMusicStyleTrack, IDirectMusicTrack8_iface);
42 static HRESULT WINAPI IDirectMusicTrack8Impl_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
43 void **ret_iface)
45 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
47 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
49 *ret_iface = NULL;
51 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicTrack) ||
52 IsEqualIID(riid, &IID_IDirectMusicTrack8))
53 *ret_iface = iface;
54 else if (IsEqualIID(riid, &IID_IPersistStream))
55 *ret_iface = &This->dmobj.IPersistStream_iface;
56 else {
57 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
58 return E_NOINTERFACE;
61 IUnknown_AddRef((IUnknown*)*ret_iface);
62 return S_OK;
65 static ULONG WINAPI IDirectMusicTrack8Impl_AddRef(IDirectMusicTrack8 *iface)
67 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
68 LONG ref = InterlockedIncrement(&This->ref);
70 TRACE("(%p) ref=%d\n", This, ref);
72 return ref;
75 static ULONG WINAPI IDirectMusicTrack8Impl_Release(IDirectMusicTrack8 *iface)
77 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
78 LONG ref = InterlockedDecrement(&This->ref);
80 TRACE("(%p) ref=%d\n", This, ref);
82 if (!ref) {
83 HeapFree(GetProcessHeap(), 0, This);
84 DMSTYLE_UnlockModule();
87 return ref;
90 static HRESULT WINAPI IDirectMusicTrack8Impl_Init(IDirectMusicTrack8 *iface,
91 IDirectMusicSegment *pSegment)
93 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
94 FIXME("(%p, %p): stub\n", This, pSegment);
95 return S_OK;
98 static HRESULT WINAPI IDirectMusicTrack8Impl_InitPlay(IDirectMusicTrack8 *iface,
99 IDirectMusicSegmentState *pSegmentState, IDirectMusicPerformance *pPerformance,
100 void **ppStateData, DWORD dwVirtualTrack8ID, DWORD dwFlags)
102 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
103 FIXME("(%p, %p, %p, %p, %d, %d): stub\n", This, pSegmentState, pPerformance, ppStateData, dwVirtualTrack8ID, dwFlags);
104 return S_OK;
107 static HRESULT WINAPI IDirectMusicTrack8Impl_EndPlay(IDirectMusicTrack8 *iface, void *pStateData)
109 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
110 FIXME("(%p, %p): stub\n", This, pStateData);
111 return S_OK;
114 static HRESULT WINAPI IDirectMusicTrack8Impl_Play(IDirectMusicTrack8 *iface, void *pStateData,
115 MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, DWORD dwFlags,
116 IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID)
118 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
119 FIXME("(%p, %p, %d, %d, %d, %d, %p, %p, %d): stub\n", This, pStateData, mtStart, mtEnd, mtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
120 return S_OK;
123 static HRESULT WINAPI IDirectMusicTrack8Impl_GetParam(IDirectMusicTrack8 *iface, REFGUID rguidType,
124 MUSIC_TIME mtTime, MUSIC_TIME *pmtNext, void *pParam)
126 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
127 FIXME("(%p, %s, %d, %p, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pmtNext, pParam);
128 return S_OK;
131 static HRESULT WINAPI IDirectMusicTrack8Impl_SetParam(IDirectMusicTrack8 *iface, REFGUID rguidType,
132 MUSIC_TIME mtTime, void *pParam)
134 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
135 FIXME("(%p, %s, %d, %p): stub\n", This, debugstr_dmguid(rguidType), mtTime, pParam);
136 return S_OK;
139 static HRESULT WINAPI IDirectMusicTrack8Impl_IsParamSupported(IDirectMusicTrack8 *iface,
140 REFGUID rguidType)
142 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
144 TRACE("(%p, %s)\n", This, debugstr_dmguid(rguidType));
146 if (!rguidType)
147 return E_POINTER;
149 if (IsEqualGUID (rguidType, &GUID_DisableTimeSig)
150 || IsEqualGUID (rguidType, &GUID_EnableTimeSig)
151 || IsEqualGUID (rguidType, &GUID_IDirectMusicStyle)
152 || IsEqualGUID (rguidType, &GUID_SeedVariations)
153 || IsEqualGUID (rguidType, &GUID_TimeSignature)) {
154 TRACE("param supported\n");
155 return S_OK;
157 TRACE("param unsupported\n");
158 return DMUS_E_TYPE_UNSUPPORTED;
161 static HRESULT WINAPI IDirectMusicTrack8Impl_AddNotificationType(IDirectMusicTrack8 *iface,
162 REFGUID rguidNotificationType)
164 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
165 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
166 return S_OK;
169 static HRESULT WINAPI IDirectMusicTrack8Impl_RemoveNotificationType(IDirectMusicTrack8 *iface,
170 REFGUID rguidNotificationType)
172 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
173 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
174 return S_OK;
177 static HRESULT WINAPI IDirectMusicTrack8Impl_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME mtStart,
178 MUSIC_TIME mtEnd, IDirectMusicTrack **ppTrack)
180 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
181 FIXME("(%p, %d, %d, %p): stub\n", This, mtStart, mtEnd, ppTrack);
182 return S_OK;
185 static HRESULT WINAPI IDirectMusicTrack8Impl_PlayEx(IDirectMusicTrack8 *iface, void *pStateData,
186 REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD dwFlags,
187 IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID)
189 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
190 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %d, %p, %p, %d): stub\n", This, pStateData, wine_dbgstr_longlong(rtStart),
191 wine_dbgstr_longlong(rtEnd), wine_dbgstr_longlong(rtOffset), dwFlags, pPerf, pSegSt, dwVirtualID);
192 return S_OK;
195 static HRESULT WINAPI IDirectMusicTrack8Impl_GetParamEx(IDirectMusicTrack8 *iface,
196 REFGUID rguidType, REFERENCE_TIME rtTime, REFERENCE_TIME *prtNext, void *pParam,
197 void *pStateData, DWORD dwFlags)
199 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
200 FIXME("(%p, %s, 0x%s, %p, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
201 wine_dbgstr_longlong(rtTime), prtNext, pParam, pStateData, dwFlags);
202 return S_OK;
205 static HRESULT WINAPI IDirectMusicTrack8Impl_SetParamEx(IDirectMusicTrack8 *iface,
206 REFGUID rguidType, REFERENCE_TIME rtTime, void *pParam, void *pStateData, DWORD dwFlags)
208 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
209 FIXME("(%p, %s, 0x%s, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
210 wine_dbgstr_longlong(rtTime), pParam, pStateData, dwFlags);
211 return S_OK;
214 static HRESULT WINAPI IDirectMusicTrack8Impl_Compose(IDirectMusicTrack8 *iface, IUnknown *context,
215 DWORD trackgroup, IDirectMusicTrack **track)
217 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
219 TRACE("(%p, %p, %d, %p): method not implemented\n", This, context, trackgroup, track);
220 return E_NOTIMPL;
223 static HRESULT WINAPI IDirectMusicTrack8Impl_Join(IDirectMusicTrack8 *iface,
224 IDirectMusicTrack *pNewTrack, MUSIC_TIME mtJoin, IUnknown *pContext, DWORD dwTrackGroup,
225 IDirectMusicTrack **ppResultTrack)
227 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
228 FIXME("(%p, %p, %d, %p, %d, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
229 return S_OK;
232 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
233 IDirectMusicTrack8Impl_QueryInterface,
234 IDirectMusicTrack8Impl_AddRef,
235 IDirectMusicTrack8Impl_Release,
236 IDirectMusicTrack8Impl_Init,
237 IDirectMusicTrack8Impl_InitPlay,
238 IDirectMusicTrack8Impl_EndPlay,
239 IDirectMusicTrack8Impl_Play,
240 IDirectMusicTrack8Impl_GetParam,
241 IDirectMusicTrack8Impl_SetParam,
242 IDirectMusicTrack8Impl_IsParamSupported,
243 IDirectMusicTrack8Impl_AddNotificationType,
244 IDirectMusicTrack8Impl_RemoveNotificationType,
245 IDirectMusicTrack8Impl_Clone,
246 IDirectMusicTrack8Impl_PlayEx,
247 IDirectMusicTrack8Impl_GetParamEx,
248 IDirectMusicTrack8Impl_SetParamEx,
249 IDirectMusicTrack8Impl_Compose,
250 IDirectMusicTrack8Impl_Join
253 static HRESULT parse_style_ref(IDirectMusicStyleTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
254 IStream *pStm)
256 DMUS_PRIVATE_CHUNK Chunk;
257 DWORD ListSize[3], ListCount[3];
258 LARGE_INTEGER liMove; /* used when skipping chunks */
259 HRESULT hr;
261 IDirectMusicObject* pObject = NULL;
262 LPDMUS_PRIVATE_STYLE_ITEM pNewItem = NULL;
264 if (pChunk->fccID != DMUS_FOURCC_STYLE_REF_LIST) {
265 ERR_(dmfile)(": %s chunk should be a STYLE list\n", debugstr_fourcc (pChunk->fccID));
266 return E_FAIL;
269 ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
270 ListCount[0] = 0;
272 do {
273 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
274 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
275 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
276 switch (Chunk.fccID) {
277 case DMUS_FOURCC_TIME_STAMP_CHUNK: {
278 TRACE_(dmfile)(": Time Stamp chunk\n");
279 pNewItem = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_ITEM));
280 if (NULL == pNewItem) {
281 ERR(": no more memory\n");
282 return E_OUTOFMEMORY;
284 IStream_Read (pStm, &pNewItem->dwTimeStamp, sizeof(DWORD), NULL);
285 TRACE_(dmfile)(" - dwTimeStamp: %u\n", pNewItem->dwTimeStamp);
286 list_add_tail (&This->Items, &pNewItem->entry);
287 break;
289 case FOURCC_LIST: {
290 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
291 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
292 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
293 ListCount[1] = 0;
294 switch (Chunk.fccID) {
296 * should be a DMRF (DirectMusic Reference) list @TODO
298 case DMUS_FOURCC_REF_LIST: {
299 FIXME_(dmfile)(": DMRF (DM References) list, not yet handled\n");
300 hr = IDirectMusicUtils_IPersistStream_ParseReference(&This->dmobj.IPersistStream_iface,
301 &Chunk, pStm, &pObject);
302 if (FAILED(hr)) {
303 ERR(": could not load Reference\n");
304 return hr;
306 hr = IDirectMusicObject_QueryInterface(pObject, &IID_IDirectMusicStyle8, (LPVOID*)&pNewItem->pObject);
307 if (FAILED(hr)) {
308 ERR(": Reference not an IDirectMusicStyle, exiting\n");
309 exit(-1);
310 return hr;
312 IDirectMusicObject_Release(pObject);
313 break;
315 default: {
316 TRACE_(dmfile)(": unknown (skipping)\n");
317 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
318 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
319 break;
322 break;
324 default: {
325 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
326 liMove.QuadPart = Chunk.dwSize;
327 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
328 break;
331 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
332 } while (ListCount[0] < ListSize[0]);
334 return S_OK;
337 static HRESULT parse_styletrack_list(IDirectMusicStyleTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
338 IStream *pStm)
340 DMUS_PRIVATE_CHUNK Chunk;
341 DWORD ListSize[3], ListCount[3];
342 LARGE_INTEGER liMove; /* used when skipping chunks */
343 HRESULT hr;
345 if (pChunk->fccID != DMUS_FOURCC_STYLE_TRACK_LIST) {
346 ERR_(dmfile)(": %s chunk should be a STYLETRACK list\n", debugstr_fourcc (pChunk->fccID));
347 return E_FAIL;
350 ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
351 ListCount[0] = 0;
353 do {
354 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
355 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
356 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
357 switch (Chunk.fccID) {
358 case FOURCC_LIST: {
359 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
360 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
361 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
362 ListCount[1] = 0;
363 switch (Chunk.fccID) {
364 case DMUS_FOURCC_STYLE_REF_LIST: {
365 TRACE_(dmfile)(": STYLE_REF list\n");
366 hr = parse_style_ref(This, &Chunk, pStm);
367 if (FAILED(hr)) return hr;
368 break;
370 default: {
371 TRACE_(dmfile)(": unknown (skipping)\n");
372 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
373 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
374 break;
377 break;
379 default: {
380 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
381 liMove.QuadPart = Chunk.dwSize;
382 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
383 break;
386 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
387 } while (ListCount[0] < ListSize[0]);
389 return S_OK;
392 static inline IDirectMusicStyleTrack *impl_from_IPersistStream(IPersistStream *iface)
394 return CONTAINING_RECORD(iface, IDirectMusicStyleTrack, dmobj.IPersistStream_iface);
397 static HRESULT WINAPI IPersistStreamImpl_Load(IPersistStream *iface, IStream *pStm)
399 IDirectMusicStyleTrack *This = impl_from_IPersistStream(iface);
400 DMUS_PRIVATE_CHUNK Chunk;
401 LARGE_INTEGER liMove;
402 HRESULT hr;
404 FIXME("(%p, %p): Loading not fully implemented yet\n", This, pStm);
406 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
407 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
408 switch (Chunk.fccID) {
409 case FOURCC_LIST: {
410 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
411 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
412 switch (Chunk.fccID) {
413 case DMUS_FOURCC_STYLE_TRACK_LIST: {
414 TRACE_(dmfile)(": Chord track list\n");
415 hr = parse_styletrack_list(This, &Chunk, pStm);
416 if (FAILED(hr)) return hr;
417 break;
419 default: {
420 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
421 liMove.QuadPart = Chunk.dwSize;
422 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
423 return E_FAIL;
426 TRACE_(dmfile)(": reading finished\n");
427 break;
429 default: {
430 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
431 liMove.QuadPart = Chunk.dwSize;
432 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
433 return E_FAIL;
437 return S_OK;
440 static const IPersistStreamVtbl persiststream_vtbl = {
441 dmobj_IPersistStream_QueryInterface,
442 dmobj_IPersistStream_AddRef,
443 dmobj_IPersistStream_Release,
444 dmobj_IPersistStream_GetClassID,
445 unimpl_IPersistStream_IsDirty,
446 IPersistStreamImpl_Load,
447 unimpl_IPersistStream_Save,
448 unimpl_IPersistStream_GetSizeMax
451 /* for ClassFactory */
452 HRESULT WINAPI create_dmstyletrack(REFIID lpcGUID, void **ppobj)
454 IDirectMusicStyleTrack *track;
455 HRESULT hr;
457 track = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*track));
458 if (!track) {
459 *ppobj = NULL;
460 return E_OUTOFMEMORY;
462 track->IDirectMusicTrack8_iface.lpVtbl = &dmtrack8_vtbl;
463 track->ref = 1;
464 dmobject_init(&track->dmobj, &CLSID_DirectMusicStyleTrack,
465 (IUnknown *)&track->IDirectMusicTrack8_iface);
466 track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
467 list_init (&track->Items);
469 DMSTYLE_LockModule();
470 hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
471 IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface);
473 return hr;