Beispiel #1
0
Tag::Tag(const QString &filename)
    : m_filename(filename)
{
    TagLib::MPEG::File mpegfile(filename.toLocal8Bit().constData());
    TagLib::ID3v2::Tag* id3v2 = mpegfile.ID3v2Tag();
    if (id3v2 && !id3v2->isEmpty()) {
        readRegularTag(id3v2, m_data);

        int picnum = 0;

        TagLib::ID3v2::FrameList frames = id3v2->frameListMap()["APIC"]; // attached picture
        TagLib::ID3v2::FrameList::ConstIterator it = frames.begin();
        while (it != frames.end()) {
            TagLib::ID3v2::AttachedPictureFrame* apic = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(*it);
            TagLib::ByteVector bytes = apic->picture();
            QImage img = QImage::fromData(reinterpret_cast<const uchar*>(bytes.data()), bytes.size());
            if (!img.isNull()) {
                m_data[QLatin1String("picture") + QString::number(picnum++)] = QVariant(img);
            }
            ++it;
        }

    } else {
        TagLib::FileRef fileref(filename.toLocal8Bit().constData());
        if (fileref.isNull())
            return;
        TagLib::Tag* tag = fileref.tag();
        if (!tag || tag->isEmpty())
            return;

        readRegularTag(tag, m_data);
    }
}
bool TagReader::IsMediaFile(const QString& filename) const {
  qLog(Debug) << "Checking for valid file" << filename;

  std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
  return !fileref->isNull() && fileref->tag();
}
bool TagReader::SaveSongRatingToFile(
    const QString& filename, const pb::tagreader::SongMetadata& song) const {
  if (filename.isNull()) return false;

  qLog(Debug) << "Saving song rating tags to" << filename;
  if (song.rating() < 0) {
    // The FMPS spec says unrated == "tag not present". For us, no rating
    // results in rating being -1, so don't write anything in that case.
    // Actually, we should also remove tag set in this case, but in
    // Clementine it is not possible to unset rating i.e. make a song "unrated".
    qLog(Debug) << "Unrated: do nothing";
    return true;
  }

  std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));

  if (!fileref || fileref->isNull())  // The file probably doesn't exist
    return false;

  if (TagLib::MPEG::File* file =
          dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
    TagLib::ID3v2::Tag* tag = file->ID3v2Tag(true);

    // Save as FMPS
    SetUserTextFrame("FMPS_Rating", QString::number(song.rating()), tag);

    // Also save as POPM
    TagLib::ID3v2::PopularimeterFrame* frame = GetPOPMFrameFromTag(tag);
    frame->setRating(ConvertToPOPMRating(song.rating()));

  } else if (TagLib::FLAC::File* file =
                 dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
    TagLib::Ogg::XiphComment* vorbis_comments = file->xiphComment(true);
    SetFMPSRatingVorbisComments(vorbis_comments, song);
  } else if (TagLib::Ogg::XiphComment* tag =
                 dynamic_cast<TagLib::Ogg::XiphComment*>(
                     fileref->file()->tag())) {
    SetFMPSRatingVorbisComments(tag, song);
  }
#ifdef TAGLIB_WITH_ASF
  else if (TagLib::ASF::File* file =
               dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
    TagLib::ASF::Tag* tag = file->tag();
    tag->addAttribute("FMPS/Rating", NumberToASFAttribute(song.rating()));
  }
#endif
  else if (TagLib::MP4::File* file =
               dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
    TagLib::MP4::Tag* tag = file->tag();
    tag->itemListMap()[kMP4_FMPS_Rating_ID] = TagLib::StringList(
        QStringToTaglibString(QString::number(song.rating())));
  } else {
    // Nothing to save: stop now
    return true;
  }

  bool ret = fileref->save();
#ifdef Q_OS_LINUX
  if (ret) {
    // Linux: inotify doesn't seem to notice the change to the file unless we
    // change the timestamps as well. (this is what touch does)
    utimensat(0, QFile::encodeName(filename).constData(), nullptr, 0);
  }
