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
);
68 static ULONG WINAPI
IDirectMusicInstrumentImpl_Release(LPDIRECTMUSICINSTRUMENT iface
)
70 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
71 ULONG ref
= InterlockedDecrement(&This
->ref
);
73 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
79 HeapFree(GetProcessHeap(), 0, This
->regions
);
80 for (i
= 0; i
< This
->nb_articulations
; i
++)
81 HeapFree(GetProcessHeap(), 0, This
->articulations
->connections
);
82 HeapFree(GetProcessHeap(), 0, This
->articulations
);
83 HeapFree(GetProcessHeap(), 0, This
);
84 DMUSIC_UnlockModule();
90 /* IDirectMusicInstrumentImpl IDirectMusicInstrument part: */
91 static HRESULT WINAPI
IDirectMusicInstrumentImpl_GetPatch(LPDIRECTMUSICINSTRUMENT iface
, DWORD
* pdwPatch
)
93 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
95 TRACE("(%p)->(%p)\n", This
, pdwPatch
);
97 *pdwPatch
= MIDILOCALE2Patch(&This
->header
.Locale
);
102 static HRESULT WINAPI
IDirectMusicInstrumentImpl_SetPatch(LPDIRECTMUSICINSTRUMENT iface
, DWORD dwPatch
)
104 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
106 TRACE("(%p)->(%d): stub\n", This
, dwPatch
);
108 Patch2MIDILOCALE(dwPatch
, &This
->header
.Locale
);
113 static const IDirectMusicInstrumentVtbl DirectMusicInstrument_Vtbl
=
115 IDirectMusicInstrumentImpl_QueryInterface
,
116 IDirectMusicInstrumentImpl_AddRef
,
117 IDirectMusicInstrumentImpl_Release
,
118 IDirectMusicInstrumentImpl_GetPatch
,
119 IDirectMusicInstrumentImpl_SetPatch
122 /* for ClassFactory */
123 HRESULT
DMUSIC_CreateDirectMusicInstrumentImpl (LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
) {
124 IDirectMusicInstrumentImpl
* dminst
;
127 dminst
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicInstrumentImpl
));
128 if (NULL
== dminst
) {
130 return E_OUTOFMEMORY
;
132 dminst
->IDirectMusicInstrument_iface
.lpVtbl
= &DirectMusicInstrument_Vtbl
;
136 hr
= IDirectMusicInstrument_QueryInterface(&dminst
->IDirectMusicInstrument_iface
, lpcGUID
,
138 IDirectMusicInstrument_Release(&dminst
->IDirectMusicInstrument_iface
);
143 static HRESULT
read_from_stream(IStream
*stream
, void *data
, ULONG size
)
148 hr
= IStream_Read(stream
, data
, size
, &bytes_read
);
150 TRACE("IStream_Read failed: %08x\n", hr
);
153 if (bytes_read
< size
) {
154 TRACE("Didn't read full chunk: %u < %u\n", bytes_read
, 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 inline HRESULT
advance_stream(IStream
*stream
, ULONG bytes
)
175 move
.QuadPart
= bytes
;
177 ret
= IStream_Seek(stream
, move
, STREAM_SEEK_CUR
, NULL
);
179 WARN("IStream_Seek failed: %08x\n", ret
);
184 static HRESULT
load_region(IDirectMusicInstrumentImpl
*This
, IStream
*stream
, instrument_region
*region
, ULONG length
)
187 DMUS_PRIVATE_CHUNK chunk
;
189 TRACE("(%p, %p, %p, %u)\n", This
, stream
, region
, length
);
193 ret
= read_from_stream(stream
, &chunk
, sizeof(chunk
));
197 length
= subtract_bytes(length
, sizeof(chunk
));
202 TRACE("RGNH chunk (region header): %u bytes\n", chunk
.dwSize
);
204 ret
= read_from_stream(stream
, ®ion
->header
, sizeof(region
->header
));
208 length
= subtract_bytes(length
, sizeof(region
->header
));
212 TRACE("WSMP chunk (wave sample): %u bytes\n", chunk
.dwSize
);
214 ret
= read_from_stream(stream
, ®ion
->wave_sample
, sizeof(region
->wave_sample
));
217 length
= subtract_bytes(length
, sizeof(region
->wave_sample
));
219 if (!(region
->loop_present
= (chunk
.dwSize
!= sizeof(region
->wave_sample
))))
222 ret
= read_from_stream(stream
, ®ion
->wave_loop
, sizeof(region
->wave_loop
));
226 length
= subtract_bytes(length
, sizeof(region
->wave_loop
));
230 TRACE("WLNK chunk (wave link): %u bytes\n", chunk
.dwSize
);
232 ret
= read_from_stream(stream
, ®ion
->wave_link
, sizeof(region
->wave_link
));
236 length
= subtract_bytes(length
, sizeof(region
->wave_link
));
240 TRACE("Unknown chunk %s (skipping): %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
242 ret
= advance_stream(stream
, chunk
.dwSize
);
246 length
= subtract_bytes(length
, chunk
.dwSize
);
254 static HRESULT
load_articulation(IDirectMusicInstrumentImpl
*This
, IStream
*stream
, ULONG length
)
257 instrument_articulation
*articulation
;
259 if (!This
->articulations
)
260 This
->articulations
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
->articulations
));
262 This
->articulations
= HeapReAlloc(GetProcessHeap(), 0, This
->articulations
, sizeof(*This
->articulations
) * (This
->nb_articulations
+ 1));
263 if (!This
->articulations
)
264 return E_OUTOFMEMORY
;
266 articulation
= &This
->articulations
[This
->nb_articulations
];
268 ret
= read_from_stream(stream
, &articulation
->connections_list
, sizeof(CONNECTIONLIST
));
272 articulation
->connections
= HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTION
) * articulation
->connections_list
.cConnections
);
273 if (!articulation
->connections
)
274 return E_OUTOFMEMORY
;
276 ret
= read_from_stream(stream
, articulation
->connections
, sizeof(CONNECTION
) * articulation
->connections_list
.cConnections
);
279 HeapFree(GetProcessHeap(), 0, articulation
->connections
);
283 subtract_bytes(length
, sizeof(CONNECTIONLIST
) + sizeof(CONNECTION
) * articulation
->connections_list
.cConnections
);
285 This
->nb_articulations
++;
290 /* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */
291 HRESULT
IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument
*iface
, IStream
*stream
)
293 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
295 DMUS_PRIVATE_CHUNK chunk
;
297 ULONG length
= This
->length
;
299 TRACE("(%p, %p): offset = 0x%s, length = %u)\n", This
, stream
, wine_dbgstr_longlong(This
->liInstrumentPosition
.QuadPart
), This
->length
);
304 hr
= IStream_Seek(stream
, This
->liInstrumentPosition
, STREAM_SEEK_SET
, NULL
);
307 WARN("IStream_Seek failed: %08x\n", hr
);
308 return DMUS_E_UNSUPPORTED_STREAM
;
311 This
->regions
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
->regions
) * This
->header
.cRegions
);
313 return E_OUTOFMEMORY
;
317 hr
= read_from_stream(stream
, &chunk
, sizeof(chunk
));
321 length
= subtract_bytes(length
, sizeof(chunk
) + chunk
.dwSize
);
327 TRACE("Chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
329 /* Instrument header and id are already set so just skip */
330 hr
= advance_stream(stream
, chunk
.dwSize
);
337 DWORD size
= chunk
.dwSize
;
339 TRACE("LIST chunk: %u bytes\n", chunk
.dwSize
);
341 hr
= read_from_stream(stream
, &chunk
.fccID
, sizeof(chunk
.fccID
));
345 size
= subtract_bytes(size
, sizeof(chunk
.fccID
));
350 TRACE("LRGN chunk (regions list): %u bytes\n", size
);
354 hr
= read_from_stream(stream
, &chunk
, sizeof(chunk
));
358 if (chunk
.fccID
!= FOURCC_LIST
)
360 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
364 hr
= read_from_stream(stream
, &chunk
.fccID
, sizeof(chunk
.fccID
));
368 if (chunk
.fccID
== FOURCC_RGN
)
370 TRACE("RGN chunk (region): %u bytes\n", chunk
.dwSize
);
371 hr
= load_region(This
, stream
, &This
->regions
[i
++], chunk
.dwSize
- sizeof(chunk
.fccID
));
375 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
376 hr
= advance_stream(stream
, chunk
.dwSize
- sizeof(chunk
.fccID
));
381 size
= subtract_bytes(size
, chunk
.dwSize
+ sizeof(chunk
));
386 TRACE("LART chunk (articulations list): %u bytes\n", size
);
390 hr
= read_from_stream(stream
, &chunk
, sizeof(chunk
));
394 if (chunk
.fccID
== FOURCC_ART1
)
396 TRACE("ART1 chunk (level 1 articulation): %u bytes\n", chunk
.dwSize
);
397 hr
= load_articulation(This
, stream
, chunk
.dwSize
);
401 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
402 hr
= advance_stream(stream
, chunk
.dwSize
);
407 size
= subtract_bytes(size
, chunk
.dwSize
+ sizeof(chunk
));
412 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
414 hr
= advance_stream(stream
, chunk
.dwSize
- sizeof(chunk
.fccID
));
418 size
= subtract_bytes(size
, chunk
.dwSize
- sizeof(chunk
.fccID
));
425 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
427 hr
= advance_stream(stream
, chunk
.dwSize
);
440 HeapFree(GetProcessHeap(), 0, This
->regions
);
441 This
->regions
= NULL
;
443 return DMUS_E_UNSUPPORTED_STREAM
;