shithub: qk1

Download patch

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