- make OpenAL and the decoder libraries delay loaded so that ZDoom can still start without them being present.

This required the addition of a few exception handlers so to avoid #ifdef overuse I also added some #defines for non-Windows systems that allow using __try and __except directly in the code without #ifdef'ing them out.
This commit is contained in:
Christoph Oelckers 2015-04-25 12:25:10 +02:00
parent 12118550d2
commit d880783784
8 changed files with 148 additions and 86 deletions

View file

@ -1200,9 +1200,9 @@ endif( NOT ZDOOM_OUTPUT_OLDSTYLE OR NO_GENERATOR_EXPRESSIONS )
if( MSVC ) if( MSVC )
option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF )
if( ZDOOM_GENERATE_MAPFILE ) if( ZDOOM_GENERATE_MAPFILE )
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /MAP") set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\" /MAP")
else( ZDOOM_GENERATE_MAPFILE ) else( ZDOOM_GENERATE_MAPFILE )
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\"") set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\"")
endif( ZDOOM_GENERATE_MAPFILE ) endif( ZDOOM_GENERATE_MAPFILE )
add_custom_command(TARGET zdoom POST_BUILD add_custom_command(TARGET zdoom POST_BUILD

34
src/sound/except.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef __EXCEPT_H
#define __EXCEPT_H
#ifdef _MSC_VER
//==========================================================================
//
// CheckException
//
//==========================================================================
#ifndef FACILITY_VISUALCPP
#define FACILITY_VISUALCPP ((LONG)0x6d)
#endif
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
inline int CheckException(DWORD code)
{
if (code == VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND) ||
code == VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND))
{
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
}
#else
#define __try
#define __except(a) if (0)
#endif
#endif

View file

@ -52,6 +52,7 @@ extern HWND Window;
#include <malloc.h> #include <malloc.h>
#endif #endif
#include "except.h"
#include "templates.h" #include "templates.h"
#include "fmodsound.h" #include "fmodsound.h"
#include "c_cvars.h" #include "c_cvars.h"
@ -629,30 +630,6 @@ bool FMODSoundRenderer::IsValid()
return InitSuccess; return InitSuccess;
} }
#ifdef _MSC_VER
//==========================================================================
//
// CheckException
//
//==========================================================================
#ifndef FACILITY_VISUALCPP
#define FACILITY_VISUALCPP ((LONG)0x6d)
#endif
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
static int CheckException(DWORD code)
{
if (code == VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND) ||
code == VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND))
{
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
//========================================================================== //==========================================================================
// //
// FMODSoundRenderer :: Init // FMODSoundRenderer :: Init
@ -690,12 +667,12 @@ bool FMODSoundRenderer::Init()
Printf("I_InitSound: Initializing FMOD\n"); Printf("I_InitSound: Initializing FMOD\n");
HMODULE a = GetModuleHandle("fmodex.dll");
// Create a System object and initialize. // Create a System object and initialize.
#ifdef _MSC_VER __try
__try { {
#endif result = FMOD::System_Create(&Sys);
result = FMOD::System_Create(&Sys);
#ifdef _MSC_VER
} }
__except(CheckException(GetExceptionCode())) __except(CheckException(GetExceptionCode()))
{ {
@ -707,7 +684,6 @@ bool FMODSoundRenderer::Init()
".dll\n"); ".dll\n");
return false; return false;
} }
#endif
if (result != FMOD_OK) if (result != FMOD_OK)
{ {
Sys = NULL; Sys = NULL;

View file

@ -53,6 +53,7 @@ extern HINSTANCE g_hInst;
#include "doomtype.h" #include "doomtype.h"
#include <math.h> #include <math.h>
#include "except.h"
#include "fmodsound.h" #include "fmodsound.h"
#include "oalsound.h" #include "oalsound.h"
@ -574,22 +575,22 @@ SoundDecoder *SoundRenderer::CreateDecoder(FileReader *reader)
int pos = reader->Tell(); int pos = reader->Tell();
#ifdef HAVE_MPG123 #ifdef HAVE_MPG123
decoder = new MPG123Decoder; decoder = new MPG123Decoder;
if(decoder->open(reader)) if (decoder->open(reader))
return decoder; return decoder;
reader->Seek(pos, SEEK_SET); reader->Seek(pos, SEEK_SET);
delete decoder; delete decoder;
decoder = NULL; decoder = NULL;
#endif #endif
#ifdef HAVE_SNDFILE #ifdef HAVE_SNDFILE
decoder = new SndFileDecoder; decoder = new SndFileDecoder;
if(decoder->open(reader)) if (decoder->open(reader))
return decoder; return decoder;
reader->Seek(pos, SEEK_SET); reader->Seek(pos, SEEK_SET);
delete decoder; delete decoder;
decoder = NULL; decoder = NULL;
#endif #endif
return decoder; return decoder;
} }

View file

