Esempio n. 1
0
void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const
{
  if(tag->header()->majorVersion() < 4 &&
     tag->frameList("TDRC").size() == 1 &&
     tag->frameList("TDAT").size() == 1)
  {
    TextIdentificationFrame *tdrc =
      static_cast<TextIdentificationFrame *>(tag->frameList("TDRC").front());
    UnknownFrame *tdat = static_cast<UnknownFrame *>(tag->frameList("TDAT").front());

    if(tdrc->fieldList().size() == 1 &&
       tdrc->fieldList().front().size() == 4 &&
       tdat->data().size() >= 5)
    {
      String date(tdat->data().mid(1), String::Type(tdat->data()[0]));
      if(date.length() == 4) {
        tdrc->setText(tdrc->toString() + '-' + date.substr(2, 2) + '-' + date.substr(0, 2));
        if(tag->frameList("TIME").size() == 1) {
          UnknownFrame *timeframe = static_cast<UnknownFrame *>(tag->frameList("TIME").front());
          if(timeframe->data().size() >= 5) {
            String time(timeframe->data().mid(1), String::Type(timeframe->data()[0]));
            if(time.length() == 4) {
              tdrc->setText(tdrc->toString() + 'T' + time.substr(0, 2) + ':' + time.substr(2, 2));
            }
          }
        }
      }
    }
  }
}
Esempio n. 2
0
String ID3v2::Tag::genre() const
{
  // TODO: In the next major version (TagLib 2.0) a list of multiple genres
  // should be separated by " / " instead of " ".  For the moment to keep
  // the behavior the same as released versions it is being left with " ".

  if(d->frameListMap["TCON"].isEmpty() ||
     !dynamic_cast<TextIdentificationFrame *>(d->frameListMap["TCON"].front()))
  {
    return String::null;
  }

  // ID3v2.4 lists genres as the fields in its frames field list.  If the field
  // is simply a number it can be assumed that it is an ID3v1 genre number.
  // Here was assume that if an ID3v1 string is present that it should be
  // appended to the genre string.  Multiple fields will be appended as the
  // string is built.

  TextIdentificationFrame *f = static_cast<TextIdentificationFrame *>(
    d->frameListMap["TCON"].front());

  StringList fields = f->fieldList();

  StringList genres;

  for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) {

    if((*it).isEmpty())
      continue;

    bool isNumber = true;

    for(String::ConstIterator charIt = (*it).begin();
        isNumber && charIt != (*it).end();
        ++charIt)
    {
      isNumber = *charIt >= '0' && *charIt <= '9';
    }

    if(isNumber) {
      int number = (*it).toInt();
      if(number >= 0 && number <= 255)
        *it = ID3v1::genre(number);
    }

    if(std::find(genres.begin(), genres.end(), *it) == genres.end())
      genres.append(*it);
  }

  return genres.toString();
}
Esempio n. 3
0
String ID3v2::Tag::genre() const
{
  // TODO: In the next major version (TagLib 2.0) a list of multiple genres
  // should be separated by " / " instead of " ".  For the moment to keep
  // the behavior the same as released versions it is being left with " ".

  if(!d->frameListMap["TCON"].isEmpty() &&
     dynamic_cast<TextIdentificationFrame *>(d->frameListMap["TCON"].front()))
  {
    Frame *frame = d->frameListMap["TCON"].front();

    // ID3v2.4 lists genres as the fields in its frames field list.  If the field
    // is simply a number it can be assumed that it is an ID3v1 genre number.
    // Here was assume that if an ID3v1 string is present that it should be
    // appended to the genre string.  Multiple fields will be appended as the
    // string is built.

    if(d->header.majorVersion() == 4) {
      TextIdentificationFrame *f = static_cast<TextIdentificationFrame *>(frame);
      StringList fields = f->fieldList();

      String genreString;
      bool hasNumber = false;

      for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) {
        bool isNumber = true;
        for(String::ConstIterator charIt = (*it).begin();
            isNumber && charIt != (*it).end();
            ++charIt)
        {
          isNumber = *charIt >= '0' && *charIt <= '9';
        }

        if(!genreString.isEmpty())
          genreString.append(' ');

        if(isNumber) {
          int number = (*it).toInt();
          if(number >= 0 && number <= 255) {
            hasNumber = true;
            genreString.append(ID3v1::genre(number));
          }
        }
        else
          genreString.append(*it);
      }
      if(hasNumber)
        return genreString;
    }

    String s = frame->toString();

    // ID3v2.3 "content type" can contain a ID3v1 genre number in parenthesis at
    // the beginning of the field.  If this is all that the field contains, do a
    // translation from that number to the name and return that.  If there is a
    // string folloing the ID3v1 genre number, that is considered to be
    // authoritative and we return that instead.  Or finally, the field may
    // simply be free text, in which case we just return the value.

    int closing = s.find(")");
    if(s.substr(0, 1) == "(" && closing > 0) {
      if(closing == int(s.size() - 1))
        return ID3v1::genre(s.substr(1, s.size() - 2).toInt());
      else
        return s.substr(closing + 1);
    }
    return s;
  }
  return String::null;
}