- cleanup of sound system startup and menu handling:

* added global functions that check whether FMod and OpenAL are present, without initializing the sound backend.
* make sound init code more fault tolerant. It will now try to switch between FMod and OpenAL if the currently active one cannot be found but the other one can.
* added 'ifoption' checks for sound backend to menu code.
* only show sound backends which are present and hide the options for the ones which are not.
This commit is contained in:
Christoph Oelckers 2015-04-26 12:13:21 +02:00
parent 8e70a9b894
commit aecff68a4d
6 changed files with 188 additions and 30 deletions

View file

@ -49,6 +49,7 @@
#include "i_music.h"
#include "m_joy.h"
#include "gi.h"
#include "i_sound.h"
#include "optionmenuitems.h"
@ -170,6 +171,14 @@ static bool CheckSkipOptionBlock(FScanner &sc)
filter = true;
#endif
}
else if (sc.Compare("OpenAL"))
{
filter |= IsOpenALPresent();
}
else if (sc.Compare("FModEx"))
{
filter |= IsFModExPresent();
}
}
while (sc.CheckString(","));
sc.MustGetStringName(")");
@ -591,7 +600,11 @@ static void ParseOptionSettings(FScanner &sc)
while (!sc.CheckString("}"))
{
sc.MustGetString();
if (sc.Compare("ifgame"))
if (sc.Compare("else"))
{
SkipSubBlock(sc);
}
else if (sc.Compare("ifgame"))
{
if (!CheckSkipGameBlock(sc))
{
@ -628,7 +641,11 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc)
while (!sc.CheckString("}"))
{
sc.MustGetString();
if (sc.Compare("ifgame"))
if (sc.Compare("else"))
{
SkipSubBlock(sc);
}
else if (sc.Compare("ifgame"))
{
if (!CheckSkipGameBlock(sc))
{

View file

@ -671,14 +671,8 @@ bool FMODSoundRenderer::Init()
Printf("I_InitSound: Initializing FMOD\n");
HMODULE a = GetModuleHandle("fmodex.dll");
// Create a System object and initialize.
__try
{
result = FMOD::System_Create(&Sys);
}
__except(CheckException(GetExceptionCode()))
// This is just for safety. Normally this should never be called if FMod Ex cannot be found.
if (!IsFModExPresent())
{
Sys = NULL;
Printf(TEXTCOLOR_ORANGE"Failed to load fmodex"
@ -688,6 +682,9 @@ bool FMODSoundRenderer::Init()
".dll\n");
return false;
}
// Create a System object and initialize.
result = FMOD::System_Create(&Sys);
if (result != FMOD_OK)
{
Sys = NULL;
@ -3177,3 +3174,44 @@ FMOD_RESULT FMODSoundRenderer::SetSystemReverbProperties(const REVERB_PROPERTIES
}
#endif // NO_FMOD
//==========================================================================
//
// IsFModExPresent
//
// Check if FMod can be used
//
//==========================================================================
bool IsFModExPresent()
{
#ifdef NO_FMOD
return false;
#elif !defined _WIN32
return true; // on non-Windows we cannot delay load the library so it has to be present.
#else
static bool cached_result;
static bool done = false;
if (!done)
{
done = true;
FMOD::System *Sys;
FMOD_RESULT result;
__try
{
result = FMOD::System_Create(&Sys);
}
__except (CheckException(GetExceptionCode()))
{
// FMod could not be delay loaded
return false;
}
if (result == FMOD_OK) Sys->release();
cached_result = true;
}
return cached_result;
#endif
}

View file

@ -83,13 +83,15 @@ CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, snd_output, "default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
#ifndef NO_FMOD
CVAR (String, snd_backend, "fmod", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
#define DEF_BACKEND "fmod"
#elif !defined(NO_OPENAL)
CVAR (String, snd_backend, "openal", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
#define DEF_BACKEND "openal"
#else
CVAR (String, snd_backend, "null", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
#define DEF_BACKEND "null"
#endif
CVAR(String, snd_backend, DEF_BACKEND, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
// killough 2/21/98: optionally use varying pitched sounds
CVAR (Bool, snd_pitched, false, CVAR_ARCHIVE)
@ -256,6 +258,7 @@ void I_InitSound ()
nosound = !!Args->CheckParm ("-nosound");
nosfx = !!Args->CheckParm ("-nosfx");
GSnd = NULL;
if (nosound)
{
GSnd = new NullSoundRenderer;
@ -263,16 +266,50 @@ void I_InitSound ()
return;
}
if(stricmp(snd_backend, "null") == 0)
// This has been extended to allow falling back from FMod to OpenAL and vice versa if the currently active sound system cannot be found.
if (stricmp(snd_backend, "null") == 0)
{
GSnd = new NullSoundRenderer;
#ifndef NO_FMOD
}
else if(stricmp(snd_backend, "fmod") == 0)
{
#ifndef NO_FMOD
if (IsFModExPresent())
{
GSnd = new FMODSoundRenderer;
#endif
#ifndef NO_OPENAL
else if(stricmp(snd_backend, "openal") == 0)
}
#endif
#ifndef NO_OPENAL
if ((!GSnd || !GSnd->IsValid()) && IsOpenALPresent())
{
Printf (TEXTCOLOR_RED"FMod Ex Sound init failed. Trying OpenAL.\n");
GSnd = new OpenALSoundRenderer;
#endif
snd_backend = "openal";
}
#endif
}
else if(stricmp(snd_backend, "openal") == 0)
{
#ifndef NO_OPENAL
if (IsOpenALPresent())
{
GSnd = new OpenALSoundRenderer;
}
#endif
#ifndef NO_FMOD
if ((!GSnd || !GSnd->IsValid()) && IsFModExPresent())
{
Printf (TEXTCOLOR_RED"OpenAL Sound init failed. Trying FMod Ex.\n");
GSnd = new FMODSoundRenderer;
snd_backend = "fmod";
}
#endif
}
else
{
Printf (TEXTCOLOR_RED"%s: Unknown sound system specified\n", *snd_backend);
snd_backend = "null";
}
if (!GSnd || !GSnd->IsValid ())
{
I_CloseSound();

View file

@ -175,4 +175,7 @@ FISoundChannel *S_GetChannel(void *syschan);
extern ReverbContainer *DefaultEnvironments[26];
bool IsFModExPresent();
bool IsOpenALPresent();
#endif

View file

@ -59,6 +59,36 @@ CVAR (String, snd_aldevice, "Default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, snd_efx, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
bool IsOpenALPresent()
{
#ifdef NO_OPENAL
return false;
#elif !defined _WIN32
return true; // on non-Windows we cannot delay load the library so it has to be present.
#else
static bool cached_result;
static bool done = false;
if (!done)
{
done = true;
__try
{
// just call one function from the API to force loading the DLL
alcGetError(NULL);
}
__except (CheckException(GetExceptionCode()))
{
// FMod could not be delay loaded
return false;
}
cached_result = true;
}
return cached_result;
#endif
}
void I_BuildALDeviceList(FOptionValues *opt)
{
opt->mValues.Resize(1);
@ -66,7 +96,7 @@ void I_BuildALDeviceList(FOptionValues *opt)
opt->mValues[0].Text = "Default";
#ifndef NO_OPENAL
__try
if (IsOpenALPresent())
{
const ALCchar *names = (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") ?
alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER) :
@ -82,9 +112,6 @@ void I_BuildALDeviceList(FOptionValues *opt)
names += strlen(names) + 1;
}
}
__except (CheckException(GetExceptionCode()))
{
}
#endif
}
@ -601,7 +628,7 @@ static float GetRolloff(const FRolloffInfo *rolloff, float distance)
ALCdevice *OpenALSoundRenderer::InitDevice()
{
ALCdevice *device = NULL;
__try
if (IsOpenALPresent())
{
if(strcmp(snd_aldevice, "Default") != 0)
{
@ -619,7 +646,7 @@ ALCdevice *OpenALSoundRenderer::InitDevice()
}
}
}
__except(CheckException(GetExceptionCode()))
else
{
Printf(TEXTCOLOR_ORANGE"Failed to load openal32.dll\n");
}

View file

@ -1450,11 +1450,22 @@ OptionString Resamplers
OptionString SoundBackends
{
"fmod", "FMOD"
"fmod", "FMOD Ex"
"openal", "OpenAL"
"null", "No Sound"
}
OptionString SoundBackendsFModOnly
{
"fmod", "FMOD Ex"
"null", "No Sound"
}
OptionString SoundBackendsOpenALOnly
{
"openal", "OpenAL"
"null", "No Sound"
}
OptionMenu FMODSoundItems
{
@ -1507,9 +1518,34 @@ OptionMenu SoundOptions
Option "Randomize pitches", "snd_pitched", "OnOff"
Slider "Sound channels", "snd_channels", 8, 256, 8, 0
StaticText " "
ifoption(fmodex)
{
ifoption(openal)
{
Option "Sound backend", "snd_backend", "SoundBackends"
}
else
{
Option "Sound backend", "snd_backend", "SoundBackendsFModOnly"
}
}
else
{
ifoption(openal)
{
Option "Sound backend", "snd_backend", "SoundBackendsOpenALOnly"
}
}
ifoption(fmodex)
{
Submenu "FMOD options", "FMODSoundItems"
}
ifoption(openal)
{
Submenu "OpenAL options", "OpenALSoundItems"
}
StaticText " "
Command "Restart sound", "snd_reset"