#include "mp3-tagger.h" #include "id3.h" #include "list.h" #include "comment.h" #include "xmalloc.h" #include "utf8_decode.h" #include #include #include extern char *program_name; extern const char *id3_read_charset; extern const char *id3_write_charset; static int state_open(struct tagger **taggerp, const char *filename, int wr) { struct tagger *tagger; struct id3 *id3; id3 = xnew(struct id3, 1); if (id3_open(id3, filename, wr)) { fprintf(stderr, "%s: error opening file `%s': %s\n", program_name, filename, strerror(errno)); free(id3); return -1; } tagger = xnew(struct tagger, 1); tagger->filename = xstrdup(filename); tagger->private = id3; *taggerp = tagger; return 0; } static int state_save(struct tagger *tagger) { struct id3 *id3 = (struct id3 *)tagger->private; if (id3_save(id3)) { fprintf(stderr, "%s: error saving file `%s': %s\n", program_name, tagger->filename, strerror(errno)); return -1; } return 0; } static void state_close(struct tagger *tagger) { struct id3 *id3 = (struct id3 *)tagger->private; id3_close(id3); free(id3); free(tagger->filename); free(tagger); } static void state_get_comments(const struct tagger *tagger, struct list_head *comment_head) { struct id3 *id3 = (struct id3 *)tagger->private; char buf[32]; int num; id3_get_artist(id3, buf); if (buf[0]) comment_add_any(comment_head, "ARTIST", buf, id3_read_charset); id3_get_album(id3, buf); if (buf[0]) comment_add_any(comment_head, "ALBUM", buf, id3_read_charset); id3_get_title(id3, buf); if (buf[0]) comment_add_any(comment_head, "TITLE", buf, id3_read_charset); id3_get_comment(id3, buf); if (buf[0]) comment_add_any(comment_head, "COMMENT", buf, id3_read_charset); num = id3_get_track(id3); if (num > 0) { snprintf(buf, sizeof(buf), "%d", num); comment_add_utf8(comment_head, "TRACKNUMBER", buf); } num = id3_get_year(id3); if (num > 0) { snprintf(buf, sizeof(buf), "%d", num); comment_add_utf8(comment_head, "DATE", buf); } num = id3_get_genre(id3); if (num != -1) { /* genres is array of ASCII strings. ASCII is UTF-8 compatible */ comment_add_utf8(comment_head, "GENRE", genres[num]); } } static void state_set_comments(struct tagger *tagger, const struct list_head *comment_head) { struct id3 *id3 = (struct id3 *)tagger->private; struct list_head *item; id3_clear_tags(id3); list_for_each(item, comment_head) { struct comment *comment; char *val; comment = list_entry(item, struct comment, node); if (utf8_decode(comment->utf8_val, id3_write_charset, &val)) { fprintf(stderr, "%s: error: can't convert `%s' to %s: %s\n", program_name, comment->utf8_val, id3_write_charset, strerror(errno)); exit(1); } if (strcmp(comment->key, "ARTIST") == 0) { id3_set_artist(id3, val); } else if (strcmp(comment->key, "ALBUM") == 0) { id3_set_album(id3, val); } else if (strcmp(comment->key, "TITLE") == 0) { id3_set_title(id3, val); } else if (strcmp(comment->key, "COMMENT") == 0) { id3_set_comment(id3, val); } else if (strcmp(comment->key, "TRACKNUMBER") == 0) { int track; char *end; track = strtol(val, &end, 10); if (*end == 0 && *val != 0) id3_set_track(id3, track); } else if (strcmp(comment->key, "DATE") == 0) { int year; char *end; year = strtol(val, &end, 10); if (*end == 0 && *val != 0) id3_set_year(id3, year); } else if (strcmp(comment->key, "GENRE") == 0) { int i; for (i = 0; i < NR_GENRES; i++) { if (strcasecmp(genres[i], val) == 0) { id3_set_genre(id3, i); break; } } if (i == NR_GENRES) { /* FIXME: complain */ } } else { /* FIXME: complain */ } free(val); } } struct tagger_ops mp3_tagger_ops = { .open = state_open, .save = state_save, .close = state_close, .get_comments = state_get_comments, .set_comments = state_set_comments };