1 /* IDirectMusicInstrument 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 "dmusic_private.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(dmusic);
24 static const GUID IID_IDirectMusicInstrumentPRIVATE = {0xbcb20080,0xa40c,0x11d1,{0x86,0xbc,0x00,0xc0,0x4f,0xbf,0x8f,0xef}};
26 static ULONG WINAPI IDirectMusicInstrumentImpl_IUnknown_AddRef (LPUNKNOWN iface);
27 static ULONG WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_AddRef (LPDIRECTMUSICINSTRUMENT iface);
29 /* IDirectMusicInstrument IUnknown part: */
30 static HRESULT WINAPI IDirectMusicInstrumentImpl_IUnknown_QueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID *ppobj) {
31 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, UnknownVtbl, iface);
32 TRACE("(%p, %s, %p)\n", This, debugstr_dmguid(riid), ppobj);
34 if (IsEqualIID (riid, &IID_IUnknown)) {
35 *ppobj = &This->UnknownVtbl;
36 IDirectMusicInstrumentImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
38 } else if (IsEqualIID (riid, &IID_IDirectMusicInstrument)) {
39 *ppobj = &This->InstrumentVtbl;
40 IDirectMusicInstrumentImpl_IDirectMusicInstrument_AddRef ((LPDIRECTMUSICINSTRUMENT)&This->InstrumentVtbl);
42 } else if (IsEqualIID (riid, &IID_IDirectMusicInstrumentPRIVATE)) {
43 /* it seems to me that this interface is only basic IUnknown, without any
44 other inherited functions... *sigh* this is the worst scenario, since it means
45 that whoever calls it knows the layout of original implementation table and therefore
46 tries to get data by direct access... expect crashes */
47 FIXME("*sigh*... requested private/unspecified interface\n");
48 *ppobj = &This->UnknownVtbl;
49 IDirectMusicInstrumentImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
53 WARN("(%p, %s, %p): not found\n", This, debugstr_dmguid(riid), ppobj);
57 static ULONG WINAPI IDirectMusicInstrumentImpl_IUnknown_AddRef (LPUNKNOWN iface) {
58 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, UnknownVtbl, iface);
59 ULONG refCount = InterlockedIncrement(&This->ref);
61 TRACE("(%p)->(ref before=%u)\n", This, refCount - 1);
68 static ULONG WINAPI IDirectMusicInstrumentImpl_IUnknown_Release (LPUNKNOWN iface) {
69 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, UnknownVtbl, iface);
70 ULONG refCount = InterlockedDecrement(&This->ref);
72 TRACE("(%p)->(ref before=%u)\n", This, refCount + 1);
75 HeapFree(GetProcessHeap(), 0, This);
78 DMUSIC_UnlockModule();
83 static const IUnknownVtbl DirectMusicInstrument_Unknown_Vtbl = {
84 IDirectMusicInstrumentImpl_IUnknown_QueryInterface,
85 IDirectMusicInstrumentImpl_IUnknown_AddRef,
86 IDirectMusicInstrumentImpl_IUnknown_Release
89 /* IDirectMusicInstrumentImpl IDirectMusicInstrument part: */
90 static HRESULT WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_QueryInterface (LPDIRECTMUSICINSTRUMENT iface, REFIID riid, LPVOID *ppobj) {
91 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
92 return IDirectMusicInstrumentImpl_IUnknown_QueryInterface ((LPUNKNOWN)&This->UnknownVtbl, riid, ppobj);
95 static ULONG WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_AddRef (LPDIRECTMUSICINSTRUMENT iface) {
96 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
97 return IDirectMusicInstrumentImpl_IUnknown_AddRef ((LPUNKNOWN)&This->UnknownVtbl);
100 static ULONG WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_Release (LPDIRECTMUSICINSTRUMENT iface) {
101 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
102 return IDirectMusicInstrumentImpl_IUnknown_Release ((LPUNKNOWN)&This->UnknownVtbl);
105 static HRESULT WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_GetPatch (LPDIRECTMUSICINSTRUMENT iface, DWORD* pdwPatch) {
106 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
107 TRACE("(%p, %p)\n", This, pdwPatch);
108 *pdwPatch = MIDILOCALE2Patch(&This->pHeader->Locale);
112 static HRESULT WINAPI IDirectMusicInstrumentImpl_IDirectMusicInstrument_SetPatch (LPDIRECTMUSICINSTRUMENT iface, DWORD dwPatch) {
113 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
114 TRACE("(%p, %d): stub\n", This, dwPatch);
115 Patch2MIDILOCALE(dwPatch, &This->pHeader->Locale);
119 static const IDirectMusicInstrumentVtbl DirectMusicInstrument_Instrument_Vtbl = {
120 IDirectMusicInstrumentImpl_IDirectMusicInstrument_QueryInterface,
121 IDirectMusicInstrumentImpl_IDirectMusicInstrument_AddRef,
122 IDirectMusicInstrumentImpl_IDirectMusicInstrument_Release,
123 IDirectMusicInstrumentImpl_IDirectMusicInstrument_GetPatch,
124 IDirectMusicInstrumentImpl_IDirectMusicInstrument_SetPatch
127 /* for ClassFactory */
128 HRESULT WINAPI DMUSIC_CreateDirectMusicInstrumentImpl (LPCGUID lpcGUID, LPVOID* ppobj, LPUNKNOWN pUnkOuter) {
129 IDirectMusicInstrumentImpl* dminst;
131 dminst = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectMusicInstrumentImpl));
132 if (NULL == dminst) {
134 return E_OUTOFMEMORY;
136 dminst->UnknownVtbl = &DirectMusicInstrument_Unknown_Vtbl;
137 dminst->InstrumentVtbl = &DirectMusicInstrument_Instrument_Vtbl;
138 dminst->ref = 0; /* will be inited by QueryInterface */
140 return IDirectMusicInstrumentImpl_IUnknown_QueryInterface ((LPUNKNOWN)&dminst->UnknownVtbl, lpcGUID, ppobj);
143 static HRESULT read_from_stream(IStream *stream, void *data, ULONG size)
148 hr = IStream_Read(stream, data, size, &readed);
150 TRACE("IStream_Read failed: %08x\n", hr);
154 TRACE("Didn't read full chunk: %u < %u\n", readed, size);
161 static inline DWORD subtract_bytes(DWORD len, DWORD bytes)
164 TRACE("Apparent mismatch in chunk lengths? %u bytes remaining, %u bytes read\n", len, bytes);
170 static HRESULT load_instrument(IDirectMusicInstrumentImpl *This, IStream *stream, DWORD length)
178 hr = read_from_stream(stream, &fourcc, sizeof(fourcc));
182 hr = read_from_stream(stream, &bytes, sizeof(bytes));
186 length = subtract_bytes(length, sizeof(fourcc) + sizeof(bytes));
190 TRACE("INSH chunk: %u bytes\n", bytes);
191 hr = read_from_stream(stream, This->pHeader, sizeof(*This->pHeader));
195 move.QuadPart = bytes - sizeof(*This->pHeader);
196 hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, NULL);
198 WARN("IStream_Seek failed: %08x\n", hr);
202 length = subtract_bytes(length, bytes);
206 TRACE("DLID chunk: %u bytes\n", bytes);
207 hr = read_from_stream(stream, This->pInstrumentID, sizeof(*This->pInstrumentID));
211 move.QuadPart = bytes - sizeof(*This->pInstrumentID);
212 hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, NULL);
214 WARN("IStream_Seek failed: %08x\n", hr);
218 length = subtract_bytes(length, bytes);
222 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(fourcc), bytes);
224 move.QuadPart = bytes;
225 hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, NULL);
227 WARN("IStream_Seek failed: %08x\n", hr);
231 length = subtract_bytes(length, bytes);
239 /* aux. function that completely loads instrument; my tests indicate that it's
240 called somewhere around IDirectMusicCollection_GetInstrument */
241 HRESULT WINAPI IDirectMusicInstrumentImpl_Custom_Load (LPDIRECTMUSICINSTRUMENT iface, LPSTREAM stream)
243 ICOM_THIS_MULTI(IDirectMusicInstrumentImpl, InstrumentVtbl, iface);
249 TRACE("(%p, %p, offset = %s)\n", This, stream, wine_dbgstr_longlong(This->liInstrumentPosition.QuadPart));
251 hr = IStream_Seek(stream, This->liInstrumentPosition, STREAM_SEEK_SET, NULL);
253 WARN("IStream_Seek failed: %08x\n", hr);
257 hr = read_from_stream(stream, &fourcc, sizeof(fourcc));
261 if(fourcc != FOURCC_LIST){
262 WARN("Loading failed: Expected LIST chunk, got: %s\n", debugstr_fourcc(fourcc));
266 hr = read_from_stream(stream, &bytes, sizeof(bytes));
270 TRACE("LIST chunk: %u bytes\n", bytes);
272 hr = read_from_stream(stream, &fourcc, sizeof(fourcc));
278 TRACE("INS chunk: (no byte count)\n");
279 hr = load_instrument(This, stream, bytes - sizeof(FOURCC));
285 hr = read_from_stream(stream, &bytes, sizeof(bytes));
289 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(fourcc), bytes);
291 move.QuadPart = bytes;
292 hr = IStream_Seek(stream, move, STREAM_SEEK_CUR, NULL);
294 WARN("IStream_Seek failed: %08x\n", hr);
305 return DMUS_E_UNSUPPORTED_STREAM;