From 66db8948665b6f79d27384df68933a6311e2e8e0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 23 Aug 2019 17:15:19 +0200 Subject: [PATCH] - split off all music code from s_sound.cpp --- src/CMakeLists.txt | 1 + src/console/c_console.cpp | 2 + src/d_main.cpp | 4 + src/d_net.cpp | 1 + src/g_level.cpp | 8 + src/g_levellocals.h | 7 +- src/intermission/intermission.cpp | 3 +- src/p_saveg.cpp | 1 + src/p_setup.cpp | 2 + src/playsim/a_dynlight.cpp | 1 - src/playsim/fragglescript/t_func.cpp | 1 + src/playsim/fragglescript/t_load.cpp | 1 + src/playsim/p_acs.cpp | 1 + src/playsim/p_user.cpp | 1 + src/posix/cocoa/i_main.mm | 1 + src/sound/backend/i_sound.cpp | 1 + src/sound/music/i_music.cpp | 1 + src/sound/music/music_midi_base.cpp | 1 + src/sound/s_advsound.cpp | 1 + src/sound/s_music.cpp | 872 +++++++++++++++++++++++++++ src/sound/s_music.h | 88 +++ src/sound/s_sound.cpp | 844 +++----------------------- src/sound/s_sound.h | 38 +- src/win32/i_main.cpp | 1 + src/win32/st_start.cpp | 1 + 25 files changed, 1075 insertions(+), 808 deletions(-) create mode 100644 src/sound/s_music.cpp create mode 100644 src/sound/s_music.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b8531384bb7..fda0c0007f5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1001,6 +1001,7 @@ set (PCH_SOURCES sound/s_environment.cpp sound/s_sndseq.cpp sound/s_sound.cpp + sound/s_music.cpp serializer.cpp scriptutil.cpp st_stuff.cpp diff --git a/src/console/c_console.cpp b/src/console/c_console.cpp index 4a0b2ab0dec..f15989a6ba5 100644 --- a/src/console/c_console.cpp +++ b/src/console/c_console.cpp @@ -64,6 +64,7 @@ #include "g_levellocals.h" #include "vm.h" #include "utf8.h" +#include "s_music.h" #include "gi.h" @@ -1268,6 +1269,7 @@ void C_FullConsole () gamestate = GS_FULLCONSOLE; primaryLevel->Music = ""; S_Start (); + S_StartMusic(); P_FreeLevelData (); } else diff --git a/src/d_main.cpp b/src/d_main.cpp index 1aa67e9b48f..44cb3d00608 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -102,6 +102,7 @@ #include "g_cvars.h" #include "r_data/r_vanillatrans.h" #include "atterm.h" +#include "s_music.h" EXTERN_CVAR(Bool, hud_althud) EXTERN_CVAR(Int, vr_mode) @@ -1034,6 +1035,7 @@ void D_DoomLoop () // Update display, next frame, with current state. I_StartTic (); D_Display (); + S_UpdateMusic(); if (wantToRestart) { wantToRestart = false; @@ -2459,6 +2461,7 @@ void D_DoomMain (void) if (!batchrun) Printf ("S_Init: Setting up sound.\n"); S_Init (); + S_InitMusic(); if (!batchrun) Printf ("ST_Init: Init startup screen.\n"); if (!restart) @@ -2752,6 +2755,7 @@ void D_DoomMain (void) R_DeinitTranslationTables(); // some tables are initialized from outside the translation code. gameinfo.~gameinfo_t(); new (&gameinfo) gameinfo_t; // Reset gameinfo + S_ShutdownMusic(); S_Shutdown(); // free all channels and delete playlist C_ClearAliases(); // CCMDs won't be reinitialized so these need to be deleted here DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods diff --git a/src/d_net.cpp b/src/d_net.cpp index bcf31530068..95e1cd75624 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -67,6 +67,7 @@ #include "i_system.h" #include "vm.h" #include "gstrings.h" +#include "s_music.h" EXTERN_CVAR (Int, disableautosave) EXTERN_CVAR (Int, autosavecount) diff --git a/src/g_level.cpp b/src/g_level.cpp index 6cf4adad1af..909e73cdb89 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -89,6 +89,7 @@ #include "actorinlines.h" #include "i_time.h" #include "p_maputl.h" +#include "s_music.h" void STAT_StartNewGame(const char *lev); void STAT_ChangeLevel(const char *newl, FLevelLocals *Level); @@ -2221,3 +2222,10 @@ int IsPointInMap(FLevelLocals *Level, double x, double y, double z) return true; } + +void FLevelLocals::SetMusic() +{ + if (cdtrack == 0 || !S_ChangeCDMusic(cdtrack, cdid)) + S_ChangeMusic(Music, musicorder); +} + diff --git a/src/g_levellocals.h b/src/g_levellocals.h index ff7749b37dc..ad29e78bd73 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -424,11 +424,8 @@ struct FLevelLocals return thinker; } - void SetMusic() - { - if (cdtrack == 0 || !S_ChangeCDMusic(cdtrack, cdid)) - S_ChangeMusic(Music, musicorder); - } + void SetMusic(); + TArray vertexes; TArray sectors; diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 290dae96e9a..fa09541317a 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -51,6 +51,7 @@ #include "g_levellocals.h" #include "utf8.h" #include "templates.h" +#include "s_music.h" FIntermissionDescriptorList IntermissionDescriptors; @@ -1100,4 +1101,4 @@ CCMD(measureintermissions) } } } -} \ No newline at end of file +} diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index b842e23b6f6..025ca18a4be 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -59,6 +59,7 @@ #include "r_sky.h" #include "version.h" #include "fragglescript/t_script.h" +#include "s_music.h" EXTERN_CVAR(Bool, save_formatted) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 714cb4eba95..814052a306b 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -76,6 +76,7 @@ #include "v_video.h" #include "fragglescript/t_script.h" #include "atterm.h" +#include "s_music.h" extern AActor *SpawnMapThing (int index, FMapThing *mthing, int position); @@ -407,6 +408,7 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) // Make sure all sounds are stopped before Z_FreeTags. S_Start(); + S_StartMusic(); // [RH] clear out the mid-screen message C_MidPrint(nullptr, nullptr); diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 9aea2689ae1..686230e0b28 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -989,4 +989,3 @@ void FLevelLocals::RecreateAllAttachedLights() } } } - diff --git a/src/playsim/fragglescript/t_func.cpp b/src/playsim/fragglescript/t_func.cpp index c0804ffba09..ee41d0d9c6b 100644 --- a/src/playsim/fragglescript/t_func.cpp +++ b/src/playsim/fragglescript/t_func.cpp @@ -51,6 +51,7 @@ #include "scriptutil.h" #include "vm.h" #include "a_lights.h" +#include "s_music.h" static FRandom pr_script("FScript"); diff --git a/src/playsim/fragglescript/t_load.cpp b/src/playsim/fragglescript/t_load.cpp index 7f5d8024f7c..8d2b5d6d770 100644 --- a/src/playsim/fragglescript/t_load.cpp +++ b/src/playsim/fragglescript/t_load.cpp @@ -34,6 +34,7 @@ #include "g_levellocals.h" #include "xlat/xlat.h" #include "maploader/maploader.h" +#include "s_music.h" class FScriptLoader { diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 23d7342bfaa..0cb77f19e87 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -75,6 +75,7 @@ #include "actorinlines.h" #include "types.h" #include "scriptutil.h" +#include "s_music.h" // P-codes for ACS scripts enum diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 6578c2c99a6..1ad68b098d8 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -91,6 +91,7 @@ #include "g_game.h" #include "v_video.h" #include "gstrings.h" +#include "s_music.h" static FRandom pr_skullpop ("SkullPop"); diff --git a/src/posix/cocoa/i_main.mm b/src/posix/cocoa/i_main.mm index 5b4ea31b7e1..90e03267f9b 100644 --- a/src/posix/cocoa/i_main.mm +++ b/src/posix/cocoa/i_main.mm @@ -46,6 +46,7 @@ #include "st_console.h" #include "version.h" #include "doomerrors.h" +#include "s_music.h" #define ZD_UNUSED(VARIABLE) ((void)(VARIABLE)) diff --git a/src/sound/backend/i_sound.cpp b/src/sound/backend/i_sound.cpp index c7aae60ec23..f2e57597067 100644 --- a/src/sound/backend/i_sound.cpp +++ b/src/sound/backend/i_sound.cpp @@ -48,6 +48,7 @@ #include "v_text.h" #include "c_cvars.h" #include "stats.h" +#include "s_music.h" EXTERN_CVAR (Float, snd_sfxvolume) EXTERN_CVAR (Float, snd_musicvolume) diff --git a/src/sound/music/i_music.cpp b/src/sound/music/i_music.cpp index f4b932695d0..320495b75f0 100644 --- a/src/sound/music/i_music.cpp +++ b/src/sound/music/i_music.cpp @@ -47,6 +47,7 @@ #include "stats.h" #include "timidity/timidity.h" #include "vm.h" +#include "s_music.h" diff --git a/src/sound/music/music_midi_base.cpp b/src/sound/music/music_midi_base.cpp index 7a3071fdfbc..13e2d55843f 100644 --- a/src/sound/music/music_midi_base.cpp +++ b/src/sound/music/music_midi_base.cpp @@ -36,6 +36,7 @@ #include "v_text.h" #include "menu/menu.h" +#include "s_music.h" static uint32_t nummididevices; static bool nummididevicesset; diff --git a/src/sound/s_advsound.cpp b/src/sound/s_advsound.cpp index b869473a2bb..8a7d10947a5 100644 --- a/src/sound/s_advsound.cpp +++ b/src/sound/s_advsound.cpp @@ -49,6 +49,7 @@ #include "vm.h" #include "i_system.h" #include "atterm.h" +#include "s_music.h" // MACROS ------------------------------------------------------------------ diff --git a/src/sound/s_music.cpp b/src/sound/s_music.cpp new file mode 100644 index 00000000000..f668b6afb54 --- /dev/null +++ b/src/sound/s_music.cpp @@ -0,0 +1,872 @@ +//----------------------------------------------------------------------------- +// +// Copyright 1993-1996 id Software +// Copyright 1999-2016 Randy Heit +// Copyright 2002-2016 Christoph Oelckers +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//----------------------------------------------------------------------------- +// +// DESCRIPTION: none +// +//----------------------------------------------------------------------------- + +/* For code that originates from ZDoom the following applies: +** +**--------------------------------------------------------------------------- +** +** 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 +#include +#ifdef _WIN32 +#include +#endif + +#include "i_system.h" +#include "i_sound.h" +#include "i_music.h" +#include "i_cd.h" +#include "s_sound.h" +#include "s_sndseq.h" +#include "s_playlist.h" +#include "c_dispatch.h" +#include "m_random.h" +#include "w_wad.h" +#include "p_local.h" +#include "doomstat.h" +#include "cmdlib.h" +#include "v_video.h" +#include "v_text.h" +#include "a_sharedglobal.h" +#include "gstrings.h" +#include "gi.h" +#include "po_man.h" +#include "serializer.h" +#include "d_player.h" +#include "g_levellocals.h" +#include "vm.h" +#include "g_game.h" +#include "atterm.h" +#include "s_music.h" + +// MACROS ------------------------------------------------------------------ + + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +extern float S_GetMusicVolume (const char *music); + +static void S_ActivatePlayList(bool goBack); + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +static bool MusicPaused; // whether music is paused +MusPlayingInfo mus_playing; // music currently being played +static FString LastSong; // last music that was played +static FPlayList *PlayList; + +DEFINE_GLOBAL_NAMED(mus_playing, musplaying); +DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, name); +DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, baseorder); +DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, loop); + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- +void S_ShutdownMusic (); + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// S_Init +// +// Initializes sound stuff, including volume. Sets channels, SFX and +// music volume, allocates channel buffer, and sets S_sfx lookup. +//========================================================================== + +void S_InitMusic () +{ + // no sounds are playing, and they are not paused + mus_playing.name = ""; + LastSong = ""; + mus_playing.handle = nullptr; + mus_playing.baseorder = 0; + MusicPaused = false; + atterm(S_ShutdownMusic); +} + +//========================================================================== +// +// S_Shutdown +// +//========================================================================== + +void S_ShutdownMusic () +{ + if (PlayList != nullptr) + { + delete PlayList; + PlayList = nullptr; + } + S_StopMusic (true); + mus_playing.name = ""; + LastSong = ""; +} + +//========================================================================== +// +// S_PauseSound +// +// Stop music and sound effects, during game PAUSE. +//========================================================================== + +void S_PauseMusic () +{ + if (mus_playing.handle && !MusicPaused) + { + mus_playing.handle->Pause(); + MusicPaused = true; + } +} + +//========================================================================== +// +// S_ResumeSound +// +// Resume music and sound effects, after game PAUSE. +//========================================================================== + +void S_ResumeMusic () +{ + if (mus_playing.handle && MusicPaused) + { + mus_playing.handle->Resume(); + MusicPaused = false; + } +} + +//========================================================================== +// +// S_UpdateSound +// +//========================================================================== + +void S_UpdateMusic () +{ + I_UpdateMusic(); + + // [RH] Update music and/or playlist. IsPlaying() must be called + // to attempt to reconnect to broken net streams and to advance the + // playlist when the current song finishes. + if (mus_playing.handle != nullptr && + !mus_playing.handle->IsPlaying() && + PlayList) + { + PlayList->Advance(); + S_ActivatePlayList(false); + } +} + +//========================================================================== +// +// S_Start +// +// Per level startup code. Kills playing sounds at start of level +// and starts new music. +//========================================================================== + +void S_StartMusic () +{ + // 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); + + // start new music for the level + MusicPaused = false; + + // Don't start the music if loading a savegame, because the music is stored there. + // Don't start the music if revisiting a level in a hub for the same reason. + if (!primaryLevel->IsReentering()) + { + primaryLevel->SetMusic(); + } +} + + +//========================================================================== +// +// 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)) + { + pos = goBack ? PlayList->Backup () : PlayList->Advance (); + if (pos == startpos) + { + delete PlayList; + PlayList = nullptr; + Printf ("Cannot play anything in the playlist.\n"); + return; + } + } +} + +//========================================================================== +// +// S_ChangeCDMusic +// +// Starts a CD track as music. +//========================================================================== + +bool S_ChangeCDMusic (int track, unsigned int id, bool looping) +{ + char temp[32]; + + if (id != 0) + { + mysnprintf (temp, countof(temp), ",CD,%d,%x", track, id); + } + else + { + mysnprintf (temp, countof(temp), ",CD,%d", track); + } + return S_ChangeMusic (temp, 0, looping); +} + +//========================================================================== +// +// S_StartMusic +// +// Starts some music with the given name. +//========================================================================== + +bool S_StartMusic (const char *m_id) +{ + return S_ChangeMusic (m_id, 0, false); +} + +//========================================================================== +// +// S_ChangeMusic +// +// Starts playing a music, possibly looping. +// +// [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) +{ + if (!force && PlayList) + { // 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, "*")) + { + if (gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL) + { + musicname = primaryLevel->Music; + order = primaryLevel->musicorder; + } + else + { + musicname = nullptr; + } + } + + if (musicname == nullptr || musicname[0] == 0) + { + // Don't choke if the map doesn't have a song attached + S_StopMusic (true); + mus_playing.name = ""; + LastSong = ""; + return true; + } + + 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 && + mus_playing.handle->m_Looping == looping) + { + if (order != mus_playing.baseorder) + { + if (mus_playing.handle->SetSubsong(order)) + { + mus_playing.baseorder = order; + } + } + else if (!mus_playing.handle->IsPlaying()) + { + mus_playing.handle->Play(looping, order); + } + 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 = I_RegisterCDSong (track, id); + } + else + { + int lumpnum = -1; + int length = 0; + MusInfo *handle = nullptr; + MidiDeviceSetting *devp = MidiDevices.CheckKey(musicname); + + // Strip off any leading file:// component. + if (strncmp(musicname, "file://", 7) == 0) + { + musicname += 7; + } + + FileReader reader; + if (!FileExists (musicname)) + { + if ((lumpnum = Wads.CheckNumForFullName (musicname, true, ns_music)) == -1) + { + Printf ("Music \"%s\" not found\n", musicname); + return false; + } + if (handle == nullptr) + { + if (Wads.LumpLength (lumpnum) == 0) + { + return false; + } + reader = Wads.ReopenLumpReader(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 + if (snd_musicvolume <= 0) + { + mus_playing.loop = looping; + mus_playing.name = musicname; + mus_playing.baseorder = order; + LastSong = musicname; + return true; + } + + // load & register it + if (handle != nullptr) + { + mus_playing.handle = handle; + } + else + { + mus_playing.handle = I_RegisterSong (reader, devp); + } + } + + mus_playing.loop = looping; + mus_playing.name = musicname; + mus_playing.baseorder = 0; + LastSong = ""; + + if (mus_playing.handle != 0) + { // play it + mus_playing.handle->Start(looping, S_GetMusicVolume (musicname), order); + mus_playing.baseorder = order; + return true; + } + return false; +} + +DEFINE_ACTION_FUNCTION(DObject, S_ChangeMusic) +{ + PARAM_PROLOGUE; + PARAM_STRING(music); + PARAM_INT(order); + PARAM_BOOL(looping); + PARAM_BOOL(force); + ACTION_RETURN_BOOL(S_ChangeMusic(music, order, looping, force)); +} + + +//========================================================================== +// +// S_RestartMusic +// +// Must only be called from snd_reset in i_sound.cpp! +//========================================================================== + +void S_RestartMusic () +{ + if (!LastSong.IsEmpty()) + { + FString song = LastSong; + LastSong = ""; + S_ChangeMusic (song, mus_playing.baseorder, mus_playing.loop, true); + } +} + +//========================================================================== +// +// S_MIDIDeviceChanged +// +//========================================================================== + +void S_MIDIDeviceChanged() +{ + if (mus_playing.handle != nullptr && mus_playing.handle->IsMIDI()) + { + mus_playing.handle->Stop(); + mus_playing.handle->Start(mus_playing.loop, -1, mus_playing.baseorder); + } +} + +//========================================================================== +// +// S_GetMusic +// +//========================================================================== + +int S_GetMusic (const char **name) +{ + int order; + + if (mus_playing.name.IsNotEmpty()) + { + *name = mus_playing.name; + order = mus_playing.baseorder; + } + else + { + *name = nullptr; + order = 0; + } + return order; +} + +//========================================================================== +// +// S_StopMusic +// +//========================================================================== + +void S_StopMusic (bool force) +{ + // [RH] Don't stop if a playlist is active. + if ((force || PlayList == nullptr) && !mus_playing.name.IsEmpty()) + { + if (mus_playing.handle != nullptr) + { + if (MusicPaused) + mus_playing.handle->Resume(); + + mus_playing.handle->Stop(); + delete mus_playing.handle; + mus_playing.handle = nullptr; + } + LastSong = mus_playing.name; + mus_playing.name = ""; + } +} + +//========================================================================== +// +// CCMD idmus +// +//========================================================================== + +CCMD (idmus) +{ + level_info_t *info; + FString map; + int l; + + if (!nomusic) + { + if (argv.argc() > 1) + { + if (gameinfo.flags & GI_MAPxx) + { + l = atoi (argv[1]); + if (l <= 99) + { + map = CalcMapName (0, l); + } + else + { + Printf ("%s\n", GStrings("STSTR_NOMUS")); + return; + } + } + else + { + map = CalcMapName (argv[1][0] - '0', argv[1][1] - '0'); + } + + if ( (info = FindLevelInfo (map)) ) + { + if (info->Music.IsNotEmpty()) + { + S_ChangeMusic (info->Music, info->musicorder); + Printf ("%s\n", GStrings("STSTR_MUS")); + } + } + else + { + Printf ("%s\n", GStrings("STSTR_NOMUS")); + } + } + } +} + +//========================================================================== +// +// CCMD changemus +// +//========================================================================== + +CCMD (changemus) +{ + if (!nomusic) + { + if (argv.argc() > 1) + { + if (PlayList) + { + delete PlayList; + PlayList = nullptr; + } + S_ChangeMusic (argv[1], argv.argc() > 2 ? atoi (argv[2]) : 0); + } + else + { + const char *currentmus = mus_playing.name.GetChars(); + if(currentmus != nullptr && *currentmus != 0) + { + Printf ("currently playing %s\n", currentmus); + } + else + { + Printf ("no music playing\n"); + } + } + } +} + +//========================================================================== +// +// CCMD stopmus +// +//========================================================================== + +CCMD (stopmus) +{ + if (PlayList) + { + delete PlayList; + PlayList = nullptr; + } + S_StopMusic (false); + LastSong = ""; // forget the last played song so that it won't get restarted if some volume changes occur +} + +//========================================================================== +// +// CCMD cd_play +// +// Plays a specified track, or the entire CD if no track is specified. +//========================================================================== + +CCMD (cd_play) +{ + char musname[16]; + + if (argv.argc() == 1) + { + strcpy (musname, ",CD,"); + } + else + { + mysnprintf (musname, countof(musname), ",CD,%d", atoi(argv[1])); + } + S_ChangeMusic (musname, 0, true); +} + +//========================================================================== +// +// CCMD cd_stop +// +//========================================================================== + +CCMD (cd_stop) +{ + CD_Stop (); +} + +//========================================================================== +// +// CCMD cd_eject +// +//========================================================================== + +CCMD (cd_eject) +{ + CD_Eject (); +} + +//========================================================================== +// +// CCMD cd_close +// +//========================================================================== + +CCMD (cd_close) +{ + CD_UnEject (); +} + +//========================================================================== +// +// CCMD cd_pause +// +//========================================================================== + +CCMD (cd_pause) +{ + CD_Pause (); +} + +//========================================================================== +// +// CCMD cd_resume +// +//========================================================================== + +CCMD (cd_resume) +{ + CD_Resume (); +} + +//========================================================================== +// +// CCMD playlist +// +//========================================================================== + +UNSAFE_CCMD (playlist) +{ + int argc = argv.argc(); + + if (argc < 2 || argc > 3) + { + Printf ("playlist [|shuffle]\n"); + } + else + { + if (PlayList != nullptr) + { + PlayList->ChangeList (argv[1]); + } + else + { + PlayList = new FPlayList (argv[1]); + } + if (PlayList->GetNumSongs () == 0) + { + delete PlayList; + PlayList = nullptr; + } + else + { + if (argc == 3) + { + if (stricmp (argv[2], "shuffle") == 0) + { + PlayList->Shuffle (); + } + else + { + PlayList->SetPosition (atoi (argv[2])); + } + } + S_ActivatePlayList (false); + } + } +} + +//========================================================================== +// +// CCMD playlistpos +// +//========================================================================== + +static bool CheckForPlaylist () +{ + if (PlayList == nullptr) + { + 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"); + } +} diff --git a/src/sound/s_music.h b/src/sound/s_music.h new file mode 100644 index 00000000000..3f10eb2b899 --- /dev/null +++ b/src/sound/s_music.h @@ -0,0 +1,88 @@ +//----------------------------------------------------------------------------- +// +// Copyright 1993-1996 id Software +// Copyright 1999-2016 Randy Heit +// Copyright 2002-2016 Christoph Oelckers +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//----------------------------------------------------------------------------- +// +// DESCRIPTION: +// The not so system specific sound interface. +// +//----------------------------------------------------------------------------- + + +#ifndef __S_MUSIC__ +#define __S_MUSIC__ + +#include "doomtype.h" +#include "i_soundinternal.h" + + +void S_ParseMusInfo(); + + +// +void S_InitMusic (); +void S_ShutdownMusic (); +void S_StartMusic (); + + +// Start music using +bool S_StartMusic (const char *music_name); + +// Start music using , and set whether looping +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_MIDIDeviceChanged(); + +int S_GetMusic (const char **name); + +// Stops the music for sure. +void S_StopMusic (bool force); + +// Stop and resume music, during game PAUSE. +void S_PauseMusic (); +void S_ResumeMusic (); + +// +// Updates music & sounds +// +void S_UpdateMusic (); + +struct MidiDeviceSetting +{ + int device; + FString args; + + MidiDeviceSetting() + { + device = MDEV_DEFAULT; + } +}; + +typedef TMap MusicAliasMap; +typedef TMap MidiDeviceMap; + +extern MusicAliasMap MusicAliases; +extern MidiDeviceMap MidiDevices; + +#endif diff --git a/src/sound/s_sound.cpp b/src/sound/s_sound.cpp index 16a47bd8f61..c368a975847 100644 --- a/src/sound/s_sound.cpp +++ b/src/sound/s_sound.cpp @@ -138,17 +138,8 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor); // PRIVATE DATA DEFINITIONS ------------------------------------------------ static bool SoundPaused; // whether sound is paused -static bool MusicPaused; // whether music is paused -MusPlayingInfo mus_playing; // music currently being played -static FString LastSong; // last music that was played -static FPlayList *PlayList; static int RestartEvictionsAt; // do not restart evicted channels before this time -DEFINE_GLOBAL_NAMED(mus_playing, musplaying); -DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, name); -DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, baseorder); -DEFINE_FIELD_X(MusPlayingInfo, MusPlayingInfo, loop); - // PUBLIC DATA DEFINITIONS ------------------------------------------------- int sfx_empty; @@ -333,9 +324,6 @@ void S_Init () { S_ReturnChannel(Channels); } - - // no sounds are playing, and they are not paused - MusicPaused = false; } //========================================================================== @@ -376,15 +364,6 @@ void S_Shutdown () delete chan; } FreeChannels = NULL; - - if (PlayList != NULL) - { - delete PlayList; - PlayList = NULL; - } - S_StopMusic (true); - mus_playing.name = ""; - LastSong = ""; } //========================================================================== @@ -413,58 +392,43 @@ void S_Start () LocalSndInfo = primaryLevel->info->SoundInfo; LocalSndSeq = primaryLevel->info->SndSeq; } - - bool parse_ss = false; - - // This level uses a different local SNDINFO + + bool parse_ss = false; + + // This level uses a different local SNDINFO if (LastLocalSndInfo.CompareNoCase(LocalSndInfo) != 0 || !primaryLevel->info) + { + // First delete the old sound list + for(unsigned i = 1; i < S_sfx.Size(); i++) { - // First delete the old sound list - for(unsigned i = 1; i < S_sfx.Size(); i++) - { - S_UnloadSound(&S_sfx[i]); - } - - // Parse the global SNDINFO - S_ParseSndInfo(true); - - if (LocalSndInfo.IsNotEmpty()) - { - // Now parse the local SNDINFO - int j = Wads.CheckNumForFullName(LocalSndInfo, true); - if (j>=0) S_AddLocalSndInfo(j); - } - - // Also reload the SNDSEQ if the SNDINFO was replaced! - parse_ss = true; - } - else if (LastLocalSndSeq.CompareNoCase(LocalSndSeq) != 0) - { - parse_ss = true; + S_UnloadSound(&S_sfx[i]); } - - if (parse_ss) + + // Parse the global SNDINFO + S_ParseSndInfo(true); + + if (LocalSndInfo.IsNotEmpty()) { - S_ParseSndSeq(LocalSndSeq.IsNotEmpty()? Wads.CheckNumForFullName(LocalSndSeq, true) : -1); + // Now parse the local SNDINFO + int j = Wads.CheckNumForFullName(LocalSndInfo, true); + if (j>=0) S_AddLocalSndInfo(j); } - LastLocalSndInfo = LocalSndInfo; - LastLocalSndSeq = LocalSndSeq; + // Also reload the SNDSEQ if the SNDINFO was replaced! + parse_ss = true; } - - // 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); - - // start new music for the level - MusicPaused = false; - - // Don't start the music if loading a savegame, because the music is stored there. - // Don't start the music if revisiting a level in a hub for the same reason. - if (!primaryLevel->IsReentering()) - { - primaryLevel->SetMusic(); + else if (LastLocalSndSeq.CompareNoCase(LocalSndSeq) != 0) + { + parse_ss = true; + } + + if (parse_ss) + { + S_ParseSndSeq(LocalSndSeq.IsNotEmpty()? Wads.CheckNumForFullName(LocalSndSeq, true) : -1); + } + + LastLocalSndInfo = LocalSndInfo; + LastLocalSndSeq = LocalSndSeq; } } @@ -2002,65 +1966,6 @@ bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id) return false; } -//========================================================================== -// -// S_PauseSound -// -// Stop music and sound effects, during game PAUSE. -//========================================================================== - -void S_PauseSound (bool notmusic, bool notsfx) -{ - if (!notmusic && mus_playing.handle && !MusicPaused) - { - mus_playing.handle->Pause(); - MusicPaused = true; - } - if (!notsfx) - { - SoundPaused = true; - GSnd->SetSfxPaused (true, 0); - } -} - -DEFINE_ACTION_FUNCTION(DObject, S_PauseSound) -{ - PARAM_PROLOGUE; - PARAM_BOOL(notmusic); - PARAM_BOOL(notsfx); - S_PauseSound(notmusic, notsfx); - return 0; -} - -//========================================================================== -// -// S_ResumeSound -// -// Resume music and sound effects, after game PAUSE. -//========================================================================== - -void S_ResumeSound (bool notsfx) -{ - if (mus_playing.handle && MusicPaused) - { - mus_playing.handle->Resume(); - MusicPaused = false; - } - if (!notsfx) - { - SoundPaused = false; - GSnd->SetSfxPaused (false, 0); - } -} - -DEFINE_ACTION_FUNCTION(DObject, S_ResumeSound) -{ - PARAM_PROLOGUE; - PARAM_BOOL(notsfx); - S_ResumeSound(notsfx); - return 0; -} - //========================================================================== // // S_SetSoundPaused @@ -2202,19 +2107,6 @@ void S_UpdateSounds (AActor *listenactor) FVector3 pos, vel; SoundListener listener; - I_UpdateMusic(); - - // [RH] Update music and/or playlist. IsPlaying() must be called - // to attempt to reconnect to broken net streams and to advance the - // playlist when the current song finishes. - if (mus_playing.handle != NULL && - !mus_playing.handle->IsPlaying() && - PlayList) - { - PlayList->Advance(); - S_ActivatePlayList(false); - } - // should never happen S_SetListener(listener, listenactor); @@ -2551,331 +2443,6 @@ void S_SerializeSounds(FSerializer &arc) GSnd->UpdateSounds(); } -//========================================================================== -// -// 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)) - { - pos = goBack ? PlayList->Backup () : PlayList->Advance (); - if (pos == startpos) - { - delete PlayList; - PlayList = NULL; - Printf ("Cannot play anything in the playlist.\n"); - return; - } - } -} - -//========================================================================== -// -// S_ChangeCDMusic -// -// Starts a CD track as music. -//========================================================================== - -bool S_ChangeCDMusic (int track, unsigned int id, bool looping) -{ - char temp[32]; - - if (id != 0) - { - mysnprintf (temp, countof(temp), ",CD,%d,%x", track, id); - } - else - { - mysnprintf (temp, countof(temp), ",CD,%d", track); - } - return S_ChangeMusic (temp, 0, looping); -} - -//========================================================================== -// -// S_StartMusic -// -// Starts some music with the given name. -//========================================================================== - -bool S_StartMusic (const char *m_id) -{ - return S_ChangeMusic (m_id, 0, false); -} - -//========================================================================== -// -// S_ChangeMusic -// -// Starts playing a music, possibly looping. -// -// [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) -{ - if (!force && PlayList) - { // Don't change if a playlist is active - return false; - } - - // allow specifying "*" as a placeholder to play the level's default music. - if (musicname != NULL && !strcmp(musicname, "*")) - { - if (gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL) - { - musicname = primaryLevel->Music; - order = primaryLevel->musicorder; - } - else - { - musicname = NULL; - } - } - - if (musicname == NULL || musicname[0] == 0) - { - // Don't choke if the map doesn't have a song attached - S_StopMusic (true); - mus_playing.name = ""; - LastSong = ""; - return true; - } - - 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 != NULL) - { - DEH_Music << "D_" << mus_string; - musicname = DEH_Music; - } - } - - FName *aliasp = MusicAliases.CheckKey(musicname); - if (aliasp != NULL) - { - if (*aliasp == NAME_None) - { - return true; // flagged to be ignored - } - musicname = aliasp->GetChars(); - } - - if (!mus_playing.name.IsEmpty() && - mus_playing.handle != NULL && - stricmp (mus_playing.name, musicname) == 0 && - mus_playing.handle->m_Looping == looping) - { - if (order != mus_playing.baseorder) - { - if (mus_playing.handle->SetSubsong(order)) - { - mus_playing.baseorder = order; - } - } - else if (!mus_playing.handle->IsPlaying()) - { - mus_playing.handle->Play(looping, order); - } - return true; - } - - if (strnicmp (musicname, ",CD,", 4) == 0) - { - int track = strtoul (musicname+4, NULL, 0); - const char *more = strchr (musicname+4, ','); - unsigned int id = 0; - - if (more != NULL) - { - id = strtoul (more+1, NULL, 16); - } - S_StopMusic (true); - mus_playing.handle = I_RegisterCDSong (track, id); - } - else - { - int lumpnum = -1; - int length = 0; - MusInfo *handle = NULL; - MidiDeviceSetting *devp = MidiDevices.CheckKey(musicname); - - // Strip off any leading file:// component. - if (strncmp(musicname, "file://", 7) == 0) - { - musicname += 7; - } - - FileReader reader; - if (!FileExists (musicname)) - { - if ((lumpnum = Wads.CheckNumForFullName (musicname, true, ns_music)) == -1) - { - Printf ("Music \"%s\" not found\n", musicname); - return false; - } - if (handle == NULL) - { - if (Wads.LumpLength (lumpnum) == 0) - { - return false; - } - reader = Wads.ReopenLumpReader(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 - if (snd_musicvolume <= 0) - { - mus_playing.loop = looping; - mus_playing.name = musicname; - mus_playing.baseorder = order; - LastSong = musicname; - return true; - } - - // load & register it - if (handle != NULL) - { - mus_playing.handle = handle; - } - else - { - mus_playing.handle = I_RegisterSong (reader, devp); - } - } - - mus_playing.loop = looping; - mus_playing.name = musicname; - mus_playing.baseorder = 0; - LastSong = ""; - - if (mus_playing.handle != 0) - { // play it - mus_playing.handle->Start(looping, S_GetMusicVolume (musicname), order); - mus_playing.baseorder = order; - return true; - } - return false; -} - -DEFINE_ACTION_FUNCTION(DObject, S_ChangeMusic) -{ - PARAM_PROLOGUE; - PARAM_STRING(music); - PARAM_INT(order); - PARAM_BOOL(looping); - PARAM_BOOL(force); - ACTION_RETURN_BOOL(S_ChangeMusic(music, order, looping, force)); -} - - -//========================================================================== -// -// S_RestartMusic -// -// Must only be called from snd_reset in i_sound.cpp! -//========================================================================== - -void S_RestartMusic () -{ - if (!LastSong.IsEmpty()) - { - FString song = LastSong; - LastSong = ""; - S_ChangeMusic (song, mus_playing.baseorder, mus_playing.loop, true); - } -} - -//========================================================================== -// -// S_MIDIDeviceChanged -// -//========================================================================== - -void S_MIDIDeviceChanged() -{ - if (mus_playing.handle != NULL && mus_playing.handle->IsMIDI()) - { - mus_playing.handle->Stop(); - mus_playing.handle->Start(mus_playing.loop, -1, mus_playing.baseorder); - } -} - -//========================================================================== -// -// S_GetMusic -// -//========================================================================== - -int S_GetMusic (const char **name) -{ - int order; - - if (mus_playing.name.IsNotEmpty()) - { - *name = mus_playing.name; - order = mus_playing.baseorder; - } - else - { - *name = NULL; - order = 0; - } - return order; -} - -//========================================================================== -// -// S_StopMusic -// -//========================================================================== - -void S_StopMusic (bool force) -{ - // [RH] Don't stop if a playlist is active. - if ((force || PlayList == NULL) && !mus_playing.name.IsEmpty()) - { - if (mus_playing.handle != NULL) - { - if (MusicPaused) - mus_playing.handle->Resume(); - - mus_playing.handle->Stop(); - delete mus_playing.handle; - mus_playing.handle = NULL; - } - LastSong = mus_playing.name; - mus_playing.name = ""; - } -} //========================================================================== // @@ -2927,352 +2494,101 @@ CCMD (loopsound) //========================================================================== // -// CCMD idmus +// CCMD cachesound // //========================================================================== -CCMD (idmus) +CCMD (cachesound) { - level_info_t *info; - FString map; - int l; - - if (!nomusic) + if (argv.argc() < 2) { - if (argv.argc() > 1) - { - if (gameinfo.flags & GI_MAPxx) - { - l = atoi (argv[1]); - if (l <= 99) - { - map = CalcMapName (0, l); - } - else - { - Printf ("%s\n", GStrings("STSTR_NOMUS")); - return; - } - } - else - { - map = CalcMapName (argv[1][0] - '0', argv[1][1] - '0'); - } - - if ( (info = FindLevelInfo (map)) ) - { - if (info->Music.IsNotEmpty()) - { - S_ChangeMusic (info->Music, info->musicorder); - Printf ("%s\n", GStrings("STSTR_MUS")); - } - } - else - { - Printf ("%s\n", GStrings("STSTR_NOMUS")); - } - } + Printf ("Usage: cachesound ...\n"); + return; } -} - -//========================================================================== -// -// CCMD changemus -// -//========================================================================== - -CCMD (changemus) -{ - if (!nomusic) + for (int i = 1; i < argv.argc(); ++i) { - if (argv.argc() > 1) - { - if (PlayList) - { - delete PlayList; - PlayList = NULL; - } - S_ChangeMusic (argv[1], argv.argc() > 2 ? atoi (argv[2]) : 0); - } - else + FSoundID sfxnum = argv[i]; + if (sfxnum != FSoundID(0)) { - const char *currentmus = mus_playing.name.GetChars(); - if(currentmus != NULL && *currentmus != 0) - { - Printf ("currently playing %s\n", currentmus); - } - else - { - Printf ("no music playing\n"); - } + S_CacheSound (&S_sfx[sfxnum]); } } } -//========================================================================== -// -// CCMD stopmus -// -//========================================================================== - -CCMD (stopmus) -{ - if (PlayList) - { - delete PlayList; - PlayList = NULL; - } - S_StopMusic (false); - LastSong = ""; // forget the last played song so that it won't get restarted if some volume changes occur -} - -//========================================================================== -// -// CCMD cd_play -// -// Plays a specified track, or the entire CD if no track is specified. -//========================================================================== - -CCMD (cd_play) -{ - char musname[16]; - - if (argv.argc() == 1) - { - strcpy (musname, ",CD,"); - } - else - { - mysnprintf (musname, countof(musname), ",CD,%d", atoi(argv[1])); - } - S_ChangeMusic (musname, 0, true); -} - -//========================================================================== -// -// CCMD cd_stop -// -//========================================================================== - -CCMD (cd_stop) -{ - CD_Stop (); -} - -//========================================================================== -// -// CCMD cd_eject -// -//========================================================================== - -CCMD (cd_eject) -{ - CD_Eject (); -} - -//========================================================================== -// -// CCMD cd_close -// -//========================================================================== - -CCMD (cd_close) -{ - CD_UnEject (); -} - -//========================================================================== -// -// CCMD cd_pause -// -//========================================================================== - -CCMD (cd_pause) -{ - CD_Pause (); -} - -//========================================================================== -// -// CCMD cd_resume -// -//========================================================================== - -CCMD (cd_resume) -{ - CD_Resume (); -} - -//========================================================================== -// -// CCMD playlist -// -//========================================================================== - -UNSAFE_CCMD (playlist) -{ - int argc = argv.argc(); - if (argc < 2 || argc > 3) - { - Printf ("playlist [|shuffle]\n"); - } - else +CCMD(listsoundchannels) +{ + FSoundChan *chan; + int count = 0; + for (chan = Channels; chan != NULL; chan = chan->NextChan) { - if (PlayList != NULL) - { - PlayList->ChangeList (argv[1]); - } - else - { - PlayList = new FPlayList (argv[1]); - } - if (PlayList->GetNumSongs () == 0) - { - delete PlayList; - PlayList = NULL; - } - else + if (!(chan->ChanFlags & CHAN_EVICTED)) { - if (argc == 3) - { - if (stricmp (argv[2], "shuffle") == 0) - { - PlayList->Shuffle (); - } - else - { - PlayList->SetPosition (atoi (argv[2])); - } - } - S_ActivatePlayList (false); - } - } -} + FVector3 chanorigin; -//========================================================================== -// -// CCMD playlistpos -// -//========================================================================== + CalcPosVel(chan, &chanorigin, NULL); -static bool CheckForPlaylist () -{ - if (PlayList == NULL) - { - Printf ("No playlist is playing.\n"); - return false; + Printf("%s at (%1.5f, %1.5f, %1.5f)\n", (const char*)chan->SoundID, chanorigin.X, chanorigin.Y, chanorigin.Z); + count++; + } } - return true; + Printf("%d sounds playing\n", count); } -CCMD (playlistpos) -{ - if (CheckForPlaylist() && argv.argc() > 1) - { - PlayList->SetPosition (atoi (argv[1]) - 1); - S_ActivatePlayList (false); - } -} +// intentionally moved here to keep the s_music include out of the rest of the file. //========================================================================== // -// CCMD playlistnext +// S_PauseSound // +// Stop music and sound effects, during game PAUSE. //========================================================================== +#include "s_music.h" -CCMD (playlistnext) +void S_PauseSound (bool notmusic, bool notsfx) { - if (CheckForPlaylist()) + if (!notmusic) { - PlayList->Advance (); - S_ActivatePlayList (false); + S_PauseMusic(); } -} - -//========================================================================== -// -// CCMD playlistprev -// -//========================================================================== - -CCMD (playlistprev) -{ - if (CheckForPlaylist()) + if (!notsfx) { - PlayList->Backup (); - S_ActivatePlayList (true); + SoundPaused = true; + GSnd->SetSfxPaused (true, 0); } } -//========================================================================== -// -// CCMD playliststatus -// -//========================================================================== - -CCMD (playliststatus) +DEFINE_ACTION_FUNCTION(DObject, S_PauseSound) { - if (CheckForPlaylist ()) - { - Printf ("Song %d of %d:\n%s\n", - PlayList->GetPosition () + 1, - PlayList->GetNumSongs (), - PlayList->GetSong (PlayList->GetPosition ())); - } + PARAM_PROLOGUE; + PARAM_BOOL(notmusic); + PARAM_BOOL(notsfx); + S_PauseSound(notmusic, notsfx); + return 0; } //========================================================================== // -// CCMD cachesound +// S_ResumeSound // +// Resume music and sound effects, after game PAUSE. //========================================================================== -CCMD (cachesound) +void S_ResumeSound (bool notsfx) { - if (argv.argc() < 2) - { - Printf ("Usage: cachesound ...\n"); - return; - } - for (int i = 1; i < argv.argc(); ++i) - { - FSoundID sfxnum = argv[i]; - if (sfxnum != FSoundID(0)) - { - S_CacheSound (&S_sfx[sfxnum]); - } - } -} - - -CCMD(listsoundchannels) -{ - FSoundChan *chan; - int count = 0; - for (chan = Channels; chan != NULL; chan = chan->NextChan) + S_ResumeMusic(); + if (!notsfx) { - if (!(chan->ChanFlags & CHAN_EVICTED)) - { - FVector3 chanorigin; - - CalcPosVel(chan, &chanorigin, NULL); - - Printf("%s at (%1.5f, %1.5f, %1.5f)\n", (const char*)chan->SoundID, chanorigin.X, chanorigin.Y, chanorigin.Z); - count++; - } + SoundPaused = false; + GSnd->SetSfxPaused (false, 0); } - Printf("%d sounds playing\n", count); } -CCMD(currentmusic) +DEFINE_ACTION_FUNCTION(DObject, S_ResumeSound) { - if (mus_playing.name.IsNotEmpty()) - { - Printf("Currently playing music '%s'\n", mus_playing.name.GetChars()); - } - else - { - Printf("Currently no music playing\n"); - } + PARAM_PROLOGUE; + PARAM_BOOL(notsfx); + S_ResumeSound(notsfx); + return 0; } + diff --git a/src/sound/s_sound.h b/src/sound/s_sound.h index 795a8b338f4..b86c4573eef 100644 --- a/src/sound/s_sound.h +++ b/src/sound/s_sound.h @@ -323,24 +323,6 @@ void S_RelinkSound (AActor *from, AActor *to); // Stores/retrieves playing channel information in an archive. void S_SerializeSounds(FSerializer &arc); -// Start music using -bool S_StartMusic (const char *music_name); - -// Start music using , and set whether looping -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_MIDIDeviceChanged(); - -int S_GetMusic (const char **name); - -// Stops the music for sure. -void S_StopMusic (bool force); - // Stop and resume music, during game PAUSE. void S_PauseSound (bool notmusic, bool notsfx); void S_ResumeSound (bool notsfx); @@ -377,7 +359,6 @@ void S_ShrinkPlayerSoundLists (); void S_UnloadSound (sfxinfo_t *sfx); sfxinfo_t *S_LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer = nullptr); unsigned int S_GetMSLength(FSoundID sound); -void S_ParseMusInfo(); bool S_ParseTimeTag(const char *tag, bool *as_samples, unsigned int *time); void A_PlaySound(AActor *self, int soundid, int channel, double volume, int looping, double attenuation, int local, double pitch); @@ -392,22 +373,5 @@ void S_SetEnvironment (const ReverbContainer *settings); ReverbContainer *S_FindEnvironment (const char *name); ReverbContainer *S_FindEnvironment (int id); void S_AddEnvironment (ReverbContainer *settings); - -struct MidiDeviceSetting -{ - int device; - FString args; - - MidiDeviceSetting() - { - device = MDEV_DEFAULT; - } -}; - -typedef TMap MusicAliasMap; -typedef TMap MidiDeviceMap; - -extern MusicAliasMap MusicAliases; -extern MidiDeviceMap MidiDevices; - + #endif diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 6d9c9f77138..482ff170fed 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -74,6 +74,7 @@ #include "i_system.h" #include "gstrings.h" #include "atterm.h" +#include "s_music.h" #include "stats.h" #include "st_start.h" diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index 036a7e142bd..9777601b77b 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -50,6 +50,7 @@ #include "m_argv.h" #include "d_main.h" #include "doomerrors.h" +#include "s_music.h" // MACROS ------------------------------------------------------------------