Refactor all calls to S_PlayMusic.

This allows as much of the control flow as possible to fail gracefully without interruping currently playing music.

git-svn-id: https://svn.eduke32.com/eduke32@6619 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
hendricks266 2018-01-29 11:13:43 +00:00
parent 254b822003
commit d792054ce2
12 changed files with 153 additions and 93 deletions

View file

@ -4480,14 +4480,9 @@ extern int G_StartRTS(int lumpNum, int localPlayer)
return 0; return 0;
} }
void G_StartMusic(void) void G_PrintCurrentMusic(void)
{ {
int const levelNum = g_musicIndex; Bsnprintf(apStrings[QUOTE_MUSIC], MAXQUOTELEN, "Playing %s", g_mapInfo[g_musicIndex].musicfn);
Bassert(g_mapInfo[levelNum].musicfn != NULL);
S_PlayMusic(g_mapInfo[levelNum].musicfn);
Bsnprintf(apStrings[QUOTE_MUSIC], MAXQUOTELEN, "Playing %s", g_mapInfo[levelNum].musicfn);
P_DoQuote(QUOTE_MUSIC, g_player[myconnectindex].ps); P_DoQuote(QUOTE_MUSIC, g_player[myconnectindex].ps);
} }
@ -4721,17 +4716,18 @@ void G_HandleLocalKeys(void)
{ {
if (ridiculeNum == 5 && g_player[myconnectindex].ps->fta > 0 && g_player[myconnectindex].ps->ftq == QUOTE_MUSIC) if (ridiculeNum == 5 && g_player[myconnectindex].ps->fta > 0 && g_player[myconnectindex].ps->ftq == QUOTE_MUSIC)
{ {
const int32_t maxi = VOLUMEALL ? MUS_FIRST_SPECIAL : 6; const unsigned int maxi = VOLUMEALL ? MUS_FIRST_SPECIAL : 6;
unsigned int MyMusicIndex = g_musicIndex;
do do
{ {
g_musicIndex++; ++MyMusicIndex;
if (g_musicIndex >= maxi) if (MyMusicIndex >= maxi)
g_musicIndex = 0; MyMusicIndex = 0;
} }
while (g_mapInfo[g_musicIndex].musicfn == NULL); while (S_TryPlayLevelMusic(MyMusicIndex));
G_StartMusic(); G_PrintCurrentMusic();
return; return;
} }

View file

@ -555,7 +555,7 @@ static inline int G_GetViewscreenSizeShift(const uspritetype *tspr)
#endif #endif
} }
extern void G_StartMusic(void); extern void G_PrintCurrentMusic(void);
#ifdef LUNATIC #ifdef LUNATIC
void El_SetCON(const char *conluacode); void El_SetCON(const char *conluacode);

View file

@ -1139,14 +1139,7 @@ static int G_StartTrackSlot(int const volumeNum, int const levelNum)
{ {
int trackNum = MAXLEVELS*volumeNum + levelNum; int trackNum = MAXLEVELS*volumeNum + levelNum;
if (g_mapInfo[trackNum].musicfn != NULL) return S_TryPlaySpecialMusic(trackNum);
{
// Only set g_musicIndex on success.
g_musicIndex = trackNum;
S_PlayMusic(g_mapInfo[trackNum].musicfn);
return 0;
}
} }
return 1; return 1;

View file

