Sound backend and ogg pause features

Playback features outlined in issue #715 .

Reintroduce activate\deactivate sound backend when window focus in changed.
Added "windowed_pauseonfocuslost" cvar to allowing user control of pause when the window changes focus.
Added "ogg_pausewithgame" cvar to allow user control of ogg playback whenever the game is paused.
Introduced ogg playback command "mute" as an additional playback option for the console, command buffer and key binds.

If the window focus is changed all sound playback will stop and resume as expected.
Setting "window_pauseonfocuslost" to 1 will force the game to pause when the window focus is lost, "cl_paused" is ignored in multiplayer.
Setting "ogg_pausewithgame" to 1 will force ogg playback to pause whenever the game is paused.
Toggling ogg mute through "ogg mute" sets the volume to 0 while playback resumes.
This commit is contained in:
apartfromtime 2023-04-29 13:27:38 +10:00
parent 22617d8812
commit bc5926be4f
8 changed files with 133 additions and 1 deletions

View file

@ -96,6 +96,13 @@ Con_ToggleConsole_f(void)
{
M_ForceMenuOff();
Cvar_Set("paused", "0");
/* play music */
if (Cvar_VariableValue("ogg_pausewithgame") == 1 &&
OGG_Status() == PAUSE)
{
Cbuf_AddText("ogg toggle\n");
}
}
else
{
@ -106,6 +113,13 @@ Con_ToggleConsole_f(void)
Com_ServerState())
{
Cvar_Set("paused", "1");
/* pause music */
if (Cvar_VariableValue("ogg_pausewithgame") == 1 &&
OGG_Status() == PLAY)
{
Cbuf_AddText("ogg toggle\n");
}
}
}
}

View file

@ -309,6 +309,17 @@ CL_Pause_f(void)
}
Cvar_SetValue("paused", !cl_paused->value);
if (Cvar_VariableValue("ogg_pausewithgame") == 1 &&
OGG_Status() == PAUSE && cl_paused->value == 0) /* play music */
{
Cbuf_AddText("ogg toggle\n");
}
else if (Cvar_VariableValue("ogg_pausewithgame") == 1 &&
OGG_Status() == PLAY && cl_paused->value == 1) /* pause music */
{
Cbuf_AddText("ogg toggle\n");
}
}
void

View file

@ -104,6 +104,7 @@ static cvar_t *sensitivity;
static cvar_t *exponential_speedup;
static cvar_t *in_grab;
static cvar_t *m_filter;
static cvar_t *windowed_pauseonfocuslost;
static cvar_t *windowed_mouse;
static cvar_t *haptic_feedback_filter;
@ -687,6 +688,36 @@ IN_Update(void)
event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
{
Key_MarkAllUp();
if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
{
S_Activate(false);
if (windowed_pauseonfocuslost->value == 1)
{
Cvar_SetValue("paused", 1);
}
/* pause music */
if (Cvar_VariableValue("ogg_pausewithgame") == 1 &&
OGG_Status() == PLAY && cl.attractloop == false)
{
Cbuf_AddText("ogg toggle\n");
}
}
if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
{
S_Activate(true);
/* play music */
if (Cvar_VariableValue("ogg_pausewithgame") == 1 &&
OGG_Status() == PAUSE && cl.attractloop == false &&
cl_paused->value == 0)
{
Cbuf_AddText("ogg toggle\n");
}
}
}
else if (event.window.event == SDL_WINDOWEVENT_MOVED)
{
@ -2287,6 +2318,7 @@ IN_Init(void)
gyro_active = true;
}
windowed_pauseonfocuslost = Cvar_Get("windowed_pauseonfocuslost", "0", CVAR_USERINFO | CVAR_ARCHIVE);
windowed_mouse = Cvar_Get("windowed_mouse", "1", CVAR_USERINFO | CVAR_ARCHIVE);
Cmd_AddCommand("+mlook", IN_MLookDown);

View file

@ -124,6 +124,13 @@ M_ForceMenuOff(void)
void
M_PopMenu(void)
{
/* play music */
if (Cvar_VariableValue("ogg_pausewithgame") == 1 &&
OGG_Status() == PAUSE && cl.attractloop == false)
{
Cbuf_AddText("ogg toggle\n");
}
S_StartLocalSound(menu_out_sound);
if (m_menudepth < 1)
@ -179,6 +186,13 @@ M_PushMenu(void (*draw)(void), const char *(*key)(int))
}
#endif
/* pause music */
if (Cvar_VariableValue("ogg_pausewithgame") == 1 &&
OGG_Status() == PLAY && cl.attractloop == false)
{
Cbuf_AddText("ogg toggle\n");
}
/* if this menu is already open (and on top),
close it => toggling behaviour */
if ((m_drawfunc == draw) && (m_keyfunc == key))

View file

@ -30,6 +30,7 @@
struct sfx_s;
void S_Activate(qboolean active);
void S_Init(void);
void S_Shutdown(void);

View file

@ -34,6 +34,7 @@ typedef enum
STOP
} ogg_status_t;
int OGG_Status(void);
void OGG_InitTrackList(void);
void OGG_Init(void);
void OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate);

View file

@ -40,6 +40,7 @@
#define STB_VORBIS_NO_PUSHDATA_API
#include "header/stb_vorbis.h"
static cvar_t *ogg_pausewithgame; /* Pause music when the game is paused */
static cvar_t *ogg_enabled; /* Backend is enabled */
static cvar_t *ogg_shuffle; /* Shuffle playback */
static cvar_t *ogg_ignoretrack0; /* Toggle track 0 playing */
@ -51,6 +52,7 @@ static int ogg_mapcdtrack; /* Index of current map cdtrack */
static ogg_status_t ogg_status; /* Status indicator. */
static stb_vorbis *ogg_file; /* Ogg Vorbis file. */
static qboolean ogg_started; /* Initialization flag. */
static qboolean ogg_mutemusic; /* Mute music */
enum { MAX_NUM_OGGTRACKS = 128 };
static char* ogg_tracks[MAX_NUM_OGGTRACKS];
@ -68,6 +70,9 @@ struct {
int numsamples;
} ogg_saved_state;
static void
OGG_TogglePlayback(void);
// --------
/*
@ -238,6 +243,7 @@ void
static OGG_Read(void)
{
short samples[4096] = {0};
float volume = (ogg_mutemusic == true) ? 0.0f : ogg_volume->value;
int read_samples = stb_vorbis_get_samples_short_interleaved(ogg_file, ogg_file->channels, samples,
sizeof(samples) / sizeof(short));
@ -247,7 +253,7 @@ static OGG_Read(void)
ogg_numsamples += read_samples;
S_RawSamples(read_samples, ogg_file->sample_rate, sizeof(short), ogg_file->channels,
(byte *)samples, ogg_volume->value);
(byte *)samples, volume);
}
else
{
@ -285,6 +291,17 @@ OGG_Stream(void)
return;
}
if (ogg_pausewithgame->modified)
{
if ((ogg_pausewithgame->value == 0 && ogg_status == PAUSE) ||
(ogg_pausewithgame->value == 1 && ogg_status == PLAY))
{
OGG_TogglePlayback();
}
ogg_pausewithgame->modified = false;
}
if (ogg_status == PLAY)
{
#ifdef USE_OPENAL
@ -618,6 +635,7 @@ OGG_HelpMsg(void)
Com_Printf(" - play <track>: Play track number <track>\n");
Com_Printf(" - stop: Stop playback\n");
Com_Printf(" - toggle: Toggle pause\n");
Com_Printf(" - mute: Mute playback\n");
}
/*
@ -664,6 +682,10 @@ OGG_Cmd(void)
{
OGG_TogglePlayback();
}
else if (Q_stricmp(Cmd_Argv(1), "mute") == 0)
{
ogg_mutemusic = !ogg_mutemusic;
}
else
{
OGG_HelpMsg();
@ -712,6 +734,14 @@ OGG_RecoverState(void)
Cvar_SetValue("ogg_shuffle", shuffle_state);
}
/*
* Returns ogg status.
*/
int
OGG_Status(void)
{
return ogg_status;
}
// --------
/*
@ -721,6 +751,7 @@ void
OGG_Init(void)
{
// Cvars
ogg_pausewithgame = Cvar_Get("ogg_pausewithgame", "0", CVAR_ARCHIVE);
ogg_shuffle = Cvar_Get("ogg_shuffle", "0", CVAR_ARCHIVE);
ogg_ignoretrack0 = Cvar_Get("ogg_ignoretrack0", "0", CVAR_ARCHIVE);
ogg_volume = Cvar_Get("ogg_volume", "0.7", CVAR_ARCHIVE);
@ -741,6 +772,7 @@ OGG_Init(void)
ogg_mapcdtrack = 0;
ogg_mutemusic = false;
ogg_started = true;
}

View file

@ -89,6 +89,7 @@ static sfx_t known_sfx[MAX_SFX];
sndstarted_t sound_started = SS_NOT;
sound_t sound;
static qboolean s_registering;
qboolean s_active;
qboolean snd_is_underwater;
qboolean snd_is_underwater_enabled;
@ -1066,6 +1067,13 @@ S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx,
return;
}
/* A hack to prevent temporary entities generating sounds when the sound
backend is not active and the game is not paused */
if (s_active == false)
{
return;
}
if (!sfx)
{
return;
@ -1412,6 +1420,11 @@ S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
return;
}
if (s_active == false)
{
return;
}
VectorCopy(origin, listener_origin);
VectorCopy(forward, listener_forward);
VectorCopy(right, listener_right);
@ -1564,6 +1577,19 @@ S_SoundInfo_f(void)
}
}
/*
* Activate or deactivate sound backend
*/
void S_Activate(qboolean active)
{
s_active = active;
if (active == false)
{
S_StopAllSounds();
}
}
/*
* Initializes the sound system
* and it's requested backend
@ -1630,6 +1656,7 @@ S_Init(void)
num_sfx = 0;
paintedtime = 0;
sound_max = 0;
s_active = true;
OGG_Init();