#ifndef ID3_H #define ID3_H #include #include #include #define NR_GENRES 148 /* all data is private */ struct id3 { struct { char tag[3]; char title[30]; char artist[30]; char album[30]; char year[4]; union { struct { char comment[30]; } v1_0; struct { char comment[28]; char zero; char track; } v1_1; } u; unsigned char genre; } tag; int fd; int has_tag; enum { ID3_V1_0, ID3_V1_1 } version; }; extern const char *genres[]; extern int id3_open(struct id3 *id3, const char *filename, int wr); extern int id3_save(struct id3 *id3); extern void id3_close(struct id3 *id3); extern void id3_clear_tags(struct id3 *id3); extern void __id3_buf_to_str(char *str, const char *buf, int buf_size); static inline void id3_set_title(struct id3 *id3, const char *title) { strncpy(id3->tag.title, title, sizeof(id3->tag.title)); } static inline void id3_set_artist(struct id3 *id3, const char *artist) { strncpy(id3->tag.artist, artist, sizeof(id3->tag.artist)); } static inline void id3_set_album(struct id3 *id3, const char *album) { strncpy(id3->tag.album, album, sizeof(id3->tag.album)); } static inline void id3_set_year(struct id3 *id3, unsigned int year) { if (year == 0) { id3->tag.year[0] = 0; id3->tag.year[1] = 0; id3->tag.year[2] = 0; id3->tag.year[3] = 0; } else { id3->tag.year[3] = year % 10 + '0'; year /= 10; id3->tag.year[2] = year % 10 + '0'; year /= 10; id3->tag.year[1] = year % 10 + '0'; year /= 10; id3->tag.year[0] = year % 10 + '0'; } } static inline void id3_set_comment(struct id3 *id3, const char *comment) { if (id3->version == ID3_V1_1) { strncpy(id3->tag.u.v1_1.comment, comment, sizeof(id3->tag.u.v1_1.comment)); } else { strncpy(id3->tag.u.v1_0.comment, comment, sizeof(id3->tag.u.v1_0.comment)); } } static inline void id3_set_track(struct id3 *id3, unsigned int track) { if (track == 0) { if (id3->version == ID3_V1_1) { id3->tag.u.v1_1.track = 0; id3->version = ID3_V1_0; } } else { id3->tag.u.v1_1.zero = 0; id3->tag.u.v1_1.track = track; id3->version = ID3_V1_1; } } static inline void id3_set_genre(struct id3 *id3, unsigned int genre) { if (genre < NR_GENRES) { id3->tag.genre = genre; } else { id3->tag.genre = 0xff; } } static inline void id3_get_title(struct id3 *id3, char *title) { __id3_buf_to_str(title, id3->tag.title, sizeof(id3->tag.title)); } static inline void id3_get_artist(struct id3 *id3, char *artist) { __id3_buf_to_str(artist, id3->tag.artist, sizeof(id3->tag.artist)); } static inline void id3_get_album(struct id3 *id3, char *album) { __id3_buf_to_str(album, id3->tag.album, sizeof(id3->tag.album)); } static inline int id3_get_year(struct id3 *id3) { int i, year = 0; for (i = 0; i < 4; i++) { if (!isdigit(id3->tag.year[i])) return -1; year *= 10; year += id3->tag.year[i] - '0'; } return year; } static inline void id3_get_comment(struct id3 *id3, char *comment) { if (id3->version == ID3_V1_1) { __id3_buf_to_str(comment, id3->tag.u.v1_1.comment, sizeof(id3->tag.u.v1_1.comment)); } else { __id3_buf_to_str(comment, id3->tag.u.v1_0.comment, sizeof(id3->tag.u.v1_0.comment)); } } static inline int id3_get_track(struct id3 *id3) { if (id3->version == ID3_V1_1) return id3->tag.u.v1_1.track; return -1; } static inline int id3_get_genre(struct id3 *id3) { if (id3->tag.genre == 0xff) return -1; return id3->tag.genre; } static inline int id3_has_tag(struct id3 *id3) { return id3->has_tag; } static inline int id3_version(struct id3 *id3) { return id3->version; } #endif