Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / dsound / buffer.c
blob486bd0f763f1d94935084998faf4bf868bfa23e4
1 /* DirectSound
3 * Copyright 1998 Marcus Meissner
4 * Copyright 1998 Rob Riggs
5 * Copyright 2000-2002 TransGaming Technologies, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include <assert.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <sys/fcntl.h>
28 #ifdef HAVE_UNISTD_H
29 # include <unistd.h>
30 #endif
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>
35 #define NONAMELESSSTRUCT
36 #define NONAMELESSUNION
37 #include "windef.h"
38 #include "winbase.h"
39 #include "wingdi.h"
40 #include "winuser.h"
41 #include "winerror.h"
42 #include "mmsystem.h"
43 #include "winreg.h"
44 #include "winternl.h"
45 #include "mmddk.h"
46 #include "wine/windef16.h"
47 #include "wine/debug.h"
48 #include "dsound.h"
49 #include "dsdriver.h"
50 #include "dsound_private.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
54 /*******************************************************************************
55 * IDirectSoundNotify
57 static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
58 LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj
59 ) {
60 ICOM_THIS(IDirectSoundNotifyImpl,iface);
61 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
63 if (This->dsb == NULL) {
64 WARN("invalid parameter\n");
65 return E_INVALIDARG;
68 return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER)This->dsb, riid, ppobj);
71 static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) {
72 ICOM_THIS(IDirectSoundNotifyImpl,iface);
73 DWORD ref;
75 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
77 ref = InterlockedIncrement(&(This->ref));
78 return ref;
81 static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) {
82 ICOM_THIS(IDirectSoundNotifyImpl,iface);
83 DWORD ref;
85 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
87 ref = InterlockedDecrement(&(This->ref));
88 if (ref == 0) {
89 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb);
90 This->dsb->notify = NULL;
91 HeapFree(GetProcessHeap(),0,This);
92 TRACE("(%p) released\n",This);
94 return ref;
97 static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions(
98 LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify
99 ) {
100 ICOM_THIS(IDirectSoundNotifyImpl,iface);
101 TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify);
103 if (notify == NULL) {
104 WARN("invalid parameter: notify == NULL\n");
105 return DSERR_INVALIDPARAM;
108 if (TRACE_ON(dsound)) {
109 int i;
110 for (i=0;i<howmuch;i++)
111 TRACE("notify at %ld to 0x%08lx\n",
112 notify[i].dwOffset,(DWORD)notify[i].hEventNotify);
115 if (This->dsb->hwnotify) {
116 HRESULT hres;
117 hres = IDsDriverNotify_SetNotificationPositions(This->dsb->hwnotify, howmuch, notify);
118 if (hres != DS_OK)
119 WARN("IDsDriverNotify_SetNotificationPositions failed\n");
120 return hres;
121 } else {
122 /* Make an internal copy of the caller-supplied array.
123 * Replace the existing copy if one is already present. */
124 This->dsb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
125 This->dsb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY));
126 if (This->dsb->notifies == NULL) {
127 WARN("out of memory\n");
128 return DSERR_OUTOFMEMORY;
130 memcpy(This->dsb->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY));
131 This->dsb->nrofnotifies = howmuch;
134 return S_OK;
137 ICOM_VTABLE(IDirectSoundNotify) dsnvt =
139 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
140 IDirectSoundNotifyImpl_QueryInterface,
141 IDirectSoundNotifyImpl_AddRef,
142 IDirectSoundNotifyImpl_Release,
143 IDirectSoundNotifyImpl_SetNotificationPositions,
146 HRESULT WINAPI IDirectSoundNotifyImpl_Create(
147 IDirectSoundBufferImpl * dsb,
148 IDirectSoundNotifyImpl **pdsn)
150 IDirectSoundNotifyImpl * dsn;
151 TRACE("(%p,%p)\n",dsb,pdsn);
153 dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dsn));
155 if (dsn == NULL) {
156 WARN("out of memory\n");
157 return DSERR_OUTOFMEMORY;
160 dsn->ref = 0;
161 dsn->lpVtbl = &dsnvt;
162 dsn->dsb = dsb;
163 dsb->notify = dsn;
164 IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)dsb);
166 *pdsn = dsn;
167 return DS_OK;
170 /*******************************************************************************
171 * IDirectSoundBuffer
174 static HRESULT WINAPI IDirectSoundBufferImpl_SetFormat(
175 LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX wfex
177 ICOM_THIS(IDirectSoundBufferImpl,iface);
179 TRACE("(%p,%p)\n",This,wfex);
180 /* This method is not available on secondary buffers */
181 WARN("invalid call\n");
182 return DSERR_INVALIDCALL;
185 static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(
186 LPDIRECTSOUNDBUFFER8 iface,LONG vol
188 ICOM_THIS(IDirectSoundBufferImpl,iface);
189 LONG oldVol;
191 TRACE("(%p,%ld)\n",This,vol);
193 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
194 WARN("control unavailable: This->dsbd.dwFlags = 0x%08lx\n", This->dsbd.dwFlags);
195 return DSERR_CONTROLUNAVAIL;
198 if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) {
199 WARN("invalid parameter: vol = %ld\n", vol);
200 return DSERR_INVALIDPARAM;
203 /* **** */
204 EnterCriticalSection(&(This->lock));
206 if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) {
207 oldVol = This->ds3db_lVolume;
208 This->ds3db_lVolume = vol;
209 } else {
210 oldVol = This->volpan.lVolume;
211 This->volpan.lVolume = vol;
212 if (vol != oldVol)
213 DSOUND_RecalcVolPan(&(This->volpan));
216 if (vol != oldVol) {
217 if (This->hwbuf) {
218 HRESULT hres;
219 hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
220 if (hres != DS_OK)
221 WARN("IDsDriverBuffer_SetVolumePan failed\n");
222 } else
223 DSOUND_ForceRemix(This);
226 LeaveCriticalSection(&(This->lock));
227 /* **** */
229 return DS_OK;
232 static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(
233 LPDIRECTSOUNDBUFFER8 iface,LPLONG vol
235 ICOM_THIS(IDirectSoundBufferImpl,iface);
236 TRACE("(%p,%p)\n",This,vol);
238 if (vol == NULL) {
239 WARN("invalid parameter: vol == NULL\n");
240 return DSERR_INVALIDPARAM;
243 if (This->dsbd.dwFlags & DSBCAPS_CTRL3D)
244 *vol = This->ds3db_lVolume;
245 else
246 *vol = This->volpan.lVolume;
247 return DS_OK;
250 static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency(
251 LPDIRECTSOUNDBUFFER8 iface,DWORD freq
253 ICOM_THIS(IDirectSoundBufferImpl,iface);
254 DWORD oldFreq;
256 TRACE("(%p,%ld)\n",This,freq);
258 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
259 WARN("control unavailable\n");
260 return DSERR_CONTROLUNAVAIL;
263 if (freq == DSBFREQUENCY_ORIGINAL)
264 freq = This->wfx.nSamplesPerSec;
266 if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) {
267 WARN("invalid parameter: freq = %ld\n", freq);
268 return DSERR_INVALIDPARAM;
271 /* **** */
272 EnterCriticalSection(&(This->lock));
274 oldFreq = This->freq;
275 This->freq = freq;
276 if (freq != oldFreq) {
277 This->freqAdjust = (freq << DSOUND_FREQSHIFT) / This->dsound->wfx.nSamplesPerSec;
278 This->nAvgBytesPerSec = freq * This->wfx.nBlockAlign;
279 DSOUND_RecalcFormat(This);
280 if (!This->hwbuf)
281 DSOUND_ForceRemix(This);
284 LeaveCriticalSection(&(This->lock));
285 /* **** */
287 return DS_OK;
290 static HRESULT WINAPI IDirectSoundBufferImpl_Play(
291 LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags
293 HRESULT hres = DS_OK;
294 ICOM_THIS(IDirectSoundBufferImpl,iface);
295 TRACE("(%p,%08lx,%08lx,%08lx)\n",This,reserved1,reserved2,flags);
297 /* **** */
298 EnterCriticalSection(&(This->lock));
300 This->playflags = flags;
301 if (This->state == STATE_STOPPED) {
302 This->leadin = TRUE;
303 This->startpos = This->buf_mixpos;
304 This->state = STATE_STARTING;
305 } else if (This->state == STATE_STOPPING)
306 This->state = STATE_PLAYING;
307 if (This->hwbuf) {
308 hres = IDsDriverBuffer_Play(This->hwbuf, 0, 0, This->playflags);
309 if (hres != DS_OK)
310 WARN("IDsDriverBuffer_Play failed\n");
311 else
312 This->state = STATE_PLAYING;
315 LeaveCriticalSection(&(This->lock));
316 /* **** */
318 return hres;
321 static HRESULT WINAPI IDirectSoundBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface)
323 HRESULT hres = DS_OK;
324 ICOM_THIS(IDirectSoundBufferImpl,iface);
325 TRACE("(%p)\n",This);
327 /* **** */
328 EnterCriticalSection(&(This->lock));
330 if (This->state == STATE_PLAYING)
331 This->state = STATE_STOPPING;
332 else if (This->state == STATE_STARTING)
333 This->state = STATE_STOPPED;
334 if (This->hwbuf) {
335 hres = IDsDriverBuffer_Stop(This->hwbuf);
336 if (hres != DS_OK)
337 WARN("IDsDriverBuffer_Stop failed\n");
338 else
339 This->state = STATE_STOPPED;
341 DSOUND_CheckEvent(This, 0);
343 LeaveCriticalSection(&(This->lock));
344 /* **** */
346 return hres;
349 static DWORD WINAPI IDirectSoundBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) {
350 ICOM_THIS(IDirectSoundBufferImpl,iface);
351 DWORD ref;
353 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
355 ref = InterlockedIncrement(&(This->ref));
356 if (!ref) {
357 FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
359 return ref;
362 static DWORD WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) {
363 ICOM_THIS(IDirectSoundBufferImpl,iface);
364 int i;
365 DWORD ref;
367 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
369 ref = InterlockedDecrement(&(This->ref));
370 if (ref) return ref;
372 RtlAcquireResourceExclusive(&(This->dsound->lock), TRUE);
373 for (i=0;i<This->dsound->nrofbuffers;i++)
374 if (This->dsound->buffers[i] == This)
375 break;
376 if (i < This->dsound->nrofbuffers) {
377 /* Put the last buffer of the list in the (now empty) position */
378 This->dsound->buffers[i] = This->dsound->buffers[This->dsound->nrofbuffers - 1];
379 This->dsound->nrofbuffers--;
380 This->dsound->buffers = HeapReAlloc(GetProcessHeap(),0,This->dsound->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*This->dsound->nrofbuffers);
381 TRACE("buffer count is now %d\n", This->dsound->nrofbuffers);
382 IDirectSound_Release((LPDIRECTSOUND)This->dsound);
384 RtlReleaseResource(&(This->dsound->lock));
386 DeleteCriticalSection(&(This->lock));
388 if (This->hwbuf) {
389 IDsDriverBuffer_Release(This->hwbuf);
390 if (This->dsound->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
391 This->buffer->ref--;
392 if (This->buffer->ref==0) {
393 HeapFree(GetProcessHeap(),0,This->buffer->memory);
394 HeapFree(GetProcessHeap(),0,This->buffer);
397 } else {
398 This->buffer->ref--;
399 if (This->buffer->ref==0) {
400 HeapFree(GetProcessHeap(),0,This->buffer->memory);
401 HeapFree(GetProcessHeap(),0,This->buffer);
405 if (This->notifies != NULL)
406 HeapFree(GetProcessHeap(), 0, This->notifies);
408 HeapFree(GetProcessHeap(),0,This);
410 TRACE("(%p) released\n",This);
411 return 0;
414 DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This,
415 DWORD state, DWORD pplay, DWORD pwrite, DWORD pmix, DWORD bmix)
417 DWORD bplay;
419 TRACE("primary playpos=%ld, mixpos=%ld\n", pplay, pmix);
420 TRACE("this mixpos=%ld, time=%ld\n", bmix, GetTickCount());
422 /* the actual primary play position (pplay) is always behind last mixed (pmix),
423 * unless the computer is too slow or something */
424 /* we need to know how far away we are from there */
425 #if 0 /* we'll never fill the primary entirely */
426 if (pmix == pplay) {
427 if ((state == STATE_PLAYING) || (state == STATE_STOPPING)) {
428 /* wow, the software mixer is really doing well,
429 * seems the entire primary buffer is filled! */
430 pmix += This->dsound->buflen;
432 /* else: the primary buffer is not playing, so probably empty */
434 #endif
435 if (pmix < pplay) pmix += This->dsound->buflen; /* wraparound */
436 pmix -= pplay;
437 /* detect buffer underrun */
438 if (pwrite < pplay) pwrite += This->dsound->buflen; /* wraparound */
439 pwrite -= pplay;
440 if (pmix > (ds_snd_queue_max * This->dsound->fraglen + pwrite + This->dsound->writelead)) {
441 WARN("detected an underrun: primary queue was %ld\n",pmix);
442 pmix = 0;
444 /* divide the offset by its sample size */
445 pmix /= This->dsound->wfx.nBlockAlign;
446 TRACE("primary back-samples=%ld\n",pmix);
447 /* adjust for our frequency */
448 pmix = (pmix * This->freqAdjust) >> DSOUND_FREQSHIFT;
449 /* multiply by our own sample size */
450 pmix *= This->wfx.nBlockAlign;
451 TRACE("this back-offset=%ld\n", pmix);
452 /* subtract from our last mixed position */
453 bplay = bmix;
454 while (bplay < pmix) bplay += This->buflen; /* wraparound */
455 bplay -= pmix;
456 if (This->leadin && ((bplay < This->startpos) || (bplay > bmix))) {
457 /* seems we haven't started playing yet */
458 TRACE("this still in lead-in phase\n");
459 bplay = This->startpos;
461 /* return the result */
462 return bplay;
465 static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(
466 LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos
468 HRESULT hres;
469 ICOM_THIS(IDirectSoundBufferImpl,iface);
470 TRACE("(%p,%p,%p)\n",This,playpos,writepos);
471 if (This->hwbuf) {
472 hres=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos);
473 if (hres != DS_OK) {
474 WARN("IDsDriverBuffer_GetPosition failed\n");
475 return hres;
478 else {
479 if (playpos && (This->state != STATE_PLAYING)) {
480 /* we haven't been merged into the primary buffer (yet) */
481 *playpos = This->buf_mixpos;
483 else if (playpos) {
484 DWORD pplay, pwrite, lplay, splay, pstate;
485 /* let's get this exact; first, recursively call GetPosition on the primary */
486 EnterCriticalSection(&(This->dsound->mixlock));
487 if (DSOUND_PrimaryGetPosition(This->dsound, &pplay, &pwrite) != DS_OK)
488 WARN("DSOUND_PrimaryGetPosition failed\n");
489 /* detect HEL mode underrun */
490 pstate = This->dsound->state;
491 if (!(This->dsound->hwbuf || This->dsound->pwqueue)) {
492 TRACE("detected an underrun\n");
493 /* pplay = ? */
494 if (pstate == STATE_PLAYING)
495 pstate = STATE_STARTING;
496 else if (pstate == STATE_STOPPING)
497 pstate = STATE_STOPPED;
499 /* get data for ourselves while we still have the lock */
500 pstate &= This->state;
501 lplay = This->primary_mixpos;
502 splay = This->buf_mixpos;
503 if ((This->dsbd.dwFlags & DSBCAPS_GETCURRENTPOSITION2) || This->dsound->hwbuf) {
504 /* calculate play position using this */
505 *playpos = DSOUND_CalcPlayPosition(This, pstate, pplay, pwrite, lplay, splay);
506 } else {
507 /* (unless the app isn't using GETCURRENTPOSITION2) */
508 /* don't know exactly how this should be handled...
509 * the docs says that play cursor is reported as directly
510 * behind write cursor, hmm... */
511 /* let's just do what might work for Half-Life */
512 DWORD wp;
513 wp = (This->dsound->pwplay + ds_hel_margin) * This->dsound->fraglen;
514 while (wp >= This->dsound->buflen)
515 wp -= This->dsound->buflen;
516 *playpos = DSOUND_CalcPlayPosition(This, pstate, wp, pwrite, lplay, splay);
518 LeaveCriticalSection(&(This->dsound->mixlock));
520 if (writepos) *writepos = This->buf_mixpos;
522 if (writepos) {
523 if (This->state != STATE_STOPPED)
524 /* apply the documented 10ms lead to writepos */
525 *writepos += This->writelead;
526 while (*writepos >= This->buflen) *writepos -= This->buflen;
528 if (playpos) This->last_playpos = *playpos;
529 TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, This, GetTickCount());
530 return DS_OK;
533 static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus(
534 LPDIRECTSOUNDBUFFER8 iface,LPDWORD status
536 ICOM_THIS(IDirectSoundBufferImpl,iface);
537 TRACE("(%p,%p), thread is %04lx\n",This,status,GetCurrentThreadId());
539 if (status == NULL) {
540 WARN("invalid parameter: status = NULL\n");
541 return DSERR_INVALIDPARAM;
544 *status = 0;
545 if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) {
546 *status |= DSBSTATUS_PLAYING;
547 if (This->playflags & DSBPLAY_LOOPING)
548 *status |= DSBSTATUS_LOOPING;
551 TRACE("status=%lx\n", *status);
552 return DS_OK;
556 static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat(
557 LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten
559 ICOM_THIS(IDirectSoundBufferImpl,iface);
560 TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten);
562 if (wfsize>sizeof(This->wfx))
563 wfsize = sizeof(This->wfx);
564 if (lpwf) { /* NULL is valid */
565 memcpy(lpwf,&(This->wfx),wfsize);
566 if (wfwritten)
567 *wfwritten = wfsize;
568 } else {
569 if (wfwritten)
570 *wfwritten = sizeof(This->wfx);
571 else {
572 WARN("invalid parameter: wfwritten == NULL\n");
573 return DSERR_INVALIDPARAM;
577 return DS_OK;
580 static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
581 LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags
583 HRESULT hres = DS_OK;
584 ICOM_THIS(IDirectSoundBufferImpl,iface);
586 TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx) at %ld\n",
587 This,
588 writecursor,
589 writebytes,
590 lplpaudioptr1,
591 audiobytes1,
592 lplpaudioptr2,
593 audiobytes2,
594 flags,
595 GetTickCount()
598 if (flags & DSBLOCK_FROMWRITECURSOR) {
599 DWORD writepos;
600 /* GetCurrentPosition does too much magic to duplicate here */
601 hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writepos);
602 if (hres != DS_OK) {
603 WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n");
604 return hres;
606 writecursor += writepos;
608 while (writecursor >= This->buflen)
609 writecursor -= This->buflen;
610 if (flags & DSBLOCK_ENTIREBUFFER)
611 writebytes = This->buflen;
612 if (writebytes > This->buflen)
613 writebytes = This->buflen;
615 assert(audiobytes1!=audiobytes2);
616 assert(lplpaudioptr1!=lplpaudioptr2);
618 EnterCriticalSection(&(This->lock));
620 if ((writebytes == This->buflen) &&
621 ((This->state == STATE_STARTING) ||
622 (This->state == STATE_PLAYING)))
623 /* some games, like Half-Life, try to be clever (not) and
624 * keep one secondary buffer, and mix sounds into it itself,
625 * locking the entire buffer every time... so we can just forget
626 * about tracking the last-written-to-position... */
627 This->probably_valid_to = (DWORD)-1;
628 else
629 This->probably_valid_to = writecursor;
631 if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
632 hres = IDsDriverBuffer_Lock(This->hwbuf,
633 lplpaudioptr1, audiobytes1,
634 lplpaudioptr2, audiobytes2,
635 writecursor, writebytes,
637 if (hres != DS_OK) {
638 WARN("IDsDriverBuffer_Lock failed\n");
639 LeaveCriticalSection(&(This->lock));
640 return hres;
642 } else {
643 BOOL remix = FALSE;
644 if (writecursor+writebytes <= This->buflen) {
645 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
646 *audiobytes1 = writebytes;
647 if (lplpaudioptr2)
648 *(LPBYTE*)lplpaudioptr2 = NULL;
649 if (audiobytes2)
650 *audiobytes2 = 0;
651 TRACE("->%ld.0\n",writebytes);
652 } else {
653 *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
654 *audiobytes1 = This->buflen-writecursor;
655 if (lplpaudioptr2)
656 *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
657 if (audiobytes2)
658 *audiobytes2 = writebytes-(This->buflen-writecursor);
659 TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0);
661 if (This->state == STATE_PLAYING) {
662 /* if the segment between playpos and buf_mixpos is touched,
663 * we need to cancel some mixing */
664 /* we'll assume that the app always calls GetCurrentPosition before
665 * locking a playing buffer, so that last_playpos is up-to-date */
666 if (This->buf_mixpos >= This->last_playpos) {
667 if (This->buf_mixpos > writecursor &&
668 This->last_playpos < writecursor+writebytes)
669 remix = TRUE;
671 else {
672 if (This->buf_mixpos > writecursor ||
673 This->last_playpos < writecursor+writebytes)
674 remix = TRUE;
676 if (remix) {
677 TRACE("locking prebuffered region, ouch\n");
678 DSOUND_MixCancelAt(This, writecursor);
683 LeaveCriticalSection(&(This->lock));
684 return DS_OK;
687 static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition(
688 LPDIRECTSOUNDBUFFER8 iface,DWORD newpos
690 HRESULT hres = DS_OK;
691 ICOM_THIS(IDirectSoundBufferImpl,iface);
692 TRACE("(%p,%ld)\n",This,newpos);
694 /* **** */
695 EnterCriticalSection(&(This->lock));
697 while (newpos >= This->buflen)
698 newpos -= This->buflen;
699 This->buf_mixpos = newpos;
700 if (This->hwbuf) {
701 hres = IDsDriverBuffer_SetPosition(This->hwbuf, This->buf_mixpos);
702 if (hres != DS_OK)
703 WARN("IDsDriverBuffer_SetPosition failed\n");
706 LeaveCriticalSection(&(This->lock));
707 /* **** */
709 return hres;
712 static HRESULT WINAPI IDirectSoundBufferImpl_SetPan(
713 LPDIRECTSOUNDBUFFER8 iface,LONG pan
715 HRESULT hres = DS_OK;
716 ICOM_THIS(IDirectSoundBufferImpl,iface);
717 LONG oldPan;
719 TRACE("(%p,%ld)\n",This,pan);
721 if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) {
722 WARN("invalid parameter: pan = %ld\n", pan);
723 return DSERR_INVALIDPARAM;
726 /* You cannot use both pan and 3D controls */
727 if (!(This->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
728 (This->dsbd.dwFlags & DSBCAPS_CTRL3D)) {
729 WARN("control unavailable\n");
730 return DSERR_CONTROLUNAVAIL;
733 /* **** */
734 EnterCriticalSection(&(This->lock));
736 oldPan = This->volpan.lPan;
737 This->volpan.lPan = pan;
739 if (pan != oldPan) {
740 DSOUND_RecalcVolPan(&(This->volpan));
742 if (This->hwbuf) {
743 hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan));
744 if (hres != DS_OK)
745 WARN("IDsDriverBuffer_SetVolumePan failed\n");
746 } else
747 DSOUND_ForceRemix(This);
750 LeaveCriticalSection(&(This->lock));
751 /* **** */
753 return hres;
756 static HRESULT WINAPI IDirectSoundBufferImpl_GetPan(
757 LPDIRECTSOUNDBUFFER8 iface,LPLONG pan
759 ICOM_THIS(IDirectSoundBufferImpl,iface);
760 TRACE("(%p,%p)\n",This,pan);
762 if (pan == NULL) {
763 WARN("invalid parameter: pan = NULL\n");
764 return DSERR_INVALIDPARAM;
767 *pan = This->volpan.lPan;
769 return DS_OK;
772 static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(
773 LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2
775 ICOM_THIS(IDirectSoundBufferImpl,iface);
776 DWORD probably_valid_to;
778 TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2);
780 if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
781 HRESULT hres;
782 hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
783 if (hres != DS_OK) {
784 WARN("IDsDriverBuffer_Unlock failed\n");
785 return hres;
789 if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer->memory) + x2;
790 else probably_valid_to = (((LPBYTE)p1)-This->buffer->memory) + x1;
791 while (probably_valid_to >= This->buflen)
792 probably_valid_to -= This->buflen;
793 if ((probably_valid_to == 0) && ((x1+x2) == This->buflen) &&
794 ((This->state == STATE_STARTING) ||
795 (This->state == STATE_PLAYING)))
796 /* see IDirectSoundBufferImpl_Lock */
797 probably_valid_to = (DWORD)-1;
798 This->probably_valid_to = probably_valid_to;
800 return DS_OK;
803 static HRESULT WINAPI IDirectSoundBufferImpl_Restore(
804 LPDIRECTSOUNDBUFFER8 iface
806 ICOM_THIS(IDirectSoundBufferImpl,iface);
807 FIXME("(%p):stub\n",This);
808 return DS_OK;
811 static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency(
812 LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq
814 ICOM_THIS(IDirectSoundBufferImpl,iface);
815 TRACE("(%p,%p)\n",This,freq);
817 if (freq == NULL) {
818 WARN("invalid parameter: freq = NULL\n");
819 return DSERR_INVALIDPARAM;
822 *freq = This->freq;
823 TRACE("-> %ld\n", *freq);
825 return DS_OK;
828 static HRESULT WINAPI IDirectSoundBufferImpl_SetFX(
829 LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes
831 ICOM_THIS(IDirectSoundBufferImpl,iface);
832 DWORD u;
834 FIXME("(%p,%lu,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
836 if (pdwResultCodes)
837 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
839 WARN("control unavailable\n");
840 return DSERR_CONTROLUNAVAIL;
843 static HRESULT WINAPI IDirectSoundBufferImpl_AcquireResources(
844 LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes
846 ICOM_THIS(IDirectSoundBufferImpl,iface);
847 DWORD u;
849 FIXME("(%p,%08lu,%lu,%p): stub\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
851 if (pdwResultCodes)
852 for (u=0; u<dwEffectsCount; u++) pdwResultCodes[u] = DSFXR_UNKNOWN;
854 WARN("control unavailable\n");
855 return DSERR_CONTROLUNAVAIL;
858 static HRESULT WINAPI IDirectSoundBufferImpl_GetObjectInPath(
859 LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject
861 ICOM_THIS(IDirectSoundBufferImpl,iface);
863 FIXME("(%p,%s,%lu,%s,%p): stub\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
865 WARN("control unavailable\n");
866 return DSERR_CONTROLUNAVAIL;
869 static HRESULT WINAPI IDirectSoundBufferImpl_Initialize(
870 LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND8 dsound,LPDSBUFFERDESC dbsd
872 ICOM_THIS(IDirectSoundBufferImpl,iface);
873 FIXME("(%p,%p,%p):stub\n",This,dsound,dbsd);
874 DPRINTF("Re-Init!!!\n");
875 WARN("already initialized\n");
876 return DSERR_ALREADYINITIALIZED;
879 static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps(
880 LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps
882 ICOM_THIS(IDirectSoundBufferImpl,iface);
883 TRACE("(%p)->(%p)\n",This,caps);
885 if (caps == NULL) {
886 WARN("invalid parameter: caps == NULL\n");
887 return DSERR_INVALIDPARAM;
890 if (caps->dwSize < sizeof(*caps)) {
891 WARN("invalid parameter: caps->dwSize = %ld < %d\n",caps->dwSize, sizeof(*caps));
892 return DSERR_INVALIDPARAM;
895 caps->dwFlags = This->dsbd.dwFlags;
896 if (This->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
897 else caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
899 caps->dwBufferBytes = This->buflen;
901 /* This value represents the speed of the "unlock" command.
902 As unlock is quite fast (it does not do anything), I put
903 4096 ko/s = 4 Mo / s */
904 /* FIXME: hwbuf speed */
905 caps->dwUnlockTransferRate = 4096;
906 caps->dwPlayCpuOverhead = 0;
908 return DS_OK;
911 static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
912 LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj
914 ICOM_THIS(IDirectSoundBufferImpl,iface);
916 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
918 if (ppobj == NULL) {
919 WARN("invalid parameter\n");
920 return E_INVALIDARG;
923 *ppobj = NULL; /* assume failure */
925 if ( IsEqualGUID(riid, &IID_IUnknown) ||
926 IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
927 IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
928 if (!This->dsb)
929 SecondaryBufferImpl_Create(This, &(This->dsb));
930 if (This->dsb) {
931 IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb);
932 *ppobj = This->dsb;
933 return S_OK;
935 WARN("IID_IDirectSoundBuffer\n");
936 return E_NOINTERFACE;
939 if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ||
940 IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) {
941 if (!This->notify)
942 IDirectSoundNotifyImpl_Create(This, &(This->notify));
943 if (This->notify) {
944 IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify);
945 *ppobj = This->notify;
946 return S_OK;
948 WARN("IID_IDirectSoundNotify\n");
949 return E_NOINTERFACE;
952 if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
953 if (!This->ds3db)
954 IDirectSound3DBufferImpl_Create(This, &(This->ds3db));
955 if (This->ds3db) {
956 IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)This->ds3db);
957 *ppobj = This->ds3db;
958 return S_OK;
960 WARN("IID_IDirectSound3DBuffer\n");
961 return E_NOINTERFACE;
964 if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
965 ERR("app requested IDirectSound3DListener on secondary buffer\n");
966 return E_NOINTERFACE;
969 if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
970 /* only supported on hardware 3D secondary buffers */
971 if (!(This->dsbd.dwFlags & DSBCAPS_PRIMARYBUFFER) &&
972 (This->dsbd.dwFlags & DSBCAPS_CTRL3D) &&
973 (This->hwbuf != NULL) ) {
974 if (!This->iks)
975 IKsBufferPropertySetImpl_Create(This, &(This->iks));
976 if (This->iks) {
977 IKsPropertySet_AddRef((LPKSPROPERTYSET)*ppobj);
978 *ppobj = This->iks;
979 return S_OK;
982 WARN("IID_IKsPropertySet\n");
983 return E_NOINTERFACE;
986 FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
988 return E_NOINTERFACE;
991 static ICOM_VTABLE(IDirectSoundBuffer8) dsbvt =
993 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
994 IDirectSoundBufferImpl_QueryInterface,
995 IDirectSoundBufferImpl_AddRef,
996 IDirectSoundBufferImpl_Release,
997 IDirectSoundBufferImpl_GetCaps,
998 IDirectSoundBufferImpl_GetCurrentPosition,
999 IDirectSoundBufferImpl_GetFormat,
1000 IDirectSoundBufferImpl_GetVolume,
1001 IDirectSoundBufferImpl_GetPan,
1002 IDirectSoundBufferImpl_GetFrequency,
1003 IDirectSoundBufferImpl_GetStatus,
1004 IDirectSoundBufferImpl_Initialize,
1005 IDirectSoundBufferImpl_Lock,
1006 IDirectSoundBufferImpl_Play,
1007 IDirectSoundBufferImpl_SetCurrentPosition,
1008 IDirectSoundBufferImpl_SetFormat,
1009 IDirectSoundBufferImpl_SetVolume,
1010 IDirectSoundBufferImpl_SetPan,
1011 IDirectSoundBufferImpl_SetFrequency,
1012 IDirectSoundBufferImpl_Stop,
1013 IDirectSoundBufferImpl_Unlock,
1014 IDirectSoundBufferImpl_Restore,
1015 IDirectSoundBufferImpl_SetFX,
1016 IDirectSoundBufferImpl_AcquireResources,
1017 IDirectSoundBufferImpl_GetObjectInPath
1020 HRESULT WINAPI IDirectSoundBufferImpl_Create(
1021 IDirectSoundImpl *ds,
1022 IDirectSoundBufferImpl **pdsb,
1023 LPDSBUFFERDESC dsbd)
1025 IDirectSoundBufferImpl *dsb;
1026 LPWAVEFORMATEX wfex = dsbd->lpwfxFormat;
1027 HRESULT err = DS_OK;
1028 DWORD capf = 0;
1029 int use_hw;
1030 TRACE("(%p,%p,%p)\n",ds,pdsb,dsbd);
1032 if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
1033 WARN("invalid parameter: dsbd->dwBufferBytes = %ld\n", dsbd->dwBufferBytes);
1034 *pdsb = NULL;
1035 return DSERR_INVALIDPARAM; /* FIXME: which error? */
1038 dsb = (IDirectSoundBufferImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb));
1040 if (dsb == 0) {
1041 WARN("out of memory\n");
1042 *pdsb = NULL;
1043 return DSERR_OUTOFMEMORY;
1045 dsb->ref = 0;
1046 dsb->dsb = 0;
1047 dsb->dsound = ds;
1048 dsb->lpVtbl = &dsbvt;
1049 dsb->iks = NULL;
1051 memcpy(&dsb->dsbd, dsbd, sizeof(*dsbd));
1052 if (wfex)
1053 memcpy(&dsb->wfx, wfex, sizeof(dsb->wfx));
1055 TRACE("Created buffer at %p\n", dsb);
1057 dsb->buflen = dsbd->dwBufferBytes;
1058 dsb->freq = dsbd->lpwfxFormat->nSamplesPerSec;
1060 dsb->notify = NULL;
1061 dsb->notifies = NULL;
1062 dsb->nrofnotifies = 0;
1063 dsb->hwnotify = 0;
1065 /* Check necessary hardware mixing capabilities */
1066 if (wfex->nChannels==2) capf |= DSCAPS_SECONDARYSTEREO;
1067 else capf |= DSCAPS_SECONDARYMONO;
1068 if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT;
1069 else capf |= DSCAPS_SECONDARY8BIT;
1071 use_hw = (ds->drvcaps.dwFlags & capf) == capf;
1072 TRACE("use_hw = 0x%08x, capf = 0x%08lx, ds->drvcaps.dwFlags = 0x%08lx\n", use_hw, capf, ds->drvcaps.dwFlags);
1074 /* FIXME: check hardware sample rate mixing capabilities */
1075 /* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */
1076 /* FIXME: check whether any hardware buffers are left */
1077 /* FIXME: handle DSDHEAP_CREATEHEAP for hardware buffers */
1079 /* Allocate system memory if applicable */
1080 if ((ds->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
1081 dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
1082 if (dsb->buffer == NULL) {
1083 WARN("out of memory\n");
1084 HeapFree(GetProcessHeap(),0,dsb);
1085 *pdsb = NULL;
1086 return DSERR_OUTOFMEMORY;
1089 dsb->buffer->memory = (LPBYTE)HeapAlloc(GetProcessHeap(),0,dsb->buflen);
1090 if (dsb->buffer->memory == NULL) {
1091 WARN("out of memory\n");
1092 HeapFree(GetProcessHeap(),0,dsb->buffer);
1093 HeapFree(GetProcessHeap(),0,dsb);
1094 *pdsb = NULL;
1095 return DSERR_OUTOFMEMORY;
1099 /* Allocate the hardware buffer */
1100 if (use_hw) {
1101 err = IDsDriver_CreateSoundBuffer(ds->driver,wfex,dsbd->dwFlags,0,
1102 &(dsb->buflen),&(dsb->buffer->memory),
1103 (LPVOID*)&(dsb->hwbuf));
1104 if (err != DS_OK) {
1105 WARN("IDsDriver_CreateSoundBuffer failed\n");
1106 if (dsb->buffer->memory)
1107 HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
1108 if (dsb->buffer)
1109 HeapFree(GetProcessHeap(),0,dsb->buffer);
1110 HeapFree(GetProcessHeap(),0,dsb);
1111 *pdsb = NULL;
1112 return err;
1116 /* calculate fragment size and write lead */
1117 DSOUND_RecalcFormat(dsb);
1119 /* It's not necessary to initialize values to zero since */
1120 /* we allocated this structure with HEAP_ZERO_MEMORY... */
1121 dsb->playpos = 0;
1122 dsb->buf_mixpos = 0;
1123 dsb->state = STATE_STOPPED;
1125 dsb->freqAdjust = (dsb->freq << DSOUND_FREQSHIFT) /
1126 ds->wfx.nSamplesPerSec;
1127 dsb->nAvgBytesPerSec = dsb->freq *
1128 dsbd->lpwfxFormat->nBlockAlign;
1130 if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
1131 dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
1132 dsb->ds3db_ds3db.vPosition.x = 0.0;
1133 dsb->ds3db_ds3db.vPosition.y = 0.0;
1134 dsb->ds3db_ds3db.vPosition.z = 0.0;
1135 dsb->ds3db_ds3db.vVelocity.x = 0.0;
1136 dsb->ds3db_ds3db.vVelocity.y = 0.0;
1137 dsb->ds3db_ds3db.vVelocity.z = 0.0;
1138 dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
1139 dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
1140 dsb->ds3db_ds3db.vConeOrientation.x = 0.0;
1141 dsb->ds3db_ds3db.vConeOrientation.y = 0.0;
1142 dsb->ds3db_ds3db.vConeOrientation.z = 0.0;
1143 dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
1144 dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
1145 dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
1146 dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
1148 dsb->ds3db_need_recalc = FALSE;
1149 DSOUND_Calc3DBuffer(dsb);
1150 } else
1151 DSOUND_RecalcVolPan(&(dsb->volpan));
1153 InitializeCriticalSection(&(dsb->lock));
1155 /* register buffer */
1156 RtlAcquireResourceExclusive(&(ds->lock), TRUE);
1157 if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) {
1158 IDirectSoundBufferImpl **newbuffers = (IDirectSoundBufferImpl**)HeapReAlloc(GetProcessHeap(),0,ds->buffers,sizeof(IDirectSoundBufferImpl*)*(ds->nrofbuffers+1));
1159 if (newbuffers) {
1160 ds->buffers = newbuffers;
1161 ds->buffers[ds->nrofbuffers] = dsb;
1162 ds->nrofbuffers++;
1163 TRACE("buffer count is now %d\n", ds->nrofbuffers);
1164 } else {
1165 ERR("out of memory for buffer list! Current buffer count is %d\n", ds->nrofbuffers);
1166 if (dsb->buffer->memory)
1167 HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
1168 if (dsb->buffer)
1169 HeapFree(GetProcessHeap(),0,dsb->buffer);
1170 DeleteCriticalSection(&(dsb->lock));
1171 RtlReleaseResource(&(ds->lock));
1172 HeapFree(GetProcessHeap(),0,dsb);
1173 *pdsb = NULL;
1174 return DSERR_OUTOFMEMORY;
1177 RtlReleaseResource(&(ds->lock));
1178 IDirectSound8_AddRef((LPDIRECTSOUND8)ds);
1179 *pdsb = dsb;
1180 return S_OK;
1183 /*******************************************************************************
1184 * SecondaryBuffer
1187 static HRESULT WINAPI SecondaryBufferImpl_QueryInterface(
1188 LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj)
1190 ICOM_THIS(SecondaryBufferImpl,iface);
1191 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
1193 return IDirectSoundBufferImpl_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb,riid,ppobj);
1196 static DWORD WINAPI SecondaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface)
1198 ICOM_THIS(IDirectSoundBufferImpl,iface);
1199 DWORD ref;
1200 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1202 ref = InterlockedIncrement(&(This->ref));
1203 if (!ref) {
1204 FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
1206 return ref;
1209 static DWORD WINAPI SecondaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface)
1211 ICOM_THIS(IDirectSoundBufferImpl,iface);
1212 DWORD ref;
1213 TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
1215 ref = InterlockedDecrement(&(This->ref));
1216 if (!ref) {
1217 This->dsb->dsb = NULL;
1218 IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
1219 HeapFree(GetProcessHeap(),0,This);
1220 TRACE("(%p) released\n",This);
1222 return ref;
1225 static HRESULT WINAPI SecondaryBufferImpl_GetCaps(
1226 LPDIRECTSOUNDBUFFER8 iface,LPDSBCAPS caps)
1228 ICOM_THIS(SecondaryBufferImpl,iface);
1229 TRACE("(%p)->(%p)\n",This,caps);
1231 return IDirectSoundBufferImpl_GetCaps((LPDIRECTSOUNDBUFFER8)This->dsb,caps);
1234 static HRESULT WINAPI SecondaryBufferImpl_GetCurrentPosition(
1235 LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos)
1237 ICOM_THIS(SecondaryBufferImpl,iface);
1238 TRACE("(%p,%p,%p)\n",This,playpos,writepos);
1240 return IDirectSoundBufferImpl_GetCurrentPosition((LPDIRECTSOUNDBUFFER8)This->dsb,playpos,writepos);
1243 static HRESULT WINAPI SecondaryBufferImpl_GetFormat(
1244 LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten)
1246 ICOM_THIS(SecondaryBufferImpl,iface);
1247 TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten);
1249 return IDirectSoundBufferImpl_GetFormat((LPDIRECTSOUNDBUFFER8)This->dsb,lpwf,wfsize,wfwritten);
1252 static HRESULT WINAPI SecondaryBufferImpl_GetVolume(
1253 LPDIRECTSOUNDBUFFER8 iface,LPLONG vol)
1255 ICOM_THIS(SecondaryBufferImpl,iface);
1256 TRACE("(%p,%p)\n",This,vol);
1258 return IDirectSoundBufferImpl_GetVolume((LPDIRECTSOUNDBUFFER8)This->dsb,vol);
1261 static HRESULT WINAPI SecondaryBufferImpl_GetPan(
1262 LPDIRECTSOUNDBUFFER8 iface,LPLONG pan)
1264 ICOM_THIS(SecondaryBufferImpl,iface);
1265 TRACE("(%p,%p)\n",This,pan);
1267 return IDirectSoundBufferImpl_GetPan((LPDIRECTSOUNDBUFFER8)This->dsb,pan);
1270 static HRESULT WINAPI SecondaryBufferImpl_GetFrequency(
1271 LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq)
1273 ICOM_THIS(SecondaryBufferImpl,iface);
1274 TRACE("(%p,%p)\n",This,freq);
1276 return IDirectSoundBufferImpl_GetFrequency((LPDIRECTSOUNDBUFFER8)This->dsb,freq);
1279 static HRESULT WINAPI SecondaryBufferImpl_GetStatus(
1280 LPDIRECTSOUNDBUFFER8 iface,LPDWORD status)
1282 ICOM_THIS(SecondaryBufferImpl,iface);
1283 TRACE("(%p,%p)\n",This,status);
1285 return IDirectSoundBufferImpl_GetStatus((LPDIRECTSOUNDBUFFER8)This->dsb,status);
1288 static HRESULT WINAPI SecondaryBufferImpl_Initialize(
1289 LPDIRECTSOUNDBUFFER8 iface,LPDIRECTSOUND8 dsound,LPDSBUFFERDESC dbsd)
1291 ICOM_THIS(SecondaryBufferImpl,iface);
1292 TRACE("(%p,%p,%p)\n",This,dsound,dbsd);
1294 return IDirectSoundBufferImpl_Initialize((LPDIRECTSOUNDBUFFER8)This->dsb,dsound,dbsd);
1297 static HRESULT WINAPI SecondaryBufferImpl_Lock(
1298 LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags)
1300 ICOM_THIS(SecondaryBufferImpl,iface);
1301 TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx)\n",
1302 This,writecursor,writebytes,lplpaudioptr1,audiobytes1,lplpaudioptr2,audiobytes2,flags);
1304 return IDirectSoundBufferImpl_Lock((LPDIRECTSOUNDBUFFER8)This->dsb,writecursor,writebytes,lplpaudioptr1,audiobytes1,lplpaudioptr2,audiobytes2,flags);
1307 static HRESULT WINAPI SecondaryBufferImpl_Play(
1308 LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags)
1310 ICOM_THIS(SecondaryBufferImpl,iface);
1311 TRACE("(%p,%08lx,%08lx,%08lx)\n",This,reserved1,reserved2,flags);
1313 return IDirectSoundBufferImpl_Play((LPDIRECTSOUNDBUFFER8)This->dsb,reserved1,reserved2,flags);
1316 static HRESULT WINAPI SecondaryBufferImpl_SetCurrentPosition(
1317 LPDIRECTSOUNDBUFFER8 iface,DWORD newpos)
1319 ICOM_THIS(SecondaryBufferImpl,iface);
1320 TRACE("(%p,%ld)\n",This,newpos);
1322 return IDirectSoundBufferImpl_SetCurrentPosition((LPDIRECTSOUNDBUFFER8)This->dsb,newpos);
1325 static HRESULT WINAPI SecondaryBufferImpl_SetFormat(
1326 LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX wfex)
1328 ICOM_THIS(SecondaryBufferImpl,iface);
1329 TRACE("(%p,%p)\n",This,wfex);
1331 return IDirectSoundBufferImpl_SetFormat((LPDIRECTSOUNDBUFFER8)This->dsb,wfex);
1334 static HRESULT WINAPI SecondaryBufferImpl_SetVolume(
1335 LPDIRECTSOUNDBUFFER8 iface,LONG vol)
1337 ICOM_THIS(SecondaryBufferImpl,iface);
1338 TRACE("(%p,%ld)\n",This,vol);
1340 return IDirectSoundBufferImpl_SetVolume((LPDIRECTSOUNDBUFFER8)This->dsb,vol);
1343 static HRESULT WINAPI SecondaryBufferImpl_SetPan(
1344 LPDIRECTSOUNDBUFFER8 iface,LONG pan)
1346 ICOM_THIS(SecondaryBufferImpl,iface);
1347 TRACE("(%p,%ld)\n",This,pan);
1349 return IDirectSoundBufferImpl_SetPan((LPDIRECTSOUNDBUFFER8)This->dsb,pan);
1352 static HRESULT WINAPI SecondaryBufferImpl_SetFrequency(
1353 LPDIRECTSOUNDBUFFER8 iface,DWORD freq)
1355 ICOM_THIS(SecondaryBufferImpl,iface);
1356 TRACE("(%p,%ld)\n",This,freq);
1358 return IDirectSoundBufferImpl_SetFrequency((LPDIRECTSOUNDBUFFER8)This->dsb,freq);
1361 static HRESULT WINAPI SecondaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface)
1363 ICOM_THIS(SecondaryBufferImpl,iface);
1364 TRACE("(%p)\n",This);
1366 return IDirectSoundBufferImpl_Stop((LPDIRECTSOUNDBUFFER8)This->dsb);
1369 static HRESULT WINAPI SecondaryBufferImpl_Unlock(
1370 LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2)
1372 ICOM_THIS(SecondaryBufferImpl,iface);
1373 TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2);
1375 return IDirectSoundBufferImpl_Unlock((LPDIRECTSOUNDBUFFER8)This->dsb,p1,x1,p2,x2);
1378 static HRESULT WINAPI SecondaryBufferImpl_Restore(
1379 LPDIRECTSOUNDBUFFER8 iface)
1381 ICOM_THIS(SecondaryBufferImpl,iface);
1382 TRACE("(%p)\n",This);
1384 return IDirectSoundBufferImpl_Restore((LPDIRECTSOUNDBUFFER8)This->dsb);
1387 static HRESULT WINAPI SecondaryBufferImpl_SetFX(
1388 LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes)
1390 ICOM_THIS(SecondaryBufferImpl,iface);
1391 TRACE("(%p,%lu,%p,%p)\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes);
1393 return IDirectSoundBufferImpl_SetFX((LPDIRECTSOUNDBUFFER8)This->dsb,dwEffectsCount,pDSFXDesc,pdwResultCodes);
1396 static HRESULT WINAPI SecondaryBufferImpl_AcquireResources(
1397 LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes)
1399 ICOM_THIS(SecondaryBufferImpl,iface);
1400 TRACE("(%p,%08lu,%lu,%p)\n",This,dwFlags,dwEffectsCount,pdwResultCodes);
1402 return IDirectSoundBufferImpl_AcquireResources((LPDIRECTSOUNDBUFFER8)This->dsb,dwFlags,dwEffectsCount,pdwResultCodes);
1405 static HRESULT WINAPI SecondaryBufferImpl_GetObjectInPath(
1406 LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject)
1408 ICOM_THIS(SecondaryBufferImpl,iface);
1409 TRACE("(%p,%s,%lu,%s,%p)\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject);
1411 return IDirectSoundBufferImpl_GetObjectInPath((LPDIRECTSOUNDBUFFER8)This->dsb,rguidObject,dwIndex,rguidInterface,ppObject);
1414 static ICOM_VTABLE(IDirectSoundBuffer8) sbvt =
1416 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1417 SecondaryBufferImpl_QueryInterface,
1418 SecondaryBufferImpl_AddRef,
1419 SecondaryBufferImpl_Release,
1420 SecondaryBufferImpl_GetCaps,
1421 SecondaryBufferImpl_GetCurrentPosition,
1422 SecondaryBufferImpl_GetFormat,
1423 SecondaryBufferImpl_GetVolume,
1424 SecondaryBufferImpl_GetPan,
1425 SecondaryBufferImpl_GetFrequency,
1426 SecondaryBufferImpl_GetStatus,
1427 SecondaryBufferImpl_Initialize,
1428 SecondaryBufferImpl_Lock,
1429 SecondaryBufferImpl_Play,
1430 SecondaryBufferImpl_SetCurrentPosition,
1431 SecondaryBufferImpl_SetFormat,
1432 SecondaryBufferImpl_SetVolume,
1433 SecondaryBufferImpl_SetPan,
1434 SecondaryBufferImpl_SetFrequency,
1435 SecondaryBufferImpl_Stop,
1436 SecondaryBufferImpl_Unlock,
1437 SecondaryBufferImpl_Restore,
1438 SecondaryBufferImpl_SetFX,
1439 SecondaryBufferImpl_AcquireResources,
1440 SecondaryBufferImpl_GetObjectInPath
1443 HRESULT WINAPI SecondaryBufferImpl_Create(
1444 IDirectSoundBufferImpl *dsb,
1445 SecondaryBufferImpl **psb)
1447 SecondaryBufferImpl *sb;
1448 TRACE("(%p,%p)\n",dsb,psb);
1450 sb = (SecondaryBufferImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*sb));
1452 if (sb == 0) {
1453 WARN("out of memory\n");
1454 *psb = NULL;
1455 return DSERR_OUTOFMEMORY;
1457 sb->ref = 0;
1458 sb->dsb = dsb;
1459 sb->lpVtbl = &sbvt;
1461 IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
1462 *psb = sb;
1463 return S_OK;