Exemple #1
0
//***************************************************************************
bool Kwave::MP3Decoder::parseID3Tags(ID3_Tag &tag)
{
    if (tag.NumFrames() < 1) return true; // no tags, nothing to do

    QDate creation_date;
    QTime creation_time;
    int year  = -1;
    int month = -1;
    int day   = -1;

    ID3_Tag::Iterator *it = tag.CreateIterator();
    ID3_Frame *frame = 0;
    Kwave::FileInfo info(metaData());
    while (it && (frame = it->GetNext())) {
	const ID3_FrameID id = frame->GetID();
	const Kwave::FileProperty property = m_property_map.property(id);
	const ID3_PropertyMap::Encoding encoding = m_property_map.encoding(id);
	switch (encoding) {
	    case ID3_PropertyMap::ENC_TEXT_PARTINSET:
	    {
		QString s = parseId3Frame2String(frame);
		int cd  = 0;
		int cds = 0;
		if (s.contains(QLatin1Char('/'))) {
		    int i = s.indexOf(QLatin1Char('/'));
		    cd = s.left(i).toInt();
		    cds = s.mid(i + 1).toInt();
		} else {
		    cd = s.toInt();
		}
		if (cd  > 0) info.set(Kwave::INF_CD , QVariant(cd));
		if (cds > 0) info.set(Kwave::INF_CDS, QVariant(cds));
		break;
	    }
	    case ID3_PropertyMap::ENC_TRACK_NUM:
	    {
		QString s = parseId3Frame2String(frame);
		int track  = 0;
		int tracks = 0;
		if (s.contains(QLatin1Char('/'))) {
		    int i = s.indexOf(QLatin1Char('/'));
		    track = s.left(i).toInt();
		    tracks = s.mid(i + 1).toInt();
		} else {
		    track = s.toInt();
		}
		if (track  > 0) info.set(Kwave::INF_TRACK , QVariant(track));
		if (tracks > 0) info.set(Kwave::INF_TRACKS, QVariant(tracks));
		break;
	    }
	    case ID3_PropertyMap::ENC_TERMS_OF_USE:
		// the same as ENC_COMMENT, but without "Description"
		/* FALLTHROUGH */
	    case ID3_PropertyMap::ENC_COMMENT:
	    {
		QString s = parseId3Frame2String(frame);

		// optionally prepend language
		char *lang = ID3_GetString(frame, ID3FN_LANGUAGE);
		if (lang) {
		    s = _("[") + _(lang) + _("] ") + s;
		    ID3_FreeString(lang);
		}

		// append to already existing tag, separated by a slash
		if (info.contains(property))
		    s = info.get(property).toString() + _(" / ") + s;
		info.set(property, QVariant(s));
		break;
	    }
	    case ID3_PropertyMap::ENC_GENRE_TYPE:
	    {
		QString s = parseId3Frame2String(frame);
		int genre = Kwave::GenreType::fromID3(s);
		if (genre >= 0)
		    s = Kwave::GenreType::name(genre, false);
		info.set(property, QVariant(s));
		break;
	    }
	    case ID3_PropertyMap::ENC_LENGTH:
	    {
		// length in ms -> convert this to samples
		QString       s    = parseId3Frame2String(frame);
		const double  rate = info.rate();
		bool          ok   = false;
		const double  ms   = s.toDouble(&ok) + 0.5;
		if (ok && (rate > 0)) {
		    // NOTE: this overwrites the length found in the header!
		    sample_index_t length = static_cast<sample_index_t>(
			(rate * ms) / 1000.0);
		    info.setLength(length);
		}
		break;
	    }
	    case ID3_PropertyMap::ENC_TEXT_TIMESTAMP:
	    {
		if (!creation_date.isValid()) {
		    QString s = parseId3Frame2String(frame);
		    switch (id)
		    {
			case ID3FID_RECORDINGDATES:
			    // should be a ISO 8601 timestamp or similar
			    s = Kwave::string2date(s);
			    if (s.length())
				creation_date =
				    QDate::fromString(s, Qt::ISODate);
			    break;
			case ID3FID_DATE: {
			    // DDMM
			    unsigned int ddmm = s.toUInt();
			    day   = ddmm / 100;
			    month = ddmm % 100;
			    break;
			}
			case ID3FID_YEAR: /* FALLTHROUGH */
			case ID3FID_ORIGYEAR:
			    // YYYY
			    year = s.toUInt();
			    break;
			default:
			    break;
		    }
		}

		if (creation_time.isValid()) {
		    switch (id)
		    {
			case ID3FID_TIME:
			    creation_time = QTime::fromString(_("hhmm"));
			    break;
			default:
			    break;
		    }
		}
		break;
	    }
	    case ID3_PropertyMap::ENC_TEXT_SLASH:
	    {
		// append to already existing tag, separated by a slash
		QString s = parseId3Frame2String(frame);
		if (info.contains(property))
		    s = info.get(property).toString() + _(" / ") + s;
		info.set(property, QVariant(s));
		break;
	    }
	    case ID3_PropertyMap::ENC_TEXT_URL:   /* FALLTHROUGH */
	    case ID3_PropertyMap::ENC_TEXT:
		info.set(property, QVariant(parseId3Frame2String(frame)));
		break;
	    case ID3_PropertyMap::ENC_NONE: /* FALLTHROUGH */
	    default:
	    {
		QString s = parseId3Frame2String(frame);
		qWarning("unsupported ID3 tag: %d, descr: '%s', text: '%s'",
			 id, frame->GetDescription(), DBG(s));
		break;
	    }
	}
    }

    /*
     * try to build a valid creation date/time
     */
    if (!creation_date.isValid()) {
	// no complete creation date - try to reassemble from found y/m/d
	creation_date = QDate(year, month, day);
    }
    if (creation_date.isValid() && creation_time.isValid()) {
	// full date + time
	QDateTime dt(creation_date, creation_time);
	info.set(Kwave::INF_CREATION_DATE, dt.toString(
	    _("yyyy-MM-ddTHH:mm:ss")));
    } else if (creation_date.isValid()) {
	// date without time
	info.set(Kwave::INF_CREATION_DATE, creation_date.toString(
	    _("yyyy-MM-dd")));
    } else if (year > 0) {
	// only year
	creation_date = QDate(year, 1, 1);
	info.set(Kwave::INF_CREATION_DATE, creation_date.toString(_("yyyy")));
    }

    metaData().replace(Kwave::MetaDataList(info));

    return true;
}
Exemple #2
0
void play_debug_meta(char* filename){
  ID3_Tag tag(filename);

  ID3_Tag::Iterator* iter = tag.CreateIterator();
  ID3_Frame* frame = NULL;
  char buf[1000];

  // Iconv conversion descriptor: UTF-16 -> UTF-8
  iconv_t cd = iconv_open("UTF8","UTF16BE");

  while (NULL != (frame = iter->GetNext()))
  {
    char* val = NULL;
    field_text(&val, frame); 
    printf("Frame: type %d %s %s:\n", frame->GetID(), frame->GetTextID(), frame->GetDescription());
    ID3_Frame::Iterator* fieldIter = frame->CreateIterator();
    ID3_Field* field = NULL;

    while (NULL != (field = fieldIter->GetNext())) {
      printf("  Field: type ");
      ID3_FieldType type = field->GetType();
      switch(type) {
      case ID3FTY_NONE:
        printf("none"); break;
      case ID3FTY_INTEGER:
        printf("int"); break;
      case ID3FTY_BINARY:
        printf("binary"); break;
      case ID3FTY_TEXTSTRING:
        field->Get(buf, 1000);
        printf("text with %d items, encoding ", field->GetNumTextItems());
        switch(field->GetEncoding()){
        case ID3TE_UTF16: printf("UTF-16"); 

          if ( cd != (iconv_t) -1 ) {
            char* in = (char*) field->GetRawUnicodeText();
            size_t insize = field->Size();

            char* bufptr = buf;
            size_t bufsize = 1000;
            size_t rc = 0;

            // Initialize iconv state
            if( iconv(cd, NULL, NULL, &bufptr, &bufsize) == (size_t) -1 ){
              printf("iconv init Failed\n");
            }
            if ( (rc = iconv(cd, &in, &insize, &bufptr, &bufsize)) != (size_t) -1 ) {
              *bufptr = '\0';
              printf(": '%s' (%d chars)\n", buf, rc);
            } else {
              printf("<conversion using iconv failed>");
              perror("iconv");
            }
          }
          break;
        case ID3TE_UTF16BE: printf("UTF-16BE"); 
          printf(": '%s'", buf);
          break;
        case ID3TE_UTF8: printf("UTF-8");
          printf(": '%s'", buf);
          break;
        case ID3TE_NONE: printf("none");
          printf(": '%s'", buf);
          break;
        case ID3TE_ISO8859_1: printf("ISO-8859-1/ASCII");
          printf(": '%s'", buf);
          break;
        }
        break;
      }
      printf("\n");
    }
    delete fieldIter;
    delete [] val;
  }
  delete iter;

  iconv_close(cd);
}