ReactOS  0.4.14-dev-50-g13bb5e2
instrument.c
Go to the documentation of this file.
1 /*
2  * IDirectMusicInstrument Implementation
3  *
4  * Copyright (C) 2003-2004 Rok Mandeljc
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include "dmusic_private.h"
22 
24 
25 static const GUID IID_IDirectMusicInstrumentPRIVATE = { 0xbcb20080, 0xa40c, 0x11d1, { 0x86, 0xbc, 0x00, 0xc0, 0x4f, 0xbf, 0x8f, 0xef } };
26 
27 /* IDirectMusicInstrument IUnknown part: */
29 {
30  TRACE("(%p)->(%s, %p)\n", iface, debugstr_dmguid(riid), ret_iface);
31 
32  if (IsEqualIID(riid, &IID_IUnknown) ||
33  IsEqualIID(riid, &IID_IDirectMusicInstrument))
34  {
35  *ret_iface = iface;
37  return S_OK;
38  }
40  {
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  */
46  FIXME("*sigh*... requested private/unspecified interface\n");
47 
48  *ret_iface = iface;
50  return S_OK;
51  }
52 
53  WARN("(%p)->(%s, %p): not found\n", iface, debugstr_dmguid(riid), ret_iface);
54 
55  return E_NOINTERFACE;
56 }
57 
59 {
62 
63  TRACE("(%p)->(): new ref = %u\n", iface, ref);
64 
65  return ref;
66 }
67 
69 {
72 
73  TRACE("(%p)->(): new ref = %u\n", iface, ref);
74 
75  if (!ref)
76  {
77  ULONG i;
78 
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);
85  }
86 
87  return ref;
88 }
89 
90 /* IDirectMusicInstrumentImpl IDirectMusicInstrument part: */
92 {
94 
95  TRACE("(%p)->(%p)\n", This, pdwPatch);
96 
97  *pdwPatch = MIDILOCALE2Patch(&This->header.Locale);
98 
99  return S_OK;
100 }
101 
103 {
105 
106  TRACE("(%p)->(%d): stub\n", This, dwPatch);
107 
108  Patch2MIDILOCALE(dwPatch, &This->header.Locale);
109 
110  return S_OK;
111 }
112 
113 static const IDirectMusicInstrumentVtbl DirectMusicInstrument_Vtbl =
114 {
120 };
121 
122 /* for ClassFactory */
125  HRESULT hr;
126 
128  if (NULL == dminst) {
129  *ppobj = NULL;
130  return E_OUTOFMEMORY;
131  }
133  dminst->ref = 1;
134 
137  ppobj);
139 
140  return hr;
141 }
142 
144 {
145  ULONG bytes_read;
146  HRESULT hr;
147 
148  hr = IStream_Read(stream, data, size, &bytes_read);
149  if(FAILED(hr)){
150  TRACE("IStream_Read failed: %08x\n", hr);
151  return hr;
152  }
153  if (bytes_read < size) {
154  TRACE("Didn't read full chunk: %u < %u\n", bytes_read, size);
155  return E_FAIL;
156  }
157 
158  return S_OK;
159 }
160 
162 {
163  if(bytes > len){
164  TRACE("Apparent mismatch in chunk lengths? %u bytes remaining, %u bytes read\n", len, bytes);
165  return 0;
166  }
167  return len - bytes;
168 }
169 
171 {
172  LARGE_INTEGER move;
173  HRESULT ret;
174 
175  move.QuadPart = bytes;
176 
177  ret = IStream_Seek(stream, move, STREAM_SEEK_CUR, NULL);
178  if (FAILED(ret))
179  WARN("IStream_Seek failed: %08x\n", ret);
180 
181  return ret;
182 }
183 
185 {
186  HRESULT ret;
188 
189  TRACE("(%p, %p, %p, %u)\n", This, stream, region, length);
190 
191  while (length)
192  {
193  ret = read_from_stream(stream, &chunk, sizeof(chunk));
194  if (FAILED(ret))
195  return ret;
196 
197  length = subtract_bytes(length, sizeof(chunk));
198 
199  switch (chunk.fccID)
200  {
201  case FOURCC_RGNH:
202  TRACE("RGNH chunk (region header): %u bytes\n", chunk.dwSize);
203 
204  ret = read_from_stream(stream, &region->header, sizeof(region->header));
205  if (FAILED(ret))
206  return ret;
207 
208  length = subtract_bytes(length, sizeof(region->header));
209  break;
210 
211  case FOURCC_WSMP:
212  TRACE("WSMP chunk (wave sample): %u bytes\n", chunk.dwSize);
213 
214  ret = read_from_stream(stream, &region->wave_sample, sizeof(region->wave_sample));
215  if (FAILED(ret))
216  return ret;
217  length = subtract_bytes(length, sizeof(region->wave_sample));
218 
219  if (!(region->loop_present = (chunk.dwSize != sizeof(region->wave_sample))))
220  break;
221 
222  ret = read_from_stream(stream, &region->wave_loop, sizeof(region->wave_loop));
223  if (FAILED(ret))
224  return ret;
225 
226  length = subtract_bytes(length, sizeof(region->wave_loop));
227  break;
228 
229  case FOURCC_WLNK:
230  TRACE("WLNK chunk (wave link): %u bytes\n", chunk.dwSize);
231 
232  ret = read_from_stream(stream, &region->wave_link, sizeof(region->wave_link));
233  if (FAILED(ret))
234  return ret;
235 
236  length = subtract_bytes(length, sizeof(region->wave_link));
237  break;
238 
239  default:
240  TRACE("Unknown chunk %s (skipping): %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
241 
242  ret = advance_stream(stream, chunk.dwSize);
243  if (FAILED(ret))
244  return ret;
245 
246  length = subtract_bytes(length, chunk.dwSize);
247  break;
248  }
249  }
250 
251  return S_OK;
252 }
253 
255 {
256  HRESULT ret;
257  instrument_articulation *articulation;
258 
259  if (!This->articulations)
260  This->articulations = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->articulations));
261  else
262  This->articulations = HeapReAlloc(GetProcessHeap(), 0, This->articulations, sizeof(*This->articulations) * (This->nb_articulations + 1));
263  if (!This->articulations)
264  return E_OUTOFMEMORY;
265 
266  articulation = &This->articulations[This->nb_articulations];
267 
268  ret = read_from_stream(stream, &articulation->connections_list, sizeof(CONNECTIONLIST));
269  if (FAILED(ret))
270  return ret;
271 
272  articulation->connections = HeapAlloc(GetProcessHeap(), 0, sizeof(CONNECTION) * articulation->connections_list.cConnections);
273  if (!articulation->connections)
274  return E_OUTOFMEMORY;
275 
276  ret = read_from_stream(stream, articulation->connections, sizeof(CONNECTION) * articulation->connections_list.cConnections);
277  if (FAILED(ret))
278  {
279  HeapFree(GetProcessHeap(), 0, articulation->connections);
280  return ret;
281  }
282 
283  subtract_bytes(length, sizeof(CONNECTIONLIST) + sizeof(CONNECTION) * articulation->connections_list.cConnections);
284 
285  This->nb_articulations++;
286 
287  return S_OK;
288 }
289 
290 /* Function that loads all instrument data and which is called from IDirectMusicCollection_GetInstrument as in native */
292 {
294  HRESULT hr;
296  ULONG i = 0;
297  ULONG length = This->length;
298 
299  TRACE("(%p, %p): offset = 0x%s, length = %u)\n", This, stream, wine_dbgstr_longlong(This->liInstrumentPosition.QuadPart), This->length);
300 
301  if (This->loaded)
302  return S_OK;
303 
304  hr = IStream_Seek(stream, This->liInstrumentPosition, STREAM_SEEK_SET, NULL);
305  if (FAILED(hr))
306  {
307  WARN("IStream_Seek failed: %08x\n", hr);
309  }
310 
311  This->regions = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->regions) * This->header.cRegions);
312  if (!This->regions)
313  return E_OUTOFMEMORY;
314 
315  while (length)
316  {
317  hr = read_from_stream(stream, &chunk, sizeof(chunk));
318  if (FAILED(hr))
319  goto error;
320 
321  length = subtract_bytes(length, sizeof(chunk) + chunk.dwSize);
322 
323  switch (chunk.fccID)
324  {
325  case FOURCC_INSH:
326  case FOURCC_DLID:
327  TRACE("Chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
328 
329  /* Instrument header and id are already set so just skip */
330  hr = advance_stream(stream, chunk.dwSize);
331  if (FAILED(hr))
332  goto error;
333 
334  break;
335 
336  case FOURCC_LIST: {
337  DWORD size = chunk.dwSize;
338 
339  TRACE("LIST chunk: %u bytes\n", chunk.dwSize);
340 
341  hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
342  if (FAILED(hr))
343  goto error;
344 
345  size = subtract_bytes(size, sizeof(chunk.fccID));
346 
347  switch (chunk.fccID)
348  {
349  case FOURCC_LRGN:
350  TRACE("LRGN chunk (regions list): %u bytes\n", size);
351 
352  while (size)
353  {
354  hr = read_from_stream(stream, &chunk, sizeof(chunk));
355  if (FAILED(hr))
356  goto error;
357 
358  if (chunk.fccID != FOURCC_LIST)
359  {
360  TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
361  goto error;
362  }
363 
364  hr = read_from_stream(stream, &chunk.fccID, sizeof(chunk.fccID));
365  if (FAILED(hr))
366  goto error;
367 
368  if (chunk.fccID == FOURCC_RGN)
369  {
370  TRACE("RGN chunk (region): %u bytes\n", chunk.dwSize);
371  hr = load_region(This, stream, &This->regions[i++], chunk.dwSize - sizeof(chunk.fccID));
372  }
373  else
374  {
375  TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
376  hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
377  }
378  if (FAILED(hr))
379  goto error;
380 
381  size = subtract_bytes(size, chunk.dwSize + sizeof(chunk));
382  }
383  break;
384 
385  case FOURCC_LART:
386  TRACE("LART chunk (articulations list): %u bytes\n", size);
387 
388  while (size)
389  {
390  hr = read_from_stream(stream, &chunk, sizeof(chunk));
391  if (FAILED(hr))
392  goto error;
393 
394  if (chunk.fccID == FOURCC_ART1)
395  {
396  TRACE("ART1 chunk (level 1 articulation): %u bytes\n", chunk.dwSize);
397  hr = load_articulation(This, stream, chunk.dwSize);
398  }
399  else
400  {
401  TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
402  hr = advance_stream(stream, chunk.dwSize);
403  }
404  if (FAILED(hr))
405  goto error;
406 
407  size = subtract_bytes(size, chunk.dwSize + sizeof(chunk));
408  }
409  break;
410 
411  default:
412  TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
413 
414  hr = advance_stream(stream, chunk.dwSize - sizeof(chunk.fccID));
415  if (FAILED(hr))
416  goto error;
417 
418  size = subtract_bytes(size, chunk.dwSize - sizeof(chunk.fccID));
419  break;
420  }
421  break;
422  }
423 
424  default:
425  TRACE("Unknown chunk %s: %u bytes\n", debugstr_fourcc(chunk.fccID), chunk.dwSize);
426 
427  hr = advance_stream(stream, chunk.dwSize);
428  if (FAILED(hr))
429  goto error;
430 
431  break;
432  }
433  }
434 
435  This->loaded = TRUE;
436 
437  return S_OK;
438 
439 error:
440  HeapFree(GetProcessHeap(), 0, This->regions);
441  This->regions = NULL;
442 
444 }
DWORD MIDILOCALE2Patch(const MIDILOCALE *pLocale)
Definition: dmusic_main.c:197
static const IDirectMusicInstrumentVtbl DirectMusicInstrument_Vtbl
Definition: instrument.c:113
static IDirectMusicInstrumentImpl * impl_from_IDirectMusicInstrument(IDirectMusicInstrument *iface)
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define E_NOINTERFACE
Definition: winerror.h:2364
#define FOURCC_LRGN
Definition: dls1.h:43
HRESULT hr
Definition: shlfolder.c:183
#define error(str)
Definition: mkdosfs.c:1605
const char * debugstr_dmguid(const GUID *id)
Definition: dmusic_main.c:237
REFIID riid
Definition: precomp.h:44
#define IDirectMusicInstrument_Release(p)
Definition: dmusicc.h:526
ULONG cConnections
Definition: dls1.h:73
#define WARN(fmt,...)
Definition: debug.h:111
IDirectMusicInstrument IDirectMusicInstrument_iface
#define DMUS_E_UNSUPPORTED_STREAM
Definition: dmerror.h:101
#define FOURCC_RGNH
Definition: dls1.h:45
#define FOURCC_WSMP
Definition: dls1.h:49
void Patch2MIDILOCALE(DWORD dwPatch, LPMIDILOCALE pLocale)
Definition: dmusic_main.c:207
#define FOURCC_ART1
Definition: dls1.h:47
#define E_FAIL
Definition: ddrawi.h:102
#define FOURCC_LART
Definition: dls1.h:46
Definition: send.c:47
static HRESULT WINAPI IDirectMusicInstrumentImpl_SetPatch(LPDIRECTMUSICINSTRUMENT iface, DWORD dwPatch)
Definition: instrument.c:102
static void DMUSIC_UnlockModule(void)
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HRESULT DMUSIC_CreateDirectMusicInstrumentImpl(LPCGUID lpcGUID, LPVOID *ppobj, LPUNKNOWN pUnkOuter)
Definition: instrument.c:123
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
static HRESULT advance_stream(IStream *stream, ULONG bytes)
Definition: instrument.c:170
static LPUNKNOWN
Definition: ndr_ole.c:49
GLenum GLint ref
Definition: glext.h:6028
#define FIXME(fmt,...)
Definition: debug.h:110
#define FOURCC_DLID
Definition: dls1.h:34
static const char * debugstr_fourcc(DWORD fourcc)
Definition: parsing.c:86
static ULONG WINAPI IDirectMusicInstrumentImpl_Release(LPDIRECTMUSICINSTRUMENT iface)
Definition: instrument.c:68
smooth NULL
Definition: ftsmooth.c:416
static void DMUSIC_LockModule(void)
static HRESULT WINAPI IDirectMusicInstrumentImpl_GetPatch(LPDIRECTMUSICINSTRUMENT iface, DWORD *pdwPatch)
Definition: instrument.c:91
#define FOURCC_RGN
Definition: dls1.h:44
#define IDirectMusicInstrument_QueryInterface(p, a, b)
Definition: dmusicc.h:524
#define TRACE(s)
Definition: solgame.cpp:4
#define FOURCC_WLNK
Definition: dls1.h:48
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:395
#define FOURCC_LIST
Definition: mmsystem.h:565
static const GUID IID_IDirectMusicInstrumentPRIVATE
Definition: instrument.c:25
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
LONG HRESULT
Definition: typedefs.h:77
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
struct IDirectMusicInstrument * LPDIRECTMUSICINSTRUMENT
Definition: dmusicc.h:99
const GUID IID_IUnknown
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static HRESULT load_region(IDirectMusicInstrumentImpl *This, IStream *stream, instrument_region *region, ULONG length)
Definition: instrument.c:184
static DWORD subtract_bytes(DWORD len, DWORD bytes)
Definition: instrument.c:161
int ret
#define IDirectMusicInstrument_AddRef(p)
Definition: dmusicc.h:525
#define InterlockedDecrement
Definition: armddk.h:52
Definition: parse.h:22
static HRESULT WINAPI IDirectMusicInstrumentImpl_QueryInterface(LPDIRECTMUSICINSTRUMENT iface, REFIID riid, LPVOID *ret_iface)
Definition: instrument.c:28
GLenum GLsizei len
Definition: glext.h:6722
CONNECTIONLIST connections_list
#define S_OK
Definition: intsafe.h:59
#define InterlockedIncrement
Definition: armddk.h:53
#define HeapReAlloc
Definition: compat.h:393
static HRESULT load_articulation(IDirectMusicInstrumentImpl *This, IStream *stream, ULONG length)
Definition: instrument.c:254
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
unsigned int ULONG
Definition: retypes.h:1
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:41
static ULONG WINAPI IDirectMusicInstrumentImpl_AddRef(LPDIRECTMUSICINSTRUMENT iface)
Definition: instrument.c:58
HRESULT IDirectMusicInstrumentImpl_CustomLoad(IDirectMusicInstrument *iface, IStream *stream)
Definition: instrument.c:291
WINE_DEFAULT_DEBUG_CHANNEL(dmusic)
#define HeapFree(x, y, z)
Definition: compat.h:394
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
static HRESULT read_from_stream(IStream *stream, void *data, ULONG size)
Definition: instrument.c:143
LONGLONG QuadPart
Definition: typedefs.h:112
#define FOURCC_INSH
Definition: dls1.h:42