shithub: libtags

Download patch

ref: 5d5b02ab50f08d12ad930e18c69ba2a2b852e547
parent: d8185e7273233384dcf32da043c28446082df1d2
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Wed Dec 18 15:20:24 EST 2019

change callback api to include raw "key" of the tag, add Tunknown type. this allows programs to read ALL text tags

--- a/README.md
+++ b/README.md
@@ -38,4 +38,4 @@
 Just compile it to an archive (`.a`) and link to your program. Use it in your code
 by including `tags.h`, that's the API. Documentation is in the header.
 
-See `examples/readtags.c`.
+See `examples/readtags.c`. You can compile like so: `gcc examples/readtags.c src/*.c -Isrc -o readtags`.
--- a/default.nix
+++ /dev/null
@@ -1,22 +1,0 @@
-{ stdenv, mk, pkgconfig, fetchgitLocal }:
-
-stdenv.mkDerivation rec {
-  name = "libtags";
-  src = ./.;#fetchgitLocal ./.;
-
-  buildInputs = [ mk ];
-  propagatedBuildInputs = [ pkgconfig ];
-  enableParallelBuilding = true;
-
-  installPhase = ''
-    cd src && mk -f mkfile.nix install && cd ..
-    cd examples && mk -f mkfile.nix install INCLUDES=-I$out/include LIBS="-L$out/lib -ltags"
-  '';
-
-  meta = {
-    description = "A cross-platform library for reading tags, designed for highly constrained environments";
-    maintainers = with stdenv.lib.maintainers; [ ftrvxmtrx ];
-    platforms = stdenv.lib.platforms.unix;
-    license = stdenv.lib.licenses.mit;
-  };
-}
--- a/examples/readtags.c
+++ b/examples/readtags.c
@@ -38,12 +38,12 @@
 };
 
 static void
-cb(Tagctx *ctx, int t, const char *v, int offset, int size, Tagread f)
+cb(Tagctx *ctx, int t, const char *k, const char *v, int offset, int size, Tagread f)
 {
-	USED(ctx); USED(offset); USED(size); USED(f);
+	USED(ctx); USED(k); USED(f);
 	if(t == Timage)
 		print("%-12s %s %d %d\n", t2s[t], v, offset, size);
-	else
+	else if(t != Tunknown)
 		print("%-12s %s\n", t2s[t], v);
 }
 
--- a/src/flac.c
+++ b/src/flac.c
@@ -51,7 +51,7 @@
 			offset = beuint(d) + ctx->seek(ctx, 0, 1) + 20;
 			ctx->read(ctx, d, 20);
 			n = beuint(&d[16]);
-			tagscallcb(ctx, Timage, mime, offset, n, nil);
+			tagscallcb(ctx, Timage, "", mime, offset, n, nil);
 		}else if((d[0] & 0x7f) == 4){ /* 4 = vorbis comment */
 			int i, numtags, tagsz, vensz;
 			char *k, *v;
--- a/src/id3v1.c
+++ b/src/id3v1.c
@@ -26,23 +26,23 @@
 		return -1;
 
 	if((ctx->found & 1<<Ttitle) == 0 && iso88591toutf8(out, Outsz, &in[3], 30) > 0)
-		txtcb(ctx, Ttitle, out);
+		txtcb(ctx, Ttitle, "", out);
 	if((ctx->found & 1<<Tartist) == 0 && iso88591toutf8(out, Outsz, &in[33], 30) > 0)
-		txtcb(ctx, Tartist, out);
+		txtcb(ctx, Tartist, "", out);
 	if((ctx->found & 1<<Talbum) == 0 && iso88591toutf8(out, Outsz, &in[63], 30) > 0)
-		txtcb(ctx, Talbum, out);
+		txtcb(ctx, Talbum, "", out);
 
 	in[93+4] = 0;
 	if((ctx->found & 1<<Tdate) == 0 && in[93] != 0)
-		txtcb(ctx, Tdate, &in[93]);
+		txtcb(ctx, Tdate, "", &in[93]);
 
 	if((ctx->found & 1<<Ttrack) == 0 && in[125] == 0 && in[126] > 0){
 		snprint((char*)out, Outsz, "%d", in[126]);
-		txtcb(ctx, Ttrack, out);
+		txtcb(ctx, Ttrack, "", out);
 	}
 
 	if((ctx->found & 1<<Tgenre) == 0 && in[127] < Numgenre)
-		txtcb(ctx, Tgenre, id3genres[in[127]]);
+		txtcb(ctx, Tgenre, "", id3genres[in[127]]);
 
 	return 0;
 }
