ref: 140b307ed8b5f7681e2d0316fb1c867febb27d6c
parent: 9889d0321728042f16dd37d45235d051953070ec
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sun Dec 24 12:34:34 EST 2023
sort out AL device/hrtf dynamic switching; introduce cvar callbacks
--- a/cvar.c
+++ b/cvar.c
@@ -125,10 +125,14 @@
if (Cmd_Argc() == 1)
{
Con_Printf ("\"%s\" is \"%s\"\n", v->name, v->string);
+ if(v->cb != nil)
+ v->cb(v);
return true;
}
setcvar (v->name, Cmd_Argv(1));
+ if(v->cb != nil)
+ v->cb(v);
return true;
}
--- a/cvar.h
+++ b/cvar.h
@@ -32,15 +32,18 @@
interface from being ambiguous.
*/
-typedef struct cvar_s
+typedef struct cvar_s cvar_t;
+
+struct cvar_s
{
- char *name;
- char *string;
+ char *name;
+ char *string;
bool archive; // set to true to cause it to be saved to vars.rc
bool server; // notifies players when changed
- float value;
+ float value;
+ void (*cb) (cvar_t *);
struct cvar_s *next;
-} cvar_t;
+};
void Cvar_RegisterVariable (cvar_t *variable);
// registers a cvar that already has the name, string, and optionally the
--- a/unix/snd_openal.c
+++ b/unix/snd_openal.c
@@ -25,10 +25,13 @@
};
cvar_t volume = {"volume", "0.7", 1};
-static cvar_t s_al_dev = {"s_al_device", "", true};
+
+static cvar_t s_al_dev = {"s_al_device", "-1", true};
+static int s_al_dev_prev = -2;
+
+static cvar_t s_al_hrtf = {"s_al_hrtf", "0", true};
static cvar_t s_al_resampler_default = {"s_al_resampler_default", "6", true}; // 23rd order Sinc
static cvar_t s_al_resampler_up = {"s_al_resampler_up", "1", true}; // Linear
-static cvar_t s_al_hrtf = {"s_al_hrtf", "0", true};
static cvar_t ambient_level = {"ambient_level", "0.3"};
static cvar_t ambient_fade = {"ambient_fade", "100"};
@@ -41,7 +44,10 @@
static alchan_t *chans;
static int al_default_resampler, al_num_resamplers;
-static char *(*alGetStringiSOFT)(ALenum, ALsizei);
+static ALchar *(*qk1alGetStringiSOFT)(ALenum, ALsizei);
+static ALCchar *(*qk1alcGetStringiSOFT)(ALCdevice *, ALenum, ALsizei);
+static ALCboolean (*qk1alcResetDeviceSOFT)(ALCdevice *, const ALCint *attr);
+static ALCboolean *(*qk1alcReopenDeviceSOFT)(ALCdevice *, const ALCchar *devname, const ALCint *attr);
#define ALERR() alcheckerr(__FILE__, __LINE__)
@@ -65,7 +71,7 @@
break;
}
ret |= e;
- fprintf(stderr, "%s:%d: AL: %s\n", file, line, s);
+ fprintf(stderr, "AL: %s:%d: %s\n", file, line, s);
}
if(dev != nil && (e = alcGetError(dev)) != ALC_NO_ERROR){
switch(e){
@@ -80,7 +86,7 @@
break;
}
ret |= e;
- fprintf(stderr, "%s:%d: ALC: %s\n", file, line, s);
+ fprintf(stderr, "ALC: %s:%d: %s\n", file, line, s);
}
return ret;
@@ -354,27 +360,37 @@
return sfx;
}
+static ALCint *
+alcattr(bool hrtf)
+{
+ static ALCint attr[] = {
+ 0, 0, 0, 0, 0,
+ };
+
+ attr[0] = 0;
+ if(hrtf){
+ attr[0] = s_al_hrtf.value != 0 ? ALC_HRTF_SOFT : 0;
+ attr[1] = s_al_hrtf.value != 0 ? (s_al_hrtf.value > 0 ? ALC_TRUE : ALC_FALSE) : ALC_DONT_CARE_SOFT;
+ if(attr[1] == ALC_TRUE){
+ attr[2] = ALC_HRTF_ID_SOFT;
+ attr[3] = s_al_hrtf.value - 1;
+ }
+ }
+
+ return attr;
+}
+
static int
-alinit(void)
+alinit(const char *devname)
{
- const char *devname;
ALCcontext *c;
int e;
- ALCint attr[] = {
- 0, 0, 0
- };
- if(*(devname = s_al_dev.string) == 0)
- devname = alcGetString(nil, ALC_DEFAULT_DEVICE_SPECIFIER);
- if(devname == nil)
- return -1;
dev = alcOpenDevice(devname); ALERR();
if(dev == nil)
return -1;
- attr[0] = s_al_hrtf.value != 0 ? ALC_HRTF_SOFT : 0;
- attr[1] = s_al_hrtf.value > 0 ? ALC_TRUE : ALC_FALSE;
- c = alcCreateContext(dev, attr); ALERR();
+ c = alcCreateContext(dev, nil); ALERR();
if(c == nil){
closedev:
alcCloseDevice(dev); ALERR();
@@ -403,12 +419,99 @@
al_num_resamplers = alGetInteger(AL_NUM_RESAMPLERS_SOFT);
if(ALERR())
al_num_resamplers = 0;
- alGetStringiSOFT = alGetProcAddress("alGetStringiSOFT");
+ qk1alGetStringiSOFT = alGetProcAddress("alGetStringiSOFT");
}
-
return 0;
}
+static void
+alreinit(const char *def, const char *all)
+{
+ const char *s;
+ int i, n;
+
+ n = s_al_dev.value;
+ if(n == s_al_dev_prev)
+ return;
+ if(qk1alcReopenDeviceSOFT == nil && alcIsExtensionPresent(nil, "ALC_SOFT_reopen_device"))
+ qk1alcReopenDeviceSOFT = alGetProcAddress("alcReopenDeviceSOFT");
+ if(qk1alcReopenDeviceSOFT == nil){
+ Con_Printf("AL: can't change device settings on the fly\n");
+ return;
+ }
+ for(i = 1, s = all; s != nil && *s; i++){
+ if((n == 0 && def != nil && strcmp(s, def) == 0) || n == i){
+ if(dev == nil)
+ n = alinit(all);
+ else{
+ n = qk1alcReopenDeviceSOFT(dev, s, alcattr(false)) ? 0 : -1;
+ ALERR();
+ }
+ if(n != 0)
+ Con_Printf("AL: failed to switch to %s\n", s);
+ else
+ s_al_dev_prev = n;
+ return;
+ }
+ s += strlen(s)+1;
+ }
+ Con_Printf("AL: no such device: %d\n", n);
+}
+
+static void
+alvarcb(cvar_t *var)
+{
+ const char *all, *def, *s;
+ bool hrtf;
+ int i, n;
+
+ def = alcGetString(nil, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
+ if(ALERR())
+ def = nil;
+ all = alcGetString(nil, ALC_ALL_DEVICES_SPECIFIER);
+ if(ALERR())
+ all = nil;
+
+ if(var == &s_al_dev && Cmd_Argc() == 1){
+ Con_Printf("%-2d: default (%s)\n", 0, def ? def : "<invalid>");
+ for(i = 1, s = all; s != nil && *s; i++){
+ Con_Printf("%-2d: %s%s\n", i, s, strcmp(s, def) == 0 ? " (default)" : "");
+ s += strlen(s)+1;
+ }
+ return;
+ }
+
+ alreinit(def, all);
+
+ if(alcIsExtensionPresent(dev, "ALC_SOFT_HRTF")){
+ qk1alcGetStringiSOFT = alcGetProcAddress(dev, "alcGetStringiSOFT");
+ qk1alcResetDeviceSOFT = alcGetProcAddress(dev, "alcResetDeviceSOFT");
+ hrtf = true;
+ }else{
+ qk1alcGetStringiSOFT = nil;
+ qk1alcResetDeviceSOFT = nil;
+ hrtf = false;
+ }
+ if(var == &s_al_hrtf && Cmd_Argc() == 1){
+ Con_Printf("%-2d: disabled\n", -1);
+ Con_Printf("%-2d: don't care (default)\n", 0);
+ if(qk1alcGetStringiSOFT == nil)
+ return;
+ alcGetIntegerv(dev, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &n); ALERR();
+ for(i = 0; i < n; i++){
+ s = qk1alcGetStringiSOFT(dev, ALC_HRTF_SPECIFIER_SOFT, i);
+ if(!ALERR() && s != nil)
+ Con_Printf("%-2d: %s\n", i+1, s);
+ }
+ return;
+ }
+
+ if(qk1alcResetDeviceSOFT != nil){
+ qk1alcResetDeviceSOFT(dev, alcattr(hrtf));
+ ALERR();
+ }
+}
+
void
sfxbegin(void)
{
@@ -417,6 +520,8 @@
int
initsnd(void)
{
+ s_al_dev.cb = s_al_hrtf.cb = alvarcb;
+
Cvar_RegisterVariable(&volume);
Cvar_RegisterVariable(&ambient_level);
Cvar_RegisterVariable(&ambient_fade);
@@ -426,7 +531,7 @@
Cvar_RegisterVariable(&s_al_hrtf);
Cmd_AddCommand("stopsound", stopallsfx);
- alinit();
+ alinit(nil);
known_sfx = Hunk_Alloc(MAX_SOUNDS * sizeof *known_sfx);
num_sfx = 0;