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);