summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Bergli Heier <snakebite@jvnv.net>2010-08-18 21:23:40 +0200
committerJon Bergli Heier <snakebite@jvnv.net>2010-08-18 21:23:40 +0200
commit566d311638aca1ed21da78a5dce320e94134160b (patch)
tree5a497e17ea9b59f87a50213142a6aebfa0f4d822
parentabac0fad0e30c670f70e325588e5503259f4b29e (diff)
Basic ID3 tag implementation, using libid3tag.
-rw-r--r--SConstruct1
-rw-r--r--music.c4
-rw-r--r--music.h4
-rw-r--r--tag.c72
-rw-r--r--tag.h24
5 files changed, 105 insertions, 0 deletions
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 <glib.h>
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 <id3tag.h>
+
+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 <glib.h>
+
+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