mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- separated the game-dependent music lookup parts from the core player.
This commit is contained in:
parent
4af96bab47
commit
f0534afde6
3 changed files with 177 additions and 111 deletions
|
@ -72,6 +72,7 @@
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
extern float S_GetMusicVolume (const char *music);
|
extern float S_GetMusicVolume (const char *music);
|
||||||
|
@ -86,11 +87,26 @@ static FPlayList PlayList;
|
||||||
float relative_volume = 1.f;
|
float relative_volume = 1.f;
|
||||||
float saved_relative_volume = 1.0f; // this could be used to implement an ACS FadeMusic function
|
float saved_relative_volume = 1.0f; // this could be used to implement an ACS FadeMusic function
|
||||||
|
|
||||||
|
static FileReader DefaultOpenMusic(const char* fn)
|
||||||
|
{
|
||||||
|
// This is the minimum needed to make the music system functional.
|
||||||
|
FileReader fr;
|
||||||
|
fr.OpenFile(fn);
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
static MusicCallbacks mus_cb = { nullptr, DefaultOpenMusic };
|
||||||
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
// CODE --------------------------------------------------------------------
|
// CODE --------------------------------------------------------------------
|
||||||
|
|
||||||
|
void S_SetMusicCallbacks(MusicCallbacks* cb)
|
||||||
|
{
|
||||||
|
mus_cb = *cb;
|
||||||
|
if (mus_cb.OpenMusic == nullptr) mus_cb.OpenMusic = DefaultOpenMusic; // without this we are dead in the water.
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -293,33 +309,24 @@ 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)
|
||||||
{
|
{
|
||||||
if (nomusic) return false; // skip the entire procedure if music is globally disabled.
|
if (nomusic) return false; // skip the entire procedure if music is globally disabled.
|
||||||
|
|
||||||
if (!force && PlayList.GetNumSongs())
|
if (!force && PlayList.GetNumSongs())
|
||||||
{ // Don't change if a playlist is active
|
{ // Don't change if a playlist is active
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Do game specific lookup.
|
||||||
// allow specifying "*" as a placeholder to play the level's default music.
|
FString musicname_;
|
||||||
if (musicname != nullptr && !strcmp(musicname, "*"))
|
if (mus_cb.LookupFileName)
|
||||||
{
|
{
|
||||||
if (gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL)
|
musicname_ = mus_cb.LookupFileName(musicname, order);
|
||||||
{
|
musicname = musicname_.GetChars();
|
||||||
musicname = primaryLevel->Music;
|
|
||||||
order = primaryLevel->musicorder;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
musicname = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (musicname == nullptr || musicname[0] == 0)
|
if (musicname == nullptr || musicname[0] == 0)
|
||||||
|
@ -330,35 +337,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 (musicname[0] == '$')
|
|
||||||
{
|
|
||||||
// handle dehacked replacement.
|
|
||||||
// Any music name defined this way needs to be prefixed with 'D_' because
|
|
||||||
// Doom.exe does not contain the prefix so these strings don't either.
|
|
||||||
const char * mus_string = GStrings[musicname+1];
|
|
||||||
if (mus_string != nullptr)
|
|
||||||
{
|
|
||||||
DEH_Music << "D_" << mus_string;
|
|
||||||
musicname = DEH_Music;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FName *aliasp = MusicAliases.CheckKey(musicname);
|
|
||||||
if (aliasp != nullptr)
|
|
||||||
{
|
|
||||||
if (*aliasp == NAME_None)
|
|
||||||
{
|
|
||||||
return true; // flagged to be ignored
|
|
||||||
}
|
|
||||||
musicname = aliasp->GetChars();
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
|
@ -380,79 +362,46 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strnicmp (musicname, ",CD,", 4) == 0)
|
int lumpnum = -1;
|
||||||
|
int length = 0;
|
||||||
|
ZMusic_MusicStream handle = nullptr;
|
||||||
|
MidiDeviceSetting* devp = MidiDevices.CheckKey(musicname);
|
||||||
|
|
||||||
|
// Strip off any leading file:// component.
|
||||||
|
if (strncmp(musicname, "file://", 7) == 0)
|
||||||
{
|
{
|
||||||
static bool warned = false;
|
musicname += 7;
|
||||||
if (!warned)
|
}
|
||||||
Printf(TEXTCOLOR_RED "CD Audio no longer supported\n");
|
|
||||||
warned = true;
|
// opening the music must be done by the game because it's different depending on the game's file system use.
|
||||||
return false;
|
FileReader reader = mus_cb.OpenMusic(musicname);
|
||||||
|
if (!reader.isOpen()) return false;
|
||||||
|
|
||||||
|
// shutdown old music
|
||||||
|
S_StopMusic(true);
|
||||||
|
|
||||||
|
// Just record it if volume is 0 or music was disabled
|
||||||
|
if (snd_musicvolume <= 0)
|
||||||
|
{
|
||||||
|
mus_playing.loop = looping;
|
||||||
|
mus_playing.name = musicname;
|
||||||
|
mus_playing.baseorder = order;
|
||||||
|
mus_playing.LastSong = musicname;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load & register it
|
||||||
|
if (handle != nullptr)
|
||||||
|
{
|
||||||
|
mus_playing.handle = handle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int lumpnum = -1;
|
auto mreader = GetMusicReader(reader); // this passes the file reader to the newly created wrapper.
|
||||||
int length = 0;
|
mus_playing.handle = ZMusic_OpenSong(mreader, devp ? (EMidiDevice)devp->device : MDEV_DEFAULT, devp ? devp->args.GetChars() : "");
|
||||||
ZMusic_MusicStream handle = nullptr;
|
if (mus_playing.handle == nullptr)
|
||||||
MidiDeviceSetting *devp = MidiDevices.CheckKey(musicname);
|
|
||||||
|
|
||||||
// Strip off any leading file:// component.
|
|
||||||
if (strncmp(musicname, "file://", 7) == 0)
|
|
||||||
{
|
{
|
||||||
musicname += 7;
|
Printf("Unable to load %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError());
|
||||||
}
|
|
||||||
|
|
||||||
FileReader reader;
|
|
||||||
if (!FileExists (musicname))
|
|
||||||
{
|
|
||||||
if ((lumpnum = fileSystem.CheckNumForFullName (musicname, true, ns_music)) == -1)
|
|
||||||
{
|
|
||||||
Printf ("Music \"%s\" not found\n", musicname);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (handle == nullptr)
|
|
||||||
{
|
|
||||||
if (fileSystem.FileLength (lumpnum) == 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
reader = fileSystem.ReopenFileReader(lumpnum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Load an external file.
|
|
||||||
if (!reader.OpenFile(musicname))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// shutdown old music
|
|
||||||
S_StopMusic (true);
|
|
||||||
|
|
||||||
// Just record it if volume is 0 or music was disabled
|
|
||||||
if (snd_musicvolume <= 0)
|
|
||||||
{
|
|
||||||
mus_playing.loop = looping;
|
|
||||||
mus_playing.name = musicname;
|
|
||||||
mus_playing.baseorder = order;
|
|
||||||
mus_playing.LastSong = musicname;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load & register it
|
|
||||||
if (handle != nullptr)
|
|
||||||
{
|
|
||||||
mus_playing.handle = handle;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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() : "");
|
|
||||||
if (mus_playing.handle == nullptr)
|
|
||||||
{
|
|
||||||
Printf("Unable to load %s: %s\n", mus_playing.name.GetChars(), ZMusic_GetLastError());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,6 +424,7 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// S_RestartMusic
|
// S_RestartMusic
|
||||||
|
|
|
@ -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();
|
||||||
|
@ -22,6 +31,8 @@ void S_ResetMusic ();
|
||||||
bool S_StartMusic (const char *music_name);
|
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_SetupMusic(const char* musicname, int order, bool looping, FileReader(*OpenMusic)(const char* filename));
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
void S_RestartMusic ();
|
void S_RestartMusic ();
|
||||||
|
|
|
@ -97,6 +97,105 @@ public:
|
||||||
void PrintSoundList();
|
void PrintSoundList();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// LookupMusic
|
||||||
|
//
|
||||||
|
// resolves aliases and special names
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static FString LookupMusic(const char* musicname, int& order)
|
||||||
|
{
|
||||||
|
if (strnicmp(musicname, ",CD,", 4) == 0)
|
||||||
|
{
|
||||||
|
static bool warned = false;
|
||||||
|
if (!warned)
|
||||||
|
Printf(TEXTCOLOR_RED "CD Audio no longer supported\n");
|
||||||
|
warned = true;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow specifying "*" as a placeholder to play the level's default music.
|
||||||
|
if (musicname != nullptr && !strcmp(musicname, "*"))
|
||||||
|
{
|
||||||
|
if (gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL)
|
||||||
|
{
|
||||||
|
musicname = primaryLevel->Music.GetChars();
|
||||||
|
order = primaryLevel->musicorder;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
musicname = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (musicname == nullptr || musicname[0] == 0)
|
||||||
|
{
|
||||||
|
// got nothing, return nothing.
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (*musicname == '/') musicname++;
|
||||||
|
|
||||||
|
FString DEH_Music;
|
||||||
|
if (musicname[0] == '$')
|
||||||
|
{
|
||||||
|
// handle dehacked replacement.
|
||||||
|
// Any music name defined this way needs to be prefixed with 'D_' because
|
||||||
|
// Doom.exe does not contain the prefix so these strings don't either.
|
||||||
|
const char* mus_string = GStrings[musicname + 1];
|
||||||
|
if (mus_string != nullptr)
|
||||||
|
{
|
||||||
|
DEH_Music << "D_" << mus_string;
|
||||||
|
musicname = DEH_Music;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FName* aliasp = MusicAliases.CheckKey(musicname);
|
||||||
|
if (aliasp != nullptr)
|
||||||
|
{
|
||||||
|
if (*aliasp == NAME_None)
|
||||||
|
{
|
||||||
|
order = -1;
|
||||||
|
return ""; // flagged to be ignored
|
||||||
|
}
|
||||||
|
musicname = aliasp->GetChars();
|
||||||
|
}
|
||||||
|
return musicname;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// OpenMusic
|
||||||
|
//
|
||||||
|
// opens a FileReader for the music - used as a callback to keep
|
||||||
|
// implementation details out of the core player.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static FileReader OpenMusic(const char* musicname)
|
||||||
|
{
|
||||||
|
FileReader reader;
|
||||||
|
if (!FileExists(musicname))
|
||||||
|
{
|
||||||
|
int lumpnum;
|
||||||
|
if ((lumpnum = fileSystem.CheckNumForFullName(musicname, true, ns_music)) == -1)
|
||||||
|
{
|
||||||
|
Printf("Music \"%s\" not found\n", musicname);
|
||||||
|
}
|
||||||
|
else if (fileSystem.FileLength(lumpnum) != 0)
|
||||||
|
{
|
||||||
|
reader = fileSystem.ReopenFileReader(lumpnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Load an external file.
|
||||||
|
reader.OpenFile(musicname);
|
||||||
|
}
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// S_Init
|
// S_Init
|
||||||
|
@ -107,6 +206,10 @@ public:
|
||||||
|
|
||||||
void S_Init()
|
void S_Init()
|
||||||
{
|
{
|
||||||
|
// Hook up the music player with the engine specific customizations.
|
||||||
|
static MusicCallbacks cb = { LookupMusic, OpenMusic };
|
||||||
|
S_SetMusicCallbacks(&cb);
|
||||||
|
|
||||||
// Must be up before I_InitSound.
|
// Must be up before I_InitSound.
|
||||||
if (!soundEngine)
|
if (!soundEngine)
|
||||||
{
|
{
|
||||||
|
@ -1438,3 +1541,5 @@ ADD_STAT (sound)
|
||||||
{
|
{
|
||||||
return GSnd->GatherStats ();
|
return GSnd->GatherStats ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue