Fix snd_restart. it should restore the OGG playback state.

My solution to this problem is somewhat hacky. A newly added function
OGG_SaveState() can be called to save the state and OGG_RecoverState()
at a later time to restore it. There's only one state and it works
only iff OGG is state playing.

This closes #347.
This commit is contained in:
Yamagi Burmeister 2019-01-05 19:26:50 +01:00
parent 46503018f0
commit 7d9016510e
3 changed files with 62 additions and 0 deletions

View file

@ -425,9 +425,15 @@ CL_Userinfo_f(void)
void void
CL_Snd_Restart_f(void) CL_Snd_Restart_f(void)
{ {
OGG_SaveState();
S_Shutdown(); S_Shutdown();
S_Init(); S_Init();
CL_RegisterSounds(); CL_RegisterSounds();
OGG_InitTrackList();
OGG_RecoverState();
} }
int precache_check; int precache_check;

View file

@ -35,6 +35,8 @@ typedef enum
void OGG_InitTrackList(void); void OGG_InitTrackList(void);
void OGG_Init(void); void OGG_Init(void);
void OGG_PlayTrack(int track); void OGG_PlayTrack(int track);
void OGG_RecoverState(void);
void OGG_SaveState(void);
void OGG_Shutdown(void); void OGG_Shutdown(void);
void OGG_Stop(void); void OGG_Stop(void);
void OGG_Stream(void); void OGG_Stream(void);

View file

@ -45,6 +45,7 @@ static cvar_t *ogg_ignoretrack0; /* Toggle track 0 playing */
static cvar_t *ogg_volume; /* Music volume. */ static cvar_t *ogg_volume; /* Music volume. */
static int ogg_curfile; /* Index of currently played file. */ static int ogg_curfile; /* Index of currently played file. */
static int ogg_numbufs; /* Number of buffers for OpenAL */ static int ogg_numbufs; /* Number of buffers for OpenAL */
static int ogg_numsamples; /* Number of sambles read from the current file */
static ogg_status_t ogg_status; /* Status indicator. */ static ogg_status_t ogg_status; /* Status indicator. */
static stb_vorbis *ogg_file; /* Ogg Vorbis file. */ static stb_vorbis *ogg_file; /* Ogg Vorbis file. */
static qboolean ogg_started; /* Initialization flag. */ static qboolean ogg_started; /* Initialization flag. */
@ -59,6 +60,12 @@ enum GameType {
rogue rogue
}; };
struct {
qboolean saved;
int curfile;
int numsamples;
} ogg_saved_state;
// -------- // --------
/* /*
@ -236,6 +243,8 @@ static OGG_Read(void)
if (read_samples > 0) if (read_samples > 0)
{ {
ogg_numsamples += read_samples;
S_RawSamples(read_samples, ogg_file->sample_rate, ogg_file->channels, ogg_file->channels, S_RawSamples(read_samples, ogg_file->sample_rate, ogg_file->channels, ogg_file->channels,
(byte *)samples, ogg_volume->value); (byte *)samples, ogg_volume->value);
} }
@ -249,6 +258,7 @@ static OGG_Read(void)
stb_vorbis_close(ogg_file); stb_vorbis_close(ogg_file);
ogg_status = STOP; ogg_status = STOP;
ogg_numbufs = 0; ogg_numbufs = 0;
ogg_numsamples = 0;
OGG_PlayTrack(ogg_curfile); OGG_PlayTrack(ogg_curfile);
} }
@ -411,6 +421,7 @@ OGG_PlayTrack(int trackNo)
/* Play file. */ /* Play file. */
ogg_curfile = trackNo; ogg_curfile = trackNo;
ogg_numsamples = 0;
ogg_status = PLAY; ogg_status = PLAY;
} }
@ -577,6 +588,48 @@ OGG_Cmd(void)
} }
} }
/*
* Saves the current state of the subsystem.
*/
void
OGG_SaveState(void)
{
if (ogg_status != PLAY)
{
ogg_saved_state.saved = false;
return;
}
ogg_saved_state.saved = true;
ogg_saved_state.curfile = ogg_curfile;
ogg_saved_state.numsamples = ogg_numsamples;
}
/*
* Recover the previously saved state.
*/
void
OGG_RecoverState(void)
{
if (!ogg_saved_state.saved)
{
return;
}
// Mkay, ultra evil hack to recover the state in case of
// shuffled playback. OGG_PlayTrack() does the shuffeling,
// so switch it of before and enable after state recovery.
int shuffle_state = ogg_shuffle->value;
Cvar_SetValue("ogg_shuffle", 0);
OGG_PlayTrack(ogg_saved_state.curfile);
stb_vorbis_seek_frame(ogg_file, ogg_saved_state.numsamples);
ogg_numsamples = ogg_saved_state.numsamples;
Cvar_SetValue("ogg_shuffle", shuffle_state);
}
// -------- // --------
/* /*
@ -602,6 +655,7 @@ OGG_Init(void)
// Global variables // Global variables
ogg_curfile = -1; ogg_curfile = -1;
ogg_numsamples = 0;
ogg_status = STOP; ogg_status = STOP;
ogg_started = true; ogg_started = true;