1 /* IDirectMusicBuffer 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"
24 WINE_DEFAULT_DEBUG_CHANNEL(dmusic
);
26 static inline IDirectMusicBufferImpl
*impl_from_IDirectMusicBuffer(IDirectMusicBuffer
*iface
)
28 return CONTAINING_RECORD(iface
, IDirectMusicBufferImpl
, IDirectMusicBuffer_iface
);
31 /* IDirectMusicBufferImpl IUnknown part: */
32 static HRESULT WINAPI
IDirectMusicBufferImpl_QueryInterface(LPDIRECTMUSICBUFFER iface
, REFIID riid
, LPVOID
*ret_iface
)
34 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_dmguid(riid
), ret_iface
);
36 if (IsEqualIID(riid
, &IID_IUnknown
) ||
37 IsEqualIID(riid
, &IID_IDirectMusicBuffer
))
39 IDirectMusicBuffer_AddRef(iface
);
46 WARN("(%p)->(%s, %p): not found\n", iface
, debugstr_dmguid(riid
), ret_iface
);
51 static ULONG WINAPI
IDirectMusicBufferImpl_AddRef(LPDIRECTMUSICBUFFER iface
)
53 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
54 ULONG ref
= InterlockedIncrement(&This
->ref
);
56 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
63 static ULONG WINAPI
IDirectMusicBufferImpl_Release(LPDIRECTMUSICBUFFER iface
)
65 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
66 ULONG ref
= InterlockedDecrement(&This
->ref
);
68 TRACE("(%p)->(): new ref = %u\n", iface
, ref
);
71 HeapFree(GetProcessHeap(), 0, This
->data
);
72 HeapFree(GetProcessHeap(), 0, This
);
75 DMUSIC_UnlockModule();
80 /* IDirectMusicBufferImpl IDirectMusicBuffer part: */
81 static HRESULT WINAPI
IDirectMusicBufferImpl_Flush(LPDIRECTMUSICBUFFER iface
)
83 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
85 FIXME("(%p): stub\n", This
);
90 static HRESULT WINAPI
IDirectMusicBufferImpl_TotalTime(LPDIRECTMUSICBUFFER iface
, LPREFERENCE_TIME prtTime
)
92 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
94 FIXME("(%p, %p): stub\n", This
, prtTime
);
99 static HRESULT WINAPI
IDirectMusicBufferImpl_PackStructured(LPDIRECTMUSICBUFFER iface
, REFERENCE_TIME ref_time
, DWORD channel_group
, DWORD channel_message
)
101 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
102 DWORD new_write_pos
= This
->write_pos
+ sizeof(DMUS_EVENTHEADER
) + sizeof(DWORD
);
103 DMUS_EVENTHEADER header
;
105 TRACE("(%p)->(0x%s, %u, 0x%x)\n", iface
, wine_dbgstr_longlong(ref_time
), channel_group
, channel_message
);
107 if (new_write_pos
> This
->size
)
108 return DMUS_E_BUFFER_FULL
;
110 /* Channel_message 0xZZYYXX is a midi message where XX = status byte, YY = byte 1 and ZZ = byte 2 */
112 if (!(channel_message
& 0x80))
114 /* Status byte MSB is always set */
115 return DMUS_E_INVALID_EVENT
;
118 if (!This
->write_pos
)
119 This
->start_time
= ref_time
;
121 header
.cbEvent
= sizeof(channel_message
);
122 header
.dwChannelGroup
= channel_group
;
123 header
.rtDelta
= ref_time
- This
->start_time
;
124 header
.dwFlags
= DMUS_EVENT_STRUCTURED
;
126 memcpy(This
->data
+ This
->write_pos
, &header
, sizeof(header
));
127 *(DWORD
*)(This
->data
+ This
->write_pos
+ sizeof(header
)) = channel_message
;
128 This
->write_pos
= new_write_pos
;
133 static HRESULT WINAPI
IDirectMusicBufferImpl_PackUnstructured(LPDIRECTMUSICBUFFER iface
, REFERENCE_TIME rt
, DWORD dwChannelGroup
, DWORD cb
, LPBYTE lpb
)
135 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
137 FIXME("(%p, 0x%s, %d, %d, %p): stub\n", This
, wine_dbgstr_longlong(rt
), dwChannelGroup
, cb
, lpb
);
142 static HRESULT WINAPI
IDirectMusicBufferImpl_ResetReadPtr(LPDIRECTMUSICBUFFER iface
)
144 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
146 FIXME("(%p): stub\n", This
);
151 static HRESULT WINAPI
IDirectMusicBufferImpl_GetNextEvent(LPDIRECTMUSICBUFFER iface
, LPREFERENCE_TIME prt
, LPDWORD pdwChannelGroup
, LPDWORD pdwLength
, LPBYTE
* ppData
)
153 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
155 FIXME("(%p, %p, %p, %p, %p): stub\n", This
, prt
, pdwChannelGroup
, pdwLength
, ppData
);
160 static HRESULT WINAPI
IDirectMusicBufferImpl_GetRawBufferPtr(LPDIRECTMUSICBUFFER iface
, LPBYTE
* data
)
162 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
164 TRACE("(%p)->(%p)\n", iface
, data
);
174 static HRESULT WINAPI
IDirectMusicBufferImpl_GetStartTime(LPDIRECTMUSICBUFFER iface
, LPREFERENCE_TIME ref_time
)
176 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
178 TRACE("(%p)->(%p)\n", iface
, ref_time
);
182 if (!This
->write_pos
)
183 return DMUS_E_BUFFER_EMPTY
;
185 *ref_time
= This
->start_time
;
190 static HRESULT WINAPI
IDirectMusicBufferImpl_GetUsedBytes(LPDIRECTMUSICBUFFER iface
, LPDWORD used_bytes
)
192 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
194 TRACE("(%p)->(%p)\n", iface
, used_bytes
);
199 *used_bytes
= This
->write_pos
;
204 static HRESULT WINAPI
IDirectMusicBufferImpl_GetMaxBytes(LPDIRECTMUSICBUFFER iface
, LPDWORD max_bytes
)
206 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
208 TRACE("(%p)->(%p)\n", iface
, max_bytes
);
213 *max_bytes
= This
->size
;
218 static HRESULT WINAPI
IDirectMusicBufferImpl_GetBufferFormat(LPDIRECTMUSICBUFFER iface
, LPGUID format
)
220 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
222 TRACE("(%p)->(%p)\n", iface
, format
);
227 *format
= This
->format
;
231 static HRESULT WINAPI
IDirectMusicBufferImpl_SetStartTime(LPDIRECTMUSICBUFFER iface
, REFERENCE_TIME ref_time
)
233 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
235 TRACE("(%p)->(0x%s)\n", This
, wine_dbgstr_longlong(ref_time
));
237 This
->start_time
= ref_time
;
242 static HRESULT WINAPI
IDirectMusicBufferImpl_SetUsedBytes (LPDIRECTMUSICBUFFER iface
, DWORD cb
)
244 IDirectMusicBufferImpl
*This
= impl_from_IDirectMusicBuffer(iface
);
246 FIXME("(%p, %d): stub\n", This
, cb
);
251 static const IDirectMusicBufferVtbl DirectMusicBuffer_Vtbl
= {
252 IDirectMusicBufferImpl_QueryInterface
,
253 IDirectMusicBufferImpl_AddRef
,
254 IDirectMusicBufferImpl_Release
,
255 IDirectMusicBufferImpl_Flush
,
256 IDirectMusicBufferImpl_TotalTime
,
257 IDirectMusicBufferImpl_PackStructured
,
258 IDirectMusicBufferImpl_PackUnstructured
,
259 IDirectMusicBufferImpl_ResetReadPtr
,
260 IDirectMusicBufferImpl_GetNextEvent
,
261 IDirectMusicBufferImpl_GetRawBufferPtr
,
262 IDirectMusicBufferImpl_GetStartTime
,
263 IDirectMusicBufferImpl_GetUsedBytes
,
264 IDirectMusicBufferImpl_GetMaxBytes
,
265 IDirectMusicBufferImpl_GetBufferFormat
,
266 IDirectMusicBufferImpl_SetStartTime
,
267 IDirectMusicBufferImpl_SetUsedBytes
270 HRESULT
DMUSIC_CreateDirectMusicBufferImpl(LPDMUS_BUFFERDESC desc
, LPVOID
* ret_iface
)
272 IDirectMusicBufferImpl
* dmbuffer
;
275 TRACE("(%p, %p)\n", desc
, ret_iface
);
279 dmbuffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirectMusicBufferImpl
));
281 return E_OUTOFMEMORY
;
283 dmbuffer
->IDirectMusicBuffer_iface
.lpVtbl
= &DirectMusicBuffer_Vtbl
;
284 dmbuffer
->ref
= 0; /* Will be inited by QueryInterface */
286 if (IsEqualGUID(&desc
->guidBufferFormat
, &GUID_NULL
))
287 dmbuffer
->format
= KSDATAFORMAT_SUBTYPE_MIDI
;
289 dmbuffer
->format
= desc
->guidBufferFormat
;
290 dmbuffer
->size
= (desc
->cbBuffer
+ 3) & ~3; /* Buffer size must be multiple of 4 bytes */
292 dmbuffer
->data
= HeapAlloc(GetProcessHeap(), 0, dmbuffer
->size
);
293 if (!dmbuffer
->data
) {
294 HeapFree(GetProcessHeap(), 0, dmbuffer
);
295 return E_OUTOFMEMORY
;
298 hr
= IDirectMusicBufferImpl_QueryInterface((LPDIRECTMUSICBUFFER
)dmbuffer
, &IID_IDirectMusicBuffer
, ret_iface
);
301 HeapFree(GetProcessHeap(), 0, dmbuffer
->data
);
302 HeapFree(GetProcessHeap(), 0, dmbuffer
);