--- a/src/id3v2.c
+++ b/src/id3v2.c
@@ -19,25 +19,25 @@
 {
 	k++;
 	if(strcmp(k, "AL") == 0 || strcmp(k, "ALB") == 0)
-		txtcb(ctx, Talbum, v);
+		txtcb(ctx, Talbum, k-1, v);
 	else if(strcmp(k, "PE1") == 0 || strcmp(k, "PE2") == 0 || strcmp(k, "P1") == 0 || strcmp(k, "P2") == 0)
-		txtcb(ctx, Tartist, v);
+		txtcb(ctx, Tartist, k-1, v);
 	else if(strcmp(k, "IT2") == 0 || strcmp(k, "T2") == 0)
-		txtcb(ctx, Ttitle, v);
+		txtcb(ctx, Ttitle, k-1, v);
 	else if(strcmp(k, "YE") == 0 || strcmp(k, "YER") == 0 || strcmp(k, "DRC") == 0)
-		txtcb(ctx, Tdate, v);
+		txtcb(ctx, Tdate, k-1, v);
 	else if(strcmp(k, "RK") == 0 || strcmp(k, "RCK") == 0)
-		txtcb(ctx, Ttrack, v);
+		txtcb(ctx, Ttrack, k-1, v);
 	else if(strcmp(k, "CO") == 0 || strcmp(k, "CON") == 0){
 		for(; v[0]; v++){
 			if(v[0] == '(' && v[1] <= '9' && v[1] >= '0'){
 				int i = atoi(&v[1]);
 				if(i < Numgenre)
-					txtcb(ctx, Tgenre, id3genres[i]);
+					txtcb(ctx, Tgenre, k-1, id3genres[i]);
 				for(v++; v[0] && v[0] != ')'; v++);
 				v--;
 			}else if(v[0] != '(' && v[0] != ')'){
-				txtcb(ctx, Tgenre, v);
+				txtcb(ctx, Tgenre, k-1, v);
 				break;
 			}
 		}
@@ -58,11 +58,12 @@
 				type = Talbumpeak;
 		}
 		if(type >= 0)
-			txtcb(ctx, type, v+5);
+			txtcb(ctx, type, k-1, v+5);
 		else
 			return 0;
-	}else
-		return 0;
+	}else{
+		txtcb(ctx, Tunknown, k-1, v);
+	}
 	return 1;
 }
 
@@ -98,11 +99,11 @@
 			peaks[sizeof(peaks)-1] = 0;
 
 			if(strcmp((char*)tag, "track") == 0){
-				txtcb(ctx, Ttrackgain, vas);
-				txtcb(ctx, Ttrackpeak, peaks);
+				txtcb(ctx, Ttrackgain, "RVA2", vas);
+				txtcb(ctx, Ttrackpeak, "RVA2", peaks);
 			}else if(strcmp((char*)tag, "album") == 0){
-				txtcb(ctx, Talbumgain, vas);
-				txtcb(ctx, Talbumpeak, peaks);
+				txtcb(ctx, Talbumgain, "RVA2", vas);
+				txtcb(ctx, Talbumpeak, "RVA2", peaks);
 			}
 			break;
 		}
@@ -171,7 +172,7 @@
 					break;
 				}
 			}
-			tagscallcb(ctx, Timage, b, offset+n, tsz-n, f);
+			tagscallcb(ctx, Timage, "APIC", b, offset+n, tsz-n, f);
 			n = 256;
 		}
 	}else if(strcmp((char*)d, "PIC") == 0){
@@ -189,7 +190,7 @@
 					break;
 				}
 			}
-			tagscallcb(ctx, Timage, strcmp(b, "JPG") == 0 ? "image/jpeg" : "image/png", offset+n, tsz-n, f);
+			tagscallcb(ctx, Timage, "PIC", strcmp(b, "JPG") == 0 ? "image/jpeg" : "image/png", offset+n, tsz-n, f);
 			n = 256;
 		}
 	}else if(strcmp((char*)d, "RVA2") == 0 && tsz >= 6+5){
--- a/src/m4a.c
+++ b/src/m4a.c
@@ -128,13 +128,13 @@
 				return -1;
 			sz -= 4;
 			snprint((char*)d, ctx->bufsz, "%d", beuint(d));
-			txtcb(ctx, type, d);
+			txtcb(ctx, type, "", d);
 		}else if(type == Tgenre){
 			if(ctx->read(ctx, d, 2) != 2)
 				return -1;
 			sz -= 2;
 			if((i = d[1]-1) >= 0 && i < Numgenre)
-				txtcb(ctx, type, id3genres[i]);
+				txtcb(ctx, type, "", id3genres[i]);
 		}else if(dtype == 1){ /* text */
 			if(sz >= ctx->bufsz) /* skip tags that can't fit into memory. ">=" because of '\0' */
 				continue;
@@ -141,12 +141,12 @@
 			if(ctx->read(ctx, d, sz) != sz)
 				return -1;
 			d[sz] = 0;
-			txtcb(ctx, type, d);
+			txtcb(ctx, type, "", d);
 			sz = 0;
 		}else if(type == Timage && dtype == 13) /* jpeg cover image */
-			tagscallcb(ctx, Timage, "image/jpeg", ctx->seek(ctx, 0, 1), sz, nil);
+			tagscallcb(ctx, Timage, "", "image/jpeg", ctx->seek(ctx, 0, 1), sz, nil);
 		else if(type == Timage && dtype == 14) /* png cover image */