#endif  // Q_OS_LINUX
  return ret;
}
bool TagReader::SaveSongStatisticsToFile(
    const QString& filename, const pb::tagreader::SongMetadata& song) const {
  if (filename.isNull()) return false;

  qLog(Debug) << "Saving song statistics tags to" << filename;

  std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));

  if (!fileref || fileref->isNull())  // The file probably doesn't exist
    return false;

  if (TagLib::MPEG::File* file =
          dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
    TagLib::ID3v2::Tag* tag = file->ID3v2Tag(true);

    // Save as FMPS
    SetUserTextFrame("FMPS_PlayCount", QString::number(song.playcount()), tag);
    SetUserTextFrame("FMPS_Rating_Amarok_Score",
                     QString::number(song.score() / 100.0), tag);

    // Also save as POPM
    TagLib::ID3v2::PopularimeterFrame* frame = GetPOPMFrameFromTag(tag);
    frame->setCounter(song.playcount());

  } else if (TagLib::FLAC::File* file =
                 dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
    TagLib::Ogg::XiphComment* vorbis_comments = file->xiphComment(true);
    SetFMPSStatisticsVorbisComments(vorbis_comments, song);
  } else if (TagLib::Ogg::XiphComment* tag =
                 dynamic_cast<TagLib::Ogg::XiphComment*>(
                     fileref->file()->tag())) {
    SetFMPSStatisticsVorbisComments(tag, song);
  }
#ifdef TAGLIB_WITH_ASF
  else if (TagLib::ASF::File* file =
               dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
    TagLib::ASF::Tag* tag = file->tag();
    tag->addAttribute("FMPS/Playcount", NumberToASFAttribute(song.playcount()));
    tag->addAttribute("FMPS/Rating_Amarok_Score",
                      NumberToASFAttribute(song.score() / 100.0));
  }
#endif
  else if (TagLib::MP4::File* file =
               dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
    TagLib::MP4::Tag* tag = file->tag();
    tag->itemListMap()[kMP4_FMPS_Score_ID] = TagLib::StringList(
        QStringToTaglibString(QString::number(song.score() / 100.0)));
    tag->itemListMap()[kMP4_FMPS_Playcount_ID] =
        TagLib::StringList(TagLib::String::number(song.playcount()));
  } else {
    // Nothing to save: stop now
    return true;
  }

  bool ret = fileref->save();
#ifdef Q_OS_LINUX
  if (ret) {
    // Linux: inotify doesn't seem to notice the change to the file unless we
    // change the timestamps as well. (this is what touch does)
    utimensat(0, QFile::encodeName(filename).constData(), nullptr, 0);
  }
#endif  // Q_OS_LINUX
  return ret;
}
bool TagReader::SaveFile(const QString& filename,
                         const pb::tagreader::SongMetadata& song) const {
  if (filename.isNull()) return false;

  qLog(Debug) << "Saving tags to" << filename;

  std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));

  if (!fileref || fileref->isNull())  // The file probably doesn't exist
    return false;

  fileref->tag()->setTitle(StdStringToTaglibString(song.title()));
  fileref->tag()->setArtist(StdStringToTaglibString(song.artist()));  // TPE1
  fileref->tag()->setAlbum(StdStringToTaglibString(song.album()));
  fileref->tag()->setGenre(StdStringToTaglibString(song.genre()));
  fileref->tag()->setComment(StdStringToTaglibString(song.comment()));
  fileref->tag()->setYear(song.year());
  fileref->tag()->setTrack(song.track());

  if (TagLib::MPEG::File* file =
          dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
    TagLib::ID3v2::Tag* tag = file->ID3v2Tag(true);
    SetTextFrame(
        "TPOS", song.disc() <= 0 - 1 ? QString() : QString::number(song.disc()),
        tag);
    SetTextFrame("TBPM",
                 song.bpm() <= 0 - 1 ? QString() : QString::number(song.bpm()),
                 tag);
    SetTextFrame("TCOM", song.composer(), tag);
    SetTextFrame("TIT1", song.grouping(), tag);
    // Skip TPE1 (which is the artist) here because we already set it
    SetTextFrame("TPE2", song.albumartist(), tag);
    SetTextFrame("TCMP", std::string(song.compilation() ? "1" : "0"), tag);
  } else if (TagLib::FLAC::File* file =
                 dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
    TagLib::Ogg::XiphComment* tag = file->xiphComment();
    SetVorbisComments(tag, song);
  } else if (TagLib::MP4::File* file =
                 dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
    TagLib::MP4::Tag* tag = file->tag();
    tag->itemListMap()["disk"] =
        TagLib::MP4::Item(song.disc() <= 0 - 1 ? 0 : song.disc(), 0);
    tag->itemListMap()["tmpo"] = TagLib::StringList(
        song.bpm() <= 0 - 1 ? "0" : TagLib::String::number(song.bpm()));
    tag->itemListMap()["\251wrt"] = TagLib::StringList(song.composer());
    tag->itemListMap()["\251grp"] = TagLib::StringList(song.grouping());
    tag->itemListMap()["aART"] = TagLib::StringList(song.albumartist());
    tag->itemListMap()["cpil"] =
        TagLib::StringList(song.compilation() ? "1" : "0");
  }

  // Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same
  // way;
  // apart, so we keep specific behavior for some formats by adding another
  // "else if" block above.
  if (TagLib::Ogg::XiphComment* tag =
          dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
    SetVorbisComments(tag, song);
  }

  bool ret = fileref->save();