@ -1,3 +1,10 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define USE_WINDOWS_DWORD
#endif
#include "except.h"
#include "mpg123_decoder.h" #include "mpg123_decoder.h"
#include "files.h" #include "files.h"
@ -49,9 +56,17 @@ bool MPG123Decoder::open(FileReader *reader)
{ {
if(!inited) if(!inited)
{ {
if(mpg123_init() != MPG123_OK) __try
return false; {
inited = true; if(mpg123_init() != MPG123_OK)
return false;
inited = true;
}
__except (CheckException(GetExceptionCode()))
{
// this means that the delay loaded decoder DLL was not found.
return false;
}
} }
Reader = reader; Reader = reader;

View file

@ -38,6 +38,7 @@
#define USE_WINDOWS_DWORD #define USE_WINDOWS_DWORD
#endif #endif
#include "except.h"
#include "doomstat.h" #include "doomstat.h"
#include "templates.h" #include "templates.h"
#include "oalsound.h" #include "oalsound.h"
@ -65,19 +66,25 @@ void I_BuildALDeviceList(FOptionValues *opt)
opt->mValues[0].Text = "Default"; opt->mValues[0].Text = "Default";
#ifndef NO_OPENAL #ifndef NO_OPENAL
const ALCchar *names = (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") ? __try
alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER) : {
alcGetString(NULL, ALC_DEVICE_SPECIFIER)); const ALCchar *names = (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") ?
if(!names) alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER) :
Printf("Failed to get device list: %s\n", alcGetString(NULL, alcGetError(NULL))); alcGetString(NULL, ALC_DEVICE_SPECIFIER));
else while(*names) if (!names)
{ Printf("Failed to get device list: %s\n", alcGetString(NULL, alcGetError(NULL)));
unsigned int i = opt->mValues.Reserve(1); else while (*names)
opt->mValues[i].TextValue = names; {
opt->mValues[i].Text = names; unsigned int i = opt->mValues.Reserve(1);
opt->mValues[i].TextValue = names;
opt->mValues[i].Text = names;
names += strlen(names)+1; names += strlen(names) + 1;
} }
}
__except (CheckException(GetExceptionCode()))
{
}
#endif #endif
} }
@ -588,6 +595,34 @@ static float GetRolloff(const FRolloffInfo *rolloff, float distance)
return (powf(10.f, volume) - 1.f) / 9.f; return (powf(10.f, volume) - 1.f) / 9.f;
} }
ALCdevice *OpenALSoundRenderer::InitDevice()
{
ALCdevice *device = NULL;
__try
{
if(strcmp(snd_aldevice, "Default") != 0)
{
device = alcOpenDevice(*snd_aldevice);
if(!device)
Printf(TEXTCOLOR_BLUE" Failed to open device "TEXTCOLOR_BOLD"%s"TEXTCOLOR_BLUE". Trying default.\n", *snd_aldevice);
}
if(!device)
{
device = alcOpenDevice(NULL);
if(!device)
{
Printf(TEXTCOLOR_RED" Could not open audio device\n");
}
}
}
__except(CheckException(GetExceptionCode()))
{
Printf(TEXTCOLOR_ORANGE"Failed to load openal32.dll\n");
}
return device;
}
template<typename T> template<typename T>
static void LoadALFunc(const char *name, T *x) static void LoadALFunc(const char *name, T *x)
@ -601,22 +636,8 @@ OpenALSoundRenderer::OpenALSoundRenderer()
Printf("I_InitSound: Initializing OpenAL\n"); Printf("I_InitSound: Initializing OpenAL\n");
if(strcmp(snd_aldevice, "Default") != 0) Device = InitDevice();
{ if (Device == NULL) return;
Device = alcOpenDevice(*snd_aldevice);
if(!Device)
Printf(TEXTCOLOR_BLUE" Failed to open device "TEXTCOLOR_BOLD"%s"TEXTCOLOR_BLUE". Trying default.\n", *snd_aldevice);
}
if(!Device)
{
Device = alcOpenDevice(NULL);
if(!Device)
{
Printf(TEXTCOLOR_RED" Could not open audio device\n");
return;
}
}
const ALCchar *current = NULL; const ALCchar *current = NULL;
if(alcIsExtensionPresent(Device, "ALC_ENUMERATE_ALL_EXT")) if(alcIsExtensionPresent(Device, "ALC_ENUMERATE_ALL_EXT"))

View file

@ -206,6 +206,8 @@ private:
TArray<OpenALSoundStream*> Streams; TArray<OpenALSoundStream*> Streams;
friend class OpenALSoundStream; friend class OpenALSoundStream;
ALCdevice *InitDevice();
}; };
#endif // NO_OPENAL #endif // NO_OPENAL

View file

@ -1,3 +1,10 @@
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define USE_WINDOWS_DWORD
#endif
#include "except.h"
#include "sndfile_decoder.h" #include "sndfile_decoder.h"
#include "files.h" #include "files.h"
@ -47,19 +54,25 @@ SndFileDecoder::~SndFileDecoder()
bool SndFileDecoder::open(FileReader *reader) bool SndFileDecoder::open(FileReader *reader)
{ {
SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell }; __try
{
SF_VIRTUAL_IO sfio = { file_get_filelen, file_seek, file_read, file_write, file_tell };
Reader = reader; Reader = reader;
SndFile = sf_open_virtual(&sfio, SFM_READ, &SndInfo, this); SndFile = sf_open_virtual(&sfio, SFM_READ, &SndInfo, this);
if(SndFile) if (SndFile)
{ {
if(SndInfo.channels == 1 || SndInfo.channels == 2) if (SndInfo.channels == 1 || SndInfo.channels == 2)
return true; return true;
sf_close(SndFile);
SndFile = 0;
}
sf_close(SndFile);
SndFile = 0;
}
}
__except (CheckException(GetExceptionCode()))
{
// this means that the delay loaded decoder DLL was not found.
}
return false; return false;
} }