xref: /reactos/dll/directx/wine/dsound/buffer.c (revision 6b1ca758)
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