diff --git a/README.md b/README.md new file mode 100644 index 0000000..ba9bae0 --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# TagLib +Used to set meta data tags on the following audio formats: + +``` +ape +flac +mp3 +mpc +mpeg +ogg +``` + +Supports reading and writing the following attributes: + +``` +title +artist +album +year +track +genre +``` + +And reading the attributes: +``` +bitRate +sampleRate +channels +length +``` + +Example use (load and modify a track genre): + +```Io +t := TagLib clone setPath("foo.mp3") load +writeln("genre = ", t genre) +t setGenre("ambient") +t save +``` + +# Installation +`taglib` should be installed and foundable in your system. Then: +``` +eerie install https://github.com/IoLanguage/TagLib.git +``` diff --git a/build.io b/build.io new file mode 100755 index 0000000..1b7662b --- /dev/null +++ b/build.io @@ -0,0 +1,10 @@ +AddonBuilder clone do( + dependsOnLib("tag_c") + dependsOnHeader("taglib/tag_c.h") + + debs atPut("tag_c", "libtagc0-dev") + ebuilds atPut("tag_c", "taglib") + pkgs atPut("tag_c", "taglib") + rpms atPut("tag_c", "taglib-devel") +) + diff --git a/depends b/depends new file mode 100644 index 0000000..e69de29 diff --git a/io/TagLib.io b/io/TagLib.io new file mode 100644 index 0000000..18d4ef3 --- /dev/null +++ b/io/TagLib.io @@ -0,0 +1 @@ +/* TagLib */ diff --git a/io/TagLib_extras.io b/io/TagLib_extras.io new file mode 100644 index 0000000..aa810db --- /dev/null +++ b/io/TagLib_extras.io @@ -0,0 +1,13 @@ +TagLib do( + path ::= nil + title ::= nil + artist ::= nil + album ::= nil + year ::= nil + track ::= nil + genre ::= nil + bitRate ::= nil + sampleRate ::= nil + channels ::= nil + length ::= nil +) \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..a81c58b --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "TagLib", + "version": "0.1", + "description": "Used to set meta data tags on the following audio formats: ape, flac, mp3, mpc, mpeg, ogg.", + "author": "Steve Dekorte", + "website": "http://iolanguage.org/", + "readme": "README.md", + "protos": ["TagLib"], + "dependencies": { + "libs": ["tag_c"], + "headers": ["taglib/tag_c.h"], + "protos": [], + "packages": [] + } +} diff --git a/protos b/protos new file mode 100755 index 0000000..0a6c64c --- /dev/null +++ b/protos @@ -0,0 +1 @@ +TagLib diff --git a/samples/sounds/max.mp3 b/samples/sounds/max.mp3 new file mode 100644 index 0000000..30c5d4f Binary files /dev/null and b/samples/sounds/max.mp3 differ diff --git a/samples/sounds/max.wav b/samples/sounds/max.wav new file mode 100644 index 0000000..b4660e5 Binary files /dev/null and b/samples/sounds/max.wav differ diff --git a/samples/tag.io b/samples/tag.io new file mode 100755 index 0000000..12d1b24 --- /dev/null +++ b/samples/tag.io @@ -0,0 +1,18 @@ +#!/usr/bin/env io + +TagLib do( +newSlot("path") +newSlot("title") +newSlot("artist") +newSlot("album") +newSlot("year") +newSlot("comment") +newSlot("track") +newSlot("genre") +) + +path := Path with(System launchPath, "sounds/max.mp3") +tag := TagLib clone setPath(path) load +writeln(tag) +tag setComment("max headroom saying 'hello, this is max headroom'") +tag save diff --git a/source/IoTagLib.c b/source/IoTagLib.c new file mode 100644 index 0000000..bc52edf --- /dev/null +++ b/source/IoTagLib.c @@ -0,0 +1,170 @@ +//metadoc TagLib copyright Steve Dekorte, 2004 +//metadoc TagLib license BSD revised +//metadoc TagLib category API +/*metadoc TagLib description +Used to set meta data tags on the following audio formats: +
+ape
+flac
+mp3
+mpc
+mpeg
+ogg
+
+Supports reading and writing the following attributes: +
title
+artist
+album
+year
+track
+genre 
+
+And reading the attributes: +
+bitRate
+sampleRate
+channels
+length
+
+ +Example use (load and modify a track genre): + +
+t := TagLib clone setPath("foo.mp3") load
+writeln("genre = ", t genre)
+t setGenre("ambient")
+t save
+
+*/ + +//doc TagLib setPath(aSeq) Sets the path to the file. +//doc TagLib path Returns the path to the file. + +#include "IoTagLib.h" +#include "IoState.h" +#include "IoNumber.h" +#include "IoSeq.h" +#include + +#define DATA(self) ((IoTagLibData *)IoObject_dataPointer(self)) +static const char *protoId = "TagLib"; + +IoTag *IoTagLib_newTag(void *state) +{ + IoTag *tag = IoTag_newWithName_("TagLib"); + IoTag_state_(tag, state); + IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoTagLib_rawClone); + return tag; +} + +IoTagLib *IoTagLib_proto(void *state) +{ + IoObject *self = IoObject_new(state); + IoObject_tag_(self, IoTagLib_newTag(state)); + + IoState_registerProtoWithId_(state, self, protoId); + + { + IoMethodTable methodTable[] = { + {"load", IoTagLib_load}, + {"save", IoTagLib_save}, + {NULL, NULL}, + }; + IoObject_addMethodTable_(self, methodTable); + } + + return self; +} + +IoTagLib *IoTagLib_rawClone(IoTagLib *proto) +{ + IoObject *self = IoObject_rawClonePrimitive(proto); + return self; +} + +IoTagLib *IoTagLib_new(void *state) +{ + IoObject *proto = IoState_protoWithId_(state, protoId); + return IOCLONE(proto); +} + +// ----------------------------------------------------------- + + +IoObject *IoTagLib_load(IoTagLib *self, IoObject *locals, IoMessage *m) +{ + /*doc TagLib load + Loads tag data from the file specified in the path slot. Returns self. + */ + + TagLib_File *file; + TagLib_Tag *tag; + const TagLib_AudioProperties *properties; + IoSeq *path = IoObject_symbolGetSlot_(self, IOSYMBOL("path")); + IOASSERT(path, "missing path slot"); + + taglib_set_strings_unicode(0); + + file = taglib_file_new(CSTRING(path)); + + IOASSERT(file, "unable to open file"); + + tag = (TagLib_Tag *)taglib_file_tag(file); + properties = taglib_file_audioproperties(file); + + IoObject_setSlot_to_(self, IOSYMBOL("title"), IOSYMBOL(taglib_tag_title(tag))); + IoObject_setSlot_to_(self, IOSYMBOL("artist"), IOSYMBOL(taglib_tag_artist(tag))); + IoObject_setSlot_to_(self, IOSYMBOL("album"), IOSYMBOL(taglib_tag_album(tag))); + IoObject_setSlot_to_(self, IOSYMBOL("year"), IONUMBER(taglib_tag_year(tag))); + IoObject_setSlot_to_(self, IOSYMBOL("comment"), IOSYMBOL(taglib_tag_comment(tag))); + IoObject_setSlot_to_(self, IOSYMBOL("track"), IONUMBER(taglib_tag_track(tag))); + IoObject_setSlot_to_(self, IOSYMBOL("genre"), IOSYMBOL(taglib_tag_genre(tag))); + + // audio data - can't write this - it's up to the mp3 encoder + IoObject_setSlot_to_(self, IOSYMBOL("bitRate"), IONUMBER(taglib_audioproperties_bitrate(properties))); + IoObject_setSlot_to_(self, IOSYMBOL("sampleRate"), IONUMBER(taglib_audioproperties_samplerate(properties))); + IoObject_setSlot_to_(self, IOSYMBOL("channels"), IONUMBER(taglib_audioproperties_channels(properties))); + IoObject_setSlot_to_(self, IOSYMBOL("length"), IONUMBER(taglib_audioproperties_length(properties))); + + taglib_tag_free_strings(); + taglib_file_free(file); + + return self; +} + +IoObject *IoTagLib_save(IoTagLib *self, IoObject *locals, IoMessage *m) +{ + /*doc TagLib save + Saves the tag settings and returns self. + */ + + TagLib_File *file; + TagLib_Tag *tag; + //const TagLib_AudioProperties *properties; + IoSeq *path = IoObject_symbolGetSlot_(self, IOSYMBOL("path")); + IOASSERT(path, "missing path slot"); + + taglib_set_strings_unicode(0); + + file = taglib_file_new(CSTRING(path)); + + IOASSERT(file, "unable to open file"); + + tag = (TagLib_Tag *)taglib_file_tag(file); + + taglib_tag_set_title(tag, CSTRING(IoObject_seqGetSlot_(self, IOSYMBOL("title")))); + taglib_tag_set_album(tag, CSTRING(IoObject_seqGetSlot_(self, IOSYMBOL("album")))); + taglib_tag_set_year(tag, (int)IoObject_doubleGetSlot_(self, IOSYMBOL("year"))); + taglib_tag_set_comment(tag, CSTRING(IoObject_seqGetSlot_(self, IOSYMBOL("comment")))); + taglib_tag_set_track(tag, (int)IoObject_doubleGetSlot_(self, IOSYMBOL("track"))); + taglib_tag_set_genre(tag, CSTRING(IoObject_seqGetSlot_(self, IOSYMBOL("genre")))); + + taglib_file_save(file); + + taglib_tag_free_strings(); + taglib_file_free(file); + + return self; + +} + diff --git a/source/IoTagLib.h b/source/IoTagLib.h new file mode 100644 index 0000000..d963e2a --- /dev/null +++ b/source/IoTagLib.h @@ -0,0 +1,29 @@ +/* copyright: Steve Dekorte, 2002 + * All rights reserved. See _BSDLicense.txt. + */ + +#ifndef IoTagLib_DEFINED +#define IoTagLib_DEFINED 1 + +#include "IoObject.h" +#include "IoSeq.h" + +typedef IoObject IoTagLib; + +typedef struct +{ + +} IoTagLibData; + +IoTagLib *IoTagLib_proto(void *state); +IoTagLib *IoTagLib_new(void *state); +IoTagLib *IoTagLib_rawClone(IoTagLib *self); + +void IoTagLib_free(IoTagLib *self); + +// ----------------------------------------------------------- + +IoObject *IoTagLib_load(IoTagLib *self, IoObject *locals, IoMessage *m); +IoObject *IoTagLib_save(IoTagLib *self, IoObject *locals, IoMessage *m); + +#endif