ref: a857dd669858e58bb773ff4ee1f6cbe15826cddd
parent: be176cb096df301fd3ca221c0b08a88cf812c8b9
author: Konstantinn Bonnet <qu7uux@gmail.com>
date: Thu Mar 9 20:05:16 EST 2017
snd: reimplement cdaudio code without libregexp and mixfs(1) this works like shit with actual cdroms; perhaps a separate proc is the only solution here, but not sure.
--- a/cd.c
+++ /dev/null
@@ -1,206 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <regexp.h>
-#include "dat.h"
-#include "quakedef.h"
-#include "fns.h"
-
-static int cdread;
-static int cdloop;
-static int cdvol;
-static int chtrk;
-static int ntrk;
-static int trk;
-static char trtype;
-static int ctid = -1;
-static Reprog *pat;
-
-
-static int
-cdinfo(void)
-{
- int fd, i, n;
- Dir *d;
-
- ntrk = 0;
-
- if((fd = open("/mnt/cd", OREAD)) < 0)
- goto err;
- if((n = dirreadall(fd, &d)) < 0)
- goto err;
- close(fd);
- for(i = 0; i < n; i++)
- if(regexec(pat, d[i].name, nil, 0)){
- if(!trtype)
- trtype = d[i].name[0];
- ntrk++;
- }
- free(d);
- if(ntrk < 1)
- return -1;
- return 0;
-
-err:
- close(fd);
- fprint(2, "cdinfo: %r\n");
- return -1;
-}
-
-static void
-cproc(void *)
-{
- int a, n, afd, fd;
- char s[24];
- uchar buf[8192];
- short *p;
-
- if((afd = open("/dev/audio", OWRITE)) < 0)
- return;
- fd = -1;
- for(;;){
- if(chtrk > 0){
- close(fd);
- trk = chtrk;
- snprint(s, sizeof s, "/mnt/cd/%c%03ud", trtype, trk);
- if((fd = open(s, OREAD)) < 0)
- fprint(2, "cproc: %r");
- chtrk = 0;
- }
- if(!cdread || fd < 0){
- sleep(1);
- continue;
- }
- if((n = read(fd, buf, sizeof buf)) < 0)
- break;
- if(n == 0){
- if(cdloop)
- seek(fd, 0, 0);
- else{
- close(fd);
- fd = -1;
- }
- continue;
- }
- p = (short *)buf;
- while((uintptr)p < (uintptr)(buf + sizeof buf)){
- a = *p * cdvol >> 8;
- if(a < (short)0x8000)
- a = 0x8000;
- *p++ = a;
- }
- if(write(afd, buf, n) != n)
- break;
- }
- close(afd);
- close(fd);
-}
-
-void
-CDAudio_Play(byte nt, qboolean loop)
-{
- if(ctid < 0)
- return;
- nt -= 1; /* d001 was assumed part of the track list */
- if(nt < 1 || nt > ntrk){
- Con_Printf("cd: invalid track number %ud\n", nt);
- return;
- }
-
- chtrk = nt;
- cdloop = loop;
- if(cdvol > 0)
- cdread = 1;
-}
-
-void
-CDAudio_Stop(void)
-{
- cdread = 0;
- cdloop = 0;
-}
-
-void
-CDAudio_Pause(void)
-{
- cdread = 0;
-}
-
-void
-CDAudio_Resume(void)
-{
- cdread = 1;
-}
-
-void
-CD_f(void)
-{
- char *cmd;
-
- if(Cmd_Argc() < 2)
- return;
- cmd = Cmd_Argv(1);
- if(cistrcmp(cmd, "play") == 0){
- CDAudio_Play((uchar)atoi(Cmd_Argv(2)), false);
- return;
- }else if(cistrcmp(cmd, "loop") == 0){
- CDAudio_Play((uchar)atoi(Cmd_Argv(2)), true);
- return;
- }else if(cistrcmp(cmd, "stop") == 0){
- CDAudio_Stop();
- return;
- }else if(cistrcmp(cmd, "pause") == 0){
- CDAudio_Pause();
- return;
- }else if(cistrcmp(cmd, "resume") == 0){
- CDAudio_Resume();
- return;
- }else if(cistrcmp(cmd, "info") == 0){
- Con_Printf("track %ud/%ud; loop %d; vol %d\n", trk, ntrk, cdloop, cdvol);
- return;
- }
-}
-
-void
-CDAudio_Update(void)
-{
- int v;
-
- v = cdvol;
- cdvol = bgmvolume.value * 256;
- if(v <= 0 && cdvol > 0)
- cdread = 1;
- else if(v > 0 && cdvol <= 0)
- cdread = 0;
-}
-
-int
-CDAudio_Init(void)
-{
- if(cls.state == ca_dedicated)
- return -1;
- pat = regcomp("[au][0-9][0-9][0-9]");
- if(cdinfo() < 0)
- return -1;
- if((ctid = proccreate(cproc, nil, 16384)) < 0)
- sysfatal("proccreate: %r");
-
- Cmd_AddCommand("cd", CD_f);
-
- Con_Printf("CD Audio Initialized\n");
- return 0;
-}
-
-void
-CDAudio_Shutdown(void)
-{
- if(ctid < 0)
- return;
-
- CDAudio_Stop();
- postnote(PNPROC, ctid, "shutdown");
- ctid = -1;
- free(pat);
- pat = nil;
- cdread = cdloop = 0;
-}
--- a/cdaudio.h
+++ /dev/null
@@ -1,7 +1,0 @@
-int CDAudio_Init(void);
-void CDAudio_Play(byte track, qboolean looping);
-void CDAudio_Stop(void);
-void CDAudio_Pause(void);
-void CDAudio_Resume(void);
-void CDAudio_Shutdown(void);
-void CDAudio_Update(void);
--- a/cl_parse.c
+++ b/cl_parse.c
@@ -841,9 +841,9 @@
cl.paused = MSG_ReadByte ();
if (cl.paused)
- CDAudio_Pause ();
+ pausecd();
else
- CDAudio_Resume ();
+ resumecd();
}
break;
@@ -876,11 +876,11 @@
case svc_cdtrack:
cl.cdtrack = MSG_ReadByte ();
- cl.looptrack = MSG_ReadByte ();
+ MSG_ReadByte(); /* looptrack */
if((cls.demoplayback || cls.demorecording) && cls.forcetrack > 0)
- CDAudio_Play ((byte)cls.forcetrack, true);
+ startcd(cls.forcetrack, 1);
else
- CDAudio_Play ((byte)cl.cdtrack, true);
+ startcd(cl.cdtrack, 1);
break;
case svc_intermission:
--- a/client.h
+++ b/client.h
@@ -193,7 +193,7 @@
int num_statics; // held in cl_staticentities array
entity_t viewent; // the gun model
- int cdtrack, looptrack; // cd audio
+ int cdtrack;
// frag scoreboard
scoreboard_t *scores; // [cl.maxclients]
--- a/fns.h
+++ b/fns.h
@@ -1,4 +1,9 @@
+void stepcd(void);
void stepsnd(vec3_t, vec3_t, vec3_t, vec3_t);
+void stopcd(void);
+void pausecd(void);
+void resumecd(void);
+void startcd(int, int);
void stopallsfx(void);
void stopsfx(int, int);
void startsfx(int, int, Sfx *, vec3_t, float, float);
@@ -6,7 +11,9 @@
void staticsfx(Sfx *, vec3_t, float, float);
void touchsfx(char *);
Sfx* precachesfx(char *);
+void shutcd(void);
void shutsnd(void);
+int initcd(void);
int initsnd(void);
void setcvar(char*, char*);
void setcvarv(char*, float);
--- a/host.c
+++ b/host.c
@@ -570,7 +570,7 @@
else
stepsnd (vec3_origin, vec3_origin, vec3_origin, vec3_origin);
- CDAudio_Update();
+ stepcd();
if (host_speeds.value)
{
@@ -682,7 +682,8 @@
R_Init ();
if(initsnd() < 0)
fprint(2, "initsnd: %r\n");
- CDAudio_Init ();
+ if(initcd() < 0)
+ fprint(2, "initcd: %r\n");
Sbar_Init ();
CL_Init ();
}
@@ -721,8 +722,8 @@
dumpcfg();
- CDAudio_Shutdown ();
NET_Shutdown ();
+ shutcd();
shutsnd();
IN_Shutdown ();
--- a/mkfile
+++ b/mkfile
@@ -4,7 +4,6 @@
TARG=quake
OFILES=\
- cd.$O\
cl_demo.$O\
cl_input.$O\
cl_main.$O\
@@ -79,7 +78,6 @@
adivtab.h\
anorms.h\
bspfile.h\
- cdaudio.h\
client.h\
cmd.h\
common.h\
--- a/quakedef.h
+++ b/quakedef.h
@@ -188,7 +188,6 @@
#include "console.h"
#include "view.h"
#include "menu.h"
-#include "cdaudio.h"
/* included here to avoid type incompatibilities errors from 2c(1),2l(1) */
#include "r_local.h"
--- a/snd.c
+++ b/snd.c
@@ -46,6 +46,11 @@
static Sfx *ambsfx[Namb];
+static char cdfile[13];
+static int ntrk;
+static int cdfd = -1;
+static int cdread, cdloop, cdvol;
+
typedef struct
{
int length;
@@ -324,6 +329,13 @@
return sc;
}
+void
+stepcd(void)
+{
+ cdvol = bgmvolume.value * 256;
+ cdread = cdfd >= 0 && cdvol > 0;
+}
+
static void
sndout(void)
{
@@ -335,7 +347,8 @@
pb = sampbuf;
pe = sampbuf + nsamp * 2;
while(pb < pe){
- v = *pb++ * vol >> 8;
+ v = (short)(p[1] << 8 | p[0]) * cdvol >> 8;
+ v += *pb++ * vol >> 8;
if(v > 0x7fff)
v = 0x7fff;
else if(v < -0x8000)
@@ -426,6 +439,25 @@
}
static void
+readcd(int ns)
+{
+ int n;
+
+ if(cdfd < 0 || !cdread)
+ return;
+ if(n = readn(cdfd, mixbuf, ns), n != ns){
+ if(n < 0 || !cdloop)
+ stopcd();
+ else{
+ seek(cdfd, 0, 0);
+ ns -= n;
+ if(n = readn(cdfd, mixbuf+n, ns), n != ns)
+ stopcd();
+ }
+ }
+}
+
+static void
spatialize(Chan *c)
{
vec_t Δr, m;
@@ -491,6 +523,7 @@
void
stepsnd(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
{
+ int ns;
Chan *c, *sum;
if(afd < 0)
@@ -534,10 +567,12 @@
nsamp = nsamp + 15 & ~15;
if(nsamp > Ssamp)
nsamp = Ssamp;
+ ns = nsamp * Sblk;
+ memset(mixbuf, 0, ns);
+ readcd(ns);
samplesfx();
sampt += nsamp;
- nsamp *= Sblk;
- if(write(afd, mixbuf, nsamp) != nsamp){
+ if(write(afd, mixbuf, ns) != ns){
fprint(2, "sndwrite: %r\n");
shutsnd();
}
@@ -545,6 +580,46 @@
}
void
+stopcd(void)
+{
+ if(cdfd >= 0)
+ close(cdfd);
+ cdread = 0;
+ cdloop = 0;
+}
+
+void
+pausecd(void)
+{
+ cdread = 0;
+}
+
+void
+resumecd(void)
+{
+ cdread = 1;
+}
+
+void
+startcd(int nt, int loop)
+{
+ if(ntrk < 1)
+ return;
+ nt -= 1; /* d001 assumed part of track list */
+ if(nt < 1 || nt > ntrk){
+ fprint(2, "startcd: invalid track number %ud\n", nt);
+ return;
+ }
+ if(cdfd = open(va("%s%03d", cdfile, nt), OREAD), cdfd < 0){
+ fprint(2, "startcd: open: %r\n");
+ return;
+ }
+ cdloop = loop;
+ if(cdvol > 0)
+ cdread = 1;
+}
+
+void
stopallsfx(void)
{
if(afd < 0)
@@ -721,6 +796,33 @@
}
static void
+cdcmd(void)
+{
+ char *c;
+
+ if(Cmd_Argc() < 2){
+usage:
+ Con_Printf("cd (play|loop|stop|pause|resume|info) [track]\n");
+ return;
+ }
+ c = Cmd_Argv(1);
+ if(cistrcmp(c, "play") == 0){
+ if(Cmd_Argc() < 2)
+ goto usage;
+ startcd(atoi(Cmd_Argv(2)), 0);
+ }else if(cistrcmp(c, "loop") == 0){
+ if(Cmd_Argc() < 2)
+ goto usage;
+ startcd(atoi(Cmd_Argv(2)), 1);
+ }else if(cistrcmp(c, "stop") == 0)
+ stopcd();
+ else if(cistrcmp(c, "pause") == 0)
+ pausecd();
+ else if(cistrcmp(c, "resume") == 0)
+ resumecd();
+}
+
+static void
playsfx(void)
{
static int hash = 345;
@@ -791,11 +893,62 @@
}
void
+shutcd(void)
+{
+ stopcd();
+}
+
+void
shutsnd(void)
{
if(afd < 0)
return;
close(afd);
+}
+
+static int
+cdinfo(void)
+{
+ int fd, i, n, nt;
+ char *t, types[] = {'a', 'u', 0};
+ Dir *d;
+
+ ntrk = 0;
+ if(fd = open("/mnt/cd", OREAD), fd < 0)
+ return -1;
+ if(n = dirreadall(fd, &d), n < 0){
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ t = types;
+ for(;;){
+ for(nt=0, i=0; i<n; i++)
+ if(strcmp(d[i].name, va("%c%03d", *t, ntrk+1)) == 0){
+ ntrk++;
+ nt = 1;
+ }
+ if(ntrk < 1){
+ if(*++t == 0){
+ werrstr("cdinfo: no tracks found");
+ break;
+ }
+ }else if(nt == 0){
+ snprint(cdfile, sizeof cdfile, "/mnt/cd/%c", *t);
+ break;
+ }
+ }
+ free(d);
+ return ntrk < 1 ? -1 : 0;
+}
+
+int
+initcd(void)
+{
+ if(cdinfo() < 0)
+ return -1;
+ Cmd_AddCommand("cd", cdcmd);
+ return 0;
}
int