nikhilm / node-taglib

Simple taglib bindings to Javascript using node.js
http://nikhilm.github.com/node-taglib
MIT License
147 stars 25 forks source link

Add async API #15

Closed nikhilm closed 12 years ago

nikhilm commented 12 years ago

FileRef is blocking until the file is read, move this into the libuv thread pool. Provide async and sync APIs.

nikhilm commented 12 years ago

Also provide async API for Tag.save

nikhilm commented 12 years ago

Possible designs:

TagLib.tag(filename, function(err, Tag) {
    Tag.artist = null;
    Tag.save(function(err) {})
})
TagLib.audioProperties(filename, function(err, AudioProperties) {
})
nikhilm commented 12 years ago

Check if setting tag.field = value is an I/O operation or not, that is, does I/O only occur when FileRef::save is called of also when setting individual fields.

lennart commented 12 years ago

I just checked the taglib source for the implementation of setTitle on both MPEG and OGG and they just do the following:

the tl;dr

Guessing, that they wrote consistent code in taglib, all other methods (setYear, setArtist etc.) and all other implementations (FLAC, MP4) will defer all I/O operations until a save() call. In short:

tag.field = value will never do any I/O operation

the investigation

from xiphcomment.cpp#124

void Ogg::XiphComment::setTitle(const String &s)
{ 
  addField("TITLE", s);
}

and xiphcomment.cpp#196

void Ogg::XiphComment::addField(const String &key, const String &value, bool replace)
{
  if(replace)
    removeField(key.upper());

  if(!key.isEmpty() && !value.isEmpty())
    d->fieldListMap[key.upper()].append(value);
}

and for ID3Tags (in this case v2)

from taglib/mpeg/id3v2/id3v2tag.cpp#194

void ID3v2::Tag::setTitle(const String &s)
{
  setTextFrame("TIT2", s);
}

and on line 460

void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value)
{
  if(value.isEmpty()) {
    removeFrames(id);
    return;
  }

  if(!d->frameListMap[id].isEmpty())
    d->frameListMap[id].front()->setText(value);
  else {
    const String::Type encoding = d->factory->defaultTextEncoding();
    TextIdentificationFrame *f = new TextIdentificationFrame(id, encoding);
    addFrame(f);
    f->setText(value);
  }
}

addFrame just adds the frame to the frameList (line 304)

void ID3v2::Tag::addFrame(Frame *frame)
{
  d->frameList.append(frame);
  d->frameListMap[frame->frameID()].append(frame);
}

digging deeper TextIdentificationFrame->setText() is defined in taglib/mpeg/id3v2/frames/textidentificationframe.cpp#65

void TextIdentificationFrame::setText(const StringList &l)
{
  d->fieldList = l;
}

void TextIdentificationFrame::setText(const String &s)
{
  d->fieldList = s;
}