mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / dmstyle / chordtrack.c
blob90db0a202a0edd54e966bd52e692999954db4c65
1 /* IDirectMusicChordTrack Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
4 * Copyright (C) 2003-2004 Raphael Junqueira
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "dmstyle_private.h"
22 #include "dmobject.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(dmstyle);
25 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
27 /*****************************************************************************
28 * IDirectMusicChordTrack implementation
30 typedef struct IDirectMusicChordTrack {
31 IDirectMusicTrack8 IDirectMusicTrack8_iface;
32 struct dmobject dmobj; /* IPersistStream only */
33 LONG ref;
34 DWORD dwScale;
35 } IDirectMusicChordTrack;
37 /* IDirectMusicChordTrack IDirectMusicTrack8 part: */
38 static inline IDirectMusicChordTrack *impl_from_IDirectMusicTrack8(IDirectMusicTrack8 *iface)
40 return CONTAINING_RECORD(iface, IDirectMusicChordTrack, IDirectMusicTrack8_iface);
43 static HRESULT WINAPI chord_track_QueryInterface(IDirectMusicTrack8 *iface, REFIID riid,
44 void **ret_iface)
46 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
48 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
50 *ret_iface = NULL;
52 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicTrack) ||
53 IsEqualIID(riid, &IID_IDirectMusicTrack8))
54 *ret_iface = iface;
55 else if (IsEqualIID(riid, &IID_IPersistStream))
56 *ret_iface = &This->dmobj.IPersistStream_iface;
57 else {
58 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ret_iface);
59 return E_NOINTERFACE;
62 IUnknown_AddRef((IUnknown*)*ret_iface);
63 return S_OK;
66 static ULONG WINAPI chord_track_AddRef(IDirectMusicTrack8 *iface)
68 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
69 LONG ref = InterlockedIncrement(&This->ref);
71 TRACE("(%p) ref=%d\n", This, ref);
73 return ref;
76 static ULONG WINAPI chord_track_Release(IDirectMusicTrack8 *iface)
78 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
79 LONG ref = InterlockedDecrement(&This->ref);
81 TRACE("(%p) ref=%d\n", This, ref);
83 if (!ref) {
84 HeapFree(GetProcessHeap(), 0, This);
85 DMSTYLE_UnlockModule();
88 return ref;
91 static HRESULT WINAPI chord_track_Init(IDirectMusicTrack8 *iface, IDirectMusicSegment *pSegment)
93 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
94 FIXME("(%p, %p): stub\n", This, pSegment);
95 return S_OK;
98 static HRESULT WINAPI chord_track_InitPlay(IDirectMusicTrack8 *iface,
99 IDirectMusicSegmentState *pSegmentState, IDirectMusicPerformance *pPerformance,
100 void **ppStateData, DWORD dwVirtualTrack8ID, DWORD dwFlags)
102 IDirectMusicChordTrack *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 chord_track_EndPlay(IDirectMusicTrack8 *iface, void *pStateData)
109 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
110 FIXME("(%p, %p): stub\n", This, pStateData);
111 return S_OK;
114 static HRESULT WINAPI chord_track_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 IDirectMusicChordTrack *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 chord_track_GetParam(IDirectMusicTrack8 *iface, REFGUID type, MUSIC_TIME time,
124 MUSIC_TIME *next, void *param)
126 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
128 TRACE("(%p, %s, %d, %p, %p):\n", This, debugstr_dmguid(type), time, next, param);
130 if (!type)
131 return E_POINTER;
133 if (IsEqualGUID(type, &GUID_ChordParam)) {
134 FIXME("GUID_ChordParam not handled yet\n");
135 return S_OK;
136 } else if (IsEqualGUID(type, &GUID_RhythmParam)) {
137 FIXME("GUID_RhythmParam not handled yet\n");
138 return S_OK;
141 return DMUS_E_GET_UNSUPPORTED;
144 static HRESULT WINAPI chord_track_SetParam(IDirectMusicTrack8 *iface, REFGUID type, MUSIC_TIME time,
145 void *param)
147 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
149 TRACE("(%p, %s, %d, %p)\n", This, debugstr_dmguid(type), time, param);
151 if (!type)
152 return E_POINTER;
153 if (!IsEqualGUID(type, &GUID_ChordParam))
154 return DMUS_E_SET_UNSUPPORTED;
156 FIXME("GUID_ChordParam not handled yet\n");
158 return S_OK;
161 static HRESULT WINAPI chord_track_IsParamSupported(IDirectMusicTrack8 *iface, REFGUID type)
163 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
165 TRACE("(%p, %s)\n", This, debugstr_dmguid(type));
167 if (!type)
168 return E_POINTER;
170 if (IsEqualGUID(type, &GUID_ChordParam) || IsEqualGUID(type, &GUID_RhythmParam))
171 return S_OK;
173 TRACE("param unsupported\n");
174 return DMUS_E_TYPE_UNSUPPORTED;
177 static HRESULT WINAPI chord_track_AddNotificationType(IDirectMusicTrack8 *iface,
178 REFGUID rguidNotificationType)
180 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
181 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
182 return S_OK;
185 static HRESULT WINAPI chord_track_RemoveNotificationType(IDirectMusicTrack8 *iface,
186 REFGUID rguidNotificationType)
188 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
189 FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType));
190 return S_OK;
193 static HRESULT WINAPI chord_track_Clone(IDirectMusicTrack8 *iface, MUSIC_TIME mtStart,
194 MUSIC_TIME mtEnd, IDirectMusicTrack **ppTrack)
196 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
197 FIXME("(%p, %d, %d, %p): stub\n", This, mtStart, mtEnd, ppTrack);
198 return S_OK;
201 static HRESULT WINAPI chord_track_PlayEx(IDirectMusicTrack8 *iface, void *pStateData,
202 REFERENCE_TIME rtStart, REFERENCE_TIME rtEnd, REFERENCE_TIME rtOffset, DWORD dwFlags,
203 IDirectMusicPerformance *pPerf, IDirectMusicSegmentState *pSegSt, DWORD dwVirtualID)
205 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
206 FIXME("(%p, %p, 0x%s, 0x%s, 0x%s, %d, %p, %p, %d): stub\n", This, pStateData, wine_dbgstr_longlong(rtStart),
207 wine_dbgstr_longlong(rtEnd), wine_dbgstr_longlong(rtOffset), dwFlags, pPerf, pSegSt, dwVirtualID);
208 return S_OK;
211 static HRESULT WINAPI chord_track_GetParamEx(IDirectMusicTrack8 *iface, REFGUID rguidType,
212 REFERENCE_TIME rtTime, REFERENCE_TIME *prtNext, void *pParam, void *pStateData,
213 DWORD dwFlags)
215 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
216 FIXME("(%p, %s, 0x%s, %p, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
217 wine_dbgstr_longlong(rtTime), prtNext, pParam, pStateData, dwFlags);
218 return S_OK;
221 static HRESULT WINAPI chord_track_SetParamEx(IDirectMusicTrack8 *iface, REFGUID rguidType,
222 REFERENCE_TIME rtTime, void *pParam, void *pStateData, DWORD dwFlags)
224 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
225 FIXME("(%p, %s, 0x%s, %p, %p, %d): stub\n", This, debugstr_dmguid(rguidType),
226 wine_dbgstr_longlong(rtTime), pParam, pStateData, dwFlags);
227 return S_OK;
230 static HRESULT WINAPI chord_track_Compose(IDirectMusicTrack8 *iface, IUnknown *context,
231 DWORD trackgroup, IDirectMusicTrack **track)
233 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
235 TRACE("(%p, %p, %d, %p): method not implemented\n", This, context, trackgroup, track);
236 return E_NOTIMPL;
239 static HRESULT WINAPI chord_track_Join(IDirectMusicTrack8 *iface, IDirectMusicTrack *pNewTrack,
240 MUSIC_TIME mtJoin, IUnknown *pContext, DWORD dwTrackGroup,
241 IDirectMusicTrack **ppResultTrack)
243 IDirectMusicChordTrack *This = impl_from_IDirectMusicTrack8(iface);
244 FIXME("(%p, %p, %d, %p, %d, %p): stub\n", This, pNewTrack, mtJoin, pContext, dwTrackGroup, ppResultTrack);
245 return S_OK;
248 static const IDirectMusicTrack8Vtbl dmtrack8_vtbl = {
249 chord_track_QueryInterface,
250 chord_track_AddRef,
251 chord_track_Release,
252 chord_track_Init,
253 chord_track_InitPlay,
254 chord_track_EndPlay,
255 chord_track_Play,
256 chord_track_GetParam,
257 chord_track_SetParam,
258 chord_track_IsParamSupported,
259 chord_track_AddNotificationType,
260 chord_track_RemoveNotificationType,
261 chord_track_Clone,
262 chord_track_PlayEx,
263 chord_track_GetParamEx,
264 chord_track_SetParamEx,
265 chord_track_Compose,
266 chord_track_Join
269 static HRESULT parse_chordtrack_list(IDirectMusicChordTrack *This, DMUS_PRIVATE_CHUNK *pChunk,
270 IStream *pStm)
272 DMUS_PRIVATE_CHUNK Chunk;
273 DWORD ListSize[3], ListCount[3];
274 LARGE_INTEGER liMove; /* used when skipping chunks */
276 if (pChunk->fccID != DMUS_FOURCC_CHORDTRACK_LIST) {
277 ERR_(dmfile)(": %s chunk should be a CHORDTRACK list\n", debugstr_fourcc (pChunk->fccID));
278 return E_FAIL;
281 ListSize[0] = pChunk->dwSize - sizeof(FOURCC);
282 ListCount[0] = 0;
284 do {
285 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
286 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
287 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
288 switch (Chunk.fccID) {
289 case DMUS_FOURCC_CHORDTRACKHEADER_CHUNK: {
290 TRACE_(dmfile)(": Chord track header chunk\n");
291 IStream_Read (pStm, &This->dwScale, sizeof(DWORD), NULL);
292 TRACE_(dmfile)(" - dwScale: %d\n", This->dwScale);
293 break;
295 case DMUS_FOURCC_CHORDTRACKBODY_CHUNK: {
296 DWORD sz;
297 DWORD it;
298 DWORD num;
299 DMUS_IO_CHORD body;
300 DMUS_IO_SUBCHORD subchords;
302 TRACE_(dmfile)(": Chord track body chunk\n");
304 IStream_Read (pStm, &sz, sizeof(DWORD), NULL);
305 TRACE_(dmfile)(" - sizeof(DMUS_IO_CHORD): %d\n", sz);
306 if (sz != sizeof(DMUS_IO_CHORD)) return E_FAIL;
307 IStream_Read (pStm, &body, sizeof(DMUS_IO_CHORD), NULL);
308 TRACE_(dmfile)(" - wszName: %s\n", debugstr_w(body.wszName));
309 TRACE_(dmfile)(" - mtTime: %u\n", body.mtTime);
310 TRACE_(dmfile)(" - wMeasure: %u\n", body.wMeasure);
311 TRACE_(dmfile)(" - bBeat: %u\n", body.bBeat);
312 TRACE_(dmfile)(" - bFlags: 0x%02x\n", body.bFlags);
314 IStream_Read (pStm, &num, sizeof(DWORD), NULL);
315 TRACE_(dmfile)(" - # DMUS_IO_SUBCHORDS: %d\n", num);
316 IStream_Read (pStm, &sz, sizeof(DWORD), NULL);
317 TRACE_(dmfile)(" - sizeof(DMUS_IO_SUBCHORDS): %d\n", sz);
318 if (sz != sizeof(DMUS_IO_SUBCHORD)) return E_FAIL;
320 for (it = 0; it < num; ++it) {
321 IStream_Read (pStm, &subchords, sizeof(DMUS_IO_SUBCHORD), NULL);
322 TRACE_(dmfile)("DMUS_IO_SUBCHORD #%d\n", it+1);
323 TRACE_(dmfile)(" - dwChordPattern: %u\n", subchords.dwChordPattern);
324 TRACE_(dmfile)(" - dwScalePattern: %u\n", subchords.dwScalePattern);
325 TRACE_(dmfile)(" - dwInversionPoints: %u\n", subchords.dwInversionPoints);
326 TRACE_(dmfile)(" - dwLevels: %u\n", subchords.dwLevels);
327 TRACE_(dmfile)(" - bChordRoot: %u\n", subchords.bChordRoot);
328 TRACE_(dmfile)(" - bScaleRoot: %u\n", subchords.bScaleRoot);
330 break;
332 default: {
333 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
334 liMove.QuadPart = Chunk.dwSize;
335 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
336 break;
339 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
340 } while (ListCount[0] < ListSize[0]);
342 return S_OK;
345 static inline IDirectMusicChordTrack *impl_from_IPersistStream(IPersistStream *iface)
347 return CONTAINING_RECORD(iface, IDirectMusicChordTrack, dmobj.IPersistStream_iface);
350 static HRESULT WINAPI IPersistStreamImpl_Load(IPersistStream *iface, IStream *pStm)
352 IDirectMusicChordTrack *This = impl_from_IPersistStream(iface);
353 DMUS_PRIVATE_CHUNK Chunk;
354 LARGE_INTEGER liMove;
355 HRESULT hr;
357 TRACE("(%p, %p): Loading\n", This, pStm);
359 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
360 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
361 switch (Chunk.fccID) {
362 case FOURCC_LIST: {
363 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
364 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
365 switch (Chunk.fccID) {
366 case DMUS_FOURCC_CHORDTRACK_LIST: {
367 TRACE_(dmfile)(": Chord track list\n");
368 hr = parse_chordtrack_list(This, &Chunk, pStm);
369 if (FAILED(hr)) return hr;
370 break;
372 default: {
373 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
374 liMove.QuadPart = Chunk.dwSize;
375 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
376 return E_FAIL;
379 TRACE_(dmfile)(": reading finished\n");
380 break;
382 default: {
383 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
384 liMove.QuadPart = Chunk.dwSize;
385 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
386 return E_FAIL;
390 return S_OK;
393 static HRESULT WINAPI IPersistStreamImpl_Save(IPersistStream *iface, IStream *stream,
394 BOOL cleardirty)
396 IDirectMusicChordTrack *This = impl_from_IPersistStream(iface);
398 FIXME("(%p, %p, %d): stub\n", This, stream, cleardirty);
400 if (!stream)
401 return E_POINTER;
403 return E_NOTIMPL;
406 static const IPersistStreamVtbl persiststream_vtbl = {
407 dmobj_IPersistStream_QueryInterface,
408 dmobj_IPersistStream_AddRef,
409 dmobj_IPersistStream_Release,
410 dmobj_IPersistStream_GetClassID,
411 unimpl_IPersistStream_IsDirty,
412 IPersistStreamImpl_Load,
413 IPersistStreamImpl_Save,
414 unimpl_IPersistStream_GetSizeMax
417 /* for ClassFactory */
418 HRESULT WINAPI create_dmchordtrack(REFIID lpcGUID, void **ppobj)
420 IDirectMusicChordTrack *track;
421 HRESULT hr;
423 track = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*track));
424 if (!track) {
425 *ppobj = NULL;
426 return E_OUTOFMEMORY;
428 track->IDirectMusicTrack8_iface.lpVtbl = &dmtrack8_vtbl;
429 track->ref = 1;
430 dmobject_init(&track->dmobj, &CLSID_DirectMusicChordTrack,
431 (IUnknown *)&track->IDirectMusicTrack8_iface);
432 track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
434 DMSTYLE_LockModule();
435 hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj);
436 IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface);
438 return hr;