Add better error handling for Tag reader
This commit is contained in:
@@ -1075,11 +1075,11 @@ if(HAVE_LIBMTP)
|
||||
link_directories(${LIBMTP_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
if(USE_TAGLIB AND TAGLIB_FOUND)
|
||||
if(HAVE_TAGLIB)
|
||||
link_directories(${TAGLIB_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
if(USE_TAGPARSER AND TAGPARSER_FOUND)
|
||||
if(HAVE_TAGPARSER)
|
||||
link_directories(${TAGPARSER_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -206,8 +206,8 @@ void SCollection::SyncPlaycountAndRatingToFiles() {
|
||||
const qint64 nb_songs = songs.size();
|
||||
int i = 0;
|
||||
for (const Song &song : songs) {
|
||||
TagReaderClient::Instance()->UpdateSongPlaycountBlocking(song);
|
||||
TagReaderClient::Instance()->UpdateSongRatingBlocking(song);
|
||||
(void)TagReaderClient::Instance()->SaveSongPlaycountBlocking(song.url().toLocalFile(), song.playcount());
|
||||
(void)TagReaderClient::Instance()->SaveSongRatingBlocking(song.url().toLocalFile(), song.rating());
|
||||
app_->task_manager()->SetTaskProgress(task_id, ++i, nb_songs);
|
||||
}
|
||||
app_->task_manager()->SetTaskFinished(task_id);
|
||||
@@ -217,7 +217,7 @@ void SCollection::SyncPlaycountAndRatingToFiles() {
|
||||
void SCollection::SongsPlaycountChanged(const SongList &songs, const bool save_tags) {
|
||||
|
||||
if (save_tags || save_playcounts_to_files_) {
|
||||
app_->tag_reader_client()->UpdateSongsPlaycount(songs);
|
||||
app_->tag_reader_client()->SaveSongsPlaycount(songs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -225,7 +225,7 @@ void SCollection::SongsPlaycountChanged(const SongList &songs, const bool save_t
|
||||
void SCollection::SongsRatingChanged(const SongList &songs, const bool save_tags) {
|
||||
|
||||
if (save_tags || save_ratings_to_files_) {
|
||||
app_->tag_reader_client()->UpdateSongsRating(songs);
|
||||
app_->tag_reader_client()->SaveSongsRating(songs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,11 @@ QUrl CollectionPlaylistItem::Url() const { return song_.url(); }
|
||||
|
||||
void CollectionPlaylistItem::Reload() {
|
||||
|
||||
TagReaderClient::Instance()->ReadFileBlocking(song_.url().toLocalFile(), &song_);
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->ReadFileBlocking(song_.url().toLocalFile(), &song_);
|
||||
if (!result.success()) {
|
||||
qLog(Error) << "Could not reload file" << song_.url() << result.error;
|
||||
return;
|
||||
}
|
||||
UpdateTemporaryMetadata(song_);
|
||||
|
||||
}
|
||||
|
||||
@@ -817,8 +817,8 @@ void CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file,
|
||||
}
|
||||
|
||||
Song song_on_disk(source_);
|
||||
TagReaderClient::Instance()->ReadFileBlocking(file, &song_on_disk);
|
||||
if (song_on_disk.is_valid()) {
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->ReadFileBlocking(file, &song_on_disk);
|
||||
if (result.success() && song_on_disk.is_valid()) {
|
||||
song_on_disk.set_source(source_);
|
||||
song_on_disk.set_directory_id(t->dir());
|
||||
song_on_disk.set_id(matching_song.id());
|
||||
@@ -870,8 +870,8 @@ SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path
|
||||
}
|
||||
else { // It's a normal media file
|
||||
Song song(source_);
|
||||
TagReaderClient::Instance()->ReadFileBlocking(file, &song);
|
||||
if (song.is_valid()) {
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->ReadFileBlocking(file, &song);
|
||||
if (result.success() && song.is_valid()) {
|
||||
song.set_source(source_);
|
||||
PerformEBUR128Analysis(song);
|
||||
song.set_fingerprint(fingerprint);
|
||||
|
||||
@@ -37,8 +37,10 @@
|
||||
#cmakedefine HAVE_KEYSYMDEF_H
|
||||
#cmakedefine HAVE_XF86KEYSYM_H
|
||||
|
||||
#cmakedefine HAVE_TAGLIB
|
||||
#cmakedefine HAVE_TAGLIB_DSFFILE
|
||||
#cmakedefine HAVE_TAGLIB_DSDIFFFILE
|
||||
#cmakedefine HAVE_TAGPARSER
|
||||
|
||||
#cmakedefine USE_BUNDLE
|
||||
|
||||
@@ -51,9 +53,6 @@
|
||||
|
||||
#cmakedefine ENABLE_WIN32_CONSOLE
|
||||
|
||||
#cmakedefine USE_TAGLIB
|
||||
#cmakedefine USE_TAGPARSER
|
||||
|
||||
#cmakedefine HAVE_QX11APPLICATION
|
||||
|
||||
#cmakedefine HAVE_EBUR128
|
||||
|
||||
@@ -2249,7 +2249,7 @@ void MainWindow::RenumberTracks() {
|
||||
Song song = item->OriginalMetadata();
|
||||
if (song.IsEditable()) {
|
||||
song.set_track(track);
|
||||
TagReaderReply *reply = TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
||||
TagReaderReply *reply = TagReaderClient::Instance()->WriteFile(song.url().toLocalFile(), song);
|
||||
QPersistentModelIndex persistent_index = QPersistentModelIndex(source_index);
|
||||
QObject::connect(reply, &TagReaderReply::Finished, this, [this, reply, persistent_index]() { SongSaveComplete(reply, persistent_index); }, Qt::QueuedConnection);
|
||||
}
|
||||
@@ -2280,7 +2280,7 @@ void MainWindow::SelectionSetValue() {
|
||||
Song song = item->OriginalMetadata();
|
||||
if (!song.is_valid()) continue;
|
||||
if (song.url().isLocalFile() && Playlist::set_column_value(song, column, column_value)) {
|
||||
TagReaderReply *reply = TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
||||
TagReaderReply *reply = TagReaderClient::Instance()->WriteFile(song.url().toLocalFile(), song);
|
||||
QPersistentModelIndex persistent_index = QPersistentModelIndex(source_index);
|
||||
QObject::connect(reply, &TagReaderReply::Finished, this, [this, reply, persistent_index]() { SongSaveComplete(reply, persistent_index); }, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
@@ -1302,27 +1302,27 @@ void Song::InitFromProtobuf(const spb::tagreader::SongMetadata &pb) {
|
||||
|
||||
d->init_from_file_ = true;
|
||||
d->valid_ = pb.valid();
|
||||
set_title(QString::fromUtf8(pb.title().data(), static_cast<qint64>(pb.title().size())));
|
||||
set_album(QString::fromUtf8(pb.album().data(), static_cast<qint64>(pb.album().size())));
|
||||
set_artist(QString::fromUtf8(pb.artist().data(), static_cast<qint64>(pb.artist().size())));
|
||||
set_albumartist(QString::fromUtf8(pb.albumartist().data(), static_cast<qint64>(pb.albumartist().size())));
|
||||
set_title(QString::fromStdString(pb.title()));
|
||||
set_album(QString::fromStdString(pb.album()));
|
||||
set_artist(QString::fromStdString(pb.artist()));
|
||||
set_albumartist(QString::fromStdString(pb.albumartist()));
|
||||
d->track_ = pb.track();
|
||||
d->disc_ = pb.disc();
|
||||
d->year_ = pb.year();
|
||||
d->originalyear_ = pb.originalyear();
|
||||
d->genre_ = QString::fromUtf8(pb.genre().data(), static_cast<qint64>(pb.genre().size()));
|
||||
d->genre_ = QString::fromStdString(pb.genre());
|
||||
d->compilation_ = pb.compilation();
|
||||
d->composer_ = QString::fromUtf8(pb.composer().data(), static_cast<qint64>(pb.composer().size()));
|
||||
d->performer_ = QString::fromUtf8(pb.performer().data(), static_cast<qint64>(pb.performer().size()));
|
||||
d->grouping_ = QString::fromUtf8(pb.grouping().data(), static_cast<qint64>(pb.grouping().size()));
|
||||
d->comment_ = QString::fromUtf8(pb.comment().data(), static_cast<qint64>(pb.comment().size()));
|
||||
d->lyrics_ = QString::fromUtf8(pb.lyrics().data(), static_cast<qint64>(pb.lyrics().size()));
|
||||
d->composer_ = QString::fromStdString(pb.composer());
|
||||
d->performer_ = QString::fromStdString(pb.performer());
|
||||
d->grouping_ = QString::fromStdString(pb.grouping());
|
||||
d->comment_ = QString::fromStdString(pb.comment());
|
||||
d->lyrics_ = QString::fromStdString(pb.lyrics());
|
||||
set_length_nanosec(static_cast<qint64>(pb.length_nanosec()));
|
||||
d->bitrate_ = pb.bitrate();
|
||||
d->samplerate_ = pb.samplerate();
|
||||
d->bitdepth_ = pb.bitdepth();
|
||||
set_url(QUrl::fromEncoded(QByteArray(pb.url().data(), static_cast<qint64>(pb.url().size()))));
|
||||
d->basefilename_ = QString::fromUtf8(pb.basefilename().data(), static_cast<qint64>(pb.basefilename().size()));
|
||||
set_url(QUrl::fromEncoded(QString::fromStdString(pb.url()).toUtf8()));
|
||||
d->basefilename_ = QString::fromStdString(pb.basefilename());
|
||||
d->filetype_ = static_cast<FileType>(pb.filetype());
|
||||
d->filesize_ = pb.filesize();
|
||||
d->mtime_ = pb.mtime();
|
||||
@@ -1340,19 +1340,19 @@ void Song::InitFromProtobuf(const spb::tagreader::SongMetadata &pb) {
|
||||
|
||||
d->art_embedded_ = pb.has_art_embedded();
|
||||
|
||||
d->acoustid_id_ = QString::fromUtf8(pb.acoustid_id().data(), static_cast<qint64>(pb.acoustid_id().size()));
|
||||
d->acoustid_fingerprint_ = QString::fromUtf8(pb.acoustid_fingerprint().data(), static_cast<qint64>(pb.acoustid_fingerprint().size()));
|
||||
d->acoustid_id_ = QString::fromStdString(pb.acoustid_id());
|
||||
d->acoustid_fingerprint_ = QString::fromStdString(pb.acoustid_fingerprint());
|
||||
|
||||
d->musicbrainz_album_artist_id_ = QString::fromUtf8(pb.musicbrainz_album_artist_id().data(), static_cast<qint64>(pb.musicbrainz_album_artist_id().size()));
|
||||
d->musicbrainz_artist_id_ = QString::fromUtf8(pb.musicbrainz_artist_id().data(), static_cast<qint64>(pb.musicbrainz_artist_id().size()));
|
||||
d->musicbrainz_original_artist_id_ = QString::fromUtf8(pb.musicbrainz_original_artist_id().data(), static_cast<qint64>(pb.musicbrainz_original_artist_id().size()));
|
||||
d->musicbrainz_album_id_ = QString::fromUtf8(pb.musicbrainz_album_id().data(), static_cast<qint64>(pb.musicbrainz_album_id().size()));
|
||||
d->musicbrainz_original_album_id_ = QString::fromUtf8(pb.musicbrainz_original_album_id().data(), static_cast<qint64>(pb.musicbrainz_original_album_id().size()));
|
||||
d->musicbrainz_recording_id_ = QString::fromUtf8(pb.musicbrainz_recording_id().data(), static_cast<qint64>(pb.musicbrainz_recording_id().size()));
|
||||
d->musicbrainz_track_id_ = QString::fromUtf8(pb.musicbrainz_track_id().data(), static_cast<qint64>(pb.musicbrainz_track_id().size()));
|
||||
d->musicbrainz_disc_id_ = QString::fromUtf8(pb.musicbrainz_disc_id().data(), static_cast<qint64>(pb.musicbrainz_disc_id().size()));
|
||||
d->musicbrainz_release_group_id_ = QString::fromUtf8(pb.musicbrainz_release_group_id().data(), static_cast<qint64>(pb.musicbrainz_release_group_id().size()));
|
||||
d->musicbrainz_work_id_ = QString::fromUtf8(pb.musicbrainz_work_id().data(), static_cast<qint64>(pb.musicbrainz_work_id().size()));
|
||||
d->musicbrainz_album_artist_id_ = QString::fromStdString(pb.musicbrainz_album_artist_id());
|
||||
d->musicbrainz_artist_id_ = QString::fromStdString(pb.musicbrainz_artist_id().data());
|
||||
d->musicbrainz_original_artist_id_ = QString::fromStdString(pb.musicbrainz_original_artist_id());
|
||||
d->musicbrainz_album_id_ = QString::fromStdString(pb.musicbrainz_album_id());
|
||||
d->musicbrainz_original_album_id_ = QString::fromStdString(pb.musicbrainz_original_album_id());
|
||||
d->musicbrainz_recording_id_ = QString::fromStdString(pb.musicbrainz_recording_id());
|
||||
d->musicbrainz_track_id_ = QString::fromStdString(pb.musicbrainz_track_id());
|
||||
d->musicbrainz_disc_id_ = QString::fromStdString(pb.musicbrainz_disc_id());
|
||||
d->musicbrainz_release_group_id_ = QString::fromStdString(pb.musicbrainz_release_group_id());
|
||||
d->musicbrainz_work_id_ = QString::fromStdString(pb.musicbrainz_work_id());
|
||||
|
||||
d->suspicious_tags_ = pb.suspicious_tags();
|
||||
|
||||
|
||||
@@ -354,8 +354,11 @@ void SongLoader::EffectiveSongLoad(Song *song) {
|
||||
}
|
||||
else {
|
||||
// It's a normal media file
|
||||
QString filename = song->url().toLocalFile();
|
||||
TagReaderClient::Instance()->ReadFileBlocking(filename, song);
|
||||
const QString filename = song->url().toLocalFile();
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->ReadFileBlocking(filename, song);
|
||||
if (!result.success()) {
|
||||
qLog(Error) << "Could not read file" << song->url() << result.error;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2019-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2019-2024, 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
|
||||
@@ -73,11 +73,7 @@ void TagReaderClient::WorkerFailedToStart() {
|
||||
TagReaderReply *TagReaderClient::IsMediaFile(const QString &filename) {
|
||||
|
||||
spb::tagreader::Message message;
|
||||
spb::tagreader::IsMediaFileRequest *request = message.mutable_is_media_file_request();
|
||||
|
||||
const QByteArray filename_data = filename.toUtf8();
|
||||
request->set_filename(filename_data.constData(), filename_data.length());
|
||||
|
||||
message.mutable_is_media_file_request()->set_filename(filename.toStdString());
|
||||
return worker_pool_->SendMessageWithReply(&message);
|
||||
|
||||
}
|
||||
@@ -85,39 +81,33 @@ TagReaderReply *TagReaderClient::IsMediaFile(const QString &filename) {
|
||||
TagReaderReply *TagReaderClient::ReadFile(const QString &filename) {
|
||||
|
||||
spb::tagreader::Message message;
|
||||
spb::tagreader::ReadFileRequest *request = message.mutable_read_file_request();
|
||||
|
||||
const QByteArray filename_data = filename.toUtf8();
|
||||
request->set_filename(filename_data.constData(), filename_data.length());
|
||||
|
||||
message.mutable_read_file_request()->set_filename(filename.toStdString());
|
||||
return worker_pool_->SendMessageWithReply(&message);
|
||||
|
||||
}
|
||||
|
||||
TagReaderReply *TagReaderClient::SaveFile(const QString &filename, const Song &metadata, const SaveTypes save_types, const SaveCoverOptions &save_cover_options) {
|
||||
TagReaderReply *TagReaderClient::WriteFile(const QString &filename, const Song &metadata, const SaveTypes save_types, const SaveCoverOptions &save_cover_options) {
|
||||
|
||||
spb::tagreader::Message message;
|
||||
spb::tagreader::SaveFileRequest *request = message.mutable_save_file_request();
|
||||
spb::tagreader::WriteFileRequest *request = message.mutable_write_file_request();
|
||||
|
||||
const QByteArray filename_data = filename.toUtf8();
|
||||
request->set_filename(filename_data.constData(), filename_data.length());
|
||||
request->set_filename(filename.toStdString());
|
||||
|
||||
request->set_save_tags(save_types.testFlag(SaveType::Tags));
|
||||
request->set_save_playcount(save_types.testFlag(SaveType::PlayCount));
|
||||
request->set_save_rating(save_types.testFlag(SaveType::Rating));
|
||||
request->set_save_cover(save_types.testFlag(SaveType::Cover));
|
||||
|
||||
if (save_cover_options.cover_filename.length() > 0) {
|
||||
const QByteArray cover_filename = save_cover_options.cover_filename.toUtf8();
|
||||
request->set_cover_filename(cover_filename.constData(), cover_filename.length());
|
||||
if (!save_cover_options.cover_filename.isEmpty()) {
|
||||
request->set_cover_filename(save_cover_options.cover_filename.toStdString());
|
||||
}
|
||||
if (save_cover_options.cover_data.length() > 0) {
|
||||
request->set_cover_data(save_cover_options.cover_data.constData(), save_cover_options.cover_data.length());
|
||||
if (!save_cover_options.cover_data.isEmpty()) {
|
||||
request->set_cover_data(save_cover_options.cover_data.toStdString());
|
||||
}
|
||||
if (save_cover_options.mime_type.length() > 0) {
|
||||
const QByteArray cover_mime_type = save_cover_options.mime_type.toUtf8();
|
||||
request->set_cover_mime_type(cover_mime_type.constData(), cover_mime_type.length());
|
||||
if (!save_cover_options.mime_type.isEmpty()) {
|
||||
request->set_cover_mime_type(save_cover_options.mime_type.toStdString());
|
||||
}
|
||||
|
||||
metadata.ToProtobuf(request->mutable_metadata());
|
||||
|
||||
ReplyType *reply = worker_pool_->SendMessageWithReply(&message);
|
||||
@@ -131,8 +121,7 @@ TagReaderReply *TagReaderClient::LoadEmbeddedArt(const QString &filename) {
|
||||
spb::tagreader::Message message;
|
||||
spb::tagreader::LoadEmbeddedArtRequest *request = message.mutable_load_embedded_art_request();
|
||||
|
||||
const QByteArray filename_data = filename.toUtf8();
|
||||
request->set_filename(filename_data.constData(), filename_data.length());
|
||||
request->set_filename(filename.toStdString());
|
||||
|
||||
return worker_pool_->SendMessageWithReply(&message);
|
||||
|
||||
@@ -143,63 +132,59 @@ TagReaderReply *TagReaderClient::SaveEmbeddedArt(const QString &filename, const
|
||||
spb::tagreader::Message message;
|
||||
spb::tagreader::SaveEmbeddedArtRequest *request = message.mutable_save_embedded_art_request();
|
||||
|
||||
const QByteArray filename_data = filename.toUtf8();
|
||||
request->set_filename(filename_data.constData(), filename_data.length());
|
||||
if (save_cover_options.cover_filename.length() > 0) {
|
||||
const QByteArray cover_filename = save_cover_options.cover_filename.toUtf8();
|
||||
request->set_cover_filename(cover_filename.constData(), cover_filename.length());
|
||||
request->set_filename(filename.toStdString());
|
||||
|
||||
if (!save_cover_options.cover_filename.isEmpty()) {
|
||||
request->set_cover_filename(save_cover_options.cover_filename.toStdString());
|
||||
}
|
||||
if (save_cover_options.cover_data.length() > 0) {
|
||||
request->set_cover_data(save_cover_options.cover_data.constData(), save_cover_options.cover_data.length());
|
||||
if (!save_cover_options.cover_data.isEmpty()) {
|
||||
request->set_cover_data(save_cover_options.cover_data.toStdString());
|
||||
}
|
||||
if (save_cover_options.mime_type.length() > 0) {
|
||||
const QByteArray cover_mime_type = save_cover_options.mime_type.toUtf8();
|
||||
request->set_cover_mime_type(cover_mime_type.constData(), cover_mime_type.length());
|
||||
if (!save_cover_options.mime_type.isEmpty()) {
|
||||
request->set_cover_mime_type(save_cover_options.mime_type.toStdString());
|
||||
}
|
||||
|
||||
return worker_pool_->SendMessageWithReply(&message);
|
||||
|
||||
}
|
||||
|
||||
TagReaderReply *TagReaderClient::UpdateSongPlaycount(const Song &metadata) {
|
||||
TagReaderReply *TagReaderClient::SaveSongPlaycount(const QString &filename, const uint playcount) {
|
||||
|
||||
spb::tagreader::Message message;
|
||||
spb::tagreader::SaveSongPlaycountToFileRequest *request = message.mutable_save_song_playcount_to_file_request();
|
||||
|
||||
const QByteArray filename_data = metadata.url().toLocalFile().toUtf8();
|
||||
request->set_filename(filename_data.constData(), filename_data.length());
|
||||
metadata.ToProtobuf(request->mutable_metadata());
|
||||
request->set_filename(filename.toStdString());
|
||||
request->set_playcount(playcount);
|
||||
|
||||
return worker_pool_->SendMessageWithReply(&message);
|
||||
|
||||
}
|
||||
|
||||
void TagReaderClient::UpdateSongsPlaycount(const SongList &songs) {
|
||||
void TagReaderClient::SaveSongsPlaycount(const SongList &songs) {
|
||||
|
||||
for (const Song &song : songs) {
|
||||
TagReaderReply *reply = UpdateSongPlaycount(song);
|
||||
TagReaderReply *reply = SaveSongPlaycount(song.url().toLocalFile(), song.playcount());
|
||||
QObject::connect(reply, &TagReaderReply::Finished, reply, &TagReaderReply::deleteLater);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TagReaderReply *TagReaderClient::UpdateSongRating(const Song &metadata) {
|
||||
TagReaderReply *TagReaderClient::SaveSongRating(const QString &filename, const float rating) {
|
||||
|
||||
spb::tagreader::Message message;
|
||||
spb::tagreader::SaveSongRatingToFileRequest *request = message.mutable_save_song_rating_to_file_request();
|
||||
|
||||
const QByteArray filename_data = metadata.url().toLocalFile().toUtf8();
|
||||
request->set_filename(filename_data.constData(), filename_data.length());
|
||||
metadata.ToProtobuf(request->mutable_metadata());
|
||||
request->set_filename(filename.toStdString());
|
||||
request->set_rating(rating);
|
||||
|
||||
return worker_pool_->SendMessageWithReply(&message);
|
||||
|
||||
}
|
||||
|
||||
void TagReaderClient::UpdateSongsRating(const SongList &songs) {
|
||||
void TagReaderClient::SaveSongsRating(const SongList &songs) {
|
||||
|
||||
for (const Song &song : songs) {
|
||||
TagReaderReply *reply = UpdateSongRating(song);
|
||||
TagReaderReply *reply = SaveSongRating(song.url().toLocalFile(), song.rating());
|
||||
QObject::connect(reply, &TagReaderReply::Finished, reply, &TagReaderReply::deleteLater);
|
||||
}
|
||||
|
||||
@@ -209,124 +194,180 @@ bool TagReaderClient::IsMediaFileBlocking(const QString &filename) {
|
||||
|
||||
Q_ASSERT(QThread::currentThread() != thread());
|
||||
|
||||
bool ret = false;
|
||||
bool success = false;
|
||||
|
||||
TagReaderReply *reply = IsMediaFile(filename);
|
||||
if (reply->WaitForFinished()) {
|
||||
ret = reply->message().is_media_file_response().success();
|
||||
const spb::tagreader::IsMediaFileResponse &response = reply->message().is_media_file_response();
|
||||
if (response.has_success()) {
|
||||
success = response.success();
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
return ret;
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
void TagReaderClient::ReadFileBlocking(const QString &filename, Song *song) {
|
||||
TagReaderClient::Result TagReaderClient::ReadFileBlocking(const QString &filename, Song *song) {
|
||||
|
||||
Q_ASSERT(QThread::currentThread() != thread());
|
||||
|
||||
Result result(Result::ErrorCode::Failure);
|
||||
|
||||
TagReaderReply *reply = ReadFile(filename);
|
||||
if (reply->WaitForFinished()) {
|
||||
song->InitFromProtobuf(reply->message().read_file_response().metadata());
|
||||
const spb::tagreader::ReadFileResponse &response = reply->message().read_file_response();
|
||||
if (response.has_success()) {
|
||||
if (response.success()) {
|
||||
result.error_code = Result::ErrorCode::Success;
|
||||
if (response.has_metadata()) {
|
||||
song->InitFromProtobuf(response.metadata());
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.error_code = Result::ErrorCode::Failure;
|
||||
if (response.has_error()) {
|
||||
result.error = QString::fromStdString(response.error());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
bool TagReaderClient::SaveFileBlocking(const QString &filename, const Song &metadata, const SaveTypes save_types, const SaveCoverOptions &save_cover_options) {
|
||||
TagReaderClient::Result TagReaderClient::WriteFileBlocking(const QString &filename, const Song &metadata, const SaveTypes save_types, const SaveCoverOptions &save_cover_options) {
|
||||
|
||||
Q_ASSERT(QThread::currentThread() != thread());
|
||||
|
||||
bool ret = false;
|
||||
Result result(Result::ErrorCode::Failure);
|
||||
|
||||
TagReaderReply *reply = SaveFile(filename, metadata, save_types, save_cover_options);
|
||||
TagReaderReply *reply = WriteFile(filename, metadata, save_types, save_cover_options);
|
||||
if (reply->WaitForFinished()) {
|
||||
ret = reply->message().save_file_response().success();
|
||||
const spb::tagreader::WriteFileResponse &response = reply->message().write_file_response();
|
||||
if (response.has_success()) {
|
||||
result.error_code = response.success() ? Result::ErrorCode::Success : Result::ErrorCode::Failure;
|
||||
if (response.has_error()) {
|
||||
result.error = QString::fromStdString(response.error());
|
||||
}
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
return ret;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
QByteArray TagReaderClient::LoadEmbeddedArtBlocking(const QString &filename) {
|
||||
TagReaderClient::Result TagReaderClient::LoadEmbeddedArtBlocking(const QString &filename, QByteArray &data) {
|
||||
|
||||
Q_ASSERT(QThread::currentThread() != thread());
|
||||
|
||||
QByteArray ret;
|
||||
Result result(Result::ErrorCode::Failure);
|
||||
|
||||
TagReaderReply *reply = LoadEmbeddedArt(filename);
|
||||
if (reply->WaitForFinished()) {
|
||||
const std::string &data_str = reply->message().load_embedded_art_response().data();
|
||||
ret = QByteArray(data_str.data(), static_cast<qint64>(data_str.size()));
|
||||
const spb::tagreader::LoadEmbeddedArtResponse &response = reply->message().load_embedded_art_response();
|
||||
if (response.has_success()) {
|
||||
if (response.success()) {
|
||||
result.error_code = Result::ErrorCode::Success;
|
||||
if (response.has_data()) {
|
||||
data = QByteArray(response.data().data(), static_cast<qint64>(response.data().size()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.error_code = Result::ErrorCode::Failure;
|
||||
if (response.has_error()) {
|
||||
result.error = QString::fromStdString(response.error());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
return ret;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
QImage TagReaderClient::LoadEmbeddedArtAsImageBlocking(const QString &filename) {
|
||||
TagReaderClient::Result TagReaderClient::LoadEmbeddedArtAsImageBlocking(const QString &filename, QImage &image) {
|
||||
|
||||
Q_ASSERT(QThread::currentThread() != thread());
|
||||
|
||||
QImage ret;
|
||||
|
||||
TagReaderReply *reply = LoadEmbeddedArt(filename);
|
||||
if (reply->WaitForFinished()) {
|
||||
const std::string &data_str = reply->message().load_embedded_art_response().data();
|
||||
ret.loadFromData(QByteArray(data_str.data(), static_cast<qint64>(data_str.size())));
|
||||
QByteArray data;
|
||||
Result result = LoadEmbeddedArtBlocking(filename, data);
|
||||
if (result.error_code == Result::ErrorCode::Success && !image.loadFromData(data)) {
|
||||
result.error_code = Result::ErrorCode::Failure;
|
||||
result.error = QObject::tr("Failed to load image from data for %1").arg(filename);
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
return ret;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
bool TagReaderClient::SaveEmbeddedArtBlocking(const QString &filename, const SaveCoverOptions &save_cover_options) {
|
||||
TagReaderClient::Result TagReaderClient::SaveEmbeddedArtBlocking(const QString &filename, const SaveCoverOptions &save_cover_options) {
|
||||
|
||||
Q_ASSERT(QThread::currentThread() != thread());
|
||||
|
||||
bool success = false;
|
||||
Result result(Result::ErrorCode::Failure);
|
||||
|
||||
TagReaderReply *reply = SaveEmbeddedArt(filename, save_cover_options);
|
||||
if (reply->WaitForFinished()) {
|
||||
success = reply->message().save_embedded_art_response().success();
|
||||
const spb::tagreader::SaveEmbeddedArtResponse &response = reply->message().save_embedded_art_response();
|
||||
if (response.has_success()) {
|
||||
result.error_code = response.success() ? Result::ErrorCode::Success : Result::ErrorCode::Failure;
|
||||
if (response.has_error()) {
|
||||
result.error = QString::fromStdString(response.error());
|
||||
}
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
return success;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
bool TagReaderClient::UpdateSongPlaycountBlocking(const Song &metadata) {
|
||||
TagReaderClient::Result TagReaderClient::SaveSongPlaycountBlocking(const QString &filename, const uint playcount) {
|
||||
|
||||
Q_ASSERT(QThread::currentThread() != thread());
|
||||
|
||||
bool success = false;
|
||||
Result result(Result::ErrorCode::Failure);
|
||||
|
||||
TagReaderReply *reply = UpdateSongPlaycount(metadata);
|
||||
TagReaderReply *reply = SaveSongPlaycount(filename, playcount);
|
||||
if (reply->WaitForFinished()) {
|
||||
success = reply->message().save_song_playcount_to_file_response().success();
|
||||
const spb::tagreader::SaveSongPlaycountToFileResponse &response = reply->message().save_song_playcount_to_file_response();
|
||||
if (response.has_success()) {
|
||||
result.error_code = response.success() ? Result::ErrorCode::Success : Result::ErrorCode::Failure;
|
||||
if (response.has_error()) {
|
||||
result.error = QString::fromStdString(response.error());
|
||||
}
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
return success;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
bool TagReaderClient::UpdateSongRatingBlocking(const Song &metadata) {
|
||||
TagReaderClient::Result TagReaderClient::SaveSongRatingBlocking(const QString &filename, const float rating) {
|
||||
|
||||
Q_ASSERT(QThread::currentThread() != thread());
|
||||
|
||||
bool success = false;
|
||||
Result result(Result::ErrorCode::Failure);
|
||||
|
||||
TagReaderReply *reply = UpdateSongRating(metadata);
|
||||
TagReaderReply *reply = SaveSongRating(filename, rating);
|
||||
if (reply->WaitForFinished()) {
|
||||
success = reply->message().save_song_rating_to_file_response().success();
|
||||
const spb::tagreader::SaveSongRatingToFileResponse &response = reply->message().save_song_rating_to_file_response();
|
||||
if (response.has_success()) {
|
||||
result.error_code = response.success() ? Result::ErrorCode::Success : Result::ErrorCode::Failure;
|
||||
if (response.has_error()) {
|
||||
result.error = QString::fromStdString(response.error());
|
||||
}
|
||||
}
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
return success;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2011, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2019-2023, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2019-2024, 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
|
||||
@@ -70,24 +70,45 @@ class TagReaderClient : public QObject {
|
||||
QString mime_type;
|
||||
};
|
||||
|
||||
class Result {
|
||||
public:
|
||||
enum class ErrorCode {
|
||||
Success,
|
||||
Unsupported,
|
||||
Failure,
|
||||
};
|
||||
Result(const ErrorCode _error_code, const QString &_error = QString()) : error_code(_error_code), error(_error) {}
|
||||
ErrorCode error_code;
|
||||
QString error;
|
||||
bool success() const { return error_code == TagReaderClient::Result::ErrorCode::Success; }
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
ReplyType *IsMediaFile(const QString &filename);
|
||||
ReplyType *ReadFile(const QString &filename);
|
||||
ReplyType *SaveFile(const QString &filename, const Song &metadata, const SaveTypes types = SaveType::Tags, const SaveCoverOptions &save_cover_options = SaveCoverOptions());
|
||||
ReplyType *WriteFile(const QString &filename, const Song &metadata, const SaveTypes types = SaveType::Tags, const SaveCoverOptions &save_cover_options = SaveCoverOptions());
|
||||
ReplyType *LoadEmbeddedArt(const QString &filename);
|
||||
ReplyType *SaveEmbeddedArt(const QString &filename, const SaveCoverOptions &save_cover_options);
|
||||
ReplyType *UpdateSongPlaycount(const Song &metadata);
|
||||
ReplyType *UpdateSongRating(const Song &metadata);
|
||||
ReplyType *SaveSongPlaycount(const QString &filename, const uint playcount);
|
||||
ReplyType *SaveSongRating(const QString &filename, const float rating);
|
||||
|
||||
// Convenience functions that call the above functions and wait for a response.
|
||||
// These block the calling thread with a semaphore, and must NOT be called from the TagReaderClient's thread.
|
||||
void ReadFileBlocking(const QString &filename, Song *song);
|
||||
bool SaveFileBlocking(const QString &filename, const Song &metadata, const SaveTypes types = SaveType::Tags, const SaveCoverOptions &save_cover_options = SaveCoverOptions());
|
||||
Result ReadFileBlocking(const QString &filename, Song *song);
|
||||
Result WriteFileBlocking(const QString &filename, const Song &metadata, const SaveTypes types = SaveType::Tags, const SaveCoverOptions &save_cover_options = SaveCoverOptions());
|
||||
bool IsMediaFileBlocking(const QString &filename);
|
||||
QByteArray LoadEmbeddedArtBlocking(const QString &filename);
|
||||
QImage LoadEmbeddedArtAsImageBlocking(const QString &filename);
|
||||
bool SaveEmbeddedArtBlocking(const QString &filename, const SaveCoverOptions &save_cover_options);
|
||||
bool UpdateSongPlaycountBlocking(const Song &metadata);
|
||||
bool UpdateSongRatingBlocking(const Song &metadata);
|
||||
Result LoadEmbeddedArtBlocking(const QString &filename, QByteArray &data);
|
||||
Result LoadEmbeddedArtAsImageBlocking(const QString &filename, QImage &image);
|
||||
Result SaveEmbeddedArtBlocking(const QString &filename, const SaveCoverOptions &save_cover_options);
|
||||
Result SaveSongPlaycountBlocking(const QString &filename, const uint playcount);
|
||||
Result SaveSongRatingBlocking(const QString &filename, const float rating);
|
||||
|
||||
// TODO: Make this not a singleton
|
||||
static TagReaderClient *Instance() { return sInstance; }
|
||||
@@ -100,8 +121,8 @@ class TagReaderClient : public QObject {
|
||||
void WorkerFailedToStart();
|
||||
|
||||
public slots:
|
||||
void UpdateSongsPlaycount(const SongList &songs);
|
||||
void UpdateSongsRating(const SongList &songs);
|
||||
void SaveSongsPlaycount(const SongList &songs);
|
||||
void SaveSongsRating(const SongList &songs);
|
||||
|
||||
private:
|
||||
static TagReaderClient *sInstance;
|
||||
|
||||
@@ -440,8 +440,9 @@ void AlbumCoverChoiceController::ShowCover(const Song &song, const QImage &image
|
||||
}
|
||||
case AlbumCoverLoaderOptions::Type::Embedded:{
|
||||
if (song.art_embedded() && !song.url().isEmpty() && song.url().isValid() && song.url().isLocalFile()) {
|
||||
const QImage image_embedded_cover = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(song.url().toLocalFile());
|
||||
if (!image_embedded_cover.isNull()) {
|
||||
QImage image_embedded_cover;
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(song.url().toLocalFile(), image_embedded_cover);
|
||||
if (result.success() && !image_embedded_cover.isNull()) {
|
||||
QPixmap pixmap = QPixmap::fromImage(image_embedded_cover);
|
||||
if (!pixmap.isNull()) {
|
||||
pixmap.setDevicePixelRatio(devicePixelRatioF());
|
||||
|
||||
@@ -290,8 +290,8 @@ AlbumCoverLoader::LoadImageResult AlbumCoverLoader::LoadImage(TaskPtr task, cons
|
||||
AlbumCoverLoader::LoadImageResult AlbumCoverLoader::LoadEmbeddedImage(TaskPtr task) {
|
||||
|
||||
if (task->art_embedded && task->song_url.isValid() && task->song_url.isLocalFile()) {
|
||||
task->album_cover.image_data = TagReaderClient::Instance()->LoadEmbeddedArtBlocking(task->song_url.toLocalFile());
|
||||
if (!task->album_cover.image_data.isEmpty() && task->album_cover.image.loadFromData(task->album_cover.image_data)) {
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->LoadEmbeddedArtBlocking(task->song_url.toLocalFile(), task->album_cover.image_data);
|
||||
if (result.success() && !task->album_cover.image_data.isEmpty() && task->album_cover.image.loadFromData(task->album_cover.image_data)) {
|
||||
return LoadImageResult(AlbumCoverLoaderResult::Type::Embedded, LoadImageResult::Status::Success);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,7 +717,10 @@ void AlbumCoverManager::SaveCoverToFile() {
|
||||
return;
|
||||
case AlbumCoverLoaderOptions::Type::Embedded:
|
||||
if (song.art_embedded()) {
|
||||
result.image_data = TagReaderClient::Instance()->LoadEmbeddedArtBlocking(song.url().toLocalFile());
|
||||
const TagReaderClient::Result tagreaderclient_result = TagReaderClient::Instance()->LoadEmbeddedArtBlocking(song.url().toLocalFile(), result.image_data);
|
||||
if (!tagreaderclient_result.success()) {
|
||||
qLog(Error) << "Could not load embedded art from" << song.url() << tagreaderclient_result.error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AlbumCoverLoaderOptions::Type::Automatic:
|
||||
|
||||
@@ -76,8 +76,8 @@ void CoverExportRunnable::ProcessAndExportCover() {
|
||||
break;
|
||||
case AlbumCoverLoaderOptions::Type::Embedded:
|
||||
if (song_.art_embedded() && dialog_result_.export_embedded_) {
|
||||
image = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(song_.url().toLocalFile());
|
||||
if (!image.isNull()) {
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(song_.url().toLocalFile(), image);
|
||||
if (result.success() && !image.isNull()) {
|
||||
extension = QLatin1String("jpg");
|
||||
}
|
||||
}
|
||||
@@ -168,8 +168,8 @@ void CoverExportRunnable::ExportCover() {
|
||||
break;
|
||||
case AlbumCoverLoaderOptions::Type::Embedded:
|
||||
if (song_.art_embedded() && dialog_result_.export_embedded_) {
|
||||
image = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(song_.url().toLocalFile());
|
||||
if (!image.isNull()) {
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(song_.url().toLocalFile(), image);
|
||||
if (result.success() && !image.isNull()) {
|
||||
embedded_cover = true;
|
||||
extension = QLatin1String("jpg");
|
||||
}
|
||||
|
||||
@@ -399,8 +399,8 @@ QList<EditTagDialog::Data> EditTagDialog::LoadData(const SongList &songs) {
|
||||
if (song.IsEditable()) {
|
||||
// Try reloading the tags from file
|
||||
Song copy(song);
|
||||
TagReaderClient::Instance()->ReadFileBlocking(copy.url().toLocalFile(), ©);
|
||||
if (copy.is_valid()) {
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->ReadFileBlocking(copy.url().toLocalFile(), ©);
|
||||
if (result.success() && copy.is_valid()) {
|
||||
copy.MergeUserSetData(song, false, false);
|
||||
ret << Data(copy);
|
||||
}
|
||||
@@ -1295,7 +1295,7 @@ void EditTagDialog::SaveData() {
|
||||
if (save_embedded_cover) {
|
||||
save_types |= TagReaderClient::SaveType::Cover;
|
||||
}
|
||||
TagReaderReply *reply = TagReaderClient::Instance()->SaveFile(ref.current_.url().toLocalFile(), ref.current_, save_types, savecover_options);
|
||||
TagReaderReply *reply = TagReaderClient::Instance()->WriteFile(ref.current_.url().toLocalFile(), ref.current_, save_types, savecover_options);
|
||||
QObject::connect(reply, &TagReaderReply::Finished, this, [this, reply, ref]() { SongSaveTagsComplete(reply, ref.current_.url().toLocalFile(), ref.current_, ref.cover_action_); }, Qt::QueuedConnection);
|
||||
}
|
||||
// If the cover was changed, but no tags written, make sure to update the collection.
|
||||
@@ -1450,7 +1450,11 @@ void EditTagDialog::UpdateLyrics(const quint64 id, const QString &provider, cons
|
||||
void EditTagDialog::SongSaveTagsComplete(TagReaderReply *reply, const QString &filename, Song song, const UpdateCoverAction cover_action) {
|
||||
|
||||
--save_tag_pending_;
|
||||
const bool success = reply->message().save_file_response().success();
|
||||
const bool success = reply->message().write_file_response().success();
|
||||
QString error;
|
||||
if (!success && reply->message().write_file_response().has_error()) {
|
||||
error = QString::fromStdString(reply->message().write_file_response().error());
|
||||
}
|
||||
reply->deleteLater();
|
||||
|
||||
if (success) {
|
||||
@@ -1483,7 +1487,12 @@ void EditTagDialog::SongSaveTagsComplete(TagReaderReply *reply, const QString &f
|
||||
}
|
||||
}
|
||||
else {
|
||||
emit Error(tr("An error occurred writing metadata to '%1'").arg(filename));
|
||||
if (error.isEmpty()) {
|
||||
emit Error(tr("Could not write metadata to %1").arg(filename));
|
||||
}
|
||||
else {
|
||||
emit Error(tr("Could not write metadata to %1: %2").arg(filename, error));
|
||||
}
|
||||
}
|
||||
|
||||
if (save_tag_pending_ <= 0) SaveDataFinished();
|
||||
|
||||
@@ -278,8 +278,9 @@ void TrackSelectionDialog::SaveData(const QList<Data> &data) {
|
||||
copy.set_track(new_metadata.track());
|
||||
copy.set_year(new_metadata.year());
|
||||
|
||||
if (!TagReaderClient::Instance()->SaveFileBlocking(copy.url().toLocalFile(), copy)) {
|
||||
qLog(Warning) << "Failed to write new auto-tags to" << copy.url().toLocalFile();
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->WriteFileBlocking(copy.url().toLocalFile(), copy, TagReaderClient::SaveType::Tags, TagReaderClient::SaveCoverOptions());
|
||||
if (!result.success()) {
|
||||
qLog(Error) << "Failed to write new auto-tags to" << copy.url().toLocalFile() << result.error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -245,7 +245,10 @@ void Organize::ProcessSomeFiles() {
|
||||
}
|
||||
}
|
||||
else if (destination_->source() == Song::Source::Device) {
|
||||
job.cover_image_ = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(task.song_info_.song_.url().toLocalFile());
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->LoadEmbeddedArtAsImageBlocking(task.song_info_.song_.url().toLocalFile(), job.cover_image_);
|
||||
if (!result.success()) {
|
||||
qLog(Error) << "Could not save embedded art to" << task.song_info_.song_.url() << result.error;
|
||||
}
|
||||
}
|
||||
|
||||
if (!job.cover_source_.isEmpty()) {
|
||||
|
||||
@@ -415,8 +415,13 @@ SongList OrganizeDialog::LoadSongsBlocking(const QStringList &filenames) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TagReaderClient::Instance()->ReadFileBlocking(filename, &song);
|
||||
if (song.is_valid()) songs << song;
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->ReadFileBlocking(filename, &song);
|
||||
if (result.success() && song.is_valid()) {
|
||||
songs << song;
|
||||
}
|
||||
else {
|
||||
qLog(Error) << "Could not read file" << filename << result.error;
|
||||
}
|
||||
}
|
||||
|
||||
return songs;
|
||||
|
||||
@@ -415,7 +415,7 @@ bool Playlist::setData(const QModelIndex &idx, const QVariant &value, const int
|
||||
if (!set_column_value(song, static_cast<Column>(idx.column()), value)) return false;
|
||||
|
||||
if (song.url().isLocalFile()) {
|
||||
TagReaderReply *reply = TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
||||
TagReaderReply *reply = TagReaderClient::Instance()->WriteFile(song.url().toLocalFile(), song);
|
||||
QPersistentModelIndex persistent_index = QPersistentModelIndex(idx);
|
||||
QObject::connect(reply, &TagReaderReply::Finished, this, [this, reply, persistent_index, item]() { SongSaveComplete(reply, persistent_index, item->OriginalMetadata()); }, Qt::QueuedConnection);
|
||||
}
|
||||
@@ -431,11 +431,16 @@ bool Playlist::setData(const QModelIndex &idx, const QVariant &value, const int
|
||||
void Playlist::SongSaveComplete(TagReaderReply *reply, const QPersistentModelIndex &idx, const Song &old_metadata) {
|
||||
|
||||
if (reply->is_successful() && idx.isValid()) {
|
||||
if (reply->message().save_file_response().success()) {
|
||||
if (reply->message().write_file_response().success()) {
|
||||
ItemReload(idx, old_metadata, true);
|
||||
}
|
||||
else {
|
||||
emit Error(tr("An error occurred writing metadata to '%1'").arg(QString::fromStdString(reply->request_message().save_file_request().filename())));
|
||||
if (reply->request_message().write_file_response().has_error()) {
|
||||
emit Error(tr("Could not write metadata to %1: %2").arg(QString::fromStdString(reply->request_message().write_file_request().filename()), QString::fromStdString(reply->request_message().write_file_response().error())));
|
||||
}
|
||||
else {
|
||||
emit Error(tr("Could not write metadata to %1").arg(QString::fromStdString(reply->request_message().write_file_request().filename())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,12 @@ QUrl SongPlaylistItem::Url() const { return song_.url(); }
|
||||
void SongPlaylistItem::Reload() {
|
||||
|
||||
if (!song_.url().isLocalFile()) return;
|
||||
TagReaderClient::Instance()->ReadFileBlocking(song_.url().toLocalFile(), &song_);
|
||||
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->ReadFileBlocking(song_.url().toLocalFile(), &song_);
|
||||
if (!result.success()) {
|
||||
qLog(Error) << "Could not reload file" << song_.url() << result.error;
|
||||
}
|
||||
|
||||
UpdateTemporaryMetadata(song_);
|
||||
|
||||
}
|
||||
|
||||
@@ -102,7 +102,10 @@ void ParserBase::LoadSong(const QString &filename_or_url, const qint64 beginning
|
||||
}
|
||||
}
|
||||
|
||||
TagReaderClient::Instance()->ReadFileBlocking(filename, song);
|
||||
const TagReaderClient::Result result = TagReaderClient::Instance()->ReadFileBlocking(filename, song);
|
||||
if (!result.success()) {
|
||||
qLog(Error) << "Could not read file" << filename << result.error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -188,12 +188,15 @@ SongList PlaylistParser::LoadFromFile(const QString &filename) const {
|
||||
|
||||
// Open the file
|
||||
QFile file(filename);
|
||||
if (!file.open(QIODevice::ReadOnly)) return SongList();
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
emit Error(tr("Could not open file %1").arg(filename));
|
||||
return SongList();
|
||||
}
|
||||
|
||||
SongList ret = parser->Load(&file, filename, fileinfo.absolutePath());
|
||||
const SongList songs = parser->Load(&file, filename, fileinfo.absolutePath(), true);
|
||||
file.close();
|
||||
|
||||
return ret;
|
||||
return songs;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user