mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 07:12:07 +00:00
client: play arbitrary CDTRACK ogg file
https://github.com/yquake2/yquake2remaster/issues/18
This commit is contained in:
parent
005dfa0ed5
commit
87c0029b2b
8 changed files with 145 additions and 58 deletions
|
@ -1095,9 +1095,7 @@ CL_ParseConfigString(void)
|
|||
{
|
||||
if (cl.refresh_prepped)
|
||||
{
|
||||
int track = (int)strtol(cl.configstrings[CS_CDTRACK], (char **)NULL, 10);
|
||||
|
||||
OGG_PlayTrack(track, true, true);
|
||||
OGG_PlayTrack(cl.configstrings[CS_CDTRACK], true, true);
|
||||
}
|
||||
}
|
||||
else if ((i >= CS_MODELS) && (i < CS_MODELS + MAX_MODELS))
|
||||
|
|
|
@ -46,21 +46,21 @@ cvar_t *crosshair_3d_glow_b;
|
|||
|
||||
cvar_t *cl_stats;
|
||||
|
||||
int r_numdlights;
|
||||
dlight_t r_dlights[MAX_DLIGHTS];
|
||||
static int r_numdlights;
|
||||
static dlight_t r_dlights[MAX_DLIGHTS];
|
||||
|
||||
int r_numentities;
|
||||
entity_t r_entities[MAX_ENTITIES];
|
||||
static int r_numentities;
|
||||
static entity_t r_entities[MAX_ENTITIES];
|
||||
|
||||
int r_numparticles;
|
||||
particle_t r_particles[MAX_PARTICLES];
|
||||
static int r_numparticles;
|
||||
static particle_t r_particles[MAX_PARTICLES];
|
||||
|
||||
lightstyle_t r_lightstyles[MAX_LIGHTSTYLES];
|
||||
static lightstyle_t r_lightstyles[MAX_LIGHTSTYLES];
|
||||
|
||||
char cl_weaponmodels[MAX_CLIENTWEAPONMODELS][MAX_QPATH];
|
||||
int num_cl_weaponmodels;
|
||||
|
||||
void V_Render3dCrosshair(void);
|
||||
static void V_Render3dCrosshair(void);
|
||||
|
||||
/*
|
||||
* Specifies the model that will be used as the world
|
||||
|
@ -139,7 +139,7 @@ V_AddLightStyle(int style, float r, float g, float b)
|
|||
/*
|
||||
*If cl_testparticles is set, create 4096 particles in the view
|
||||
*/
|
||||
void
|
||||
static void
|
||||
V_TestParticles(void)
|
||||
{
|
||||
particle_t *p;
|
||||
|
@ -169,7 +169,7 @@ V_TestParticles(void)
|
|||
/*
|
||||
* If cl_testentities is set, create 32 player models
|
||||
*/
|
||||
void
|
||||
static void
|
||||
V_TestEntities(void)
|
||||
{
|
||||
int i, j;
|
||||
|
@ -200,18 +200,20 @@ V_TestEntities(void)
|
|||
/*
|
||||
* If cl_testlights is set, create 32 lights models
|
||||
*/
|
||||
void
|
||||
static void
|
||||
V_TestLights(void)
|
||||
{
|
||||
int i, j;
|
||||
float f, r;
|
||||
dlight_t *dl;
|
||||
int i;
|
||||
|
||||
r_numdlights = 32;
|
||||
memset(r_dlights, 0, sizeof(r_dlights));
|
||||
|
||||
for (i = 0; i < r_numdlights; i++)
|
||||
{
|
||||
dlight_t *dl;
|
||||
float f, r;
|
||||
int j;
|
||||
|
||||
dl = &r_dlights[i];
|
||||
|
||||
r = 64 * ((i % 4) - 1.5f);
|
||||
|
@ -362,9 +364,7 @@ CL_PrepRefresh(void)
|
|||
cl.force_refdef = true; /* make sure we have a valid refdef */
|
||||
|
||||
/* start the cd track */
|
||||
int track = (int)strtol(cl.configstrings[CS_CDTRACK], (char **)NULL, 10);
|
||||
|
||||
OGG_PlayTrack(track, true, true);
|
||||
OGG_PlayTrack(cl.configstrings[CS_CDTRACK], true, true);
|
||||
}
|
||||
|
||||
float
|
||||
|
@ -388,14 +388,14 @@ CalcFov(float fov_x, float width, float height)
|
|||
}
|
||||
|
||||
/* gun frame debugging functions */
|
||||
void
|
||||
static void
|
||||
V_Gun_Next_f(void)
|
||||
{
|
||||
gun_frame++;
|
||||
Com_Printf("frame %i\n", gun_frame);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
V_Gun_Prev_f(void)
|
||||
{
|
||||
gun_frame--;
|
||||
|
@ -408,7 +408,7 @@ V_Gun_Prev_f(void)
|
|||
Com_Printf("frame %i\n", gun_frame);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
V_Gun_Model_f(void)
|
||||
{
|
||||
char name[MAX_QPATH];
|
||||
|
@ -423,7 +423,7 @@ V_Gun_Model_f(void)
|
|||
gun_model = R_RegisterModel(name);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
entitycmpfnc(const entity_t *a, const entity_t *b)
|
||||
{
|
||||
/* all other models are sorted by model then skin */
|
||||
|
@ -600,7 +600,7 @@ V_RenderView(float stereo_separation)
|
|||
SCR_DrawCrosshair();
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
V_Render3dCrosshair(void)
|
||||
{
|
||||
trace_t crosshair_trace;
|
||||
|
@ -646,7 +646,7 @@ V_Render3dCrosshair(void)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
V_Viewpos_f(void)
|
||||
{
|
||||
Com_Printf("position: %i %i %i, angles: %i %i %i\n",
|
||||
|
|
|
@ -2299,8 +2299,7 @@ EnableOGGMusic(void *unused)
|
|||
|
||||
if (cls.state == ca_active)
|
||||
{
|
||||
int track = (int)strtol(cl.configstrings[CS_CDTRACK], (char **)NULL, 10);
|
||||
OGG_PlayTrack(track, true, true);
|
||||
OGG_PlayTrack(cl.configstrings[CS_CDTRACK], true, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -37,7 +37,7 @@ typedef enum
|
|||
int OGG_Status(void);
|
||||
void OGG_InitTrackList(void);
|
||||
void OGG_Init(void);
|
||||
void OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate);
|
||||
void OGG_PlayTrack(const char* track, qboolean cdtrack, qboolean immediate);
|
||||
void OGG_RecoverState(void);
|
||||
void OGG_SaveState(void);
|
||||
void OGG_Shutdown(void);
|
||||
|
|
|
@ -64,7 +64,7 @@ enum GameType {
|
|||
rogue
|
||||
};
|
||||
|
||||
struct {
|
||||
static struct {
|
||||
qboolean saved;
|
||||
int curfile;
|
||||
int numsamples;
|
||||
|
@ -88,15 +88,24 @@ OGG_TogglePlayback(void);
|
|||
static int getMappedGOGtrack(int track, enum GameType gameType)
|
||||
{
|
||||
if(track <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(track == 1)
|
||||
{
|
||||
return 0; // 1 is illegal (=> data track on CD), 0 means "no track"
|
||||
}
|
||||
|
||||
if(gameType == other)
|
||||
{
|
||||
return track;
|
||||
}
|
||||
|
||||
if(gameType == rogue)
|
||||
{
|
||||
return track + 10;
|
||||
}
|
||||
|
||||
// apparently it's xatrix => map the track to the corresponding TrackXX.ogg from GOG
|
||||
switch(track)
|
||||
|
@ -185,14 +194,16 @@ OGG_InitTrackList(void)
|
|||
|
||||
char testFileName[MAX_OSPATH];
|
||||
|
||||
// the simple case (like before: $mod/music/02.ogg - 11.ogg or whatever)
|
||||
/* the simple case (like before: $mod/music/02.ogg - 11.ogg or whatever) */
|
||||
snprintf(testFileName, MAX_OSPATH, "%s02.ogg", fullMusicPath);
|
||||
|
||||
if(Sys_IsFile(testFileName))
|
||||
{
|
||||
int i;
|
||||
|
||||
ogg_tracks[2] = strdup(testFileName);
|
||||
|
||||
for(int i=3; i<MAX_NUM_OGGTRACKS; ++i)
|
||||
for(i = 3; i < MAX_NUM_OGGTRACKS; ++i)
|
||||
{
|
||||
snprintf(testFileName, MAX_OSPATH, "%s%02i.ogg", fullMusicPath, i);
|
||||
|
||||
|
@ -206,13 +217,15 @@ OGG_InitTrackList(void)
|
|||
return;
|
||||
}
|
||||
|
||||
// the GOG case: music/Track02.ogg to Track21.ogg
|
||||
/* the GOG case: music/Track02.ogg to Track21.ogg */
|
||||
snprintf(testFileName, MAX_OSPATH, "%sTrack%02i.ogg",
|
||||
fullMusicPath, getMappedGOGtrack(8, gameType));
|
||||
|
||||
if(Sys_IsFile(testFileName))
|
||||
{
|
||||
for(int i=2; i<MAX_NUM_OGGTRACKS; ++i)
|
||||
int i;
|
||||
|
||||
for(i = 2; i < MAX_NUM_OGGTRACKS; ++i)
|
||||
{
|
||||
int gogTrack = getMappedGOGtrack(i, gameType);
|
||||
|
||||
|
@ -227,10 +240,34 @@ OGG_InitTrackList(void)
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
/* the ReRelease case: music/track02.ogg to track79.ogg */
|
||||
snprintf(testFileName, MAX_OSPATH, "%strack%02i.ogg",
|
||||
fullMusicPath, getMappedGOGtrack(8, gameType));
|
||||
|
||||
if(Sys_IsFile(testFileName))
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 2; i < MAX_NUM_OGGTRACKS; ++i)
|
||||
{
|
||||
int gogTrack = getMappedGOGtrack(i, gameType);
|
||||
|
||||
snprintf(testFileName, MAX_OSPATH, "%strack%02i.ogg", fullMusicPath, gogTrack);
|
||||
|
||||
if(Sys_IsFile(testFileName))
|
||||
{
|
||||
ogg_tracks[i] = strdup(testFileName);
|
||||
ogg_maxfileindex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// if tracks have been found above, we would've returned there
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if tracks have been found above, we would've returned there */
|
||||
Com_Printf("No Ogg Vorbis music tracks have been found, so there will be no music.\n");
|
||||
}
|
||||
|
||||
|
@ -267,7 +304,7 @@ static OGG_Read(void)
|
|||
ogg_numbufs = 0;
|
||||
ogg_numsamples = 0;
|
||||
|
||||
OGG_PlayTrack(ogg_curfile, false, false);
|
||||
OGG_PlayTrack(va("%d", ogg_curfile), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,7 +394,7 @@ OGG_Stream(void)
|
|||
|
||||
// Ogg playback has stopped and shuffle was modified, play the map cdtrack.
|
||||
ogg_shuffle->modified = false;
|
||||
OGG_PlayTrack(ogg_mapcdtrack, true, true);
|
||||
OGG_PlayTrack(va("%d", ogg_mapcdtrack), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,8 +404,11 @@ OGG_Stream(void)
|
|||
* play the ogg file that corresponds to the CD track with the given number
|
||||
*/
|
||||
void
|
||||
OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate)
|
||||
OGG_PlayTrack(const char *track, qboolean cdtrack, qboolean immediate)
|
||||
{
|
||||
char name[MAX_OSPATH], *path = NULL;
|
||||
int trackNo;
|
||||
|
||||
if (sound_started == SS_NOT)
|
||||
{
|
||||
return; // sound is not initialized
|
||||
|
@ -379,6 +419,53 @@ OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate)
|
|||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
int res = 0;
|
||||
FILE* f;
|
||||
|
||||
path = FS_NextPath(path);
|
||||
|
||||
if (!path)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Com_sprintf(name, sizeof(name), "%s/music/%s", path, track);
|
||||
|
||||
/* Open ogg vorbis file. */
|
||||
f = Q_fopen(name, "rb");
|
||||
if (f == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check running music. */
|
||||
if (ogg_status == PLAY)
|
||||
{
|
||||
OGG_Stop();
|
||||
}
|
||||
|
||||
// fclose is not required on error with close_on_free=true
|
||||
ogg_file = stb_vorbis_open_file(f, true, &res, NULL);
|
||||
|
||||
if (res != 0)
|
||||
{
|
||||
Com_Printf("%s: '%s' is not a valid Ogg Vorbis file (error %i).\n",
|
||||
__func__, name, res);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Play file. */
|
||||
ogg_curfile = 0;
|
||||
ogg_numsamples = 0;
|
||||
ogg_status = PLAY;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
trackNo = (int)strtol(track, (char **)NULL, 10);
|
||||
|
||||
// Track 0 means "stop music".
|
||||
if (trackNo == 0)
|
||||
{
|
||||
|
@ -474,7 +561,8 @@ OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate)
|
|||
|
||||
if (ogg_tracks[trackNo] == NULL)
|
||||
{
|
||||
Com_Printf("%s: Don't have a .ogg file for track %d\n", __func__, trackNo);
|
||||
Com_Printf("%s: Don't have a .ogg file for track %d\n",
|
||||
__func__, trackNo);
|
||||
}
|
||||
|
||||
/* Check running music. */
|
||||
|
@ -492,7 +580,8 @@ OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate)
|
|||
|
||||
if (ogg_tracks[trackNo] == NULL)
|
||||
{
|
||||
Com_Printf("OGG_PlayTrack: I don't have a file for track %d!\n", trackNo);
|
||||
Com_Printf("%s: I don't have a file for track %d!\n",
|
||||
__func__, trackNo);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -502,7 +591,8 @@ OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate)
|
|||
|
||||
if (f == NULL)
|
||||
{
|
||||
Com_Printf("%s: could not open file %s for track %d: %s.\n", __func__, ogg_tracks[trackNo], trackNo, strerror(errno));
|
||||
Com_Printf("%s: could not open file %s for track %d: %s.\n",
|
||||
__func__, ogg_tracks[trackNo], trackNo, strerror(errno));
|
||||
ogg_tracks[trackNo] = NULL;
|
||||
|
||||
return;
|
||||
|
@ -515,7 +605,8 @@ OGG_PlayTrack(int trackNo, qboolean cdtrack, qboolean immediate)
|
|||
|
||||
if (res != 0)
|
||||
{
|
||||
Com_Printf("%s: '%s' is not a valid Ogg Vorbis file (error %i).\n", __func__, ogg_tracks[trackNo], res);
|
||||
Com_Printf("%s: '%s' is not a valid Ogg Vorbis file (error %i).\n",
|
||||
__func__, ogg_tracks[trackNo], res);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -626,7 +717,7 @@ OGG_TogglePlayback(void)
|
|||
/*
|
||||
* Prints a help message for the 'ogg' cmd.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
OGG_HelpMsg(void)
|
||||
{
|
||||
Com_Printf("Unknown sub command %s\n\n", Cmd_Argv(1));
|
||||
|
@ -641,7 +732,7 @@ OGG_HelpMsg(void)
|
|||
/*
|
||||
* The 'ogg' cmd. Gives some control and information about the playback state.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
OGG_Cmd(void)
|
||||
{
|
||||
if (Cmd_Argc() < 2)
|
||||
|
@ -662,17 +753,7 @@ OGG_Cmd(void)
|
|||
return;
|
||||
}
|
||||
|
||||
int track = (int)strtol(Cmd_Argv(2), NULL, 10);
|
||||
|
||||
if (track < 2 || track > ogg_maxfileindex)
|
||||
{
|
||||
Com_Printf("invalid track %s, must be an number between 2 and %d\n", Cmd_Argv(1), ogg_maxfileindex);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
OGG_PlayTrack(track, false, true);
|
||||
}
|
||||
OGG_PlayTrack(Cmd_Argv(2), false, true);
|
||||
}
|
||||
else if (Q_stricmp(Cmd_Argv(1), "stop") == 0)
|
||||
{
|
||||
|
@ -727,7 +808,7 @@ OGG_RecoverState(void)
|
|||
int shuffle_state = ogg_shuffle->value;
|
||||
Cvar_SetValue("ogg_shuffle", 0);
|
||||
|
||||
OGG_PlayTrack(ogg_saved_state.curfile, false, true);
|
||||
OGG_PlayTrack(va("%d", ogg_saved_state.curfile), false, true);
|
||||
stb_vorbis_seek_frame(ogg_file, ogg_saved_state.numsamples);
|
||||
ogg_numsamples = ogg_saved_state.numsamples;
|
||||
|
||||
|
|
|
@ -908,7 +908,14 @@ SP_worldspawn(edict_t *ent)
|
|||
gi.configstring(CS_SKYAXIS, va("%f %f %f",
|
||||
st.skyaxis[0], st.skyaxis[1], st.skyaxis[2]));
|
||||
|
||||
if (st.music && st.music[0])
|
||||
{
|
||||
gi.configstring(CS_CDTRACK, st.music);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.configstring(CS_CDTRACK, va("%i", ent->sounds));
|
||||
}
|
||||
|
||||
gi.configstring(CS_MAXCLIENTS, va("%i", (int)(maxclients->value)));
|
||||
|
||||
|
|
|
@ -344,6 +344,7 @@ typedef struct
|
|||
float skyrotate;
|
||||
vec3_t skyaxis;
|
||||
char *nextmap;
|
||||
char *music;
|
||||
|
||||
int lip;
|
||||
int distance;
|
||||
|
|
|
@ -104,5 +104,6 @@
|
|||
{"maxyaw", STOFS(maxyaw), F_FLOAT, FFL_SPAWNTEMP},
|
||||
{"minpitch", STOFS(minpitch), F_FLOAT, FFL_SPAWNTEMP},
|
||||
{"maxpitch", STOFS(maxpitch), F_FLOAT, FFL_SPAWNTEMP},
|
||||
{"music", STOFS(music), F_LSTRING, FFL_SPAWNTEMP},
|
||||
{"nextmap", STOFS(nextmap), F_LSTRING, FFL_SPAWNTEMP},
|
||||
{0, 0, 0, 0}
|
||||
|
|
Loading…
Reference in a new issue