drop sdl_mixer
parent
fa80b2c710
commit
c4d7dcf2c7
|
@ -34,7 +34,6 @@ client_src = [
|
||||||
'../engine/server.cpp',
|
'../engine/server.cpp',
|
||||||
'../engine/serverbrowser.cpp',
|
'../engine/serverbrowser.cpp',
|
||||||
'../engine/shader.cpp',
|
'../engine/shader.cpp',
|
||||||
'../engine/sound.cpp',
|
|
||||||
'../engine/stain.cpp',
|
'../engine/stain.cpp',
|
||||||
'../engine/texture.cpp',
|
'../engine/texture.cpp',
|
||||||
'../engine/ui.cpp',
|
'../engine/ui.cpp',
|
||||||
|
@ -55,7 +54,6 @@ client_src = [
|
||||||
threads_dep = dependency('threads')
|
threads_dep = dependency('threads')
|
||||||
sdl2_dep = dependency('sdl2')
|
sdl2_dep = dependency('sdl2')
|
||||||
sdl2_image_dep = dependency('SDL2_image')
|
sdl2_image_dep = dependency('SDL2_image')
|
||||||
sdl2_mixer_dep = dependency('SDL2_mixer')
|
|
||||||
zlib_dep = dependency('zlib')
|
zlib_dep = dependency('zlib')
|
||||||
gl_dep = dependency('gl')
|
gl_dep = dependency('gl')
|
||||||
rt_dep = cc.find_library('rt', required: false)
|
rt_dep = cc.find_library('rt', required: false)
|
||||||
|
@ -64,7 +62,7 @@ executable('native_client',
|
||||||
client_src,
|
client_src,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
threads_dep, libenet, sdl2_dep, sdl2_image_dep,
|
threads_dep, libenet, sdl2_dep, sdl2_image_dep,
|
||||||
sdl2_mixer_dep, zlib_dep, gl_dep, rt_dep
|
zlib_dep, gl_dep, rt_dep
|
||||||
],
|
],
|
||||||
include_directories: octacore_includes,
|
include_directories: octacore_includes,
|
||||||
install: true,
|
install: true,
|
||||||
|
|
|
@ -752,16 +752,6 @@ extern void clearchanges(int type);
|
||||||
extern void menuprocess();
|
extern void menuprocess();
|
||||||
extern void clearmainmenu();
|
extern void clearmainmenu();
|
||||||
|
|
||||||
// sound
|
|
||||||
extern void clearmapsounds();
|
|
||||||
extern void checkmapsounds();
|
|
||||||
extern void updatesounds();
|
|
||||||
extern void preloadmapsounds();
|
|
||||||
|
|
||||||
extern void initmumble();
|
|
||||||
extern void closemumble();
|
|
||||||
extern void updatemumble();
|
|
||||||
|
|
||||||
// grass
|
// grass
|
||||||
extern void loadgrassshaders();
|
extern void loadgrassshaders();
|
||||||
extern void generategrass();
|
extern void generategrass();
|
||||||
|
|
|
@ -17,7 +17,7 @@ void cleanup()
|
||||||
extern void clear_command(); clear_command();
|
extern void clear_command(); clear_command();
|
||||||
extern void clear_console(); clear_console();
|
extern void clear_console(); clear_console();
|
||||||
extern void clear_models(); clear_models();
|
extern void clear_models(); clear_models();
|
||||||
extern void clear_sound(); clear_sound();
|
//extern void clear_sound(); clear_sound();
|
||||||
closelogfile();
|
closelogfile();
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if(screen) SDL_SetWindowFullscreen(screen, 0);
|
if(screen) SDL_SetWindowFullscreen(screen, 0);
|
||||||
|
@ -109,13 +109,6 @@ void writeinitcfg()
|
||||||
f->printf("fullscreen %d\n", fullscreen);
|
f->printf("fullscreen %d\n", fullscreen);
|
||||||
f->printf("screenw %d\n", scr_w);
|
f->printf("screenw %d\n", scr_w);
|
||||||
f->printf("screenh %d\n", scr_h);
|
f->printf("screenh %d\n", scr_h);
|
||||||
extern int sound, soundchans, soundfreq, soundbufferlen;
|
|
||||||
extern char *audiodriver;
|
|
||||||
f->printf("sound %d\n", sound);
|
|
||||||
f->printf("soundchans %d\n", soundchans);
|
|
||||||
f->printf("soundfreq %d\n", soundfreq);
|
|
||||||
f->printf("soundbufferlen %d\n", soundbufferlen);
|
|
||||||
if(audiodriver[0]) f->printf("audiodriver %s\n", escapestring(audiodriver));
|
|
||||||
delete f;
|
delete f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,7 +247,7 @@ void renderbackground(const char *caption, Texture *mapshot, const char *mapname
|
||||||
{
|
{
|
||||||
if(!inbetweenframes && !force) return;
|
if(!inbetweenframes && !force) return;
|
||||||
|
|
||||||
if(menumute) stopsounds(); // stop sounds while loading
|
//if(menumute) stopsounds(); // stop sounds while loading
|
||||||
|
|
||||||
int w = hudw, h = hudh;
|
int w = hudw, h = hudh;
|
||||||
if(forceaspect) w = int(ceil(h*forceaspect));
|
if(forceaspect) w = int(ceil(h*forceaspect));
|
||||||
|
@ -1123,7 +1116,7 @@ int main(int argc, char **argv)
|
||||||
emptymap(0, true, NULL, false);
|
emptymap(0, true, NULL, false);
|
||||||
|
|
||||||
logoutf("init: sound");
|
logoutf("init: sound");
|
||||||
initsound();
|
//initsound();
|
||||||
|
|
||||||
logoutf("init: cfg");
|
logoutf("init: cfg");
|
||||||
initing = INIT_LOAD;
|
initing = INIT_LOAD;
|
||||||
|
@ -1175,7 +1168,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
if(initscript) execute(initscript);
|
if(initscript) execute(initscript);
|
||||||
|
|
||||||
initmumble();
|
//initmumble();
|
||||||
resetfpshistory();
|
resetfpshistory();
|
||||||
|
|
||||||
inputgrab(grabinput = true);
|
inputgrab(grabinput = true);
|
||||||
|
@ -1214,7 +1207,7 @@ int main(int argc, char **argv)
|
||||||
// miscellaneous general game effects
|
// miscellaneous general game effects
|
||||||
recomputecamera();
|
recomputecamera();
|
||||||
updateparticles();
|
updateparticles();
|
||||||
updatesounds();
|
//updatesounds();
|
||||||
|
|
||||||
if(minimized) continue;
|
if(minimized) continue;
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,7 @@ struct aviwriter
|
||||||
path(filename);
|
path(filename);
|
||||||
if(!strrchr(filename, '.')) concatstring(filename, ".avi");
|
if(!strrchr(filename, '.')) concatstring(filename, ".avi");
|
||||||
|
|
||||||
|
#if 0
|
||||||
extern bool nosound; // sound.cpp
|
extern bool nosound; // sound.cpp
|
||||||
if(sound && !nosound)
|
if(sound && !nosound)
|
||||||
{
|
{
|
||||||
|
@ -210,6 +211,7 @@ struct aviwriter
|
||||||
}
|
}
|
||||||
if(dbgmovie) conoutf(CON_DEBUG, "soundspec: %dhz %s x %d", soundfrequency, desc, soundchannels);
|
if(dbgmovie) conoutf(CON_DEBUG, "soundspec: %dhz %s x %d", soundfrequency, desc, soundchannels);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
~aviwriter()
|
~aviwriter()
|
||||||
|
@ -958,7 +960,7 @@ namespace recorder
|
||||||
shouldencode = SDL_CreateCond();
|
shouldencode = SDL_CreateCond();
|
||||||
shouldread = SDL_CreateCond();
|
shouldread = SDL_CreateCond();
|
||||||
thread = SDL_CreateThread(videoencoder, "video encoder", NULL);
|
thread = SDL_CreateThread(videoencoder, "video encoder", NULL);
|
||||||
if(file->soundfrequency > 0) Mix_SetPostMix(soundencoder, NULL);
|
//if(file->soundfrequency > 0) Mix_SetPostMix(soundencoder, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup()
|
void cleanup()
|
||||||
|
@ -974,7 +976,7 @@ namespace recorder
|
||||||
{
|
{
|
||||||
if(!file) return;
|
if(!file) return;
|
||||||
if(state == REC_OK) state = REC_USERHALT;
|
if(state == REC_OK) state = REC_USERHALT;
|
||||||
if(file->soundfrequency > 0) Mix_SetPostMix(NULL, NULL);
|
//if(file->soundfrequency > 0) Mix_SetPostMix(NULL, NULL);
|
||||||
|
|
||||||
SDL_LockMutex(videolock); // wakeup thread enough to kill it
|
SDL_LockMutex(videolock); // wakeup thread enough to kill it
|
||||||
SDL_CondSignal(shouldencode);
|
SDL_CondSignal(shouldencode);
|
||||||
|
|
|
@ -1,881 +0,0 @@
|
||||||
// sound.cpp: basic positional sound using sdl_mixer
|
|
||||||
|
|
||||||
#include "engine.h"
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include "SDL2_mixer/SDL_mixer.h"
|
|
||||||
#else
|
|
||||||
#include "SDL_mixer.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool nosound = true;
|
|
||||||
|
|
||||||
struct soundsample
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
Mix_Chunk *chunk;
|
|
||||||
|
|
||||||
soundsample() : name(NULL), chunk(NULL) {}
|
|
||||||
~soundsample() { DELETEA(name); }
|
|
||||||
|
|
||||||
void cleanup() { if(chunk) { Mix_FreeChunk(chunk); chunk = NULL; } }
|
|
||||||
bool load(const char *dir, bool msg = false);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct soundslot
|
|
||||||
{
|
|
||||||
soundsample *sample;
|
|
||||||
int volume;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct soundconfig
|
|
||||||
{
|
|
||||||
int slots, numslots;
|
|
||||||
int maxuses;
|
|
||||||
|
|
||||||
bool hasslot(const soundslot *p, const vector<soundslot> &v) const
|
|
||||||
{
|
|
||||||
return p >= v.getbuf() + slots && p < v.getbuf() + slots+numslots && slots+numslots < v.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
int chooseslot(int flags) const
|
|
||||||
{
|
|
||||||
if(flags&SND_NO_ALT || numslots <= 1) return slots;
|
|
||||||
if(flags&SND_USE_ALT) return slots + 1 + rnd(numslots - 1);
|
|
||||||
return slots + rnd(numslots);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct soundchannel
|
|
||||||
{
|
|
||||||
int id;
|
|
||||||
bool inuse;
|
|
||||||
vec loc;
|
|
||||||
soundslot *slot;
|
|
||||||
extentity *ent;
|
|
||||||
int radius, volume, pan, flags;
|
|
||||||
bool dirty;
|
|
||||||
|
|
||||||
soundchannel(int id) : id(id) { reset(); }
|
|
||||||
|
|
||||||
bool hasloc() const { return loc.x >= -1e15f; }
|
|
||||||
void clearloc() { loc = vec(-1e16f, -1e16f, -1e16f); }
|
|
||||||
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
inuse = false;
|
|
||||||
clearloc();
|
|
||||||
slot = NULL;
|
|
||||||
ent = NULL;
|
|
||||||
radius = 0;
|
|
||||||
volume = -1;
|
|
||||||
pan = -1;
|
|
||||||
flags = 0;
|
|
||||||
dirty = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
vector<soundchannel> channels;
|
|
||||||
int maxchannels = 0;
|
|
||||||
|
|
||||||
soundchannel &newchannel(int n, soundslot *slot, const vec *loc = NULL, extentity *ent = NULL, int flags = 0, int radius = 0)
|
|
||||||
{
|
|
||||||
if(ent)
|
|
||||||
{
|
|
||||||
loc = &ent->o;
|
|
||||||
ent->flags |= EF_SOUND;
|
|
||||||
}
|
|
||||||
while(!channels.inrange(n)) channels.add(channels.length());
|
|
||||||
soundchannel &chan = channels[n];
|
|
||||||
chan.reset();
|
|
||||||
chan.inuse = true;
|
|
||||||
if(loc) chan.loc = *loc;
|
|
||||||
chan.slot = slot;
|
|
||||||
chan.ent = ent;
|
|
||||||
chan.flags = 0;
|
|
||||||
chan.radius = radius;
|
|
||||||
return chan;
|
|
||||||
}
|
|
||||||
|
|
||||||
void freechannel(int n)
|
|
||||||
{
|
|
||||||
if(!channels.inrange(n) || !channels[n].inuse) return;
|
|
||||||
soundchannel &chan = channels[n];
|
|
||||||
chan.inuse = false;
|
|
||||||
if(chan.ent) chan.ent->flags &= ~EF_SOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
void syncchannel(soundchannel &chan)
|
|
||||||
{
|
|
||||||
if(!chan.dirty) return;
|
|
||||||
if(!Mix_FadingChannel(chan.id)) Mix_Volume(chan.id, chan.volume);
|
|
||||||
Mix_SetPanning(chan.id, 255-chan.pan, chan.pan);
|
|
||||||
chan.dirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopchannels()
|
|
||||||
{
|
|
||||||
loopv(channels)
|
|
||||||
{
|
|
||||||
soundchannel &chan = channels[i];
|
|
||||||
if(!chan.inuse) continue;
|
|
||||||
Mix_HaltChannel(i);
|
|
||||||
freechannel(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setmusicvol(int musicvol);
|
|
||||||
VARFP(soundvol, 0, 255, 255, if(!soundvol) { stopchannels(); setmusicvol(0); });
|
|
||||||
VARFP(musicvol, 0, 60, 255, setmusicvol(soundvol ? musicvol : 0));
|
|
||||||
|
|
||||||
char *musicfile = NULL, *musicdonecmd = NULL;
|
|
||||||
|
|
||||||
Mix_Music *music = NULL;
|
|
||||||
SDL_RWops *musicrw = NULL;
|
|
||||||
stream *musicstream = NULL;
|
|
||||||
|
|
||||||
void setmusicvol(int musicvol)
|
|
||||||
{
|
|
||||||
if(nosound) return;
|
|
||||||
if(music) Mix_VolumeMusic((musicvol*MIX_MAX_VOLUME)/255);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopmusic()
|
|
||||||
{
|
|
||||||
if(nosound) return;
|
|
||||||
DELETEA(musicfile);
|
|
||||||
DELETEA(musicdonecmd);
|
|
||||||
if(music)
|
|
||||||
{
|
|
||||||
Mix_HaltMusic();
|
|
||||||
Mix_FreeMusic(music);
|
|
||||||
music = NULL;
|
|
||||||
}
|
|
||||||
if(musicrw) { SDL_FreeRW(musicrw); musicrw = NULL; }
|
|
||||||
DELETEP(musicstream);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define AUDIODRIVER "directsound winmm"
|
|
||||||
#else
|
|
||||||
#define AUDIODRIVER ""
|
|
||||||
#endif
|
|
||||||
bool shouldinitaudio = true;
|
|
||||||
SVARF(audiodriver, AUDIODRIVER, { shouldinitaudio = true; initwarning("sound configuration", INIT_RESET, CHANGE_SOUND); });
|
|
||||||
VARF(sound, 0, 1, 1, { shouldinitaudio = true; initwarning("sound configuration", INIT_RESET, CHANGE_SOUND); });
|
|
||||||
VARF(soundchans, 1, 32, 128, initwarning("sound configuration", INIT_RESET, CHANGE_SOUND));
|
|
||||||
VARF(soundfreq, 0, 44100, 48000, initwarning("sound configuration", INIT_RESET, CHANGE_SOUND));
|
|
||||||
VARF(soundbufferlen, 128, 1024, 4096, initwarning("sound configuration", INIT_RESET, CHANGE_SOUND));
|
|
||||||
|
|
||||||
bool initaudio()
|
|
||||||
{
|
|
||||||
static string fallback = "";
|
|
||||||
static bool initfallback = true;
|
|
||||||
if(initfallback)
|
|
||||||
{
|
|
||||||
initfallback = false;
|
|
||||||
if(char *env = SDL_getenv("SDL_AUDIODRIVER")) copystring(fallback, env);
|
|
||||||
}
|
|
||||||
if(!fallback[0] && audiodriver[0])
|
|
||||||
{
|
|
||||||
vector<char*> drivers;
|
|
||||||
explodelist(audiodriver, drivers);
|
|
||||||
loopv(drivers)
|
|
||||||
{
|
|
||||||
SDL_setenv("SDL_AUDIODRIVER", drivers[i], 1);
|
|
||||||
if(SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0)
|
|
||||||
{
|
|
||||||
drivers.deletearrays();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
drivers.deletearrays();
|
|
||||||
}
|
|
||||||
SDL_setenv("SDL_AUDIODRIVER", fallback, 1);
|
|
||||||
if(SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0) return true;
|
|
||||||
conoutf(CON_ERROR, "sound init failed: %s", SDL_GetError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initsound()
|
|
||||||
{
|
|
||||||
SDL_version version;
|
|
||||||
SDL_GetVersion(&version);
|
|
||||||
if(version.major == 2 && version.minor == 0 && version.patch == 6)
|
|
||||||
{
|
|
||||||
nosound = true;
|
|
||||||
if(sound) conoutf(CON_ERROR, "audio is broken in SDL 2.0.6");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(shouldinitaudio)
|
|
||||||
{
|
|
||||||
shouldinitaudio = false;
|
|
||||||
if(SDL_WasInit(SDL_INIT_AUDIO)) SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
|
||||||
if(!sound || !initaudio())
|
|
||||||
{
|
|
||||||
nosound = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Mix_OpenAudio(soundfreq, MIX_DEFAULT_FORMAT, 2, soundbufferlen)<0)
|
|
||||||
{
|
|
||||||
nosound = true;
|
|
||||||
conoutf(CON_ERROR, "sound init failed (SDL_mixer): %s", Mix_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Mix_AllocateChannels(soundchans);
|
|
||||||
maxchannels = soundchans;
|
|
||||||
nosound = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void musicdone()
|
|
||||||
{
|
|
||||||
if(music) { Mix_HaltMusic(); Mix_FreeMusic(music); music = NULL; }
|
|
||||||
if(musicrw) { SDL_FreeRW(musicrw); musicrw = NULL; }
|
|
||||||
DELETEP(musicstream);
|
|
||||||
DELETEA(musicfile);
|
|
||||||
if(!musicdonecmd) return;
|
|
||||||
char *cmd = musicdonecmd;
|
|
||||||
musicdonecmd = NULL;
|
|
||||||
execute(cmd);
|
|
||||||
delete[] cmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mix_Music *loadmusic(const char *name)
|
|
||||||
{
|
|
||||||
if(!musicstream) musicstream = openzipfile(name, "rb");
|
|
||||||
if(musicstream)
|
|
||||||
{
|
|
||||||
if(!musicrw) musicrw = musicstream->rwops();
|
|
||||||
if(!musicrw) DELETEP(musicstream);
|
|
||||||
}
|
|
||||||
if(musicrw) music = Mix_LoadMUSType_RW(musicrw, MUS_NONE, 0);
|
|
||||||
else music = Mix_LoadMUS(findfile(name, "rb"));
|
|
||||||
if(!music)
|
|
||||||
{
|
|
||||||
if(musicrw) { SDL_FreeRW(musicrw); musicrw = NULL; }
|
|
||||||
DELETEP(musicstream);
|
|
||||||
}
|
|
||||||
return music;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startmusic(char *name, char *cmd)
|
|
||||||
{
|
|
||||||
if(nosound) return;
|
|
||||||
stopmusic();
|
|
||||||
if(soundvol && musicvol && *name)
|
|
||||||
{
|
|
||||||
defformatstring(file, "media/%s", name);
|
|
||||||
path(file);
|
|
||||||
if(loadmusic(file))
|
|
||||||
{
|
|
||||||
DELETEA(musicfile);
|
|
||||||
DELETEA(musicdonecmd);
|
|
||||||
musicfile = newstring(file);
|
|
||||||
if(cmd[0]) musicdonecmd = newstring(cmd);
|
|
||||||
Mix_PlayMusic(music, cmd[0] ? 0 : -1);
|
|
||||||
Mix_VolumeMusic((musicvol*MIX_MAX_VOLUME)/255);
|
|
||||||
intret(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
conoutf(CON_ERROR, "could not play music: %s", file);
|
|
||||||
intret(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMANDN(music, startmusic, "ss");
|
|
||||||
|
|
||||||
static Mix_Chunk *loadwav(const char *name)
|
|
||||||
{
|
|
||||||
Mix_Chunk *c = NULL;
|
|
||||||
stream *z = openzipfile(name, "rb");
|
|
||||||
if(z)
|
|
||||||
{
|
|
||||||
SDL_RWops *rw = z->rwops();
|
|
||||||
if(rw)
|
|
||||||
{
|
|
||||||
c = Mix_LoadWAV_RW(rw, 0);
|
|
||||||
SDL_FreeRW(rw);
|
|
||||||
}
|
|
||||||
delete z;
|
|
||||||
}
|
|
||||||
if(!c) c = Mix_LoadWAV(findfile(name, "rb"));
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool soundsample::load(const char *dir, bool msg)
|
|
||||||
{
|
|
||||||
if(chunk) return true;
|
|
||||||
if(!name[0]) return false;
|
|
||||||
|
|
||||||
static const char * const exts[] = { "", ".wav", ".ogg" };
|
|
||||||
string filename;
|
|
||||||
loopi(sizeof(exts)/sizeof(exts[0]))
|
|
||||||
{
|
|
||||||
formatstring(filename, "media/sound/%s%s%s", dir, name, exts[i]);
|
|
||||||
if(msg && !i) renderprogress(0, filename);
|
|
||||||
path(filename);
|
|
||||||
chunk = loadwav(filename);
|
|
||||||
if(chunk) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
conoutf(CON_ERROR, "failed to load sample: media/sound/%s%s", dir, name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct soundtype
|
|
||||||
{
|
|
||||||
hashnameset<soundsample> samples;
|
|
||||||
vector<soundslot> slots;
|
|
||||||
vector<soundconfig> configs;
|
|
||||||
const char *dir;
|
|
||||||
|
|
||||||
soundtype(const char *dir) : dir(dir) {}
|
|
||||||
|
|
||||||
int findsound(const char *name, int vol)
|
|
||||||
{
|
|
||||||
loopv(configs)
|
|
||||||
{
|
|
||||||
soundconfig &s = configs[i];
|
|
||||||
loopj(s.numslots)
|
|
||||||
{
|
|
||||||
soundslot &c = slots[s.slots+j];
|
|
||||||
if(!strcmp(c.sample->name, name) && (!vol || c.volume==vol)) return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int addslot(const char *name, int vol)
|
|
||||||
{
|
|
||||||
soundsample *s = samples.access(name);
|
|
||||||
if(!s)
|
|
||||||
{
|
|
||||||
char *n = newstring(name);
|
|
||||||
s = &samples[n];
|
|
||||||
s->name = n;
|
|
||||||
s->chunk = NULL;
|
|
||||||
}
|
|
||||||
soundslot *oldslots = slots.getbuf();
|
|
||||||
int oldlen = slots.length();
|
|
||||||
soundslot &slot = slots.add();
|
|
||||||
// soundslots.add() may relocate slot pointers
|
|
||||||
if(slots.getbuf() != oldslots) loopv(channels)
|
|
||||||
{
|
|
||||||
soundchannel &chan = channels[i];
|
|
||||||
if(chan.inuse && chan.slot >= oldslots && chan.slot < &oldslots[oldlen])
|
|
||||||
chan.slot = &slots[chan.slot - oldslots];
|
|
||||||
}
|
|
||||||
slot.sample = s;
|
|
||||||
slot.volume = vol ? vol : 100;
|
|
||||||
return oldlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
int addsound(const char *name, int vol, int maxuses = 0)
|
|
||||||
{
|
|
||||||
soundconfig &s = configs.add();
|
|
||||||
s.slots = addslot(name, vol);
|
|
||||||
s.numslots = 1;
|
|
||||||
s.maxuses = maxuses;
|
|
||||||
return configs.length()-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addalt(const char *name, int vol)
|
|
||||||
{
|
|
||||||
if(configs.empty()) return;
|
|
||||||
addslot(name, vol);
|
|
||||||
configs.last().numslots++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
slots.setsize(0);
|
|
||||||
configs.setsize(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
loopv(channels)
|
|
||||||
{
|
|
||||||
soundchannel &chan = channels[i];
|
|
||||||
if(chan.inuse && slots.inbuf(chan.slot))
|
|
||||||
{
|
|
||||||
Mix_HaltChannel(i);
|
|
||||||
freechannel(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void cleanupsamples()
|
|
||||||
{
|
|
||||||
enumerate(samples, soundsample, s, s.cleanup());
|
|
||||||
}
|
|
||||||
|
|
||||||
void cleanup()
|
|
||||||
{
|
|
||||||
cleanupsamples();
|
|
||||||
slots.setsize(0);
|
|
||||||
configs.setsize(0);
|
|
||||||
samples.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void preloadsound(int n)
|
|
||||||
{
|
|
||||||
if(nosound || !configs.inrange(n)) return;
|
|
||||||
soundconfig &config = configs[n];
|
|
||||||
loopk(config.numslots) slots[config.slots+k].sample->load(dir, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool playing(const soundchannel &chan, const soundconfig &config) const
|
|
||||||
{
|
|
||||||
return chan.inuse && config.hasslot(chan.slot, slots);
|
|
||||||
}
|
|
||||||
} gamesounds("game/"), mapsounds("mapsound/");
|
|
||||||
|
|
||||||
void registersound(char *name, int *vol) { intret(gamesounds.addsound(name, *vol, 0)); }
|
|
||||||
COMMAND(registersound, "si");
|
|
||||||
|
|
||||||
void mapsound(char *name, int *vol, int *maxuses) { intret(mapsounds.addsound(name, *vol, *maxuses < 0 ? 0 : max(1, *maxuses))); }
|
|
||||||
COMMAND(mapsound, "sii");
|
|
||||||
|
|
||||||
void altsound(char *name, int *vol) { gamesounds.addalt(name, *vol); }
|
|
||||||
COMMAND(altsound, "si");
|
|
||||||
|
|
||||||
void altmapsound(char *name, int *vol) { mapsounds.addalt(name, *vol); }
|
|
||||||
COMMAND(altmapsound, "si");
|
|
||||||
|
|
||||||
ICOMMAND(numsounds, "", (), intret(gamesounds.configs.length()));
|
|
||||||
ICOMMAND(nummapsounds, "", (), intret(mapsounds.configs.length()));
|
|
||||||
|
|
||||||
void soundreset()
|
|
||||||
{
|
|
||||||
gamesounds.reset();
|
|
||||||
}
|
|
||||||
COMMAND(soundreset, "");
|
|
||||||
|
|
||||||
void mapsoundreset()
|
|
||||||
{
|
|
||||||
mapsounds.reset();
|
|
||||||
}
|
|
||||||
COMMAND(mapsoundreset, "");
|
|
||||||
|
|
||||||
void resetchannels()
|
|
||||||
{
|
|
||||||
loopv(channels) if(channels[i].inuse) freechannel(i);
|
|
||||||
channels.shrink(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear_sound()
|
|
||||||
{
|
|
||||||
closemumble();
|
|
||||||
if(nosound) return;
|
|
||||||
stopmusic();
|
|
||||||
|
|
||||||
gamesounds.cleanup();
|
|
||||||
mapsounds.cleanup();
|
|
||||||
Mix_CloseAudio();
|
|
||||||
resetchannels();
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopmapsounds()
|
|
||||||
{
|
|
||||||
loopv(channels) if(channels[i].inuse && channels[i].ent)
|
|
||||||
{
|
|
||||||
Mix_HaltChannel(i);
|
|
||||||
freechannel(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearmapsounds()
|
|
||||||
{
|
|
||||||
stopmapsounds();
|
|
||||||
mapsounds.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopmapsound(extentity *e)
|
|
||||||
{
|
|
||||||
loopv(channels)
|
|
||||||
{
|
|
||||||
soundchannel &chan = channels[i];
|
|
||||||
if(chan.inuse && chan.ent == e)
|
|
||||||
{
|
|
||||||
Mix_HaltChannel(i);
|
|
||||||
freechannel(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkmapsounds()
|
|
||||||
{
|
|
||||||
const vector<extentity *> &ents = entities::getents();
|
|
||||||
loopv(ents)
|
|
||||||
{
|
|
||||||
extentity &e = *ents[i];
|
|
||||||
if(e.type!=ET_SOUND) continue;
|
|
||||||
if(camera1->o.dist(e.o) < e.attr2)
|
|
||||||
{
|
|
||||||
if(!(e.flags&EF_SOUND)) playsound(e.attr1, NULL, &e, SND_MAP, -1);
|
|
||||||
}
|
|
||||||
else if(e.flags&EF_SOUND) stopmapsound(&e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VAR(stereo, 0, 1, 1);
|
|
||||||
|
|
||||||
VAR(maxsoundradius, 1, 340, 0);
|
|
||||||
|
|
||||||
bool updatechannel(soundchannel &chan)
|
|
||||||
{
|
|
||||||
if(!chan.slot) return false;
|
|
||||||
int vol = soundvol, pan = 255/2;
|
|
||||||
if(chan.hasloc())
|
|
||||||
{
|
|
||||||
vec v;
|
|
||||||
float dist = chan.loc.dist(camera1->o, v);
|
|
||||||
int rad = maxsoundradius;
|
|
||||||
if(chan.ent)
|
|
||||||
{
|
|
||||||
rad = chan.ent->attr2;
|
|
||||||
if(chan.ent->attr3)
|
|
||||||
{
|
|
||||||
rad -= chan.ent->attr3;
|
|
||||||
dist -= chan.ent->attr3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(chan.radius > 0) rad = maxsoundradius ? min(maxsoundradius, chan.radius) : chan.radius;
|
|
||||||
if(rad > 0) vol -= int(clamp(dist/rad, 0.0f, 1.0f)*soundvol); // simple mono distance attenuation
|
|
||||||
if(stereo && (v.x != 0 || v.y != 0) && dist>0)
|
|
||||||
{
|
|
||||||
v.rotate_around_z(-camera1->yaw*RAD);
|
|
||||||
pan = int(255.9f*(0.5f - 0.5f*v.x/v.magnitude2())); // range is from 0 (left) to 255 (right)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vol = (vol*MIX_MAX_VOLUME*chan.slot->volume)/255/255;
|
|
||||||
vol = min(vol, MIX_MAX_VOLUME);
|
|
||||||
if(vol == chan.volume && pan == chan.pan) return false;
|
|
||||||
chan.volume = vol;
|
|
||||||
chan.pan = pan;
|
|
||||||
chan.dirty = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reclaimchannels()
|
|
||||||
{
|
|
||||||
loopv(channels)
|
|
||||||
{
|
|
||||||
soundchannel &chan = channels[i];
|
|
||||||
if(chan.inuse && !Mix_Playing(i)) freechannel(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void syncchannels()
|
|
||||||
{
|
|
||||||
loopv(channels)
|
|
||||||
{
|
|
||||||
soundchannel &chan = channels[i];
|
|
||||||
if(chan.inuse && chan.hasloc() && updatechannel(chan)) syncchannel(chan);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VARP(minimizedsounds, 0, 0, 1);
|
|
||||||
|
|
||||||
void updatesounds()
|
|
||||||
{
|
|
||||||
updatemumble();
|
|
||||||
if(nosound) return;
|
|
||||||
if(minimized && !minimizedsounds) stopsounds();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reclaimchannels();
|
|
||||||
if(mainmenu) stopmapsounds();
|
|
||||||
else checkmapsounds();
|
|
||||||
syncchannels();
|
|
||||||
}
|
|
||||||
if(music)
|
|
||||||
{
|
|
||||||
if(!Mix_PlayingMusic()) musicdone();
|
|
||||||
else if(Mix_PausedMusic()) Mix_ResumeMusic();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VARP(maxsoundsatonce, 0, 7, 100);
|
|
||||||
|
|
||||||
VAR(dbgsound, 0, 0, 1);
|
|
||||||
|
|
||||||
void preloadsound(int n)
|
|
||||||
{
|
|
||||||
gamesounds.preloadsound(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void preloadmapsound(int n)
|
|
||||||
{
|
|
||||||
mapsounds.preloadsound(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void preloadmapsounds()
|
|
||||||
{
|
|
||||||
const vector<extentity *> &ents = entities::getents();
|
|
||||||
loopv(ents)
|
|
||||||
{
|
|
||||||
extentity &e = *ents[i];
|
|
||||||
if(e.type==ET_SOUND) mapsounds.preloadsound(e.attr1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int playsound(int n, const vec *loc, extentity *ent, int flags, int loops, int fade, int chanid, int radius, int expire)
|
|
||||||
{
|
|
||||||
if(nosound || !soundvol || (minimized && !minimizedsounds)) return -1;
|
|
||||||
|
|
||||||
soundtype &sounds = ent || flags&SND_MAP ? mapsounds : gamesounds;
|
|
||||||
if(!sounds.configs.inrange(n)) { conoutf(CON_WARN, "unregistered sound: %d", n); return -1; }
|
|
||||||
soundconfig &config = sounds.configs[n];
|
|
||||||
|
|
||||||
if(loc && (maxsoundradius || radius > 0))
|
|
||||||
{
|
|
||||||
// cull sounds that are unlikely to be heard
|
|
||||||
int rad = radius > 0 ? (maxsoundradius ? min(maxsoundradius, radius) : radius) : maxsoundradius;
|
|
||||||
if(camera1->o.dist(*loc) > 1.5f*rad)
|
|
||||||
{
|
|
||||||
if(channels.inrange(chanid) && sounds.playing(channels[chanid], config))
|
|
||||||
{
|
|
||||||
Mix_HaltChannel(chanid);
|
|
||||||
freechannel(chanid);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(chanid < 0)
|
|
||||||
{
|
|
||||||
if(config.maxuses)
|
|
||||||
{
|
|
||||||
int uses = 0;
|
|
||||||
loopv(channels) if(sounds.playing(channels[i], config) && ++uses >= config.maxuses) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// avoid bursts of sounds with heavy packetloss and in sp
|
|
||||||
static int soundsatonce = 0, lastsoundmillis = 0;
|
|
||||||
if(totalmillis == lastsoundmillis) soundsatonce++; else soundsatonce = 1;
|
|
||||||
lastsoundmillis = totalmillis;
|
|
||||||
if(maxsoundsatonce && soundsatonce > maxsoundsatonce) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(channels.inrange(chanid))
|
|
||||||
{
|
|
||||||
soundchannel &chan = channels[chanid];
|
|
||||||
if(sounds.playing(chan, config))
|
|
||||||
{
|
|
||||||
if(loc) chan.loc = *loc;
|
|
||||||
else if(chan.hasloc()) chan.clearloc();
|
|
||||||
return chanid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(fade < 0) return -1;
|
|
||||||
|
|
||||||
soundslot &slot = sounds.slots[config.chooseslot(flags)];
|
|
||||||
if(!slot.sample->chunk && !slot.sample->load(sounds.dir)) return -1;
|
|
||||||
|
|
||||||
if(dbgsound) conoutf("sound: %s%s", sounds.dir, slot.sample->name);
|
|
||||||
|
|
||||||
chanid = -1;
|
|
||||||
loopv(channels) if(!channels[i].inuse) { chanid = i; break; }
|
|
||||||
if(chanid < 0 && channels.length() < maxchannels) chanid = channels.length();
|
|
||||||
if(chanid < 0) loopv(channels) if(!channels[i].volume) { Mix_HaltChannel(i); freechannel(i); chanid = i; break; }
|
|
||||||
if(chanid < 0) return -1;
|
|
||||||
|
|
||||||
soundchannel &chan = newchannel(chanid, &slot, loc, ent, flags, radius);
|
|
||||||
updatechannel(chan);
|
|
||||||
int playing = -1;
|
|
||||||
if(fade)
|
|
||||||
{
|
|
||||||
Mix_Volume(chanid, chan.volume);
|
|
||||||
playing = expire >= 0 ? Mix_FadeInChannelTimed(chanid, slot.sample->chunk, loops, fade, expire) : Mix_FadeInChannel(chanid, slot.sample->chunk, loops, fade);
|
|
||||||
}
|
|
||||||
else playing = expire >= 0 ? Mix_PlayChannelTimed(chanid, slot.sample->chunk, loops, expire) : Mix_PlayChannel(chanid, slot.sample->chunk, loops);
|
|
||||||
if(playing >= 0) syncchannel(chan);
|
|
||||||
else freechannel(chanid);
|
|
||||||
return playing;
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopsounds()
|
|
||||||
{
|
|
||||||
loopv(channels) if(channels[i].inuse)
|
|
||||||
{
|
|
||||||
Mix_HaltChannel(i);
|
|
||||||
freechannel(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool stopsound(int n, int chanid, int fade)
|
|
||||||
{
|
|
||||||
if(!gamesounds.configs.inrange(n) || !channels.inrange(chanid) || !gamesounds.playing(channels[chanid], gamesounds.configs[n])) return false;
|
|
||||||
if(dbgsound) conoutf("stopsound: %s%s", gamesounds.dir, channels[chanid].slot->sample->name);
|
|
||||||
if(!fade || !Mix_FadeOutChannel(chanid, fade))
|
|
||||||
{
|
|
||||||
Mix_HaltChannel(chanid);
|
|
||||||
freechannel(chanid);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int playsoundname(const char *s, const vec *loc, int vol, int flags, int loops, int fade, int chanid, int radius, int expire)
|
|
||||||
{
|
|
||||||
if(!vol) vol = 100;
|
|
||||||
int id = gamesounds.findsound(s, vol);
|
|
||||||
if(id < 0) id = gamesounds.addsound(s, vol);
|
|
||||||
return playsound(id, loc, NULL, flags, loops, fade, chanid, radius, expire);
|
|
||||||
}
|
|
||||||
|
|
||||||
ICOMMAND(playsound, "i", (int *n), playsound(*n));
|
|
||||||
|
|
||||||
void resetsound()
|
|
||||||
{
|
|
||||||
clearchanges(CHANGE_SOUND);
|
|
||||||
if(!nosound)
|
|
||||||
{
|
|
||||||
gamesounds.cleanupsamples();
|
|
||||||
mapsounds.cleanupsamples();
|
|
||||||
if(music)
|
|
||||||
{
|
|
||||||
Mix_HaltMusic();
|
|
||||||
Mix_FreeMusic(music);
|
|
||||||
}
|
|
||||||
if(musicstream) musicstream->seek(0, SEEK_SET);
|
|
||||||
Mix_CloseAudio();
|
|
||||||
}
|
|
||||||
initsound();
|
|
||||||
resetchannels();
|
|
||||||
if(nosound)
|
|
||||||
{
|
|
||||||
DELETEA(musicfile);
|
|
||||||
DELETEA(musicdonecmd);
|
|
||||||
music = NULL;
|
|
||||||
gamesounds.cleanupsamples();
|
|
||||||
mapsounds.cleanupsamples();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(music && loadmusic(musicfile))
|
|
||||||
{
|
|
||||||
Mix_PlayMusic(music, musicdonecmd ? 0 : -1);
|
|
||||||
Mix_VolumeMusic((musicvol*MIX_MAX_VOLUME)/255);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DELETEA(musicfile);
|
|
||||||
DELETEA(musicdonecmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
COMMAND(resetsound, "");
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
|
|
||||||
#include <wchar.h>
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifdef _POSIX_SHARED_MEMORY_OBJECTS
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <wchar.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(WIN32) || defined(_POSIX_SHARED_MEMORY_OBJECTS)
|
|
||||||
struct MumbleInfo
|
|
||||||
{
|
|
||||||
int version, timestamp;
|
|
||||||
vec pos, front, top;
|
|
||||||
wchar_t name[256];
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
static HANDLE mumblelink = NULL;
|
|
||||||
static MumbleInfo *mumbleinfo = NULL;
|
|
||||||
#define VALID_MUMBLELINK (mumblelink && mumbleinfo)
|
|
||||||
#elif defined(_POSIX_SHARED_MEMORY_OBJECTS)
|
|
||||||
static int mumblelink = -1;
|
|
||||||
static MumbleInfo *mumbleinfo = (MumbleInfo *)-1;
|
|
||||||
#define VALID_MUMBLELINK (mumblelink >= 0 && mumbleinfo != (MumbleInfo *)-1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VALID_MUMBLELINK
|
|
||||||
VARFP(mumble, 0, 1, 1, { if(mumble) initmumble(); else closemumble(); });
|
|
||||||
#else
|
|
||||||
VARFP(mumble, 0, 0, 1, { if(mumble) initmumble(); else closemumble(); });
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void initmumble()
|
|
||||||
{
|
|
||||||
if(!mumble) return;
|
|
||||||
#ifdef VALID_MUMBLELINK
|
|
||||||
if(VALID_MUMBLELINK) return;
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
mumblelink = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "MumbleLink");
|
|
||||||
if(mumblelink)
|
|
||||||
{
|
|
||||||
mumbleinfo = (MumbleInfo *)MapViewOfFile(mumblelink, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(MumbleInfo));
|
|
||||||
if(mumbleinfo) wcsncpy(mumbleinfo->name, L"Tesseract", 256);
|
|
||||||
}
|
|
||||||
#elif defined(_POSIX_SHARED_MEMORY_OBJECTS)
|
|
||||||
defformatstring(shmname, "/MumbleLink.%d", getuid());
|
|
||||||
mumblelink = shm_open(shmname, O_RDWR, 0);
|
|
||||||
if(mumblelink >= 0)
|
|
||||||
{
|
|
||||||
mumbleinfo = (MumbleInfo *)mmap(NULL, sizeof(MumbleInfo), PROT_READ|PROT_WRITE, MAP_SHARED, mumblelink, 0);
|
|
||||||
if(mumbleinfo != (MumbleInfo *)-1) wcsncpy(mumbleinfo->name, L"Tesseract", 256);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(!VALID_MUMBLELINK) closemumble();
|
|
||||||
#else
|
|
||||||
conoutf(CON_ERROR, "Mumble positional audio is not available on this platform.");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void closemumble()
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
if(mumbleinfo) { UnmapViewOfFile(mumbleinfo); mumbleinfo = NULL; }
|
|
||||||
if(mumblelink) { CloseHandle(mumblelink); mumblelink = NULL; }
|
|
||||||
#elif defined(_POSIX_SHARED_MEMORY_OBJECTS)
|
|
||||||
if(mumbleinfo != (MumbleInfo *)-1) { munmap(mumbleinfo, sizeof(MumbleInfo)); mumbleinfo = (MumbleInfo *)-1; }
|
|
||||||
if(mumblelink >= 0) { close(mumblelink); mumblelink = -1; }
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline vec mumblevec(const vec &v, bool pos = false)
|
|
||||||
{
|
|
||||||
// change from X left, Z up, Y forward to X right, Y up, Z forward
|
|
||||||
// 8 cube units = 1 meter
|
|
||||||
vec m(-v.x, v.z, v.y);
|
|
||||||
if(pos) m.div(8);
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updatemumble()
|
|
||||||
{
|
|
||||||
#ifdef VALID_MUMBLELINK
|
|
||||||
if(!VALID_MUMBLELINK) return;
|
|
||||||
|
|
||||||
static int timestamp = 0;
|
|
||||||
|
|
||||||
mumbleinfo->version = 1;
|
|
||||||
mumbleinfo->timestamp = ++timestamp;
|
|
||||||
|
|
||||||
mumbleinfo->pos = mumblevec(player->o, true);
|
|
||||||
mumbleinfo->front = mumblevec(vec(player->yaw*RAD, player->pitch*RAD));
|
|
||||||
mumbleinfo->top = mumblevec(vec(player->yaw*RAD, (player->pitch+90)*RAD));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1374,7 +1374,7 @@ void splitocta(cube *c, int size)
|
||||||
void resetmap()
|
void resetmap()
|
||||||
{
|
{
|
||||||
clearoverrides();
|
clearoverrides();
|
||||||
clearmapsounds();
|
//clearmapsounds();
|
||||||
resetblendmap();
|
resetblendmap();
|
||||||
clearlights();
|
clearlights();
|
||||||
clearpvs();
|
clearpvs();
|
||||||
|
|
|
@ -891,7 +891,7 @@ bool load_world(const char *mname, const char *cname) // still supports a
|
||||||
game::preload();
|
game::preload();
|
||||||
flushpreloadedmodels();
|
flushpreloadedmodels();
|
||||||
|
|
||||||
preloadmapsounds();
|
//preloadmapsounds();
|
||||||
|
|
||||||
entitiesinoctanodes();
|
entitiesinoctanodes();
|
||||||
attachentities();
|
attachentities();
|
||||||
|
|
|
@ -341,7 +341,7 @@ struct ctfclientmode : clientmode
|
||||||
{
|
{
|
||||||
preloadmodel("game/flag/rojo");
|
preloadmodel("game/flag/rojo");
|
||||||
preloadmodel("game/flag/azul");
|
preloadmodel("game/flag/azul");
|
||||||
for(int i = S_FLAGPICKUP; i <= S_FLAGFAIL; i++) preloadsound(i);
|
//for(int i = S_FLAGPICKUP; i <= S_FLAGFAIL; i++) preloadsound(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawblip(gameent *d, float x, float y, float s, const vec &pos, bool flagblip)
|
void drawblip(gameent *d, float x, float y, float s, const vec &pos, bool flagblip)
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace entities
|
||||||
case TELEPORT:
|
case TELEPORT:
|
||||||
if(e.attr2 > 0) preloadmodel(mapmodelname(e.attr2));
|
if(e.attr2 > 0) preloadmodel(mapmodelname(e.attr2));
|
||||||
case JUMPPAD:
|
case JUMPPAD:
|
||||||
if(e.attr4 > 0) preloadmapsound(e.attr4);
|
//if(e.attr4 > 0) preloadmapsound(e.attr4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ namespace entities
|
||||||
itemstat &is = itemstats[type-I_FIRST];
|
itemstat &is = itemstats[type-I_FIRST];
|
||||||
v += is.add;
|
v += is.add;
|
||||||
if(v>is.max) v = is.max;
|
if(v>is.max) v = is.max;
|
||||||
if(local) msgsound(is.sound);
|
//if(local) msgsound(is.sound);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -520,7 +520,7 @@ namespace game
|
||||||
|
|
||||||
void preloadsounds()
|
void preloadsounds()
|
||||||
{
|
{
|
||||||
for(int i = S_JUMP; i <= S_DIE2; i++) preloadsound(i);
|
//for(int i = S_JUMP; i <= S_DIE2; i++) preloadsound(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void preload()
|
void preload()
|
||||||
|
|
|
@ -410,13 +410,12 @@ enum
|
||||||
SND_USE_ALT = 1<<2
|
SND_USE_ALT = 1<<2
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int playsound(int n, const vec *loc = NULL, extentity *ent = NULL, int flags = 0, int loops = 0, int fade = 0, int chanid = -1, int radius = 0, int expire = -1);
|
inline int playsound(
|
||||||
extern int playsoundname(const char *s, const vec *loc = NULL, int vol = 0, int flags = 0, int loops = 0, int fade = 0, int chanid = -1, int radius = 0, int expire = -1);
|
int, const vec * = NULL, extentity * = NULL, int = 0, int = 0, int = 0,
|
||||||
extern void preloadsound(int n);
|
int = -1, int = 0, int = -1
|
||||||
extern void preloadmapsound(int n);
|
) {
|
||||||
extern bool stopsound(int n, int chanid, int fade = 0);
|
return -1;
|
||||||
extern void stopsounds();
|
}
|
||||||
extern void initsound();
|
|
||||||
|
|
||||||
// rendermodel
|
// rendermodel
|
||||||
enum { MDL_CULL_VFC = 1<<0, MDL_CULL_DIST = 1<<1, MDL_CULL_OCCLUDED = 1<<2, MDL_CULL_QUERY = 1<<3, MDL_FULLBRIGHT = 1<<4, MDL_NORENDER = 1<<5, MDL_MAPMODEL = 1<<6, MDL_NOBATCH = 1<<7, MDL_ONLYSHADOW = 1<<8, MDL_NOSHADOW = 1<<9, MDL_FORCESHADOW = 1<<10, MDL_FORCETRANSPARENT = 1<<11 };
|
enum { MDL_CULL_VFC = 1<<0, MDL_CULL_DIST = 1<<1, MDL_CULL_OCCLUDED = 1<<2, MDL_CULL_QUERY = 1<<3, MDL_FULLBRIGHT = 1<<4, MDL_NORENDER = 1<<5, MDL_MAPMODEL = 1<<6, MDL_NOBATCH = 1<<7, MDL_ONLYSHADOW = 1<<8, MDL_NOSHADOW = 1<<9, MDL_FORCESHADOW = 1<<10, MDL_FORCETRANSPARENT = 1<<11 };
|
||||||
|
|
Loading…
Reference in New Issue