From f0534afde6e7c596db42945a955bb6959753a515 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Apr 2020 18:24:00 +0200 Subject: [PATCH] - separated the game-dependent music lookup parts from the core player. --- src/sound/music/music.cpp | 172 ++++++++++++++------------------------ src/sound/music/s_music.h | 11 +++ src/sound/s_doomsound.cpp | 105 +++++++++++++++++++++++ 3 files changed, 177 insertions(+), 111 deletions(-) diff --git a/src/sound/music/music.cpp b/src/sound/music/music.cpp index e93e5eb18..356587f45 100644 --- a/src/sound/music/music.cpp +++ b/src/sound/music/music.cpp @@ -72,6 +72,7 @@ // MACROS ------------------------------------------------------------------ + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- extern float S_GetMusicVolume (const char *music); @@ -86,11 +87,26 @@ static FPlayList PlayList; float relative_volume = 1.f; 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 ------------------------------------------------- // 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 // -// 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,,[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 (!force && PlayList.GetNumSongs()) { // Don't change if a playlist is active return false; } - - // allow specifying "*" as a placeholder to play the level's default music. - if (musicname != nullptr && !strcmp(musicname, "*")) + // Do game specific lookup. + FString musicname_; + if (mus_cb.LookupFileName) { - if (gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL) - { - musicname = primaryLevel->Music; - order = primaryLevel->musicorder; - } - else - { - musicname = nullptr; - } + musicname_ = mus_cb.LookupFileName(musicname, order); + musicname = musicname_.GetChars(); } 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 = ""; 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() && mus_playing.handle != nullptr && - stricmp (mus_playing.name, musicname) == 0 && + stricmp(mus_playing.name, musicname) == 0 && ZMusic_IsLooping(mus_playing.handle) == zmusic_bool(looping)) { if (order != mus_playing.baseorder) @@ -380,79 +362,46 @@ bool S_ChangeMusic (const char *musicname, int order, bool looping, bool force) 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; - if (!warned) - Printf(TEXTCOLOR_RED "CD Audio no longer supported\n"); - warned = true; - return false; + musicname += 7; + } + + // 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; + + // 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 { - 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) + 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) { - musicname += 7; - } - - 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()); - } + 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; } + //========================================================================== // // S_RestartMusic diff --git a/src/sound/music/s_music.h b/src/sound/music/s_music.h index d58ca9ebd..707dc3cc2 100644 --- a/src/sound/music/s_music.h +++ b/src/sound/music/s_music.h @@ -7,6 +7,15 @@ #include "name.h" #include +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_PauseStream(bool pause); void S_StopStream(); @@ -22,6 +31,8 @@ void S_ResetMusic (); bool S_StartMusic (const char *music_name); // Start music using , 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); void S_RestartMusic (); diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index b3b256361..695c36a09 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -97,6 +97,105 @@ public: 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 @@ -107,6 +206,10 @@ public: 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. if (!soundEngine) { @@ -1438,3 +1541,5 @@ ADD_STAT (sound) { return GSnd->GatherStats (); } + +