1c2c66affSColin Finck /* DirectSound
2c2c66affSColin Finck *
3c2c66affSColin Finck * Copyright 1998 Marcus Meissner
4c2c66affSColin Finck * Copyright 1998 Rob Riggs
5c2c66affSColin Finck * Copyright 2000-2002 TransGaming Technologies, Inc.
6c2c66affSColin Finck *
7c2c66affSColin Finck * This library is free software; you can redistribute it and/or
8c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
9c2c66affSColin Finck * License as published by the Free Software Foundation; either
10c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
11c2c66affSColin Finck *
12c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
13c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15c2c66affSColin Finck * Lesser General Public License for more details.
16c2c66affSColin Finck *
17c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
18c2c66affSColin Finck * License along with this library; if not, write to the Free Software
19c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20c2c66affSColin Finck */
21c2c66affSColin Finck
22c2c66affSColin Finck #include "dsound_private.h"
23c2c66affSColin Finck
24c2c66affSColin Finck /*******************************************************************************
25c2c66affSColin Finck * IDirectSoundNotify
26c2c66affSColin Finck */
27c2c66affSColin Finck
28c2c66affSColin Finck struct IDirectSoundNotifyImpl
29c2c66affSColin Finck {
30c2c66affSColin Finck /* IUnknown fields */
31c2c66affSColin Finck const IDirectSoundNotifyVtbl *lpVtbl;
32c2c66affSColin Finck LONG ref;
33c2c66affSColin Finck IDirectSoundBufferImpl* dsb;
34c2c66affSColin Finck };
35c2c66affSColin Finck
36c2c66affSColin Finck static HRESULT IDirectSoundNotifyImpl_Create(IDirectSoundBufferImpl *dsb,
37c2c66affSColin Finck IDirectSoundNotifyImpl **pdsn);
38c2c66affSColin Finck static HRESULT IDirectSoundNotifyImpl_Destroy(IDirectSoundNotifyImpl *pdsn);
39c2c66affSColin Finck
IDirectSoundNotifyImpl_QueryInterface(LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID * ppobj)40c2c66affSColin Finck static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
41c2c66affSColin Finck LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj
42c2c66affSColin Finck ) {
43c2c66affSColin Finck IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
44c2c66affSColin Finck TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
45c2c66affSColin Finck
46c2c66affSColin Finck if (This->dsb == NULL) {
47c2c66affSColin Finck WARN("invalid parameter\n");
48c2c66affSColin Finck return E_INVALIDARG;
49c2c66affSColin Finck }
50c2c66affSColin Finck
51c2c66affSColin Finck return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER)This->dsb, riid, ppobj);
52c2c66affSColin Finck }
53c2c66affSColin Finck
IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)54c2c66affSColin Finck static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface)
55c2c66affSColin Finck {
56c2c66affSColin Finck IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
57c2c66affSColin Finck ULONG ref = InterlockedIncrement(&(This->ref));
58c2c66affSColin Finck TRACE("(%p) ref was %d\n", This, ref - 1);
59c2c66affSColin Finck return ref;
60c2c66affSColin Finck }
61c2c66affSColin Finck
IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)62c2c66affSColin Finck static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface)
63c2c66affSColin Finck {
64c2c66affSColin Finck IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
65c2c66affSColin Finck ULONG ref = InterlockedDecrement(&(This->ref));
66c2c66affSColin Finck TRACE("(%p) ref was %d\n", This, ref + 1);
67c2c66affSColin Finck
68c2c66affSColin Finck if (!ref) {
69c2c66affSColin Finck This->dsb->notify = NULL;
70c2c66affSColin Finck IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb);
71c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This);
72c2c66affSColin Finck TRACE("(%p) released\n", This);
73c2c66affSColin Finck }
74c2c66affSColin Finck return ref;
75c2c66affSColin Finck }
76c2c66affSColin Finck
IDirectSoundNotifyImpl_SetNotificationPositions(LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify)77c2c66affSColin Finck static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
78c2c66affSColin Finck LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
79c2c66affSColin Finck ) {
80c2c66affSColin Finck IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface;
81c2c66affSColin Finck TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify);
82c2c66affSColin Finck
83c2c66affSColin Finck if (howmuch > 0 && notify == NULL) {
84c2c66affSColin Finck WARN("invalid parameter: notify == NULL\n");
85c2c66affSColin Finck return DSERR_INVALIDPARAM;
86c2c66affSColin Finck }
87c2c66affSColin Finck
88c2c66affSColin Finck if (TRACE_ON(dsound)) {
89c2c66affSColin Finck unsigned int i;
90c2c66affSColin Finck for (i=0;i<howmuch;i++)
91c2c66affSColin Finck TRACE("notify at %d to %p\n",
92c2c66affSColin Finck notify[i].dwOffset,notify[i].hEventNotify);
93c2c66affSColin Finck }
94c2c66affSColin Finck
95c2c66affSColin Finck if (This->dsb->hwnotify) {
96c2c66affSColin Finck HRESULT hres;
97c2c66affSColin Finck hres = IDsDriverNotify_SetNotificationPositions(This->dsb->hwnotify, howmuch, notify);
98c2c66affSColin Finck if (hres != DS_OK)
99c2c66affSColin Finck WARN("IDsDriverNotify_SetNotificationPositions failed\n");
100c2c66affSColin Finck return hres;
101c2c66affSColin Finck } else if (howmuch > 0) {
102c2c66affSColin Finck /* Make an internal copy of the caller-supplied array.
103c2c66affSColin Finck * Replace the existing copy if one is already present. */
104c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
105c2c66affSColin Finck This->dsb->notifies = HeapAlloc(GetProcessHeap(), 0,
106c2c66affSColin Finck howmuch * sizeof(DSBPOSITIONNOTIFY));
107c2c66affSColin Finck
108c2c66affSColin Finck if (This->dsb->notifies == NULL) {
109c2c66affSColin Finck WARN("out of memory\n");
110c2c66affSColin Finck return DSERR_OUTOFMEMORY;
111c2c66affSColin Finck }
112c2c66affSColin Finck CopyMemory(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
113c2c66affSColin Finck This->dsb->nrofnotifies = howmuch;
114c2c66affSColin Finck } else {
115c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->dsb->notifies);
116c2c66affSColin Finck This->dsb->notifies = NULL;
117c2c66affSColin Finck This->dsb->nrofnotifies = 0;
118c2c66affSColin Finck }
119c2c66affSColin Finck
120c2c66affSColin Finck return S_OK;
121c2c66affSColin Finck }
122c2c66affSColin Finck
123c2c66affSColin Finck static const IDirectSoundNotifyVtbl dsnvt =
124c2c66affSColin Finck {
125c2c66affSColin Finck IDirectSoundNotifyImpl_QueryInterface,
126c2c66affSColin Finck IDirectSoundNotifyImpl_AddRef,
127c2c66affSColin Finck IDirectSoundNotifyImpl_Release,
128c2c66affSColin Finck IDirectSoundNotifyImpl_SetNotificationPositions,
129c2c66affSColin Finck };
130c2c66affSColin Finck
IDirectSoundNotifyImpl_Create(IDirectSoundBufferImpl * dsb,IDirectSoundNotifyImpl ** pdsn)131c2c66affSColin Finck static HRESULT IDirectSoundNotifyImpl_Create(
132c2c66affSColin Finck IDirectSoundBufferImpl * dsb,
133c2c66affSColin Finck IDirectSoundNotifyImpl **pdsn)
134c2c66affSColin Finck {
135c2c66affSColin Finck IDirectSoundNotifyImpl * dsn;
136c2c66affSColin Finck TRACE("(%p,%p)\n",dsb,pdsn);
137c2c66affSColin Finck
138c2c66affSColin Finck dsn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dsn));
139c2c66affSColin Finck
140c2c66affSColin Finck if (dsn == NULL) {
141c2c66affSColin Finck WARN("out of memory\n");
142c2c66affSColin Finck return DSERR_OUTOFMEMORY;
143c2c66affSColin Finck }
144c2c66affSColin Finck
145c2c66affSColin Finck dsn->ref = 0;
146c2c66affSColin Finck dsn->lpVtbl = &dsnvt;
147c2c66affSColin Finck dsn->dsb = dsb;
148c2c66affSColin Finck dsb->notify = dsn;
149c2c66affSColin Finck IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
150c2c66affSColin Finck
151c2c66affSColin Finck *pdsn = dsn;
152c2c66affSColin Finck return DS_OK;
153c2c66affSColin Finck }
154c2c66affSColin Finck
IDirectSoundNotifyImpl_Destroy(IDirectSoundNotifyImpl * pdsn)155c2c66affSColin Finck static HRESULT IDirectSoundNotifyImpl_Destroy(
156c2c66affSColin Finck IDirectSoundNotifyImpl *pdsn)
157c2c66affSColin Finck {
158c2c66affSColin Finck TRACE("(%p)\n",pdsn);
159c2c66affSColin Finck
160c2c66affSColin Finck while (IDirectSoundNotifyImpl_Release((LPDIRECTSOUNDNOTIFY)pdsn) > 0);
161c2c66affSColin Finck
162c2c66affSColin Finck return DS_OK;
163c2c66affSColin Finck }
164c2c66affSColin Finck
165c2c66affSColin Finck /*******************************************************************************
166c2c66affSColin Finck * IDirectSoundBuffer
167c2c66affSColin Finck */
168c2c66affSColin Finck
impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8 * iface)169c2c66affSColin Finck static inline IDirectSoundBufferImpl *impl_from_IDirectSoundBuffer8(IDirectSoundBuffer8 *iface)
170c2c66affSColin Finck {
171c2c66affSColin Finck return CONTAINING_RECORD(iface, IDirectSoundBufferImpl, IDirectSoundBuffer8_iface);
172c2c66affSColin Finck }
173c2c66affSColin Finck
is_primary_buffer(IDirectSoundBufferImpl * This)174c2c66affSColin Finck static inline BOOL is_primary_buffer(IDirectSoundBufferImpl *This)
175c2c66affSColin Finck {
176c2c66affSColin Finck return This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER ? TRUE : FALSE;
177c2c66affSColin Finck }
178c2c66affSColin Finck
IDirectSoundBufferImpl_SetFormat(IDirectSoundBuffer8 * iface,LPCWAVEFORMATEX wfex)179c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(IDirectSoundBuffer8 *iface,
180c2c66affSColin Finck LPCWAVEFORMATEX wfex)
181c2c66affSColin Finck {
182c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
183c2c66affSColin Finck
184c2c66affSColin Finck TRACE("(%p,%p)\n", iface, wfex);
185c2c66affSColin Finck
186c2c66affSColin Finck if (is_primary_buffer(This))
187c2c66affSColin Finck return primarybuffer_SetFormat(This->device, wfex);
188c2c66affSColin Finck else {
189c2c66affSColin Finck WARN("not available for secondary buffers.\n");
190c2c66affSColin Finck return DSERR_INVALIDCALL;
191c2c66affSColin Finck }
192c2c66affSColin Finck }
193c2c66affSColin Finck
IDirectSoundBufferImpl_SetVolume(IDirectSoundBuffer8 * iface,LONG vol)194c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(IDirectSoundBuffer8 *iface, LONG vol)
195c2c66affSColin Finck {
196c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
197c2c66affSColin Finck LONG oldVol;
198c2c66affSColin Finck
199c2c66affSColin Finck HRESULT hres = DS_OK;
200c2c66affSColin Finck
201c2c66affSColin Finck TRACE("(%p,%d)\n",This,vol);
202c2c66affSColin Finck
203c2c66affSColin Finck if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
204c2c66affSColin Finck WARN("control unavailable: This->dsbd.dwFlags = 0x%08x\n", This->dsbd.dwFlags);
205c2c66affSColin Finck return DSERR_CONTROLUNAVAIL;
206c2c66affSColin Finck }
207c2c66affSColin Finck
208c2c66affSColin Finck if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) {
209c2c66affSColin Finck WARN("invalid parameter: vol = %d\n", vol);
210c2c66affSColin Finck return DSERR_INVALIDPARAM;
211c2c66affSColin Finck }
212c2c66affSColin Finck
213c2c66affSColin Finck /* **** */
214c2c66affSColin Finck RtlAcquireResourceExclusive(&This->lock, TRUE);
215c2c66affSColin Finck
216c2c66affSColin Finck if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) {
217c2c66affSColin Finck oldVol = This->ds3db_lVolume;
218c2c66affSColin Finck This->ds3db_lVolume = vol;
219c2c66affSColin Finck if (vol != oldVol)
220c2c66affSColin Finck /* recalc 3d volume, which in turn recalcs the pans */
221c2c66affSColin Finck DSOUND_Calc3DBuffer(This);
222c2c66affSColin Finck } else {
223c2c66affSColin Finck oldVol = This->volpan.lVolume;
224c2c66affSColin Finck This->volpan.lVolume = vol;
225c2c66affSColin Finck if (vol != oldVol)
226c2c66affSColin Finck DSOUND_RecalcVolPan(&(This->volpan));
227c2c66affSColin Finck }
228c2c66affSColin Finck
229c2c66affSColin Finck if (vol != oldVol) {
230c2c66affSColin Finck if (This->hwbuf) {
231c2c66affSColin Finck hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
232c2c66affSColin Finck if (hres != DS_OK)
233c2c66affSColin Finck WARN("IDsDriverBuffer_SetVolumePan failed\n");
234c2c66affSColin Finck }
235c2c66affSColin Finck }
236c2c66affSColin Finck
237c2c66affSColin Finck RtlReleaseResource(&This->lock);
238c2c66affSColin Finck /* **** */
239c2c66affSColin Finck
240c2c66affSColin Finck return hres;
241c2c66affSColin Finck }
242c2c66affSColin Finck
IDirectSoundBufferImpl_GetVolume(IDirectSoundBuffer8 * iface,LONG * vol)243c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(IDirectSoundBuffer8 *iface, LONG *vol)
244c2c66affSColin Finck {
245c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
246c2c66affSColin Finck
247c2c66affSColin Finck TRACE("(%p,%p)\n",This,vol);
248c2c66affSColin Finck
249c2c66affSColin Finck if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
250c2c66affSColin Finck WARN("control unavailable\n");
251c2c66affSColin Finck return DSERR_CONTROLUNAVAIL;
252c2c66affSColin Finck }
253c2c66affSColin Finck
254c2c66affSColin Finck if (vol == NULL) {
255c2c66affSColin Finck WARN("invalid parameter: vol == NULL\n");
256c2c66affSColin Finck return DSERR_INVALIDPARAM;
257c2c66affSColin Finck }
258c2c66affSColin Finck
259c2c66affSColin Finck *vol = This->volpan.lVolume;
260c2c66affSColin Finck
261c2c66affSColin Finck return DS_OK;
262c2c66affSColin Finck }
263c2c66affSColin Finck
IDirectSoundBufferImpl_SetFrequency(IDirectSoundBuffer8 * iface,DWORD freq)264c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(IDirectSoundBuffer8 *iface, DWORD freq)
265c2c66affSColin Finck {
266c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
267c2c66affSColin Finck DWORD oldFreq;
268c2c66affSColin Finck
269c2c66affSColin Finck TRACE("(%p,%d)\n",This,freq);
270c2c66affSColin Finck
271c2c66affSColin Finck if (is_primary_buffer(This)) {
272c2c66affSColin Finck WARN("not available for primary buffers.\n");
273c2c66affSColin Finck return DSERR_CONTROLUNAVAIL;
274c2c66affSColin Finck }
275c2c66affSColin Finck
276c2c66affSColin Finck if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
277c2c66affSColin Finck WARN("control unavailable\n");
278c2c66affSColin Finck return DSERR_CONTROLUNAVAIL;
279c2c66affSColin Finck }
280c2c66affSColin Finck
281c2c66affSColin Finck if (freq == DSBFREQUENCY_ORIGINAL)
282c2c66affSColin Finck freq = This->pwfx->nSamplesPerSec;
283c2c66affSColin Finck
284c2c66affSColin Finck if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) {
285c2c66affSColin Finck WARN("invalid parameter: freq = %d\n", freq);
286c2c66affSColin Finck return DSERR_INVALIDPARAM;
287c2c66affSColin Finck }
288c2c66affSColin Finck
289c2c66affSColin Finck /* **** */
290c2c66affSColin Finck RtlAcquireResourceExclusive(&This->lock, TRUE);
291c2c66affSColin Finck
292c2c66affSColin Finck oldFreq = This->freq;
293c2c66affSColin Finck This->freq = freq;
294c2c66affSColin Finck if (freq != oldFreq) {
295c2c66affSColin Finck This->freqAdjust = ((DWORD64)This->freq << DSOUND_FREQSHIFT) / This->device->pwfx->nSamplesPerSec;
296c2c66affSColin Finck This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign;
297c2c66affSColin Finck DSOUND_RecalcFormat(This);
298c2c66affSColin Finck DSOUND_MixToTemporary(This, 0, This->buflen, FALSE);
299c2c66affSColin Finck }
300c2c66affSColin Finck
301c2c66affSColin Finck RtlReleaseResource(&This->lock);
302c2c66affSColin Finck /* **** */
303c2c66affSColin Finck
304c2c66affSColin Finck return DS_OK;
305c2c66affSColin Finck }
306c2c66affSColin Finck
IDirectSoundBufferImpl_Play(IDirectSoundBuffer8 * iface,DWORD reserved1,DWORD reserved2,DWORD flags)307c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_Play(IDirectSoundBuffer8 *iface, DWORD reserved1,
308c2c66affSColin Finck DWORD reserved2, DWORD flags)
309c2c66affSColin Finck {
310c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
311c2c66affSColin Finck HRESULT hres = DS_OK;
312c2c66affSColin Finck
313c2c66affSColin Finck TRACE("(%p,%08x,%08x,%08x)\n",This,reserved1,reserved2,flags);
314c2c66affSColin Finck
315c2c66affSColin Finck /* **** */
316c2c66affSColin Finck RtlAcquireResourceExclusive(&This->lock, TRUE);
317c2c66affSColin Finck
318c2c66affSColin Finck This->playflags = flags;
319c2c66affSColin Finck if (This->state == STATE_STOPPED && !This->hwbuf) {
320c2c66affSColin Finck This->leadin = TRUE;
321c2c66affSColin Finck This->state = STATE_STARTING;
322c2c66affSColin Finck } else if (This->state == STATE_STOPPING)
323c2c66affSColin Finck This->state = STATE_PLAYING;
324c2c66affSColin Finck if (This->hwbuf) {
325c2c66affSColin Finck hres = IDsDriverBuffer_Play(This->hwbuf, 0, 0, This->playflags);
326c2c66affSColin Finck if (hres != DS_OK)
327c2c66affSColin Finck WARN("IDsDriverBuffer_Play failed\n");
328c2c66affSColin Finck else
329c2c66affSColin Finck This->state = STATE_PLAYING;
330c2c66affSColin Finck }
331c2c66affSColin Finck
332c2c66affSColin Finck RtlReleaseResource(&This->lock);
333c2c66affSColin Finck /* **** */
334c2c66affSColin Finck
335c2c66affSColin Finck return hres;
336c2c66affSColin Finck }
337c2c66affSColin Finck
IDirectSoundBufferImpl_Stop(IDirectSoundBuffer8 * iface)338c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_Stop(IDirectSoundBuffer8 *iface)
339c2c66affSColin Finck {
340c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
341c2c66affSColin Finck HRESULT hres = DS_OK;
342c2c66affSColin Finck
343c2c66affSColin Finck TRACE("(%p)\n",This);
344c2c66affSColin Finck
345c2c66affSColin Finck /* **** */
346c2c66affSColin Finck RtlAcquireResourceExclusive(&This->lock, TRUE);
347c2c66affSColin Finck
348c2c66affSColin Finck if (This->state == STATE_PLAYING)
349c2c66affSColin Finck This->state = STATE_STOPPING;
350c2c66affSColin Finck else if (This->state == STATE_STARTING)
351c2c66affSColin Finck {
352c2c66affSColin Finck This->state = STATE_STOPPED;
353c2c66affSColin Finck DSOUND_CheckEvent(This, 0, 0);
354c2c66affSColin Finck }
355c2c66affSColin Finck if (This->hwbuf) {
356c2c66affSColin Finck hres = IDsDriverBuffer_Stop(This->hwbuf);
357c2c66affSColin Finck if (hres != DS_OK)
358c2c66affSColin Finck WARN("IDsDriverBuffer_Stop failed\n");
359c2c66affSColin Finck else
360c2c66affSColin Finck This->state = STATE_STOPPED;
361c2c66affSColin Finck }
362c2c66affSColin Finck
363c2c66affSColin Finck RtlReleaseResource(&This->lock);
364c2c66affSColin Finck /* **** */
365c2c66affSColin Finck
366c2c66affSColin Finck return hres;
367c2c66affSColin Finck }
368c2c66affSColin Finck
IDirectSoundBufferImpl_AddRef(IDirectSoundBuffer8 * iface)369c2c66affSColin Finck static ULONG WINAPI IDirectSoundBufferImpl_AddRef(IDirectSoundBuffer8 *iface)
370c2c66affSColin Finck {
371c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
372c2c66affSColin Finck ULONG ref = InterlockedIncrement(&This->ref);
373c2c66affSColin Finck
374c2c66affSColin Finck TRACE("(%p) ref was %d\n", This, ref - 1);
375c2c66affSColin Finck
376c2c66affSColin Finck if(ref == 1)
377c2c66affSColin Finck InterlockedIncrement(&This->numIfaces);
378c2c66affSColin Finck
379c2c66affSColin Finck return ref;
380c2c66affSColin Finck }
381c2c66affSColin Finck
IDirectSoundBufferImpl_Release(IDirectSoundBuffer8 * iface)382c2c66affSColin Finck static ULONG WINAPI IDirectSoundBufferImpl_Release(IDirectSoundBuffer8 *iface)
383c2c66affSColin Finck {
384c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
385c2c66affSColin Finck ULONG ref = InterlockedDecrement(&This->ref);
386c2c66affSColin Finck
387c2c66affSColin Finck TRACE("(%p) ref was %d\n", This, ref + 1);
388c2c66affSColin Finck
389c2c66affSColin Finck if (!ref && !InterlockedDecrement(&This->numIfaces)) {
390c2c66affSColin Finck if (is_primary_buffer(This))
391c2c66affSColin Finck primarybuffer_destroy(This);
392c2c66affSColin Finck else
393c2c66affSColin Finck secondarybuffer_destroy(This);
394c2c66affSColin Finck }
395c2c66affSColin Finck return ref;
396c2c66affSColin Finck }
397c2c66affSColin Finck
IDirectSoundBufferImpl_GetCurrentPosition(IDirectSoundBuffer8 * iface,DWORD * playpos,DWORD * writepos)398c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(IDirectSoundBuffer8 *iface,
399c2c66affSColin Finck DWORD *playpos, DWORD *writepos)
400c2c66affSColin Finck {
401c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
402c2c66affSColin Finck HRESULT hres;
403c2c66affSColin Finck
404c2c66affSColin Finck TRACE("(%p,%p,%p)\n",This,playpos,writepos);
405c2c66affSColin Finck
406c2c66affSColin Finck RtlAcquireResourceShared(&This->lock, TRUE);
407c2c66affSColin Finck if (This->hwbuf) {
408c2c66affSColin Finck hres=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos);
409c2c66affSColin Finck if (hres != DS_OK) {
410c2c66affSColin Finck WARN("IDsDriverBuffer_GetPosition failed\n");
411c2c66affSColin Finck return hres;
412c2c66affSColin Finck }
413c2c66affSColin Finck } else {
414c2c66affSColin Finck DWORD pos = This->sec_mixpos;
415c2c66affSColin Finck
416c2c66affSColin Finck /* sanity */
417c2c66affSColin Finck if (pos >= This->buflen){
418c2c66affSColin Finck FIXME("Bad play position. playpos: %d, buflen: %d\n", pos, This->buflen);
419c2c66affSColin Finck pos %= This->buflen;
420c2c66affSColin Finck }
421c2c66affSColin Finck
422c2c66affSColin Finck if (playpos)
423c2c66affSColin Finck *playpos = pos;
424c2c66affSColin Finck if (writepos)
425c2c66affSColin Finck *writepos = pos;
426c2c66affSColin Finck }
427c2c66affSColin Finck if (writepos && This->state != STATE_STOPPED && (!This->hwbuf || !(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDWRITELEAD))) {
428c2c66affSColin Finck /* apply the documented 10ms lead to writepos */
429c2c66affSColin Finck *writepos += This->writelead;
430c2c66affSColin Finck *writepos %= This->buflen;
431c2c66affSColin Finck }
432c2c66affSColin Finck RtlReleaseResource(&This->lock);
433c2c66affSColin Finck
434c2c66affSColin Finck TRACE("playpos = %d, writepos = %d, buflen=%d (%p, time=%d)\n",
435c2c66affSColin Finck playpos?*playpos:-1, writepos?*writepos:-1, This->buflen, This, GetTickCount());
436c2c66affSColin Finck
437c2c66affSColin Finck return DS_OK;
438c2c66affSColin Finck }
439c2c66affSColin Finck
IDirectSoundBufferImpl_GetStatus(IDirectSoundBuffer8 * iface,DWORD * status)440c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus(IDirectSoundBuffer8 *iface, DWORD *status)
441c2c66affSColin Finck {
442c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
443c2c66affSColin Finck
444c2c66affSColin Finck TRACE("(%p,%p), thread is %04x\n",This,status,GetCurrentThreadId());
445c2c66affSColin Finck
446c2c66affSColin Finck if (status == NULL) {
447c2c66affSColin Finck WARN("invalid parameter: status = NULL\n");
448c2c66affSColin Finck return DSERR_INVALIDPARAM;
449c2c66affSColin Finck }
450c2c66affSColin Finck
451c2c66affSColin Finck *status = 0;
452c2c66affSColin Finck RtlAcquireResourceShared(&This->lock, TRUE);
453c2c66affSColin Finck if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) {
454c2c66affSColin Finck *status |= DSBSTATUS_PLAYING;
455c2c66affSColin Finck if (This->playflags & DSBPLAY_LOOPING)
456c2c66affSColin Finck *status |= DSBSTATUS_LOOPING;
457c2c66affSColin Finck }
458c2c66affSColin Finck RtlReleaseResource(&This->lock);
459c2c66affSColin Finck
460c2c66affSColin Finck TRACE("status=%x\n", *status);
461c2c66affSColin Finck return DS_OK;
462c2c66affSColin Finck }
463c2c66affSColin Finck
464c2c66affSColin Finck
IDirectSoundBufferImpl_GetFormat(IDirectSoundBuffer8 * iface,LPWAVEFORMATEX lpwf,DWORD wfsize,DWORD * wfwritten)465c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat(IDirectSoundBuffer8 *iface,
466c2c66affSColin Finck LPWAVEFORMATEX lpwf, DWORD wfsize, DWORD *wfwritten)
467c2c66affSColin Finck {
468c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
469c2c66affSColin Finck DWORD size;
470c2c66affSColin Finck
471c2c66affSColin Finck TRACE("(%p,%p,%d,%p)\n",This,lpwf,wfsize,wfwritten);
472c2c66affSColin Finck
473c2c66affSColin Finck size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
474c2c66affSColin Finck
475c2c66affSColin Finck if (lpwf) { /* NULL is valid */
476c2c66affSColin Finck if (wfsize >= size) {
477c2c66affSColin Finck CopyMemory(lpwf,This->pwfx,size);
478c2c66affSColin Finck if (wfwritten)
479c2c66affSColin Finck *wfwritten = size;
480c2c66affSColin Finck } else {
481c2c66affSColin Finck WARN("invalid parameter: wfsize too small\n");
482c2c66affSColin Finck CopyMemory(lpwf,This->pwfx,wfsize);
483c2c66affSColin Finck if (wfwritten)
484c2c66affSColin Finck *wfwritten = wfsize;
485c2c66affSColin Finck return DSERR_INVALIDPARAM;
486c2c66affSColin Finck }
487c2c66affSColin Finck } else {
488c2c66affSColin Finck if (wfwritten)
489c2c66affSColin Finck *wfwritten = sizeof(WAVEFORMATEX) + This->pwfx->cbSize;
490c2c66affSColin Finck else {
491c2c66affSColin Finck WARN("invalid parameter: wfwritten == NULL\n");
492c2c66affSColin Finck return DSERR_INVALIDPARAM;
493c2c66affSColin Finck }
494c2c66affSColin Finck }
495c2c66affSColin Finck
496c2c66affSColin Finck return DS_OK;
497c2c66affSColin Finck }
498c2c66affSColin Finck
IDirectSoundBufferImpl_Lock(IDirectSoundBuffer8 * iface,DWORD writecursor,DWORD writebytes,void ** lplpaudioptr1,DWORD * audiobytes1,void ** lplpaudioptr2,DWORD * audiobytes2,DWORD flags)499c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_Lock(IDirectSoundBuffer8 *iface, DWORD writecursor,
500c2c66affSColin Finck DWORD writebytes, void **lplpaudioptr1, DWORD *audiobytes1, void **lplpaudioptr2,
501c2c66affSColin Finck DWORD *audiobytes2, DWORD flags)
502c2c66affSColin Finck {
503c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
504c2c66affSColin Finck HRESULT hres = DS_OK;
505c2c66affSColin Finck
506c2c66affSColin Finck TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n", This, writecursor, writebytes, lplpaudioptr1,
507c2c66affSColin Finck audiobytes1, lplpaudioptr2, audiobytes2, flags, GetTickCount());
508c2c66affSColin Finck
509c2c66affSColin Finck if (!audiobytes1)
510c2c66affSColin Finck return DSERR_INVALIDPARAM;
511c2c66affSColin Finck
512c2c66affSColin Finck /* when this flag is set, writecursor is meaningless and must be calculated */
513c2c66affSColin Finck if (flags & DSBLOCK_FROMWRITECURSOR) {
514c2c66affSColin Finck /* GetCurrentPosition does too much magic to duplicate here */
515c2c66affSColin Finck hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writecursor);
516c2c66affSColin Finck if (hres != DS_OK) {
517c2c66affSColin Finck WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n");
518c2c66affSColin Finck return hres;
519c2c66affSColin Finck }
520c2c66affSColin Finck }
521c2c66affSColin Finck
522c2c66affSColin Finck /* when this flag is set, writebytes is meaningless and must be set */
523c2c66affSColin Finck if (flags & DSBLOCK_ENTIREBUFFER)
524c2c66affSColin Finck writebytes = This->buflen;
525c2c66affSColin Finck
526c2c66affSColin Finck if (writecursor >= This->buflen) {
527c2c66affSColin Finck WARN("Invalid parameter, writecursor: %u >= buflen: %u\n",
528c2c66affSColin Finck writecursor, This->buflen);
529c2c66affSColin Finck return DSERR_INVALIDPARAM;
530c2c66affSColin Finck }
531c2c66affSColin Finck
532c2c66affSColin Finck if (writebytes > This->buflen) {
533c2c66affSColin Finck WARN("Invalid parameter, writebytes: %u > buflen: %u\n",
534c2c66affSColin Finck writebytes, This->buflen);
535c2c66affSColin Finck return DSERR_INVALIDPARAM;
536c2c66affSColin Finck }
537c2c66affSColin Finck
538c2c66affSColin Finck /* **** */
539c2c66affSColin Finck RtlAcquireResourceShared(&This->lock, TRUE);
540c2c66affSColin Finck
541c2c66affSColin Finck if (!(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
542c2c66affSColin Finck hres = IDsDriverBuffer_Lock(This->hwbuf,
543c2c66affSColin Finck lplpaudioptr1, audiobytes1,
544c2c66affSColin Finck lplpaudioptr2, audiobytes2,
545c2c66affSColin Finck writecursor, writebytes,
546c2c66affSColin Finck 0);
547c2c66affSColin Finck if (hres != DS_OK) {
548c2c66affSColin Finck WARN("IDsDriverBuffer_Lock failed\n");
549c2c66affSColin Finck RtlReleaseResource(&This->lock);
550c2c66affSColin Finck return hres;
551c2c66affSColin Finck }
552c2c66affSColin Finck } else {
553c2c66affSColin Finck if (writecursor+writebytes <= This->buflen) {
554c2c66affSColin Finck *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
555c2c66affSColin Finck if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
556c2c66affSColin Finck WARN("Overwriting mixing position, case 1\n");
557c2c66affSColin Finck *audiobytes1 = writebytes;
558c2c66affSColin Finck if (lplpaudioptr2)
559c2c66affSColin Finck *(LPBYTE*)lplpaudioptr2 = NULL;
560c2c66affSColin Finck if (audiobytes2)
561c2c66affSColin Finck *audiobytes2 = 0;
562c2c66affSColin Finck TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n",
563c2c66affSColin Finck *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
564c2c66affSColin Finck TRACE("->%d.0\n",writebytes);
565c2c66affSColin Finck } else {
566c2c66affSColin Finck DWORD remainder = writebytes + writecursor - This->buflen;
567c2c66affSColin Finck *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
568c2c66affSColin Finck *audiobytes1 = This->buflen-writecursor;
569c2c66affSColin Finck if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING)
570c2c66affSColin Finck WARN("Overwriting mixing position, case 2\n");
571c2c66affSColin Finck if (lplpaudioptr2)
572c2c66affSColin Finck *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
573c2c66affSColin Finck if (audiobytes2)
574c2c66affSColin Finck *audiobytes2 = writebytes-(This->buflen-writecursor);
575c2c66affSColin Finck if (audiobytes2 && This->sec_mixpos < remainder && This->state == STATE_PLAYING)
576c2c66affSColin Finck WARN("Overwriting mixing position, case 3\n");
577c2c66affSColin Finck TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor);
578c2c66affSColin Finck }
579c2c66affSColin Finck }
580c2c66affSColin Finck
581c2c66affSColin Finck RtlReleaseResource(&This->lock);
582c2c66affSColin Finck /* **** */
583c2c66affSColin Finck
584c2c66affSColin Finck return DS_OK;
585c2c66affSColin Finck }
586c2c66affSColin Finck
IDirectSoundBufferImpl_SetCurrentPosition(IDirectSoundBuffer8 * iface,DWORD newpos)587c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(IDirectSoundBuffer8 *iface,
588c2c66affSColin Finck DWORD newpos)
589c2c66affSColin Finck {
590c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
591c2c66affSColin Finck HRESULT hres = DS_OK;
592c2c66affSColin Finck DWORD oldpos;
593c2c66affSColin Finck
594c2c66affSColin Finck TRACE("(%p,%d)\n",This,newpos);
595c2c66affSColin Finck
596c2c66affSColin Finck /* **** */
597c2c66affSColin Finck RtlAcquireResourceExclusive(&This->lock, TRUE);
598c2c66affSColin Finck
599c2c66affSColin Finck oldpos = This->sec_mixpos;
600c2c66affSColin Finck
601c2c66affSColin Finck /* start mixing from this new location instead */
602c2c66affSColin Finck newpos %= This->buflen;
603c2c66affSColin Finck newpos -= newpos%This->pwfx->nBlockAlign;
604c2c66affSColin Finck This->sec_mixpos = newpos;
605c2c66affSColin Finck
606c2c66affSColin Finck /* at this point, do not attempt to reset buffers, mess with primary mix position,
607c2c66affSColin Finck or anything like that to reduce latency. The data already prebuffered cannot be changed */
608c2c66affSColin Finck
609c2c66affSColin Finck /* position HW buffer if applicable, else just start mixing from new location instead */
610c2c66affSColin Finck if (This->hwbuf) {
611c2c66affSColin Finck hres = IDsDriverBuffer_SetPosition(This->hwbuf, This->buf_mixpos);
612c2c66affSColin Finck if (hres != DS_OK)
613c2c66affSColin Finck WARN("IDsDriverBuffer_SetPosition failed\n");
614c2c66affSColin Finck }
615c2c66affSColin Finck else if (oldpos != newpos)
616c2c66affSColin Finck /* FIXME: Perhaps add a call to DSOUND_MixToTemporary here? Not sure it's needed */
617c2c66affSColin Finck This->buf_mixpos = DSOUND_secpos_to_bufpos(This, newpos, 0, NULL);
618c2c66affSColin Finck
619c2c66affSColin Finck RtlReleaseResource(&This->lock);
620c2c66affSColin Finck /* **** */
621c2c66affSColin Finck
622c2c66affSColin Finck return hres;
623c2c66affSColin Finck }
624c2c66affSColin Finck
IDirectSoundBufferImpl_SetPan(IDirectSoundBuffer8 * iface,LONG pan)625c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(IDirectSoundBuffer8 *iface, LONG pan)
626c2c66affSColin Finck {
627c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
628c2c66affSColin Finck HRESULT hres = DS_OK;
629c2c66affSColin Finck
630c2c66affSColin Finck TRACE("(%p,%d)\n",This,pan);
631c2c66affSColin Finck
632c2c66affSColin Finck if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) {
633c2c66affSColin Finck WARN("invalid parameter: pan = %d\n", pan);
634c2c66affSColin Finck return DSERR_INVALIDPARAM;
635c2c66affSColin Finck }
636c2c66affSColin Finck
637c2c66affSColin Finck /* You cannot use both pan and 3D controls */
638c2c66affSColin Finck if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
639c2c66affSColin Finck (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) {
640c2c66affSColin Finck WARN("control unavailable\n");
641c2c66affSColin Finck return DSERR_CONTROLUNAVAIL;
642c2c66affSColin Finck }
643c2c66affSColin Finck
644c2c66affSColin Finck /* **** */
645c2c66affSColin Finck RtlAcquireResourceExclusive(&This->lock, TRUE);
646c2c66affSColin Finck
647c2c66affSColin Finck if (This->volpan.lPan != pan) {
648c2c66affSColin Finck This->volpan.lPan = pan;
649c2c66affSColin Finck DSOUND_RecalcVolPan(&(This->volpan));
650c2c66affSColin Finck
651c2c66affSColin Finck if (This->hwbuf) {
652c2c66affSColin Finck hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
653c2c66affSColin Finck if (hres != DS_OK)
654c2c66affSColin Finck WARN("IDsDriverBuffer_SetVolumePan failed\n");
655c2c66affSColin Finck }
656c2c66affSColin Finck }
657c2c66affSColin Finck
658c2c66affSColin Finck RtlReleaseResource(&This->lock);
659c2c66affSColin Finck /* **** */
660c2c66affSColin Finck
661c2c66affSColin Finck return hres;
662c2c66affSColin Finck }
663c2c66affSColin Finck
IDirectSoundBufferImpl_GetPan(IDirectSoundBuffer8 * iface,LONG * pan)664c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_GetPan(IDirectSoundBuffer8 *iface, LONG *pan)
665c2c66affSColin Finck {
666c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
667c2c66affSColin Finck
668c2c66affSColin Finck TRACE("(%p,%p)\n",This,pan);
669c2c66affSColin Finck
670c2c66affSColin Finck if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN)) {
671c2c66affSColin Finck WARN("control unavailable\n");
672c2c66affSColin Finck return DSERR_CONTROLUNAVAIL;
673c2c66affSColin Finck }
674c2c66affSColin Finck
675c2c66affSColin Finck if (pan == NULL) {
676c2c66affSColin Finck WARN("invalid parameter: pan = NULL\n");
677c2c66affSColin Finck return DSERR_INVALIDPARAM;
678c2c66affSColin Finck }
679c2c66affSColin Finck
680c2c66affSColin Finck *pan = This->volpan.lPan;
681c2c66affSColin Finck
682c2c66affSColin Finck return DS_OK;
683c2c66affSColin Finck }
684c2c66affSColin Finck
IDirectSoundBufferImpl_Unlock(IDirectSoundBuffer8 * iface,void * p1,DWORD x1,void * p2,DWORD x2)685c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(IDirectSoundBuffer8 *iface, void *p1, DWORD x1,
686c2c66affSColin Finck void *p2, DWORD x2)
687c2c66affSColin Finck {
688c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface), *iter;
689c2c66affSColin Finck HRESULT hres = DS_OK;
690c2c66affSColin Finck
691c2c66affSColin Finck TRACE("(%p,%p,%d,%p,%d)\n", This,p1,x1,p2,x2);
692c2c66affSColin Finck
693c2c66affSColin Finck /* **** */
694c2c66affSColin Finck RtlAcquireResourceShared(&This->lock, TRUE);
695c2c66affSColin Finck
696c2c66affSColin Finck if (!(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
697c2c66affSColin Finck hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
698c2c66affSColin Finck if (hres != DS_OK)
699c2c66affSColin Finck WARN("IDsDriverBuffer_Unlock failed\n");
700c2c66affSColin Finck }
701c2c66affSColin Finck
702c2c66affSColin Finck RtlReleaseResource(&This->lock);
703c2c66affSColin Finck /* **** */
704c2c66affSColin Finck
705c2c66affSColin Finck if (!p2)
706c2c66affSColin Finck x2 = 0;
707c2c66affSColin Finck
708c2c66affSColin Finck if (!This->hwbuf && (x1 || x2))
709c2c66affSColin Finck {
710c2c66affSColin Finck RtlAcquireResourceShared(&This->device->buffer_list_lock, TRUE);
711c2c66affSColin Finck LIST_FOR_EACH_ENTRY(iter, &This->buffer->buffers, IDirectSoundBufferImpl, entry )
712c2c66affSColin Finck {
713c2c66affSColin Finck RtlAcquireResourceShared(&iter->lock, TRUE);
714c2c66affSColin Finck if (x1)
715c2c66affSColin Finck {
716c2c66affSColin Finck if(x1 + (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory > iter->buflen)
717c2c66affSColin Finck hres = DSERR_INVALIDPARAM;
718c2c66affSColin Finck else
719c2c66affSColin Finck DSOUND_MixToTemporary(iter, (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory, x1, FALSE);
720c2c66affSColin Finck }
721c2c66affSColin Finck if (x2)
722c2c66affSColin Finck DSOUND_MixToTemporary(iter, 0, x2, FALSE);
723c2c66affSColin Finck RtlReleaseResource(&iter->lock);
724c2c66affSColin Finck }
725c2c66affSColin Finck RtlReleaseResource(&This->device->buffer_list_lock);
726c2c66affSColin Finck }
727c2c66affSColin Finck
728c2c66affSColin Finck return hres;
729c2c66affSColin Finck }
730c2c66affSColin Finck
IDirectSoundBufferImpl_Restore(IDirectSoundBuffer8 * iface)731c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_Restore(IDirectSoundBuffer8 *iface)
732c2c66affSColin Finck {
733c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
734c2c66affSColin Finck
735c2c66affSColin Finck FIXME("(%p):stub\n",This);
736c2c66affSColin Finck return DS_OK;
737c2c66affSColin Finck }
738c2c66affSColin Finck
IDirectSoundBufferImpl_GetFrequency(IDirectSoundBuffer8 * iface,DWORD * freq)739c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(IDirectSoundBuffer8 *iface, DWORD *freq)
740c2c66affSColin Finck {
741c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
742c2c66affSColin Finck
743c2c66affSColin Finck TRACE("(%p,%p)\n",This,freq);
744c2c66affSColin Finck
745c2c66affSColin Finck if (freq == NULL) {
746c2c66affSColin Finck WARN("invalid parameter: freq = NULL\n");
747c2c66affSColin Finck return DSERR_INVALIDPARAM;
748c2c66affSColin Finck }
749c2c66affSColin Finck
750c2c66affSColin Finck *freq = This->freq;
751c2c66affSColin Finck TRACE("-> %d\n", *freq);
752c2c66affSColin Finck
753c2c66affSColin Finck return DS_OK;
754c2c66affSColin Finck }
755c2c66affSColin Finck
IDirectSoundBufferImpl_SetFX(IDirectSoundBuffer8 * iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,DWORD * pdwResultCodes)756c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(IDirectSoundBuffer8 *iface, DWORD dwEffectsCount,
757c2c66affSColin Finck LPDSEFFECTDESC pDSFXDesc, DWORD *pdwResultCodes)
758c2c66affSColin Finck {
759c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
760c2c66affSColin Finck DWORD u;
761c2c66affSColin Finck
762c2c66affSColin Finck FIXME("(%p,%u,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
763c2c66affSColin Finck
764c2c66affSColin Finck if (pdwResultCodes)
765c2c66affSColin Finck for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
766c2c66affSColin Finck
767c2c66affSColin Finck WARN("control unavailable\n");
768c2c66affSColin Finck return DSERR_CONTROLUNAVAIL;
769c2c66affSColin Finck }
770c2c66affSColin Finck
IDirectSoundBufferImpl_AcquireResources(IDirectSoundBuffer8 * iface,DWORD dwFlags,DWORD dwEffectsCount,DWORD * pdwResultCodes)771c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(IDirectSoundBuffer8 *iface,
772c2c66affSColin Finck DWORD dwFlags, DWORD dwEffectsCount, DWORD *pdwResultCodes)
773c2c66affSColin Finck {
774c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
775c2c66affSColin Finck DWORD u;
776c2c66affSColin Finck
777c2c66affSColin Finck FIXME("(%p,%08u,%u,%p): stub, faking success\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
778c2c66affSColin Finck
779c2c66affSColin Finck if (pdwResultCodes)
780c2c66affSColin Finck for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
781c2c66affSColin Finck
782c2c66affSColin Finck WARN("control unavailable\n");
783c2c66affSColin Finck return DS_OK;
784c2c66affSColin Finck }
785c2c66affSColin Finck
IDirectSoundBufferImpl_GetObjectInPath(IDirectSoundBuffer8 * iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,void ** ppObject)786c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(IDirectSoundBuffer8 *iface,
787c2c66affSColin Finck REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, void **ppObject)
788c2c66affSColin Finck {
789c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
790c2c66affSColin Finck
791c2c66affSColin Finck FIXME("(%p,%s,%u,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
792c2c66affSColin Finck
793c2c66affSColin Finck WARN("control unavailable\n");
794c2c66affSColin Finck return DSERR_CONTROLUNAVAIL;
795c2c66affSColin Finck }
796c2c66affSColin Finck
IDirectSoundBufferImpl_Initialize(IDirectSoundBuffer8 * iface,IDirectSound * dsound,LPCDSBUFFERDESC dbsd)797c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(IDirectSoundBuffer8 *iface,
798c2c66affSColin Finck IDirectSound *dsound, LPCDSBUFFERDESC dbsd)
799c2c66affSColin Finck {
800c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
801c2c66affSColin Finck
802c2c66affSColin Finck WARN("(%p) already initialized\n", This);
803c2c66affSColin Finck return DSERR_ALREADYINITIALIZED;
804c2c66affSColin Finck }
805c2c66affSColin Finck
IDirectSoundBufferImpl_GetCaps(IDirectSoundBuffer8 * iface,LPDSBCAPS caps)806c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(IDirectSoundBuffer8 *iface, LPDSBCAPS caps)
807c2c66affSColin Finck {
808c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
809c2c66affSColin Finck
810c2c66affSColin Finck TRACE("(%p)->(%p)\n",This,caps);
811c2c66affSColin Finck
812c2c66affSColin Finck if (caps == NULL) {
813c2c66affSColin Finck WARN("invalid parameter: caps == NULL\n");
814c2c66affSColin Finck return DSERR_INVALIDPARAM;
815c2c66affSColin Finck }
816c2c66affSColin Finck
817c2c66affSColin Finck if (caps->dwSize < sizeof(*caps)) {
818c2c66affSColin Finck WARN("invalid parameter: caps->dwSize = %d\n",caps->dwSize);
819c2c66affSColin Finck return DSERR_INVALIDPARAM;
820c2c66affSColin Finck }
821c2c66affSColin Finck
822c2c66affSColin Finck caps->dwFlags = This->dsbd.dwFlags;
823c2c66affSColin Finck if (This->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
824c2c66affSColin Finck else caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
825c2c66affSColin Finck
826c2c66affSColin Finck caps->dwBufferBytes = This->buflen;
827c2c66affSColin Finck
828c2c66affSColin Finck /* According to windows, this is zero*/
829c2c66affSColin Finck caps->dwUnlockTransferRate = 0;
830c2c66affSColin Finck caps->dwPlayCpuOverhead = 0;
831c2c66affSColin Finck
832c2c66affSColin Finck return DS_OK;
833c2c66affSColin Finck }
834c2c66affSColin Finck
IDirectSoundBufferImpl_QueryInterface(IDirectSoundBuffer8 * iface,REFIID riid,void ** ppobj)835c2c66affSColin Finck static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(IDirectSoundBuffer8 *iface, REFIID riid,
836c2c66affSColin Finck void **ppobj)
837c2c66affSColin Finck {
838c2c66affSColin Finck IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface);
839c2c66affSColin Finck
840c2c66affSColin Finck TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
841c2c66affSColin Finck
842c2c66affSColin Finck if (ppobj == NULL) {
843c2c66affSColin Finck WARN("invalid parameter\n");
844c2c66affSColin Finck return E_INVALIDARG;
845c2c66affSColin Finck }
846c2c66affSColin Finck
847c2c66affSColin Finck *ppobj = NULL; /* assume failure */
848c2c66affSColin Finck
849c2c66affSColin Finck if ( IsEqualGUID(riid, &IID_IUnknown) ||
850c2c66affSColin Finck IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
851c2c66affSColin Finck IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
852c2c66affSColin Finck IDirectSoundBuffer8_AddRef(iface);
853c2c66affSColin Finck *ppobj = iface;
854c2c66affSColin Finck return S_OK;
855c2c66affSColin Finck }
856c2c66affSColin Finck
857c2c66affSColin Finck if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
858c2c66affSColin Finck if (!This->notify)
859c2c66affSColin Finck IDirectSoundNotifyImpl_Create(This, &(This->notify));
860c2c66affSColin Finck if (This->notify) {
861c2c66affSColin Finck IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
862c2c66affSColin Finck *ppobj = This->notify;
863c2c66affSColin Finck return S_OK;
864c2c66affSColin Finck }
865c2c66affSColin Finck WARN("IID_IDirectSoundNotify\n");
866c2c66affSColin Finck return E_NOINTERFACE;
867c2c66affSColin Finck }
868c2c66affSColin Finck
869c2c66affSColin Finck if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
870c2c66affSColin Finck if (!This->ds3db)
871c2c66affSColin Finck IDirectSound3DBufferImpl_Create(This, &(This->ds3db));
872c2c66affSColin Finck if (This->ds3db) {
873c2c66affSColin Finck IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->ds3db);
874c2c66affSColin Finck *ppobj = This->ds3db;
875c2c66affSColin Finck return S_OK;
876c2c66affSColin Finck }
877c2c66affSColin Finck WARN("IID_IDirectSound3DBuffer\n");
878c2c66affSColin Finck return E_NOINTERFACE;
879c2c66affSColin Finck }
880c2c66affSColin Finck
881c2c66affSColin Finck if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
882c2c66affSColin Finck ERR("app requested IDirectSound3DListener on secondary buffer\n");
883c2c66affSColin Finck return E_NOINTERFACE;
884c2c66affSColin Finck }
885c2c66affSColin Finck
886c2c66affSColin Finck if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
887c2c66affSColin Finck if (!This->iks)
888c2c66affSColin Finck IKsBufferPropertySetImpl_Create(This, &(This->iks));
889c2c66affSColin Finck if (This->iks) {
890c2c66affSColin Finck IKsPropertySet_AddRef((LPKSPROPERTYSET)This->iks);
891c2c66affSColin Finck *ppobj = This->iks;
892c2c66affSColin Finck return S_OK;
893c2c66affSColin Finck }
894c2c66affSColin Finck WARN("IID_IKsPropertySet\n");
895c2c66affSColin Finck return E_NOINTERFACE;
896c2c66affSColin Finck }
897c2c66affSColin Finck
898c2c66affSColin Finck FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
899c2c66affSColin Finck
900c2c66affSColin Finck return E_NOINTERFACE;
901c2c66affSColin Finck }
902c2c66affSColin Finck
903c2c66affSColin Finck static const IDirectSoundBuffer8Vtbl dsbvt =
904c2c66affSColin Finck {
905c2c66affSColin Finck IDirectSoundBufferImpl_QueryInterface,
906c2c66affSColin Finck IDirectSoundBufferImpl_AddRef,
907c2c66affSColin Finck IDirectSoundBufferImpl_Release,
908c2c66affSColin Finck IDirectSoundBufferImpl_GetCaps,
909c2c66affSColin Finck IDirectSoundBufferImpl_GetCurrentPosition,
910c2c66affSColin Finck IDirectSoundBufferImpl_GetFormat,
911c2c66affSColin Finck IDirectSoundBufferImpl_GetVolume,
912c2c66affSColin Finck IDirectSoundBufferImpl_GetPan,
913c2c66affSColin Finck IDirectSoundBufferImpl_GetFrequency,
914c2c66affSColin Finck IDirectSoundBufferImpl_GetStatus,
915c2c66affSColin Finck IDirectSoundBufferImpl_Initialize,
916c2c66affSColin Finck IDirectSoundBufferImpl_Lock,
917c2c66affSColin Finck IDirectSoundBufferImpl_Play,
918c2c66affSColin Finck IDirectSoundBufferImpl_SetCurrentPosition,
919c2c66affSColin Finck IDirectSoundBufferImpl_SetFormat,
920c2c66affSColin Finck IDirectSoundBufferImpl_SetVolume,
921c2c66affSColin Finck IDirectSoundBufferImpl_SetPan,
922c2c66affSColin Finck IDirectSoundBufferImpl_SetFrequency,
923c2c66affSColin Finck IDirectSoundBufferImpl_Stop,
924c2c66affSColin Finck IDirectSoundBufferImpl_Unlock,
925c2c66affSColin Finck IDirectSoundBufferImpl_Restore,
926c2c66affSColin Finck IDirectSoundBufferImpl_SetFX,
927c2c66affSColin Finck IDirectSoundBufferImpl_AcquireResources,
928c2c66affSColin Finck IDirectSoundBufferImpl_GetObjectInPath
929c2c66affSColin Finck };
930c2c66affSColin Finck
IDirectSoundBufferImpl_Create(DirectSoundDevice * device,IDirectSoundBufferImpl ** pdsb,LPCDSBUFFERDESC dsbd)931c2c66affSColin Finck HRESULT IDirectSoundBufferImpl_Create(
932c2c66affSColin Finck DirectSoundDevice * device,
933c2c66affSColin Finck IDirectSoundBufferImpl **pdsb,
934c2c66affSColin Finck LPCDSBUFFERDESC dsbd)
935c2c66affSColin Finck {
936c2c66affSColin Finck IDirectSoundBufferImpl *dsb;
937c2c66affSColin Finck LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
938c2c66affSColin Finck HRESULT err = DS_OK;
939c2c66affSColin Finck DWORD capf = 0;
940c2c66affSColin Finck int use_hw;
941c2c66affSColin Finck TRACE("(%p,%p,%p)\n",device,pdsb,dsbd);
942c2c66affSColin Finck
943c2c66affSColin Finck if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
944c2c66affSColin Finck WARN("invalid parameter: dsbd->dwBufferBytes = %d\n", dsbd->dwBufferBytes);
945c2c66affSColin Finck *pdsb = NULL;
946c2c66affSColin Finck return DSERR_INVALIDPARAM; /* FIXME: which error? */
947c2c66affSColin Finck }
948c2c66affSColin Finck
949c2c66affSColin Finck dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
950c2c66affSColin Finck
951c2c66affSColin Finck if (dsb == 0) {
952c2c66affSColin Finck WARN("out of memory\n");
953c2c66affSColin Finck *pdsb = NULL;
954c2c66affSColin Finck return DSERR_OUTOFMEMORY;
955c2c66affSColin Finck }
956c2c66affSColin Finck
957c2c66affSColin Finck TRACE("Created buffer at %p\n", dsb);
958c2c66affSColin Finck
959c2c66affSColin Finck dsb->ref = 1;
960c2c66affSColin Finck dsb->numIfaces = 1;
961c2c66affSColin Finck dsb->device = device;
962c2c66affSColin Finck dsb->IDirectSoundBuffer8_iface.lpVtbl = &dsbvt;
963c2c66affSColin Finck dsb->iks = NULL;
964c2c66affSColin Finck
965c2c66affSColin Finck /* size depends on version */
966c2c66affSColin Finck CopyMemory(&dsb->dsbd, dsbd, dsbd->dwSize);
967c2c66affSColin Finck
968c2c66affSColin Finck dsb->pwfx = DSOUND_CopyFormat(wfex);
969c2c66affSColin Finck if (dsb->pwfx == NULL) {
970c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb);
971c2c66affSColin Finck *pdsb = NULL;
972c2c66affSColin Finck return DSERR_OUTOFMEMORY;
973c2c66affSColin Finck }
974c2c66affSColin Finck
975c2c66affSColin Finck if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign)
976c2c66affSColin Finck dsb->buflen = dsbd->dwBufferBytes +
977c2c66affSColin Finck (dsbd->lpwfxFormat->nBlockAlign -
978c2c66affSColin Finck (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign));
979c2c66affSColin Finck else
980c2c66affSColin Finck dsb->buflen = dsbd->dwBufferBytes;
981c2c66affSColin Finck
982c2c66affSColin Finck dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
983c2c66affSColin Finck dsb->notify = NULL;
984c2c66affSColin Finck dsb->notifies = NULL;
985c2c66affSColin Finck dsb->nrofnotifies = 0;
986c2c66affSColin Finck dsb->hwnotify = 0;
987c2c66affSColin Finck
988c2c66affSColin Finck /* Check necessary hardware mixing capabilities */
989c2c66affSColin Finck if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
990c2c66affSColin Finck else capf |= DSCAPS_SECONDARYMONO;
991c2c66affSColin Finck if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
992c2c66affSColin Finck else capf |= DSCAPS_SECONDARY8BIT;
993c2c66affSColin Finck
994c2c66affSColin Finck use_hw = !!(dsbd->dwFlags & DSBCAPS_LOCHARDWARE);
995c2c66affSColin Finck TRACE("use_hw = %d, capf = 0x%08x, device->drvcaps.dwFlags = 0x%08x\n", use_hw, capf, device->drvcaps.dwFlags);
996c2c66affSColin Finck if (use_hw && ((device->drvcaps.dwFlags & capf) != capf || !device->driver))
997c2c66affSColin Finck {
998c2c66affSColin Finck if (device->driver)
999c2c66affSColin Finck WARN("Format not supported for hardware buffer\n");
1000c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->pwfx);
1001c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb);
1002c2c66affSColin Finck *pdsb = NULL;
1003c2c66affSColin Finck if ((device->drvcaps.dwFlags & capf) != capf)
1004c2c66affSColin Finck return DSERR_BADFORMAT;
1005c2c66affSColin Finck return DSERR_GENERIC;
1006c2c66affSColin Finck }
1007c2c66affSColin Finck
1008c2c66affSColin Finck /* FIXME: check hardware sample rate mixing capabilities */
1009c2c66affSColin Finck /* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */
1010c2c66affSColin Finck /* FIXME: check whether any hardware buffers are left */
1011c2c66affSColin Finck /* FIXME: handle DSDHEAP_CREATEHEAP for hardware buffers */
1012c2c66affSColin Finck
1013c2c66affSColin Finck /* Allocate an empty buffer */
1014c2c66affSColin Finck dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
1015c2c66affSColin Finck if (dsb->buffer == NULL) {
1016c2c66affSColin Finck WARN("out of memory\n");
1017c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->pwfx);
1018c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb);
1019c2c66affSColin Finck *pdsb = NULL;
1020c2c66affSColin Finck return DSERR_OUTOFMEMORY;
1021c2c66affSColin Finck }
1022c2c66affSColin Finck
1023c2c66affSColin Finck /* Allocate system memory for buffer if applicable */
1024c2c66affSColin Finck if ((device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
1025c2c66affSColin Finck dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen);
1026c2c66affSColin Finck if (dsb->buffer->memory == NULL) {
1027c2c66affSColin Finck WARN("out of memory\n");
1028c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->pwfx);
1029c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->buffer);
1030c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb);
1031c2c66affSColin Finck *pdsb = NULL;
1032c2c66affSColin Finck return DSERR_OUTOFMEMORY;
1033c2c66affSColin Finck }
1034c2c66affSColin Finck }
1035c2c66affSColin Finck
1036c2c66affSColin Finck /* Allocate the hardware buffer */
1037c2c66affSColin Finck if (use_hw) {
1038c2c66affSColin Finck err = IDsDriver_CreateSoundBuffer(device->driver,wfex,dsbd->dwFlags,0,
1039c2c66affSColin Finck &(dsb->buflen),&(dsb->buffer->memory),
1040c2c66affSColin Finck (LPVOID*)&(dsb->hwbuf));
1041c2c66affSColin Finck if (FAILED(err))
1042c2c66affSColin Finck {
1043c2c66affSColin Finck WARN("Failed to create hardware secondary buffer: %08x\n", err);
1044c2c66affSColin Finck if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)
1045c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
1046c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->buffer);
1047c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->pwfx);
1048c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb);
1049c2c66affSColin Finck *pdsb = NULL;
1050c2c66affSColin Finck return DSERR_GENERIC;
1051c2c66affSColin Finck }
1052c2c66affSColin Finck }
1053c2c66affSColin Finck
1054c2c66affSColin Finck dsb->buffer->ref = 1;
1055c2c66affSColin Finck list_init(&dsb->buffer->buffers);
1056c2c66affSColin Finck list_add_head(&dsb->buffer->buffers, &dsb->entry);
1057c2c66affSColin Finck FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0);
1058c2c66affSColin Finck
1059c2c66affSColin Finck /* It's not necessary to initialize values to zero since */
1060c2c66affSColin Finck /* we allocated this structure with HEAP_ZERO_MEMORY... */
1061c2c66affSColin Finck dsb->buf_mixpos = dsb->sec_mixpos = 0;
1062c2c66affSColin Finck dsb->state = STATE_STOPPED;
1063c2c66affSColin Finck
1064c2c66affSColin Finck dsb->freqAdjust = ((DWORD64)dsb->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec;
1065c2c66affSColin Finck dsb->nAvgBytesPerSec = dsb->freq *
1066c2c66affSColin Finck dsbd->lpwfxFormat->nBlockAlign;
1067c2c66affSColin Finck
1068c2c66affSColin Finck /* calculate fragment size and write lead */
1069c2c66affSColin Finck DSOUND_RecalcFormat(dsb);
1070c2c66affSColin Finck
1071c2c66affSColin Finck if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
1072c2c66affSColin Finck dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
1073c2c66affSColin Finck dsb->ds3db_ds3db.vPosition.x = 0.0;
1074c2c66affSColin Finck dsb->ds3db_ds3db.vPosition.y = 0.0;
1075c2c66affSColin Finck dsb->ds3db_ds3db.vPosition.z = 0.0;
1076c2c66affSColin Finck dsb->ds3db_ds3db.vVelocity.x = 0.0;
1077c2c66affSColin Finck dsb->ds3db_ds3db.vVelocity.y = 0.0;
1078c2c66affSColin Finck dsb->ds3db_ds3db.vVelocity.z = 0.0;
1079c2c66affSColin Finck dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
1080c2c66affSColin Finck dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
1081c2c66affSColin Finck dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
1082c2c66affSColin Finck dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
1083c2c66affSColin Finck dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
1084c2c66affSColin Finck dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
1085c2c66affSColin Finck dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
1086c2c66affSColin Finck dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
1087c2c66affSColin Finck dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
1088c2c66affSColin Finck
1089c2c66affSColin Finck dsb->ds3db_need_recalc = FALSE;
1090c2c66affSColin Finck DSOUND_Calc3DBuffer(dsb);
1091c2c66affSColin Finck } else
1092c2c66affSColin Finck DSOUND_RecalcVolPan(&(dsb->volpan));
1093c2c66affSColin Finck
1094c2c66affSColin Finck RtlInitializeResource(&dsb->lock);
1095c2c66affSColin Finck
1096c2c66affSColin Finck /* register buffer if not primary */
1097c2c66affSColin Finck if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
1098c2c66affSColin Finck err = DirectSoundDevice_AddBuffer(device, dsb);
1099c2c66affSColin Finck if (err != DS_OK) {
1100c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
1101c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->buffer);
1102c2c66affSColin Finck RtlDeleteResource(&dsb->lock);
1103c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->pwfx);
1104c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb);
1105c2c66affSColin Finck dsb = NULL;
1106c2c66affSColin Finck }
1107c2c66affSColin Finck }
1108c2c66affSColin Finck
1109c2c66affSColin Finck *pdsb = dsb;
1110c2c66affSColin Finck return err;
1111c2c66affSColin Finck }
1112c2c66affSColin Finck
secondarybuffer_destroy(IDirectSoundBufferImpl * This)1113c2c66affSColin Finck void secondarybuffer_destroy(IDirectSoundBufferImpl *This)
1114c2c66affSColin Finck {
1115c2c66affSColin Finck DirectSoundDevice_RemoveBuffer(This->device, This);
1116c2c66affSColin Finck RtlDeleteResource(&This->lock);
1117c2c66affSColin Finck
1118c2c66affSColin Finck if (This->hwbuf)
1119c2c66affSColin Finck IDsDriverBuffer_Release(This->hwbuf);
1120c2c66affSColin Finck if (!This->hwbuf || (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)) {
1121c2c66affSColin Finck This->buffer->ref--;
1122c2c66affSColin Finck list_remove(&This->entry);
1123c2c66affSColin Finck if (This->buffer->ref == 0) {
1124c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->buffer->memory);
1125c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->buffer);
1126c2c66affSColin Finck }
1127c2c66affSColin Finck }
1128c2c66affSColin Finck
1129c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->tmp_buffer);
1130c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->notifies);
1131c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This->pwfx);
1132c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This);
1133c2c66affSColin Finck
1134c2c66affSColin Finck TRACE("(%p) released\n", This);
1135c2c66affSColin Finck }
1136c2c66affSColin Finck
IDirectSoundBufferImpl_Destroy(IDirectSoundBufferImpl * pdsb)1137c2c66affSColin Finck HRESULT IDirectSoundBufferImpl_Destroy(
1138c2c66affSColin Finck IDirectSoundBufferImpl *pdsb)
1139c2c66affSColin Finck {
1140c2c66affSColin Finck TRACE("(%p)\n",pdsb);
1141c2c66affSColin Finck
1142c2c66affSColin Finck /* This keeps the *_Destroy functions from possibly deleting
1143c2c66affSColin Finck * this object until it is ready to be deleted */
1144c2c66affSColin Finck InterlockedIncrement(&pdsb->numIfaces);
1145c2c66affSColin Finck
1146c2c66affSColin Finck if (pdsb->iks) {
1147c2c66affSColin Finck WARN("iks not NULL\n");
1148c2c66affSColin Finck IKsBufferPropertySetImpl_Destroy(pdsb->iks);
1149c2c66affSColin Finck pdsb->iks = NULL;
1150c2c66affSColin Finck }
1151c2c66affSColin Finck
1152c2c66affSColin Finck if (pdsb->ds3db) {
1153c2c66affSColin Finck WARN("ds3db not NULL\n");
1154c2c66affSColin Finck IDirectSound3DBufferImpl_Destroy(pdsb->ds3db);
1155c2c66affSColin Finck pdsb->ds3db = NULL;
1156c2c66affSColin Finck }
1157c2c66affSColin Finck
1158c2c66affSColin Finck if (pdsb->notify) {
1159c2c66affSColin Finck WARN("notify not NULL\n");
1160c2c66affSColin Finck IDirectSoundNotifyImpl_Destroy(pdsb->notify);
1161c2c66affSColin Finck pdsb->notify = NULL;
1162c2c66affSColin Finck }
1163c2c66affSColin Finck
1164c2c66affSColin Finck secondarybuffer_destroy(pdsb);
1165c2c66affSColin Finck
1166c2c66affSColin Finck return S_OK;
1167c2c66affSColin Finck }
1168c2c66affSColin Finck
IDirectSoundBufferImpl_Duplicate(DirectSoundDevice * device,IDirectSoundBufferImpl ** ppdsb,IDirectSoundBufferImpl * pdsb)1169c2c66affSColin Finck HRESULT IDirectSoundBufferImpl_Duplicate(
1170c2c66affSColin Finck DirectSoundDevice *device,
1171c2c66affSColin Finck IDirectSoundBufferImpl **ppdsb,
1172c2c66affSColin Finck IDirectSoundBufferImpl *pdsb)
1173c2c66affSColin Finck {
1174c2c66affSColin Finck IDirectSoundBufferImpl *dsb;
1175c2c66affSColin Finck HRESULT hres = DS_OK;
1176c2c66affSColin Finck TRACE("(%p,%p,%p)\n", device, ppdsb, pdsb);
1177c2c66affSColin Finck
1178c2c66affSColin Finck dsb = HeapAlloc(GetProcessHeap(),0,sizeof(*dsb));
1179c2c66affSColin Finck if (dsb == NULL) {
1180c2c66affSColin Finck WARN("out of memory\n");
1181c2c66affSColin Finck *ppdsb = NULL;
1182c2c66affSColin Finck return DSERR_OUTOFMEMORY;
1183c2c66affSColin Finck }
1184c2c66affSColin Finck CopyMemory(dsb, pdsb, sizeof(*dsb));
1185c2c66affSColin Finck
1186c2c66affSColin Finck dsb->pwfx = DSOUND_CopyFormat(pdsb->pwfx);
1187c2c66affSColin Finck if (dsb->pwfx == NULL) {
1188c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb);
1189c2c66affSColin Finck *ppdsb = NULL;
1190c2c66affSColin Finck return DSERR_OUTOFMEMORY;
1191c2c66affSColin Finck }
1192c2c66affSColin Finck
1193c2c66affSColin Finck if (pdsb->hwbuf) {
1194c2c66affSColin Finck TRACE("duplicating hardware buffer\n");
1195c2c66affSColin Finck
1196c2c66affSColin Finck hres = IDsDriver_DuplicateSoundBuffer(device->driver, pdsb->hwbuf,
1197c2c66affSColin Finck (LPVOID *)&dsb->hwbuf);
1198c2c66affSColin Finck if (FAILED(hres)) {
1199c2c66affSColin Finck WARN("IDsDriver_DuplicateSoundBuffer failed (%08x)\n", hres);
1200c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->pwfx);
1201c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb);
1202c2c66affSColin Finck *ppdsb = NULL;
1203c2c66affSColin Finck return hres;
1204c2c66affSColin Finck }
1205c2c66affSColin Finck }
1206c2c66affSColin Finck
1207c2c66affSColin Finck dsb->buffer->ref++;
1208c2c66affSColin Finck list_add_head(&dsb->buffer->buffers, &dsb->entry);
1209c2c66affSColin Finck dsb->ref = 1;
1210c2c66affSColin Finck dsb->numIfaces = 1;
1211c2c66affSColin Finck dsb->state = STATE_STOPPED;
1212c2c66affSColin Finck dsb->buf_mixpos = dsb->sec_mixpos = 0;
1213c2c66affSColin Finck dsb->notify = NULL;
1214c2c66affSColin Finck dsb->notifies = NULL;
1215c2c66affSColin Finck dsb->nrofnotifies = 0;
1216c2c66affSColin Finck dsb->device = device;
1217c2c66affSColin Finck dsb->ds3db = NULL;
1218c2c66affSColin Finck dsb->iks = NULL; /* FIXME? */
1219c2c66affSColin Finck dsb->tmp_buffer = NULL;
1220c2c66affSColin Finck DSOUND_RecalcFormat(dsb);
1221c2c66affSColin Finck DSOUND_MixToTemporary(dsb, 0, dsb->buflen, FALSE);
1222c2c66affSColin Finck
1223c2c66affSColin Finck RtlInitializeResource(&dsb->lock);
1224c2c66affSColin Finck
1225c2c66affSColin Finck /* register buffer */
1226c2c66affSColin Finck hres = DirectSoundDevice_AddBuffer(device, dsb);
1227c2c66affSColin Finck if (hres != DS_OK) {
1228c2c66affSColin Finck RtlDeleteResource(&dsb->lock);
1229c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->tmp_buffer);
1230c2c66affSColin Finck list_remove(&dsb->entry);
1231c2c66affSColin Finck dsb->buffer->ref--;
1232c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb->pwfx);
1233c2c66affSColin Finck HeapFree(GetProcessHeap(),0,dsb);
1234c2c66affSColin Finck dsb = NULL;
1235c2c66affSColin Finck }
1236c2c66affSColin Finck
1237c2c66affSColin Finck *ppdsb = dsb;
1238c2c66affSColin Finck return hres;
1239c2c66affSColin Finck }
1240c2c66affSColin Finck
1241c2c66affSColin Finck /*******************************************************************************
1242c2c66affSColin Finck * IKsBufferPropertySet
1243c2c66affSColin Finck */
1244c2c66affSColin Finck
1245c2c66affSColin Finck /* IUnknown methods */
IKsBufferPropertySetImpl_QueryInterface(LPKSPROPERTYSET iface,REFIID riid,LPVOID * ppobj)1246c2c66affSColin Finck static HRESULT WINAPI IKsBufferPropertySetImpl_QueryInterface(
1247c2c66affSColin Finck LPKSPROPERTYSET iface,
1248c2c66affSColin Finck REFIID riid,
1249c2c66affSColin Finck LPVOID *ppobj )
1250c2c66affSColin Finck {
1251c2c66affSColin Finck IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1252c2c66affSColin Finck TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1253c2c66affSColin Finck
1254c2c66affSColin Finck return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
1255c2c66affSColin Finck }
1256c2c66affSColin Finck
IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)1257c2c66affSColin Finck static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface)
1258c2c66affSColin Finck {
1259c2c66affSColin Finck IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1260c2c66affSColin Finck ULONG ref = InterlockedIncrement(&(This->ref));
1261c2c66affSColin Finck TRACE("(%p) ref was %d\n", This, ref - 1);
1262c2c66affSColin Finck return ref;
1263c2c66affSColin Finck }
1264c2c66affSColin Finck
IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)1265c2c66affSColin Finck static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface)
1266c2c66affSColin Finck {
1267c2c66affSColin Finck IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1268c2c66affSColin Finck ULONG ref = InterlockedDecrement(&(This->ref));
1269c2c66affSColin Finck TRACE("(%p) ref was %d\n", This, ref + 1);
1270c2c66affSColin Finck
1271c2c66affSColin Finck if (!ref) {
1272c2c66affSColin Finck This->dsb->iks = 0;
1273c2c66affSColin Finck IDirectSoundBuffer_Release((LPDIRECTSOUND3DBUFFER)This->dsb);
1274c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This);
1275c2c66affSColin Finck TRACE("(%p) released\n", This);
1276c2c66affSColin Finck }
1277c2c66affSColin Finck return ref;
1278c2c66affSColin Finck }
1279c2c66affSColin Finck
IKsBufferPropertySetImpl_Get(LPKSPROPERTYSET iface,REFGUID guidPropSet,ULONG dwPropID,LPVOID pInstanceData,ULONG cbInstanceData,LPVOID pPropData,ULONG cbPropData,PULONG pcbReturned)1280c2c66affSColin Finck static HRESULT WINAPI IKsBufferPropertySetImpl_Get(
1281c2c66affSColin Finck LPKSPROPERTYSET iface,
1282c2c66affSColin Finck REFGUID guidPropSet,
1283c2c66affSColin Finck ULONG dwPropID,
1284c2c66affSColin Finck LPVOID pInstanceData,
1285c2c66affSColin Finck ULONG cbInstanceData,
1286c2c66affSColin Finck LPVOID pPropData,
1287c2c66affSColin Finck ULONG cbPropData,
1288c2c66affSColin Finck PULONG pcbReturned )
1289c2c66affSColin Finck {
1290c2c66affSColin Finck IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1291c2c66affSColin Finck PIDSDRIVERPROPERTYSET ps;
1292c2c66affSColin Finck TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n",
1293c2c66affSColin Finck This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned);
1294c2c66affSColin Finck
1295c2c66affSColin Finck if (This->dsb->hwbuf) {
1296c2c66affSColin Finck IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
1297c2c66affSColin Finck
1298c2c66affSColin Finck if (ps) {
1299c2c66affSColin Finck DSPROPERTY prop;
1300c2c66affSColin Finck HRESULT hres;
1301c2c66affSColin Finck
1302c2c66affSColin Finck prop.s.Set = *guidPropSet;
1303c2c66affSColin Finck prop.s.Id = dwPropID;
1304c2c66affSColin Finck prop.s.Flags = 0; /* unused */
1305*6b1ca758STimo Kreuzer prop.s.InstanceId = (ULONG_PTR)This->dsb->device;
1306c2c66affSColin Finck
1307c2c66affSColin Finck
1308c2c66affSColin Finck hres = IDsDriverPropertySet_Get(ps, &prop, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned);
1309c2c66affSColin Finck
1310c2c66affSColin Finck IDsDriverPropertySet_Release(ps);
1311c2c66affSColin Finck
1312c2c66affSColin Finck return hres;
1313c2c66affSColin Finck }
1314c2c66affSColin Finck }
1315c2c66affSColin Finck
1316c2c66affSColin Finck return E_PROP_ID_UNSUPPORTED;
1317c2c66affSColin Finck }
1318c2c66affSColin Finck
IKsBufferPropertySetImpl_Set(LPKSPROPERTYSET iface,REFGUID guidPropSet,ULONG dwPropID,LPVOID pInstanceData,ULONG cbInstanceData,LPVOID pPropData,ULONG cbPropData)1319c2c66affSColin Finck static HRESULT WINAPI IKsBufferPropertySetImpl_Set(
1320c2c66affSColin Finck LPKSPROPERTYSET iface,
1321c2c66affSColin Finck REFGUID guidPropSet,
1322c2c66affSColin Finck ULONG dwPropID,
1323c2c66affSColin Finck LPVOID pInstanceData,
1324c2c66affSColin Finck ULONG cbInstanceData,
1325c2c66affSColin Finck LPVOID pPropData,
1326c2c66affSColin Finck ULONG cbPropData )
1327c2c66affSColin Finck {
1328c2c66affSColin Finck IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1329c2c66affSColin Finck PIDSDRIVERPROPERTYSET ps;
1330c2c66affSColin Finck TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData);
1331c2c66affSColin Finck
1332c2c66affSColin Finck if (This->dsb->hwbuf) {
1333c2c66affSColin Finck IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
1334c2c66affSColin Finck
1335c2c66affSColin Finck if (ps) {
1336c2c66affSColin Finck DSPROPERTY prop;
1337c2c66affSColin Finck HRESULT hres;
1338c2c66affSColin Finck
1339c2c66affSColin Finck prop.s.Set = *guidPropSet;
1340c2c66affSColin Finck prop.s.Id = dwPropID;
1341c2c66affSColin Finck prop.s.Flags = 0; /* unused */
1342*6b1ca758STimo Kreuzer prop.s.InstanceId = (ULONG_PTR)This->dsb->device;
1343c2c66affSColin Finck hres = IDsDriverPropertySet_Set(ps,&prop,pInstanceData,cbInstanceData,pPropData,cbPropData);
1344c2c66affSColin Finck
1345c2c66affSColin Finck IDsDriverPropertySet_Release(ps);
1346c2c66affSColin Finck
1347c2c66affSColin Finck return hres;
1348c2c66affSColin Finck }
1349c2c66affSColin Finck }
1350c2c66affSColin Finck
1351c2c66affSColin Finck return E_PROP_ID_UNSUPPORTED;
1352c2c66affSColin Finck }
1353c2c66affSColin Finck
IKsBufferPropertySetImpl_QuerySupport(LPKSPROPERTYSET iface,REFGUID guidPropSet,ULONG dwPropID,PULONG pTypeSupport)1354c2c66affSColin Finck static HRESULT WINAPI IKsBufferPropertySetImpl_QuerySupport(
1355c2c66affSColin Finck LPKSPROPERTYSET iface,
1356c2c66affSColin Finck REFGUID guidPropSet,
1357c2c66affSColin Finck ULONG dwPropID,
1358c2c66affSColin Finck PULONG pTypeSupport )
1359c2c66affSColin Finck {
1360c2c66affSColin Finck IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface;
1361c2c66affSColin Finck PIDSDRIVERPROPERTYSET ps;
1362c2c66affSColin Finck TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport);
1363c2c66affSColin Finck
1364c2c66affSColin Finck if (This->dsb->hwbuf) {
1365c2c66affSColin Finck IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps);
1366c2c66affSColin Finck
1367c2c66affSColin Finck if (ps) {
1368c2c66affSColin Finck HRESULT hres;
1369c2c66affSColin Finck
1370c2c66affSColin Finck hres = IDsDriverPropertySet_QuerySupport(ps,guidPropSet, dwPropID,pTypeSupport);
1371c2c66affSColin Finck
1372c2c66affSColin Finck IDsDriverPropertySet_Release(ps);
1373c2c66affSColin Finck
1374c2c66affSColin Finck return hres;
1375c2c66affSColin Finck }
1376c2c66affSColin Finck }
1377c2c66affSColin Finck
1378c2c66affSColin Finck return E_PROP_ID_UNSUPPORTED;
1379c2c66affSColin Finck }
1380c2c66affSColin Finck
1381c2c66affSColin Finck static const IKsPropertySetVtbl iksbvt = {
1382c2c66affSColin Finck IKsBufferPropertySetImpl_QueryInterface,
1383c2c66affSColin Finck IKsBufferPropertySetImpl_AddRef,
1384c2c66affSColin Finck IKsBufferPropertySetImpl_Release,
1385c2c66affSColin Finck IKsBufferPropertySetImpl_Get,
1386c2c66affSColin Finck IKsBufferPropertySetImpl_Set,
1387c2c66affSColin Finck IKsBufferPropertySetImpl_QuerySupport
1388c2c66affSColin Finck };
1389c2c66affSColin Finck
IKsBufferPropertySetImpl_Create(IDirectSoundBufferImpl * dsb,IKsBufferPropertySetImpl ** piks)1390c2c66affSColin Finck HRESULT IKsBufferPropertySetImpl_Create(
1391c2c66affSColin Finck IDirectSoundBufferImpl *dsb,
1392c2c66affSColin Finck IKsBufferPropertySetImpl **piks)
1393c2c66affSColin Finck {
1394c2c66affSColin Finck IKsBufferPropertySetImpl *iks;
1395c2c66affSColin Finck TRACE("(%p,%p)\n",dsb,piks);
1396c2c66affSColin Finck *piks = NULL;
1397c2c66affSColin Finck
1398c2c66affSColin Finck iks = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks));
1399c2c66affSColin Finck if (iks == 0) {
1400c2c66affSColin Finck WARN("out of memory\n");
1401c2c66affSColin Finck *piks = NULL;
1402c2c66affSColin Finck return DSERR_OUTOFMEMORY;
1403c2c66affSColin Finck }
1404c2c66affSColin Finck
1405c2c66affSColin Finck iks->ref = 0;
1406c2c66affSColin Finck iks->dsb = dsb;
1407c2c66affSColin Finck dsb->iks = iks;
1408c2c66affSColin Finck iks->lpVtbl = &iksbvt;
1409c2c66affSColin Finck
1410c2c66affSColin Finck IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
1411c2c66affSColin Finck
1412c2c66affSColin Finck *piks = iks;
1413c2c66affSColin Finck return S_OK;
1414c2c66affSColin Finck }
1415c2c66affSColin Finck
IKsBufferPropertySetImpl_Destroy(IKsBufferPropertySetImpl * piks)1416c2c66affSColin Finck HRESULT IKsBufferPropertySetImpl_Destroy(
1417c2c66affSColin Finck IKsBufferPropertySetImpl *piks)
1418c2c66affSColin Finck {
1419c2c66affSColin Finck TRACE("(%p)\n",piks);
1420c2c66affSColin Finck
1421c2c66affSColin Finck while (IKsBufferPropertySetImpl_Release((LPKSPROPERTYSET)piks) > 0);
1422c2c66affSColin Finck
1423c2c66affSColin Finck return S_OK;
1424c2c66affSColin Finck }
1425