Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set properties dynamically (useful for lyrics, composer etc) #18

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 36 additions & 49 deletions src/taglib2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ using namespace std;
using namespace v8;
using namespace node;

static std::wstring GetWString(v8::Handle<v8::String> str)
{
uint16_t* buf = new uint16_t[str->Length()+1];
str->Write(buf);
std::wstring value = reinterpret_cast<wchar_t*>(buf);
delete [] buf;
return value;
}

Local<Value> TagLibStringToString(TagLib::String s) {

if (s.isEmpty()) return Nan::Null();
Expand All @@ -53,13 +62,9 @@ TagLib::String StringToTagLibString(std::string s) {
return TagLib::String(s, TagLib::String::UTF8);
}

bool isFile(const char *s) {
struct stat st;
#ifdef _WIN32
return ::stat(s, &st) == 0 && (st.st_mode & (S_IFREG));
#else
return ::stat(s, &st) == 0 && (st.st_mode & (S_IFREG | S_IFLNK));
#endif
bool isFile(const wchar_t *fileName) {
std::ifstream infile(fileName);
return infile.good();
}

NAN_METHOD(writeTagsSync) {
Expand All @@ -79,7 +84,7 @@ NAN_METHOD(writeTagsSync) {
if (!info[1]->IsObject()) return;

options = v8::Local<v8::Object>::Cast(info[1]);
std::string audio_file = *v8::String::Utf8Value(info[0]->ToString());
std::wstring audio_file = GetWString(info[0]->ToString());

if (!isFile(audio_file.c_str())) {
Nan::ThrowTypeError("Audio file not found");
Expand Down Expand Up @@ -120,47 +125,29 @@ NAN_METHOD(writeTagsSync) {
return o->Get(Nan::New(name).ToLocalChecked())->Int32Value();
};

if (hasOption(options, "albumartist")) {
hasProps = true;
TagLib::String value = getOptionString(options, "albumartist");
map.erase(TagLib::String("ALBUMARTIST"));
map.insert(TagLib::String("ALBUMARTIST"), value);
}
string common_props[8] = {"artist", "title", "album", "comment", "genre", "year", "track", "pictures"};

if (hasOption(options, "discnumber")) {
hasProps = true;
TagLib::String value = getOptionString(options, "discnumber");
map.erase(TagLib::String("DISCNUMBER"));
map.insert(TagLib::String("DISCNUMBER"), value);
}
Local<Array> property_names = options->GetOwnPropertyNames();
for (int i = 0; i < property_names->Length(); ++i) {
auto key = property_names->Get(Nan::New(i));
std::string key_utf = *v8::String::Utf8Value(key);

if (hasOption(options, "tracknumber")) {
hasProps = true;
TagLib::String value = getOptionString(options, "tracknumber");
map.erase(TagLib::String("TRACKNUMBER"));
map.insert(TagLib::String("TRACKNUMBER"), value);
}
bool isCommon = false;

if (hasOption(options, "composer")) {
hasProps = true;
TagLib::String value = getOptionString(options, "composer");
map.erase(TagLib::String("COMPOSER"));
map.insert(TagLib::String("COMPOSER"), value);
}
for (int i = 0; i < 8; i++) {
if (key_utf.compare(common_props[i]) == 0)
isCommon = true;
}

if (hasOption(options, "id")) {
hasProps = true;
TagLib::String value = getOptionString(options, "id");
map.erase(TagLib::String("ID"));
map.insert(TagLib::String("ID"), value);
}
if (!isCommon) {
hasProps = true;

if (hasOption(options, "bpm")) {
hasProps = true;
TagLib::String value = getOptionString(options, "bpm");
map.erase(TagLib::String("BPM"));
map.insert(TagLib::String("BPM"), value);
}
TagLib::String value = getOptionString(options, key_utf);

map.erase(TagLib::String(TagLib::String(key_utf).upper()));
map.insert(TagLib::String(TagLib::String(key_utf).upper()), value);
}
}

if (hasProps) {
f.setProperties(map);
Expand Down Expand Up @@ -247,15 +234,15 @@ NAN_METHOD(writeTagsSync) {
NAN_METHOD(readTagsSync) {
Nan::HandleScope scope;

std::string audio_file = *v8::String::Utf8Value(info[0]->ToString());
std::wstring audio_file = GetWString(info[0]->ToString());

if (!isFile(audio_file.c_str())) {
Nan::ThrowTypeError("Audio file not found");
return;
}

string ext;
const size_t pos = audio_file.find_last_of(".");
std::wstring ext;
const size_t pos = audio_file.find_last_of(L".");

if (pos != -1) {
ext = audio_file.substr(pos + 1);
Expand Down Expand Up @@ -373,7 +360,7 @@ NAN_METHOD(readTagsSync) {
// file is not the greatest way to get the pictures for flac files. It seems
// like this should be managed by the tag->pictures() method on FileRef, but
// isn't, open to changes here.
if (audio_file.find(".flac") != std::string::npos) {
if (audio_file.find(L".flac") != std::wstring::npos) {

TagLib::FLAC::File flacfile(audio_file.c_str());
TagLib::List<TagLib::FLAC::Picture *> list = flacfile.pictureList();
Expand Down Expand Up @@ -468,7 +455,7 @@ NAN_METHOD(readTagsSync) {
// this is the same hackery, a second read, is required to get the codec
// since codec isn't always a member of audioProperties. There should be
// a better way of getting properties that are unique to each format.
if (ext == "M4A" || ext == "MP4") {
if (ext == L"M4A" || ext == L"MP4") {
TagLib::MP4::File mp4file(audio_file.c_str());
if (mp4file.audioProperties()) {
auto codec = mp4file.audioProperties()->codec();
Expand Down