dinput: Use vid/pid for first chunk of product guid on OSX, too.
[wine.git] / dlls / dmcompos / chordmap.c
blob5296970b56cc9f35485b4896eadaf8d2e4fc3d3a
1 /* IDirectMusicChordMap 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 "dmcompos_private.h"
21 #include "dmobject.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmcompos);
24 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
26 /*****************************************************************************
27 * IDirectMusicChordMapImpl implementation
29 typedef struct IDirectMusicChordMapImpl {
30 IDirectMusicChordMap IDirectMusicChordMap_iface;
31 struct dmobject dmobj;
32 LONG ref;
33 } IDirectMusicChordMapImpl;
35 /* IDirectMusicChordMapImpl IDirectMusicChordMap part: */
36 static inline IDirectMusicChordMapImpl *impl_from_IDirectMusicChordMap(IDirectMusicChordMap *iface)
38 return CONTAINING_RECORD(iface, IDirectMusicChordMapImpl, IDirectMusicChordMap_iface);
41 static HRESULT WINAPI IDirectMusicChordMapImpl_QueryInterface(IDirectMusicChordMap *iface,
42 REFIID riid, void **ret_iface)
44 IDirectMusicChordMapImpl *This = impl_from_IDirectMusicChordMap(iface);
46 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ret_iface);
48 *ret_iface = NULL;
50 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectMusicChordMap))
51 *ret_iface = iface;
52 else if (IsEqualIID(riid, &IID_IDirectMusicObject))
53 *ret_iface = &This->dmobj.IDirectMusicObject_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 IDirectMusicChordMapImpl_AddRef(IDirectMusicChordMap *iface)
67 IDirectMusicChordMapImpl *This = impl_from_IDirectMusicChordMap(iface);
68 LONG ref = InterlockedIncrement(&This->ref);
70 TRACE("(%p) ref=%d\n", This, ref);
72 return ref;
75 static ULONG WINAPI IDirectMusicChordMapImpl_Release(IDirectMusicChordMap *iface)
77 IDirectMusicChordMapImpl *This = impl_from_IDirectMusicChordMap(iface);
78 LONG ref = InterlockedDecrement(&This->ref);
80 TRACE("(%p) ref=%d\n", This, ref);
82 if (!ref) {
83 HeapFree(GetProcessHeap(), 0, This);
84 DMCOMPOS_UnlockModule();
87 return ref;
90 static HRESULT WINAPI IDirectMusicChordMapImpl_GetScale(IDirectMusicChordMap *iface,
91 DWORD *pdwScale)
93 IDirectMusicChordMapImpl *This = impl_from_IDirectMusicChordMap(iface);
94 FIXME("(%p, %p): stub\n", This, pdwScale);
95 return S_OK;
98 static const IDirectMusicChordMapVtbl dmchordmap_vtbl = {
99 IDirectMusicChordMapImpl_QueryInterface,
100 IDirectMusicChordMapImpl_AddRef,
101 IDirectMusicChordMapImpl_Release,
102 IDirectMusicChordMapImpl_GetScale
105 /* IDirectMusicChordMapImpl IDirectMusicObject part: */
106 static HRESULT WINAPI chord_IDirectMusicObject_ParseDescriptor(IDirectMusicObject *iface,
107 IStream *stream, DMUS_OBJECTDESC *desc)
109 struct chunk_entry riff = {0};
110 HRESULT hr;
112 TRACE("(%p, %p, %p)\n", iface, stream, desc);
114 if (!stream || !desc)
115 return E_POINTER;
117 if ((hr = stream_get_chunk(stream, &riff)) != S_OK)
118 return hr;
119 if (riff.id != FOURCC_RIFF || riff.type != DMUS_FOURCC_CHORDMAP_FORM) {
120 TRACE("loading failed: unexpected %s\n", debugstr_chunk(&riff));
121 stream_skip_chunk(stream, &riff);
122 return DMUS_E_CHUNKNOTFOUND;
125 hr = dmobj_parsedescriptor(stream, &riff, desc, DMUS_OBJ_OBJECT);
126 if (FAILED(hr))
127 return hr;
129 desc->guidClass = CLSID_DirectMusicChordMap;
130 desc->dwValidData |= DMUS_OBJ_CLASS;
132 TRACE("returning descriptor:\n%s\n", debugstr_DMUS_OBJECTDESC (desc));
133 return S_OK;
136 static const IDirectMusicObjectVtbl dmobject_vtbl = {
137 dmobj_IDirectMusicObject_QueryInterface,
138 dmobj_IDirectMusicObject_AddRef,
139 dmobj_IDirectMusicObject_Release,
140 dmobj_IDirectMusicObject_GetDescriptor,
141 dmobj_IDirectMusicObject_SetDescriptor,
142 chord_IDirectMusicObject_ParseDescriptor
145 /* IDirectMusicChordMapImpl IPersistStream part: */
146 static inline IDirectMusicChordMapImpl *impl_from_IPersistStream(IPersistStream *iface)
148 return CONTAINING_RECORD(iface, IDirectMusicChordMapImpl, dmobj.IPersistStream_iface);
151 static HRESULT WINAPI IPersistStreamImpl_Load(IPersistStream *iface, IStream *pStm)
153 IDirectMusicChordMapImpl *This = impl_from_IPersistStream(iface);
154 FOURCC chunkID;
155 DWORD chunkSize, StreamSize, StreamCount, ListSize[3], ListCount[3];
156 LARGE_INTEGER liMove; /* used when skipping chunks */
158 FIXME("(%p, %p): Loading not implemented yet\n", This, pStm);
159 IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
160 IStream_Read (pStm, &chunkSize, sizeof(DWORD), NULL);
161 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
162 switch (chunkID) {
163 case FOURCC_RIFF: {
164 IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
165 TRACE_(dmfile)(": RIFF chunk of type %s", debugstr_fourcc(chunkID));
166 StreamSize = chunkSize - sizeof(FOURCC);
167 StreamCount = 0;
168 switch (chunkID) {
169 case DMUS_FOURCC_CHORDMAP_FORM: {
170 TRACE_(dmfile)(": chordmap form\n");
171 do {
172 IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
173 IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
174 StreamCount += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
175 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
176 switch (chunkID) {
177 case DMUS_FOURCC_GUID_CHUNK: {
178 TRACE_(dmfile)(": GUID chunk\n");
179 This->dmobj.desc.dwValidData |= DMUS_OBJ_OBJECT;
180 IStream_Read (pStm, &This->dmobj.desc.guidObject, chunkSize, NULL);
181 break;
183 case DMUS_FOURCC_VERSION_CHUNK: {
184 TRACE_(dmfile)(": version chunk\n");
185 This->dmobj.desc.dwValidData |= DMUS_OBJ_VERSION;
186 IStream_Read (pStm, &This->dmobj.desc.vVersion, chunkSize, NULL);
187 break;
189 case DMUS_FOURCC_CATEGORY_CHUNK: {
190 TRACE_(dmfile)(": category chunk\n");
191 This->dmobj.desc.dwValidData |= DMUS_OBJ_CATEGORY;
192 IStream_Read (pStm, This->dmobj.desc.wszCategory, chunkSize, NULL);
193 break;
195 case FOURCC_LIST: {
196 IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
197 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(chunkID));
198 ListSize[0] = chunkSize - sizeof(FOURCC);
199 ListCount[0] = 0;
200 switch (chunkID) {
201 case DMUS_FOURCC_UNFO_LIST: {
202 TRACE_(dmfile)(": UNFO list\n");
203 do {
204 IStream_Read (pStm, &chunkID, sizeof(FOURCC), NULL);
205 IStream_Read (pStm, &chunkSize, sizeof(FOURCC), NULL);
206 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + chunkSize;
207 TRACE_(dmfile)(": %s chunk (size = %d)", debugstr_fourcc (chunkID), chunkSize);
208 switch (chunkID) {
209 /* don't ask me why, but M$ puts INFO elements in UNFO list sometimes
210 (though strings seem to be valid unicode) */
211 case mmioFOURCC('I','N','A','M'):
212 case DMUS_FOURCC_UNAM_CHUNK: {
213 TRACE_(dmfile)(": name chunk\n");
214 This->dmobj.desc.dwValidData |= DMUS_OBJ_NAME;
215 IStream_Read (pStm, This->dmobj.desc.wszName, chunkSize, NULL);
216 break;
218 case mmioFOURCC('I','A','R','T'):
219 case DMUS_FOURCC_UART_CHUNK: {
220 TRACE_(dmfile)(": artist chunk (ignored)\n");
221 liMove.QuadPart = chunkSize;
222 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
223 break;
225 case mmioFOURCC('I','C','O','P'):
226 case DMUS_FOURCC_UCOP_CHUNK: {
227 TRACE_(dmfile)(": copyright chunk (ignored)\n");
228 liMove.QuadPart = chunkSize;
229 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
230 break;
232 case mmioFOURCC('I','S','B','J'):
233 case DMUS_FOURCC_USBJ_CHUNK: {
234 TRACE_(dmfile)(": subject chunk (ignored)\n");
235 liMove.QuadPart = chunkSize;
236 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
237 break;
239 case mmioFOURCC('I','C','M','T'):
240 case DMUS_FOURCC_UCMT_CHUNK: {
241 TRACE_(dmfile)(": comment chunk (ignored)\n");
242 liMove.QuadPart = chunkSize;
243 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
244 break;
246 default: {
247 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
248 liMove.QuadPart = chunkSize;
249 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
250 break;
253 TRACE_(dmfile)(": ListCount[0] = %d < ListSize[0] = %d\n", ListCount[0], ListSize[0]);
254 } while (ListCount[0] < ListSize[0]);
255 break;
257 default: {
258 TRACE_(dmfile)(": unknown (skipping)\n");
259 liMove.QuadPart = chunkSize - sizeof(FOURCC);
260 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
261 break;
264 break;
266 default: {
267 TRACE_(dmfile)(": unknown chunk (irrelevant & skipping)\n");
268 liMove.QuadPart = chunkSize;
269 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
270 break;
273 TRACE_(dmfile)(": StreamCount[0] = %d < StreamSize[0] = %d\n", StreamCount, StreamSize);
274 } while (StreamCount < StreamSize);
275 break;
277 default: {
278 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
279 liMove.QuadPart = StreamSize;
280 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
281 return E_FAIL;
284 TRACE_(dmfile)(": reading finished\n");
285 break;
287 default: {
288 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
289 liMove.QuadPart = chunkSize;
290 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
291 return E_FAIL;
295 return S_OK;
298 static const IPersistStreamVtbl persiststream_vtbl = {
299 dmobj_IPersistStream_QueryInterface,
300 dmobj_IPersistStream_AddRef,
301 dmobj_IPersistStream_Release,
302 dmobj_IPersistStream_GetClassID,
303 unimpl_IPersistStream_IsDirty,
304 IPersistStreamImpl_Load,
305 unimpl_IPersistStream_Save,
306 unimpl_IPersistStream_GetSizeMax
309 /* for ClassFactory */
310 HRESULT WINAPI create_dmchordmap(REFIID lpcGUID, void **ppobj)
312 IDirectMusicChordMapImpl* obj;
313 HRESULT hr;
315 obj = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicChordMapImpl));
316 if (NULL == obj) {
317 *ppobj = NULL;
318 return E_OUTOFMEMORY;
320 obj->IDirectMusicChordMap_iface.lpVtbl = &dmchordmap_vtbl;
321 obj->ref = 1;
322 dmobject_init(&obj->dmobj, &CLSID_DirectMusicChordMap,
323 (IUnknown *)&obj->IDirectMusicChordMap_iface);
324 obj->dmobj.IDirectMusicObject_iface.lpVtbl = &dmobject_vtbl;
325 obj->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl;
327 DMCOMPOS_LockModule();
328 hr = IDirectMusicChordMap_QueryInterface(&obj->IDirectMusicChordMap_iface, lpcGUID, ppobj);
329 IDirectMusicChordMap_Release(&obj->IDirectMusicChordMap_iface);
331 return hr;