Rewrite album cover loader
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/* This file is part of Strawberry.
|
||||
Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
|
||||
Strawberry is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -30,8 +30,6 @@
|
||||
#include "core/logging.h"
|
||||
#include "tagreaderbase.h"
|
||||
|
||||
const std::string TagReaderBase::kEmbeddedCover = "(embedded)";
|
||||
|
||||
TagReaderBase::TagReaderBase() = default;
|
||||
TagReaderBase::~TagReaderBase() = default;
|
||||
|
||||
@@ -59,10 +57,10 @@ int TagReaderBase::ConvertToPOPMRating(const float rating) {
|
||||
|
||||
}
|
||||
|
||||
QByteArray TagReaderBase::LoadCoverDataFromRequest(const spb::tagreader::SaveFileRequest &request) {
|
||||
TagReaderBase::Cover TagReaderBase::LoadCoverFromRequest(const spb::tagreader::SaveFileRequest &request) {
|
||||
|
||||
if (!request.has_save_cover() || !request.save_cover()) {
|
||||
return QByteArray();
|
||||
return Cover();
|
||||
}
|
||||
|
||||
const QString song_filename = QString::fromUtf8(request.filename().data(), request.filename().size());
|
||||
@@ -74,16 +72,16 @@ QByteArray TagReaderBase::LoadCoverDataFromRequest(const spb::tagreader::SaveFil
|
||||
if (request.has_cover_data()) {
|
||||
cover_data = QByteArray(request.cover_data().data(), request.cover_data().size());
|
||||
}
|
||||
bool cover_is_jpeg = false;
|
||||
if (request.has_cover_is_jpeg()) {
|
||||
cover_is_jpeg = request.cover_is_jpeg();
|
||||
QString cover_mime_type;
|
||||
if (request.has_cover_mime_type()) {
|
||||
cover_mime_type = QByteArray(request.cover_mime_type().data(), request.cover_mime_type().size());
|
||||
}
|
||||
|
||||
return LoadCoverDataFromRequest(song_filename, cover_filename, cover_data, cover_is_jpeg);
|
||||
return LoadCoverFromRequest(song_filename, cover_filename, cover_data, cover_mime_type);
|
||||
|
||||
}
|
||||
|
||||
QByteArray TagReaderBase::LoadCoverDataFromRequest(const spb::tagreader::SaveEmbeddedArtRequest &request) {
|
||||
TagReaderBase::Cover TagReaderBase::LoadCoverFromRequest(const spb::tagreader::SaveEmbeddedArtRequest &request) {
|
||||
|
||||
const QString song_filename = QString::fromUtf8(request.filename().data(), request.filename().size());
|
||||
QString cover_filename;
|
||||
@@ -94,37 +92,39 @@ QByteArray TagReaderBase::LoadCoverDataFromRequest(const spb::tagreader::SaveEmb
|
||||
if (request.has_cover_data()) {
|
||||
cover_data = QByteArray(request.cover_data().data(), request.cover_data().size());
|
||||
}
|
||||
bool cover_is_jpeg = false;
|
||||
if (request.has_cover_is_jpeg()) {
|
||||
cover_is_jpeg = request.cover_is_jpeg();
|
||||
QString cover_mime_type;
|
||||
if (request.has_cover_mime_type()) {
|
||||
cover_mime_type = QByteArray(request.cover_mime_type().data(), request.cover_mime_type().size());
|
||||
}
|
||||
|
||||
return LoadCoverDataFromRequest(song_filename, cover_filename, cover_data, cover_is_jpeg);
|
||||
return LoadCoverFromRequest(song_filename, cover_filename, cover_data, cover_mime_type);
|
||||
|
||||
}
|
||||
|
||||
QByteArray TagReaderBase::LoadCoverDataFromRequest(const QString &song_filename, const QString &cover_filename, QByteArray cover_data, const bool cover_is_jpeg) {
|
||||
|
||||
if (!cover_data.isEmpty() && cover_is_jpeg) {
|
||||
qLog(Debug) << "Using cover from JPEG data for" << song_filename;
|
||||
return cover_data;
|
||||
}
|
||||
TagReaderBase::Cover TagReaderBase::LoadCoverFromRequest(const QString &song_filename, const QString &cover_filename, QByteArray cover_data, QString cover_mime_type) {
|
||||
|
||||
if (cover_data.isEmpty() && !cover_filename.isEmpty()) {
|
||||
qLog(Debug) << "Loading cover from" << cover_filename << "for" << song_filename;
|
||||
QFile file(cover_filename);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qLog(Error) << "Failed to open file" << cover_filename << "for reading:" << file.errorString();
|
||||
return QByteArray();
|
||||
return Cover();
|
||||
}
|
||||
cover_data = file.readAll();
|
||||
file.close();
|
||||
}
|
||||
|
||||
if (!cover_data.isEmpty()) {
|
||||
if (QMimeDatabase().mimeTypeForData(cover_data).name() == "image/jpeg") {
|
||||
if (cover_mime_type.isEmpty()) {
|
||||
cover_mime_type = QMimeDatabase().mimeTypeForData(cover_data).name();
|
||||
}
|
||||
if (cover_mime_type == "image/jpeg") {
|
||||
qLog(Debug) << "Using cover from JPEG data for" << song_filename;
|
||||
return cover_data;
|
||||
return Cover(cover_data, cover_mime_type);
|
||||
}
|
||||
if (cover_mime_type == "image/png") {
|
||||
qLog(Debug) << "Using cover from PNG data for" << song_filename;
|
||||
return Cover(cover_data, cover_mime_type);
|
||||
}
|
||||
// Convert image to JPEG.
|
||||
qLog(Debug) << "Converting cover to JPEG data for" << song_filename;
|
||||
@@ -135,9 +135,9 @@ QByteArray TagReaderBase::LoadCoverDataFromRequest(const QString &song_filename,
|
||||
cover_image.save(&buffer, "JPEG");
|
||||
buffer.close();
|
||||
}
|
||||
return cover_data;
|
||||
return Cover(cover_data, "image/jpeg");
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
return Cover();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This file is part of Strawberry.
|
||||
Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
|
||||
Strawberry is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -36,6 +36,14 @@ class TagReaderBase {
|
||||
explicit TagReaderBase();
|
||||
~TagReaderBase();
|
||||
|
||||
class Cover {
|
||||
public:
|
||||
explicit Cover(const QByteArray &_data = QByteArray(), const QString &_mime_type = QString()) : data(_data), mime_type(_mime_type) {}
|
||||
QByteArray data;
|
||||
QString mime_type;
|
||||
QString error;
|
||||
};
|
||||
|
||||
virtual bool IsMediaFile(const QString &filename) const = 0;
|
||||
|
||||
virtual bool ReadFile(const QString &filename, spb::tagreader::SongMetadata *song) const = 0;
|
||||
@@ -50,14 +58,11 @@ class TagReaderBase {
|
||||
static float ConvertPOPMRating(const int POPM_rating);
|
||||
static int ConvertToPOPMRating(const float rating);
|
||||
|
||||
static QByteArray LoadCoverDataFromRequest(const spb::tagreader::SaveFileRequest &request);
|
||||
static QByteArray LoadCoverDataFromRequest(const spb::tagreader::SaveEmbeddedArtRequest &request);
|
||||
static Cover LoadCoverFromRequest(const spb::tagreader::SaveFileRequest &request);
|
||||
static Cover LoadCoverFromRequest(const spb::tagreader::SaveEmbeddedArtRequest &request);
|
||||
|
||||
private:
|
||||
static QByteArray LoadCoverDataFromRequest(const QString &song_filename, const QString &cover_filename, QByteArray cover_data, const bool cover_is_jpeg);
|
||||
|
||||
protected:
|
||||
static const std::string kEmbeddedCover;
|
||||
static Cover LoadCoverFromRequest(const QString &song_filename, const QString &cover_filename, QByteArray cover_data, QString cover_mime_type);
|
||||
|
||||
Q_DISABLE_COPY(TagReaderBase)
|
||||
};
|
||||
|
||||
@@ -69,7 +69,7 @@ message SongMetadata {
|
||||
optional int64 lastplayed = 29;
|
||||
optional int64 lastseen = 30;
|
||||
|
||||
optional string art_automatic = 31;
|
||||
optional bool art_embedded = 31;
|
||||
|
||||
optional float rating = 32;
|
||||
|
||||
@@ -97,6 +97,7 @@ message IsMediaFileRequest {
|
||||
|
||||
message IsMediaFileResponse {
|
||||
optional bool success = 1;
|
||||
optional string error = 2;
|
||||
}
|
||||
|
||||
message ReadFileRequest {
|
||||
@@ -105,6 +106,7 @@ message ReadFileRequest {
|
||||
|
||||
message ReadFileResponse {
|
||||
optional SongMetadata metadata = 1;
|
||||
optional string error = 2;
|
||||
}
|
||||
|
||||
message SaveFileRequest {
|
||||
@@ -116,11 +118,12 @@ message SaveFileRequest {
|
||||
optional SongMetadata metadata = 6;
|
||||
optional string cover_filename = 7;
|
||||
optional bytes cover_data = 8;
|
||||
optional bool cover_is_jpeg = 9;
|
||||
optional string cover_mime_type = 9;
|
||||
}
|
||||
|
||||
message SaveFileResponse {
|
||||
optional bool success = 1;
|
||||
optional string error = 2;
|
||||
}
|
||||
|
||||
message LoadEmbeddedArtRequest {
|
||||
@@ -129,17 +132,19 @@ message LoadEmbeddedArtRequest {
|
||||
|
||||
message LoadEmbeddedArtResponse {
|
||||
optional bytes data = 1;
|
||||
optional string error = 2;
|
||||
}
|
||||
|
||||
message SaveEmbeddedArtRequest {
|
||||
optional string filename = 1;
|
||||
optional string cover_filename = 2;
|
||||
optional bytes cover_data = 3;
|
||||
optional bool cover_is_jpeg = 4;
|
||||
optional string cover_mime_type = 4;
|
||||
}
|
||||
|
||||
message SaveEmbeddedArtResponse {
|
||||
optional bool success = 1;
|
||||
optional string error = 2;
|
||||
}
|
||||
|
||||
message SaveSongPlaycountToFileRequest {
|
||||
@@ -149,6 +154,7 @@ message SaveSongPlaycountToFileRequest {
|
||||
|
||||
message SaveSongPlaycountToFileResponse {
|
||||
optional bool success = 1;
|
||||
optional string error = 2;
|
||||
}
|
||||
|
||||
message SaveSongRatingToFileRequest {
|
||||
@@ -158,6 +164,7 @@ message SaveSongRatingToFileRequest {
|
||||
|
||||
message SaveSongRatingToFileResponse {
|
||||
optional bool success = 1;
|
||||
optional string error = 2;
|
||||
}
|
||||
|
||||
message Message {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* This file is part of Strawberry.
|
||||
Copyright 2013, David Sansome <me@davidsansome.com>
|
||||
Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
|
||||
Strawberry is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -287,7 +287,7 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
||||
if (!pictures.isEmpty()) {
|
||||
for (TagLib::FLAC::Picture *picture : pictures) {
|
||||
if (picture->type() == TagLib::FLAC::Picture::FrontCover && picture->data().size() > 0) {
|
||||
song->set_art_automatic(kEmbeddedCover);
|
||||
song->set_art_embedded(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -302,7 +302,7 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
||||
if (!pictures.isEmpty()) {
|
||||
for (TagLib::FLAC::Picture *picture : pictures) {
|
||||
if (picture->type() == TagLib::FLAC::Picture::FrontCover && picture->data().size() > 0) {
|
||||
song->set_art_automatic(kEmbeddedCover);
|
||||
song->set_art_embedded(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -362,7 +362,7 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
||||
TStringToStdString(map["SYLT"].front()->toString(), song->mutable_lyrics());
|
||||
}
|
||||
|
||||
if (map.contains("APIC")) song->set_art_automatic(kEmbeddedCover);
|
||||
if (map.contains("APIC")) song->set_art_embedded(true);
|
||||
|
||||
// Find a suitable comment tag. For now we ignore iTunNORM comments.
|
||||
for (uint i = 0; i < map["COMM"].size(); ++i) {
|
||||
@@ -469,7 +469,7 @@ bool TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
|
||||
|
||||
// Find album cover art
|
||||
if (mp4_tag->item("covr").isValid()) {
|
||||
song->set_art_automatic(kEmbeddedCover);
|
||||
song->set_art_embedded(true);
|
||||
}
|
||||
|
||||
if (mp4_tag->item("disk").isValid()) {
|
||||
@@ -715,8 +715,8 @@ void TagReaderTagLib::ParseOggTag(const TagLib::Ogg::FieldListMap &map, QString
|
||||
|
||||
if (map.contains("DISCNUMBER")) *disc = TStringToQString(map["DISCNUMBER"].front()).trimmed();
|
||||
if (map.contains("COMPILATION")) *compilation = TStringToQString(map["COMPILATION"].front()).trimmed();
|
||||
if (map.contains("COVERART")) song->set_art_automatic(kEmbeddedCover);
|
||||
if (map.contains("METADATA_BLOCK_PICTURE")) song->set_art_automatic(kEmbeddedCover);
|
||||
if (map.contains("COVERART")) song->set_art_embedded(true);
|
||||
if (map.contains("METADATA_BLOCK_PICTURE")) song->set_art_embedded(true);
|
||||
|
||||
if (map.contains("FMPS_PLAYCOUNT") && song->playcount() <= 0) {
|
||||
const int playcount = TStringToQString(map["FMPS_PLAYCOUNT"].front()).trimmed().toInt();
|
||||
@@ -753,7 +753,7 @@ void TagReaderTagLib::ParseAPETag(const TagLib::APE::ItemListMap &map, QString *
|
||||
}
|
||||
}
|
||||
|
||||
if (map.find("COVER ART (FRONT)") != map.end()) song->set_art_automatic(kEmbeddedCover);
|
||||
if (map.find("COVER ART (FRONT)") != map.end()) song->set_art_embedded(true);
|
||||
if (map.contains("COMPILATION")) {
|
||||
*compilation = TStringToQString(TagLib::String::number(map["COMPILATION"].toString().toInt()));
|
||||
}
|
||||
@@ -853,7 +853,7 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
||||
|
||||
qLog(Debug) << "Saving" << save_tags_options.join(", ") << "to" << filename;
|
||||
|
||||
const QByteArray cover_data = LoadCoverDataFromRequest(request);
|
||||
const Cover cover = LoadCoverFromRequest(request);
|
||||
|
||||
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
||||
if (!fileref || fileref->isNull()) return false;
|
||||
@@ -883,7 +883,7 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
||||
SetRating(xiph_comment, song);
|
||||
}
|
||||
if (save_cover) {
|
||||
SetEmbeddedArt(file_flac, xiph_comment, cover_data);
|
||||
SetEmbeddedArt(file_flac, xiph_comment, cover.data, cover.mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -949,7 +949,7 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
||||
SetRating(tag, song);
|
||||
}
|
||||
if (save_cover) {
|
||||
SetEmbeddedArt(file_mpeg, tag, cover_data);
|
||||
SetEmbeddedArt(file_mpeg, tag, cover.data, cover.mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -971,7 +971,7 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
||||
SetRating(tag, song);
|
||||
}
|
||||
if (save_cover) {
|
||||
SetEmbeddedArt(file_mp4, tag, cover_data);
|
||||
SetEmbeddedArt(file_mp4, tag, cover.data, cover.mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -989,20 +989,20 @@ bool TagReaderTagLib::SaveFile(const spb::tagreader::SaveFileRequest &request) c
|
||||
SetRating(xiph_comment, song);
|
||||
}
|
||||
if (save_cover) {
|
||||
SetEmbeddedArt(xiph_comment, cover_data);
|
||||
SetEmbeddedArt(xiph_comment, cover.data, cover.mime_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool result = fileref->save();
|
||||
const bool success = fileref->save();
|
||||
#ifdef Q_OS_LINUX
|
||||
if (result) {
|
||||
if (success) {
|
||||
// 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 result;
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
@@ -1238,7 +1238,7 @@ QByteArray TagReaderTagLib::LoadEmbeddedAPEArt(const TagLib::APE::ItemListMap &m
|
||||
|
||||
}
|
||||
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::FLAC::File *flac_file, TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data) const {
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::FLAC::File *flac_file, TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const {
|
||||
|
||||
(void)xiph_comment;
|
||||
|
||||
@@ -1247,28 +1247,28 @@ void TagReaderTagLib::SetEmbeddedArt(TagLib::FLAC::File *flac_file, TagLib::Ogg:
|
||||
if (!data.isEmpty()) {
|
||||
TagLib::FLAC::Picture *picture = new TagLib::FLAC::Picture();
|
||||
picture->setType(TagLib::FLAC::Picture::FrontCover);
|
||||
picture->setMimeType("image/jpeg");
|
||||
picture->setMimeType(QStringToTString(mime_type));
|
||||
picture->setData(TagLib::ByteVector(data.constData(), data.size()));
|
||||
flac_file->addPicture(picture);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data) const {
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const {
|
||||
|
||||
xiph_comment->removeAllPictures();
|
||||
|
||||
if (!data.isEmpty()) {
|
||||
TagLib::FLAC::Picture *picture = new TagLib::FLAC::Picture();
|
||||
picture->setType(TagLib::FLAC::Picture::FrontCover);
|
||||
picture->setMimeType("image/jpeg");
|
||||
picture->setMimeType(QStringToTString(mime_type));
|
||||
picture->setData(TagLib::ByteVector(data.constData(), data.size()));
|
||||
xiph_comment->addPicture(picture);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::MPEG::File *file_mp3, TagLib::ID3v2::Tag *tag, const QByteArray &data) const {
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::MPEG::File *file_mp3, TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const {
|
||||
|
||||
(void)file_mp3;
|
||||
|
||||
@@ -1284,14 +1284,14 @@ void TagReaderTagLib::SetEmbeddedArt(TagLib::MPEG::File *file_mp3, TagLib::ID3v2
|
||||
TagLib::ID3v2::AttachedPictureFrame *frontcover = nullptr;
|
||||
frontcover = new TagLib::ID3v2::AttachedPictureFrame("APIC");
|
||||
frontcover->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
|
||||
frontcover->setMimeType("image/jpeg");
|
||||
frontcover->setMimeType(QStringToTString(mime_type));
|
||||
frontcover->setPicture(TagLib::ByteVector(data.constData(), data.size()));
|
||||
tag->addFrame(frontcover);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::MP4::File *aac_file, TagLib::MP4::Tag *tag, const QByteArray &data) const {
|
||||
void TagReaderTagLib::SetEmbeddedArt(TagLib::MP4::File *aac_file, TagLib::MP4::Tag *tag, const QByteArray &data, const QString &mime_type) const {
|
||||
|
||||
(void)aac_file;
|
||||
|
||||
@@ -1300,7 +1300,17 @@ void TagReaderTagLib::SetEmbeddedArt(TagLib::MP4::File *aac_file, TagLib::MP4::T
|
||||
if (tag->contains("covr")) tag->removeItem("covr");
|
||||
}
|
||||
else {
|
||||
covers.append(TagLib::MP4::CoverArt(TagLib::MP4::CoverArt::JPEG, TagLib::ByteVector(data.constData(), data.size())));
|
||||
TagLib::MP4::CoverArt::Format cover_format;
|
||||
if (mime_type == "image/jpeg") {
|
||||
cover_format = TagLib::MP4::CoverArt::Format::JPEG;
|
||||
}
|
||||
else if (mime_type == "image/png") {
|
||||
cover_format = TagLib::MP4::CoverArt::Format::PNG;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
covers.append(TagLib::MP4::CoverArt(cover_format, TagLib::ByteVector(data.constData(), data.size())));
|
||||
tag->setItem("covr", covers);
|
||||
}
|
||||
|
||||
@@ -1314,7 +1324,7 @@ bool TagReaderTagLib::SaveEmbeddedArt(const spb::tagreader::SaveEmbeddedArtReque
|
||||
|
||||
qLog(Debug) << "Saving art to" << filename;
|
||||
|
||||
const QByteArray cover_data = LoadCoverDataFromRequest(request);
|
||||
const Cover cover = LoadCoverFromRequest(request);
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
TagLib::FileRef fileref(filename.toStdWString().c_str());
|
||||
@@ -1328,40 +1338,40 @@ bool TagReaderTagLib::SaveEmbeddedArt(const spb::tagreader::SaveEmbeddedArtReque
|
||||
if (TagLib::FLAC::File *flac_file = dynamic_cast<TagLib::FLAC::File*>(fileref.file())) {
|
||||
TagLib::Ogg::XiphComment *xiph_comment = flac_file->xiphComment(true);
|
||||
if (!xiph_comment) return false;
|
||||
SetEmbeddedArt(flac_file, xiph_comment, cover_data);
|
||||
SetEmbeddedArt(flac_file, xiph_comment, cover.data, cover.mime_type);
|
||||
}
|
||||
|
||||
// Ogg Vorbis / Opus / Speex
|
||||
else if (TagLib::Ogg::XiphComment *xiph_comment = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref.file()->tag())) {
|
||||
SetEmbeddedArt(xiph_comment, cover_data);
|
||||
SetEmbeddedArt(xiph_comment, cover.data, cover.mime_type);
|
||||
}
|
||||
|
||||
// MP3
|
||||
else if (TagLib::MPEG::File *file_mp3 = dynamic_cast<TagLib::MPEG::File*>(fileref.file())) {
|
||||
TagLib::ID3v2::Tag *tag = file_mp3->ID3v2Tag();
|
||||
if (!tag) return false;
|
||||
SetEmbeddedArt(file_mp3, tag, cover_data);
|
||||
SetEmbeddedArt(file_mp3, tag, cover.data, cover.mime_type);
|
||||
}
|
||||
|
||||
// MP4/AAC
|
||||
else if (TagLib::MP4::File *aac_file = dynamic_cast<TagLib::MP4::File*>(fileref.file())) {
|
||||
TagLib::MP4::Tag *tag = aac_file->tag();
|
||||
if (!tag) return false;
|
||||
SetEmbeddedArt(aac_file, tag, cover_data);
|
||||
SetEmbeddedArt(aac_file, tag, cover.data, cover.mime_type);
|
||||
}
|
||||
|
||||
// Not supported.
|
||||
else return false;
|
||||
|
||||
const bool result = fileref.file()->save();
|
||||
const bool success = fileref.file()->save();
|
||||
#ifdef Q_OS_LINUX
|
||||
if (result) {
|
||||
if (success) {
|
||||
// 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 result;
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
@@ -1490,15 +1500,15 @@ bool TagReaderTagLib::SaveSongPlaycountToFile(const QString &filename, const spb
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ret = fileref->save();
|
||||
bool success = fileref->save();
|
||||
#ifdef Q_OS_LINUX
|
||||
if (ret) {
|
||||
if (success) {
|
||||
// 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;
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
@@ -1602,14 +1612,14 @@ bool TagReaderTagLib::SaveSongRatingToFile(const QString &filename, const spb::t
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ret = fileref->save();
|
||||
const bool success = fileref->save();
|
||||
#ifdef Q_OS_LINUX
|
||||
if (ret) {
|
||||
if (success) {
|
||||
// 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;
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* This file is part of Strawberry.
|
||||
Copyright 2013, David Sansome <me@davidsansome.com>
|
||||
Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
Copyright 2018-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
|
||||
Strawberry is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -96,10 +96,10 @@ class TagReaderTagLib : public TagReaderBase {
|
||||
void SetRating(TagLib::MP4::Tag *tag, const spb::tagreader::SongMetadata &song) const;
|
||||
void SetRating(TagLib::ASF::Tag *tag, const spb::tagreader::SongMetadata &song) const;
|
||||
|
||||
void SetEmbeddedArt(TagLib::FLAC::File *flac_file, TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data) const;
|
||||
void SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data) const;
|
||||
void SetEmbeddedArt(TagLib::MPEG::File *file_mp3, TagLib::ID3v2::Tag *tag, const QByteArray &data) const;
|
||||
void SetEmbeddedArt(TagLib::MP4::File *aac_file, TagLib::MP4::Tag *tag, const QByteArray &data) const;
|
||||
void SetEmbeddedArt(TagLib::FLAC::File *flac_file, TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const;
|
||||
void SetEmbeddedArt(TagLib::Ogg::XiphComment *xiph_comment, const QByteArray &data, const QString &mime_type) const;
|
||||
void SetEmbeddedArt(TagLib::MPEG::File *file_mp3, TagLib::ID3v2::Tag *tag, const QByteArray &data, const QString &mime_type) const;
|
||||
void SetEmbeddedArt(TagLib::MP4::File *aac_file, TagLib::MP4::Tag *tag, const QByteArray &data, const QString &mime_type) const;
|
||||
|
||||
private:
|
||||
FileRefFactory *factory_;
|
||||
|
||||
@@ -224,7 +224,7 @@ bool TagReaderTagParser::ReadFile(const QString &filename, spb::tagreader::SongM
|
||||
song->set_track(tag->value(TagParser::KnownField::TrackPosition).toInteger());
|
||||
song->set_disc(tag->value(TagParser::KnownField::DiskPosition).toInteger());
|
||||
if (!tag->value(TagParser::KnownField::Cover).empty() && tag->value(TagParser::KnownField::Cover).dataSize() > 0) {
|
||||
song->set_art_automatic(kEmbeddedCover);
|
||||
song->set_art_embedded(true);
|
||||
}
|
||||
const float rating = ConvertPOPMRating(tag->value(TagParser::KnownField::Rating));
|
||||
if (song->rating() <= 0 && rating > 0.0 && rating <= 1.0) {
|
||||
|
||||
Reference in New Issue
Block a user