-			tagscallcb(ctx, Timage, "image/png", ctx->seek(ctx, 0, 1), sz, nil);
+			tagscallcb(ctx, Timage, "", "image/png", ctx->seek(ctx, 0, 1), sz, nil);
 	}
 
 	return 0;
--- a/src/tags.c
+++ b/src/tags.c
@@ -26,11 +26,13 @@
 };
 
 void
-tagscallcb(Tagctx *ctx, int type, const char *s, int offset, int size, Tagread f)
+tagscallcb(Tagctx *ctx, int type, const char *k, const char *s, int offset, int size, Tagread f)
 {
-	ctx->found |= 1<<type;
-	ctx->tag(ctx, type, s, offset, size, f);
-	ctx->num++;
+	if(type != Tunknown){
+		ctx->found |= 1<<type;
+		ctx->num++;
+	}
+	ctx->tag(ctx, type, k, s, offset, size, f);
 }
 
 int
--- a/src/tags.h
+++ b/src/tags.h
@@ -8,6 +8,7 @@
 /* Tag type. */
 enum
 {
+	Tunknown = -1,
 	Tartist,
 	Talbum,
 	Ttitle,
@@ -43,13 +44,14 @@
 	int (*seek)(Tagctx *ctx, int offset, int whence);
 
 	/* Callback that is used by libtags to inform about the tags of a file.
-	 * "type" is the tag's type (Tartist, ...). "s" is the null-terminated string unless "type" is
+	 * "type" is the tag's type (Tartist, ...) or Tunknown if libtags doesn't know how to map a tag kind to
+	 * any of these. "k" is the raw key like "TPE1", "TPE2", etc. "s" is the null-terminated string unless "type" is
 	 * Timage. "offset" and "size" define the placement and size of the image cover ("type" = Timage)
 	 * inside the file, and "f" is not NULL in case reading the image cover requires additional
 	 * operations on the data, in which case you need to read the image cover as a stream and call this
 	 * function to apply these operations on the contents read.
 	 */
-	void (*tag)(Tagctx *ctx, int type, const char *s, int offset, int size, Tagread f);
+	void (*tag)(Tagctx *ctx, int type, const char *k, const char *s, int offset, int size, Tagread f);
 
 	/* Auxiliary data. Not used by libtags. */
 	void *aux;
--- a/src/tagspriv.h
+++ b/src/tagspriv.h
@@ -44,6 +44,6 @@
  */
 void cbvorbiscomment(Tagctx *ctx, char *k, char *v);
 
-void tagscallcb(Tagctx *ctx, int type, const char *s, int offset, int size, Tagread f);
+void tagscallcb(Tagctx *ctx, int type, const char *k, const char *s, int offset, int size, Tagread f);
 
-#define txtcb(ctx, type, s) tagscallcb(ctx, type, (const char*)s, 0, 0, nil)
+#define txtcb(ctx, type, k, s) tagscallcb(ctx, type, k, (const char*)s, 0, 0, nil)
--- a/src/vorbis.c
+++ b/src/vorbis.c
@@ -11,25 +11,27 @@
 	if(*v == 0)
 		return;
 	if(cistrcmp(k, "album") == 0)
-		txtcb(ctx, Talbum, v);
+		txtcb(ctx, Talbum, k, v);
 	else if(cistrcmp(k, "title") == 0)
-		txtcb(ctx, Ttitle, v);
+		txtcb(ctx, Ttitle, k, v);
 	else if(cistrcmp(k, "artist") == 0 || cistrcmp(k, "performer") == 0)
-		txtcb(ctx, Tartist, v);
+		txtcb(ctx, Tartist, k, v);
 	else if(cistrcmp(k, "tracknumber") == 0)
-		txtcb(ctx, Ttrack, v);
+		txtcb(ctx, Ttrack, k, v);
 	else if(cistrcmp(k, "date") == 0)
-		txtcb(ctx, Tdate, v);
+		txtcb(ctx, Tdate, k, v);
 	else if(cistrcmp(k, "replaygain_track_peak") == 0)
-		txtcb(ctx, Ttrackpeak, v);
+		txtcb(ctx, Ttrackpeak, k, v);
 	else if(cistrcmp(k, "replaygain_track_gain") == 0)
-		txtcb(ctx, Ttrackgain, v);
+		txtcb(ctx, Ttrackgain, k, v);
 	else if(cistrcmp(k, "replaygain_album_peak") == 0)
-		txtcb(ctx, Talbumpeak, v);
+		txtcb(ctx, Talbumpeak, k, v);
 	else if(cistrcmp(k, "replaygain_album_gain") == 0)
-		txtcb(ctx, Talbumgain, v);
+		txtcb(ctx, Talbumgain, k, v);
 	else if(cistrcmp(k, "genre") == 0)
-		txtcb(ctx, Tgenre, v);
+		txtcb(ctx, Tgenre, k, v);
+	else
+		txtcb(ctx, Tunknown, k, v);
 }
 
 int