#ifdef Q_OS_LINUX
  if (ret) {
    // Linux: inotify doesn't seem to notice the change to the file unless we
    // change the timestamps as well. (this is what touch does)
    utimensat(0, QFile::encodeName(filename).constData(), nullptr, 0);
  }
#endif  // Q_OS_LINUX

  return ret;
}
void TagReader::ReadFile(const QString& filename,
                         pb::tagreader::SongMetadata* song) const {
  const QByteArray url(QUrl::fromLocalFile(filename).toEncoded());
  const QFileInfo info(filename);

  qLog(Debug) << "Reading tags from" << filename;

  song->set_basefilename(DataCommaSizeFromQString(info.fileName()));
  song->set_url(url.constData(), url.size());
  song->set_filesize(info.size());
  song->set_mtime(info.lastModified().toTime_t());
  song->set_ctime(info.created().toTime_t());

  std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
  if (fileref->isNull()) {
    qLog(Info) << "TagLib hasn't been able to read " << filename << " file";
    return;
  }

  TagLib::Tag* tag = fileref->tag();
  if (tag) {
    Decode(tag->title(), nullptr, song->mutable_title());
    Decode(tag->artist(), nullptr, song->mutable_artist());  // TPE1
    Decode(tag->album(), nullptr, song->mutable_album());
    Decode(tag->genre(), nullptr, song->mutable_genre());
    song->set_year(tag->year());
    song->set_track(tag->track());
    song->set_valid(true);
  }

  QString disc;
  QString compilation;

  // Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same
  // way;
  // apart, so we keep specific behavior for some formats by adding another
  // "else if" block below.
  if (TagLib::Ogg::XiphComment* tag =
          dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
    ParseOggTag(tag->fieldListMap(), nullptr, &disc, &compilation, song);
  }

  if (TagLib::MPEG::File* file =
          dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
    if (file->ID3v2Tag()) {
      const TagLib::ID3v2::FrameListMap& map = file->ID3v2Tag()->frameListMap();

      if (!map["TPOS"].isEmpty())
        disc = TStringToQString(map["TPOS"].front()->toString()).trimmed();

      if (!map["TBPM"].isEmpty())
        song->set_bpm(TStringToQString(map["TBPM"].front()->toString())
                          .trimmed()
                          .toFloat());

      if (!map["TCOM"].isEmpty())
        Decode(map["TCOM"].front()->toString(), nullptr,
               song->mutable_composer());

      if (!map["TIT1"].isEmpty())  // content group
        Decode(map["TIT1"].front()->toString(), nullptr,
               song->mutable_grouping());

      // Skip TPE1 (which is the artist) here because we already fetched it

      if (!map["TPE2"].isEmpty())  // non-standard: Apple, Microsoft
        Decode(map["TPE2"].front()->toString(), nullptr,
               song->mutable_albumartist());

      if (!map["TCMP"].isEmpty())
        compilation =
            TStringToQString(map["TCMP"].front()->toString()).trimmed();

      if (!map["APIC"].isEmpty()) song->set_art_automatic(kEmbeddedCover);

      // Find a suitable comment tag.  For now we ignore iTunNORM comments.
      for (int i = 0; i < map["COMM"].size(); ++i) {
        const TagLib::ID3v2::CommentsFrame* frame =
            dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(map["COMM"][i]);

        if (frame && TStringToQString(frame->description()) != "iTunNORM") {
          Decode(frame->text(), nullptr, song->mutable_comment());
          break;
        }
      }

      // Parse FMPS frames
      for (int i = 0; i < map["TXXX"].size(); ++i) {
        const TagLib::ID3v2::UserTextIdentificationFrame* frame =
            dynamic_cast<const TagLib::ID3v2::UserTextIdentificationFrame*>(
                map["TXXX"][i]);

        if (frame && frame->description().startsWith("FMPS_")) {
          ParseFMPSFrame(TStringToQString(frame->description()),
                         TStringToQString(frame->fieldList()[1]), song);
        }
      }

      // Check POPM tags
      // We do this after checking FMPS frames, so FMPS have precedence, as we
      // will consider POPM tags iff song has no rating/playcount already set.
      if (!map["POPM"].isEmpty()) {
        const TagLib::ID3v2::PopularimeterFrame* frame =
            dynamic_cast<const TagLib::ID3v2::PopularimeterFrame*>(
                map["POPM"].front());
        if (frame) {
          // Take a user rating only if there's no rating already set
          if (song->rating() <= 0 && frame->rating() > 0) {
            song->set_rating(ConvertPOPMRating(frame->rating()));
          }
          if (song->playcount() <= 0 && frame->counter() > 0) {
            song->set_playcount(frame->counter());
          }
        }
      }
    }
  } else if (TagLib::FLAC::File* file =
                 dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
    if (file->xiphComment()) {
      ParseOggTag(file->xiphComment()->fieldListMap(), nullptr, &disc,
                  &compilation, song);
#ifdef TAGLIB_HAS_FLAC_PICTURELIST
      if (!file->pictureList().isEmpty()) {
        song->set_art_automatic(kEmbeddedCover);
      }
#endif
    }
    Decode(tag->comment(), nullptr, song->mutable_comment());
  } else if (TagLib::MP4::File* file =
                 dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
    if (file->tag()) {
      TagLib::MP4::Tag* mp4_tag = file->tag();
      const TagLib::MP4::ItemListMap& items = mp4_tag->itemListMap();

      // Find album artists
      TagLib::MP4::ItemListMap::ConstIterator it = items.find("aART");
      if (it != items.end()) {
        TagLib::StringList album_artists = it->second.toStringList();
        if (!album_artists.isEmpty()) {
          Decode(album_artists.front(), nullptr, song->mutable_albumartist());
        }
      }

      // Find album cover art
      if (items.find("covr") != items.end()) {
        song->set_art_automatic(kEmbeddedCover);
      }

      if (items.contains("disk")) {
        disc = TStringToQString(
            TagLib::String::number(items["disk"].toIntPair().first));
      }

      if (items.contains(kMP4_FMPS_Rating_ID)) {
        float rating =
            TStringToQString(items[kMP4_FMPS_Rating_ID].toStringList().toString(
                                 '\n')).toFloat();
        if (song->rating() <= 0 && rating > 0) {
          song->set_rating(rating);
        }
      }
      if (items.contains(kMP4_FMPS_Playcount_ID)) {
        int playcount =
            TStringToQString(
                items[kMP4_FMPS_Playcount_ID].toStringList().toString('\n'))
                .toFloat();
        if (song->playcount() <= 0 && playcount > 0) {
          song->set_playcount(playcount);
        }
      }
      if (items.contains(kMP4_FMPS_Playcount_ID)) {
        int score = TStringToQString(
                        items[kMP4_FMPS_Score_ID].toStringList().toString('\n'))
                        .toFloat() *
                    100;
        if (song->score() <= 0 && score > 0) {
          song->set_score(score);
        }
      }

      if (items.contains("\251wrt")) {
        Decode(items["\251wrt"].toStringList().toString(", "), nullptr,
               song->mutable_composer());
      }
      if (items.contains("\251grp")) {
        Decode(items["\251grp"].toStringList().toString(" "), nullptr,
               song->mutable_grouping());
      }
      Decode(mp4_tag->comment(), nullptr, song->mutable_comment());
    }
  }
#ifdef TAGLIB_WITH_ASF
  else if (TagLib::ASF::File* file =
               dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
    const TagLib::ASF::AttributeListMap& attributes_map =
        file->tag()->attributeListMap();
    if (attributes_map.contains("FMPS/Rating")) {
      const TagLib::ASF::AttributeList& attributes =
          attributes_map["FMPS/Rating"];
      if (!attributes.isEmpty()) {
        float rating =
            TStringToQString(attributes.front().toString()).toFloat();
        if (song->rating() <= 0 && rating > 0) {
          song->set_rating(rating);
        }
      }
    }
    if (attributes_map.contains("FMPS/Playcount")) {
      const TagLib::ASF::AttributeList& attributes =
          attributes_map["FMPS/Playcount"];
      if (!attributes.isEmpty()) {
        int playcount = TStringToQString(attributes.front().toString()).toInt();
        if (song->playcount() <= 0 && playcount > 0) {
          song->set_playcount(playcount);
        }
      }
    }
    if (attributes_map.contains("FMPS/Rating_Amarok_Score")) {
      const TagLib::ASF::AttributeList& attributes =
          attributes_map["FMPS/Rating_Amarok_Score"];
      if (!attributes.isEmpty()) {
        int score =
            TStringToQString(attributes.front().toString()).toFloat() * 100;
        if (song->score() <= 0 && score > 0) {
          song->set_score(score);
        }
      }
    }
  }
#endif
  else if (tag) {
    Decode(tag->comment(), nullptr, song->mutable_comment());
  }

  if (!disc.isEmpty()) {
    const int i = disc.indexOf('/');
    if (i != -1) {
      // disc.right( i ).toInt() is total number of discs, we don't use this at
      // the moment
      song->set_disc(disc.left(i).toInt());
    } else {
      song->set_disc(disc.toInt());
    }
  }

  if (compilation.isEmpty()) {
    // well, it wasn't set, but if the artist is VA assume it's a compilation
    if (QStringFromStdString(song->artist()).toLower() == "various artists") {
      song->set_compilation(true);
    }
  } else {
    song->set_compilation(compilation.toInt() == 1);
  }

  if (fileref->audioProperties()) {
    song->set_bitrate(fileref->audioProperties()->bitrate());
    song->set_samplerate(fileref->audioProperties()->sampleRate());
    song->set_length_nanosec(fileref->audioProperties()->length() *
                             kNsecPerSec);
  }

  // Get the filetype if we can
  song->set_type(GuessFileType(fileref.get()));

// Set integer fields to -1 if they're not valid
#define SetDefault(field)   \
  if (song->field() <= 0) { \
    song->set_##field(-1);  \
  }
  SetDefault(track);
  SetDefault(disc);
  SetDefault(bpm);
  SetDefault(year);
  SetDefault(bitrate);
  SetDefault(samplerate);
  SetDefault(lastplayed);
#undef SetDefault
}
void CollectionScanner::popFromQueue() {
    if (stopped) return;

    if (fileQueue.isEmpty()) {
        complete();
        return;
    }

    QFileInfo fileInfo = fileQueue.first();
    // qDebug() << "Processing " << fileInfo.absoluteFilePath();

    // parse metadata with TagLib
    QString filename = fileInfo.absoluteFilePath();
#ifdef Q_OS_WIN
    const wchar_t * encodedName = reinterpret_cast<const wchar_t*>(filename.utf16());
    TagLib::FileRef fileref(encodedName);
#else
    // const char * encodedName = QFile::encodeName(filename).constData();
    TagLib::FileRef fileref((TagLib::FileName)filename.toUtf8());
#endif

    // if taglib cannot parse the file, drop it
    if (fileref.isNull()) {
        // qDebug() << "Taglib cannot parse" << fileInfo.absoluteFilePath();
        fileQueue.removeAll(fileInfo);

        // add to nontracks table
        QString path = fileInfo.absoluteFilePath();
        path.remove(this->rootDirectory.absolutePath() + "/");
        insertOrUpdateNonTrack(path, QDateTime::currentDateTime().toTime_t());

        QTimer::singleShot(0, this, SLOT(popFromQueue()));
        return;
    }

    // Ok this is an interesting file

    // This object will experience an incredible adventure,
    // facing countless perils and finally reaching its final destination
    FileInfo *file = new FileInfo();
    file->setFileInfo(fileInfo);

    // Copy TagLib::FileRef in our Tags class.
    // TagLib::FileRef keeps files open and we would quickly reach the max open files limit
    Tags *tags = new Tags();
    TagLib::Tag *tag = fileref.tag();
    if (tag) {
        tags->title = Tags::toQString(tag->title());
        tags->artist = Tags::toQString(tag->artist());
        tags->album = Tags::toQString(tag->album());
        tags->track = tag->track();
        tags->year = tag->year();
        TagLib::AudioProperties *audioProperties = fileref.audioProperties();
        if (audioProperties)
            tags->length = audioProperties->length();
    }
    file->setTags(tags);

    // get data from the internet
    giveThisFileAnArtist(file);
}
Beispiel #8
0
void nuiMimeMultiPart::Dump(nglOStream* pStream)
{
  nglString varname(_T("MyParam"));
  nglString value(_T("MyValue"));
  
  nglString fileref(_T("MyFile"));
  nglString filename(_T("prout.txt"));
  //  nglString filename(_T(""));
  
  nglString mimetype("plain/text");
  const uint8* data = (const uint8*)"YATTA!";
  uint32 datalen = strlen((const char*)data);
  //////////////////////////////////////
  
  nglString str;

  // prepare start and end boundaries:
  nglString start;
  start.CFormat(_T("--%s"), mBoundary.GetChars());
  
  nglString end;
  end.Add(_T("\n"));
  end.Add(start);
  end.Add(_T("--\n"));
  start.Add(_T("\n"));
  
  
  {
    std::map<nglString, nglString>::const_iterator it = mVariables.begin();
    std::map<nglString, nglString>::const_iterator end = mVariables.end();
    while (it != end)
    {
      pStream->WriteText(start);
      
      str.CFormat(_T("Content-Disposition: form-data; name=\"%s\"\n\n"), it->first.GetChars());
      pStream->WriteText(str);
      pStream->WriteText(it->second);
      pStream->WriteText(_T("\n"));
      
      ++it;
    }
  }

  {  
    for (uint32 i = 0; i < mpFiles.size(); i++)
    {
      pStream->WriteText(start);
      str.CFormat(_T("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\n"), mpFiles[i]->mVarName.GetChars(), mpFiles[i]->mFileName.GetChars());
      pStream->WriteText(str);
      str.CFormat(_T("Content-Transfer-Encoding: %s\n"), mpFiles[i]->mContentTransfertEncoding.GetChars());
      pStream->WriteText(str);
      str.CFormat(_T("Content-Type: %s\n\n"), mpFiles[i]->mType.GetChars());
      pStream->WriteText(str);
      pStream->WriteUInt8(&mpFiles[i]->mContents[0], mpFiles[i]->mContents.size());
    }
  }

  if (mVariables.empty() && mpFiles.empty())
    pStream->WriteText(start);
    
  pStream->WriteText(end);
  
  
  //mem.WriteUInt8((const uint8*)"\0", 1); // Add final 0 for printf
  //nglString enc(mem.GetBufferData(),  mem.GetSize());
  //NGL_OUT(_T("Mime encoded:\n%s\n"), enc.GetChars());
}
Beispiel #9
0
Tags *TagUtils::load(const QString &filename) {
#ifdef Q_OS_WIN
    const wchar_t * encodedName = reinterpret_cast<const wchar_t*>(filename.utf16());
    TagLib::FileStream readOnlyStream(encodedName, true);
#else
    TagLib::FileStream readOnlyStream((TagLib::FileName)filename.toUtf8(), true);
#endif

    TagLib::FileRef fileref(&readOnlyStream);
    if (fileref.isNull()) {
        qDebug() << "Taglib cannot parse" << filename;
        return nullptr;
    }

    Tags *tags = new Tags();
    tags->setFilename(filename);

    TagLib::Tag *tag = fileref.tag();
    if (tag) {
        tags->setTitle(TagUtils::qString(tag->title()));
        tags->setArtistString(TagUtils::qString(tag->artist()));
        tags->setAlbumString(TagUtils::qString(tag->album()));
        tags->setGenre(TagUtils::qString(tag->genre()));
        tags->setTrackNumber(tag->track());
        tags->setYear(tag->year());
        tags->setComment(TagUtils::qString(tag->comment()));
        TagLib::AudioProperties *audioProperties = fileref.audioProperties();
        if (audioProperties)
            tags->setDuration(audioProperties->length());
    }

    /*
    TagLib::PropertyMap map = tag->properties();
    for (TagLib::PropertyMap::ConstIterator i = map.begin(); i != map.end(); ++i) {
        for (TagLib::StringList::ConstIterator j = i->second.begin(); j != i->second.end(); ++j) {
            const QString tagName = TagLibUtils::toQString(i->first);
            qDebug() << "PropertyMap" << tagName << TagLibUtils::toQString(*j);
            if (tagName == QLatin1String("ALBUMARTIST"))
                tags->setAlbumArtist(TagLibUtils::toQString(*j));
            else if (tagName == QLatin1String("DISCNUMBER"))
                tags->setDiskNumber(TagLibUtils::toQString(*j).toInt());
            // else if (tagName == QLatin1String("COMPOSER"))
            // tags->setComposer(toQString(*j));
            else if (tagName == QLatin1String("LYRICS"))
                tags->setLyrics(TagLibUtils::toQString(*j));
            //else if (tagName == QLatin1String("BPM"))
            //    tags->bpm = toQString(*j).toInt();
            // else qDebug() << "Unused tag" << tagName << toQString(*j);
        }
    }
    */

    // Handle file types where TagLibf:::File::tag() returns a "TagUnion"
    TagLib::File *file = fileref.file();

    if (TagLib::MPEG::File *f = dynamic_cast<TagLib::MPEG::File*>(file)) {
        if (TagLib::ID3v2::Tag *t = f->ID3v2Tag()) Id3Utils::load(t, tags);

    } else if (TagLib::TrueAudio::File *f = dynamic_cast<TagLib::TrueAudio::File*>(file)) {
        if (TagLib::ID3v2::Tag *t = f->ID3v2Tag()) Id3Utils::load(t, tags);

    } else if (TagLib::FLAC::File *f = dynamic_cast<TagLib::FLAC::File*>(file)) {
        if (TagLib::Ogg::XiphComment *t = f->xiphComment()) VorbisUtils::load(t, tags);
        else if (TagLib::ID3v2::Tag *t = f->ID3v2Tag()) Id3Utils::load(t, tags);

    } else if (TagLib::APE::File *f = dynamic_cast<TagLib::APE::File*>(file)) {
        if (TagLib::APE::Tag *t = f->APETag()) ApeUtils::load(t, tags);

    } else if (TagLib::MPC::File *f = dynamic_cast<TagLib::MPC::File*>(file)) {
        if (TagLib::APE::Tag *t = f->APETag()) ApeUtils::load(t, tags);

    } else if (TagLib::WavPack::File *f = dynamic_cast<TagLib::WavPack::File*>(file)) {
        if (TagLib::APE::Tag *t = f->APETag()) ApeUtils::load(t, tags);

    } else {

        // Fallback to casting tag() for any other file type
        TagLib::Tag *tag = file->tag();

        if (TagLib::ID3v2::Tag *t = dynamic_cast<TagLib::ID3v2::Tag*>(tag))
            Id3Utils::load(t, tags);

        else if (TagLib::Ogg::XiphComment *t = dynamic_cast<TagLib::Ogg::XiphComment*>(tag))
            VorbisUtils::load(t, tags);

        else if (TagLib::APE::Tag *t = dynamic_cast<TagLib::APE::Tag*>(tag))
            ApeUtils::load(t, tags);

        else if (TagLib::MP4::Tag *t = dynamic_cast<TagLib::MP4::Tag*>(tag))
            Mp4Utils::load(t, tags);

        else if (TagLib::ASF::Tag *t = dynamic_cast<TagLib::ASF::Tag*>(tag))
            AsfUtils::load(t, tags);
    }

    return tags;
}