ref: c138c7d8813dcd77cfe33e37f1416427819b5e93
parent: b868b9919f570cbcbdb3c713bf1431b9d843ea43
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue Jun 27 11:10:37 EDT 2023
readtags, zuke: extract cover images stored in the audio files (thanks g-w1)
--- a/sys/src/cmd/audio/readtags/readtags.c
+++ b/sys/src/cmd/audio/readtags/readtags.c
@@ -24,10 +24,47 @@
[Timage] = "image",
};
+static int image;
+
static void
tag(Tagctx *ctx, int t, const char *k, const char *v, int offset, int size, Tagread f)
{- USED(ctx); USED(k); USED(f);
+ char *prog, *buf, tmp[32];
+ int p[2], n, pid;
+ Waitmsg *w;
+
+ USED(k);
+ if(image){+ if(t != Timage)
+ return;
+ prog = nil;
+ if(strcmp(v, "image/jpeg") == 0)
+ prog = "jpg";
+ else if(strcmp(v, "image/png") == 0)
+ prog = "png";
+ else
+ sysfatal("unknown image type: %s", v);+ if((buf = malloc(size)) == nil)
+ sysfatal("no memory");+ if(ctx->seek(ctx, offset, 0) != offset || (n = ctx->read(ctx, buf, size)) != size)
+ sysfatal("image load failed");+ if(f != nil)
+ n = f(buf, &n);
+ pipe(p);
+ if((pid = rfork(RFPROC|RFFDG|RFNOTEG|RFCENVG)) < 0)
+ sysfatal("rfork: %r");+ if(pid == 0){+ dup(p[0], 0); close(p[0]);
+ close(p[1]);
+ snprint(tmp, sizeof(tmp), "/bin/%s", prog);
+ execl(tmp, prog, "-9t", nil);
+ sysfatal("execl: %r");+ }
+ close(p[0]);
+ write(p[1], buf, n);
+ close(p[1]);
+ exits((w = wait()) != nil ? w->msg : nil);
+ }
if(t == Timage)
print("%-12s %s %d %d\n", t2s[t], v, offset, size);else if(t != Tunknown)
@@ -57,7 +94,7 @@
static void
usage(void)
{- fprint(2, "usage: %s FILE...\n", argv0);
+ fprint(2, "usage: %s [-i] [file ...]\n", argv0);
exits("usage");}
@@ -79,21 +116,29 @@
};
ARGBEGIN{+ case 'i':
+ image++;
+ break;
default:
usage();
}ARGEND
- if(argc < 1)
- usage();
+ i = 0;
+ if(argc < 1){+ aux.fd = 0;
+ goto stdin;
+ }
- for(i = 0; i < argc; i++){- print("*** %s\n", argv[i]);+ for(; i < argc; i++){+ if(!image)
+ print("*** %s\n", argv[i]);if((aux.fd = open(argv[i], OREAD)) < 0)
print("failed to open\n"); else{- if(tagsget(&ctx) != 0)
+stdin:
+ if(tagsget(&ctx) != 0 && !image)
print("no tags or failed to read tags\n");- else{+ else if(!image){if(ctx.duration > 0)
print("%-12s %d ms\n", "duration", ctx.duration);if(ctx.samplerate > 0)
@@ -105,8 +150,11 @@
}
close(aux.fd);
}
- print("\n");+ if(!image)
+ print("\n");}
+ if(image)
+ sysfatal("no image found");exits(nil);
}
--- a/sys/src/cmd/audio/zuke/zuke.c
+++ b/sys/src/cmd/audio/zuke/zuke.c
@@ -493,7 +493,7 @@
coverload(void *player_)
{int p[2], pid, fd, i;
- char *prog, *path, *s, tmp[32];
+ char *prog, *path, *s, tmp[64];
Meta *m;
Channel *ch;
Player *player;
@@ -507,14 +507,9 @@
fd = -1;
prog = nil;
- if(m->imagefmt != nil && m->imagereader == 0){- if(strcmp(m->imagefmt, "image/png") == 0)
- prog = "png";
- else if(strcmp(m->imagefmt, "image/jpeg") == 0)
- prog = "jpg";
- }
-
- if(prog == nil){+ if(m->imagefmt != nil)
+ prog = "audio/readtags -i";
+ else{path = strdup(m->path);
if(path != nil && (s = utfrrune(path, '/')) != nil){*s = 0;
@@ -521,11 +516,11 @@
for(i = 0; i < nelem(covers) && prog == nil; i++){ if((s = smprint("%s/%s.jpg", path, covers[i])) != nil && (fd = open(s, OREAD|OCEXEC)) >= 0)- prog = "jpg";
+ prog = "jpg -9t";
free(s);
s = nil;
if(fd < 0 && (s = smprint("%s/%s.png", path, covers[i])) != nil && (fd = open(s, OREAD|OCEXEC)) >= 0)- prog = "png";
+ prog = "png -9t";
free(s);
}
}
@@ -534,11 +529,9 @@
if(prog == nil)
goto done;
-
- if(fd < 0){+ if(fd < 0)
fd = open(m->path, OREAD|OCEXEC);
- seek(fd, m->imageoffset, 0);
- }
+ snprint(tmp, sizeof(tmp), "%s | resample -x%d", prog, Coversz);
pipe(p);
if((pid = rfork(RFPROC|RFFDG|RFNOTEG|RFCENVG|RFNOWAIT)) == 0){dup(fd, 0); close(fd);
@@ -547,7 +540,6 @@
dup(fd = open("/dev/null", OWRITE), 2);close(fd);
}
- snprint(tmp, sizeof(tmp), "%s -9t | resample -x%d", prog, Coversz);
execl("/bin/rc", "rc", "-c", tmp, nil); sysfatal("execl: %r");}
@@ -556,6 +548,7 @@
if(pid > 0){newcover = readimage(display, p[0], 1);
+ /* if readtags fails, readimage will also fail, and we send nil over ch */
sendp(ch, newcover);
}
close(p[0]);
@@ -1206,7 +1199,7 @@
for(; (i = chartorune(&c, s)) > 0 && c != Runeerror; s += i)
sendul(kbd, c);
continue;
- }
+ }
if(*s != '/' && m->wdir != nil)
s = smprint("%s/%.*s", m->wdir, m->ndata, m->data);--
⑨