code: plan9front

Download patch

ref: be36c092ac061a04065720e98e5849130487be7f
parent: 2204634275cbb3337cfc7cc994b57f9aa4017d0d
author: Jacob Moody <moody@posixcafe.org>
date: Sat Jul 17 14:56:11 EDT 2021

aux/cddb: Provide -e option to print commands to rip audio with tags.

Also parse title/track artist and year.

--- a/sys/man/4/cdfs
+++ b/sys/man/4/cdfs
@@ -19,6 +19,9 @@
 ] [
 .B -s
 .I server
+] [
+.B -e
+.I dir
 ]
 .B query
 .I diskid
@@ -175,7 +178,7 @@
 Additional lines may further describe the current disc.
 .PP
 .I Aux/cddb
-takes 4 optional arguments.
+takes 5 optional arguments.
 The
 .B -s
 option makes
@@ -183,7 +186,7 @@
 use
 .I server
 for the query instead of
-.LR freedb.freedb.org .
+.LR gnudb.org .
 The
 .B -D
 option causes the raw database response from the server to be dumped
@@ -195,6 +198,12 @@
 is like
 .B -t
 but prints a final line with the total time.
+The
+.B -e
+option will print rc commands using
+.IR audio/flacenc (1)
+to encode and tag audio tracks from the disc to output directory
+.I dir .
 .SH EXAMPLES
 Backup to a BD-R disc:
 .br
--- a/sys/src/cmd/aux/cddb.c
+++ b/sys/src/cmd/aux/cddb.c
@@ -9,11 +9,13 @@
 #define DPRINT if(debug)fprint
 int tflag;
 int Tflag;
+char *eflag;
 
 typedef struct Track Track;
 struct Track {
 	int n;
 	char *title;
+	char *artist;
 };
 
 enum {
@@ -25,6 +27,8 @@
 	ulong diskid;
 	int ntrack;
 	char *title;
+	char *year;
+	char *artist;
 	Track track[MTRACK];
 };
 
@@ -55,17 +59,23 @@
 {
 	int i, n, s;
 
-	print("title	%s\n", t->title);
+	print("title\t%s\n", t->title);
+	if(t->year[0] != 0)
+		print("year\t%s\n", t->year);
+	if(t->artist[0] != 0)
+		print("artist\t%s\n", t->artist);
 	for(i=0; i<t->ntrack; i++){
+		print("%d\t%s", i+1, t->track[i].title);
 		if(tflag){
 			n = t->track[i+1].n;
 			if(i == t->ntrack-1)
 				n *= 75;
 			s = (n - t->track[i].n)/75;
-			print("%d\t%s\t%d:%2.2d\n", i+1, t->track[i].title, s/60, s%60);
+			print("\t%d:%2.2d", s/60, s%60); 
 		}
-		else
-			print("%d\t%s\n", i+1, t->track[i].title);
+		if(t->track[i].artist[0] != 0)
+			print("\t%s", t->track[i].artist);
+		print("\n");
 	}
 	if(Tflag){
 		s = t->track[i].n;
@@ -73,23 +83,40 @@
 	}
 }
 
-char*
-append(char *a, char *b)
+static void
+dumpencode(Toc *t)
 {
-	char *c;
+	int i;
 
-	c = emalloc(strlen(a)+strlen(b)+1);
-	strcpy(c, a);
-	strcat(c, b);
-	return c;
+	quotefmtinstall();
+	for(i=0; i < t->ntrack; i++){
+		print("</mnt/cd/a%03d audio/flacenc ", i);
+		print("-T 'title='^%q -T 'trackno=%d' ", t->track[i].title, i+1);
+		if(t->year[0] != 0)
+			print("-T 'year='^%q ", t->year);
+		if(t->track[i].artist[0] != 0 || t->artist[0] != 0)
+			print("-T 'artist='^%q ", t->track[i].artist[0] != 0 ? t->track[i].artist : t->artist);
+		print(">%q/a%03d.flac\n", eflag, i);
+	}
 }
 
+static char*
+split(char *s)
+{
+	char *p;
+
+	if((p = strchr(s, '/')) == nil)
+		return nil;
+	p[-1] = 0;
+	return p+2;
+}
+
 static int
 cddbfilltoc(Toc *t)
 {
 	int fd;
 	int i;
-	char *p, *q;
+	char *p, *q, *a;
 	Biobuf bin;
 	char *f[10];
 	int nf;
@@ -183,8 +210,12 @@
 	}
 
 	t->title = "";
-	for(i=0; i<t->ntrack; i++)
+	t->artist = "";
+	t->year = "";
+	for(i=0; i<t->ntrack; i++) {
 		t->track[i].title = "";
+		t->track[i].artist = "";
+	}
 
 	/* fetch results for this cd */
 	fprint(fd, "cddb read %s %s\r\n", categ, id);
@@ -195,8 +226,18 @@
 		while(isspace(*q))
 			*q-- = 0;
 DPRINT(2, "cddb %s\n", p);
-		if(strncmp(p, "DTITLE=", 7) == 0)
-			t->title = append(t->title, p+7);
+		if(strncmp(p, "DTITLE=", 7) == 0) {
+			p += 7;
+			a = split(p);
+			if(a != nil) {
+				t->artist = estrdup(p);
+				p = a;
+			}
+			t->title = estrdup(p);
+		}
+		else if(strncmp(p, "DYEAR=", 6) == 0) {
+			t->year = estrdup(p+6);
+		}
 		else if(strncmp(p, "TTITLE", 6) == 0 && isdigit(p[6])) {
 			i = atoi(p+6);
 			if(i < t->ntrack) {
@@ -205,8 +246,12 @@
 					p++;
 				if(*p == '=')
 					p++;
-
-				t->track[i].title = append(t->track[i].title, estrdup(p));
+				a = split(p);
+				if(a != nil) {
+					t->track[i].artist = estrdup(p);
+					p = a;
+				}
+				t->track[i].title = estrdup(p);	
 			}
 		} 
 	} while(*p != '.');
@@ -238,6 +283,9 @@
 	case 's':
 		server = EARGF(usage());
 		break;
+	case 'e':
+		eflag = EARGF(usage());
+		break;
 	case 'T':
 		Tflag = 1;
 		/*FALLTHROUGH*/
@@ -260,6 +308,9 @@
 	if(cddbfilltoc(&toc) < 0)
 		exits("whoops");
 
-	dumpcddb(&toc);
+	if(eflag != nil)
+		dumpencode(&toc);
+	else
+		dumpcddb(&toc);
 	exits(nil);
 }