/*! * \brief Remove the albumart image from the file * * \param filename The music file to remove the albumart * \param albumart The Album Art image to remove * \returns True if successful */ bool MetaIOID3::removeAlbumArt(const QString &filename, const AlbumArtImage *albumart) { if (filename.isEmpty() || !albumart) return false; AttachedPictureFrame::Type type = AttachedPictureFrame::Other; switch (albumart->imageType) { case IT_FRONTCOVER: type = AttachedPictureFrame::FrontCover; break; case IT_BACKCOVER: type = AttachedPictureFrame::BackCover; break; case IT_CD: type = AttachedPictureFrame::Media; break; case IT_INLAY: type = AttachedPictureFrame::LeafletPage; break; default: type = AttachedPictureFrame::Other; break; } TagLib::MPEG::File *mpegfile = OpenFile(filename); if (!mpegfile) return false; TagLib::ID3v2::Tag *tag = mpegfile->ID3v2Tag(); if (!tag) { delete mpegfile; return false; } AttachedPictureFrame *apic = findAPIC(tag, type, QStringToTString(albumart->description)); if (!apic) { delete mpegfile; return false; } tag->removeFrame(apic); mpegfile->save(); delete mpegfile; return true; }
/*! * \brief Writes metadata common to all tag formats to the tag * * \param tag A pointer to the tag * \param metadata Pointer to the metadata */ void MetaIOTagLib::WriteGenericMetadata(Tag *tag, const Metadata *metadata) { if (!tag || !metadata) return; if (!metadata->Artist().isEmpty()) tag->setArtist(QStringToTString(metadata->Artist())); if (!metadata->Title().isEmpty()) tag->setTitle(QStringToTString(metadata->Title())); if (!metadata->Album().isEmpty()) tag->setAlbum(QStringToTString(metadata->Album())); if (metadata->Year() > 999 && metadata->Year() < 10000) // 4 digit year. tag->setYear(metadata->Year()); if (!metadata->Genre().isEmpty()) tag->setGenre(QStringToTString(metadata->Genre())); if (0 != metadata->Track()) tag->setTrack(metadata->Track()); }
/*! * \brief Remove the albumart image from the file * * \param filename The music file to remove the albumart * \param albumart The Album Art image to remove * \returns True if successful */ bool MetaIOID3::removeAlbumArt(const QString &filename, const AlbumArtImage *albumart) { if (filename.isEmpty() || !albumart) return false; AttachedPictureFrame::Type type = AttachedPictureFrame::Other; switch (albumart->m_imageType) { case IT_FRONTCOVER: type = AttachedPictureFrame::FrontCover; break; case IT_BACKCOVER: type = AttachedPictureFrame::BackCover; break; case IT_CD: type = AttachedPictureFrame::Media; break; case IT_INLAY: type = AttachedPictureFrame::LeafletPage; break; case IT_ARTIST: type = AttachedPictureFrame::Artist; break; default: type = AttachedPictureFrame::Other; break; } if (!OpenFile(filename, true)) return false; TagLib::ID3v2::Tag *tag = GetID3v2Tag(); if (!tag) return false; AttachedPictureFrame *apic = findAPIC(tag, type, QStringToTString(albumart->m_description)); if (!apic) return false; tag->removeFrame(apic); if (!SaveFile()) return false; return true; }
/*! * \copydoc MetaIO::write() */ bool MetaIOFLACVorbis::write(Metadata* mdata) { if (!mdata) return false; TagLib::FLAC::File *flacfile = OpenFile(mdata->Filename()); if (!flacfile) return false; TagLib::Ogg::XiphComment *tag = flacfile->xiphComment(); if (!tag) { delete flacfile; return false; } WriteGenericMetadata(tag, mdata); // Compilation if (mdata->Compilation()) { tag->addField("MUSICBRAINZ_ALBUMARTISTID", MYTH_MUSICBRAINZ_ALBUMARTIST_UUID, true); tag->addField("COMPILATION_ARTIST", QStringToTString(mdata->CompilationArtist()), true); } else { // Don't remove the musicbrainz field unless it indicated a compilation if (tag->contains("MUSICBRAINZ_ALBUMARTISTID") && (tag->fieldListMap()["MUSICBRAINZ_ALBUMARTISTID"].toString() == MYTH_MUSICBRAINZ_ALBUMARTIST_UUID)) { tag->removeField("MUSICBRAINZ_ALBUMARTISTID"); } tag->removeField("COMPILATION_ARTIST"); } bool result = flacfile->save(); if (flacfile) delete flacfile; return (result); }
bool MetaIOID3::writeLastPlay(TagLib::ID3v2::Tag *tag, QDateTime lastPlay) { if (!tag) return false; // MythTV Specific Rating Tag UserTextIdentificationFrame *txxx = find(tag, "MythTVLastPlayed"); if (!txxx) { txxx = new UserTextIdentificationFrame(); tag->addFrame(txxx); txxx->setDescription("MythTVLastPlayed"); } lastPlay.setTimeSpec(Qt::UTC); txxx->setText(QStringToTString(lastPlay.toString(Qt::ISODate))); return true; }
bool MetaIOID3::changeImageType(const QString &filename, const AlbumArtImage* albumart, ImageType newType) { if (!albumart) return false; if (albumart->m_imageType == newType) return true; AttachedPictureFrame::Type type = AttachedPictureFrame::Other; switch (albumart->m_imageType) { case IT_FRONTCOVER: type = AttachedPictureFrame::FrontCover; break; case IT_BACKCOVER: type = AttachedPictureFrame::BackCover; break; case IT_CD: type = AttachedPictureFrame::Media; break; case IT_INLAY: type = AttachedPictureFrame::LeafletPage; break; case IT_ARTIST: type = AttachedPictureFrame::Artist; break; default: type = AttachedPictureFrame::Other; break; } if (!OpenFile(filename, true)) return false; TagLib::ID3v2::Tag *tag = GetID3v2Tag(); if (!tag) return false; AttachedPictureFrame *apic = findAPIC(tag, type, QStringToTString(albumart->m_description)); if (!apic) return false; // set the new image type switch (newType) { case IT_FRONTCOVER: apic->setType(AttachedPictureFrame::FrontCover); break; case IT_BACKCOVER: apic->setType(AttachedPictureFrame::BackCover); break; case IT_CD: apic->setType(AttachedPictureFrame::Media); break; case IT_INLAY: apic->setType(AttachedPictureFrame::LeafletPage); break; case IT_ARTIST: apic->setType(AttachedPictureFrame::Artist); break; default: apic->setType(AttachedPictureFrame::Other); break; } if (!SaveFile()) return false; return true; }
/*! * \brief Write the albumart image to the file * * \param filename The music file to add the albumart * \param albumart The Album Art image to write * \returns True if successful * * \note We always save the image in JPEG format */ bool MetaIOID3::writeAlbumArt(const QString &filename, const AlbumArtImage *albumart) { if (filename.isEmpty() || !albumart) return false; // load the image into a QByteArray QImage image(albumart->m_filename); QByteArray imageData; QBuffer buffer(&imageData); buffer.open(QIODevice::WriteOnly); image.save(&buffer, "JPEG"); AttachedPictureFrame::Type type = AttachedPictureFrame::Other; switch (albumart->m_imageType) { case IT_FRONTCOVER: type = AttachedPictureFrame::FrontCover; break; case IT_BACKCOVER: type = AttachedPictureFrame::BackCover; break; case IT_CD: type = AttachedPictureFrame::Media; break; case IT_INLAY: type = AttachedPictureFrame::LeafletPage; break; case IT_ARTIST: type = AttachedPictureFrame::Artist; break; default: type = AttachedPictureFrame::Other; break; } if (!OpenFile(filename, true)) return false; TagLib::ID3v2::Tag *tag = GetID3v2Tag(); if (!tag) return false; AttachedPictureFrame *apic = findAPIC(tag, type, QStringToTString(albumart->m_description)); if (!apic) { apic = new AttachedPictureFrame(); tag->addFrame(apic); apic->setType(type); } QString mimetype = "image/jpeg"; TagLib::ByteVector bytevector; bytevector.setData(imageData.data(), imageData.size()); apic->setMimeType(QStringToTString(mimetype)); apic->setPicture(bytevector); apic->setDescription(QStringToTString(albumart->m_description)); if (!SaveFile()) return false; return true; }
/*! * \copydoc MetaIO::write() */ bool MetaIOID3::write(const QString &filename, MusicMetadata* mdata) { if (filename.isEmpty()) return false; if (!OpenFile(filename, true)) return false; TagLib::ID3v2::Tag *tag = GetID3v2Tag(); if (!tag) return false; WriteGenericMetadata(tag, mdata); // MythTV rating and playcount, stored in POPM frame writeRating(tag, mdata->Rating()); writePlayCount(tag, mdata->PlayCount()); writeLastPlay(tag, mdata->LastPlay()); // MusicBrainz ID UserTextIdentificationFrame *musicbrainz = nullptr; musicbrainz = find(tag, "MusicBrainz Album Artist Id"); if (mdata->Compilation()) { if (!musicbrainz) { musicbrainz = new UserTextIdentificationFrame(TagLib::String::UTF8); tag->addFrame(musicbrainz); musicbrainz->setDescription("MusicBrainz Album Artist Id"); } musicbrainz->setText(MYTH_MUSICBRAINZ_ALBUMARTIST_UUID); } else if (musicbrainz) tag->removeFrame(musicbrainz); // Compilation Artist Frame (TPE4/2) if (!mdata->CompilationArtist().isEmpty()) { TextIdentificationFrame *tpe4frame = nullptr; TagLib::ID3v2::FrameList tpelist = tag->frameListMap()["TPE4"]; if (!tpelist.isEmpty()) tpe4frame = (TextIdentificationFrame *)tpelist.front(); if (!tpe4frame) { tpe4frame = new TextIdentificationFrame(TagLib::ByteVector("TPE4"), TagLib::String::UTF8); tag->addFrame(tpe4frame); } tpe4frame->setText(QStringToTString(mdata->CompilationArtist())); TextIdentificationFrame *tpe2frame = nullptr; tpelist = tag->frameListMap()["TPE2"]; if (!tpelist.isEmpty()) tpe2frame = (TextIdentificationFrame *)tpelist.front(); if (!tpe2frame) { tpe2frame = new TextIdentificationFrame(TagLib::ByteVector("TPE2"), TagLib::String::UTF8); tag->addFrame(tpe2frame); } tpe2frame->setText(QStringToTString(mdata->CompilationArtist())); } if (!SaveFile()) return false; return true; }
/*! * \copydoc MetaIO::write() */ bool MetaIOID3::write(Metadata* mdata) { TagLib::MPEG::File *mpegfile = OpenFile(mdata->Filename()); if (!mpegfile) return false; TagLib::ID3v2::Tag *tag = mpegfile->ID3v2Tag(); if (!tag) { delete mpegfile; return false; } WriteGenericMetadata(tag, mdata); // MythTV rating and playcount, stored in POPM frame writeRating(tag, mdata->Rating()); writePlayCount(tag, mdata->PlayCount()); // MusicBrainz ID UserTextIdentificationFrame *musicbrainz = NULL; musicbrainz = find(tag, "MusicBrainz Album Artist Id"); if (mdata->Compilation()) { if (!musicbrainz) { musicbrainz = new UserTextIdentificationFrame(TagLib::String::UTF8); tag->addFrame(musicbrainz); musicbrainz->setDescription("MusicBrainz Album Artist Id"); } musicbrainz->setText(MYTH_MUSICBRAINZ_ALBUMARTIST_UUID); } else if (musicbrainz) tag->removeFrame(musicbrainz); // Compilation Artist Frame (TPE4/2) if (!mdata->CompilationArtist().isEmpty()) { TextIdentificationFrame *tpe4frame = NULL; TagLib::ID3v2::FrameList tpelist = tag->frameListMap()["TPE4"]; if (!tpelist.isEmpty()) tpe4frame = (TextIdentificationFrame *)tpelist.front(); if (!tpe4frame) { tpe4frame = new TextIdentificationFrame(TagLib::ByteVector("TPE4"), TagLib::String::UTF8); tag->addFrame(tpe4frame); } tpe4frame->setText(QStringToTString(mdata->CompilationArtist())); TextIdentificationFrame *tpe2frame = NULL; tpelist = tag->frameListMap()["TPE2"]; if (!tpelist.isEmpty()) tpe2frame = (TextIdentificationFrame *)tpelist.front(); if (!tpe2frame) { tpe2frame = new TextIdentificationFrame(TagLib::ByteVector("TPE2"), TagLib::String::UTF8); tag->addFrame(tpe2frame); } tpe2frame->setText(QStringToTString(mdata->CompilationArtist())); } bool result = mpegfile->save(); delete mpegfile; return result; }
TagLib::String operator[](const char *key) const { return QStringToTString(m_info["Comment"][key].value().toString()); }
void MetaDetector::updateMediaFileTagCodec(MediaMeta *meta, const QByteArray &codecName, bool forceEncode) { Q_ASSERT(meta != nullptr); if (meta->localPath.isEmpty()) { qCritical() << "meta localPath is empty:" << meta->title << meta->hash; return ; } QByteArray detectByte; QByteArray detectCodec = codecName; auto mediaPath = QStringToTString(meta->localPath); #ifdef _WIN32 TagLib::FileRef f(meta->localPath.toStdWString().c_str()); #else TagLib::FileRef f(meta->localPath.toStdString().c_str()); #endif TagLib::Tag *tag = f.tag(); if (!f.file()) { qCritical() << "TagLib: open file failed:" << meta->localPath << f.file(); } if (!tag) { qWarning() << "TagLib: no tag for media file" << meta->localPath; return; } bool encode = true; encode &= tag->title().isNull() ? true : tag->title().isLatin1(); encode &= tag->artist().isNull() ? true : tag->artist().isLatin1(); encode &= tag->album().isNull() ? true : tag->album().isLatin1(); if (forceEncode) { encode = true; } if (encode) { if (detectCodec.isEmpty()) { detectByte += tag->title().toCString(); detectByte += tag->artist().toCString(); detectByte += tag->album().toCString(); detectCodec = detectEncodings(detectByte).value(0); // qDebug() << "detect codec" << detectEncodings(detectByte); } // qDebug() << "convert to" << detectCodec; // QTextCodec *codec = QTextCodec::codecForName(detectCodec); // meta->album = codec->toUnicode(tag->album().to8Bit().c_str()); // meta->artist = codec->toUnicode(tag->artist().to8Bit().c_str()); // meta->title = codec->toUnicode(tag->title().to8Bit().c_str()); //#ifndef true // qDebug() << "convert to" << detectCodec << QTextCodec::availableCodecs(); const size_t buflen = 1024 * 10; char buf[buflen]; UErrorCode err = U_ZERO_ERROR; int32_t len = ucnv_convert("utf-8", detectCodec, buf, buflen, tag->title().toCString(), -1, &err); meta->title = QString::fromUtf8(buf); // qDebug() << len << QString::fromUtf8(buf) << buf << u_errorName(err); err = U_ZERO_ERROR; len = ucnv_convert("utf-8", detectCodec, buf, buflen, tag->artist().toCString(), -1, &err); meta->artist = QString::fromUtf8(buf); // qDebug() << len << QString::fromUtf8(buf) << buf << u_errorName(err); err = U_ZERO_ERROR; len = ucnv_convert("utf-8", detectCodec, buf, buflen, tag->album().toCString(), -1, &err); meta->album = QString::fromUtf8(buf); // qDebug() << len << QString::fromUtf8(buf) << buf << u_errorName(err); Q_UNUSED(len); //#endif } else { meta->album = TStringToQString(tag->album()); meta->artist = TStringToQString(tag->artist()); meta->title = TStringToQString(tag->title()); } if (meta->title.isEmpty()) { QFileInfo localFi(meta->localPath); meta->title = localFi.completeBaseName(); } }