Comparing version 0.2.1 to 0.3.0
@@ -1,2 +0,2 @@ | ||
var Taglib = require(__dirname+"/../lib/taglib") | ||
var Taglib = require(__dirname+"/../taglib") | ||
var util = require("util") | ||
@@ -3,0 +3,0 @@ |
@@ -1,5 +0,8 @@ | ||
var Taglib = require(__dirname+"/../lib/taglib") | ||
var Taglib = require(__dirname+"/../taglib") | ||
var util = require("util") | ||
var p = new Taglib.Tag(process.argv[2]); | ||
util.debug( util.inspect(p) ) | ||
for (var i = 2; i < process.argv.length; i++) { | ||
Taglib.tag(process.argv[i], function(err, tag) { | ||
console.dir(err ? err : tag); | ||
}); | ||
} |
{ | ||
"name": "taglib", | ||
"description": "Simple bindings to TagLib", | ||
"version": "0.2.1", | ||
"version": "0.3.0", | ||
"repository": { | ||
@@ -9,9 +9,11 @@ "type": "git", | ||
}, | ||
"author": "Nikhil Marathe <nsm.nikhil@gmail.com> (http://kodeclutz.blogspot.com/)", | ||
"main": "lib/taglib.js", | ||
"author": "Nikhil Marathe <nsm.nikhil@gmail.com> (http://nikhilism.com)", | ||
"main": "taglib.node", | ||
"directories": { | ||
"lib": "lib" | ||
"example": "examples" | ||
}, | ||
"devDependencies": { | ||
"vows" : ">= 0.5.9" | ||
"vows" : ">= 0.6.0", | ||
"async" : ">=0.1.0", | ||
"match-files" : "latest" | ||
}, | ||
@@ -22,4 +24,4 @@ "scripts": { | ||
"engines": { | ||
"node": "*" | ||
"node": ">= 0.4.10" | ||
} | ||
} |
139
README.md
node-taglib | ||
=========== | ||
node-taglib is a simple binding to [TagLib](http://developer.kde.org/~wheeler/taglib/) in Javascript. | ||
node-taglib is a simple binding to | ||
[TagLib](http://developer.kde.org/~wheeler/taglib/) in Javascript. | ||
It requires [node.js](http://nodejs.org). | ||
For now it exposes Tag and AudioProperties. | ||
For now it exposes Tag and AudioProperties. Synchronous write support is | ||
supported for Tag. | ||
## Usage | ||
**NOTE: Asynchronous API requires use of TagLib [from git][taglib-git] since | ||
certain bugs present in the released v1.7 cause problems.** | ||
var Tag = require('taglib').Tag; | ||
var t = new Tag(path); | ||
t.title # => "Another one bites the dust" | ||
t.artist # => "Kween" | ||
t.artist = "Queen" | ||
t.save() # => true | ||
[taglib-git]: https://github.com/taglib/taglib | ||
## Build | ||
## Example | ||
// load the library | ||
var taglib = require('taglib'); | ||
// asynchronous API | ||
taglib.tag(path, function(err, tag) { | ||
tag.artist; // => "Queen" | ||
tag.title = "Erm"; | ||
tag.saveSync(); | ||
}); | ||
// synchronous API | ||
var tag = taglib.tagSync(path); | ||
tag.title; // => "Another one bites the dust" | ||
tag.artist; // => "Kween" | ||
tag.artist = "Queen"; | ||
tag.isEmpty(); // => false | ||
tag.saveSync(); // => true | ||
## Installation | ||
### via npm (Recommended) | ||
npm install taglib | ||
### From source | ||
# make sure you have node and taglib installed | ||
@@ -26,5 +53,97 @@ git clone git://github.com/nikhilm/node-taglib.git | ||
node examples/simple.js /path/to/mp3_or_ogg_file | ||
# you can now require('./taglib') | ||
The `examples` show usage. | ||
## API | ||
### tag(path, callback) | ||
Read the tag from the file at `path` _asynchronously_. The callback should have | ||
signature `(err, tag)`. On success, `err` will be `null` and `tag` will be | ||
a `Tag`. If errors occurred, `err` will contain the error and | ||
`tag` will be `null`. `err` will be an object with field `code` having the | ||
integer error code (`errno.h`) and field `message` will have a string | ||
representation. | ||
### tagSync(path) | ||
Read the tag from the file at `path` _synchronously_. Returns a `Tag`. If | ||
errors occurred, throws an exception. | ||
### Tag | ||
**NOTE: A Tag object should *NOT* be created using `new`. Instead use `tag()` | ||
or `tagSync()`** | ||
A Tag object allows access to all the meta-data fields. node-taglib currently | ||
supports only the fields common to all formats: | ||
* title (string) | ||
* album (string) | ||
* comment (string) | ||
* artist (string) | ||
* track (string) | ||
* year (integer) | ||
* genre (string) | ||
To get a value, simply access the field -- `tag.artist`. | ||
To set a value, assign a value to the field -- `tag.year = 2012`. You **will | ||
have to call `saveSync()`** to actually save the changes to the file on disc. | ||
##### Large number of files | ||
Due to TagLib's design, every `Tag` object in memory has to keep its backing | ||
file descriptor open. If you are dealing with a large number of files, you will | ||
soon run into problems because operating systems impose limits on how many | ||
files a process can have open simultaneously. If you only want to read | ||
meta-data and not write it immediately, then **deep copy** the fields over to | ||
a plain JS object, then dispose the `Tag` object so that you can operate on | ||
more files. | ||
### Tag.save(callback) | ||
Save any changes in the Tag meta-data to disk _asynchronously_. `callback` will | ||
be invoked once the save is done, and should have a signature `(err)`. `err` | ||
will be `null` if the save was successful, otherwise it will be an object with | ||
`message` having the error string and `path` having the file path. | ||
### Tag.saveSync() | ||
Save any changes in the Tag meta-data to disk _synchronously_. | ||
### Tag.isEmpty() | ||
Returns whether the tag is empty or not. | ||
### AudioProperties(path) | ||
**NOTE: This will be replaced by a more functional API, similar to the tags API.** | ||
Object to get the audio properties of file at `path`. Throws an exception on | ||
errors. | ||
var ap = new taglib.AudioProperties('path'); | ||
console.log("Bitrate", ap.bitrate); | ||
The following fields are available: | ||
* length | ||
* bitrate | ||
* sampleRate | ||
* channels | ||
Writing audio properties is not supported. | ||
### taglib.WITH_ASF | ||
A boolean representing whether node-taglib supports ASF files. Depends on | ||
feature being enabled in TagLib. | ||
### taglib.WITH_MP4 | ||
A boolean representing whether node-taglib supports MP4 files. Depends on | ||
feature being enabled in TagLib. | ||
Contributors are listed at: <https://github.com/nikhilm/node-taglib/contributors> |
@@ -1,10 +0,31 @@ | ||
var assert = require('assert') | ||
var vows = require('vows') | ||
var fs = require('fs') | ||
var Taglib = require(__dirname + '/../lib/taglib') | ||
var assert = require('assert'), | ||
vows = require('vows'), | ||
fs = require('fs'), | ||
Taglib = require(__dirname + '/../taglib'); | ||
vows.describe('taglib bindings') | ||
.addBatch({ | ||
'opening UTF-8 Path': { | ||
topic: Taglib.tagSync(__dirname + '/sample-with-ütf.mp3'), | ||
'should be a `Tag`': function(tag) { | ||
assert.equal(Taglib.Tag, tag.constructor); | ||
} | ||
}, | ||
'ASF support yes/no should be defined': { | ||
topic: Taglib.WITH_ASF, | ||
'is boolean': function(topic) { | ||
assert.isBoolean(topic); | ||
} | ||
}, | ||
'MP4 support yes/no should be defined': { | ||
topic: Taglib.WITH_MP4, | ||
'is boolean': function(topic) { | ||
assert.isBoolean(topic); | ||
} | ||
}, | ||
'reading Tags from File': { | ||
topic: new Taglib.Tag(__dirname+'/sample.mp3'), | ||
topic: Taglib.tagSync(__dirname+'/sample.mp3'), | ||
'should be a `Tag`': function (tag) { | ||
@@ -36,2 +57,52 @@ assert.equal(Taglib.Tag, tag.constructor); | ||
'reading Tags from non-existent file': { | ||
// nested functions because vows automatically calls a topic | ||
// function | ||
topic: function() { | ||
return function() { | ||
return Taglib.tagSync('thisfileobviouslyshouldnot.exist'); | ||
} | ||
}, | ||
'should throw an exception': function(topic) { | ||
assert.throws(topic, /readable/); | ||
} | ||
}, | ||
'reading Tags from a non-audio file': { | ||
topic: function() { | ||
return function() { | ||
return Taglib.tagSync(__filename); | ||
} | ||
}, | ||
'should throw an exception': function(topic) { | ||
assert.throws(topic, /extract tags/); | ||
} | ||
}, | ||
'reading AudioProperties from non-existent file': { | ||
topic: function() { | ||
return function() { | ||
return new Taglib.AudioProperties('thisfileobviouslyshouldnot.exist'); | ||
} | ||
}, | ||
'should throw an exception': function(topic) { | ||
assert.throws(topic, /readable/); | ||
} | ||
}, | ||
'reading AudioProperties from a non-audio file': { | ||
topic: function() { | ||
return function() { | ||
return new Taglib.AudioProperties(__filename); | ||
} | ||
}, | ||
'should throw an exception': function(topic) { | ||
assert.throws(topic, /extract audio properties/); | ||
} | ||
}, | ||
'writing Tags to File': { | ||
@@ -41,13 +112,36 @@ topic: function() { | ||
fs.writeFileSync(filename, fs.readFileSync(__dirname+'/sample.mp3')); | ||
var t = new Taglib.Tag(filename); | ||
var t = Taglib.tagSync(filename); | ||
t.title = 'Something completely different…'; | ||
t.save(); | ||
t.saveSync(); | ||
return filename; | ||
}, | ||
'should have written `Something completely different…` to title': function (filename) { | ||
var tag = new Taglib.Tag(filename); | ||
assert.equal("Something completely different…", tag.title); | ||
var tag = Taglib.tagSync(filename); | ||
assert.equal(tag.title, "Something completely different…"); | ||
} | ||
}, | ||
'stripping Tags from File': { | ||
topic: function() { | ||
var filename, t; | ||
filename = __dirname + '/sample-clean.mp3'; | ||
fs.writeFileSync(filename, fs.readFileSync(__dirname + '/sample.mp3')); | ||
t = Taglib.tagSync(filename); | ||
t.title = null; | ||
t.artist = null; | ||
t.album = null; | ||
t.genre = null; | ||
t.year = null; | ||
t.comment = null; | ||
t.track = null; | ||
t.saveSync(); | ||
return filename; | ||
}, | ||
'should result in a Tag that `isEmpty`': function(filename) { | ||
var tag; | ||
tag = Taglib.tagSync(filename); | ||
assert.ok(tag.isEmpty()); | ||
} | ||
}, | ||
'reading Properties from File': { | ||
@@ -70,3 +164,54 @@ topic: new Taglib.AudioProperties(__dirname+'/blip.mp3'), | ||
}, | ||
}, | ||
'reading Tag from a file asynchronously': { | ||
topic: function() { | ||
Taglib.tag(__dirname+'/sample.mp3', this.callback); | ||
}, | ||
'should be a `Tag`': function (tag) { | ||
assert.equal(Taglib.Tag, tag.constructor); | ||
}, | ||
'should be `A bit-bucket full of tags`': function (tag) { | ||
assert.equal('A bit-bucket full of tags', tag.title); | ||
}, | ||
'should be a `A bit-bucket full of tags`': function (tag) { | ||
assert.equal('A bit-bucket full of tags', tag.title); | ||
}, | ||
'should be by `gitzer\'s`': function (tag) { | ||
assert.equal('gitzer\'s', tag.artist); | ||
}, | ||
'should be on `Waffles for free!`': function (tag) { | ||
assert.equal("Waffles for free!", tag.album); | ||
}, | ||
'should be the first': function (tag) { | ||
assert.equal(1, tag.track) | ||
}, | ||
'should be from 2011': function (tag) { | ||
assert.equal(2011, tag.year); | ||
}, | ||
'should have a silly comment': function(tag) { | ||
assert.equal("Salami Wiglet.", tag.comment); | ||
} | ||
}, | ||
'writing Tag to a file asynchronously': { | ||
topic: function() { | ||
var filename = __dirname+'/sample-write-async.mp3'; | ||
fs.writeFileSync(filename, fs.readFileSync(__dirname+'/sample.mp3')); | ||
var self = this; | ||
Taglib.tag(filename, function(err, tag) { | ||
if (err) { | ||
self.callback(err); | ||
} | ||
tag.title = 'Something completely different…'; | ||
tag.save(function(err) { | ||
self.callback(err, filename); | ||
}); | ||
}); | ||
}, | ||
'should have written `Something completely different…` to title': function (filename) { | ||
var tag = Taglib.tagSync(filename); | ||
assert.equal(tag.title, "Something completely different…"); | ||
} | ||
} | ||
}).export(module); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
52206
25
302
149
1
3
8