Improve album cover loader, lyrics search and streaming support
- Improve album cover loader - Add album cover loader result struct - Move album cover thumbnail scaling to album cover loader - Make init art manual look for album cover images in song directory - Make album cover search work for songs outside of collection and streams - Make album cover search work based on artist + title if album is not present - Update art manual in playlist for local files, devices and CDDA - Make lyrics search work for streams - Add stream dialog to menu - Remove dead code in InternetSearchModel - Simplify code in InternetSearchView
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||
* Copyright 2013-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -96,6 +96,7 @@
|
||||
#include "dialogs/console.h"
|
||||
#include "dialogs/trackselectiondialog.h"
|
||||
#include "dialogs/edittagdialog.h"
|
||||
#include "dialogs/addstreamdialog.h"
|
||||
#include "organise/organisedialog.h"
|
||||
#include "widgets/fancytabwidget.h"
|
||||
#include "widgets/playingwidget.h"
|
||||
@@ -131,7 +132,7 @@
|
||||
#endif
|
||||
#include "covermanager/albumcovermanager.h"
|
||||
#include "covermanager/albumcoverchoicecontroller.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
#include "covermanager/albumcoverloaderresult.h"
|
||||
#include "covermanager/currentalbumcoverloader.h"
|
||||
#ifndef Q_OS_WIN
|
||||
# include "device/devicemanager.h"
|
||||
@@ -178,10 +179,6 @@
|
||||
# include "windows7thumbbar.h"
|
||||
#endif
|
||||
|
||||
using std::bind;
|
||||
using std::floor;
|
||||
using std::stable_sort;
|
||||
|
||||
const char *MainWindow::kSettingsGroup = "MainWindow";
|
||||
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
|
||||
|
||||
@@ -231,6 +228,11 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
TranscodeDialog *dialog = new TranscodeDialog(this);
|
||||
return dialog;
|
||||
}),
|
||||
add_stream_dialog_([=]() {
|
||||
AddStreamDialog *add_stream_dialog = new AddStreamDialog;
|
||||
connect(add_stream_dialog, SIGNAL(accepted()), this, SLOT(AddStreamAccepted()));
|
||||
return add_stream_dialog;
|
||||
}),
|
||||
#ifdef HAVE_SUBSONIC
|
||||
subsonic_view_(new InternetSongsView(app_, app->internet_services()->ServiceBySource(Song::Source_Subsonic), SubsonicSettingsPage::kSettingsGroup, SettingsDialog::Page_Subsonic, this)),
|
||||
#endif
|
||||
@@ -260,7 +262,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
// Initialise the UI
|
||||
ui_->setupUi(this);
|
||||
|
||||
connect(app_->current_albumcover_loader(), SIGNAL(AlbumCoverLoaded(Song, QUrl, QImage)), SLOT(AlbumCoverLoaded(Song, QUrl, QImage)));
|
||||
connect(app_->current_albumcover_loader(), SIGNAL(AlbumCoverLoaded(Song, AlbumCoverLoaderResult)), SLOT(AlbumCoverLoaded(Song, AlbumCoverLoaderResult)));
|
||||
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()));
|
||||
@@ -361,6 +363,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
|
||||
ui_->action_add_file->setIcon(IconLoader::Load("document-open"));
|
||||
ui_->action_add_folder->setIcon(IconLoader::Load("document-open-folder"));
|
||||
ui_->action_add_stream->setIcon(IconLoader::Load("document-open-remote"));
|
||||
ui_->action_shuffle_mode->setIcon(IconLoader::Load("media-playlist-shuffle"));
|
||||
ui_->action_repeat_mode->setIcon(IconLoader::Load("media-playlist-repeat"));
|
||||
ui_->action_new_playlist->setIcon(IconLoader::Load("document-new"));
|
||||
@@ -431,6 +434,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
connect(ui_->action_open_cd, SIGNAL(triggered()), SLOT(AddCDTracks()));
|
||||
connect(ui_->action_add_file, SIGNAL(triggered()), SLOT(AddFile()));
|
||||
connect(ui_->action_add_folder, SIGNAL(triggered()), SLOT(AddFolder()));
|
||||
connect(ui_->action_add_stream, SIGNAL(triggered()), SLOT(AddStream()));
|
||||
connect(ui_->action_cover_manager, SIGNAL(triggered()), SLOT(ShowCoverManager()));
|
||||
connect(ui_->action_equalizer, SIGNAL(triggered()), equalizer_.get(), SLOT(show()));
|
||||
#if defined(HAVE_GSTREAMER)
|
||||
@@ -705,7 +709,7 @@ 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(AlbumCoverReady(Song, QImage)), context_view_, SLOT(AlbumCoverLoaded(Song, QImage)));
|
||||
connect(this, SIGNAL(SearchCoverInProgress()), context_view_->album_widget(), SLOT(SearchCoverInProgress()));
|
||||
connect(context_view_, SIGNAL(AlbumEnabledChanged()), SLOT(TabSwitched()));
|
||||
connect(context_view_->albums_widget(), SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
|
||||
@@ -738,7 +742,7 @@ 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(AlbumCoverReady(Song, QImage)), ui_->widget_playing, SLOT(AlbumCoverLoaded(Song, QImage)));
|
||||
connect(this, SIGNAL(SearchCoverInProgress()), ui_->widget_playing, SLOT(SearchCoverInProgress()));
|
||||
|
||||
connect(ui_->action_console, SIGNAL(triggered()), SLOT(ShowConsole()));
|
||||
@@ -1777,7 +1781,7 @@ void MainWindow::EditTracks() {
|
||||
|
||||
void MainWindow::EditTagDialogAccepted() {
|
||||
|
||||
for (const PlaylistItemPtr item : edit_tag_dialog_->playlist_items()) {
|
||||
for (PlaylistItemPtr item : edit_tag_dialog_->playlist_items()) {
|
||||
item->Reload();
|
||||
}
|
||||
|
||||
@@ -1923,6 +1927,16 @@ void MainWindow::AddCDTracks() {
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::AddStream() { add_stream_dialog_->show(); }
|
||||
|
||||
void MainWindow::AddStreamAccepted() {
|
||||
|
||||
MimeData* data = new MimeData;
|
||||
data->setUrls(QList<QUrl>() << add_stream_dialog_->url());
|
||||
AddToPlaylist(data);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::ShowInCollection() {
|
||||
|
||||
// Show the first valid selected track artist/album in CollectionView
|
||||
@@ -2512,7 +2526,7 @@ void MainWindow::AutoCompleteTags() {
|
||||
|
||||
void MainWindow::AutoCompleteTagsAccepted() {
|
||||
|
||||
for (const PlaylistItemPtr item : autocomplete_tag_items_) {
|
||||
for (PlaylistItemPtr item : autocomplete_tag_items_) {
|
||||
item->Reload();
|
||||
}
|
||||
autocomplete_tag_items_.clear();
|
||||
@@ -2600,14 +2614,14 @@ void MainWindow::SearchCoverAutomatically() {
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image) {
|
||||
void MainWindow::AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &result) {
|
||||
|
||||
if (song.effective_albumartist() != song_playing_.effective_albumartist() || song.effective_album() != song_playing_.effective_album() || song.title() != song_playing_.title()) return;
|
||||
if (song != song_playing_) return;
|
||||
|
||||
song_ = song;
|
||||
image_original_ = image;
|
||||
image_original_ = result.image_original;
|
||||
|
||||
emit AlbumCoverReady(song, cover_url, image);
|
||||
emit AlbumCoverReady(song, result.image_original);
|
||||
|
||||
GetCoverAutomatically();
|
||||
|
||||
@@ -2617,13 +2631,12 @@ void MainWindow::GetCoverAutomatically() {
|
||||
|
||||
// Search for cover automatically?
|
||||
bool search =
|
||||
song_.source() == Song::Source_Collection &&
|
||||
album_cover_choice_controller_->search_cover_auto_action()->isChecked() &&
|
||||
!song_.has_manually_unset_cover() &&
|
||||
!song_.art_automatic_is_valid() &&
|
||||
!song_.art_manual_is_valid() &&
|
||||
!song_.effective_albumartist().isEmpty() &&
|
||||
!song_.effective_album().isEmpty();
|
||||
album_cover_choice_controller_->search_cover_auto_action()->isChecked() &&
|
||||
!song_.has_manually_unset_cover() &&
|
||||
!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_);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||
* Copyright 2013-2020, 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
|
||||
@@ -59,8 +59,7 @@
|
||||
#include "playlist/playlistitem.h"
|
||||
#include "settings/settingsdialog.h"
|
||||
#include "settings/behavioursettingspage.h"
|
||||
|
||||
using std::unique_ptr;
|
||||
#include "covermanager/albumcoverloaderresult.h"
|
||||
|
||||
class About;
|
||||
class AlbumCoverManager;
|
||||
@@ -95,6 +94,7 @@ class InternetTabsView;
|
||||
#ifdef Q_OS_WIN
|
||||
class Windows7ThumbBar;
|
||||
#endif
|
||||
class AddStreamDialog;
|
||||
|
||||
class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
Q_OBJECT
|
||||
@@ -126,7 +126,7 @@ 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 AlbumCoverReady(const Song &song, const QImage &image);
|
||||
void SearchCoverInProgress();
|
||||
// Signals that stop playing after track was toggled.
|
||||
void StopAfterToggled(bool stop);
|
||||
@@ -210,6 +210,8 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
void AddFile();
|
||||
void AddFolder();
|
||||
void AddCDTracks();
|
||||
void AddStream();
|
||||
void AddStreamAccepted();
|
||||
|
||||
void CommandlineOptionsReceived(const quint32 instanceId, const QByteArray &string_options);
|
||||
|
||||
@@ -251,7 +253,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
void UnsetCover();
|
||||
void ShowCover();
|
||||
void SearchCoverAutomatically();
|
||||
void AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image);
|
||||
void AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &result);
|
||||
|
||||
void ScrobblingEnabledChanged(const bool value);
|
||||
void ScrobbleButtonVisibilityChanged(const bool value);
|
||||
@@ -308,6 +310,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
#ifdef HAVE_GSTREAMER
|
||||
Lazy<TranscodeDialog> transcode_dialog_;
|
||||
#endif
|
||||
Lazy<AddStreamDialog> add_stream_dialog_;
|
||||
|
||||
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
||||
std::unique_ptr<TagFetcher> tag_fetcher_;
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
</property>
|
||||
<addaction name="action_add_file"/>
|
||||
<addaction name="action_add_folder"/>
|
||||
<addaction name="action_add_stream"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_shuffle_mode"/>
|
||||
<addaction name="action_repeat_mode"/>
|
||||
@@ -827,6 +828,11 @@
|
||||
<string>Rescan songs(s)</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_add_stream">
|
||||
<property name="text">
|
||||
<string>Add stream...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "collection/directory.h"
|
||||
#include "playlist/playlistitem.h"
|
||||
#include "playlist/playlistsequence.h"
|
||||
#include "covermanager/albumcoverloaderresult.h"
|
||||
#include "covermanager/albumcoverfetcher.h"
|
||||
#include "equalizer/equalizer.h"
|
||||
|
||||
@@ -98,6 +99,8 @@ void RegisterMetaTypes() {
|
||||
qRegisterMetaType<QList<PlaylistItemPtr> >("QList<PlaylistItemPtr>");
|
||||
qRegisterMetaType<PlaylistSequence::RepeatMode>("PlaylistSequence::RepeatMode");
|
||||
qRegisterMetaType<PlaylistSequence::ShuffleMode>("PlaylistSequence::ShuffleMode");
|
||||
qRegisterMetaType<AlbumCoverLoaderResult>("AlbumCoverLoaderResult");
|
||||
qRegisterMetaType<AlbumCoverLoaderResult::Type>("AlbumCoverLoaderResult::Type");
|
||||
qRegisterMetaType<CoverSearchResult>("CoverSearchResult");
|
||||
qRegisterMetaType<QList<CoverSearchResult> >("QList<CoverSearchResult>");
|
||||
qRegisterMetaType<CoverSearchResults>("CoverSearchResults");
|
||||
|
||||
@@ -58,14 +58,13 @@
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "playlist/playlistsequence.h"
|
||||
#include "covermanager/currentalbumcoverloader.h"
|
||||
#include "covermanager/albumcoverloaderresult.h"
|
||||
|
||||
#include <core/mpris2_player.h>
|
||||
#include <core/mpris2_playlists.h>
|
||||
#include <core/mpris2_root.h>
|
||||
#include <core/mpris2_tracklist.h>
|
||||
|
||||
using std::reverse;
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &arg, const MprisPlaylist &playlist) {
|
||||
arg.beginStructure();
|
||||
arg << playlist.id << playlist.name << playlist.icon;
|
||||
@@ -122,7 +121,7 @@ Mpris2::Mpris2(Application *app, QObject *parent)
|
||||
return;
|
||||
}
|
||||
|
||||
connect(app_->current_albumcover_loader(), SIGNAL(AlbumCoverLoaded(Song, QUrl, QImage)), SLOT(AlbumCoverLoaded(Song, QUrl, QImage)));
|
||||
connect(app_->current_albumcover_loader(), SIGNAL(AlbumCoverLoaded(Song, AlbumCoverLoaderResult)), SLOT(AlbumCoverLoaded(Song, AlbumCoverLoaderResult)));
|
||||
|
||||
connect(app_->player()->engine(), SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State)));
|
||||
connect(app_->player(), SIGNAL(VolumeChanged(int)), SLOT(VolumeChanged()));
|
||||
@@ -378,7 +377,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) {
|
||||
|
||||
AlbumCoverLoaded(song, QUrl(), QImage());
|
||||
AlbumCoverLoaded(song);
|
||||
EmitNotification("CanPlay");
|
||||
EmitNotification("CanPause");
|
||||
EmitNotification("CanGoNext", CanGoNext());
|
||||
@@ -388,9 +387,7 @@ void Mpris2::CurrentSongChanged(const Song &song) {
|
||||
}
|
||||
|
||||
// ... and we add the cover information later, when it's available.
|
||||
void Mpris2::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image) {
|
||||
|
||||
Q_UNUSED(image);
|
||||
void Mpris2::AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &result) {
|
||||
|
||||
last_metadata_ = QVariantMap();
|
||||
song.ToXesam(&last_metadata_);
|
||||
@@ -398,9 +395,14 @@ void Mpris2::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QIm
|
||||
using mpris::AddMetadata;
|
||||
AddMetadata("mpris:trackid", current_track_id(), &last_metadata_);
|
||||
|
||||
if (cover_url.isValid()) {
|
||||
AddMetadata("mpris:artUrl", cover_url.toString(), &last_metadata_);
|
||||
QUrl cover_url;
|
||||
if (result.cover_url.isValid() && result.cover_url.isLocalFile()) {
|
||||
cover_url = result.cover_url;
|
||||
}
|
||||
else if (result.temp_cover_url.isValid() && result.temp_cover_url.isLocalFile()) {
|
||||
cover_url = result.temp_cover_url;
|
||||
}
|
||||
if (cover_url.isValid()) AddMetadata("mpris:artUrl", result.cover_url.toString(), &last_metadata_);
|
||||
|
||||
AddMetadata("year", song.year(), &last_metadata_);
|
||||
AddMetadata("bitrate", song.bitrate(), &last_metadata_);
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "engine/engine_fwd.h"
|
||||
#include "covermanager/albumcoverloaderresult.h"
|
||||
|
||||
class Application;
|
||||
class Song;
|
||||
@@ -204,7 +205,7 @@ signals:
|
||||
void PlaylistChanged(const MprisPlaylist &playlist);
|
||||
|
||||
private slots:
|
||||
void AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image);
|
||||
void AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &result = AlbumCoverLoaderResult());
|
||||
void EngineStateChanged(Engine::State newState);
|
||||
void VolumeChanged();
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QSharedData>
|
||||
#include <QHash>
|
||||
#include <QByteArray>
|
||||
@@ -42,6 +43,7 @@
|
||||
#include <QIcon>
|
||||
#include <QTextCodec>
|
||||
#include <QSqlQuery>
|
||||
#include <QStandardPaths>
|
||||
#include <QtDebug>
|
||||
|
||||
#ifdef HAVE_LIBGPOD
|
||||
@@ -66,7 +68,6 @@
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
#include "tagreadermessages.pb.h"
|
||||
|
||||
using std::sort;
|
||||
#ifndef USE_SYSTEM_TAGLIB
|
||||
using namespace Strawberry_TagLib;
|
||||
#endif
|
||||
@@ -353,7 +354,8 @@ bool Song::is_cdda() const { return d->source_ == Source_CDDA; }
|
||||
bool Song::is_compilation() const { return (d->compilation_ || d->compilation_detected_ || d->compilation_on_) && !d->compilation_off_; }
|
||||
|
||||
bool Song::art_automatic_is_valid() const {
|
||||
return (
|
||||
return !d->art_automatic_.isEmpty() &&
|
||||
(
|
||||
(d->art_automatic_.path() == kManuallyUnsetCover) ||
|
||||
(d->art_automatic_.path() == kEmbeddedCover) ||
|
||||
(d->art_automatic_.isValid() && !d->art_automatic_.isLocalFile()) ||
|
||||
@@ -363,7 +365,8 @@ bool Song::art_automatic_is_valid() const {
|
||||
}
|
||||
|
||||
bool Song::art_manual_is_valid() const {
|
||||
return (
|
||||
return !d->art_manual_.isEmpty() &&
|
||||
(
|
||||
(d->art_manual_.path() == kManuallyUnsetCover) ||
|
||||
(d->art_manual_.path() == kEmbeddedCover) ||
|
||||
(d->art_manual_.isValid() && !d->art_manual_.isLocalFile()) ||
|
||||
@@ -655,6 +658,29 @@ Song::FileType Song::FiletypeByExtension(const QString &ext) {
|
||||
|
||||
}
|
||||
|
||||
QString Song::ImageCacheDir(const Song::Source source) {
|
||||
|
||||
switch (source) {
|
||||
case Song::Source_Collection:
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/collectionalbumcovers";
|
||||
case Song::Source_Subsonic:
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/subsonicalbumcovers";
|
||||
case Song::Source_Tidal:
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/tidalalbumcovers";
|
||||
case Song::Source_Qobuz:
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/qobuzalbumcovers";
|
||||
case Song::Source_LocalFile:
|
||||
case Song::Source_CDDA:
|
||||
case Song::Source_Device:
|
||||
case Song::Source_Stream:
|
||||
case Song::Source_Unknown:
|
||||
return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/albumcovers";
|
||||
}
|
||||
|
||||
return QString();
|
||||
|
||||
}
|
||||
|
||||
int CompareSongsName(const Song &song1, const Song &song2) {
|
||||
return song1.PrettyTitleWithArtist().localeAwareCompare(song2.PrettyTitleWithArtist()) < 0;
|
||||
}
|
||||
@@ -997,16 +1023,24 @@ void Song::InitFromFilePartial(const QString &filename) {
|
||||
|
||||
void Song::InitArtManual() {
|
||||
|
||||
QString album = d->album_;
|
||||
QString album = effective_album();
|
||||
album.remove(Song::kAlbumRemoveDisc);
|
||||
|
||||
// If we don't have an art, check if we have one in the cache
|
||||
if (d->art_manual_.isEmpty() && d->art_automatic_.isEmpty()) {
|
||||
if (d->art_manual_.isEmpty() && d->art_automatic_.isEmpty() && !effective_albumartist().isEmpty() && !album.isEmpty()) {
|
||||
QString filename(Utilities::Sha1CoverHash(effective_albumartist(), album).toHex() + ".jpg");
|
||||
QString path(AlbumCoverLoader::ImageCacheDir(d->source_) + "/" + filename);
|
||||
QString path(ImageCacheDir(d->source_) + "/" + filename);
|
||||
if (QFile::exists(path)) {
|
||||
d->art_manual_ = QUrl::fromLocalFile(path);
|
||||
}
|
||||
else if (d->url_.isLocalFile()) { // Pick the first image file in the album directory.
|
||||
QFileInfo file(d->url_.toLocalFile());
|
||||
QDir dir(file.path());
|
||||
QStringList files = dir.entryList(QStringList() << "*.jpg" << "*.png" << "*.gif" << "*.jpeg", QDir::Files|QDir::Readable, QDir::Name);
|
||||
if (files.count() > 0) {
|
||||
d->art_manual_ = QUrl::fromLocalFile(file.path() + QDir::separator() + files.first());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ class Song {
|
||||
static FileType FiletypeByMimetype(const QString &mimetype);
|
||||
static FileType FiletypeByDescription(const QString &text);
|
||||
static FileType FiletypeByExtension(const QString &ext);
|
||||
static QString ImageCacheDir(const Song::Source source);
|
||||
|
||||
// Sort songs alphabetically using their pretty title
|
||||
static void SortSongsListAlphabetically(QList<Song> *songs);
|
||||
|
||||
@@ -40,7 +40,7 @@ StandardItemIconLoader::StandardItemIconLoader(AlbumCoverLoader *cover_loader, Q
|
||||
|
||||
cover_options_.desired_height_ = 16;
|
||||
|
||||
connect(cover_loader_, SIGNAL(ImageLoaded(quint64, QUrl, QImage)), SLOT(ImageLoaded(quint64, QUrl, QImage)));
|
||||
connect(cover_loader_, SIGNAL(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)), SLOT(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)));
|
||||
}
|
||||
|
||||
void StandardItemIconLoader::SetModel(QAbstractItemModel *model) {
|
||||
@@ -96,15 +96,13 @@ void StandardItemIconLoader::ModelReset() {
|
||||
|
||||
}
|
||||
|
||||
void StandardItemIconLoader::ImageLoaded(const quint64 id, const QUrl &cover_url, const QImage &image) {
|
||||
|
||||
Q_UNUSED(cover_url);
|
||||
void StandardItemIconLoader::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult result) {
|
||||
|
||||
QStandardItem *item = pending_covers_.take(id);
|
||||
if (!item) return;
|
||||
|
||||
if (!image.isNull()) {
|
||||
item->setIcon(QIcon(QPixmap::fromImage(image)));
|
||||
if (!result.image_scaled.isNull()) {
|
||||
item->setIcon(QIcon(QPixmap::fromImage(result.image_scaled)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QUrl>
|
||||
#include <QImage>
|
||||
|
||||
#include "covermanager/albumcoverloaderoptions.h"
|
||||
#include "covermanager/albumcoverloaderresult.h"
|
||||
|
||||
class QAbstractItemModel;
|
||||
class QStandardItem;
|
||||
@@ -52,12 +54,12 @@ class StandardItemIconLoader : public QObject {
|
||||
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(const quint64 id, const QUrl &cover_url, const QImage &image);
|
||||
private slots:
|
||||
void AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult result);
|
||||
void RowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end);
|
||||
void ModelReset();
|
||||
|
||||
private:
|
||||
private:
|
||||
AlbumCoverLoader *cover_loader_;
|
||||
AlbumCoverLoaderOptions cover_options_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user