mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-27 04:00:42 +00:00
- update of music code, in particular separating the engine-specific lookup from the backend.
# Conflicts: # source/core/music/music.cpp # Conflicts: # source/build/src/palette.cpp
This commit is contained in:
parent
d0406e27b6
commit
6a8efb7520
32 changed files with 891 additions and 347 deletions
|
@ -698,6 +698,7 @@ set (PCH_SOURCES
|
||||||
core/quotes.cpp
|
core/quotes.cpp
|
||||||
core/screenshot.cpp
|
core/screenshot.cpp
|
||||||
core/serializer.cpp
|
core/serializer.cpp
|
||||||
|
core/raze_music.cpp
|
||||||
|
|
||||||
core/2d/v_2ddrawer.cpp
|
core/2d/v_2ddrawer.cpp
|
||||||
core/2d/v_draw.cpp
|
core/2d/v_draw.cpp
|
||||||
|
|
|
@ -48,7 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "nnexts.h"
|
#include "nnexts.h"
|
||||||
#include "savegamehelp.h"
|
#include "savegamehelp.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "mapinfo.h"
|
#include "mapinfo.h"
|
||||||
|
|
||||||
#include "aibat.h"
|
#include "aibat.h"
|
||||||
|
|
|
@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "baselayer.h"
|
#include "baselayer.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "sfx.h"
|
#include "sfx.h"
|
||||||
#include "sound/s_soundinternal.h"
|
#include "sound/s_soundinternal.h"
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "c_console.h"
|
#include "c_console.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
#include "i_specialpaths.h"
|
#include "i_specialpaths.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "statistics.h"
|
#include "statistics.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
|
@ -96,6 +96,8 @@ void InitFileSystem(TArray<GrpEntry>&);
|
||||||
void I_SetWindowTitle(const char* caption);
|
void I_SetWindowTitle(const char* caption);
|
||||||
void InitENet();
|
void InitENet();
|
||||||
void ShutdownENet();
|
void ShutdownENet();
|
||||||
|
void S_ParseSndInfo();
|
||||||
|
|
||||||
bool AppActive;
|
bool AppActive;
|
||||||
int chatmodeon; // needed by the common console code.
|
int chatmodeon; // needed by the common console code.
|
||||||
|
|
||||||
|
@ -273,9 +275,7 @@ void UserConfig::ProcessOptions()
|
||||||
AddArt.reset(Args->GatherFiles("-art"));
|
AddArt.reset(Args->GatherFiles("-art"));
|
||||||
|
|
||||||
nologo = Args->CheckParm("-nologo") || Args->CheckParm("-quick");
|
nologo = Args->CheckParm("-nologo") || Args->CheckParm("-quick");
|
||||||
nomusic = Args->CheckParm("-nomusic");
|
nosound = Args->CheckParm("-nosfx") || Args->CheckParm("-nosound");
|
||||||
nosound = Args->CheckParm("-nosfx");
|
|
||||||
if (Args->CheckParm("-nosound")) nomusic = nosound = true;
|
|
||||||
if (Args->CheckParm("-setup")) queryiwad = 1;
|
if (Args->CheckParm("-setup")) queryiwad = 1;
|
||||||
else if (Args->CheckParm("-nosetup")) queryiwad = 0;
|
else if (Args->CheckParm("-nosetup")) queryiwad = 0;
|
||||||
|
|
||||||
|
@ -714,7 +714,10 @@ int RunGame()
|
||||||
V_InitFonts();
|
V_InitFonts();
|
||||||
C_CON_SetAliases();
|
C_CON_SetAliases();
|
||||||
sfx_empty = fileSystem.FindFile("engine/dsempty.lmp"); // this must be done outside the sound code because it's initialized late.
|
sfx_empty = fileSystem.FindFile("engine/dsempty.lmp"); // this must be done outside the sound code because it's initialized late.
|
||||||
Mus_Init();
|
I_InitSound();
|
||||||
|
Mus_InitMusic();
|
||||||
|
timerSetCallback(Mus_UpdateMusic);
|
||||||
|
S_ParseSndInfo();
|
||||||
InitStatistics();
|
InitStatistics();
|
||||||
M_Init();
|
M_Init();
|
||||||
SetDefaultStrings();
|
SetDefaultStrings();
|
||||||
|
|
|
@ -63,7 +63,7 @@ struct UserConfig
|
||||||
|
|
||||||
bool nomonsters = false;
|
bool nomonsters = false;
|
||||||
bool nosound = false;
|
bool nosound = false;
|
||||||
bool nomusic = false;
|
//bool nomusic = false;
|
||||||
bool nologo = false;
|
bool nologo = false;
|
||||||
int setupstate = -1;
|
int setupstate = -1;
|
||||||
|
|
||||||
|
@ -77,9 +77,10 @@ struct UserConfig
|
||||||
|
|
||||||
extern UserConfig userConfig;
|
extern UserConfig userConfig;
|
||||||
|
|
||||||
|
extern int nomusic;
|
||||||
inline bool MusicEnabled()
|
inline bool MusicEnabled()
|
||||||
{
|
{
|
||||||
return !userConfig.nomusic;
|
return !nomusic;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool SoundEnabled()
|
inline bool SoundEnabled()
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "rts.h"
|
#include "rts.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
#include "quotemgr.h"
|
#include "quotemgr.h"
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
|
#include <zmusic.h>
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
|
@ -48,69 +49,28 @@
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "c_console.h"
|
#include "c_console.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
|
#include "i_sound.h"
|
||||||
#include "i_soundfont.h"
|
#include "i_soundfont.h"
|
||||||
#include "s_music.h"
|
#include "s_music.h"
|
||||||
#include "printf.h"
|
#include "filereadermusicinterface.h"
|
||||||
#include "timer.h"
|
|
||||||
#include "backend/i_sound.h"
|
|
||||||
#include <zmusic.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void I_InitSoundFonts();
|
void I_InitSoundFonts();
|
||||||
void S_SetStreamVolume(float);
|
|
||||||
void S_ParseSndInfo();
|
|
||||||
|
|
||||||
EXTERN_CVAR (Int, snd_samplerate)
|
EXTERN_CVAR (Int, snd_samplerate)
|
||||||
EXTERN_CVAR (Int, snd_mididevice)
|
EXTERN_CVAR (Int, snd_mididevice)
|
||||||
EXTERN_CVAR(Float, snd_mastervolume)
|
EXTERN_CVAR(Float, snd_mastervolume)
|
||||||
|
int nomusic = 0;
|
||||||
float relative_volume = 1.f, saved_relative_volume = 1.f;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// CVAR: cd_drive
|
// CVAR snd_musicvolume
|
||||||
//
|
|
||||||
// Which drive (letter) to use for CD audio. If not a valid drive letter,
|
|
||||||
// let the operating system decide for us.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
EXTERN_CVAR(Bool, cd_enabled);
|
|
||||||
|
|
||||||
CUSTOM_CVAR(String, cd_drive, "", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG)
|
|
||||||
{
|
|
||||||
if (cd_enabled && !Args->CheckParm("-nocdaudio")) CD_Enable(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// CVAR: cd_enabled
|
|
||||||
//
|
|
||||||
// Use the CD device? Can be overridden with -nocdaudio on the command line
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
CUSTOM_CVAR(Bool, cd_enabled, true, CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG)
|
|
||||||
{
|
|
||||||
if (self && !Args->CheckParm("-nocdaudio"))
|
|
||||||
CD_Enable(cd_drive);
|
|
||||||
else
|
|
||||||
CD_Enable(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// CVAR mus_volume
|
|
||||||
//
|
//
|
||||||
// Maximum volume of MOD/stream music.
|
// Maximum volume of MOD/stream music.
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
CUSTOM_CVARD(Float, mus_volume, 0.5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls music volume")
|
CUSTOM_CVARD(Float, snd_musicvolume, 0.5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls music volume")
|
||||||
{
|
{
|
||||||
if (self < 0.f)
|
if (self < 0.f)
|
||||||
self = 0.f;
|
self = 0.f;
|
||||||
|
@ -202,20 +162,68 @@ static void mus_sfclose(void* handle)
|
||||||
reinterpret_cast<FSoundFontReader*>(handle)->close();
|
reinterpret_cast<FSoundFontReader*>(handle)->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef ZMUSIC_LITE
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
// Pass some basic working data to the music backend
|
||||||
|
// We do this once at startup for everything available.
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void Mus_Init(void)
|
static void SetupGenMidi()
|
||||||
{
|
{
|
||||||
I_InitSound();
|
// The OPL renderer should not care about where this comes from.
|
||||||
I_InitSoundFonts();
|
// Note: No I_Error here - this needs to be consistent with the rest of the music code.
|
||||||
S_ParseSndInfo();
|
auto lump = fileSystem.CheckNumForName("GENMIDI", ns_global);
|
||||||
|
if (lump < 0)
|
||||||
|
{
|
||||||
|
Printf("No GENMIDI lump found. OPL playback not available.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto data = fileSystem.OpenFileReader(lump);
|
||||||
|
|
||||||
mus_volume.Callback ();
|
auto genmidi = data.Read();
|
||||||
|
if (genmidi.Size() < 8 + 175 * 36 || memcmp(genmidi.Data(), "#OPL_II#", 8)) return;
|
||||||
|
ZMusic_SetGenMidi(genmidi.Data()+8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetupWgOpn()
|
||||||
|
{
|
||||||
|
int lump = fileSystem.CheckNumForFullName("xg.wopn");
|
||||||
|
if (lump < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FileData data = fileSystem.ReadFile(lump);
|
||||||
|
ZMusic_SetWgOpn(data.GetMem(), (uint32_t)data.GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetupDMXGUS()
|
||||||
|
{
|
||||||
|
int lump = fileSystem.CheckNumForFullName("DMXGUS");
|
||||||
|
if (lump < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FileData data = fileSystem.ReadFile(lump);
|
||||||
|
ZMusic_SetDmxGus(data.GetMem(), (uint32_t)data.GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void I_InitMusic(void)
|
||||||
|
{
|
||||||
|
I_InitSoundFonts();
|
||||||
|
|
||||||
|
snd_musicvolume.Callback ();
|
||||||
|
|
||||||
|
nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound");
|
||||||
|
|
||||||
snd_mididevice.Callback();
|
snd_mididevice.Callback();
|
||||||
|
|
||||||
|
@ -230,7 +238,11 @@ void Mus_Init(void)
|
||||||
callbacks.SF_Close = mus_sfclose;
|
callbacks.SF_Close = mus_sfclose;
|
||||||
|
|
||||||
ZMusic_SetCallbacks(&callbacks);
|
ZMusic_SetCallbacks(&callbacks);
|
||||||
timerSetCallback(S_UpdateMusic);
|
#ifndef ZMUSIC_LITE
|
||||||
|
SetupGenMidi();
|
||||||
|
SetupDMXGUS();
|
||||||
|
SetupWgOpn();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -244,7 +256,7 @@ void I_SetRelativeVolume(float vol)
|
||||||
{
|
{
|
||||||
relative_volume = (float)vol;
|
relative_volume = (float)vol;
|
||||||
ChangeMusicSetting(zmusic_relative_volume, nullptr, (float)vol);
|
ChangeMusicSetting(zmusic_relative_volume, nullptr, (float)vol);
|
||||||
mus_volume.Callback();
|
snd_musicvolume.Callback();
|
||||||
}
|
}
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -300,7 +312,8 @@ static ZMusic_MidiSource GetMIDISource(const char *fn)
|
||||||
FString src = fn;
|
FString src = fn;
|
||||||
if (src.Compare("*") == 0) src = mus_playing.name;
|
if (src.Compare("*") == 0) src = mus_playing.name;
|
||||||
|
|
||||||
auto lump = fileSystem.FindFile(src);
|
auto lump = fileSystem.CheckNumForName(src, ns_music);
|
||||||
|
if (lump < 0) lump = fileSystem.CheckNumForFullName(src);
|
||||||
if (lump < 0)
|
if (lump < 0)
|
||||||
{
|
{
|
||||||
Printf("Cannot find MIDI lump %s.\n", src.GetChars());
|
Printf("Cannot find MIDI lump %s.\n", src.GetChars());
|
||||||
|
@ -344,7 +357,7 @@ static ZMusic_MidiSource GetMIDISource(const char *fn)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
CCMD (writewave)
|
UNSAFE_CCMD (writewave)
|
||||||
{
|
{
|
||||||
if (argv.argc() >= 3 && argv.argc() <= 7)
|
if (argv.argc() >= 3 && argv.argc() <= 7)
|
||||||
{
|
{
|
||||||
|
@ -352,18 +365,23 @@ CCMD (writewave)
|
||||||
if (source == nullptr) return;
|
if (source == nullptr) return;
|
||||||
|
|
||||||
EMidiDevice dev = MDEV_DEFAULT;
|
EMidiDevice dev = MDEV_DEFAULT;
|
||||||
|
#ifndef ZMUSIC_LITE
|
||||||
if (argv.argc() >= 6)
|
if (argv.argc() >= 6)
|
||||||
{
|
{
|
||||||
if (!stricmp(argv[5], "Timidity") || !stricmp(argv[5], "Timidity++")) dev = MDEV_TIMIDITY;
|
if (!stricmp(argv[5], "WildMidi")) dev = MDEV_WILDMIDI;
|
||||||
|
else if (!stricmp(argv[5], "GUS")) dev = MDEV_GUS;
|
||||||
|
else if (!stricmp(argv[5], "Timidity") || !stricmp(argv[5], "Timidity++")) dev = MDEV_TIMIDITY;
|
||||||
else if (!stricmp(argv[5], "FluidSynth")) dev = MDEV_FLUIDSYNTH;
|
else if (!stricmp(argv[5], "FluidSynth")) dev = MDEV_FLUIDSYNTH;
|
||||||
else if (!stricmp(argv[5], "OPL")) dev = MDEV_OPL;
|
else if (!stricmp(argv[5], "OPL")) dev = MDEV_OPL;
|
||||||
|
else if (!stricmp(argv[5], "OPN")) dev = MDEV_OPN;
|
||||||
|
else if (!stricmp(argv[5], "ADL")) dev = MDEV_ADL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Printf("%s: Unknown MIDI device\n", argv[5]);
|
Printf("%s: Unknown MIDI device\n", argv[5]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// We must stop the currently playing music to avoid interference between two synths.
|
// We must stop the currently playing music to avoid interference between two synths.
|
||||||
auto savedsong = mus_playing;
|
auto savedsong = mus_playing;
|
||||||
S_StopMusic(true);
|
S_StopMusic(true);
|
||||||
|
@ -392,7 +410,7 @@ CCMD (writewave)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
CCMD(writemidi)
|
UNSAFE_CCMD(writemidi)
|
||||||
{
|
{
|
||||||
if (argv.argc() != 3)
|
if (argv.argc() != 3)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,14 +34,26 @@
|
||||||
#ifndef __I_MUSIC_H__
|
#ifndef __I_MUSIC_H__
|
||||||
#define __I_MUSIC_H__
|
#define __I_MUSIC_H__
|
||||||
|
|
||||||
|
#include "c_cvars.h"
|
||||||
|
|
||||||
class FileReader;
|
class FileReader;
|
||||||
|
struct FOptionValues;
|
||||||
|
|
||||||
//
|
//
|
||||||
// MUSIC I/O
|
// MUSIC I/O
|
||||||
//
|
//
|
||||||
|
void I_InitMusic ();
|
||||||
|
void I_BuildMIDIMenuList (FOptionValues *);
|
||||||
|
|
||||||
// Volume.
|
// Volume.
|
||||||
void I_SetRelativeVolume(float);
|
void I_SetRelativeVolume(float);
|
||||||
void I_SetMusicVolume (double volume);
|
void I_SetMusicVolume (double volume);
|
||||||
|
|
||||||
|
|
||||||
|
extern int nomusic;
|
||||||
|
|
||||||
|
EXTERN_CVAR(Bool, mus_enabled)
|
||||||
|
EXTERN_CVAR(Float, snd_musicvolume)
|
||||||
|
|
||||||
|
|
||||||
#endif //__I_MUSIC_H__
|
#endif //__I_MUSIC_H__
|
||||||
|
|
|
@ -35,7 +35,9 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "i_soundfont.h"
|
#include "i_soundfont.h"
|
||||||
|
#include "i_soundinternal.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
#include "i_system.h"
|
||||||
#include "gameconfigfile.h"
|
#include "gameconfigfile.h"
|
||||||
#include "filereadermusicinterface.h"
|
#include "filereadermusicinterface.h"
|
||||||
#include <zmusic.h>
|
#include <zmusic.h>
|
||||||
|
@ -292,7 +294,7 @@ FileReader FPatchSetReader::OpenFile(const char *name)
|
||||||
|
|
||||||
FLumpPatchSetReader::FLumpPatchSetReader(const char *filename)
|
FLumpPatchSetReader::FLumpPatchSetReader(const char *filename)
|
||||||
{
|
{
|
||||||
mLumpIndex = fileSystem.FindFile(filename);
|
mLumpIndex = fileSystem.CheckNumForFullName(filename);
|
||||||
|
|
||||||
mBasePath = filename;
|
mBasePath = filename;
|
||||||
FixPathSeperator(mBasePath);
|
FixPathSeperator(mBasePath);
|
||||||
|
@ -310,7 +312,7 @@ FileReader FLumpPatchSetReader::OpenFile(const char *name)
|
||||||
FString path;
|
FString path;
|
||||||
if (IsAbsPath(name)) return FileReader(); // no absolute paths in the lump directory.
|
if (IsAbsPath(name)) return FileReader(); // no absolute paths in the lump directory.
|
||||||
path = mBasePath + name;
|
path = mBasePath + name;
|
||||||
auto index = fileSystem.FindFile(path);
|
auto index = fileSystem.CheckNumForFullName(path);
|
||||||
if (index < 0) return FileReader();
|
if (index < 0) return FileReader();
|
||||||
return fileSystem.ReopenFileReader(index);
|
return fileSystem.ReopenFileReader(index);
|
||||||
}
|
}
|
||||||
|
@ -470,7 +472,7 @@ FSoundFontReader *FSoundFontManager::OpenSoundFont(const char *name, int allowed
|
||||||
if (name != nullptr)
|
if (name != nullptr)
|
||||||
{
|
{
|
||||||
const char *p = name + strlen(name) - 4;
|
const char *p = name + strlen(name) - 4;
|
||||||
if (p > name && !stricmp(p, ".cfg") && fileSystem.FindFile(name) >= 0)
|
if (p > name && !stricmp(p, ".cfg") && fileSystem.CheckNumForFullName(name) >= 0)
|
||||||
{
|
{
|
||||||
return new FLumpPatchSetReader(name);
|
return new FLumpPatchSetReader(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
**
|
**
|
||||||
** music.cpp
|
** music.cpp
|
||||||
**
|
**
|
||||||
** music engine - borrowed from GZDoom
|
** music engine
|
||||||
**
|
**
|
||||||
** Copyright 1999-2016 Randy Heit
|
** Copyright 1999-2016 Randy Heit
|
||||||
** Copyright 2002-2016 Christoph Oelckers
|
** Copyright 2002-2016 Christoph Oelckers
|
||||||
|
@ -35,51 +35,35 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <zmusic.h>
|
#include <stdio.h>
|
||||||
#include "z_music.h"
|
#include <stdlib.h>
|
||||||
#include "zstring.h"
|
|
||||||
#include "backend/i_sound.h"
|
|
||||||
#include "name.h"
|
#include "i_sound.h"
|
||||||
#include "s_music.h"
|
|
||||||
#include "i_music.h"
|
#include "i_music.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "files.h"
|
#include "s_playlist.h"
|
||||||
|
#include "c_dispatch.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "gamecvars.h"
|
#include "s_music.h"
|
||||||
#include "c_dispatch.h"
|
|
||||||
#include "gamecontrol.h"
|
|
||||||
#include "filereadermusicinterface.h"
|
#include "filereadermusicinterface.h"
|
||||||
#include "v_text.h"
|
#include <zmusic.h>
|
||||||
#include "mapinfo.h"
|
|
||||||
#include "serializer.h"
|
|
||||||
|
|
||||||
MusPlayingInfo mus_playing;
|
static bool MusicPaused; // whether music is paused
|
||||||
MusicAliasMap MusicAliases;
|
MusPlayingInfo mus_playing; // music currently being played
|
||||||
MidiDeviceMap MidiDevices;
|
static FPlayList PlayList;
|
||||||
|
float relative_volume = 1.f;
|
||||||
|
float saved_relative_volume = 1.0f; // this could be used to implement an ACS FadeMusic function
|
||||||
MusicVolumeMap MusicVolumes;
|
MusicVolumeMap MusicVolumes;
|
||||||
MusicAliasMap LevelMusicAliases;
|
MidiDeviceMap MidiDevices;
|
||||||
bool MusicPaused;
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
static bool mus_blocked;
|
|
||||||
static FString lastStartedMusic;
|
|
||||||
EXTERN_CVAR(Float, mus_volume)
|
|
||||||
CVAR(Bool, printmusicinfo, false, 0)
|
|
||||||
CVAR(Bool, mus_extendedlookup, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|
||||||
|
|
||||||
// Order is: streaming formats, module formats, emulated formats and MIDI formats - for external files the first one found wins so ambiguous names should be avoided
|
extern float S_GetMusicVolume (const char *music);
|
||||||
static const char* knownMusicExts[] = {
|
|
||||||
"OGG", "FLAC", "MP3", "MP2", "XA", "XM", "MOD",
|
|
||||||
"IT", "S3M", "MTM", "STM", "669", "PTM", "AMF",
|
|
||||||
"OKT", "DSM", "AMFF", "SPC", "VGM", "VGZ", "AY",
|
|
||||||
"GBS", "GYM", "HES", "KSS", "NSF", "NSFE", "SAP",
|
|
||||||
"MID", "HMP", "HMI", "XMI", "VOC"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static void S_ActivatePlayList(bool goBack);
|
||||||
|
|
||||||
FString G_SetupFilenameBasedMusic(const char* fn, const char* defmusic)
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
{
|
|
||||||
FString name = StripExtension(fn);
|
|
||||||
FString test;
|
|
||||||
|
|
||||||
// Test if a real file with this name exists with all known extensions for music.
|
// Test if a real file with this name exists with all known extensions for music.
|
||||||
for (auto& ext : knownMusicExts)
|
for (auto& ext : knownMusicExts)
|
||||||
|
@ -94,77 +78,25 @@ FString G_SetupFilenameBasedMusic(const char* fn, const char* defmusic)
|
||||||
return defmusic;
|
return defmusic;
|
||||||
}
|
}
|
||||||
|
|
||||||
FString MusicFileExists(const char* fn)
|
|
||||||
|
static FileReader DefaultOpenMusic(const char* fn)
|
||||||
{
|
{
|
||||||
if (mus_extendedlookup) return G_SetupFilenameBasedMusic(fn, nullptr);
|
// This is the minimum needed to make the music system functional.
|
||||||
if (FileExists(fn)) return fn;
|
FileReader fr;
|
||||||
return FString();
|
fr.OpenFile(fn);
|
||||||
|
return fr;
|
||||||
}
|
}
|
||||||
|
static MusicCallbacks mus_cb = { nullptr, DefaultOpenMusic };
|
||||||
|
|
||||||
int LookupMusicLump(const char* fn)
|
|
||||||
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
void S_SetMusicCallbacks(MusicCallbacks* cb)
|
||||||
{
|
{
|
||||||
if (mus_extendedlookup)
|
mus_cb = *cb;
|
||||||
{
|
if (mus_cb.OpenMusic == nullptr) mus_cb.OpenMusic = DefaultOpenMusic; // without this we are dead in the water.
|
||||||
FString name = StripExtension(fn);
|
|
||||||
int l = fileSystem.FindFileWithExtensions(name, knownMusicExts, countof(knownMusicExts));
|
|
||||||
if (l >= 0) return l;
|
|
||||||
}
|
|
||||||
return fileSystem.FindFile(fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// Music lookup in various places.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
FileReader LookupMusic(const char* musicname)
|
|
||||||
{
|
|
||||||
FileReader reader;
|
|
||||||
FString mus = MusicFileExists(musicname);
|
|
||||||
if (mus.IsNotEmpty())
|
|
||||||
{
|
|
||||||
// Load an external file.
|
|
||||||
reader.OpenFile(mus);
|
|
||||||
}
|
|
||||||
if (!reader.isOpen())
|
|
||||||
{
|
|
||||||
int lumpnum = LookupMusicLump(musicname);
|
|
||||||
if (mus_extendedlookup && lumpnum >= 0)
|
|
||||||
{
|
|
||||||
// EDuke also looks in a subfolder named after the main game resource. Do this as well if extended lookup is active.
|
|
||||||
auto rfn = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum));
|
|
||||||
auto rfbase = ExtractFileBase(rfn);
|
|
||||||
FStringf aliasMusicname("music/%s/%s", rfbase.GetChars(), musicname);
|
|
||||||
lumpnum = LookupMusicLump(aliasMusicname);
|
|
||||||
}
|
|
||||||
if (lumpnum == -1)
|
|
||||||
{
|
|
||||||
// Always look in the 'music' subfolder as well. This gets used by multiple setups to store ripped CD tracks.
|
|
||||||
FStringf aliasMusicname("music/%s", musicname);
|
|
||||||
lumpnum = LookupMusicLump(aliasMusicname);
|
|
||||||
}
|
|
||||||
if (lumpnum == -1 && (g_gameType & GAMEFLAG_SW))
|
|
||||||
{
|
|
||||||
// Some Shadow Warrioe distributions have the music in a subfolder named 'classic'. Check that, too.
|
|
||||||
FStringf aliasMusicname("classic/music/%s", musicname);
|
|
||||||
lumpnum = fileSystem.FindFile(aliasMusicname);
|
|
||||||
}
|
|
||||||
if (lumpnum > -1)
|
|
||||||
{
|
|
||||||
if (fileSystem.FileLength(lumpnum) >= 0)
|
|
||||||
{
|
|
||||||
reader = fileSystem.ReopenFileReader(lumpnum);
|
|
||||||
if (!reader.isOpen())
|
|
||||||
{
|
|
||||||
Printf(TEXTCOLOR_RED "Unable to play music " TEXTCOLOR_WHITE "\"%s\"\n", musicname);
|
|
||||||
}
|
|
||||||
else if (printmusicinfo) Printf("Playing music from file system %s:%s\n", fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(lumpnum)), fileSystem.GetFileFullPath(lumpnum).GetChars());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (printmusicinfo) Printf("Playing music from external file %s\n", musicname);
|
|
||||||
return reader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -240,7 +172,7 @@ static bool S_StartMusicPlaying(ZMusic_MusicStream song, bool loop, float rel_vo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify the sound system of the changed relative volume
|
// Notify the sound system of the changed relative volume
|
||||||
mus_volume.Callback();
|
snd_musicvolume.Callback();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +219,6 @@ void S_ResumeMusic ()
|
||||||
|
|
||||||
void S_UpdateMusic ()
|
void S_UpdateMusic ()
|
||||||
{
|
{
|
||||||
mus_blocked = false;
|
|
||||||
if (mus_playing.handle != nullptr)
|
if (mus_playing.handle != nullptr)
|
||||||
{
|
{
|
||||||
ZMusic_Update(mus_playing.handle);
|
ZMusic_Update(mus_playing.handle);
|
||||||
|
@ -297,31 +228,61 @@ void S_UpdateMusic ()
|
||||||
// playlist when the current song finishes.
|
// playlist when the current song finishes.
|
||||||
if (!ZMusic_IsPlaying(mus_playing.handle))
|
if (!ZMusic_IsPlaying(mus_playing.handle))
|
||||||
{
|
{
|
||||||
|
if (PlayList.GetNumSongs())
|
||||||
|
{
|
||||||
|
PlayList.Advance();
|
||||||
|
S_ActivatePlayList(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
S_StopMusic(true);
|
S_StopMusic(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// S_ChangeCDMusic
|
// Resets the music player if music playback was paused.
|
||||||
//
|
//
|
||||||
// Starts a CD track as music.
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool S_ChangeCDMusic (int track, unsigned int id, bool looping)
|
void S_ResetMusic ()
|
||||||
{
|
{
|
||||||
char temp[32];
|
// stop the old music if it has been paused.
|
||||||
|
// This ensures that the new music is started from the beginning
|
||||||
|
// if it's the same as the last one and it has been paused.
|
||||||
|
if (MusicPaused) S_StopMusic(true);
|
||||||
|
|
||||||
if (id != 0)
|
// start new music for the level
|
||||||
|
MusicPaused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// S_ActivatePlayList
|
||||||
|
//
|
||||||
|
// Plays the next song in the playlist. If no songs in the playlist can be
|
||||||
|
// played, then it is deleted.
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void S_ActivatePlayList (bool goBack)
|
||||||
|
{
|
||||||
|
int startpos, pos;
|
||||||
|
|
||||||
|
startpos = pos = PlayList.GetPosition ();
|
||||||
|
S_StopMusic (true);
|
||||||
|
while (!S_ChangeMusic (PlayList.GetSong (pos), 0, false, true))
|
||||||
{
|
{
|
||||||
mysnprintf (temp, countof(temp), ",CD,%d,%x", track, id);
|
pos = goBack ? PlayList.Backup () : PlayList.Advance ();
|
||||||
}
|
if (pos == startpos)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
mysnprintf (temp, countof(temp), ",CD,%d", track);
|
PlayList.Clear();
|
||||||
|
Printf ("Cannot play anything in the playlist.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return S_ChangeMusic (temp, 0, looping);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -340,16 +301,26 @@ bool S_StartMusic (const char *m_id)
|
||||||
//
|
//
|
||||||
// S_ChangeMusic
|
// S_ChangeMusic
|
||||||
//
|
//
|
||||||
// Starts playing a music, possibly looping.
|
// initiates playback of a song
|
||||||
//
|
//
|
||||||
// [RH] If music is a MOD, starts it at position order. If name is of the
|
|
||||||
// format ",CD,<track>,[cd id]" song is a CD track, and if [cd id] is
|
|
||||||
// specified, it will only be played if the specified CD is in a drive.
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
|
bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
|
||||||
{
|
{
|
||||||
lastStartedMusic = musicname; // remember the last piece of music that was requested to be played.
|
if (nomusic) return false; // skip the entire procedure if music is globally disabled.
|
||||||
|
|
||||||
|
if (!force && PlayList.GetNumSongs())
|
||||||
|
{ // Don't change if a playlist is active
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Do game specific lookup.
|
||||||
|
FString musicname_;
|
||||||
|
if (mus_cb.LookupFileName)
|
||||||
|
{
|
||||||
|
musicname_ = mus_cb.LookupFileName(musicname, order);
|
||||||
|
musicname = musicname_.GetChars();
|
||||||
|
}
|
||||||
|
|
||||||
if (musicname == nullptr || musicname[0] == 0)
|
if (musicname == nullptr || musicname[0] == 0)
|
||||||
{
|
{
|
||||||
// Don't choke if the map doesn't have a song attached
|
// Don't choke if the map doesn't have a song attached
|
||||||
|
@ -358,13 +329,10 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
|
||||||
mus_playing.LastSong = "";
|
mus_playing.LastSong = "";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (*musicname == '/') musicname++;
|
|
||||||
|
|
||||||
FString DEH_Music;
|
|
||||||
|
|
||||||
if (!mus_playing.name.IsEmpty() &&
|
if (!mus_playing.name.IsEmpty() &&
|
||||||
mus_playing.handle != nullptr &&
|
mus_playing.handle != nullptr &&
|
||||||
stricmp (mus_playing.name, musicname) == 0 &&
|
stricmp(mus_playing.name, musicname) == 0 &&
|
||||||
ZMusic_IsLooping(mus_playing.handle) == zmusic_bool(looping))
|
ZMusic_IsLooping(mus_playing.handle) == zmusic_bool(looping))
|
||||||
{
|
{
|
||||||
if (order != mus_playing.baseorder)
|
if (order != mus_playing.baseorder)
|
||||||
|
@ -386,29 +354,10 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strnicmp (musicname, ",CD,", 4) == 0)
|
|
||||||
{
|
|
||||||
int track = strtoul (musicname+4, nullptr, 0);
|
|
||||||
const char *more = strchr (musicname+4, ',');
|
|
||||||
unsigned int id = 0;
|
|
||||||
|
|
||||||
if (more != nullptr)
|
|
||||||
{
|
|
||||||
id = strtoul (more+1, nullptr, 16);
|
|
||||||
}
|
|
||||||
S_StopMusic (true);
|
|
||||||
mus_playing.handle = ZMusic_OpenCDSong (track, id);
|
|
||||||
if (mus_playing.handle == nullptr)
|
|
||||||
{
|
|
||||||
Printf("Unable to start CD Audio for track #%d, ID %d\n", track, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int lumpnum = -1;
|
int lumpnum = -1;
|
||||||
int length = 0;
|
int length = 0;
|
||||||
ZMusic_MusicStream handle = nullptr;
|
ZMusic_MusicStream handle = nullptr;
|
||||||
MidiDeviceSetting *devp = MidiDevices.CheckKey(musicname);
|
MidiDeviceSetting* devp = MidiDevices.CheckKey(musicname);
|
||||||
|
|
||||||
// Strip off any leading file:// component.
|
// Strip off any leading file:// component.
|
||||||
if (strncmp(musicname, "file://", 7) == 0)
|
if (strncmp(musicname, "file://", 7) == 0)
|
||||||
|
@ -416,14 +365,15 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
|
||||||
musicname += 7;
|
musicname += 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileReader reader = LookupMusic(musicname);
|
// opening the music must be done by the game because it's different depending on the game's file system use.
|
||||||
|
FileReader reader = mus_cb.OpenMusic(musicname);
|
||||||
if (!reader.isOpen()) return false;
|
if (!reader.isOpen()) return false;
|
||||||
|
|
||||||
// shutdown old music
|
// shutdown old music
|
||||||
S_StopMusic (true);
|
S_StopMusic(true);
|
||||||
|
|
||||||
// Just record it if volume is 0 or music was disabled
|
// Just record it if volume is 0 or music was disabled
|
||||||
if (mus_volume <= 0 || !mus_enabled)
|
if (snd_musicvolume <= 0 || !mus_enabled)
|
||||||
{
|
{
|
||||||
mus_playing.loop = looping;
|
mus_playing.loop = looping;
|
||||||
mus_playing.name = musicname;
|
mus_playing.name = musicname;
|
||||||
|
@ -440,13 +390,12 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto mreader = GetMusicReader(reader); // this passes the file reader to the newly created wrapper.
|
auto mreader = GetMusicReader(reader); // this passes the file reader to the newly created wrapper.
|
||||||
mus_playing.handle = ZMusic_OpenSong(mreader, devp? (EMidiDevice)devp->device : MDEV_DEFAULT, devp? devp->args.GetChars() : "");
|
mus_playing.handle = ZMusic_OpenSong(mreader, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : "");
|
||||||
if (mus_playing.handle == nullptr)
|
if (mus_playing.handle == nullptr)
|
||||||
{
|
{
|
||||||
Printf("Unable to load %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError());
|
Printf("Unable to load %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mus_playing.loop = looping;
|
mus_playing.loop = looping;
|
||||||
mus_playing.name = musicname;
|
mus_playing.name = musicname;
|
||||||
|
@ -477,7 +426,8 @@ bool S_ChangeMusic(const char* musicname, int order, bool looping, bool force)
|
||||||
|
|
||||||
void S_RestartMusic ()
|
void S_RestartMusic ()
|
||||||
{
|
{
|
||||||
if (!mus_playing.LastSong.IsEmpty() && mus_volume > 0 && mus_enabled)
|
if (snd_musicvolume <= 0) return;
|
||||||
|
if (!mus_playing.LastSong.IsEmpty() && mus_enabled)
|
||||||
{
|
{
|
||||||
FString song = mus_playing.LastSong;
|
FString song = mus_playing.LastSong;
|
||||||
mus_playing.LastSong = "";
|
mus_playing.LastSong = "";
|
||||||
|
@ -542,7 +492,7 @@ void S_StopMusic (bool force)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// [RH] Don't stop if a playlist is active.
|
// [RH] Don't stop if a playlist is active.
|
||||||
if (!mus_playing.name.IsEmpty())
|
if ((force || PlayList.GetNumSongs() == 0) && !mus_playing.name.IsEmpty())
|
||||||
{
|
{
|
||||||
if (mus_playing.handle != nullptr)
|
if (mus_playing.handle != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -556,7 +506,7 @@ void S_StopMusic (bool force)
|
||||||
mus_playing.LastSong = std::move(mus_playing.name);
|
mus_playing.LastSong = std::move(mus_playing.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const CRecoverableError& )
|
catch (const std::runtime_error& )
|
||||||
{
|
{
|
||||||
//Printf("Unable to stop %s: %s\n", mus_playing.name.GetChars(), err.what());
|
//Printf("Unable to stop %s: %s\n", mus_playing.name.GetChars(), err.what());
|
||||||
if (mus_playing.handle != nullptr)
|
if (mus_playing.handle != nullptr)
|
||||||
|
@ -577,10 +527,11 @@ void S_StopMusic (bool force)
|
||||||
|
|
||||||
CCMD (changemus)
|
CCMD (changemus)
|
||||||
{
|
{
|
||||||
if (MusicEnabled())
|
if (!nomusic)
|
||||||
{
|
{
|
||||||
if (argv.argc() > 1)
|
if (argv.argc() > 1)
|
||||||
{
|
{
|
||||||
|
PlayList.Clear();
|
||||||
S_ChangeMusic (argv[1], argv.argc() > 2 ? atoi (argv[2]) : 0);
|
S_ChangeMusic (argv[1], argv.argc() > 2 ? atoi (argv[2]) : 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -610,104 +561,136 @@ CCMD (changemus)
|
||||||
|
|
||||||
CCMD (stopmus)
|
CCMD (stopmus)
|
||||||
{
|
{
|
||||||
|
PlayList.Clear();
|
||||||
S_StopMusic (false);
|
S_StopMusic (false);
|
||||||
mus_playing.LastSong = ""; // forget the last played song so that it won't get restarted if some volume changes occur
|
mus_playing.LastSong = ""; // forget the last played song so that it won't get restarted if some volume changes occur
|
||||||
}
|
}
|
||||||
|
|
||||||
static FString lastMusicLevel, lastMusic;
|
//==========================================================================
|
||||||
int Mus_Play(const char *mapname, const char *fn, bool loop)
|
//
|
||||||
|
// CCMD playlist
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
UNSAFE_CCMD (playlist)
|
||||||
{
|
{
|
||||||
if (mus_blocked) return 1; // Caller should believe it succeeded.
|
int argc = argv.argc();
|
||||||
// Store the requested names for resuming.
|
|
||||||
lastMusicLevel = mapname;
|
|
||||||
lastMusic = fn;
|
|
||||||
|
|
||||||
if (!MusicEnabled())
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow per level music substitution.
|
if (argc < 2 || argc > 3)
|
||||||
// For most cases using $musicalias would be sufficient, but that method only works if a level actually has some music defined at all.
|
|
||||||
// This way it can be done with an add-on definition lump even in cases like Redneck Rampage where no music definitions exist
|
|
||||||
// or where music gets reused for multiple levels but replacement is wanted individually.
|
|
||||||
if (mapname && *mapname)
|
|
||||||
{
|
{
|
||||||
if (*mapname == '/') mapname++;
|
Printf ("playlist <playlist.m3u> [<position>|shuffle]\n");
|
||||||
FName *check = LevelMusicAliases.CheckKey(FName(mapname, true));
|
|
||||||
if (check) fn = check->GetChars();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Now perform music aliasing. This also needs to be done before checking identities because multiple names can map to the same song.
|
|
||||||
FName* aliasp = MusicAliases.CheckKey(fn);
|
|
||||||
if (aliasp != nullptr)
|
|
||||||
{
|
{
|
||||||
if (*aliasp == NAME_None)
|
if (!PlayList.ChangeList(argv[1]))
|
||||||
{
|
{
|
||||||
return true; // flagged to be ignored
|
Printf("Could not open " TEXTCOLOR_BOLD "%s" TEXTCOLOR_NORMAL ": %s\n", argv[1], strerror(errno));
|
||||||
}
|
return;
|
||||||
fn = aliasp->GetChars();
|
|
||||||
}
|
}
|
||||||
|
if (PlayList.GetNumSongs () > 0)
|
||||||
if (!mus_restartonload)
|
|
||||||
{
|
{
|
||||||
// If the currently playing piece of music is the same, do not restart. Note that there's still edge cases where this may fail to detect identities.
|
if (argc == 3)
|
||||||
if (mus_playing.handle != nullptr && lastStartedMusic.CompareNoCase(fn) == 0 && mus_playing.loop)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return S_ChangeMusic(fn, 0, loop, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Mus_IsPlaying()
|
|
||||||
{
|
|
||||||
return mus_playing.handle != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mus_Stop()
|
|
||||||
{
|
|
||||||
if (mus_blocked) return;
|
|
||||||
S_StopMusic(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mus_Fade(double seconds)
|
|
||||||
{
|
|
||||||
// Todo: Blood uses this, but the streamer cannot currently fade the volume.
|
|
||||||
Mus_Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mus_SetPaused(bool on)
|
|
||||||
{
|
|
||||||
if (on) S_PauseMusic();
|
|
||||||
else S_ResumeMusic();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mus_Serialize(FSerializer &arc)
|
|
||||||
{
|
|
||||||
if (arc.BeginObject("music"))
|
|
||||||
{
|
|
||||||
if (arc.isWriting())
|
|
||||||
{
|
{
|
||||||
FString music = mus_playing.name;
|
if (stricmp (argv[2], "shuffle") == 0)
|
||||||
if (music.IsEmpty()) music = mus_playing.LastSong;
|
{
|
||||||
|
PlayList.Shuffle ();
|
||||||
arc.AddString("music", music);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlayList.SetPosition (atoi (argv[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
S_ActivatePlayList (false);
|
||||||
}
|
}
|
||||||
else arc("music", mus_playing.LastSong);
|
|
||||||
|
|
||||||
arc("baseorder", mus_playing.baseorder)
|
|
||||||
("loop", mus_playing.loop)
|
|
||||||
.EndObject();
|
|
||||||
|
|
||||||
// this is to prevent scripts from resetting the music after it has been loaded from the savegame.
|
|
||||||
if (arc.isReading()) mus_blocked = true;
|
|
||||||
// Actual music resuming cannot be performed here, it must be done in the game code.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mus_ResumeSaved()
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// CCMD playlistpos
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static bool CheckForPlaylist ()
|
||||||
{
|
{
|
||||||
S_RestartMusic();
|
if (PlayList.GetNumSongs() == 0)
|
||||||
|
{
|
||||||
|
Printf ("No playlist is playing.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCMD (playlistpos)
|
||||||
|
{
|
||||||
|
if (CheckForPlaylist() && argv.argc() > 1)
|
||||||
|
{
|
||||||
|
PlayList.SetPosition (atoi (argv[1]) - 1);
|
||||||
|
S_ActivatePlayList (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// CCMD playlistnext
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
CCMD (playlistnext)
|
||||||
|
{
|
||||||
|
if (CheckForPlaylist())
|
||||||
|
{
|
||||||
|
PlayList.Advance ();
|
||||||
|
S_ActivatePlayList (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// CCMD playlistprev
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
CCMD (playlistprev)
|
||||||
|
{
|
||||||
|
if (CheckForPlaylist())
|
||||||
|
{
|
||||||
|
PlayList.Backup ();
|
||||||
|
S_ActivatePlayList (true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// CCMD playliststatus
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
CCMD (playliststatus)
|
||||||
|
{
|
||||||
|
if (CheckForPlaylist ())
|
||||||
|
{
|
||||||
|
Printf ("Song %d of %d:\n%s\n",
|
||||||
|
PlayList.GetPosition () + 1,
|
||||||
|
PlayList.GetNumSongs (),
|
||||||
|
PlayList.GetSong (PlayList.GetPosition ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
CCMD(currentmusic)
|
||||||
|
{
|
||||||
|
if (mus_playing.name.IsNotEmpty())
|
||||||
|
{
|
||||||
|
Printf("Currently playing music '%s'\n", mus_playing.name.GetChars());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Printf("Currently no music playing\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
// ADL Midi device
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
@ -61,8 +61,49 @@
|
||||||
|
|
||||||
#define FORWARD_STRING_CVAR(key) \
|
#define FORWARD_STRING_CVAR(key) \
|
||||||
auto ret = ChangeMusicSetting(zmusic_##key, mus_playing.handle,*self); \
|
auto ret = ChangeMusicSetting(zmusic_##key, mus_playing.handle,*self); \
|
||||||
if (ret) S_MIDIDeviceChanged(-1);
|
if (ret) S_MIDIDeviceChanged(-1);
|
||||||
|
|
||||||
|
#ifndef ZMUSIC_LITE
|
||||||
|
CUSTOM_CVAR(Int, adl_chips_count, 6, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(adl_chips_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, adl_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(adl_emulator_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, adl_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(adl_run_at_pcm_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, adl_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(adl_fullpan);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, adl_bank, 14, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(adl_bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, adl_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(adl_use_custom_bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_STRING_CVAR(adl_custom_bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, adl_volume_model, 3/*ADLMIDI_VolumeModel_DMX*/, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(adl_bank);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Fluidsynth MIDI device
|
// Fluidsynth MIDI device
|
||||||
|
@ -182,10 +223,194 @@ CUSTOM_CVAR(Bool, opl_fullpan, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIR
|
||||||
FORWARD_BOOL_CVAR(opl_fullpan);
|
FORWARD_BOOL_CVAR(opl_fullpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef ZMUSIC_LITE
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// OPN MIDI device
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, opn_chips_count, 8, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(opn_chips_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, opn_emulator_id, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(opn_emulator_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, opn_run_at_pcm_rate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(opn_run_at_pcm_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, opn_fullpan, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(opn_fullpan);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, opn_use_custom_bank, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(opn_use_custom_bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_STRING_CVAR(opn_custom_bank);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// GUS MIDI device
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
CUSTOM_CVAR(String, midi_config, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_STRING_CVAR(gus_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, midi_dmxgus, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) // This was 'true' but since it requires special setup that's not such a good idea.
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(gus_dmxgus);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(String, gus_patchdir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_STRING_CVAR(gus_patchdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, midi_voices, 32, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(gus_midi_voices);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, gus_memsize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(gus_memsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Timidity++ device
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, timidity_modulation_wheel, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(timidity_modulation_wheel);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, timidity_portamento, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(timidity_portamento);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, timidity_reverb, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(timidity_reverb);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, timidity_reverb_level, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(timidity_reverb_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, timidity_chorus, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(timidity_chorus);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, timidity_surround_chorus, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(timidity_surround_chorus);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, timidity_channel_pressure, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(timidity_channel_pressure);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, timidity_lpf_def, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(timidity_lpf_def);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, timidity_temper_control, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(timidity_temper_control);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, timidity_modulation_envelope, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(timidity_modulation_envelope);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, timidity_overlap_voice_allow, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(timidity_overlap_voice_allow);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, timidity_drum_effect, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(timidity_drum_effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, timidity_pan_delay, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(timidity_pan_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Float, timidity_drum_power, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) /* coef. of drum amplitude */
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(timidity_drum_power);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, timidity_key_adjust, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(timidity_key_adjust);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Float, timidity_tempo_adjust, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(timidity_tempo_adjust);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Float, timidity_min_sustain_time, 5000, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_CVAR(timidity_min_sustain_time);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CUSTOM_CVAR(String, timidity_config, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
CUSTOM_CVAR(String, timidity_config, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
{
|
{
|
||||||
FORWARD_STRING_CVAR(timidity_config);
|
FORWARD_STRING_CVAR(timidity_config);
|
||||||
}
|
}
|
||||||
|
#ifndef ZMUSIC_LITE
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// WildMidi
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
CUSTOM_CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_STRING_CVAR(wildmidi_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, wildmidi_reverb, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(wildmidi_reverb);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, wildmidi_enhanced_resampling, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL)
|
||||||
|
{
|
||||||
|
FORWARD_BOOL_CVAR(wildmidi_enhanced_resampling);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
#include "sc_man.h"
|
#include "sc_man.h"
|
||||||
#include <zmusic.h>
|
#include <zmusic.h>
|
||||||
|
|
||||||
|
#include "raze_music.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
enum SICommands
|
enum SICommands
|
||||||
|
|
|
@ -7,6 +7,15 @@
|
||||||
#include "name.h"
|
#include "name.h"
|
||||||
#include <zmusic.h>
|
#include <zmusic.h>
|
||||||
|
|
||||||
|
class FileReader;
|
||||||
|
|
||||||
|
struct MusicCallbacks
|
||||||
|
{
|
||||||
|
FString(*LookupFileName)(const char* fn, int &order);
|
||||||
|
FileReader(*OpenMusic)(const char* fn);
|
||||||
|
};
|
||||||
|
void S_SetMusicCallbacks(MusicCallbacks* cb);
|
||||||
|
|
||||||
void S_CreateStream();
|
void S_CreateStream();
|
||||||
void S_PauseStream(bool pause);
|
void S_PauseStream(bool pause);
|
||||||
void S_StopStream();
|
void S_StopStream();
|
||||||
|
@ -15,7 +24,7 @@ void S_SetStreamVolume(float vol);
|
||||||
|
|
||||||
//
|
//
|
||||||
void S_InitMusic ();
|
void S_InitMusic ();
|
||||||
void S_StartMusic ();
|
void S_ResetMusic ();
|
||||||
|
|
||||||
|
|
||||||
// Start music using <music_name>
|
// Start music using <music_name>
|
||||||
|
@ -24,9 +33,6 @@ bool S_StartMusic (const char *music_name);
|
||||||
// Start music using <music_name>, and set whether looping
|
// Start music using <music_name>, and set whether looping
|
||||||
bool S_ChangeMusic (const char *music_name, int order=0, bool looping=true, bool force=false);
|
bool S_ChangeMusic (const char *music_name, int order=0, bool looping=true, bool force=false);
|
||||||
|
|
||||||
// Start playing a cd track as music
|
|
||||||
bool S_ChangeCDMusic (int track, unsigned int id=0, bool looping=true);
|
|
||||||
|
|
||||||
void S_RestartMusic ();
|
void S_RestartMusic ();
|
||||||
void S_MIDIDeviceChanged(int newdev);
|
void S_MIDIDeviceChanged(int newdev);
|
||||||
|
|
||||||
|
@ -50,11 +56,9 @@ struct MidiDeviceSetting
|
||||||
FString args;
|
FString args;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef TMap<FName, FName> MusicAliasMap;
|
|
||||||
typedef TMap<FName, MidiDeviceSetting> MidiDeviceMap;
|
typedef TMap<FName, MidiDeviceSetting> MidiDeviceMap;
|
||||||
typedef TMap<FName, float> MusicVolumeMap;
|
typedef TMap<FName, float> MusicVolumeMap;
|
||||||
|
|
||||||
extern MusicAliasMap MusicAliases;
|
|
||||||
extern MidiDeviceMap MidiDevices;
|
extern MidiDeviceMap MidiDevices;
|
||||||
extern MusicVolumeMap MusicVolumes;
|
extern MusicVolumeMap MusicVolumes;
|
||||||
|
|
||||||
|
@ -71,8 +75,5 @@ extern MusPlayingInfo mus_playing;
|
||||||
|
|
||||||
extern float relative_volume, saved_relative_volume;
|
extern float relative_volume, saved_relative_volume;
|
||||||
|
|
||||||
// Note for later when the OPL player is ported.
|
|
||||||
// DN3D and related games use "d3dtimbr.tmb"
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
282
source/core/raze_music.cpp
Normal file
282
source/core/raze_music.cpp
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** raze_music.cpp
|
||||||
|
** music player for Build games
|
||||||
|
**
|
||||||
|
** Copyright 2019-2020 Christoph Oelckers
|
||||||
|
**
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions
|
||||||
|
** are met:
|
||||||
|
**
|
||||||
|
** 1. Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** 3. The name of the author may not be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
**---------------------------------------------------------------------------
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "raze_music.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
#include "c_cvars.h"
|
||||||
|
#include "cmdlib.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "files.h"
|
||||||
|
#include "i_music.h"
|
||||||
|
|
||||||
|
#include "gamecontrol.h"
|
||||||
|
#include "serializer.h"
|
||||||
|
|
||||||
|
static bool mus_blocked;
|
||||||
|
static FString lastStartedMusic;
|
||||||
|
|
||||||
|
MusicAliasMap MusicAliases;
|
||||||
|
MusicAliasMap LevelMusicAliases;
|
||||||
|
|
||||||
|
CVAR(Bool, printmusicinfo, false, 0)
|
||||||
|
CVAR(Bool, mus_extendedlookup, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
|
|
||||||
|
// Order is: streaming formats, module formats, emulated formats and MIDI formats - for external files the first one found wins so ambiguous names should be avoided
|
||||||
|
static const char* knownMusicExts[] = {
|
||||||
|
"OGG", "FLAC", "MP3", "MP2", "XA", "XM", "MOD",
|
||||||
|
"IT", "S3M", "MTM", "STM", "669", "PTM", "AMF",
|
||||||
|
"OKT", "DSM", "AMFF", "SPC", "VGM", "VGZ", "AY",
|
||||||
|
"GBS", "GYM", "HES", "KSS", "NSF", "NSFE", "SAP",
|
||||||
|
"MID", "HMP", "HMI", "XMI", "VOC"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Music file name lookup
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString G_SetupFilenameBasedMusic(const char* fn, const char* defmusic)
|
||||||
|
{
|
||||||
|
FString name = StripExtension(fn);
|
||||||
|
FString test;
|
||||||
|
|
||||||
|
// Test if a real file with this name exists with all known extensions for music.
|
||||||
|
for (auto& ext : knownMusicExts)
|
||||||
|
{
|
||||||
|
test.Format("%s.%s", name.GetChars(), ext);
|
||||||
|
if (FileExists(test)) return test;
|
||||||
|
#ifdef __unix__
|
||||||
|
test.Format("%s.%s", name.GetChars(), FString(ext.GetChars()).MakeLower().GetChars());
|
||||||
|
if (FileExists(test)) return test;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return defmusic;
|
||||||
|
}
|
||||||
|
|
||||||
|
FString MusicFileExists(const char* fn)
|
||||||
|
{
|
||||||
|
if (mus_extendedlookup) return G_SetupFilenameBasedMusic(fn, nullptr);
|
||||||
|
if (FileExists(fn)) return fn;
|
||||||
|
return FString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int LookupMusicLump(const char* fn)
|
||||||
|
{
|
||||||
|
if (mus_extendedlookup)
|
||||||
|
{
|
||||||
|
FString name = StripExtension(fn);
|
||||||
|
int l = fileSystem.FindFileWithExtensions(name, knownMusicExts, countof(knownMusicExts));
|
||||||
|
if (l >= 0) return l;
|
||||||
|
}
|
||||||
|
return fileSystem.CheckNumForFullName(fn, true, ns_music);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Music lookup in various places.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FileReader OpenMusic(const char* musicname)
|
||||||
|
{
|
||||||
|
FileReader reader;
|
||||||
|
if (!mus_restartonload)
|
||||||
|
{
|
||||||
|
// If the currently playing piece of music is the same, do not restart. Note that there's still edge cases where this may fail to detect identities.
|
||||||
|
if (mus_playing.handle != nullptr && lastStartedMusic.CompareNoCase(musicname) == 0 && mus_playing.loop)
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
lastStartedMusic = musicname; // remember the last piece of music that was requested to be played.
|
||||||
|
|
||||||
|
FString mus = MusicFileExists(musicname);
|
||||||
|
if (mus.IsNotEmpty())
|
||||||
|
{
|
||||||
|
// Load an external file.
|
||||||
|
reader.OpenFile(mus);
|
||||||
|
}
|
||||||
|
if (!reader.isOpen())
|
||||||
|
{
|
||||||
|
int lumpnum = LookupMusicLump(musicname);
|
||||||
|
if (mus_extendedlookup && lumpnum >= 0)
|
||||||
|
{
|
||||||
|
// EDuke also looks in a subfolder named after the main game resource. Do this as well if extended lookup is active.
|
||||||
|
auto rfn = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(lumpnum));
|
||||||
|
auto rfbase = ExtractFileBase(rfn);
|
||||||
|
FStringf aliasMusicname("music/%s/%s", rfbase.GetChars(), musicname);
|
||||||
|
lumpnum = LookupMusicLump(aliasMusicname);
|
||||||
|
}
|
||||||
|
if (lumpnum == -1)
|
||||||
|
{
|
||||||
|
// Always look in the 'music' subfolder as well. This gets used by multiple setups to store ripped CD tracks.
|
||||||
|
FStringf aliasMusicname("music/%s", musicname);
|
||||||
|
lumpnum = LookupMusicLump(aliasMusicname);
|
||||||
|
}
|
||||||
|
if (lumpnum == -1 && (g_gameType & GAMEFLAG_SW))
|
||||||
|
{
|
||||||
|
// Some Shadow Warrioe distributions have the music in a subfolder named 'classic'. Check that, too.
|
||||||
|
FStringf aliasMusicname("classic/music/%s", musicname);
|
||||||
|
lumpnum = fileSystem.FindFile(aliasMusicname);
|
||||||
|
}
|
||||||
|
if (lumpnum > -1)
|
||||||
|
{
|
||||||
|
if (fileSystem.FileLength(lumpnum) >= 0)
|
||||||
|
{
|
||||||
|
reader = fileSystem.ReopenFileReader(lumpnum);
|
||||||
|
if (!reader.isOpen())
|
||||||
|
{
|
||||||
|
Printf(TEXTCOLOR_RED "Unable to play music " TEXTCOLOR_WHITE "\"%s\"\n", musicname);
|
||||||
|
}
|
||||||
|
else if (printmusicinfo) Printf("Playing music from file system %s:%s\n", fileSystem.GetResourceFileFullName(fileSystem.GetFileContainer(lumpnum)), fileSystem.GetFileFullPath(lumpnum).GetChars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (printmusicinfo) Printf("Playing music from external file %s\n", musicname);
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FString LookupMusic(const char* musicname, int& order)
|
||||||
|
{
|
||||||
|
// Now perform music aliasing. This also needs to be done before checking identities because multiple names can map to the same song.
|
||||||
|
FName* aliasp = MusicAliases.CheckKey(musicname);
|
||||||
|
if (aliasp != nullptr)
|
||||||
|
{
|
||||||
|
if (*aliasp == NAME_None)
|
||||||
|
{
|
||||||
|
return true; // flagged to be ignored
|
||||||
|
}
|
||||||
|
return aliasp->GetChars();
|
||||||
|
}
|
||||||
|
return musicname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static FString lastMusicLevel, lastMusic;
|
||||||
|
int Mus_Play(const char *mapname, const char *fn, bool loop)
|
||||||
|
{
|
||||||
|
if (mus_blocked) return 1; // Caller should believe it succeeded.
|
||||||
|
// Store the requested names for resuming.
|
||||||
|
lastMusicLevel = mapname;
|
||||||
|
lastMusic = fn;
|
||||||
|
|
||||||
|
if (!MusicEnabled())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow per level music substitution.
|
||||||
|
// For most cases using $musicalias would be sufficient, but that method only works if a level actually has some music defined at all.
|
||||||
|
// This way it can be done with an add-on definition lump even in cases like Redneck Rampage where no music definitions exist
|
||||||
|
// or where music gets reused for multiple levels but replacement is wanted individually.
|
||||||
|
if (mapname && *mapname)
|
||||||
|
{
|
||||||
|
if (*mapname == '/') mapname++;
|
||||||
|
FName *check = LevelMusicAliases.CheckKey(FName(mapname, true));
|
||||||
|
if (check) fn = check->GetChars();
|
||||||
|
}
|
||||||
|
|
||||||
|
return S_ChangeMusic(fn, 0, loop, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mus_IsPlaying()
|
||||||
|
{
|
||||||
|
return mus_playing.handle != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mus_Stop()
|
||||||
|
{
|
||||||
|
if (mus_blocked) return;
|
||||||
|
S_StopMusic(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mus_Fade(double seconds)
|
||||||
|
{
|
||||||
|
// Todo: Blood uses this, but the streamer cannot currently fade the volume.
|
||||||
|
Mus_Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mus_SetPaused(bool on)
|
||||||
|
{
|
||||||
|
if (on) S_PauseMusic();
|
||||||
|
else S_ResumeMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mus_Serialize(FSerializer &arc)
|
||||||
|
{
|
||||||
|
if (arc.BeginObject("music"))
|
||||||
|
{
|
||||||
|
if (arc.isWriting())
|
||||||
|
{
|
||||||
|
FString music = mus_playing.name;
|
||||||
|
if (music.IsEmpty()) music = mus_playing.LastSong;
|
||||||
|
|
||||||
|
arc.AddString("music", music);
|
||||||
|
}
|
||||||
|
else arc("music", mus_playing.LastSong);
|
||||||
|
|
||||||
|
arc("baseorder", mus_playing.baseorder)
|
||||||
|
("loop", mus_playing.loop)
|
||||||
|
.EndObject();
|
||||||
|
|
||||||
|
// this is to prevent scripts from resetting the music after it has been loaded from the savegame.
|
||||||
|
if (arc.isReading()) mus_blocked = true;
|
||||||
|
// Actual music resuming cannot be performed here, it must be done in the game code.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mus_ResumeSaved()
|
||||||
|
{
|
||||||
|
S_RestartMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mus_UpdateMusic()
|
||||||
|
{
|
||||||
|
mus_blocked = false;
|
||||||
|
S_UpdateMusic();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mus_InitMusic()
|
||||||
|
{
|
||||||
|
I_InitMusic();
|
||||||
|
static MusicCallbacks mus_cb =
|
||||||
|
{
|
||||||
|
LookupMusic,
|
||||||
|
OpenMusic
|
||||||
|
};
|
||||||
|
S_SetMusicCallbacks(&mus_cb);
|
||||||
|
}
|
|
@ -1,10 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "zstring.h"
|
#include "zstring.h"
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "name.h"
|
||||||
|
|
||||||
|
typedef TMap<FName, FName> MusicAliasMap;
|
||||||
|
extern MusicAliasMap MusicAliases;
|
||||||
|
|
||||||
// Totally minimalistic interface - should be all the game modules need.
|
// Totally minimalistic interface - should be all the game modules need.
|
||||||
|
void Mus_InitMusic();
|
||||||
void Mus_Init();
|
void Mus_UpdateMusic();
|
||||||
int Mus_Play(const char *mapname, const char *fn, bool loop);
|
int Mus_Play(const char *mapname, const char *fn, bool loop);
|
||||||
void Mus_Stop();
|
void Mus_Stop();
|
||||||
bool Mus_IsPlaying();
|
bool Mus_IsPlaying();
|
|
@ -49,7 +49,7 @@
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "s_soundinternal.h"
|
#include "s_soundinternal.h"
|
||||||
|
|
||||||
static CompositeSavegameWriter savewriter;
|
static CompositeSavegameWriter savewriter;
|
||||||
|
|
|
@ -48,13 +48,13 @@
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "s_music.h"
|
#include "s_music.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "gamecvars.h"
|
#include "gamecvars.h"
|
||||||
#include "gamecontrol.h"
|
#include "gamecontrol.h"
|
||||||
#include <zmusic.h>
|
#include <zmusic.h>
|
||||||
|
|
||||||
EXTERN_CVAR (Float, snd_sfxvolume)
|
EXTERN_CVAR (Float, snd_sfxvolume)
|
||||||
EXTERN_CVAR(Float, mus_volume)
|
EXTERN_CVAR(Float, snd_musicvolume)
|
||||||
CVAR (Int, snd_samplerate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR (Int, snd_samplerate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR (Int, snd_buffersize, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
CVAR (Int, snd_hrtf, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
CVAR (Int, snd_hrtf, -1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
|
@ -95,7 +95,7 @@ CUSTOM_CVAR(Float, snd_mastervolume, 1.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVA
|
||||||
|
|
||||||
ChangeMusicSetting(zmusic_snd_mastervolume, nullptr, self);
|
ChangeMusicSetting(zmusic_snd_mastervolume, nullptr, self);
|
||||||
snd_sfxvolume.Callback();
|
snd_sfxvolume.Callback();
|
||||||
mus_volume.Callback();
|
snd_musicvolume.Callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -33,7 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "savegamehelp.h"
|
#include "savegamehelp.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
#include "mapinfo.h"
|
#include "mapinfo.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
|
|
||||||
BEGIN_DUKE_NS
|
BEGIN_DUKE_NS
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,13 @@ double g_moveActorsTime, g_moveWorldTime; // in ms, smoothed
|
||||||
int32_t g_noLogoAnim = 0;
|
int32_t g_noLogoAnim = 0;
|
||||||
int32_t g_noLogo = 0;
|
int32_t g_noLogo = 0;
|
||||||
|
|
||||||
|
void PlayBonusMusic()
|
||||||
|
{
|
||||||
|
if (MusicEnabled() && mus_enabled)
|
||||||
|
S_PlaySound(BONUSMUSIC, CHAN_AUTO, CHANF_UI);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
////////// OFTEN-USED FEW-LINERS //////////
|
////////// OFTEN-USED FEW-LINERS //////////
|
||||||
#ifndef EDUKE32_STANDALONE
|
#ifndef EDUKE32_STANDALONE
|
||||||
static void G_HandleEventsWhileNoInput(void)
|
static void G_HandleEventsWhileNoInput(void)
|
||||||
|
@ -1921,8 +1928,7 @@ void G_BonusScreen(int32_t bonusonly)
|
||||||
videoClearScreen(0);
|
videoClearScreen(0);
|
||||||
G_DisplayMPResultsScreen();
|
G_DisplayMPResultsScreen();
|
||||||
|
|
||||||
if (MusicEnabled() && mus_enabled)
|
PlayBonusMusic();
|
||||||
S_PlaySound(BONUSMUSIC, CHAN_AUTO, CHANF_UI);
|
|
||||||
|
|
||||||
videoNextPage();
|
videoNextPage();
|
||||||
inputState.ClearAllInput();
|
inputState.ClearAllInput();
|
||||||
|
@ -1960,8 +1966,7 @@ void G_BonusScreen(int32_t bonusonly)
|
||||||
|
|
||||||
gametext_center_shade(192, GStrings("PRESSKEY"), quotepulseshade);
|
gametext_center_shade(192, GStrings("PRESSKEY"), quotepulseshade);
|
||||||
|
|
||||||
if (MusicEnabled() && mus_enabled)
|
PlayBonusMusic();
|
||||||
S_PlaySound(BONUSMUSIC, CHAN_AUTO, CHANF_UI);
|
|
||||||
|
|
||||||
videoNextPage();
|
videoNextPage();
|
||||||
inputState.ClearAllInput();
|
inputState.ClearAllInput();
|
||||||
|
|
|
@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
#include "duke3d.h"
|
#include "duke3d.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "mapinfo.h"
|
#include "mapinfo.h"
|
||||||
#include "sound/s_soundinternal.h"
|
#include "sound/s_soundinternal.h"
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
#include "sounds_common.h"
|
#include "sounds_common.h"
|
||||||
#include "sound/s_soundinternal.h"
|
#include "sound/s_soundinternal.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
|
|
||||||
BEGIN_DUKE_NS
|
BEGIN_DUKE_NS
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "exhumed.h"
|
#include "exhumed.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
|
|
||||||
BEGIN_PS_NS
|
BEGIN_PS_NS
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "i_specialpaths.h"
|
#include "i_specialpaths.h"
|
||||||
#include "gamecontrol.h"
|
#include "gamecontrol.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "mapinfo.h"
|
#include "mapinfo.h"
|
||||||
|
|
||||||
#include "savegamehelp.h"
|
#include "savegamehelp.h"
|
||||||
|
|
|
@ -46,6 +46,13 @@ double g_moveActorsTime, g_moveWorldTime; // in ms, smoothed
|
||||||
int32_t g_noLogoAnim = 0;
|
int32_t g_noLogoAnim = 0;
|
||||||
int32_t g_noLogo = 0;
|
int32_t g_noLogo = 0;
|
||||||
|
|
||||||
|
void PlayBonusMusic()
|
||||||
|
{
|
||||||
|
if (MusicEnabled() && mus_enabled)
|
||||||
|
S_PlaySound(BONUSMUSIC, CHAN_AUTO, CHANF_UI);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
////////// OFTEN-USED FEW-LINERS //////////
|
////////// OFTEN-USED FEW-LINERS //////////
|
||||||
static void G_HandleEventsWhileNoInput(void)
|
static void G_HandleEventsWhileNoInput(void)
|
||||||
{
|
{
|
||||||
|
@ -1930,8 +1937,7 @@ void G_BonusScreen(int32_t bonusonly)
|
||||||
videoClearScreen(0);
|
videoClearScreen(0);
|
||||||
G_DisplayMPResultsScreen();
|
G_DisplayMPResultsScreen();
|
||||||
|
|
||||||
if (MusicEnabled() && mus_enabled)
|
PlayBonusMusic();
|
||||||
S_PlaySound(BONUSMUSIC, CHAN_AUTO, CHANF_UI);
|
|
||||||
|
|
||||||
videoNextPage();
|
videoNextPage();
|
||||||
inputState.ClearAllInput();
|
inputState.ClearAllInput();
|
||||||
|
@ -1970,10 +1976,9 @@ void G_BonusScreen(int32_t bonusonly)
|
||||||
menutext_center(20-6, lastmapname);
|
menutext_center(20-6, lastmapname);
|
||||||
menutext_center(36-6, GStrings("Completed"));
|
menutext_center(36-6, GStrings("Completed"));
|
||||||
|
|
||||||
gametext_center_shade(192, GStrings("PRESSKEY"), quotepulseshade);
|
gametext_center_shade(192, GStrings("PRESSKEY"), quotepulseshade);
|
||||||
|
|
||||||
if (MusicEnabled() && mus_enabled)
|
PlayBonusMusic();
|
||||||
S_PlaySound(BONUSMUSIC, CHAN_AUTO, CHANF_UI);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2504,8 +2509,7 @@ void G_BonusScreenRRRA(int32_t bonusonly)
|
||||||
videoClearScreen(0);
|
videoClearScreen(0);
|
||||||
G_DisplayMPResultsScreen();
|
G_DisplayMPResultsScreen();
|
||||||
|
|
||||||
if (MusicEnabled() && mus_enabled)
|
PlayBonusMusic();
|
||||||
S_PlaySound(BONUSMUSIC, CHAN_AUTO, CHANF_UI);
|
|
||||||
|
|
||||||
videoNextPage();
|
videoNextPage();
|
||||||
inputState.ClearAllInput();
|
inputState.ClearAllInput();
|
||||||
|
|
|
@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
#include "duke3d.h"
|
#include "duke3d.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "mapinfo.h"
|
#include "mapinfo.h"
|
||||||
#include "sound/s_soundinternal.h"
|
#include "sound/s_soundinternal.h"
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
#include "sounds_common.h"
|
#include "sounds_common.h"
|
||||||
#include "sound/s_soundinternal.h"
|
#include "sound/s_soundinternal.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
|
|
||||||
BEGIN_RR_NS
|
BEGIN_RR_NS
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ Things required to make savegames work:
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "debugbreak.h"
|
#include "debugbreak.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "statistics.h"
|
#include "statistics.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
#include "mapinfo.h"
|
#include "mapinfo.h"
|
||||||
|
|
|
@ -65,7 +65,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
||||||
#include "interpso.h"
|
#include "interpso.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
|
|
||||||
BEGIN_SW_NS
|
BEGIN_SW_NS
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "i_specialpaths.h"
|
#include "i_specialpaths.h"
|
||||||
#include "savegamehelp.h"
|
#include "savegamehelp.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "mapinfo.h"
|
#include "mapinfo.h"
|
||||||
|
|
||||||
//void TimerFunc(task * Task);
|
//void TimerFunc(task * Task);
|
||||||
|
|
|
@ -49,7 +49,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
||||||
#include "menus.h"
|
#include "menus.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
#include "z_music.h"
|
#include "raze_music.h"
|
||||||
#include "sound/s_soundinternal.h"
|
#include "sound/s_soundinternal.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
|
|
|
@ -1387,7 +1387,7 @@ OptionMenu SoundOptions //protected
|
||||||
Option "$SNDMNU_SNDENABLED", "snd_enabled", "YesNo"
|
Option "$SNDMNU_SNDENABLED", "snd_enabled", "YesNo"
|
||||||
Slider "$SNDMNU_SFXVOLUME", "snd_sfxvolume", 0, 1, 0.05, 2
|
Slider "$SNDMNU_SFXVOLUME", "snd_sfxvolume", 0, 1, 0.05, 2
|
||||||
Option "$SNDMNU_MUSENABLED", "mus_enabled", "YesNo"
|
Option "$SNDMNU_MUSENABLED", "mus_enabled", "YesNo"
|
||||||
Slider "$SNDMNU_MUSICVOLUME", "mus_volume", 0, 1, 0.05, 2
|
Slider "$SNDMNU_MUSICVOLUME", "snd_musicvolume", 0, 1, 0.05, 2
|
||||||
Option "$SNDMNU_MENUSOUND", "menu_sounds", "OnOff" // placeholder until the slider can be made to work
|
Option "$SNDMNU_MENUSOUND", "menu_sounds", "OnOff" // placeholder until the slider can be made to work
|
||||||
//Slider "$SNDMNU_MENUVOLUME", "snd_menuvolume", 0, 1, 0.05, 2
|
//Slider "$SNDMNU_MENUVOLUME", "snd_menuvolume", 0, 1, 0.05, 2
|
||||||
StaticText " "
|
StaticText " "
|
||||||
|
|
Loading…
Reference in a new issue