shithub: libtags

ref: f68e997ecefd77b3d1cd33c21264d5ced6e5d021
dir: /tags.h/

View raw version
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

typedef union Tag Tag;
typedef struct Tagctx Tagctx;
typedef int (*Tagdecode)(void *buf, int *cnt);

/* Tag type. */
enum {
	Tunknown = -1,
	Tartist,
	Talbum,
	Ttitle,
	Tdate, /* "2014", "2015/02/01", but the year goes first */
	Ttrack, /* "1", "01", "1/4", but the track number goes first */
	Talbumgain, /* see GAIN note */
	Talbumpeak,
	Ttrackgain, /* see GAIN note */
	Ttrackpeak,
	Tgenre,
	Timage,
	Tcomposer,
	Tcomment,
	Talbumartist,
};

/* GAIN note:
 *
 * Even though the gain value may be expected to look as "52 dB", it
 * very well may be a plain integer (such as "12032") for R128_* tags.
 * To do things correctly you will have to check 'const char *k' argument
 * passed into your callback and parse it accordingly.
 *
 * FIXME the output gain (opus) is not parsed, btw.
 */

/* Format of the audio file. */
enum {
	Funknown = -1,
	Fmp3,
	Fvorbis,
	Fflac,
	Fm4a,
	Fopus,
	Fwav,
	Fit,
	Fxm,
	Fs3m,
	Fmod,

	Fmax,
	Fogg __attribute__((deprecated("use Fvorbis instead"))) = Fvorbis,
};

/* Image types, according to id3v2. */
enum {
	ITother,
	IT32x32_file_icon,
	ITother_file_icon,
	ITcover_front,
	ITcover_back,
	ITleaflet,
	ITmedia,
	ITlead,
	ITartist,
	ITconductor,
	ITband,
	ITcomposer,
	ITlyricist,
	ITlocation,
	ITrecording,
	ITperformance,
	ITmovie_capture,
	ITfish,
	ITillustration,
	ITlogo_band,
	ITlogo_publisher,

	ITnum,
};

/* Tag itself, either text or image, depending on the "type" passed to the tag callback. */
union Tag {
	/* Any tag type except Timage */
	struct {
		char *k; /* "TPE1", "replaygain_album_peak" etc */
		char *v; /* value */
	}text;

	/* Tag type Timage */
	struct {
		/* If not NULL, reading the image cover requires additional decoding of the data.
		 * In that case you will need to read the raw data (specified by "offset" and "size")
		 * and call this function on the buffer (tag->decode(offset, &size)).
		 * "Size" will be updated with the actual image size after decoding if the function
		 * returned 0, else there was an error.
		 */
		Tagdecode decode;
		const char *mime; /* "image/png", "image/jpeg" etc */
		int offset; /* offset from the beginning of the file */
		int size; /* number of bytes occupied by the raw image data (not decoded) */
		int type; /* type of the image (ITcover_front, ...) */
	}image;
};

/* Tag parser context. You need to set it properly before parsing an audio file using libtags. */
struct Tagctx {
	/* Read function. This is what libtags uses to read the file. */
	int (*read)(Tagctx *ctx, void *buf, int cnt);

	/* Seek function. This is what libtags uses to seek through the file. */
	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, ...) or Tunknown if libtags doesn't
	 * know how to map a tag kind to any of these.
	 * ANY tag type that isn't Timage is considered a text tag.
	 */
	void (*tag)(Tagctx *ctx, int type, Tag *tag);

	/* 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, left for the library user. */
	void *aux;

	/* Memory buffer to work in. */
	char *buf;

	/* Size of the buffer. Must be at least 256 bytes. */
	int bufsz;

	/* Here goes the stuff libtags sets. It should be accessed after tagsget() returns.
	 * A value of 0 means it's undefined.
	 */
	int channels; /* Number of channels. */
	int samplerate; /* Hz */
	int bitrate; /* Bitrate, bits/s. */
	int duration; /* ms */
	int format; /* Fmp3, Fvorbis, Fflac, Fm4a etc */

	/* Private, don't touch. */
	int found;
	int restart;
};

/* Parse the file using this function. Returns 0 on success. */
int tagsget(Tagctx *ctx);

#ifdef __cplusplus
}
#endif