@ -635,13 +635,6 @@ int32_t MIDI_PlaySong(char *song, int32_t loopflag)
track *CurrentTrack; track *CurrentTrack;
char *ptr; char *ptr;
if (_MIDI_SongLoaded)
MIDI_StopSong();
MPU_Init(MUSIC_SoundDevice);
_MIDI_Loop = loopflag;
if (_MIDI_Funcs == NULL) if (_MIDI_Funcs == NULL)
return MIDI_NullMidiModule; return MIDI_NullMidiModule;
@ -652,12 +645,12 @@ int32_t MIDI_PlaySong(char *song, int32_t loopflag)
headersize = _MIDI_ReadNumber(song, 4); headersize = _MIDI_ReadNumber(song, 4);
song += 4; song += 4;
format = _MIDI_ReadNumber(song, 2); format = _MIDI_ReadNumber(song, 2);
_MIDI_NumTracks = _MIDI_ReadNumber(song + 2, 2); int32_t My_MIDI_NumTracks = _MIDI_ReadNumber(song + 2, 2);
_MIDI_Division = _MIDI_ReadNumber(song + 4, 2); int32_t My_MIDI_Division = _MIDI_ReadNumber(song + 4, 2);
if (_MIDI_Division < 0) if (My_MIDI_Division < 0)
{ {
// If a SMPTE time division is given, just set to 96 so no errors occur // If a SMPTE time division is given, just set to 96 so no errors occur
_MIDI_Division = 96; My_MIDI_Division = 96;
} }
if (format > MAX_FORMAT) if (format > MAX_FORMAT)
@ -665,22 +658,22 @@ int32_t MIDI_PlaySong(char *song, int32_t loopflag)
ptr = song + headersize; ptr = song + headersize;
if (_MIDI_NumTracks == 0) if (My_MIDI_NumTracks == 0)
return MIDI_NoTracks; return MIDI_NoTracks;
_MIDI_TrackMemSize = _MIDI_NumTracks * sizeof(track); int32_t My_MIDI_TrackMemSize = My_MIDI_NumTracks * sizeof(track);
_MIDI_TrackPtr = (track *)Xmalloc(_MIDI_TrackMemSize); track * My_MIDI_TrackPtr = (track *)Xmalloc(My_MIDI_TrackMemSize);
CurrentTrack = _MIDI_TrackPtr; CurrentTrack = My_MIDI_TrackPtr;
numtracks = _MIDI_NumTracks; numtracks = My_MIDI_NumTracks;
while (numtracks--) while (numtracks--)
{ {
if (B_UNBUF32(ptr) != MIDI_TRACK_SIGNATURE) if (B_UNBUF32(ptr) != MIDI_TRACK_SIGNATURE)
{ {
DO_FREE_AND_NULL(_MIDI_TrackPtr); DO_FREE_AND_NULL(My_MIDI_TrackPtr);
_MIDI_TrackMemSize = 0; My_MIDI_TrackMemSize = 0;
return MIDI_InvalidTrack; return MIDI_InvalidTrack;
} }
@ -692,6 +685,19 @@ int32_t MIDI_PlaySong(char *song, int32_t loopflag)
CurrentTrack++; CurrentTrack++;
} }
// at this point we know song load is successful
if (_MIDI_SongLoaded)
MIDI_StopSong();
MPU_Init(MUSIC_SoundDevice);
_MIDI_Loop = loopflag;
_MIDI_NumTracks = My_MIDI_NumTracks;
_MIDI_Division = My_MIDI_Division;
_MIDI_TrackMemSize = My_MIDI_TrackMemSize;
_MIDI_TrackPtr = My_MIDI_TrackPtr;
_MIDI_InitEMIDI(); _MIDI_InitEMIDI();
_MIDI_ResetTracks(); _MIDI_ResetTracks();

View file

