shithub: libtags

Download patch

ref: 63b1d8e124c602cf5bec357e1f04653a86e6af52
parent: 17e82bf4cde80c08cf38d331bf0715d38e50971d
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Thu Dec 19 16:18:23 EST 2019

optional TOC handler

--- a/examples/readtags.c
+++ b/examples/readtags.c
@@ -38,7 +38,7 @@
 };
 
 static void
-cb(Tagctx *ctx, int t, const char *k, const char *v, int offset, int size, Tagread f)
+tag(Tagctx *ctx, int t, const char *k, const char *v, int offset, int size, Tagread f)
 {
 	USED(ctx); USED(k); USED(f);
 	if(t == Timage)
@@ -47,6 +47,12 @@
 		print("%-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)
 {
@@ -71,7 +77,8 @@
 	{
 		.read = ctxread,
 		.seek = ctxseek,
-		.tag = cb,
+		.tag = tag,
+		.toc = toc,
 		.buf = buf,
 		.bufsz = sizeof(buf),
 		.aux = &aux,
--- a/id3v2.c
+++ b/id3v2.c
@@ -294,10 +294,10 @@
 static void
 getduration(Tagctx *ctx, int offset)
 {
-	uvlong n, framelen, samplespf;
+	uvlong n, framelen, samplespf, toc;
 	uchar *b;
 	uint x;
-	int xversion, xlayer, xbitrate;
+	int xversion, xlayer, xbitrate, i;
 
 	if(ctx->read(ctx, ctx->buf, 256) != 256)
 		return;
@@ -330,10 +330,23 @@
 				if(ctx->duration == 0 && framelen > 0)
 					ctx->duration = n * samplespf * 1000 / framelen / ctx->samplerate;
 
-				if((x & 4) != 0){ /* TOC is set */
-					/* not doing anything yet */
+				if((x & 4) != 0 && ctx->toc != nil){ /* TOC is set */
+					toc = offset + 100 + (char*)b - ctx->buf;
+					if((x & 8) != 0) /* VBR scale */
+						toc += 4;
+					for(i = 0; i < 100; i++){
+						/*
+						 * offset = n * b[i] / 256
+						 * ms = i * duration / 100
+						 */
+						ctx->toc(ctx, i * ctx->duration / 100, toc + (n * b[i]) / 256);
+					}
+					b += 100;
+					if((x & 8) != 0) /* VBR scale */
+						b += 4;
 				}
 			}
+			offset += (char*)b - ctx->buf;
 		}else if(memcmp(&ctx->buf[0x24], "VBRI", 4) == 0){
 			n = beuint((uchar*)&ctx->buf[0x32]);
 			ctx->duration = n * samplespf * 1000 / ctx->samplerate;
--- a/tags.h
+++ b/tags.h
@@ -53,6 +53,9 @@
 	 */
 	void (*tag)(Tagctx *ctx, int type, const char *k, const char *s, int offset, int size, Tagread f);
 
+	/* Approximate millisecond-to-byte offsets within the file, if available. This callback is optional. */
+	void (*toc)(Tagctx *ctx, int ms, int offset);
+
 	/* Auxiliary data. Not used by libtags. */
 	void *aux;