Improve album cover searching and cover manager, use HttpStatusCodeAttribute and QSslError for services

- Improve album cover manager
- Change art_automatic and art_manual to QUrl
- Refresh collection album covers when new album covers are fetched
- Fix automatic album cover searching for local files outside of the collection
- Make all Json services check HttpStatusCodeAttribute
- Show detailed SSL errors for Subsonic, Tidal and Qobuz
This commit is contained in:
Jonas Kvinge
2019-07-07 21:14:24 +02:00
parent c92a7967ea
commit 65780e1672
101 changed files with 1531 additions and 1239 deletions

View File

@@ -50,7 +50,7 @@
#include "playlist/playlistmanager.h"
#include "covermanager/albumcoverloader.h"
#include "covermanager/coverproviders.h"
#include "covermanager/currentartloader.h"
#include "covermanager/currentalbumcoverloader.h"
#include "covermanager/lastfmcoverprovider.h"
#include "covermanager/discogscoverprovider.h"
#include "covermanager/musicbrainzcoverprovider.h"
@@ -132,7 +132,7 @@ class ApplicationImpl {
app->MoveToNewThread(loader);
return loader;
}),
current_art_loader_([=]() { return new CurrentArtLoader(app, app); }),
current_albumcover_loader_([=]() { return new CurrentAlbumCoverLoader(app, app); }),
lyrics_providers_([=]() {
LyricsProviders *lyrics_providers = new LyricsProviders(app);
lyrics_providers->AddProvider(new AuddLyricsProvider(app));
@@ -182,7 +182,7 @@ class ApplicationImpl {
Lazy<PlaylistManager> playlist_manager_;
Lazy<CoverProviders> cover_providers_;
Lazy<AlbumCoverLoader> album_cover_loader_;
Lazy<CurrentArtLoader> current_art_loader_;
Lazy<CurrentAlbumCoverLoader> current_albumcover_loader_;
Lazy<LyricsProviders> lyrics_providers_;
Lazy<InternetServices> internet_services_;
#ifdef HAVE_TIDAL
@@ -259,7 +259,7 @@ CollectionBackend *Application::collection_backend() const { return collection()
CollectionModel *Application::collection_model() const { return collection()->model(); }
AlbumCoverLoader *Application::album_cover_loader() const { return p_->album_cover_loader_.get(); }
CoverProviders *Application::cover_providers() const { return p_->cover_providers_.get(); }
CurrentArtLoader *Application::current_art_loader() const { return p_->current_art_loader_.get(); }
CurrentAlbumCoverLoader *Application::current_albumcover_loader() const { return p_->current_albumcover_loader_.get(); }
LyricsProviders *Application::lyrics_providers() const { return p_->lyrics_providers_.get(); }
PlaylistBackend *Application::playlist_backend() const { return p_->playlist_backend_.get(); }
PlaylistManager *Application::playlist_manager() const { return p_->playlist_manager_.get(); }

View File

@@ -54,7 +54,7 @@ class DeviceManager;
#endif
class CoverProviders;
class AlbumCoverLoader;
class CurrentArtLoader;
class CurrentAlbumCoverLoader;
class LyricsProviders;
class AudioScrobbler;
class InternetServices;
@@ -92,7 +92,7 @@ class Application : public QObject {
CoverProviders *cover_providers() const;
AlbumCoverLoader *album_cover_loader() const;
CurrentArtLoader *current_art_loader() const;
CurrentAlbumCoverLoader *current_albumcover_loader() const;
LyricsProviders *lyrics_providers() const;

View File

@@ -26,8 +26,9 @@
#include <memory>
#include <QObject>
#include <QAction>
#include <QUrl>
#include <QPixmap>
#include <QAction>
#include "systemtrayicon.h"
@@ -42,7 +43,7 @@ class MacSystemTrayIcon : public SystemTrayIcon {
void SetupMenu(QAction *previous, QAction *play, QAction *stop, QAction *stop_after, QAction *next, QAction *mute, QAction *love, QAction *quit);
void SetNowPlaying(const Song& song, const QString& image_path);
void SetNowPlaying(const Song& song, const QUrl &cover_url);
void ClearNowPlaying();
private:

View File

@@ -28,6 +28,7 @@
#include <QApplication>
#include <QAction>
#include <QIcon>
#include <QUrl>
#include <QtDebug>
#include <AppKit/NSMenu.h>
@@ -205,6 +206,6 @@ void MacSystemTrayIcon::ClearNowPlaying() {
p_->ClearNowPlaying();
}
void MacSystemTrayIcon::SetNowPlaying(const Song& song, const QString& image_path) {
void MacSystemTrayIcon::SetNowPlaying(const Song& song, const QUrl& cover_url) {
p_->ShowNowPlaying(song.artist(), song.PrettyTitle());
}

View File

@@ -122,7 +122,7 @@
#include "covermanager/albumcovermanager.h"
#include "covermanager/albumcoverchoicecontroller.h"
#include "covermanager/albumcoverloader.h"
#include "covermanager/currentartloader.h"
#include "covermanager/currentalbumcoverloader.h"
#ifndef Q_OS_WIN
# include "device/devicemanager.h"
# include "device/devicestatefiltermodel.h"
@@ -251,8 +251,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ui_->menu_help->menuAction()->setVisible(false);
#endif
connect(app_->current_art_loader(), SIGNAL(ArtLoaded(Song, QString, QImage)), SLOT(AlbumArtLoaded(Song, QString, QImage)));
album_cover_choice_controller_->SetApplication(app);
connect(app_->current_albumcover_loader(), SIGNAL(AlbumCoverLoaded(Song, QUrl, QImage)), SLOT(AlbumCoverLoaded(Song, QUrl, QImage)));
album_cover_choice_controller_->Init(app);
connect(album_cover_choice_controller_->cover_from_file_action(), SIGNAL(triggered()), this, SLOT(LoadCoverFromFile()));
connect(album_cover_choice_controller_->cover_to_file_action(), SIGNAL(triggered()), this, SLOT(SaveCoverToFile()));
connect(album_cover_choice_controller_->cover_from_url_action(), SIGNAL(triggered()), this, SLOT(LoadCoverFromURL()));
@@ -263,7 +263,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ui_->multi_loading_indicator->SetTaskManager(app_->task_manager());
context_view_->Init(app_, collection_view_->view(), album_cover_choice_controller_);
ui_->widget_playing->SetApplication(app_, album_cover_choice_controller_);
ui_->widget_playing->Init(app_, album_cover_choice_controller_);
// Initialise the search widget
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
@@ -521,10 +521,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(ui_->track_slider, SIGNAL(Previous()), app_->player(), SLOT(Previous()));
connect(ui_->track_slider, SIGNAL(Next()), app_->player(), SLOT(Next()));
// Context connections
connect(context_view_->albums(), SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
// Collection connections
connect(collection_view_->view(), SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
connect(collection_view_->view(), SIGNAL(ShowConfigDialog()), SLOT(ShowCollectionConfig()));
@@ -576,8 +572,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(tidal_view_->albums_collection_view(), SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
connect(tidal_view_->songs_collection_view(), SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
connect(tidal_view_->search_view(), SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
TidalService *tidalservice = qobject_cast<TidalService*> (app_->internet_services()->ServiceBySource(Song::Source_Tidal));
if (tidalservice)
if (TidalService *tidalservice = qobject_cast<TidalService*> (app_->internet_services()->ServiceBySource(Song::Source_Tidal)))
connect(this, SIGNAL(AuthorisationUrlReceived(const QUrl&)), tidalservice, SLOT(AuthorisationUrlReceived(const QUrl&)));
#endif
@@ -710,6 +705,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(app_->player(), SIGNAL(Playing()), context_view_, SLOT(Playing()));
connect(app_->player(), SIGNAL(Stopped()), context_view_, SLOT(Stopped()));
connect(app_->player(), SIGNAL(Error()), context_view_, SLOT(Error()));
connect(this, SIGNAL(AlbumCoverReady(Song, QUrl, QImage)), context_view_, SLOT(AlbumCoverLoaded(Song, QUrl, QImage)));
connect(this, SIGNAL(SearchCoverInProgress()), context_view_, SLOT(SearchCoverInProgress()));
connect(context_view_->albums(), SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
// Analyzer
connect(ui_->analyzer, SIGNAL(WheelEvent(int)), SLOT(VolumeWheelEvent(int)));
@@ -735,6 +733,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(app_->player(), SIGNAL(Stopped()), ui_->widget_playing, SLOT(Stopped()));
connect(app_->player(), SIGNAL(Error()), ui_->widget_playing, SLOT(Error()));
connect(ui_->widget_playing, SIGNAL(ShowAboveStatusBarChanged(bool)), SLOT(PlayingWidgetPositionChanged(bool)));
connect(this, SIGNAL(AlbumCoverReady(Song, QUrl, QImage)), ui_->widget_playing, SLOT(AlbumCoverLoaded(Song, QUrl, QImage)));
connect(this, SIGNAL(SearchCoverInProgress()), ui_->widget_playing, SLOT(SearchCoverInProgress()));
connect(ui_->action_console, SIGNAL(triggered()), SLOT(ShowConsole()));
PlayingWidgetPositionChanged(ui_->widget_playing->show_above_status_bar());
@@ -942,6 +942,7 @@ void MainWindow::ReloadAllSettings() {
osd_->ReloadSettings();
collection_view_->ReloadSettings();
ui_->playlist->view()->ReloadSettings();
app_->album_cover_loader()->ReloadSettings();
album_cover_choice_controller_->ReloadSettings();
if (cover_manager_.get()) cover_manager_->ReloadSettings();
#ifdef HAVE_TIDAL
@@ -962,6 +963,41 @@ void MainWindow::RefreshStyleSheet() {
setStyleSheet(contents);
}
void MainWindow::SaveSettings() {
SaveGeometry();
SavePlaybackStatus();
ui_->tabs->SaveSettings(kSettingsGroup);
ui_->playlist->view()->SaveGeometry();
ui_->playlist->view()->SaveSettings();
app_->scrobbler()->WriteCache();
QSettings s;
s.beginGroup(kSettingsGroup);
s.setValue("search_for_cover_auto", album_cover_choice_controller_->search_cover_auto_action()->isChecked());
s.endGroup();
}
void MainWindow::Exit() {
SaveSettings();
if (app_->player()->engine()->is_fadeout_enabled()) {
// To shut down the application when fadeout will be finished
connect(app_->player()->engine(), SIGNAL(FadeoutFinishedSignal()), qApp, SLOT(quit()));
if (app_->player()->GetState() == Engine::Playing) {
app_->player()->Stop();
hide();
if (tray_icon_) tray_icon_->SetVisible(false);
return; // Don't quit the application now: wait for the fadeout finished signal
}
}
qApp->quit();
}
void MainWindow::EngineChanged(Engine::EngineType enginetype) {
ui_->action_equalizer->setEnabled(enginetype == Engine::EngineType::GStreamer || enginetype == Engine::EngineType::Xine);
@@ -2331,30 +2367,6 @@ bool MainWindow::winEvent(MSG *msg, long*) {
}
#endif // Q_OS_WIN32
void MainWindow::Exit() {
SaveGeometry();
SavePlaybackStatus();
ui_->tabs->SaveSettings(kSettingsGroup);
ui_->playlist->view()->SaveGeometry();
ui_->playlist->view()->SaveSettings();
app_->scrobbler()->WriteCache();
if (app_->player()->engine()->is_fadeout_enabled()) {
// To shut down the application when fadeout will be finished
connect(app_->player()->engine(), SIGNAL(FadeoutFinishedSignal()), qApp, SLOT(quit()));
if (app_->player()->GetState() == Engine::Playing) {
app_->player()->Stop();
hide();
if (tray_icon_) tray_icon_->SetVisible(false);
return; // Don't quit the application now: wait for the fadeout finished signal
}
}
qApp->quit();
}
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
void MainWindow::AutoCompleteTags() {
@@ -2475,20 +2487,19 @@ void MainWindow::ShowCover() {
void MainWindow::SearchCoverAutomatically() {
QSettings s;
s.beginGroup(kSettingsGroup);
s.setValue("search_for_cover_auto", album_cover_choice_controller_->search_cover_auto_action()->isChecked());
s.endGroup();
GetCoverAutomatically();
}
void MainWindow::AlbumArtLoaded(const Song &song, const QString&, const QImage &image) {
void MainWindow::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image) {
if (song.effective_albumartist() != song_playing_.effective_albumartist() || song.effective_album() != song_playing_.effective_album() || song.title() != song_playing_.title()) return;
song_ = song;
image_original_ = image;
emit AlbumCoverReady(song, cover_url, image);
GetCoverAutomatically();
}
@@ -2497,14 +2508,18 @@ void MainWindow::GetCoverAutomatically() {
// Search for cover automatically?
bool search =
(song_.source() == Song::Source_LocalFile || song_.source() == Song::Source_Collection || song_.source() == Song::Source_CDDA) &&
album_cover_choice_controller_->search_cover_auto_action()->isChecked() &&
!song_.has_manually_unset_cover() &&
song_.art_automatic().isEmpty() &&
song_.art_manual().isEmpty() &&
!song_.art_automatic_is_valid() &&
!song_.art_manual_is_valid() &&
!song_.effective_albumartist().isEmpty() &&
!song_.effective_album().isEmpty();
if (search) album_cover_choice_controller_->SearchCoverAutomatically(song_);
if (search) {
album_cover_choice_controller_->SearchCoverAutomatically(song_);
emit SearchCoverInProgress();
}
}

View File

@@ -127,6 +127,8 @@ class MainWindow : public QMainWindow, public PlatformInterface {
bool LoadUrl(const QString& url);
signals:
void AlbumCoverReady(const Song &song, const QUrl &cover_url, const QImage &image);
void SearchCoverInProgress();
// Signals that stop playing after track was toggled.
void StopAfterToggled(bool stop);
@@ -253,7 +255,7 @@ signals:
void UnsetCover();
void ShowCover();
void SearchCoverAutomatically();
void AlbumArtLoaded(const Song &song, const QString &uri, const QImage &image);
void AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image);
void ScrobblingEnabledChanged(bool value);
void ScrobbleButtonVisibilityChanged(bool value);
@@ -262,6 +264,8 @@ signals:
private:
void SaveSettings();
void ApplyAddBehaviour(BehaviourSettingsPage::AddBehaviour b, MimeData *data) const;
void ApplyPlayBehaviour(BehaviourSettingsPage::PlayBehaviour b, MimeData *data) const;

View File

@@ -55,7 +55,7 @@
#include "playlist/playlistitem.h"
#include "playlist/playlistmanager.h"
#include "playlist/playlistsequence.h"
#include "covermanager/currentartloader.h"
#include "covermanager/currentalbumcoverloader.h"
#include <core/mpris2_player.h>
#include <core/mpris2_playlists.h>
@@ -120,7 +120,7 @@ Mpris2::Mpris2(Application *app, QObject *parent)
return;
}
connect(app_->current_art_loader(), SIGNAL(ArtLoaded(Song,QString,QImage)), SLOT(ArtLoaded(Song,QString)));
connect(app_->current_albumcover_loader(), SIGNAL(AlbumCoverLoaded(Song, QUrl, QImage)), SLOT(AlbumCoverLoaded(Song, QUrl, QImage)));
connect(app_->player()->engine(), SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State)));
connect(app_->player(), SIGNAL(VolumeChanged(int)), SLOT(VolumeChanged()));
@@ -376,7 +376,7 @@ QString Mpris2::current_track_id() const {
// We send Metadata change notification as soon as the process of changing song starts...
void Mpris2::CurrentSongChanged(const Song &song) {
ArtLoaded(song, "");
AlbumCoverLoaded(song, QUrl(), QImage());
EmitNotification("CanPlay");
EmitNotification("CanPause");
EmitNotification("CanGoNext", CanGoNext());
@@ -386,7 +386,7 @@ void Mpris2::CurrentSongChanged(const Song &song) {
}
// ... and we add the cover information later, when it's available.
void Mpris2::ArtLoaded(const Song &song, const QString &art_uri) {
void Mpris2::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image) {
last_metadata_ = QVariantMap();
song.ToXesam(&last_metadata_);
@@ -394,8 +394,8 @@ void Mpris2::ArtLoaded(const Song &song, const QString &art_uri) {
using mpris::AddMetadata;
AddMetadata("mpris:trackid", current_track_id(), &last_metadata_);
if (!art_uri.isEmpty()) {
AddMetadata("mpris:artUrl", art_uri, &last_metadata_);
if (!cover_url.isValid()) {
AddMetadata("mpris:artUrl", cover_url.toLocalFile(), &last_metadata_);
}
AddMetadata("year", song.year(), &last_metadata_);

View File

@@ -207,7 +207,7 @@ signals:
void PlaylistChanged(const MprisPlaylist &playlist);
private slots:
void ArtLoaded(const Song &song, const QString &art_uri);
void AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image);
void EngineStateChanged(Engine::State newState);
void VolumeChanged();

View File

@@ -29,6 +29,7 @@
#include <QMenu>
#include <QIcon>
#include <QString>
#include <QUrl>
#include <QtEvents>
#include <QSettings>
@@ -235,14 +236,14 @@ void QtSystemTrayIcon::SetVisible(bool visible) {
tray_->setVisible(visible);
}
void QtSystemTrayIcon::SetNowPlaying(const Song &song, const QString &image_path) {
void QtSystemTrayIcon::SetNowPlaying(const Song &song, const QUrl &cover_url) {
#ifdef Q_OS_WIN
// Windows doesn't support HTML in tooltips, so just show something basic
tray_->setToolTip(song.PrettyTitleWithArtist());
#else
int columns = image_path == nullptr ? 1 : 2;
int columns = cover_url.isEmpty() ? 1 : 2;
QString tooltip(pattern_);
@@ -260,7 +261,7 @@ void QtSystemTrayIcon::SetNowPlaying(const Song &song, const QString &image_path
tooltip.replace("%lengthValue", song.PrettyLength().toHtmlEscaped());
if (columns == 2) {
QString final_path = image_path.startsWith("file://") ? image_path.mid(7) : image_path;
QString final_path = cover_url.isLocalFile() ? cover_url.path() : cover_url.toString();
if (de_ == "kde") {
tooltip.replace("%image", "<img src=\"" % final_path % "\" />");
}

View File

@@ -28,6 +28,7 @@
#include <QObject>
#include <QSystemTrayIcon>
#include <QString>
#include <QUrl>
#include <QPixmap>
#include <QAction>
#include <QMenu>
@@ -52,7 +53,7 @@ class QtSystemTrayIcon : public SystemTrayIcon {
void ShowPopup(const QString &summary, const QString &message, int timeout);
void SetNowPlaying(const Song &song, const QString &image_path);
void SetNowPlaying(const Song &song, const QUrl &cover_url);
void ClearNowPlaying();
bool MuteEnabled() { return action_mute_->isVisible(); }

View File

@@ -210,8 +210,8 @@ struct Song::Private : public QSharedData {
bool compilation_off_; // Set by the user
// Filenames to album art for this song.
QString art_automatic_; // Guessed by CollectionWatcher
QString art_manual_; // Set by the user - should take priority
QUrl art_automatic_; // Guessed by CollectionWatcher
QUrl art_manual_; // Set by the user - should take priority
QString cue_path_; // If the song has a CUE, this contains it's path.
@@ -325,12 +325,12 @@ int Song::playcount() const { return d->playcount_; }
int Song::skipcount() const { return d->skipcount_; }
int Song::lastplayed() const { return d->lastplayed_; }
const QString &Song::art_automatic() const { return d->art_automatic_; }
const QString &Song::art_manual() const { return d->art_manual_; }
bool Song::has_manually_unset_cover() const { return d->art_manual_ == kManuallyUnsetCover; }
void Song::manually_unset_cover() { d->art_manual_ = kManuallyUnsetCover; }
bool Song::has_embedded_cover() const { return d->art_automatic_ == kEmbeddedCover; }
void Song::set_embedded_cover() { d->art_automatic_ = kEmbeddedCover; }
const QUrl &Song::art_automatic() const { return d->art_automatic_; }
const QUrl &Song::art_manual() const { return d->art_manual_; }
bool Song::has_manually_unset_cover() const { return d->art_manual_.path() == kManuallyUnsetCover; }
void Song::manually_unset_cover() { d->art_manual_.clear(); d->art_manual_.setPath(kManuallyUnsetCover); }
bool Song::has_embedded_cover() const { return d->art_automatic_.path() == kEmbeddedCover; }
void Song::set_embedded_cover() { d->art_automatic_.clear(); d->art_automatic_.setPath(kEmbeddedCover); }
const QImage &Song::image() const { return d->image_; }
const QString &Song::cue_path() const { return d->cue_path_; }
@@ -341,6 +341,26 @@ bool Song::is_metadata_good() const { return !d->title_.isEmpty() && !d->album_.
bool Song::is_stream() const { return d->source_ == Source_Stream || d->source_ == Source_Tidal || d->source_ == Source_Subsonic || d->source_ == Source_Qobuz; }
bool Song::is_cdda() const { return d->source_ == Source_CDDA; }
bool Song::art_automatic_is_valid() const {
return (
(d->art_automatic_.path() == kManuallyUnsetCover) ||
(d->art_automatic_.path() == kEmbeddedCover) ||
(d->art_automatic_.isValid() && !d->art_automatic_.isLocalFile()) ||
(d->art_automatic_.isLocalFile() && QFile::exists(d->art_automatic_.toLocalFile())) ||
(d->art_automatic_.scheme().isEmpty() && !d->art_automatic_.path().isEmpty() && QFile::exists(d->art_automatic_.path()))
);
}
bool Song::art_manual_is_valid() const {
return (
(d->art_manual_.path() == kManuallyUnsetCover) ||
(d->art_manual_.path() == kEmbeddedCover) ||
(d->art_manual_.isValid() && !d->art_manual_.isLocalFile()) ||
(d->art_manual_.isLocalFile() && QFile::exists(d->art_manual_.toLocalFile())) ||
(d->art_manual_.scheme().isEmpty() && !d->art_manual_.path().isEmpty() && QFile::exists(d->art_manual_.path()))
);
}
const QString &Song::error() const { return d->error_; }
void Song::set_id(int id) { d->id_ = id; }
@@ -415,8 +435,8 @@ void Song::set_compilation_detected(bool v) { d->compilation_detected_ = v; }
void Song::set_compilation_on(bool v) { d->compilation_on_ = v; }
void Song::set_compilation_off(bool v) { d->compilation_off_ = v; }
void Song::set_art_automatic(const QString &v) { d->art_automatic_ = v; }
void Song::set_art_manual(const QString &v) { d->art_manual_ = v; }
void Song::set_art_automatic(const QUrl &v) { d->art_automatic_ = v; }
void Song::set_art_manual(const QUrl &v) { d->art_manual_ = v; }
void Song::set_cue_path(const QString &v) { d->cue_path_ = v; }
void Song::set_image(const QImage &i) { d->image_ = i; }
@@ -677,7 +697,7 @@ void Song::InitFromProtobuf(const pb::tagreader::SongMetadata &pb) {
}
if (pb.has_art_automatic()) {
d->art_automatic_ = QStringFromStdString(pb.art_automatic());
set_art_automatic(QUrl::fromEncoded(QByteArray(pb.art_automatic().data(), pb.art_automatic().size())));
}
InitArtManual();
@@ -687,6 +707,7 @@ void Song::InitFromProtobuf(const pb::tagreader::SongMetadata &pb) {
void Song::ToProtobuf(pb::tagreader::SongMetadata *pb) const {
const QByteArray url(d->url_.toEncoded());
const QByteArray art_automatic(d->art_automatic_.toEncoded());
pb->set_valid(d->valid_);
pb->set_title(DataCommaSizeFromQString(d->title_));
@@ -717,7 +738,7 @@ void Song::ToProtobuf(pb::tagreader::SongMetadata *pb) const {
pb->set_ctime(d->ctime_);
pb->set_filesize(d->filesize_);
pb->set_suspicious_tags(d->suspicious_tags_);
pb->set_art_automatic(DataCommaSizeFromQString(d->art_automatic_));
pb->set_art_automatic(art_automatic.constData(), art_automatic.size());
pb->set_filetype(static_cast<pb::tagreader::SongMetadata_FileType>(d->filetype_));
}
@@ -866,10 +887,10 @@ void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) {
}
else if (Song::kColumns.value(i) == "art_automatic") {
d->art_automatic_ = q.value(x).toString();
set_art_automatic(QUrl::fromEncoded(tostr(x).toUtf8()));
}
else if (Song::kColumns.value(i) == "art_manual") {
d->art_manual_ = q.value(x).toString();
set_art_manual(QUrl::fromEncoded(tostr(x).toUtf8()));
}
else if (Song::kColumns.value(i) == "effective_albumartist") {
@@ -927,9 +948,10 @@ void Song::InitArtManual() {
// If we don't have an art, check if we have one in the cache
if (d->art_manual_.isEmpty() && d->art_automatic_.isEmpty()) {
QString filename(Utilities::Sha1CoverHash(d->artist_, album2).toHex() + ".jpg");
QString path(AlbumCoverLoader::ImageCacheDir() + "/" + filename);
QString path(AlbumCoverLoader::ImageCacheDir(d->source_) + "/" + filename);
if (QFile::exists(path)) {
d->art_manual_ = path;
d->art_manual_.setScheme("file");
d->art_manual_.setPath(path);
}
}
@@ -1117,7 +1139,7 @@ void Song::MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle &bundle) {
if (!bundle.genre.isEmpty()) d->genre_ = bundle.genre;
if (bundle.length > 0) set_length_nanosec(bundle.length);
if (bundle.year > 0) d->year_ = bundle.year;
if (bundle.tracknr > 0) d->track_ = bundle.tracknr;
if (bundle.track > 0) d->track_ = bundle.track;
if (bundle.filetype != FileType_Unknown) d->filetype_ = bundle.filetype;
if (bundle.samplerate > 0) d->samplerate_ = bundle.samplerate;
if (bundle.bitdepth > 0) d->samplerate_ = bundle.bitdepth;

View File

@@ -228,8 +228,8 @@ class Song {
int skipcount() const;
int lastplayed() const;
const QString &art_automatic() const;
const QString &art_manual() const;
const QUrl &art_automatic() const;
const QUrl &art_manual() const;
const QString &cue_path() const;
bool has_cue() const;
@@ -242,6 +242,8 @@ class Song {
bool is_stream() const;
bool is_cdda() const;
bool is_metadata_good() const;
bool art_automatic_is_valid() const;
bool art_manual_is_valid() const;
// Playlist views are special because you don't want to fill in album artists automatically for compilations, but you do for normal albums:
const QString &playlist_albumartist() const;
@@ -324,8 +326,8 @@ class Song {
void set_compilation_on(bool v);
void set_compilation_off(bool v);
void set_art_automatic(const QString &v);
void set_art_manual(const QString &v);
void set_art_automatic(const QUrl &v);
void set_art_manual(const QUrl &v);
void set_cue_path(const QString &v);

View File

@@ -40,7 +40,7 @@ StandardItemIconLoader::StandardItemIconLoader(AlbumCoverLoader *cover_loader, Q
cover_options_.desired_height_ = 16;
connect(cover_loader_, SIGNAL(ImageLoaded(quint64, QImage)), SLOT(ImageLoaded(quint64, QImage)));
connect(cover_loader_, SIGNAL(ImageLoaded(quint64, QUrl, QImage)), SLOT(ImageLoaded(quint64, QUrl, QImage)));
}
void StandardItemIconLoader::SetModel(QAbstractItemModel *model) {
@@ -56,7 +56,7 @@ void StandardItemIconLoader::SetModel(QAbstractItemModel *model) {
}
void StandardItemIconLoader::LoadIcon(const QString &art_automatic, const QString &art_manual, QStandardItem *for_item) {
void StandardItemIconLoader::LoadIcon(const QUrl &art_automatic, const QUrl &art_manual, QStandardItem *for_item) {
const quint64 id = cover_loader_->LoadImageAsync(cover_options_, art_automatic, art_manual);
pending_covers_[id] = for_item;
@@ -92,7 +92,7 @@ void StandardItemIconLoader::ModelReset() {
}
void StandardItemIconLoader::ImageLoaded(quint64 id, const QImage &image) {
void StandardItemIconLoader::ImageLoaded(const quint64 id, const QUrl &cover_url, const QImage &image) {
QStandardItem *item = pending_covers_.take(id);
if (!item) return;

View File

@@ -49,11 +49,11 @@ class StandardItemIconLoader : public QObject {
void SetModel(QAbstractItemModel *model);
void LoadIcon(const QString &art_automatic, const QString &art_manual, QStandardItem *for_item);
void LoadIcon(const QUrl &art_automatic, const QUrl &art_manual, QStandardItem *for_item);
void LoadIcon(const Song &song, QStandardItem *for_item);
private slots:
void ImageLoaded(quint64 id, const QImage &image);
void ImageLoaded(const quint64 id, const QUrl &cover_url, const QImage &image);
void RowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end);
void ModelReset();

View File

@@ -47,7 +47,7 @@ class SystemTrayIcon : public QObject {
// Called by the OSD
virtual void ShowPopup(const QString &summary, const QString &message, int timeout) {}
// If this get's invoked with image_path equal to nullptr, the tooltip should still be shown - just without the cover art.
virtual void SetNowPlaying(const Song &song, const QString &image_path) {}
virtual void SetNowPlaying(const Song &song, const QUrl &cover_url) {}
virtual void ClearNowPlaying() {}
virtual bool MuteEnabled() { return false; }