Browse files

Implemented async save API. Fixes #23

  • Loading branch information...
1 parent 957fbb1 commit c89731c5910ca5e5d9635e467e3bd670dbd541b9 @nikhilm committed Mar 22, 2012
Showing with 81 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +21 −0 spec/taglibSpec.js
  3. +50 −0 src/tag.cc
  4. +9 −0 src/tag.h
View
1 .gitignore
@@ -4,3 +4,4 @@ spec/sample-write.mp3
.lock-wscript
node_modules
.DS_Store
+spec/sample-write-async.mp3
View
21 spec/taglibSpec.js
@@ -189,5 +189,26 @@ vows.describe('taglib bindings')
'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);
View
50 src/tag.cc
@@ -27,6 +27,7 @@ void Tag::Initialize(Handle<Object> target)
TagTemplate->InstanceTemplate()->SetInternalFieldCount(1);
TagTemplate->SetClassName(String::NewSymbol("Tag"));
+ NODE_SET_PROTOTYPE_METHOD(TagTemplate, "save", AsyncSaveTag);
NODE_SET_PROTOTYPE_METHOD(TagTemplate, "saveSync", SyncSaveTag);
NODE_SET_PROTOTYPE_METHOD(TagTemplate, "isEmpty", IsEmpty);
@@ -294,4 +295,53 @@ void Tag::AsyncTagReadAfter(uv_work_t *req) {
//delete baton;
}
+v8::Handle<v8::Value> Tag::AsyncSaveTag(const v8::Arguments &args) {
+ HandleScope scope;
+
+ if (args.Length() >= 1 && !args[0]->IsFunction())
+ return ThrowException(String::New("Expected callback function as first argument"));
+
+ Local<Function> callback = Local<Function>::Cast(args[0]);
+
+ Tag *t = ObjectWrap::Unwrap<Tag>(args.This());
+
+ AsyncSaveBaton *baton = new AsyncSaveBaton;
+ baton->request.data = baton;
+ baton->tag = t;
+ baton->callback = Persistent<Function>::New(callback);
+ baton->success = false;
+
+ uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncSaveTagDo, Tag::AsyncSaveTagAfter);
+
+ return Undefined();
+}
+
+void Tag::AsyncSaveTagDo(uv_work_t *req) {
+ AsyncSaveBaton *baton = static_cast<AsyncSaveBaton*>(req->data);
+
+ assert(baton->tag->fileRef);
+ baton->success = baton->tag->fileRef->save();
+}
+
+void Tag::AsyncSaveTagAfter(uv_work_t *req) {
+ HandleScope scope;
+
+ AsyncSaveBaton *baton = static_cast<AsyncSaveBaton*>(req->data);
+
+ if (baton->success) {
+ Handle<Value> argv[] = { Null() };
+ baton->callback->Call(Context::GetCurrent()->Global(), 1, argv);
+ }
+ else {
+ Local<Object> error = Object::New();
+ error->Set(String::New("message"), String::New("Failed to save file"));
+ error->Set(String::New("path"), String::New(baton->tag->fileRef->file()->name()));
+ Handle<Value> argv[] = { error };
+ baton->callback->Call(Context::GetCurrent()->Global(), 1, argv);
+ }
+
+ baton->callback.Dispose();
+ delete baton;
+}
+
}
View
9 src/tag.h
@@ -42,11 +42,14 @@ class Tag : public node::ObjectWrap {
static void SetGenre(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> IsEmpty(const v8::Arguments &args);
+ static v8::Handle<v8::Value> AsyncSaveTag(const v8::Arguments &args);
static v8::Handle<v8::Value> SyncSaveTag(const v8::Arguments &args);
static v8::Handle<v8::Value> SyncTag(const v8::Arguments &args);
static v8::Handle<v8::Value> AsyncTag(const v8::Arguments &args);
static void AsyncTagRead(uv_work_t *req);
static void AsyncTagReadAfter(uv_work_t *req);
+ static void AsyncSaveTagDo(uv_work_t *req);
+ static void AsyncSaveTagAfter(uv_work_t *req);
};
struct AsyncTagBaton {
@@ -58,6 +61,12 @@ struct AsyncTagBaton {
suseconds_t startTime;
};
+struct AsyncSaveBaton {
+ uv_work_t request;
+ Tag *tag;
+ v8::Persistent<v8::Function> callback;
+ bool success;
+};
int CreateFileRef(TagLib::FileName path, TagLib::FileRef **ref);
v8::Handle<v8::String> ErrorToString(int error);

0 comments on commit c89731c

Please sign in to comment.