diff --git a/.gitignore b/.gitignore index 866df99..3444544 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ spec/sample-write.mp3 node_modules .DS_Store spec/sample-write-async.mp3 +*.swp diff --git a/binding.gyp b/binding.gyp index 3211dd9..5bbe508 100644 --- a/binding.gyp +++ b/binding.gyp @@ -4,6 +4,9 @@ "target_name": "taglib", "sources": ["src/bufferstream.c", "src/tag.cc", "src/taglib.cc"], "libraries": ["=0.6.0", - "async" : ">=0.1.0", - "match-files" : "latest" + "vows": ">=0.6.0", + "async": ">=0.1.0", + "match-files": "latest" }, "scripts": { "test": "vows --spec" }, "engines": { - "node": ">=0.10.0 <0.11" + "node": ">=0.10" } } diff --git a/src/tag.cc b/src/tag.cc index 4c14333..a83f49f 100644 --- a/src/tag.cc +++ b/src/tag.cc @@ -18,26 +18,27 @@ static Persistent TagTemplate; void Tag::Initialize(Handle target) { - HandleScope scope; + NanScope(); - TagTemplate = Persistent::New(FunctionTemplate::New()); + Local localTagTemplate = NanNew(); + NanAssignPersistent(TagTemplate, localTagTemplate); - TagTemplate->InstanceTemplate()->SetInternalFieldCount(1); - TagTemplate->SetClassName(String::NewSymbol("Tag")); + localTagTemplate->InstanceTemplate()->SetInternalFieldCount(1); + localTagTemplate->SetClassName(NanNew("Tag")); - NODE_SET_PROTOTYPE_METHOD(TagTemplate, "save", AsyncSaveTag); - NODE_SET_PROTOTYPE_METHOD(TagTemplate, "saveSync", SyncSaveTag); - NODE_SET_PROTOTYPE_METHOD(TagTemplate, "isEmpty", IsEmpty); + NODE_SET_PROTOTYPE_METHOD(localTagTemplate, "save", AsyncSaveTag); + NODE_SET_PROTOTYPE_METHOD(localTagTemplate, "saveSync", SyncSaveTag); + NODE_SET_PROTOTYPE_METHOD(localTagTemplate, "isEmpty", IsEmpty); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("title"), GetTitle, SetTitle); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("album"), GetAlbum, SetAlbum); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("comment"), GetComment, SetComment); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("artist"), GetArtist, SetArtist); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("track"), GetTrack, SetTrack); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("year"), GetYear, SetYear); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("genre"), GetGenre, SetGenre); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("title"), GetTitle, SetTitle); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("album"), GetAlbum, SetAlbum); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("comment"), GetComment, SetComment); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("artist"), GetArtist, SetArtist); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("track"), GetTrack, SetTrack); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("year"), GetYear, SetYear); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("genre"), GetGenre, SetGenre); - target->Set(String::NewSymbol("Tag"), TagTemplate->GetFunction()); + target->Set(NanNew("Tag"), localTagTemplate->GetFunction()); NODE_SET_METHOD(target, "tag", AsyncTag); NODE_SET_METHOD(target, "tagSync", SyncTag); } @@ -51,102 +52,100 @@ Tag::~Tag() { tag = NULL; } -inline Tag * unwrapTag(const AccessorInfo& info) { - return ObjectWrap::Unwrap(info.Holder()); -} +#define unwrapTag(info) ObjectWrap::Unwrap(info.Holder()) -Handle Tag::GetTitle(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->title())); +NAN_GETTER(Tag::GetTitle) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->title())); } -void Tag::SetTitle(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setTitle(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetTitle) { + NanScope(); + unwrapTag(args)->tag->setTitle(NodeStringToTagLibString(value)); } -Handle Tag::GetArtist(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->artist())); +NAN_GETTER(Tag::GetArtist) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->artist())); } -void Tag::SetArtist(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setArtist(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetArtist) { + NanScope(); + unwrapTag(args)->tag->setArtist(NodeStringToTagLibString(value)); } -Handle Tag::GetAlbum(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->album())); +NAN_GETTER(Tag::GetAlbum) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->album())); } -void Tag::SetAlbum(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setAlbum(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetAlbum) { + NanScope(); + unwrapTag(args)->tag->setAlbum(NodeStringToTagLibString(value)); } -Handle Tag::GetComment(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->comment())); +NAN_GETTER(Tag::GetComment) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->comment())); } -void Tag::SetComment(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setComment(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetComment) { + NanScope(); + unwrapTag(args)->tag->setComment(NodeStringToTagLibString(value)); } -Handle Tag::GetTrack(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(Integer::New(unwrapTag(info)->tag->track())); +NAN_GETTER(Tag::GetTrack) { + NanScope(); + NanReturnValue(NanNew(unwrapTag(args)->tag->track())); } -void Tag::SetTrack(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setTrack(value->IntegerValue()); +NAN_SETTER(Tag::SetTrack) { + NanScope(); + unwrapTag(args)->tag->setTrack(value->IntegerValue()); } -Handle Tag::GetYear(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(Integer::New(unwrapTag(info)->tag->year())); +NAN_GETTER(Tag::GetYear) { + NanScope(); + NanReturnValue(NanNew(unwrapTag(args)->tag->year())); } -void Tag::SetYear(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setYear(value->IntegerValue()); +NAN_SETTER(Tag::SetYear) { + NanScope(); + unwrapTag(args)->tag->setYear(value->IntegerValue()); } -Handle Tag::GetGenre(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->genre())); +NAN_GETTER(Tag::GetGenre) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->genre())); } -void Tag::SetGenre(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setGenre(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetGenre) { + NanScope(); + unwrapTag(args)->tag->setGenre(NodeStringToTagLibString(value)); } -Handle Tag::IsEmpty(const Arguments &args) { - HandleScope scope; - Tag *t = ObjectWrap::Unwrap(args.This()); - return Boolean::New(t->tag->isEmpty()); +NAN_METHOD(Tag::IsEmpty) { + NanScope(); + Tag *t = ObjectWrap::Unwrap(args.This()); + NanReturnValue(NanNew(t->tag->isEmpty())); } -Handle Tag::SyncSaveTag(const Arguments &args) { - HandleScope scope; - Tag *t = ObjectWrap::Unwrap(args.This()); - assert(t->fileRef); - bool success = t->fileRef->save(); - if (success) - return Undefined(); - else - return ThrowException(String::Concat( - String::New("Failed to save file: "), - String::New(t->fileRef->file()->name()) +NAN_METHOD(Tag::SyncSaveTag) { + NanScope(); + Tag *t = ObjectWrap::Unwrap(args.This()); + assert(t->fileRef); + bool success = t->fileRef->save(); + if (success) + NanReturnUndefined(); + else + return NanThrowError(String::Concat( + NanNew("Failed to save file: "), + NanNew(t->fileRef->file()->name()) )); } -Handle Tag::SyncTag(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Tag::SyncTag) { + NanScope(); TagLib::FileRef *f = 0; int error = 0; @@ -154,49 +153,49 @@ Handle Tag::SyncTag(const Arguments &args) { if (args.Length() >= 1 && args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); if ((error = CreateFileRefPath(*path, &f))) { - Local fn = String::Concat(args[0]->ToString(), Local::Cast(String::New(": ", -1))); - return ThrowException(String::Concat(fn, ErrorToString(error))); + Local fn = String::Concat(args[0]->ToString(), Local::Cast(NanNew(": ", -1))); + return NanThrowError(String::Concat(fn, ErrorToString(error))); } } else if (args.Length() >= 1 && Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) - return ThrowException(String::New("Expected string 'format' as second argument")); + return NanThrowError("Expected string 'format' as second argument"); if ((error = CreateFileRef(new BufferStream(args[0]->ToObject()), NodeStringToTagLibString(args[1]->ToString()), &f))) { - return ThrowException(ErrorToString(error)); + return NanThrowError(ErrorToString(error)); } } else { - return ThrowException(String::New("Expected string or buffer as first argument")); + return NanThrowError("Expected string or buffer as first argument"); } Tag * tag = new Tag(f); - Handle inst = TagTemplate->InstanceTemplate()->NewInstance(); + Handle inst = NanNew(TagTemplate)->InstanceTemplate()->NewInstance(); tag->Wrap(inst); - return scope.Close(inst); + NanReturnValue(inst); } -v8::Handle Tag::AsyncTag(const v8::Arguments &args) { - HandleScope scope; +NAN_METHOD(Tag::AsyncTag) { + NanScope(); if (args.Length() < 1) { - return ThrowException(String::New("Expected string or buffer as first argument")); + return NanThrowError("Expected string or buffer as first argument"); } if (args[0]->IsString()) { if (args.Length() < 2 || !args[1]->IsFunction()) - return ThrowException(String::New("Expected callback function as second argument")); + return NanThrowError("Expected callback function as second argument"); } else if (Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) - return ThrowException(String::New("Expected string 'format' as second argument")); + return NanThrowError("Expected string 'format' as second argument"); if (args.Length() < 3 || !args[2]->IsFunction()) - return ThrowException(String::New("Expected callback function as third argument")); + return NanThrowError("Expected callback function as third argument"); } else { - return ThrowException(String::New("Expected string or buffer as first argument")); + return NanThrowError("Expected string or buffer as first argument"); } @@ -209,18 +208,18 @@ v8::Handle Tag::AsyncTag(const v8::Arguments &args) { if (args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); baton->path = strdup(*path); - baton->callback = Persistent::New(Local::Cast(args[1])); + NanAssignPersistent(baton->callback, Local::Cast(args[1])); } else { baton->format = NodeStringToTagLibString(args[1]->ToString()); baton->stream = new BufferStream(args[0]->ToObject()); - baton->callback = Persistent::New(Local::Cast(args[2])); + NanAssignPersistent(baton->callback, Local::Cast(args[2])); } uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncTagReadDo, (uv_after_work_cb)Tag::AsyncTagReadAfter); - return Undefined(); + NanReturnUndefined(); } void Tag::AsyncTagReadDo(uv_work_t *req) { @@ -242,34 +241,36 @@ void Tag::AsyncTagReadDo(uv_work_t *req) { } void Tag::AsyncTagReadAfter(uv_work_t *req) { - HandleScope scope; + NanScope(); AsyncBaton *baton = static_cast(req->data); if (baton->error) { - Local error = Object::New(); - error->Set(String::New("code"), Integer::New(baton->error)); - error->Set(String::New("message"), ErrorToString(baton->error)); - Handle argv[] = { error, Null() }; - baton->callback->Call(Context::GetCurrent()->Global(), 2, argv); + Local error = NanNew(); + error->Set(NanNew("code"), NanNew(baton->error)); + error->Set(NanNew("message"), ErrorToString(baton->error)); + Handle argv[] = { error, NanNull() }; + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 2, argv); } else { - Persistent inst = Persistent::New(TagTemplate->InstanceTemplate()->NewInstance()); - baton->tag->Wrap(inst); - Handle argv[] = { Null(), inst }; - baton->callback->Call(Context::GetCurrent()->Global(), 2, argv); + Persistent inst; + Handle localInst = NanNew(TagTemplate)->InstanceTemplate()->NewInstance(); + NanAssignPersistent(inst, localInst); + baton->tag->Wrap(localInst); + Handle argv[] = { NanNull(), localInst }; + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 2, argv); } - baton->callback.Dispose(); + NanDisposePersistent(baton->callback); delete baton->path; delete baton; } -v8::Handle Tag::AsyncSaveTag(const v8::Arguments &args) { - HandleScope scope; +NAN_METHOD(Tag::AsyncSaveTag) { + NanScope(); if (args.Length() >= 1 && !args[0]->IsFunction()) - return ThrowException(String::New("Expected callback function as first argument")); + return NanThrowError("Expected callback function as first argument"); Local callback = Local::Cast(args[0]); @@ -278,12 +279,12 @@ v8::Handle Tag::AsyncSaveTag(const v8::Arguments &args) { AsyncBaton *baton = new AsyncBaton; baton->request.data = baton; baton->tag = t; - baton->callback = Persistent::New(callback); + NanAssignPersistent(baton->callback, callback); baton->error = 1; uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncSaveTagDo, (uv_after_work_cb)Tag::AsyncSaveTagAfter); - return Undefined(); + NanReturnUndefined(); } void Tag::AsyncSaveTagDo(uv_work_t *req) { @@ -294,23 +295,23 @@ void Tag::AsyncSaveTagDo(uv_work_t *req) { } void Tag::AsyncSaveTagAfter(uv_work_t *req) { - HandleScope scope; + NanScope(); AsyncBaton *baton = static_cast(req->data); if (baton->error) { - Local 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())); + Local error = NanNew(); + error->Set(NanNew("message"), NanNew("Failed to save file")); + error->Set(NanNew("path"), NanNew(baton->tag->fileRef->file()->name())); Handle argv[] = { error }; - baton->callback->Call(Context::GetCurrent()->Global(), 1, argv); + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 1, argv); } else { - Handle argv[] = { Null() }; - baton->callback->Call(Context::GetCurrent()->Global(), 1, argv); + Handle argv[] = { NanNull() }; + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 1, argv); } - baton->callback.Dispose(); + NanDisposePersistent(baton->callback); delete baton; } diff --git a/src/tag.h b/src/tag.h index f327b21..f3d9d41 100644 --- a/src/tag.h +++ b/src/tag.h @@ -5,44 +5,44 @@ #include #include +#include + namespace node_taglib { class Tag : public node::ObjectWrap { TagLib::Tag * tag; TagLib::FileRef * fileRef; - //static v8::Persistent pft; - public: static void Initialize(v8::Handle target); Tag(TagLib::FileRef * fileRef); ~Tag(); - static v8::Handle GetTitle(v8::Local property, const v8::AccessorInfo& info); - static void SetTitle(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetTitle); + static NAN_SETTER(SetTitle); - static v8::Handle GetArtist(v8::Local property, const v8::AccessorInfo& info); - static void SetArtist(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetArtist); + static NAN_SETTER(SetArtist); - static v8::Handle GetAlbum(v8::Local property, const v8::AccessorInfo& info); - static void SetAlbum(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetAlbum); + static NAN_SETTER(SetAlbum); - static v8::Handle GetYear(v8::Local property, const v8::AccessorInfo& info); - static void SetYear(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetYear); + static NAN_SETTER(SetYear); - static v8::Handle GetComment(v8::Local property, const v8::AccessorInfo& info); - static void SetComment(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetComment); + static NAN_SETTER(SetComment); - static v8::Handle GetTrack(v8::Local property, const v8::AccessorInfo& info); - static void SetTrack(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetTrack); + static NAN_SETTER(SetTrack); - static v8::Handle GetGenre(v8::Local property, const v8::AccessorInfo& info); - static void SetGenre(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetGenre); + static NAN_SETTER(SetGenre); - static v8::Handle IsEmpty(const v8::Arguments &args); - static v8::Handle AsyncSaveTag(const v8::Arguments &args); - static v8::Handle SyncSaveTag(const v8::Arguments &args); - static v8::Handle SyncTag(const v8::Arguments &args); - static v8::Handle AsyncTag(const v8::Arguments &args); + static NAN_METHOD(IsEmpty); + static NAN_METHOD(AsyncSaveTag); + static NAN_METHOD(SyncSaveTag); + static NAN_METHOD(SyncTag); + static NAN_METHOD(AsyncTag); static void AsyncTagReadDo(uv_work_t *req); static void AsyncTagReadAfter(uv_work_t *req); static void AsyncSaveTagDo(uv_work_t *req); diff --git a/src/taglib.cc b/src/taglib.cc index b22dd6b..3671466 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -131,7 +131,7 @@ TagLib::File *createFile(TagLib::IOStream *stream, TagLib::String format) { } Handle ErrorToString(int error) { - HandleScope scope; + NanEscapableScope(); std::string err; switch (error) { @@ -152,29 +152,30 @@ Handle ErrorToString(int error) { break; } - return scope.Close(String::New(err.c_str(), err.length())); + return NanEscapeScope(NanNew(err.c_str(), err.length())); } -v8::Handle AsyncReadFile(const v8::Arguments &args) { - HandleScope scope; +NAN_METHOD(AsyncReadFile) { + NanScope(); + if (args.Length() < 1) { - return ThrowException(String::New("Expected string or buffer as first argument")); + return NanThrowError("Expected string or buffer as first argument"); } if (args[0]->IsString()) { if (args.Length() < 2 || !args[1]->IsFunction()) - return ThrowException(String::New("Expected callback function as second argument")); + return NanThrowError("Expected callback function as second argument"); } else if (Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) - return ThrowException(String::New("Expected string 'format' as second argument")); + return NanThrowError("Expected string 'format' as second argument"); if (args.Length() < 3 || !args[2]->IsFunction()) - return ThrowException(String::New("Expected callback function as third argument")); + return NanThrowError("Expected callback function as third argument"); } else { - return ThrowException(String::New("Expected string or buffer as first argument")); + return NanThrowError("Expected string or buffer as first argument"); } AsyncBaton *baton = new AsyncBaton; @@ -187,18 +188,18 @@ v8::Handle AsyncReadFile(const v8::Arguments &args) { if (args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); baton->path = strdup(*path); - baton->callback = Persistent::New(Local::Cast(args[1])); + NanAssignPersistent(baton->callback, Local::Cast(args[1])); } else { baton->format = NodeStringToTagLibString(args[1]->ToString()); baton->stream = new BufferStream(args[0]->ToObject()); - baton->callback = Persistent::New(Local::Cast(args[2])); + NanAssignPersistent(baton->callback, Local::Cast(args[2])); } uv_queue_work(uv_default_loop(), &baton->request, AsyncReadFileDo, (uv_after_work_cb)AsyncReadFileAfter); - return Undefined(); + NanReturnUndefined(); } void AsyncReadFileDo(uv_work_t *req) { @@ -220,39 +221,40 @@ void AsyncReadFileDo(uv_work_t *req) { } void AsyncReadFileAfter(uv_work_t *req) { + NanScope(); AsyncBaton *baton = static_cast(req->data); if (baton->error) { - Local error = Object::New(); - error->Set(String::New("code"), Integer::New(baton->error)); - error->Set(String::New("message"), ErrorToString(baton->error)); - Handle argv[] = { error, Null(), Null() }; - baton->callback->Call(Context::GetCurrent()->Global(), 3, argv); + Local error = NanNew(); + error->Set(NanNew("code"), NanNew(baton->error)); + error->Set(NanNew("message"), ErrorToString(baton->error)); + Handle argv[] = { error, NanNull(), NanNull() }; + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 3, argv); } else { // read the data, put it in objects and delete the fileref TagLib::Tag *tag = baton->fileRef->tag(); - Local tagObj = Object::New(); + Local tagObj = NanNew(); if (!tag->isEmpty()) { - tagObj->Set(String::New("album"), TagLibStringToString(tag->album())); - tagObj->Set(String::New("artist"), TagLibStringToString(tag->artist())); - tagObj->Set(String::New("comment"), TagLibStringToString(tag->comment())); - tagObj->Set(String::New("genre"), TagLibStringToString(tag->genre())); - tagObj->Set(String::New("title"), TagLibStringToString(tag->title())); - tagObj->Set(String::New("track"), Integer::New(tag->track())); - tagObj->Set(String::New("year"), Integer::New(tag->year())); + tagObj->Set(NanNew("album"), TagLibStringToString(tag->album())); + tagObj->Set(NanNew("artist"), TagLibStringToString(tag->artist())); + tagObj->Set(NanNew("comment"), TagLibStringToString(tag->comment())); + tagObj->Set(NanNew("genre"), TagLibStringToString(tag->genre())); + tagObj->Set(NanNew("title"), TagLibStringToString(tag->title())); + tagObj->Set(NanNew("track"), NanNew(tag->track())); + tagObj->Set(NanNew("year"), NanNew(tag->year())); } TagLib::AudioProperties *props = baton->fileRef->audioProperties(); - Local propsObj = Object::New(); + Local propsObj = NanNew(); if (props) { - propsObj->Set(String::New("length"), Integer::New(props->length())); - propsObj->Set(String::New("bitrate"), Integer::New(props->bitrate())); - propsObj->Set(String::New("sampleRate"), Integer::New(props->sampleRate())); - propsObj->Set(String::New("channels"), Integer::New(props->channels())); + propsObj->Set(NanNew("length"), NanNew(props->length())); + propsObj->Set(NanNew("bitrate"), NanNew(props->bitrate())); + propsObj->Set(NanNew("sampleRate"), NanNew(props->sampleRate())); + propsObj->Set(NanNew("channels"), NanNew(props->channels())); } - Handle argv[] = { Null(), tagObj, propsObj }; - baton->callback->Call(Context::GetCurrent()->Global(), 3, argv); + Handle argv[] = { NanNull(), tagObj, propsObj }; + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 3, argv); delete baton->fileRef; delete baton; @@ -262,14 +264,16 @@ void AsyncReadFileAfter(uv_work_t *req) { Handle TagLibStringToString( TagLib::String s ) { + NanEscapableScope(); if(s.isEmpty()) { - return Null(); + return NanEscapeScope(NanNull()); } else { TagLib::ByteVector str = s.data(TagLib::String::UTF16); // Strip the Byte Order Mark of the input to avoid node adding a UTF-8 // Byte Order Mark - return String::New((uint16_t *)str.mid(2,str.size()-2).data(), s.size()); + Handle v8string = NanNew((uint16_t *)str.mid(2,str.size()-2).data(), s.size()); + return NanEscapeScope(v8string); } } @@ -284,21 +288,20 @@ TagLib::String NodeStringToTagLibString( Local s ) } } -Handle AddResolvers(const Arguments &args) +NAN_METHOD(AddResolvers) { + NanScope(); for (int i = 0; i < args.Length(); i++) { Local arg = args[i]; if (arg->IsFunction()) { - Persistent resolver = Persistent::New(Local::Cast(arg)); - TagLib::FileRef::addFileTypeResolver(new CallbackResolver(resolver)); + TagLib::FileRef::addFileTypeResolver(new CallbackResolver(Local::Cast(arg))); } } - return Undefined(); + NanReturnUndefined(); } -CallbackResolver::CallbackResolver(Persistent func) +CallbackResolver::CallbackResolver(Handle func) : TagLib::FileRef::FileTypeResolver() - , resolverFunc(func) // the constructor is always called in the v8 thread #ifdef _WIN32 , created_in(GetCurrentThreadId()) @@ -306,6 +309,7 @@ CallbackResolver::CallbackResolver(Persistent func) , created_in(pthread_self()) #endif { + NanAssignPersistent(resolverFunc, func); } void CallbackResolver::invokeResolverCb(uv_async_t *handle, int status) @@ -323,9 +327,9 @@ void CallbackResolver::stopIdling(uv_async_t *handle, int status) void CallbackResolver::invokeResolver(AsyncResolverBaton *baton) { - HandleScope scope; + NanScope(); Handle argv[] = { TagLibStringToString(baton->fileName) }; - Local ret = baton->resolver->resolverFunc->Call(Context::GetCurrent()->Global(), 1, argv); + Local ret = NanNew(baton->resolver->resolverFunc)->Call(NanGetCurrentContext()->Global(), 1, argv); if (!ret->IsString()) { baton->type = TagLib::String::null; } @@ -347,9 +351,9 @@ TagLib::File *CallbackResolver::createFile(TagLib::FileName fileName, bool readA if (created_in != pthread_self()) { #endif uv_loop_t *wait_loop = uv_loop_new(); - uv_async_init(wait_loop, &baton.idler, CallbackResolver::stopIdling); + uv_async_init(wait_loop, &baton.idler, (uv_async_cb) CallbackResolver::stopIdling); - uv_async_init(uv_default_loop(), &baton.request, invokeResolverCb); + uv_async_init(uv_default_loop(), &baton.request, (uv_async_cb) invokeResolverCb); uv_async_send(&baton.request); uv_run(wait_loop, UV_RUN_DEFAULT); uv_loop_delete(wait_loop); @@ -369,18 +373,18 @@ extern "C" { static void init (Handle target) { - HandleScope scope; + NanScope(); #ifdef TAGLIB_WITH_ASF - target->Set(String::NewSymbol("WITH_ASF"), v8::True()); + target->Set(NanNew("WITH_ASF"), NanTrue()); #else - target->Set(String::NewSymbol("WITH_ASF"), v8::False()); + target->Set(NanNew("WITH_ASF"), NanFalse()); #endif #ifdef TAGLIB_WITH_MP4 - target->Set(String::NewSymbol("WITH_MP4"), v8::True()); + target->Set(NanNew("WITH_MP4"), NanTrue()); #else - target->Set(String::NewSymbol("WITH_MP4"), v8::False()); + target->Set(NanNew("WITH_MP4"), NanFalse()); #endif NODE_SET_METHOD(target, "read", AsyncReadFile); diff --git a/src/taglib.h b/src/taglib.h index 1fa7b45..adbbc69 100644 --- a/src/taglib.h +++ b/src/taglib.h @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -23,7 +24,7 @@ TagLib::File *createFile(TagLib::IOStream *stream, TagLib::String format); v8::Handle ErrorToString(int error); v8::Handle TagLibStringToString( TagLib::String s ); TagLib::String NodeStringToTagLibString( v8::Local s ); -v8::Handle AsyncReadFile(const v8::Arguments &args); +NAN_METHOD(AsyncReadFile); void AsyncReadFileDo(uv_work_t *req); void AsyncReadFileAfter(uv_work_t *req); @@ -43,7 +44,7 @@ struct AsyncBaton { Tag *tag; /* only used by taglib.tag */ }; -v8::Handle AddResolvers(const v8::Arguments &args); +NAN_METHOD(AddResolvers); class CallbackResolver; @@ -60,7 +61,7 @@ class CallbackResolver : public TagLib::FileRef::FileTypeResolver { const uv_thread_t created_in; public: - CallbackResolver(v8::Persistent func); + CallbackResolver(v8::Handle localFunc); TagLib::File *createFile(TagLib::FileName fileName, bool readAudioProperties, TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; static void invokeResolverCb(uv_async_t *handle, int status); static void stopIdling(uv_async_t *handle, int status);