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"
24 WINE_DEFAULT_DEBUG_CHANNEL(dmusic
);
26 static const GUID IID_IDirectMusicInstrumentPRIVATE
= { 0xbcb20080, 0xa40c, 0x11d1, { 0x86, 0xbc, 0x00, 0xc0, 0x4f, 0xbf, 0x8f, 0xef } };
28 /* IDirectMusicInstrument IUnknown part: */
29 static HRESULT WINAPI
IDirectMusicInstrumentImpl_QueryInterface(LPDIRECTMUSICINSTRUMENT iface
, REFIID riid
, LPVOID
*ret_iface
)
31 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_dmguid(riid
), ret_iface
);
33 if (IsEqualIID(riid
, &IID_IUnknown
) ||
34 IsEqualIID(riid
, &IID_IDirectMusicInstrument
))
37 IDirectMusicInstrument_AddRef(iface
);
40 else if (IsEqualIID(riid
, &IID_IDirectMusicInstrumentPRIVATE
))
42 /* it seems to me that this interface is only basic IUnknown, without any
43 * other inherited functions... *sigh* this is the worst scenario, since it means
44 * that whoever calls it knows the layout of original implementation table and therefore
45 * tries to get data by direct access... expect crashes
47 FIXME("*sigh*... requested private/unspecified interface\n");
50 IDirectMusicInstrument_AddRef(iface
);
54 WARN("(%p)->(%s, %p): not found\n", iface
, debugstr_dmguid(riid
), ret_iface
);
59 static ULONG WINAPI
IDirectMusicInstrumentImpl_AddRef(LPDIRECTMUSICINSTRUMENT iface
)
61 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
62 ULONG ref
= InterlockedIncrement(&This
->ref
);
64 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
69 static ULONG WINAPI
IDirectMusicInstrumentImpl_Release(LPDIRECTMUSICINSTRUMENT iface
)
71 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
72 ULONG ref
= InterlockedDecrement(&This
->ref
);
74 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
80 HeapFree(GetProcessHeap(), 0, This
->regions
);
81 for (i
= 0; i
< This
->nb_articulations
; i
++)
82 HeapFree(GetProcessHeap(), 0, This
->articulations
->connections
);
83 HeapFree(GetProcessHeap(), 0, This
->articulations
);
84 HeapFree(GetProcessHeap(), 0, This
);
85 DMUSIC_UnlockModule();
91 /* IDirectMusicInstrumentImpl IDirectMusicInstrument part: */
92 static HRESULT WINAPI
IDirectMusicInstrumentImpl_GetPatch(LPDIRECTMUSICINSTRUMENT iface
, DWORD
* pdwPatch
)
94 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
96 TRACE("(%p)->(%p)\n", This
, pdwPatch
);
98 *pdwPatch
= MIDILOCALE2Patch(&This
->header
.Locale
);
103 static HRESULT WINAPI
IDirectMusicInstrumentImpl_SetPatch(LPDIRECTMUSICINSTRUMENT iface
, DWORD dwPatch
)
105 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
107 TRACE("(%p)->(%d): stub\n", This
, dwPatch
);
109 Patch2MIDILOCALE(dwPatch
, &This
->header
.Locale
);
114 static const IDirectMusicInstrumentVtbl DirectMusicInstrument_Vtbl
=
116 IDirectMusicInstrumentImpl_QueryInterface
,
117 IDirectMusicInstrumentImpl_AddRef
,
118 IDirectMusicInstrumentImpl_Release
,
119 IDirectMusicInstrumentImpl_GetPatch
,
120 IDirectMusicInstrumentImpl_SetPatch
123 /* for ClassFactory */
124 HRESULT
DMUSIC_CreateDirectMusicInstrumentImpl (LPCGUID lpcGUID
, LPVOID
* ppobj
, LPUNKNOWN pUnkOuter
) {
125 IDirectMusicInstrumentImpl
* dminst
;
128 dminst
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicInstrumentImpl
));
129 if (NULL
== dminst
) {
131 return E_OUTOFMEMORY
;
133 dminst
->IDirectMusicInstrument_iface
.lpVtbl
= &DirectMusicInstrument_Vtbl
;
137 hr
= IDirectMusicInstrument_QueryInterface(&dminst
->IDirectMusicInstrument_iface
, lpcGUID
,
139 IDirectMusicInstrument_Release(&dminst
->IDirectMusicInstrument_iface
);
144 static HRESULT
read_from_stream(IStream
*stream
, void *data
, ULONG size
)
149 hr
= IStream_Read(stream
, data
, size
, &bytes_read
);
151 TRACE("IStream_Read failed: %08x\n", hr
);
154 if (bytes_read
< size
) {
155 TRACE("Didn't read full chunk: %u < %u\n", bytes_read
, size
);
162 static inline DWORD
subtract_bytes(DWORD len
, DWORD bytes
)
165 TRACE("Apparent mismatch in chunk lengths? %u bytes remaining, %u bytes read\n", len
, bytes
);
171 static inline HRESULT
advance_stream(IStream
*stream
, ULONG bytes
)
176 move
.QuadPart
= bytes
;
178 ret
= IStream_Seek(stream
, move
, STREAM_SEEK_CUR
, NULL
);
180 WARN("IStream_Seek failed: %08x\n", ret
);
185 static HRESULT
load_region(IDirectMusicInstrumentImpl
*This
, IStream
*stream
, instrument_region
*region
, ULONG length
)
188 DMUS_PRIVATE_CHUNK chunk
;
190 TRACE("(%p, %p, %p, %u)\n", This
, stream
, region
, length
);
194 ret
= read_from_stream(stream
, &chunk
, sizeof(chunk
));
198 length
= subtract_bytes(length
, sizeof(chunk
));
203 TRACE("RGNH chunk (region header): %u bytes\n", chunk
.dwSize
);
205 ret
= read_from_stream(stream
, ®ion
->header
, sizeof(region
->header
));
209 length
= subtract_bytes(length
, sizeof(region
->header
));
213 TRACE("WSMP chunk (wave sample): %u bytes\n", chunk
.dwSize
);
215 ret
= read_from_stream(stream
, ®ion
->wave_sample
, sizeof(region
->wave_sample
));
218 length
= subtract_bytes(length
, sizeof(region
->wave_sample
));
220 if (!(region
->loop_present
= (chunk
.dwSize
!= sizeof(region
->wave_sample
))))
223 ret
= read_from_stream(stream
, ®ion
->wave_loop
, sizeof(region
->wave_loop
));
227 length
= subtract_bytes(length
, sizeof(region
->wave_loop
));
231 TRACE("WLNK chunk (wave link): %u bytes\n", chunk
.dwSize
);
233 ret
= read_from_stream(stream
, ®ion
->wave_link
, sizeof(region
->wave_link
));
237 length
= subtract_bytes(length
, sizeof(region
->wave_link
));
241 TRACE("Unknown chunk %s (skipping): %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
243 ret
= advance_stream(stream
, chunk
.dwSize
);
247 length
= subtract_bytes(length
, chunk
.dwSize
);
255 static HRESULT
load_articulation(IDirectMusicInstrumentImpl
*This
, IStream
*stream
, ULONG length
)
258 instrument_articulation
*articulation
;
260 if (!This
->articulations
)
261 This
->articulations
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
->articulations
));
263 This
->articulations
= HeapReAlloc(GetProcessHeap(), 0, This
->articulations
, sizeof(*This
->articulations
) * (This
->nb_articulations
+ 1));
264 if (!This
->articulations
)
265 return E_OUTOFMEMORY
;
267 articulation
= &This
->articulations
[This
->nb_articulations
];
269 ret
= read_from_stream(stream
, &articulation
->connections_list
, sizeof(CONNECTIONLIST
));
273 articulation
->connections
= HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTION
) * articulation
->connections_list
.cConnections
);
274 if (!articulation
->connections
)
275 return E_OUTOFMEMORY
;
277 ret
= read_from_stream(stream
, articulation
->connections
, sizeof(CONNECTION
) * articulation
->connections_list
.cConnections
);
280 HeapFree(GetProcessHeap(), 0, articulation
->connections
);
284 subtract_bytes(length
, sizeof(CONNECTIONLIST
) + sizeof(CONNECTION
) * articulation
->connections_list
.cConnections
);
286 This
->nb_articulations
++;
291 /* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */
292 HRESULT
IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument
*iface
, IStream
*stream
)
294 IDirectMusicInstrumentImpl
*This
= impl_from_IDirectMusicInstrument(iface
);
296 DMUS_PRIVATE_CHUNK chunk
;
298 ULONG length
= This
->length
;
300 TRACE("(%p, %p): offset = 0x%s, length = %u)\n", This
, stream
, wine_dbgstr_longlong(This
->liInstrumentPosition
.QuadPart
), This
->length
);
305 hr
= IStream_Seek(stream
, This
->liInstrumentPosition
, STREAM_SEEK_SET
, NULL
);
308 WARN("IStream_Seek failed: %08x\n", hr
);
309 return DMUS_E_UNSUPPORTED_STREAM
;
312 This
->regions
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
->regions
) * This
->header
.cRegions
);
314 return E_OUTOFMEMORY
;
318 hr
= read_from_stream(stream
, &chunk
, sizeof(chunk
));
322 length
= subtract_bytes(length
, sizeof(chunk
) + chunk
.dwSize
);
328 TRACE("Chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
330 /* Instrument header and id are already set so just skip */
331 hr
= advance_stream(stream
, chunk
.dwSize
);
338 DWORD size
= chunk
.dwSize
;
340 TRACE("LIST chunk: %u bytes\n", chunk
.dwSize
);
342 hr
= read_from_stream(stream
, &chunk
.fccID
, sizeof(chunk
.fccID
));
346 size
= subtract_bytes(size
, sizeof(chunk
.fccID
));
351 TRACE("LRGN chunk (regions list): %u bytes\n", size
);
355 hr
= read_from_stream(stream
, &chunk
, sizeof(chunk
));
359 if (chunk
.fccID
!= FOURCC_LIST
)
361 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
365 hr
= read_from_stream(stream
, &chunk
.fccID
, sizeof(chunk
.fccID
));
369 if (chunk
.fccID
== FOURCC_RGN
)
371 TRACE("RGN chunk (region): %u bytes\n", chunk
.dwSize
);
372 hr
= load_region(This
, stream
, &This
->regions
[i
++], chunk
.dwSize
- sizeof(chunk
.fccID
));
376 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
377 hr
= advance_stream(stream
, chunk
.dwSize
- sizeof(chunk
.fccID
));
382 size
= subtract_bytes(size
, chunk
.dwSize
+ sizeof(chunk
));
387 TRACE("LART chunk (articulations list): %u bytes\n", size
);
391 hr
= read_from_stream(stream
, &chunk
, sizeof(chunk
));
395 if (chunk
.fccID
== FOURCC_ART1
)
397 TRACE("ART1 chunk (level 1 articulation): %u bytes\n", chunk
.dwSize
);
398 hr
= load_articulation(This
, stream
, chunk
.dwSize
);
402 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
403 hr
= advance_stream(stream
, chunk
.dwSize
);
408 size
= subtract_bytes(size
, chunk
.dwSize
+ sizeof(chunk
));
413 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
415 hr
= advance_stream(stream
, chunk
.dwSize
- sizeof(chunk
.fccID
));
419 size
= subtract_bytes(size
, chunk
.dwSize
- sizeof(chunk
.fccID
));
426 TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk
.fccID
), chunk
.dwSize
);
428 hr
= advance_stream(stream
, chunk
.dwSize
);
441 HeapFree(GetProcessHeap(), 0, This
->regions
);
442 This
->regions
= NULL
;
444 return DMUS_E_UNSUPPORTED_STREAM
;