Added EM_SCROLLCARET definition in include/richedit.h and handling in
[wine/gsoc_dplay.git] / dlls / dmusic / instrument.c
blobdd336add4a11a92af1d07a1fe81462467124abc8
1 /* IDirectMusicInstrument Implementation
3 * Copyright (C) 2003-2004 Rok Mandeljc
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (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
13 * GNU Library General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "dmusic_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
23 WINE_DECLARE_DEBUG_CHANNEL(dmfile);
25 const GUID IID_IDirectMusicInstrumentPRIVATE = {0xbcb20080,0xa40c,0x11d1,{0x86,0xbc,0x00,0xc0,0x4f,0xbf,0x8f,0xef}};
27 /* IDirectMusicInstrument IUnknown part: */
28 HRESULT WINAPI IDirectMusicInstrumentImpl_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
29 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, UnknownVtbl, iface);
30 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
32 if (IsEqualIID (riid, &IID_IUnknown)) {
33 *ppobj = (LPVOID)&This->UnknownVtbl;
34 IDirectMusicInstrumentImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
35 return S_OK;
36 } else if (IsEqualIID (riid, &IID_IDirectMusicInstrument)) {
37 *ppobj = (LPVOID)&This->InstrumentVtbl;
38 IDirectMusicInstrumentImpl_IDirectMusicInstrument_AddRef ((LPDIRECTMUSICINSTRUMENT)&This->InstrumentVtbl);
39 return S_OK;
40 } else if (IsEqualIID (riid, &IID_IDirectMusicInstrumentPRIVATE)) {
41 /* it seems to me that this interface is only basic IUnknown, without any
42 other inherited functions... *sigh* this is the worst scenario, since it means
43 that whoever calls it knows the layout of original implementation table and therefore
44 tries to get data by direct access... expect crashes */
45 FIXME("*sigh*... requested private/unspecified interface\n");
46 *ppobj = (LPVOID)&This->UnknownVtbl;
47 IDirectMusicInstrumentImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
48 return S_OK;
51 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
52 return E_NOINTERFACE;
55 ULONG WINAPI IDirectMusicInstrumentImpl_IUnknown_AddRef (LPUNKNOWN iface) {
56 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, UnknownVtbl, iface);
57 TRACE("(%p): AddRef from %ld\n", This, This->ref);
58 return ++(This->ref);
61 ULONG WINAPI IDirectMusicInstrumentImpl_IUnknown_Release (LPUNKNOWN iface) {
62 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, UnknownVtbl, iface);
63 ULONG ref = --This->ref;
64 TRACE("(%p): ReleaseRef to %ld\n", This, This->ref);
65 if (ref == 0) {
66 HeapFree(GetProcessHeap(), 0, This);
68 return ref;
71 ICOM_VTABLE(IUnknown) DirectMusicInstrument_Unknown_Vtbl = {
72 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
73 IDirectMusicInstrumentImpl_IUnknown_QueryInterface,
74 IDirectMusicInstrumentImpl_IUnknown_AddRef,
75 IDirectMusicInstrumentImpl_IUnknown_Release
78 /* IDirectMusicInstrumentImpl IDirectMusicInstrument part: */
79 HRESULT WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_QueryInterface (LPDIRECTMUSICINSTRUMENT iface, REFIID riid, LPVOID *ppobj) {
80 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
81 return IDirectMusicInstrumentImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
84 ULONG WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_AddRef (LPDIRECTMUSICINSTRUMENT iface) {
85 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
86 return IDirectMusicInstrumentImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
89 ULONG WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_Release (LPDIRECTMUSICINSTRUMENT iface) {
90 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
91 return IDirectMusicInstrumentImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
94 HRESULT WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_GetPatch (LPDIRECTMUSICINSTRUMENT iface, DWORD* pdwPatch) {
95 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
96 TRACE("(%p, %p)\n", This, pdwPatch);
97 *pdwPatch = MIDILOCALE2Patch(&This->pHeader->Locale);
98 return S_OK;
101 HRESULT WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_SetPatch (LPDIRECTMUSICINSTRUMENT iface, DWORD dwPatch) {
102 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
103 TRACE("(%p, %ld): stub\n", This, dwPatch);
104 Patch2MIDILOCALE(dwPatch, &This->pHeader->Locale);
105 return S_OK;
108 ICOM_VTABLE(IDirectMusicInstrument) DirectMusicInstrument_Instrument_Vtbl = {
109 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
110 IDirectMusicInstrumentImpl_IDirectMusicInstrument_QueryInterface,
111 IDirectMusicInstrumentImpl_IDirectMusicInstrument_AddRef,
112 IDirectMusicInstrumentImpl_IDirectMusicInstrument_Release,
113 IDirectMusicInstrumentImpl_IDirectMusicInstrument_GetPatch,
114 IDirectMusicInstrumentImpl_IDirectMusicInstrument_SetPatch
117 /* for ClassFactory */
118 HRESULT WINAPI DMUSIC_CreateDirectMusicInstrumentImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter) {
119 IDirectMusicInstrumentImpl* dminst;
121 dminst = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicInstrumentImpl));
122 if (NULL == dminst) {
123 *ppobj = (LPVOID) NULL;
124 return E_OUTOFMEMORY;
126 dminst->UnknownVtbl = &DirectMusicInstrument_Unknown_Vtbl;
127 dminst->InstrumentVtbl = &DirectMusicInstrument_Instrument_Vtbl;
128 dminst->ref = 0; /* will be inited by QueryInterface */
130 return IDirectMusicInstrumentImpl_IUnknown_QueryInterface ((LPUNKNOWN)&dminst->UnknownVtbl, lpcGUID, ppobj);
133 /* aux. function that completely loads instrument; my tests indicate that it's
134 called somewhere around IDirectMusicCollection_GetInstrument */
135 HRESULT WINAPI IDirectMusicInstrumentImpl_Custom_Load (LPDIRECTMUSICINSTRUMENT iface, LPSTREAM pStm) {
136 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
138 DMUS_PRIVATE_CHUNK Chunk;
139 DWORD ListSize[4], ListCount[4];
140 LARGE_INTEGER liMove; /* used when skipping chunks */
142 TRACE("(%p, %p, offset = 0x%04llx)\n", This, pStm, This->liInstrumentPosition.QuadPart);
144 /* goto the beginning of chunk */
145 IStream_Seek (pStm, This->liInstrumentPosition, STREAM_SEEK_SET, NULL);
147 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
148 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
149 switch (Chunk.fccID) {
150 case FOURCC_LIST: {
151 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
152 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
153 ListSize[0] = Chunk.dwSize - sizeof(FOURCC);
154 ListCount[0] = 0;
155 switch (Chunk.fccID) {
156 case FOURCC_INS: {
157 TRACE_(dmfile)(": instrument list\n");
158 do {
159 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
160 ListCount[0] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
161 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
162 switch (Chunk.fccID) {
163 case FOURCC_INSH: {
164 TRACE_(dmfile)(": instrument header chunk\n");
165 /* should be already initialised */
166 IStream_Read (pStm, This->pHeader, Chunk.dwSize, NULL);
167 break;
169 case FOURCC_DLID: {
170 TRACE_(dmfile)(": DLID (GUID) chunk\n");
171 /* should be already initialised */
172 IStream_Read (pStm, This->pInstrumentID, Chunk.dwSize, NULL);
173 break;
175 case FOURCC_LIST: {
176 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
177 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
178 ListSize[1] = Chunk.dwSize - sizeof(FOURCC);
179 ListCount[1] = 0;
180 switch (Chunk.fccID) {
181 case FOURCC_LRGN: {
182 TRACE_(dmfile)(": regions list\n");
183 do {
184 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
185 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
186 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
187 switch (Chunk.fccID) {
188 case FOURCC_LIST: {
189 IStream_Read (pStm, &Chunk.fccID, sizeof(FOURCC), NULL);
190 TRACE_(dmfile)(": LIST chunk of type %s", debugstr_fourcc(Chunk.fccID));
191 ListSize[2] = Chunk.dwSize - sizeof(FOURCC);
192 ListCount[2] = 0;
193 switch (Chunk.fccID) {
194 case FOURCC_RGN: {
195 /* temporary structures */
196 RGNHEADER tmpRegionHeader;
197 WSMPL tmpWaveSample;
198 WLOOP tmpWaveLoop;
199 WAVELINK tmpWaveLink;
201 TRACE_(dmfile)(": region list\n");
202 do {
203 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
204 ListCount[2] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
205 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
206 switch (Chunk.fccID) {
207 case FOURCC_RGNH: {
208 TRACE_(dmfile)(": region header chunk\n");
209 memset (&tmpRegionHeader, 0, sizeof(RGNHEADER)); /* reset */
210 IStream_Read (pStm, &tmpRegionHeader, Chunk.dwSize, NULL);
211 break;
213 case FOURCC_WSMP: {
214 TRACE_(dmfile)(": wave sample chunk\n");
215 memset (&tmpWaveSample, 0, sizeof(WSMPL)); /* reset */
216 memset (&tmpWaveLoop, 0, sizeof(WLOOP)); /* reset */
217 if (Chunk.dwSize != (sizeof(WSMPL) + sizeof(WLOOP))) ERR(": incorrect chunk size\n");
218 IStream_Read (pStm, &tmpWaveSample, sizeof(WSMPL), NULL);
219 IStream_Read (pStm, &tmpWaveLoop, sizeof(WLOOP), NULL);
220 break;
222 case FOURCC_WLNK: {
223 TRACE_(dmfile)(": wave link chunk\n");
224 memset (&tmpWaveLink, 0, sizeof(WAVELINK)); /* reset */
225 IStream_Read (pStm, &tmpWaveLink, Chunk.dwSize, NULL);
226 break;
228 default: {
229 TRACE_(dmfile)(": unknown (skipping)\n");
230 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
231 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
232 break;
235 TRACE_(dmfile)(": ListCount[2] = %ld < ListSize[2] = %ld\n", ListCount[2], ListSize[2]);
236 } while (ListCount[2] < ListSize[2]);
237 FIXME(": need to write temporary data to instrument data\n");
238 break;
240 default: {
241 TRACE_(dmfile)(": unknown (skipping)\n");
242 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
243 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
244 break;
247 break;
249 default: {
250 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
251 liMove.QuadPart = Chunk.dwSize;
252 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
253 break;
256 TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
257 } while (ListCount[1] < ListSize[1]);
258 break;
260 case FOURCC_LART: {
261 TRACE_(dmfile)(": articulators list\n");
262 do {
263 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
264 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
265 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
266 switch (Chunk.fccID) {
267 case FOURCC_ART1: {
268 /* temporary structures */
269 CONNECTIONLIST tmpConnectionList;
270 LPCONNECTION tmpConnections;
272 TRACE_(dmfile)(": level 1 articulator chunk\n");
273 memset (&tmpConnectionList, 0, sizeof(CONNECTIONLIST)); /* reset */
274 tmpConnections = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(CONNECTION)*tmpConnectionList.cConnections);
275 if (Chunk.dwSize != (sizeof(CONNECTIONLIST) + sizeof(CONNECTION)*tmpConnectionList.cConnections)) ERR(": incorrect chunk size\n");
276 IStream_Read (pStm, &tmpConnectionList, sizeof(CONNECTIONLIST), NULL);
277 IStream_Read (pStm, tmpConnections, sizeof(CONNECTION)*tmpConnectionList.cConnections, NULL);
278 break;
280 default: {
281 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
282 liMove.QuadPart = Chunk.dwSize;
283 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
284 break;
287 TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
288 } while (ListCount[1] < ListSize[1]);
289 break;
291 case mmioFOURCC('I','N','F','O'): {
292 TRACE_(dmfile)(": INFO list\n");
293 do {
294 IStream_Read (pStm, &Chunk, sizeof(FOURCC)+sizeof(DWORD), NULL);
295 ListCount[1] += sizeof(FOURCC) + sizeof(DWORD) + Chunk.dwSize;
296 TRACE_(dmfile)(": %s chunk (size = 0x%04lx)", debugstr_fourcc (Chunk.fccID), Chunk.dwSize);
297 switch (Chunk.fccID) {
298 case mmioFOURCC('I','N','A','M'): {
299 TRACE_(dmfile)(": name chunk (ignored)\n");
300 if (even_or_odd(Chunk.dwSize)) {
301 ListCount[1] ++;
302 Chunk.dwSize++;
304 liMove.QuadPart = Chunk.dwSize;
305 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
306 break;
308 case mmioFOURCC('I','A','R','T'): {
309 TRACE_(dmfile)(": artist chunk (ignored)\n");
310 if (even_or_odd(Chunk.dwSize)) {
311 ListCount[1] ++;
312 Chunk.dwSize++;
314 liMove.QuadPart = Chunk.dwSize;
315 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
316 break;
318 case mmioFOURCC('I','C','O','P'): {
319 /* temporary structures */
320 CHAR tmpCopyright[DMUS_MAX_NAME];
322 TRACE_(dmfile)(": copyright chunk\n");
323 IStream_Read (pStm, tmpCopyright, Chunk.dwSize, NULL);
324 if (even_or_odd(Chunk.dwSize)) {
325 ListCount[1] ++;
326 liMove.QuadPart = 1;
327 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
329 break;
331 case mmioFOURCC('I','S','B','J'): {
332 TRACE_(dmfile)(": subject chunk (ignored)\n");
333 if (even_or_odd(Chunk.dwSize)) {
334 ListCount[1] ++;
335 Chunk.dwSize++;
337 liMove.QuadPart = Chunk.dwSize;
338 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
339 break;
341 case mmioFOURCC('I','C','M','T'): {
342 TRACE_(dmfile)(": comment chunk (ignored)\n");
343 if (even_or_odd(Chunk.dwSize)) {
344 ListCount[1] ++;
345 Chunk.dwSize++;
347 liMove.QuadPart = Chunk.dwSize;
348 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
349 break;
351 default: {
352 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
353 if (even_or_odd(Chunk.dwSize)) {
354 ListCount[1] ++;
355 Chunk.dwSize++;
357 liMove.QuadPart = Chunk.dwSize;
358 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
359 break;
362 TRACE_(dmfile)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount[1], ListSize[1]);
363 } while (ListCount[1] < ListSize[1]);
364 break;
367 default: {
368 TRACE_(dmfile)(": unknown (skipping)\n");
369 liMove.QuadPart = Chunk.dwSize - sizeof(FOURCC);
370 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
371 break;
374 break;
376 default: {
377 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
378 liMove.QuadPart = Chunk.dwSize;
379 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
380 break;
383 TRACE_(dmfile)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount[0], ListSize[0]);
384 } while (ListCount[0] < ListSize[0]);
385 break;
387 default: {
388 TRACE_(dmfile)(": unknown chunk (irrevelant & skipping)\n");
389 liMove.QuadPart = Chunk.dwSize;
390 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL);
391 break;
394 break;
396 default: {
397 TRACE_(dmfile)(": unexpected chunk; loading failed)\n");
398 liMove.QuadPart = Chunk.dwSize;
399 IStream_Seek (pStm, liMove, STREAM_SEEK_CUR, NULL); /* skip the rest of the chunk */
400 return E_FAIL;
403 /* DEBUG: dumps whole instrument object tree: */
404 /* if (TRACE_ON(dmusic)) {
405 TRACE("*** IDirectMusicInstrument (%p) ***\n", This);
406 if (This->pInstrumentID)
407 TRACE(" - GUID = %s\n", debugstr_dmguid(This->pInstrumentID));
409 TRACE(" - Instrument header:\n");
410 TRACE(" - cRegions: %ld\n", This->pHeader->cRegions);
411 TRACE(" - Locale:\n");
412 TRACE(" - ulBank: %ld\n", This->pHeader->Locale.ulBank);
413 TRACE(" - ulInstrument: %ld\n", This->pHeader->Locale.ulInstrument);
414 TRACE(" => dwPatch: %ld\n", MIDILOCALE2Patch(&This->pHeader->Locale));
417 return S_OK;