2 * IDirectMusicInstrument Implementation
4 * Copyright (C) 2003-2004 Rok Mandeljc
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 "dmusic_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(dmusic
);
25 static const GUID IID_IDirectMusicInstrumentPRIVATE
= { 0xbcb20080, 0xa40c, 0x11d1, { 0x86, 0xbc, 0x00, 0xc0, 0x4f, 0xbf, 0x8f, 0xef } };
27 /* IDirectMusicInstrument IUnknown part: */
28 static HRESULT WINAPI
IDirectMusicInstrumentImpl_QueryInterface(LPDIRECTMUSICINSTRUMENT iface
, REFIID riid
, LPVOID
*ret_iface
)
30 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_dmguid(riid
), ret_iface
);
32 if (IsEqualIID(riid
, &IID_IUnknown
) ||
33 IsEqualIID(riid
, &IID_IDirectMusicInstrument
))
36 IDirectMusicInstrument_AddRef(iface
);
39 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
46 FIXME("*sigh*... requested private/unspecified interface\n");
49 IDirectMusicInstrument_AddRef(iface
);
53 WARN("(%p)->(%s, %p): not found\n", iface
, debugstr_dmguid(riid
), ret_iface
);
58 static ULONG WINAPI
IDirectMusicInstrumentImpl_AddRef(LPDIRECTMUSICINSTRUMENT iface
)
60 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
61 ULONG ref
= InterlockedIncrement(&This
->ref
);
63 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
70 static ULONG WINAPI
IDirectMusicInstrumentImpl_Release(LPDIRECTMUSICINSTRUMENT iface
)
72 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
73 ULONG ref
= InterlockedDecrement(&This
->ref
);
75 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
78 HeapFree(GetProcessHeap(), 0, This
);
80 DMUSIC_UnlockModule();
85 /* IDirectMusicInstrumentImpl IDirectMusicInstrument part: */
86 static HRESULT WINAPI
IDirectMusicInstrumentImpl_GetPatch(LPDIRECTMUSICINSTRUMENT iface
, DWORD
* pdwPatch
)
88 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
90 TRACE("(%p)->(%p)\n", This
, pdwPatch
);
92 *pdwPatch
= MIDILOCALE2Patch(&This
->pHeader
->Locale
);
97 static HRESULT WINAPI
IDirectMusicInstrumentImpl_SetPatch(LPDIRECTMUSICINSTRUMENT iface
, DWORD dwPatch
)
99 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
101 TRACE("(%p)->(%d): stub\n", This
, dwPatch
);
103 Patch2MIDILOCALE(dwPatch
, &This
->pHeader
->Locale
);
108 static const IDirectMusicInstrumentVtbl DirectMusicInstrument_Vtbl
=
110 IDirectMusicInstrumentImpl_QueryInterface
,
111 IDirectMusicInstrumentImpl_AddRef
,
112 IDirectMusicInstrumentImpl_Release
,
113 IDirectMusicInstrumentImpl_GetPatch
,
114 IDirectMusicInstrumentImpl_SetPatch
117 /* for ClassFactory */
118 HRESULT
DMUSIC_CreateDirectMusicInstrumentImpl (LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
) {
119 IDirectMusicInstrumentImpl
* dminst
;
121 dminst
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicInstrumentImpl
));
122 if (NULL
== dminst
) {
124 return E_OUTOFMEMORY
;
126 dminst
->IDirectMusicInstrument_iface
.lpVtbl
= &DirectMusicInstrument_Vtbl
;
127 dminst
->ref
= 0; /* will be inited by QueryInterface */
129 return IDirectMusicInstrument_QueryInterface(&dminst
->IDirectMusicInstrument_iface
, lpcGUID
, ppobj
);
132 static HRESULT
read_from_stream(IStream
*stream
, void *data
, ULONG size
)
137 hr
= IStream_Read(stream
, data
, size
, &bytes_read
);
139 TRACE("IStream_Read failed: %08x\n", hr
);
142 if (bytes_read
< size
) {
143 TRACE("Didn't read full chunk: %u < %u\n", bytes_read
, size
);
150 static inline DWORD
subtract_bytes(DWORD len
, DWORD bytes
)
153 TRACE("Apparent mismatch in chunk lengths? %u bytes remaining, %u bytes read\n", len
, bytes
);
159 static HRESULT
load_instrument(IDirectMusicInstrumentImpl
*This
, IStream
*stream
, DWORD length
)
167 hr
= read_from_stream(stream
, &fourcc
, sizeof(fourcc
));
171 hr
= read_from_stream(stream
, &bytes
, sizeof(bytes
));
175 length
= subtract_bytes(length
, sizeof(fourcc
) + sizeof(bytes
));
179 TRACE("INSH chunk: %u bytes\n", bytes
);
180 hr
= read_from_stream(stream
, This
->pHeader
, sizeof(*This
->pHeader
));
184 move
.QuadPart
= bytes
- sizeof(*This
->pHeader
);
185 hr
= IStream_Seek(stream
, move
, STREAM_SEEK_CUR
, NULL
);
187 WARN("IStream_Seek failed: %08x\n", hr
);
191 length
= subtract_bytes(length
, bytes
);
195 TRACE("DLID chunk: %u bytes\n", bytes
);
196 hr
= read_from_stream(stream
, This
->pInstrumentID
, sizeof(*This
->pInstrumentID
));
200 move
.QuadPart
= bytes
- sizeof(*This
->pInstrumentID
);
201 hr
= IStream_Seek(stream
, move
, STREAM_SEEK_CUR
, NULL
);
203 WARN("IStream_Seek failed: %08x\n", hr
);
207 length
= subtract_bytes(length
, bytes
);
211 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(fourcc
), bytes
);
213 move
.QuadPart
= bytes
;
214 hr
= IStream_Seek(stream
, move
, STREAM_SEEK_CUR
, NULL
);
216 WARN("IStream_Seek failed: %08x\n", hr
);
220 length
= subtract_bytes(length
, bytes
);
228 /* aux. function that completely loads instrument; my tests indicate that it's
229 called somewhere around IDirectMusicCollection_GetInstrument */
230 HRESULT
IDirectMusicInstrumentImpl_Custom_Load(LPDIRECTMUSICINSTRUMENT iface
, LPSTREAM stream
)
232 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
238 TRACE("(%p, %p, offset = %s)\n", This
, stream
, wine_dbgstr_longlong(This
->liInstrumentPosition
.QuadPart
));
240 hr
= IStream_Seek(stream
, This
->liInstrumentPosition
, STREAM_SEEK_SET
, NULL
);
242 WARN("IStream_Seek failed: %08x\n", hr
);
246 hr
= read_from_stream(stream
, &fourcc
, sizeof(fourcc
));
250 if(fourcc
!= FOURCC_LIST
){
251 WARN("Loading failed: Expected LIST chunk, got: %s\n", debugstr_fourcc(fourcc
));
255 hr
= read_from_stream(stream
, &bytes
, sizeof(bytes
));
259 TRACE("LIST chunk: %u bytes\n", bytes
);
261 hr
= read_from_stream(stream
, &fourcc
, sizeof(fourcc
));
267 TRACE("INS chunk: (no byte count)\n");
268 hr
= load_instrument(This
, stream
, bytes
- sizeof(FOURCC
));
274 hr
= read_from_stream(stream
, &bytes
, sizeof(bytes
));
278 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(fourcc
), bytes
);
280 move
.QuadPart
= bytes
;
281 hr
= IStream_Seek(stream
, move
, STREAM_SEEK_CUR
, NULL
);
283 WARN("IStream_Seek failed: %08x\n", hr
);
294 return DMUS_E_UNSUPPORTED_STREAM
;