kernel32: Update version to Win 10.
[wine.git] / dlls / dmstyle / styletrack.c
blobf80073e42bfa9a6dc76302215f126e3385b88ec6
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 #include "wine/heap.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(dmstyle);
26 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
28 /*****************************************************************************
29 * IDirectMusicStyleTrack implementation
31 typedef struct IDirectMusicStyleTrack {
32 IDirectMusicTrack8 IDirectMusicTrack8_iface;
33 struct dmobject dmobj; /* IPersistStream only */
34 LONG ref;
35 struct list Items;
36 } IDirectMusicStyleTrack;
38 /* IDirectMusicStyleTrack IDirectMusicTrack8 part: */
39 static inline IDirectMusicStyleTrack *impl_from_IDirectMusicTrack8(IDirectMusicTrack8 *iface)
41 return CONTAINING_RECORD(iface, IDirectMusicStyleTrack, IDirectMusicTrack8_iface);
44 static HRESULT WINAPI style_track_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
45 void **ret_iface)
47 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
49 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
51 *ret_iface = NULL;
53 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicTrack) ||
54 IsEqualIID(riid, &IID_IDirectMusicTrack8))
55 *ret_iface = iface;
56 else if (IsEqualIID(riid, &IID_IPersistStream))
57 *ret_iface = &This->dmobj.IPersistStream_iface;
58 else {
59 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
60 return E_NOINTERFACE;
63 IUnknown_AddRef((IUnknown*)*ret_iface);
64 return S_OK;
67 static ULONG WINAPI style_track_AddRef(IDirectMusicTrack8 *iface)
69 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
70 LONG ref = InterlockedIncrement(&This->ref);
72 TRACE("(%p) ref=%d\n", This, ref);
74 return ref;
77 static ULONG WINAPI style_track_Release(IDirectMusicTrack8 *iface)
79 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
80 LONG ref = InterlockedDecrement(&This->ref);
82 TRACE("(%p) ref=%d\n", This, ref);
84 if (!ref) {
85 struct list *cursor, *cursor2;
86 DMUS_PRIVATE_STYLE_ITEM *item;
88 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->Items) {
89 item = LIST_ENTRY(cursor, DMUS_PRIVATE_STYLE_ITEM, entry);
90 list_remove(cursor);
92 IDirectMusicStyle8_Release(item->pObject);
93 heap_free(item);
96 heap_free(This);
97 DMSTYLE_UnlockModule();
100 return ref;
103 static HRESULT WINAPI style_track_Init(IDirectMusicTrack8 *iface, IDirectMusicSegment *pSegment)
105 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
106 FIXME("(%p, %p): stub\n", This, pSegment);
107 return S_OK;
110 static HRESULT WINAPI style_track_InitPlay(IDirectMusicTrack8 *iface,
111 IDirectMusicSegmentState *pSegmentState, IDirectMusicPerformance *pPerformance,
112 void **ppStateData, DWORD dwVirtualTrack8ID, DWORD dwFlags)
114 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
115 FIXME("(%p, %p, %p, %p, %d, %d): stub\n", This, pSegmentState, pPerformance, ppStateData, dwVirtualTrack8ID, dwFlags);
116 return S_OK;
119 static HRESULT WINAPI style_track_EndPlay(IDirectMusicTrack8 *iface, void *pStateData)
121 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
122 FIXME("(%p, %p): stub\n", This, pStateData);
123 return S_OK;
126 static HRESULT WINAPI style_track_Play(IDirectMusicTrack8 *iface, void *pStateData,
127 MUSIC_TIME mtStart, MUSIC_TIME mtEnd, MUSIC_TIME mtOffset, DWORD dwFlags,
128 IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID)
130 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
131 FIXME("(%p, %p, %d, %d, %d, %d, %p, %p, %d): stub\n", This, pStateData, mtStart, mtEnd, mtOffset, dwFlags, pPerf, pSegSt, dwVirtualID);
132 return S_OK;
135 static HRESULT WINAPI style_track_GetParam(IDirectMusicTrack8 *iface, REFGUID type,
136 MUSIC_TIME time, MUSIC_TIME *next, void *param)
138 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
139 struct list *item = NULL;
141 TRACE("(%p, %s, %d, %p, %p):\n", This, debugstr_dmguid(type), time, next, param);
143 if (!type)
144 return E_POINTER;
146 if (IsEqualGUID(&GUID_IDirectMusicStyle, type)) {
147 LIST_FOR_EACH (item, &This->Items) {
148 DMUS_PRIVATE_STYLE_ITEM *style = LIST_ENTRY(item, DMUS_PRIVATE_STYLE_ITEM, entry);
149 if (style->pObject) {
150 IDirectMusicStyle8_AddRef(style->pObject);
151 *((IDirectMusicStyle8**)param) = style->pObject;
153 return S_OK;
157 return DMUS_E_NOT_FOUND;
158 } else if (IsEqualGUID(&GUID_TimeSignature, type)) {
159 FIXME("GUID_TimeSignature not handled yet\n");
160 return S_OK;
163 return DMUS_E_GET_UNSUPPORTED;
166 static HRESULT WINAPI style_track_SetParam(IDirectMusicTrack8 *iface, REFGUID type, MUSIC_TIME time,
167 void *param)
169 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
171 TRACE("(%p, %s, %d, %p)\n", This, debugstr_dmguid(type), time, param);
173 if (!type)
174 return E_POINTER;
176 if (IsEqualGUID(type, &GUID_DisableTimeSig)) {
177 FIXME("GUID_DisableTimeSig not handled yet\n");
178 return S_OK;
179 } else if (IsEqualGUID(type, &GUID_EnableTimeSig)) {
180 FIXME("GUID_EnableTimeSig not handled yet\n");
181 return S_OK;
182 } else if (IsEqualGUID(type, &GUID_IDirectMusicStyle)) {
183 FIXME("GUID_IDirectMusicStyle not handled yet\n");
184 return S_OK;
185 } else if (IsEqualGUID(type, &GUID_SeedVariations)) {
186 FIXME("GUID_SeedVariations not handled yet\n");
187 return S_OK;
190 return DMUS_E_SET_UNSUPPORTED;
193 static HRESULT WINAPI style_track_IsParamSupported(IDirectMusicTrack8 *iface, REFGUID rguidType)
195 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
197 TRACE("(%p, %s)\n", This, debugstr_dmguid(rguidType));
199 if (!rguidType)
200 return E_POINTER;
202 if (IsEqualGUID (rguidType, &GUID_DisableTimeSig)
203 || IsEqualGUID (rguidType, &GUID_EnableTimeSig)
204 || IsEqualGUID (rguidType, &GUID_IDirectMusicStyle)
205 || IsEqualGUID (rguidType, &GUID_SeedVariations)
206 || IsEqualGUID (rguidType, &GUID_TimeSignature)) {
207 TRACE("param supported\n");
208 return S_OK;
210 TRACE("param unsupported\n");
211 return DMUS_E_TYPE_UNSUPPORTED;
214 static HRESULT WINAPI style_track_AddNotificationType(IDirectMusicTrack8 *iface,
215 REFGUID rguidNotificationType)
217 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
218 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
219 return S_OK;
222 static HRESULT WINAPI style_track_RemoveNotificationType(IDirectMusicTrack8 *iface,
223 REFGUID rguidNotificationType)
225 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
226 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
227 return S_OK;
230 static HRESULT WINAPI style_track_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME mtStart,
231 MUSIC_TIME mtEnd, IDirectMusicTrack **ppTrack)
233 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
234 FIXME("(%p, %d, %d, %p): stub\n", This, mtStart, mtEnd, ppTrack);
235 return S_OK;
238 static HRESULT WINAPI style_track_PlayEx(IDirectMusicTrack8 *iface, void *pStateData,
239 REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD dwFlags,
240 IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID)
242 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
243 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %d, %p, %p, %d): stub\n", This, pStateData, wine_dbgstr_longlong(rtStart),
244 wine_dbgstr_longlong(rtEnd), wine_dbgstr_longlong(rtOffset), dwFlags, pPerf, pSegSt, dwVirtualID);
245 return S_OK;
248 static HRESULT WINAPI style_track_GetParamEx(IDirectMusicTrack8 *iface, REFGUID rguidType,
249 REFERENCE_TIME rtTime, REFERENCE_TIME *prtNext, void *pParam, void *pStateData,
250 DWORD dwFlags)
252 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
253 FIXME("(%p, %s, 0x%s, %p, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
254 wine_dbgstr_longlong(rtTime), prtNext, pParam, pStateData, dwFlags);
255 return S_OK;
258 static HRESULT WINAPI style_track_SetParamEx(IDirectMusicTrack8 *iface, REFGUID rguidType,
259 REFERENCE_TIME rtTime, void *pParam, void *pStateData, DWORD dwFlags)
261 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
262 FIXME("(%p, %s, 0x%s, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
263 wine_dbgstr_longlong(rtTime), pParam, pStateData, dwFlags);
264 return S_OK;
267 static HRESULT WINAPI style_track_Compose(IDirectMusicTrack8 *iface, IUnknown *context,
268 DWORD trackgroup, IDirectMusicTrack **track)
270 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
272 TRACE("(%p, %p, %d, %p): method not implemented\n", This, context, trackgroup, track);
273 return E_NOTIMPL;
276 static HRESULT WINAPI style_track_Join(IDirectMusicTrack8 *iface, IDirectMusicTrack *pNewTrack,
277 MUSIC_TIME mtJoin, IUnknown *pContext, DWORD dwTrackGroup,
278 IDirectMusicTrack **ppResultTrack)
280 IDirectMusicStyleTrack *This = impl_from_IDirectMusicTrack8(iface);
281 FIXME("(%p, %p, %d, %p, %d, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
282 return S_OK;
285 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
286 style_track_QueryInterface,
287 style_track_AddRef,
288 style_track_Release,
289 style_track_Init,
290 style_track_InitPlay,
291 style_track_EndPlay,
292 style_track_Play,
293 style_track_GetParam,
294 style_track_SetParam,
295 style_track_IsParamSupported,
296 style_track_AddNotificationType,
297 style_track_RemoveNotificationType,
298 style_track_Clone,
299 style_track_PlayEx,
300 style_track_GetParamEx,
301 style_track_SetParamEx,
302 style_track_Compose,
303 style_track_Join
306 static HRESULT parse_style_ref(IDirectMusicStyleTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
307 IStream *pStm)
309 DMUS_PRIVATE_CHUNK Chunk;
310 DWORD ListSize[3], ListCount[3];
311 LARGE_INTEGER liMove; /* used when skipping chunks */
312 HRESULT hr;
314 IDirectMusicObject* pObject = NULL;
315 LPDMUS_PRIVATE_STYLE_ITEM pNewItem = NULL;
317 if (pChunk->fccID != DMUS_FOURCC_STYLE_REF_LIST) {
318 ERR_(dmfile)(": %s chunk should be a STYLE list\n", debugstr_fourcc (pChunk->fccID));
319 return E_FAIL;
322 ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
323 ListCount[0] = 0;
325 do {
326 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
327 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
328 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
329 switch (Chunk.fccID) {
330 case DMUS_FOURCC_TIME_STAMP_CHUNK: {
331 TRACE_(dmfile)(": Time Stamp chunk\n");
332 pNewItem = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(DMUS_PRIVATE_STYLE_ITEM));
333 if (NULL == pNewItem) {
334 ERR(": no more memory\n");
335 return E_OUTOFMEMORY;
337 IStream_Read (pStm, &pNewItem->dwTimeStamp, sizeof(DWORD), NULL);
338 TRACE_(dmfile)(" - dwTimeStamp: %u\n", pNewItem->dwTimeStamp);
339 list_add_tail (&This->Items, &pNewItem->entry);
340 break;
342 case FOURCC_LIST: {
343 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
344 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
345 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
346 ListCount[1] = 0;
347 switch (Chunk.fccID) {
349 * should be a DMRF (DirectMusic Reference) list @TODO
351 case DMUS_FOURCC_REF_LIST: {
352 FIXME_(dmfile)(": DMRF (DM References) list, not yet handled\n");
353 hr = IDirectMusicUtils_IPersistStream_ParseReference(&This->dmobj.IPersistStream_iface,
354 &Chunk, pStm, &pObject);
355 if (FAILED(hr)) {
356 ERR(": could not load Reference\n");
357 return hr;
359 hr = IDirectMusicObject_QueryInterface(pObject, &IID_IDirectMusicStyle8, (LPVOID*)&pNewItem->pObject);
360 if (FAILED(hr)) {
361 ERR(": Reference not an IDirectMusicStyle, exiting\n");
362 exit(-1);
363 return hr;
365 IDirectMusicObject_Release(pObject);
366 break;
368 default: {
369 TRACE_(dmfile)(": unknown (skipping)\n");
370 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
371 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
372 break;
375 break;
377 default: {
378 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
379 liMove.QuadPart = Chunk.dwSize;
380 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
381 break;
384 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
385 } while (ListCount[0] < ListSize[0]);
387 return S_OK;
390 static HRESULT parse_styletrack_list(IDirectMusicStyleTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
391 IStream *pStm)
393 DMUS_PRIVATE_CHUNK Chunk;
394 DWORD ListSize[3], ListCount[3];
395 LARGE_INTEGER liMove; /* used when skipping chunks */
396 HRESULT hr;
398 if (pChunk->fccID != DMUS_FOURCC_STYLE_TRACK_LIST) {
399 ERR_(dmfile)(": %s chunk should be a STYLETRACK list\n", debugstr_fourcc (pChunk->fccID));
400 return E_FAIL;
403 ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
404 ListCount[0] = 0;
406 do {
407 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
408 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
409 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
410 switch (Chunk.fccID) {
411 case FOURCC_LIST: {
412 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
413 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
414 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
415 ListCount[1] = 0;
416 switch (Chunk.fccID) {
417 case DMUS_FOURCC_STYLE_REF_LIST: {
418 TRACE_(dmfile)(": STYLE_REF list\n");
419 hr = parse_style_ref(This, &Chunk, pStm);
420 if (FAILED(hr)) return hr;
421 break;
423 default: {
424 TRACE_(dmfile)(": unknown (skipping)\n");
425 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
426 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
427 break;
430 break;
432 default: {
433 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
434 liMove.QuadPart = Chunk.dwSize;
435 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
436 break;
439 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
440 } while (ListCount[0] < ListSize[0]);
442 return S_OK;
445 static inline IDirectMusicStyleTrack *impl_from_IPersistStream(IPersistStream *iface)
447 return CONTAINING_RECORD(iface, IDirectMusicStyleTrack, dmobj.IPersistStream_iface);
450 static HRESULT WINAPI IPersistStreamImpl_Load(IPersistStream *iface, IStream *pStm)
452 IDirectMusicStyleTrack *This = impl_from_IPersistStream(iface);
453 DMUS_PRIVATE_CHUNK Chunk;
454 LARGE_INTEGER liMove;
455 HRESULT hr;
457 FIXME("(%p, %p): Loading not fully implemented yet\n", This, pStm);
459 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
460 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
461 switch (Chunk.fccID) {
462 case FOURCC_LIST: {
463 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
464 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
465 switch (Chunk.fccID) {
466 case DMUS_FOURCC_STYLE_TRACK_LIST: {
467 TRACE_(dmfile)(": Chord track list\n");
468 hr = parse_styletrack_list(This, &Chunk, pStm);
469 if (FAILED(hr)) return hr;
470 break;
472 default: {
473 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
474 liMove.QuadPart = Chunk.dwSize;
475 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
476 return E_FAIL;
479 TRACE_(dmfile)(": reading finished\n");
480 break;
482 default: {
483 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
484 liMove.QuadPart = Chunk.dwSize;
485 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
486 return E_FAIL;
490 return S_OK;
493 static const IPersistStreamVtbl persiststream_vtbl = {
494 dmobj_IPersistStream_QueryInterface,
495 dmobj_IPersistStream_AddRef,
496 dmobj_IPersistStream_Release,
497 dmobj_IPersistStream_GetClassID,
498 unimpl_IPersistStream_IsDirty,
499 IPersistStreamImpl_Load,
500 unimpl_IPersistStream_Save,
501 unimpl_IPersistStream_GetSizeMax
504 /* for ClassFactory */
505 HRESULT WINAPI create_dmstyletrack(REFIID lpcGUID, void **ppobj)
507 IDirectMusicStyleTrack *track;
508 HRESULT hr;
510 track = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*track));
511 if (!track) {
512 *ppobj = NULL;
513 return E_OUTOFMEMORY;
515 track->IDirectMusicTrack8_iface.lpVtbl = &dmtrack8_vtbl;
516 track->ref = 1;
517 dmobject_init(&track->dmobj, &CLSID_DirectMusicStyleTrack,
518 (IUnknown *)&track->IDirectMusicTrack8_iface);
519 track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
520 list_init (&track->Items);
522 DMSTYLE_LockModule();
523 hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
524 IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface);
526 return hr;