From 566d311638aca1ed21da78a5dce320e94134160b Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Wed, 18 Aug 2010 21:23:40 +0200 Subject: Basic ID3 tag implementation, using libid3tag. --- SConstruct | 1 + music.c | 4 ++++ music.h | 4 ++++ tag.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tag.h | 24 +++++++++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 tag.c create mode 100644 tag.h diff --git a/SConstruct b/SConstruct index e880366..f85f2a3 100644 --- a/SConstruct +++ b/SConstruct @@ -16,6 +16,7 @@ else: env.ParseConfig('pkg-config --cflags --libs glib-2.0') env.ParseConfig('pkg-config --cflags --libs gio-2.0') env.ParseConfig('pkg-config --cflags --libs libmpg123') +env.ParseConfig('pkg-config --cflags --libs id3tag') env.Program('foo', Glob('*.c') + Glob('decoders/*.c') + Glob('encoders/*.c')) diff --git a/music.c b/music.c index 84dd1c7..c81d4dd 100644 --- a/music.c +++ b/music.c @@ -43,6 +43,10 @@ gboolean music_scan(struct directory *directory) { directory->files = g_slist_prepend(directory->files, f); g_debug("added file %s to %s", entry, directory->path); + struct tag *tag = tag_read(fullpath); + if(tag) { + f->tag = tag; + } } else if(S_ISDIR(st.st_mode)) { struct directory *d = g_new0(struct directory, 1); d->path = g_build_filename(directory->path, entry, NULL); diff --git a/music.h b/music.h index e0e4fcb..2b08c39 100644 --- a/music.h +++ b/music.h @@ -1,11 +1,15 @@ #ifndef _MUSIC_H_ #define _MUSIC_H_ +#include "tag.h" + #include struct file { gchar *name; gssize size; + + struct tag *tag; }; struct directory { diff --git a/tag.c b/tag.c new file mode 100644 index 0000000..ca56106 --- /dev/null +++ b/tag.c @@ -0,0 +1,72 @@ +#include "tag.h" + +#include + +static void tag_add(struct tag *tag, enum tag_type type, const gchar *value) { + struct tag_field *field = g_new0(struct tag_field, 1); + if(field == 0) { + g_error("tag_add: g_new0 returned NULL"); + } + + field->type = type; + field->string = g_strdup(value); + tag->fields = g_slist_prepend(tag->fields, field); +} + +static void tag_add_string(struct tag *tag, struct id3_tag *id3tag, + enum tag_type type, const gchar *id) { + struct id3_frame *frame = id3_tag_findframe(id3tag, id, 0); + + if(frame == NULL) { + return; + } + + if(frame->nfields != 2) { + g_debug("unexpected nfields value"); + return; + } + + const union id3_field *field = id3_frame_field(frame, 1); + guint nstrings = id3_field_getnstrings(field); + + for(guint i = 0; i < nstrings; i++) { + const id3_ucs4_t *ucs4 = id3_field_getstrings(field, i); + + if(ucs4 == NULL) { + g_warning("ucs4 is NULL"); + continue; + } + + id3_utf8_t *utf8 = id3_ucs4_utf8duplicate(ucs4); + tag_add(tag, type, (gchar*)utf8); + g_free(utf8); + } +} + +/* TODO: support other tag formats beside ID3 */ +struct tag *tag_read(const gchar *path) { + struct id3_file *file = id3_file_open(path, ID3_FILE_MODE_READONLY); + + if(file == NULL) { + g_warning("file is NULL"); + return NULL; + } + + struct id3_tag *id3tag = id3_file_tag(file); + + if(id3tag == NULL) { + g_debug("tag is NULL"); + return NULL; + } + + struct tag *tag = g_new0(struct tag, 1); + + /* TODO: add more interesting data */ + tag_add_string(tag, id3tag, TAG_TYPE_ARTIST, ID3_FRAME_ARTIST); + tag_add_string(tag, id3tag, TAG_TYPE_ALBUM, ID3_FRAME_ALBUM); + tag_add_string(tag, id3tag, TAG_TYPE_TITLE, ID3_FRAME_TITLE); + + id3_file_close(file); + + return tag; +} diff --git a/tag.h b/tag.h new file mode 100644 index 0000000..e0e5a7d --- /dev/null +++ b/tag.h @@ -0,0 +1,24 @@ +#ifndef _TAG_H_ +#define _TAG_H_ + +#include + +enum tag_type { + TAG_TYPE_ARTIST, + TAG_TYPE_ALBUM, + TAG_TYPE_TITLE, +}; + +struct tag_field { + enum tag_type type; + gchar *string; +}; + +struct tag { + GSList *fields; +}; + +void tag_list_all(const gchar *path); +struct tag *tag_read(const gchar *path); + +#endif -- cgit v1.2.3