@ -91,7 +91,7 @@ int32_t MUSIC_StopSong(void)
int32_t MUSIC_PlaySong(char *song, int32_t loopflag) int32_t MUSIC_PlaySong(char *song, int32_t loopflag)
{ {
MUSIC_StopSong(); MUSIC_SetErrorCode(MUSIC_Ok)
if (MIDI_PlaySong(song, loopflag) != MIDI_Ok) if (MIDI_PlaySong(song, loopflag) != MIDI_Ok)
{ {

View file

@ -400,10 +400,9 @@ static int32_t osdcmd_music(osdfuncparm_t const * const parm)
return OSDCMD_OK; return OSDCMD_OK;
} }
if (g_mapInfo[sel].musicfn != NULL) if (!S_TryPlayLevelMusic(sel))
{ {
g_musicIndex = sel; G_PrintCurrentMusic();
G_StartMusic();
} }
else else
{ {

View file

@ -423,10 +423,7 @@ void G_CacheMapData(void)
if (ud.recstat == 2) if (ud.recstat == 2)
return; return;
if (g_mapInfo[MUS_LOADING].musicfn) S_TryPlaySpecialMusic(MUS_LOADING);
{
S_PlayMusic(g_mapInfo[MUS_LOADING].musicfn);
}
#if defined EDUKE32_TOUCH_DEVICES && defined USE_OPENGL #if defined EDUKE32_TOUCH_DEVICES && defined USE_OPENGL
polymost_glreset(); polymost_glreset();
@ -1404,7 +1401,7 @@ void G_NewGame(int volumeNum, int levelNum, int skillNum)
VM_OnEventWithReturn(EVENT_NEWGAMESCREEN, g_player[myconnectindex].ps->i, myconnectindex, 0) == 0 && VM_OnEventWithReturn(EVENT_NEWGAMESCREEN, g_player[myconnectindex].ps->i, myconnectindex, 0) == 0 &&
levelNum == 0 && volumeNum == 3 && ud.lockout == 0 && (G_GetLogoFlags() & LOGO_NOE4CUTSCENE)==0) levelNum == 0 && volumeNum == 3 && ud.lockout == 0 && (G_GetLogoFlags() & LOGO_NOE4CUTSCENE)==0)
{ {
S_PlayMusic(g_mapInfo[MUS_BRIEFING].musicfn); S_PlaySpecialMusicOrNothing(MUS_BRIEFING);
flushperms(); flushperms();
setview(0,0,xdim-1,ydim-1); setview(0,0,xdim-1,ydim-1);
@ -1937,14 +1934,14 @@ int G_EnterLevel(int gameMode)
if (ud.recstat != 2) if (ud.recstat != 2)
{ {
if (g_mapInfo[mii].musicfn != NULL && if (g_mapInfo[g_musicIndex].musicfn == NULL ||
(g_mapInfo[g_musicIndex].musicfn == NULL || g_mapInfo[mii].musicfn == NULL || // intentional, to pass control further while avoiding the strcmp on null
Bstrcmp(g_mapInfo[g_musicIndex].musicfn, g_mapInfo[mii].musicfn) || strcmp(g_mapInfo[g_musicIndex].musicfn, g_mapInfo[mii].musicfn) ||
g_musicSize == 0 || g_musicSize == 0 ||
ud.last_level == -1)) ud.last_level == -1)
S_PlayMusic(g_mapInfo[mii].musicfn); {
S_PlayLevelMusicOrNothing(mii);
g_musicIndex = mii; }
} }
if (gameMode & (MODE_GAME|MODE_EOL)) if (gameMode & (MODE_GAME|MODE_EOL))

View file

@ -2176,14 +2176,8 @@ static void postloadplayer(int32_t savegamep)
if (ud.config.MusicToggle) if (ud.config.MusicToggle)
{ {
if (g_mapInfo[musicIdx].musicfn != NULL && if (g_mapInfo[musicIdx].musicfn != NULL && musicIdx != g_musicIndex)
(musicIdx != g_musicIndex /* || g_mapInfo[MUS_LOADING].musicfn */)) S_PlayLevelMusicOrNothing(musicIdx);
{
S_StopMusic();
g_musicIndex = musicIdx;
S_PlayMusic(g_mapInfo[g_musicIndex].musicfn);
}
S_PauseMusic(0); S_PauseMusic(0);
} }

View file

@ -1507,10 +1507,7 @@ void G_DisplayLogo(void)
} }
if (logoflags & LOGO_PLAYMUSIC) if (logoflags & LOGO_PLAYMUSIC)
{ S_PlaySpecialMusicOrNothing(MUS_INTRO);
g_musicIndex = MUS_INTRO;
S_PlayMusic(g_mapInfo[g_musicIndex].musicfn);
}
if (!NAM) if (!NAM)
{ {

View file

@ -408,6 +408,7 @@ static void sigchld_handler(int signo)
int32_t MUSIC_PlaySong(char *song, int32_t loopflag) int32_t MUSIC_PlaySong(char *song, int32_t loopflag)
{ {
// initprintf("MUSIC_PlaySong"); // initprintf("MUSIC_PlaySong");
// TODO: graceful failure
MUSIC_StopSong(); MUSIC_StopSong();
if (external_midi) if (external_midi)

View file

@ -163,13 +163,11 @@ void S_RestartMusic(void)
{ {
if (ud.recstat != 2 && g_player[myconnectindex].ps->gm&MODE_GAME) if (ud.recstat != 2 && g_player[myconnectindex].ps->gm&MODE_GAME)
{ {
if (g_mapInfo[g_musicIndex].musicfn != NULL) S_PlayLevelMusicOrNothing(g_musicIndex);
S_PlayMusic(g_mapInfo[g_musicIndex].musicfn);
} }
else if (g_mapInfo[MUS_INTRO].musicfn != 0 && (G_GetLogoFlags() & LOGO_PLAYMUSIC)) else if (G_GetLogoFlags() & LOGO_PLAYMUSIC)
{ {
g_musicIndex = MUS_INTRO; S_PlaySpecialMusicOrNothing(MUS_INTRO);
S_PlayMusic(g_mapInfo[MUS_INTRO].musicfn);
} }
} }
@ -186,62 +184,138 @@ void S_MenuSound(void)
S_PlaySound(s); S_PlaySound(s);
} }
int32_t S_PlayMusic(const char *fn) static int32_t S_PlayMusic(const char *fn)
{ {
if (!ud.config.MusicToggle || fn == NULL) if (!ud.config.MusicToggle || fn == NULL)
return 0; return 1;
int32_t fp = S_OpenAudio(fn, 0, 1); int32_t fp = S_OpenAudio(fn, 0, 1);
if (EDUKE32_PREDICT_FALSE(fp < 0)) if (EDUKE32_PREDICT_FALSE(fp < 0))
{ {
OSD_Printf(OSD_ERROR "S_PlayMusic(): error: can't open \"%s\" for playback!\n",fn); OSD_Printf(OSD_ERROR "S_PlayMusic(): error: can't open \"%s\" for playback!\n",fn);
return 0; return 2;
} }
S_StopMusic();
int32_t MusicLen = kfilelength(fp); int32_t MusicLen = kfilelength(fp);
if (EDUKE32_PREDICT_FALSE(MusicLen < 4)) if (EDUKE32_PREDICT_FALSE(MusicLen < 4))
{ {
OSD_Printf(OSD_ERROR "S_PlayMusic(): error: empty music file \"%s\"\n", fn); OSD_Printf(OSD_ERROR "S_PlayMusic(): error: empty music file \"%s\"\n", fn);
kclose(fp); kclose(fp);
return 0; return 3;
} }
ALIGNED_FREE_AND_NULL(MusicPtr); // in case the following allocation was never freed char * MyMusicPtr = (char *)Xaligned_alloc(16, MusicLen);
MusicPtr = (char *)Xaligned_alloc(16, MusicLen); int MyMusicSize = kread(fp, MyMusicPtr, MusicLen);
g_musicSize = kread(fp, (char *)MusicPtr, MusicLen);
if (EDUKE32_PREDICT_FALSE(g_musicSize != MusicLen)) if (EDUKE32_PREDICT_FALSE(MyMusicSize != MusicLen))
{ {
OSD_Printf(OSD_ERROR "S_PlayMusic(): error: read %d bytes from \"%s\", expected %d\n", OSD_Printf(OSD_ERROR "S_PlayMusic(): error: read %d bytes from \"%s\", expected %d\n",
g_musicSize, fn, MusicLen); MyMusicSize, fn, MusicLen);
kclose(fp); kclose(fp);
g_musicSize = 0; ALIGNED_FREE_AND_NULL(MyMusicPtr);
return 0; return 4;
} }
kclose(fp); kclose(fp);
if (!Bmemcmp(MusicPtr, "MThd", 4)) if (!Bmemcmp(MyMusicPtr, "MThd", 4))
{ {
MUSIC_PlaySong(MusicPtr, MUSIC_LoopSong); int32_t retval = MUSIC_PlaySong(MyMusicPtr, MUSIC_LoopSong);
if (retval != MUSIC_Ok)
{
ALIGNED_FREE_AND_NULL(MyMusicPtr);
return 5;
}
if (MusicIsWaveform && MusicVoice >= 0)
{
FX_StopSound(MusicVoice);
MusicVoice = -1;
}
MusicIsWaveform = 0; MusicIsWaveform = 0;
ALIGNED_FREE_AND_NULL(MusicPtr);
MusicPtr = MyMusicPtr;
g_musicSize = MyMusicSize;
} }
else else
{ {
int32_t const mvol = MASTER_VOLUME(ud.config.MusicVolume); int32_t const mvol = MASTER_VOLUME(ud.config.MusicVolume);
MusicVoice = FX_Play(MusicPtr, MusicLen, 0, 0, int MyMusicVoice = FX_Play(MyMusicPtr, MusicLen, 0, 0,
0, mvol, mvol, mvol, 0, mvol, mvol, mvol,
FX_MUSIC_PRIORITY, MUSIC_ID); FX_MUSIC_PRIORITY, MUSIC_ID);
if (MusicVoice > FX_Ok)
MusicIsWaveform = 1; if (MyMusicVoice <= FX_Ok)
{
ALIGNED_FREE_AND_NULL(MyMusicPtr);
return 5;
}
if (MusicIsWaveform && MusicVoice >= 0)
FX_StopSound(MusicVoice);
MUSIC_StopSong();
MusicVoice = MyMusicVoice;
MusicIsWaveform = 1;
ALIGNED_FREE_AND_NULL(MusicPtr);
MusicPtr = MyMusicPtr;
g_musicSize = MyMusicSize;
} }
return 0; return 0;
} }
int S_TryPlayLevelMusic(unsigned int m)
{
char const * musicfn = g_mapInfo[m].musicfn;
if (musicfn != NULL)
{
if (!S_PlayMusic(musicfn))
{
g_musicIndex = m;
return 0;
}
}
return 1;
}
void S_PlayLevelMusicOrNothing(unsigned int m)
{
if (S_TryPlayLevelMusic(m))
{
S_StopMusic();
g_musicIndex = m;
}
}
int S_TryPlaySpecialMusic(unsigned int m)
{
char const * musicfn = g_mapInfo[m].musicfn;
if (musicfn != NULL)
{
if (!S_PlayMusic(musicfn))
{
g_musicIndex = m;
return 0;
}
}
return 1;
}
void S_PlaySpecialMusicOrNothing(unsigned int m)
{
if (S_TryPlaySpecialMusic(m))
{
S_StopMusic();
g_musicIndex = m;
}
}
int32_t S_GetMusicPosition(void) int32_t S_GetMusicPosition(void)
{ {
int32_t position = 0; int32_t position = 0;

View file

@ -96,7 +96,10 @@ void S_MusicVolume(int32_t volume);
void S_RestartMusic(void); void S_RestartMusic(void);
void S_PauseMusic(int32_t onf); void S_PauseMusic(int32_t onf);
void S_PauseSounds(int32_t onf); void S_PauseSounds(int32_t onf);
int32_t S_PlayMusic(const char *fn); int S_TryPlayLevelMusic(unsigned int);
void S_PlayLevelMusicOrNothing(unsigned int);
int S_TryPlaySpecialMusic(unsigned int);
void S_PlaySpecialMusicOrNothing(unsigned int);
int32_t S_PlaySound(int32_t num); int32_t S_PlaySound(int32_t num);
int32_t S_PlaySound3D(int32_t num,int32_t i,const vec3_t *pos); int32_t S_PlaySound3D(int32_t num,int32_t i,const vec3_t *pos);
void S_SoundShutdown(void); void S_SoundShutdown(void);