Commit ff60a9a2 authored by Joris Beugnies's avatar Joris Beugnies Committed by Alexandre Julliard

Make defines configurable at run-time.

parent 5d019367
......@@ -51,12 +51,15 @@
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "wingdi.h"
#include "winuser.h"
#include "winerror.h"
#include "mmsystem.h"
#include "mmddk.h"
#include "wine/windef16.h"
#include "wine/winbase16.h"
#include "wine/debug.h"
#include "dsound.h"
#include "dsdriver.h"
......@@ -93,6 +96,7 @@ typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl;
typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl;
typedef struct IKsPropertySetImpl IKsPropertySetImpl;
/*****************************************************************************
* IDirectSound implementation structure
*/
......@@ -278,6 +282,98 @@ static HRESULT mmErr(UINT err)
}
}
static int ds_emuldriver = DS_EMULDRIVER;
static int ds_hel_margin = DS_HEL_MARGIN;
static int ds_hel_queue = DS_HEL_QUEUE;
static int ds_snd_queue_max = DS_SND_QUEUE_MAX;
static int ds_snd_queue_min = DS_SND_QUEUE_MIN;
/*
* Get a config key from either the app-specific or the default config
*/
inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name,
char *buffer, DWORD size )
{
if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, buffer, &size )) return 0;
return RegQueryValueExA( defkey, name, 0, NULL, buffer, &size );
}
/*
* Setup the dsound options.
*/
inline static void setup_dsound_options(void)
{
char buffer[MAX_PATH+1];
HKEY hkey, appkey = 0;
buffer[MAX_PATH]='\0';
if (RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\dsound", 0, NULL,
REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ))
{
ERR("Cannot create config registry key\n" );
ExitProcess(1);
}
if (GetModuleFileName16( GetCurrentTask(), buffer, MAX_PATH ) ||
GetModuleFileNameA( 0, buffer, MAX_PATH ))
{
HKEY tmpkey;
if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\AppDefaults", &tmpkey ))
{
char appname[MAX_PATH+16];
char *p = strrchr( buffer, '\\' );
if (p!=NULL) {
appname[MAX_PATH]='\0';
strncpy(appname,p+1,MAX_PATH);
strcat(appname,"\\dsound");
TRACE("appname = [%s] \n",appname);
if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
RegCloseKey( tmpkey );
}
}
}
/* get options */
if (!get_config_key( hkey, appkey, "EmulDriver", buffer, MAX_PATH ))
ds_emuldriver = atoi(buffer);
if (!get_config_key( hkey, appkey, "HELmargin", buffer, MAX_PATH ))
ds_hel_margin = atoi(buffer);
if (!get_config_key( hkey, appkey, "HELqueue", buffer, MAX_PATH ))
ds_hel_queue = atoi(buffer);
if (!get_config_key( hkey, appkey, "SndQueueMax", buffer, MAX_PATH ))
ds_snd_queue_max = atoi(buffer);
if (!get_config_key( hkey, appkey, "SndQueueMin", buffer, MAX_PATH ))
ds_snd_queue_min = atoi(buffer);
if (appkey) RegCloseKey( appkey );
RegCloseKey( hkey );
if (ds_emuldriver != DS_EMULDRIVER )
WARN("ds_emuldriver = %d (default=%d)\n",ds_emuldriver, DS_EMULDRIVER);
if (ds_hel_margin != DS_HEL_MARGIN )
WARN("ds_hel_margin = %d (default=%d)\n",ds_hel_margin, DS_HEL_MARGIN );
if (ds_hel_queue != DS_HEL_QUEUE )
WARN("ds_hel_queue = %d (default=%d)\n",ds_hel_queue, DS_HEL_QUEUE );
if (ds_snd_queue_max != DS_SND_QUEUE_MAX)
WARN("ds_snd_queue_max = %d (default=%d)\n",ds_snd_queue_max ,DS_SND_QUEUE_MAX);
if (ds_snd_queue_min != DS_SND_QUEUE_MIN)
WARN("ds_snd_queue_min = %d (default=%d)\n",ds_snd_queue_min ,DS_SND_QUEUE_MIN);
}
/***************************************************************************
* DirectSoundEnumerateA [DSOUND.2]
*
......@@ -1508,7 +1604,7 @@ static DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This,
/* detect buffer underrun */
if (pwrite < pplay) pwrite += primarybuf->buflen; /* wraparound */
pwrite -= pplay;
if (pmix > (DS_SND_QUEUE_MAX * primarybuf->dsound->fraglen + pwrite + primarybuf->writelead)) {
if (pmix > (ds_snd_queue_max * primarybuf->dsound->fraglen + pwrite + primarybuf->writelead)) {
WARN("detected an underrun: primary queue was %ld\n",pmix);
pmix = 0;
}
......@@ -1555,7 +1651,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(
if (writepos) {
/* the writepos should only be used by apps with WRITEPRIMARY priority,
* in which case our software mixer is disabled anyway */
*writepos = (This->dsound->pwplay + DS_HEL_MARGIN) * This->dsound->fraglen;
*writepos = (This->dsound->pwplay + ds_hel_margin) * This->dsound->fraglen;
while (*writepos >= This->buflen)
*writepos -= This->buflen;
}
......@@ -1593,7 +1689,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition(
* behind write cursor, hmm... */
/* let's just do what might work for Half-Life */
DWORD wp;
wp = (This->dsound->pwplay + DS_HEL_MARGIN) * This->dsound->fraglen;
wp = (This->dsound->pwplay + ds_hel_margin) * This->dsound->fraglen;
while (wp >= primarybuf->buflen)
wp -= primarybuf->buflen;
*playpos = DSOUND_CalcPlayPosition(This, pstate, wp, pwrite, lplay, splay);
......@@ -2602,75 +2698,66 @@ static inline BYTE cvtS16toU8(INT16 word)
}
/* We should be able to optimize these two inline functions */
/* so that we aren't doing 8->16->8 conversions when it is */
/* not necessary. But this is still a WIP. Optimize later. */
static inline void get_fields(const IDirectSoundBufferImpl *dsb, BYTE *buf, INT *fl, INT *fr)
static inline void cp_fields(const IDirectSoundBufferImpl *dsb, BYTE *ibuf, BYTE *obuf )
{
INT16 *bufs = (INT16 *) buf;
/* TRACE("(%p)\n", buf); */
if ((dsb->wfx.wBitsPerSample == 8) && dsb->wfx.nChannels == 2) {
*fl = cvtU8toS16(*buf);
*fr = cvtU8toS16(*(buf + 1));
return;
}
if ((dsb->wfx.wBitsPerSample == 16) && dsb->wfx.nChannels == 2) {
*fl = *bufs;
*fr = *(bufs + 1);
return;
}
if ((dsb->wfx.wBitsPerSample == 8) && dsb->wfx.nChannels == 1) {
*fl = cvtU8toS16(*buf);
*fr = *fl;
return;
}
if ((dsb->wfx.wBitsPerSample == 16) && dsb->wfx.nChannels == 1) {
*fl = *bufs;
*fr = *bufs;
return;
}
FIXME("get_fields found an unsupported configuration\n");
return;
}
static inline void set_fields(BYTE *buf, INT fl, INT fr)
{
INT16 *bufs = (INT16 *) buf;
if ((primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 2)) {
*buf = cvtS16toU8(fl);
*(buf + 1) = cvtS16toU8(fr);
return;
}
if ((primarybuf->wfx.wBitsPerSample == 16) && (primarybuf->wfx.nChannels == 2)) {
*bufs = fl;
*(bufs + 1) = fr;
return;
}
if ((primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 1)) {
*buf = cvtS16toU8((fl + fr) >> 1);
return;
INT fl = 0, fr = 0;
if (dsb->wfx.nChannels == 2) {
if (dsb->wfx.wBitsPerSample == 8) {
/* avoid needless 8->16->8 conversion */
if ( (primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 2) ) {
*obuf=*ibuf;
*(obuf+1)=*(ibuf+1);
return;
}
fl = cvtU8toS16(*ibuf);
fr = cvtU8toS16(*(ibuf + 1));
} else if (dsb->wfx.wBitsPerSample == 16) {
fl = *((INT16 *)ibuf);
fr = *(((INT16 *)ibuf) + 1);
}
} else if (dsb->wfx.nChannels == 1) {
if (dsb->wfx.wBitsPerSample == 8) {
/* avoid needless 8->16->8 conversion */
if ( (primarybuf->wfx.wBitsPerSample == 8) && (primarybuf->wfx.nChannels == 1) ) {
*obuf=*ibuf;
return;
}
fl = cvtU8toS16(*ibuf);
fr = fl;
} else if (dsb->wfx.wBitsPerSample == 16) {
fl = *((INT16 *)ibuf);
fr = fl;
}
}
if ((primarybuf->wfx.wBitsPerSample == 16) && (primarybuf->wfx.nChannels == 1)) {
*bufs = (fl + fr) >> 1;
return;
if (primarybuf->wfx.nChannels == 2) {
if (primarybuf->wfx.wBitsPerSample == 8) {
*obuf = cvtS16toU8(fl);
*(obuf + 1) = cvtS16toU8(fr);
return;
}
if (primarybuf->wfx.wBitsPerSample == 16) {
*((INT16 *)obuf) = fl;
*(((INT16 *)obuf) + 1) = fr;
return;
}
}
if (primarybuf->wfx.nChannels == 1) {
fl = (fl + fr) >> 1;
if (primarybuf->wfx.wBitsPerSample == 8) {
*obuf = cvtS16toU8(fl);
return;
}
if (primarybuf->wfx.wBitsPerSample == 16) {
*((INT16 *)obuf) = fl;
return;
}
}
FIXME("set_fields found an unsupported configuration\n");
return;
}
/* Now with PerfectPitch (tm) technology */
static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
{
INT i, size, ipos, ilen, fieldL, fieldR;
INT i, size, ipos, ilen;
BYTE *ibp, *obp;
INT iAdvance = dsb->wfx.nBlockAlign;
INT oAdvance = primarybuf->wfx.nBlockAlign;
......@@ -2700,10 +2787,9 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
dsb->freq, primarybuf->wfx.nSamplesPerSec);
ilen = 0;
for (i = 0; i < len; i += oAdvance) {
get_fields(dsb, ibp, &fieldL, &fieldR);
cp_fields(dsb, ibp, obp );
ibp += iAdvance;
ilen += iAdvance;
set_fields(obp, fieldL, fieldR);
obp += oAdvance;
if (ibp >= (BYTE *)(dsb->buffer + dsb->buflen))
ibp = dsb->buffer; /* wrap */
......@@ -2719,17 +2805,15 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
/* Patent enhancements (c) 2000 Ove Kven,
* TransGaming Technologies Inc. */
FIXME("(%p) Adjusting frequency: %ld -> %ld (need optimization)\n",
/* FIXME("(%p) Adjusting frequency: %ld -> %ld (need optimization)\n",
dsb, dsb->freq, primarybuf->wfx.nSamplesPerSec);
*/
size = len / oAdvance;
ilen = 0;
ipos = dsb->buf_mixpos;
for (i = 0; i < size; i++) {
get_fields(dsb, (dsb->buffer + ipos), &fieldL, &fieldR);
set_fields(obp, fieldL, fieldR);
cp_fields(dsb, (dsb->buffer + ipos), obp);
obp += oAdvance;
dsb->freqAcc += dsb->freqAdjust;
if (dsb->freqAcc >= (1<<DSOUND_FREQSHIFT)) {
ULONG adv = (dsb->freqAcc>>DSOUND_FREQSHIFT) * iAdvance;
......@@ -3260,16 +3344,16 @@ static void DSOUND_CheckReset(IDirectSoundImpl *dsound, DWORD writepos)
DSOUND_MixReset(writepos);
primarybuf->need_remix = FALSE;
/* maximize Half-Life performance */
dsound->prebuf = DS_SND_QUEUE_MIN;
dsound->prebuf = ds_snd_queue_min;
} else {
/* if (dsound->prebuf < DS_SND_QUEUE_MAX) dsound->prebuf++; */
/* if (dsound->prebuf < ds_snd_queue_max) dsound->prebuf++; */
}
TRACE("premix adjust: %d\n", dsound->prebuf);
}
static void DSOUND_WaveQueue(IDirectSoundImpl *dsound, DWORD mixq)
{
if (mixq + dsound->pwqueue > DS_HEL_QUEUE) mixq = DS_HEL_QUEUE - dsound->pwqueue;
if (mixq + dsound->pwqueue > ds_hel_queue) mixq = ds_hel_queue - dsound->pwqueue;
TRACE("queueing %ld buffers, starting at %d\n", mixq, dsound->pwwrite);
for (; mixq; mixq--) {
waveOutWrite(dsound->hwo, dsound->pwave[dsound->pwwrite], sizeof(WAVEHDR));
......@@ -3325,7 +3409,7 @@ static void DSOUND_PerformMix(void)
playpos = dsound->pwplay * dsound->fraglen;
writepos = playpos;
if (!paused) {
writepos += DS_HEL_MARGIN * dsound->fraglen;
writepos += ds_hel_margin * dsound->fraglen;
while (writepos >= primarybuf->buflen)
writepos -= primarybuf->buflen;
}
......@@ -3515,7 +3599,7 @@ HRESULT WINAPI DirectSoundCreate(REFGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pU
PIDSDRIVER drv = NULL;
WAVEOUTCAPSA wcaps;
unsigned wod, wodn;
HRESULT err = DS_OK;
HRESULT err = DS_OK;
if (lpGUID)
TRACE("(%p,%p,%p)\n",lpGUID,ippDS,pUnkOuter);
......@@ -3531,6 +3615,9 @@ HRESULT WINAPI DirectSoundCreate(REFGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pU
return DS_OK;
}
/* get dsound configuration */
setup_dsound_options();
/* Enumerate WINMM audio devices and find the one we want */
wodn = waveOutGetNumDevs();
if (!wodn) return DSERR_NODRIVER;
......@@ -3559,7 +3646,7 @@ HRESULT WINAPI DirectSoundCreate(REFGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pU
(*ippDS)->primary = NULL;
(*ippDS)->listener = NULL;
(*ippDS)->prebuf = DS_SND_QUEUE_MAX;
(*ippDS)->prebuf = ds_snd_queue_max;
/* Get driver description */
if (drv) {
......@@ -3619,10 +3706,11 @@ HRESULT WINAPI DirectSoundCreate(REFGUID lpGUID,LPDIRECTSOUND *ppDS,IUnknown *pU
} else {
unsigned c;
/* FIXME: look at wcaps */
(*ippDS)->drvcaps.dwFlags =
DSCAPS_PRIMARY16BIT | DSCAPS_PRIMARYSTEREO;
if (DS_EMULDRIVER)
if (ds_emuldriver)
(*ippDS)->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
/* Allocate memory for HEL buffer headers */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment