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:
@@ -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(); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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_);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 % "\" />");
|
||||
}
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
Reference in New Issue
Block a user