diff --git a/src/client/cl_parse.c b/src/client/cl_parse.c index ab194665..ef8cc725 100644 --- a/src/client/cl_parse.c +++ b/src/client/cl_parse.c @@ -1095,7 +1095,9 @@ CL_ParseConfigString(void) { if (cl.refresh_prepped) { - OGG_PlayTrack((int)strtol(cl.configstrings[CS_CDTRACK], (char **)NULL, 10)); + int track = (int)strtol(cl.configstrings[CS_CDTRACK], (char **)NULL, 10); + + OGG_PlayTrack(track, true, true); } } else if ((i >= CS_MODELS) && (i < CS_MODELS + MAX_MODELS)) diff --git a/src/client/cl_view.c b/src/client/cl_view.c index 67096b33..de584cd8 100644 --- a/src/client/cl_view.c +++ b/src/client/cl_view.c @@ -363,8 +363,8 @@ CL_PrepRefresh(void) /* start the cd track */ int track = (int)strtol(cl.configstrings[CS_CDTRACK], (char **)NULL, 10); - - OGG_PlayTrack(track); + + OGG_PlayTrack(track, true, true); } float diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c index 6808ecc9..0bdab0e9 100644 --- a/src/client/menu/menu.c +++ b/src/client/menu/menu.c @@ -2174,7 +2174,7 @@ FreeLookFunc(void *unused) static void ControlsSetMenuItemValues(void) { - s_options_oggshuffle_box.curvalue = (Cvar_VariableValue("ogg_shuffle") != 0); + s_options_oggshuffle_box.curvalue = Cvar_VariableValue("ogg_shuffle"); s_options_oggenable_box.curvalue = (Cvar_VariableValue("ogg_enable") != 0); s_options_quality_list.curvalue = (Cvar_VariableValue("s_loadas8bit") == 0); s_options_alwaysrun_box.curvalue = (cl_run->value != 0); @@ -2192,6 +2192,7 @@ ControlsResetDefaultsFunc(void *unused) Cbuf_Execute(); ControlsSetMenuItemValues(); + s_options_oggshuffle_box.curvalue = 0; } static void @@ -2226,7 +2227,7 @@ EnableOGGMusic(void *unused) if (cls.state == ca_active) { int track = (int)strtol(cl.configstrings[CS_CDTRACK], (char **)NULL, 10); - OGG_PlayTrack(track); + OGG_PlayTrack(track, true, true); } } else @@ -2292,6 +2293,15 @@ Options_MenuInit(void) { extern qboolean show_gamepad; + static const char *ogg_shuffle_items[] = + { + "default", + "play once", + "sequential", + "random", + 0 + }; + static const char *able_items[] = { "disabled", @@ -2356,7 +2366,7 @@ Options_MenuInit(void) s_options_oggshuffle_box.generic.y = (y += 10); s_options_oggshuffle_box.generic.name = "OGG shuffle"; s_options_oggshuffle_box.generic.callback = OGGShuffleFunc; - s_options_oggshuffle_box.itemnames = able_items; + s_options_oggshuffle_box.itemnames = ogg_shuffle_items; s_options_quality_list.generic.type = MTYPE_SPINCONTROL; s_options_quality_list.generic.x = 0; diff --git a/src/client/sound/header/vorbis.h b/src/client/sound/header/vorbis.h index e5fb5d3b..0f05e5a2 100644 --- a/src/client/sound/header/vorbis.h +++ b/src/client/sound/header/vorbis.h @@ -36,7 +36,7 @@ typedef enum void OGG_InitTrackList(void); void OGG_Init(void); -void OGG_PlayTrack(int trackNo); +void OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate); void OGG_RecoverState(void); void OGG_SaveState(void); void OGG_Shutdown(void); diff --git a/src/client/sound/ogg.c b/src/client/sound/ogg.c index ebfa4408..1e9f04f9 100644 --- a/src/client/sound/ogg.c +++ b/src/client/sound/ogg.c @@ -47,6 +47,7 @@ static cvar_t *ogg_volume; /* Music volume. */ static int ogg_curfile; /* Index of currently played file. */ static int ogg_numbufs; /* Number of buffers for OpenAL */ static int ogg_numsamples; /* Number of sambles read from the current file */ +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. */ @@ -260,7 +261,7 @@ static OGG_Read(void) ogg_numbufs = 0; ogg_numsamples = 0; - OGG_PlayTrack(ogg_curfile); + OGG_PlayTrack(ogg_curfile, false, false); } } @@ -323,6 +324,24 @@ OGG_Stream(void) } } } + + if (ogg_status == PLAY && ogg_shuffle->modified) + { + // Shuffle was modified before last track finished. + ogg_shuffle->modified = false; + } + else if (ogg_status == STOP && ogg_shuffle->modified) + { + // If fullscreen console, clear the map cdtrack. + if (cls.state == ca_disconnected) + { + ogg_mapcdtrack = 0; // Track 0 means "stop music". + } + + // Ogg playback has stopped and shuffle was modified, play the map cdtrack. + ogg_shuffle->modified = false; + OGG_PlayTrack(ogg_mapcdtrack, true, true); + } } // -------- @@ -331,7 +350,7 @@ OGG_Stream(void) * play the ogg file that corresponds to the CD track with the given number */ void -OGG_PlayTrack(int trackNo) +OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate) { if (sound_started == SS_NOT) { @@ -344,7 +363,7 @@ OGG_PlayTrack(int trackNo) } // Track 0 means "stop music". - if(trackNo == 0) + if (trackNo == 0) { if(ogg_ignoretrack0->value == 0) { @@ -367,21 +386,65 @@ OGG_PlayTrack(int trackNo) } } - // Player has requested shuffle playback. - if((trackNo == 0) || ogg_shuffle->value) + if (cdtrack == true) // the map cdtrack. { - if(ogg_maxfileindex >= 0) - { - trackNo = randk() % (ogg_maxfileindex+1); - int retries = 100; - while(ogg_tracks[trackNo] == NULL && retries-- > 0) - { - trackNo = randk() % (ogg_maxfileindex+1); - } - } + ogg_mapcdtrack = trackNo; } - if(ogg_maxfileindex == -1) + int playback = ogg_shuffle->value; + int curtrack = 0; + + // If loading a map, restarting sound or video, the ogg backend or console issued + // a playtrack or no tracks have been played, apply shuffle parameters to the next + // track. + if ((immediate == false && (cls.state == ca_connecting || cls.state == ca_connected)) || + immediate == true || ogg_curfile == -1) + { + curtrack = trackNo; + playback = 0; + } + else + { + curtrack = ogg_curfile; + } + + int newtrack = 0; + + // These must match those in menu.c - Options_MenuInit(). + switch (playback) + { + case 0: // default + { + newtrack = curtrack; + } break; + case 1: // play once + { + return; + } break; + case 2: // sequential + { + newtrack = (curtrack + 1) % (ogg_maxfileindex + 1) != 0 ? (curtrack + 1) : 2; + } break; + case 3: // random + { + int retries = 100; + newtrack = 0; + + while (retries-- > 0 && newtrack < 2) + { + newtrack = randk() % (ogg_maxfileindex + 1); + + if (newtrack == curtrack) + { + newtrack = 0; + } + } + } break; + } + + trackNo = newtrack; + + if (ogg_maxfileindex == -1) { return; // no ogg files at all, ignore this silently instead of printing warnings all the time } @@ -392,7 +455,7 @@ OGG_PlayTrack(int trackNo) return; } - if(ogg_tracks[trackNo] == NULL) + if (ogg_tracks[trackNo] == NULL) { Com_Printf("%s: Don't have a .ogg file for track %d\n", __func__, trackNo); } @@ -592,7 +655,7 @@ OGG_Cmd(void) } else { - OGG_PlayTrack(track); + OGG_PlayTrack(track, false, true); } } else if (Q_stricmp(Cmd_Argv(1), "stop") == 0) @@ -644,7 +707,7 @@ OGG_RecoverState(void) int shuffle_state = ogg_shuffle->value; Cvar_SetValue("ogg_shuffle", 0); - OGG_PlayTrack(ogg_saved_state.curfile); + OGG_PlayTrack(ogg_saved_state.curfile, false, true); stb_vorbis_seek_frame(ogg_file, ogg_saved_state.numsamples); ogg_numsamples = ogg_saved_state.numsamples; @@ -678,6 +741,8 @@ OGG_Init(void) ogg_numsamples = 0; ogg_status = STOP; + ogg_mapcdtrack = 0; + ogg_started = true; }