#include <stdio.h>#include <stdbool.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include "tags.h" #define USED(x) (void)x typedef struct Aux Aux; struct Aux { int fd;}; static const char *t2s[] = { [Talbum] = "album", [Talbumartist] = "albumartist", [Talbumgain] = "albumgain", [Talbumpeak] = "albumpeak", [Tartist] = "artist", [Tcomment] = "comment", [Tcomposer] = "composer", [Tdate] = "date", [Tgenre] = "genre", [Timage] = "image", [Ttitle] = "title", [Ttrack] = "track", [Ttrackgain] = "trackgain", [Ttrackpeak] = "trackpeak",}; static bool image; static voidtag(Tagctx *ctx, int t, const char *k, const char *v, int offset, int size, Tagread f){ USED(k); USED(f); if(image){ if(t != Timage) return; char *raw = malloc(size); Aux *aux = ctx->aux; int prevoffset = lseek(aux->fd, 0, 1); if(lseek(aux->fd, offset, 0) != offset || read(aux->fd, raw, size) != size || (f != NULL && f(raw, &size) != 0)){ fprintf(stderr, "failed to read the image\n"); exit(1); } lseek(aux->fd, prevoffset, 0); write(1, raw, size); exit(0); return; } if(t == Timage) printf("%-12s %s %d %d\n", t2s[t], v, offset, size); else if(t == Tunknown) printf("%-12s %s\n", k, v); else printf("%-12s %s\n", t2s[t], v);} static voidtoc(Tagctx *ctx, int ms, int offset){ USED(ctx); USED(ms); USED(offset);} static intctxread(Tagctx *ctx, void *buf, int cnt){ Aux *aux = ctx->aux; return read(aux->fd, buf, cnt);} static intctxseek(Tagctx *ctx, int offset, int whence){ Aux *aux = ctx->aux; return lseek(aux->fd, offset, whence);} intmain(int argc, char **argv){ int i; char buf[256], *argv0; Aux aux; Tagctx ctx = { .read = ctxread, .seek = ctxseek, .tag = tag, .toc = toc, .buf = buf, .bufsz = sizeof(buf), .aux = &aux, }; argv0 = argv[0]; if(argc > 1 && strcmp(argv[1], "-i") == 0){ image = true; argc--; argv++; } if(argc < 2){ fprintf(stderr, "usage: %s [-i] FILE...\n", argv0); return 1; } for(i = 1; i < argc; i++){ if(!image) printf("*** %s\n", argv[i]); if((aux.fd = open(argv[i], O_RDONLY)) < 0) perror("failed to open"); else{ if(tagsget(&ctx) != 0){ fprintf(stderr, "no tags or failed to read tags\n"); return 1; }else if(image){ fprintf(stderr, "no images found\n"); return 1; }else{ if(ctx.duration > 0) printf("%-12s %d ms\n", "duration", ctx.duration); if(ctx.samplerate > 0) printf("%-12s %d\n", "samplerate", ctx.samplerate); if(ctx.channels > 0) printf("%-12s %d\n", "channels", ctx.channels); if(ctx.bitrate > 0) printf("%-12s %d\n", "bitrate", ctx.bitrate); } close(aux.fd); } if(i+1 < argc) printf("\n"); } return 0;}
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "tags.h"
#define USED(x) (void)x
typedef struct Aux Aux;
struct Aux {
int fd;
};
static const char *t2s[] = {
[Talbum] = "album",
[Talbumartist] = "albumartist",
[Talbumgain] = "albumgain",
[Talbumpeak] = "albumpeak",
[Tartist] = "artist",
[Tcomment] = "comment",
[Tcomposer] = "composer",
[Tdate] = "date",
[Tgenre] = "genre",
[Timage] = "image",
[Ttitle] = "title",
[Ttrack] = "track",
[Ttrackgain] = "trackgain",
[Ttrackpeak] = "trackpeak",
};
static bool image;
static void
tag(Tagctx *ctx, int t, const char *k, const char *v, int offset, int size, Tagread f)
{
USED(k); USED(f);
if(image){
if(t != Timage)
return;
char *raw = malloc(size);
Aux *aux = ctx->aux;
int prevoffset = lseek(aux->fd, 0, 1);
if(lseek(aux->fd, offset, 0) != offset ||
read(aux->fd, raw, size) != size ||
(f != NULL && f(raw, &size) != 0)){
fprintf(stderr, "failed to read the image\n");
exit(1);
}
lseek(aux->fd, prevoffset, 0);
write(1, raw, size);
exit(0);
return;
}
if(t == Timage)
printf("%-12s %s %d %d\n", t2s[t], v, offset, size);
else if(t == Tunknown)
printf("%-12s %s\n", k, v);
else
printf("%-12s %s\n", t2s[t], v);
}
static void
toc(Tagctx *ctx, int ms, int offset)
{
USED(ctx); USED(ms); USED(offset);
}
static int
ctxread(Tagctx *ctx, void *buf, int cnt)
{
Aux *aux = ctx->aux;
return read(aux->fd, buf, cnt);
}
static int
ctxseek(Tagctx *ctx, int offset, int whence)
{
Aux *aux = ctx->aux;
return lseek(aux->fd, offset, whence);
}
int
main(int argc, char **argv)
{
int i;
char buf[256], *argv0;
Aux aux;
Tagctx ctx = {
.read = ctxread,
.seek = ctxseek,
.tag = tag,
.toc = toc,
.buf = buf,
.bufsz = sizeof(buf),
.aux = &aux,
};
argv0 = argv[0];
if(argc > 1 && strcmp(argv[1], "-i") == 0){
image = true;
argc--;
argv++;
}
if(argc < 2){
fprintf(stderr, "usage: %s [-i] FILE...\n", argv0);
return 1;
}
for(i = 1; i < argc; i++){
if(!image)
printf("*** %s\n", argv[i]);
if((aux.fd = open(argv[i], O_RDONLY)) < 0)
perror("failed to open");
else{
if(tagsget(&ctx) != 0){
fprintf(stderr, "no tags or failed to read tags\n");
return 1;
}else if(image){
fprintf(stderr, "no images found\n");
return 1;
}else{
if(ctx.duration > 0)
printf("%-12s %d ms\n", "duration", ctx.duration);
if(ctx.samplerate > 0)
printf("%-12s %d\n", "samplerate", ctx.samplerate);
if(ctx.channels > 0)
printf("%-12s %d\n", "channels", ctx.channels);
if(ctx.bitrate > 0)
printf("%-12s %d\n", "bitrate", ctx.bitrate);
}
close(aux.fd);
}
if(i+1 < argc)
printf("\n");
}
return 0;
}