mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-02-17 17:11:19 +00:00
- split off all music code from s_sound.cpp
This commit is contained in:
parent
1595bf30c6
commit
66db894866
25 changed files with 1078 additions and 811 deletions
|
@ -1001,6 +1001,7 @@ set (PCH_SOURCES
|
||||||
sound/s_environment.cpp
|
sound/s_environment.cpp
|
||||||
sound/s_sndseq.cpp
|
sound/s_sndseq.cpp
|
||||||
sound/s_sound.cpp
|
sound/s_sound.cpp
|
||||||
|
sound/s_music.cpp
|
||||||
serializer.cpp
|
serializer.cpp
|
||||||
scriptutil.cpp
|
scriptutil.cpp
|
||||||
st_stuff.cpp
|
st_stuff.cpp
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
|
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
|
@ -1268,6 +1269,7 @@ void C_FullConsole ()
|
||||||
gamestate = GS_FULLCONSOLE;
|
gamestate = GS_FULLCONSOLE;
|
||||||
primaryLevel->Music = "";
|
primaryLevel->Music = "";
|
||||||
S_Start ();
|
S_Start ();
|
||||||
|
S_StartMusic();
|
||||||
P_FreeLevelData ();
|
P_FreeLevelData ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -102,6 +102,7 @@
|
||||||
#include "g_cvars.h"
|
#include "g_cvars.h"
|
||||||
#include "r_data/r_vanillatrans.h"
|
#include "r_data/r_vanillatrans.h"
|
||||||
#include "atterm.h"
|
#include "atterm.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, hud_althud)
|
EXTERN_CVAR(Bool, hud_althud)
|
||||||
EXTERN_CVAR(Int, vr_mode)
|
EXTERN_CVAR(Int, vr_mode)
|
||||||
|
@ -1034,6 +1035,7 @@ void D_DoomLoop ()
|
||||||
// Update display, next frame, with current state.
|
// Update display, next frame, with current state.
|
||||||
I_StartTic ();
|
I_StartTic ();
|
||||||
D_Display ();
|
D_Display ();
|
||||||
|
S_UpdateMusic();
|
||||||
if (wantToRestart)
|
if (wantToRestart)
|
||||||
{
|
{
|
||||||
wantToRestart = false;
|
wantToRestart = false;
|
||||||
|
@ -2459,6 +2461,7 @@ void D_DoomMain (void)
|
||||||
|
|
||||||
if (!batchrun) Printf ("S_Init: Setting up sound.\n");
|
if (!batchrun) Printf ("S_Init: Setting up sound.\n");
|
||||||
S_Init ();
|
S_Init ();
|
||||||
|
S_InitMusic();
|
||||||
|
|
||||||
if (!batchrun) Printf ("ST_Init: Init startup screen.\n");
|
if (!batchrun) Printf ("ST_Init: Init startup screen.\n");
|
||||||
if (!restart)
|
if (!restart)
|
||||||
|
@ -2752,6 +2755,7 @@ void D_DoomMain (void)
|
||||||
R_DeinitTranslationTables(); // some tables are initialized from outside the translation code.
|
R_DeinitTranslationTables(); // some tables are initialized from outside the translation code.
|
||||||
gameinfo.~gameinfo_t();
|
gameinfo.~gameinfo_t();
|
||||||
new (&gameinfo) gameinfo_t; // Reset gameinfo
|
new (&gameinfo) gameinfo_t; // Reset gameinfo
|
||||||
|
S_ShutdownMusic();
|
||||||
S_Shutdown(); // free all channels and delete playlist
|
S_Shutdown(); // free all channels and delete playlist
|
||||||
C_ClearAliases(); // CCMDs won't be reinitialized so these need to be deleted here
|
C_ClearAliases(); // CCMDs won't be reinitialized so these need to be deleted here
|
||||||
DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods
|
DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
EXTERN_CVAR (Int, disableautosave)
|
EXTERN_CVAR (Int, disableautosave)
|
||||||
EXTERN_CVAR (Int, autosavecount)
|
EXTERN_CVAR (Int, autosavecount)
|
||||||
|
|
|
@ -89,6 +89,7 @@
|
||||||
#include "actorinlines.h"
|
#include "actorinlines.h"
|
||||||
#include "i_time.h"
|
#include "i_time.h"
|
||||||
#include "p_maputl.h"
|
#include "p_maputl.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
void STAT_StartNewGame(const char *lev);
|
void STAT_StartNewGame(const char *lev);
|
||||||
void STAT_ChangeLevel(const char *newl, FLevelLocals *Level);
|
void STAT_ChangeLevel(const char *newl, FLevelLocals *Level);
|
||||||
|
@ -2221,3 +2222,10 @@ int IsPointInMap(FLevelLocals *Level, double x, double y, double z)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FLevelLocals::SetMusic()
|
||||||
|
{
|
||||||
|
if (cdtrack == 0 || !S_ChangeCDMusic(cdtrack, cdid))
|
||||||
|
S_ChangeMusic(Music, musicorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -424,11 +424,8 @@ public:
|
||||||
return thinker;
|
return thinker;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetMusic()
|
void SetMusic();
|
||||||
{
|
|
||||||
if (cdtrack == 0 || !S_ChangeCDMusic(cdtrack, cdid))
|
|
||||||
S_ChangeMusic(Music, musicorder);
|
|
||||||
}
|
|
||||||
|
|
||||||
TArray<vertex_t> vertexes;
|
TArray<vertex_t> vertexes;
|
||||||
TArray<sector_t> sectors;
|
TArray<sector_t> sectors;
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
FIntermissionDescriptorList IntermissionDescriptors;
|
FIntermissionDescriptorList IntermissionDescriptors;
|
||||||
|
|
||||||
|
@ -1100,4 +1101,4 @@ CCMD(measureintermissions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
#include "r_sky.h"
|
#include "r_sky.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "fragglescript/t_script.h"
|
#include "fragglescript/t_script.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Bool, save_formatted)
|
EXTERN_CVAR(Bool, save_formatted)
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "fragglescript/t_script.h"
|
#include "fragglescript/t_script.h"
|
||||||
#include "atterm.h"
|
#include "atterm.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
extern AActor *SpawnMapThing (int index, FMapThing *mthing, int position);
|
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.
|
// Make sure all sounds are stopped before Z_FreeTags.
|
||||||
S_Start();
|
S_Start();
|
||||||
|
S_StartMusic();
|
||||||
|
|
||||||
// [RH] clear out the mid-screen message
|
// [RH] clear out the mid-screen message
|
||||||
C_MidPrint(nullptr, nullptr);
|
C_MidPrint(nullptr, nullptr);
|
||||||
|
|
|
@ -989,4 +989,3 @@ void FLevelLocals::RecreateAllAttachedLights()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "scriptutil.h"
|
#include "scriptutil.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "a_lights.h"
|
#include "a_lights.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
static FRandom pr_script("FScript");
|
static FRandom pr_script("FScript");
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "xlat/xlat.h"
|
#include "xlat/xlat.h"
|
||||||
#include "maploader/maploader.h"
|
#include "maploader/maploader.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
class FScriptLoader
|
class FScriptLoader
|
||||||
{
|
{
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
#include "actorinlines.h"
|
#include "actorinlines.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "scriptutil.h"
|
#include "scriptutil.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
// P-codes for ACS scripts
|
// P-codes for ACS scripts
|
||||||
enum
|
enum
|
||||||
|
|
|
@ -91,6 +91,7 @@
|
||||||
#include "g_game.h"
|
#include "g_game.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
static FRandom pr_skullpop ("SkullPop");
|
static FRandom pr_skullpop ("SkullPop");
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "st_console.h"
|
#include "st_console.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
|
|
||||||
#define ZD_UNUSED(VARIABLE) ((void)(VARIABLE))
|
#define ZD_UNUSED(VARIABLE) ((void)(VARIABLE))
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
EXTERN_CVAR (Float, snd_sfxvolume)
|
EXTERN_CVAR (Float, snd_sfxvolume)
|
||||||
EXTERN_CVAR (Float, snd_musicvolume)
|
EXTERN_CVAR (Float, snd_musicvolume)
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "timidity/timidity.h"
|
#include "timidity/timidity.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
static uint32_t nummididevices;
|
static uint32_t nummididevices;
|
||||||
static bool nummididevicesset;
|
static bool nummididevicesset;
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "atterm.h"
|
#include "atterm.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
872
src/sound/s_music.cpp
Normal file
872
src/sound/s_music.cpp
Normal file
|
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <io.h>
|
||||||
|
#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,<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)
|
||||||
|
{
|
||||||
|
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 <playlist.m3u> [<position>|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");
|
||||||
|
}
|
||||||
|
}
|
88
src/sound/s_music.h
Normal file
88
src/sound/s_music.h
Normal file
|
@ -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 <music_name>
|
||||||
|
bool S_StartMusic (const char *music_name);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// 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<FName, FName> MusicAliasMap;
|
||||||
|
typedef TMap<FName, MidiDeviceSetting> MidiDeviceMap;
|
||||||
|
|
||||||
|
extern MusicAliasMap MusicAliases;
|
||||||
|
extern MidiDeviceMap MidiDevices;
|
||||||
|
|
||||||
|
#endif
|
|
@ -138,17 +138,8 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor);
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
static bool SoundPaused; // whether sound is paused
|
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
|
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 -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
int sfx_empty;
|
int sfx_empty;
|
||||||
|
@ -333,9 +324,6 @@ void S_Init ()
|
||||||
{
|
{
|
||||||
S_ReturnChannel(Channels);
|
S_ReturnChannel(Channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// no sounds are playing, and they are not paused
|
|
||||||
MusicPaused = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -376,15 +364,6 @@ void S_Shutdown ()
|
||||||
delete chan;
|
delete chan;
|
||||||
}
|
}
|
||||||
FreeChannels = NULL;
|
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;
|
LocalSndInfo = primaryLevel->info->SoundInfo;
|
||||||
LocalSndSeq = primaryLevel->info->SndSeq;
|
LocalSndSeq = primaryLevel->info->SndSeq;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_ss = false;
|
bool parse_ss = false;
|
||||||
|
|
||||||
// This level uses a different local SNDINFO
|
// This level uses a different local SNDINFO
|
||||||
if (LastLocalSndInfo.CompareNoCase(LocalSndInfo) != 0 || !primaryLevel->info)
|
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
|
S_UnloadSound(&S_sfx[i]);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse_ss)
|
|
||||||
{
|
|
||||||
S_ParseSndSeq(LocalSndSeq.IsNotEmpty()? Wads.CheckNumForFullName(LocalSndSeq, true) : -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LastLocalSndInfo = LocalSndInfo;
|
// Parse the global SNDINFO
|
||||||
LastLocalSndSeq = LocalSndSeq;
|
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)
|
||||||
// stop the old music if it has been paused.
|
{
|
||||||
// This ensures that the new music is started from the beginning
|
parse_ss = true;
|
||||||
// if it's the same as the last one and it has been paused.
|
}
|
||||||
if (MusicPaused) S_StopMusic(true);
|
|
||||||
|
if (parse_ss)
|
||||||
// start new music for the level
|
{
|
||||||
MusicPaused = false;
|
S_ParseSndSeq(LocalSndSeq.IsNotEmpty()? Wads.CheckNumForFullName(LocalSndSeq, true) : -1);
|
||||||
|
}
|
||||||
// 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.
|
LastLocalSndInfo = LocalSndInfo;
|
||||||
if (!primaryLevel->IsReentering())
|
LastLocalSndSeq = LocalSndSeq;
|
||||||
{
|
|
||||||
primaryLevel->SetMusic();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2002,65 +1966,6 @@ bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id)
|
||||||
return false;
|
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
|
// S_SetSoundPaused
|
||||||
|
@ -2202,19 +2107,6 @@ void S_UpdateSounds (AActor *listenactor)
|
||||||
FVector3 pos, vel;
|
FVector3 pos, vel;
|
||||||
SoundListener listener;
|
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
|
// should never happen
|
||||||
S_SetListener(listener, listenactor);
|
S_SetListener(listener, listenactor);
|
||||||
|
|
||||||
|
@ -2551,331 +2443,6 @@ void S_SerializeSounds(FSerializer &arc)
|
||||||
GSnd->UpdateSounds();
|
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,<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)
|
|
||||||
{
|
|
||||||
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 = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -2925,303 +2492,6 @@ CCMD (loopsound)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// 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 = NULL;
|
|
||||||
}
|
|
||||||
S_ChangeMusic (argv[1], argv.argc() > 2 ? atoi (argv[2]) : 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char *currentmus = mus_playing.name.GetChars();
|
|
||||||
if(currentmus != NULL && *currentmus != 0)
|
|
||||||
{
|
|
||||||
Printf ("currently playing %s\n", currentmus);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Printf ("no music playing\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// 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 <playlist.m3u> [<position>|shuffle]\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (PlayList != NULL)
|
|
||||||
{
|
|
||||||
PlayList->ChangeList (argv[1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PlayList = new FPlayList (argv[1]);
|
|
||||||
}
|
|
||||||
if (PlayList->GetNumSongs () == 0)
|
|
||||||
{
|
|
||||||
delete PlayList;
|
|
||||||
PlayList = NULL;
|
|
||||||
}
|
|
||||||
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 == NULL)
|
|
||||||
{
|
|
||||||
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 cachesound <sound name>
|
// CCMD cachesound <sound name>
|
||||||
|
@ -3265,14 +2535,60 @@ CCMD(listsoundchannels)
|
||||||
Printf("%d sounds playing\n", count);
|
Printf("%d sounds playing\n", count);
|
||||||
}
|
}
|
||||||
|
|
||||||
CCMD(currentmusic)
|
// intentionally moved here to keep the s_music include out of the rest of the file.
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// S_PauseSound
|
||||||
|
//
|
||||||
|
// Stop music and sound effects, during game PAUSE.
|
||||||
|
//==========================================================================
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
|
void S_PauseSound (bool notmusic, bool notsfx)
|
||||||
{
|
{
|
||||||
if (mus_playing.name.IsNotEmpty())
|
if (!notmusic)
|
||||||
{
|
{
|
||||||
Printf("Currently playing music '%s'\n", mus_playing.name.GetChars());
|
S_PauseMusic();
|
||||||
}
|
}
|
||||||
else
|
if (!notsfx)
|
||||||
{
|
{
|
||||||
Printf("Currently no music playing\n");
|
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)
|
||||||
|
{
|
||||||
|
S_ResumeMusic();
|
||||||
|
if (!notsfx)
|
||||||
|
{
|
||||||
|
SoundPaused = false;
|
||||||
|
GSnd->SetSfxPaused (false, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DObject, S_ResumeSound)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_BOOL(notsfx);
|
||||||
|
S_ResumeSound(notsfx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -323,24 +323,6 @@ void S_RelinkSound (AActor *from, AActor *to);
|
||||||
// Stores/retrieves playing channel information in an archive.
|
// Stores/retrieves playing channel information in an archive.
|
||||||
void S_SerializeSounds(FSerializer &arc);
|
void S_SerializeSounds(FSerializer &arc);
|
||||||
|
|
||||||
// Start music using <music_name>
|
|
||||||
bool S_StartMusic (const char *music_name);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// 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.
|
// Stop and resume music, during game PAUSE.
|
||||||
void S_PauseSound (bool notmusic, bool notsfx);
|
void S_PauseSound (bool notmusic, bool notsfx);
|
||||||
void S_ResumeSound (bool notsfx);
|
void S_ResumeSound (bool notsfx);
|
||||||
|
@ -377,7 +359,6 @@ void S_ShrinkPlayerSoundLists ();
|
||||||
void S_UnloadSound (sfxinfo_t *sfx);
|
void S_UnloadSound (sfxinfo_t *sfx);
|
||||||
sfxinfo_t *S_LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer = nullptr);
|
sfxinfo_t *S_LoadSound(sfxinfo_t *sfx, FSoundLoadBuffer *pBuffer = nullptr);
|
||||||
unsigned int S_GetMSLength(FSoundID sound);
|
unsigned int S_GetMSLength(FSoundID sound);
|
||||||
void S_ParseMusInfo();
|
|
||||||
bool S_ParseTimeTag(const char *tag, bool *as_samples, unsigned int *time);
|
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);
|
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 (const char *name);
|
||||||
ReverbContainer *S_FindEnvironment (int id);
|
ReverbContainer *S_FindEnvironment (int id);
|
||||||
void S_AddEnvironment (ReverbContainer *settings);
|
void S_AddEnvironment (ReverbContainer *settings);
|
||||||
|
|
||||||
struct MidiDeviceSetting
|
|
||||||
{
|
|
||||||
int device;
|
|
||||||
FString args;
|
|
||||||
|
|
||||||
MidiDeviceSetting()
|
|
||||||
{
|
|
||||||
device = MDEV_DEFAULT;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef TMap<FName, FName> MusicAliasMap;
|
|
||||||
typedef TMap<FName, MidiDeviceSetting> MidiDeviceMap;
|
|
||||||
|
|
||||||
extern MusicAliasMap MusicAliases;
|
|
||||||
extern MidiDeviceMap MidiDevices;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -74,6 +74,7 @@
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "gstrings.h"
|
#include "gstrings.h"
|
||||||
#include "atterm.h"
|
#include "atterm.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "st_start.h"
|
#include "st_start.h"
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "d_main.h"
|
#include "d_main.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
|
#include "s_music.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue