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
);
36 } else if (IsEqualIID (riid
, &IID_IDirectMusicInstrument
)) {
37 *ppobj
= (LPVOID
)&This
->InstrumentVtbl
;
38 IDirectMusicInstrumentImpl_IDirectMusicInstrument_AddRef ((LPDIRECTMUSICINSTRUMENT
)&This
->InstrumentVtbl
);
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
);
51 WARN("(%p, %s, %p): not found\n", This
, debugstr_dmguid(riid
), ppobj
);
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
);
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
);
66 HeapFree(GetProcessHeap(), 0, This
);
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
);
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
);
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
) {
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
);
155 switch (Chunk
.fccID
) {
157 TRACE_(dmfile
)(": instrument list\n");
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
) {
164 TRACE_(dmfile
)(": instrument header chunk\n");
165 /* should be already initialised */
166 IStream_Read (pStm
, This
->pHeader
, Chunk
.dwSize
, NULL
);
170 TRACE_(dmfile
)(": DLID (GUID) chunk\n");
171 /* should be already initialised */
172 IStream_Read (pStm
, This
->pInstrumentID
, Chunk
.dwSize
, NULL
);
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
);
180 switch (Chunk
.fccID
) {
182 TRACE_(dmfile
)(": regions list\n");
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
) {
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
);
193 switch (Chunk
.fccID
) {
195 /* temporary structures */
196 RGNHEADER tmpRegionHeader
;
199 WAVELINK tmpWaveLink
;
201 TRACE_(dmfile
)(": region list\n");
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
) {
208 TRACE_(dmfile
)(": region header chunk\n");
209 memset (&tmpRegionHeader
, 0, sizeof(RGNHEADER
)); /* reset */
210 IStream_Read (pStm
, &tmpRegionHeader
, Chunk
.dwSize
, NULL
);
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
);
223 TRACE_(dmfile
)(": wave link chunk\n");
224 memset (&tmpWaveLink
, 0, sizeof(WAVELINK
)); /* reset */
225 IStream_Read (pStm
, &tmpWaveLink
, Chunk
.dwSize
, NULL
);
229 TRACE_(dmfile
)(": unknown (skipping)\n");
230 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
231 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
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");
241 TRACE_(dmfile
)(": unknown (skipping)\n");
242 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
243 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
250 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
251 liMove
.QuadPart
= Chunk
.dwSize
;
252 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
256 TRACE_(dmfile
)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount
[1], ListSize
[1]);
257 } while (ListCount
[1] < ListSize
[1]);
261 TRACE_(dmfile
)(": articulators list\n");
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
) {
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
);
281 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
282 liMove
.QuadPart
= Chunk
.dwSize
;
283 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
287 TRACE_(dmfile
)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount
[1], ListSize
[1]);
288 } while (ListCount
[1] < ListSize
[1]);
291 case mmioFOURCC('I','N','F','O'): {
292 TRACE_(dmfile
)(": INFO list\n");
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
)) {
304 liMove
.QuadPart
= Chunk
.dwSize
;
305 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
308 case mmioFOURCC('I','A','R','T'): {
309 TRACE_(dmfile
)(": artist chunk (ignored)\n");
310 if (even_or_odd(Chunk
.dwSize
)) {
314 liMove
.QuadPart
= Chunk
.dwSize
;
315 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
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
)) {
327 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
331 case mmioFOURCC('I','S','B','J'): {
332 TRACE_(dmfile
)(": subject chunk (ignored)\n");
333 if (even_or_odd(Chunk
.dwSize
)) {
337 liMove
.QuadPart
= Chunk
.dwSize
;
338 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
341 case mmioFOURCC('I','C','M','T'): {
342 TRACE_(dmfile
)(": comment chunk (ignored)\n");
343 if (even_or_odd(Chunk
.dwSize
)) {
347 liMove
.QuadPart
= Chunk
.dwSize
;
348 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
352 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
353 if (even_or_odd(Chunk
.dwSize
)) {
357 liMove
.QuadPart
= Chunk
.dwSize
;
358 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
362 TRACE_(dmfile
)(": ListCount[1] = %ld < ListSize[1] = %ld\n", ListCount
[1], ListSize
[1]);
363 } while (ListCount
[1] < ListSize
[1]);
368 TRACE_(dmfile
)(": unknown (skipping)\n");
369 liMove
.QuadPart
= Chunk
.dwSize
- sizeof(FOURCC
);
370 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
377 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
378 liMove
.QuadPart
= Chunk
.dwSize
;
379 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
383 TRACE_(dmfile
)(": ListCount[0] = %ld < ListSize[0] = %ld\n", ListCount
[0], ListSize
[0]);
384 } while (ListCount
[0] < ListSize
[0]);
388 TRACE_(dmfile
)(": unknown chunk (irrevelant & skipping)\n");
389 liMove
.QuadPart
= Chunk
.dwSize
;
390 IStream_Seek (pStm
, liMove
, STREAM_SEEK_CUR
, NULL
);
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 */
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));