Files
cantata/lyrics/lyricspage.cpp
2011-11-30 20:07:06 +00:00

233 lines
6.5 KiB
C++

#include "songinfoprovider.h"
#include "lyricspage.h"
#include "ultimatelyricsprovider.h"
#include "ultimatelyricsreader.h"
#include "musiclibrarymodel.h"
#include <QFuture>
#include <QFutureWatcher>
#include <QSettings>
#include <QtConcurrentRun>
#include <QTextBrowser>
#include <QFile>
#include <QDir>
#include <QIcon>
#include <QToolButton>
#ifdef ENABLE_KDE_SUPPORT
#include <KDE/KAction>
#include <KDE/KLocale>
#include <KDE/KXMLGUIClient>
#include <KDE/KActionCollection>
#endif
static QString changeExt(const QString &f, const QString &newExt)
{
QString newStr(f);
int dotPos(newStr.lastIndexOf('.'));
if (-1==dotPos) {
newStr+=newExt;
} else {
newStr.remove(dotPos, newStr.length());
newStr+=newExt;
}
return newStr;
}
static const QLatin1String constLyricsDir("lyrics/");
static const QLatin1String constExtension(".lyrics");
static QString cacheFile(QString artist, QString title, bool createDir=false)
{
title.replace("/", "_");
artist.replace("/", "_");
return QDir::toNativeSeparators(MusicLibraryModel::cacheDir(constLyricsDir+artist+'/', createDir))+title+constExtension;
}
typedef QList<UltimateLyricsProvider *> ProviderList;
bool CompareLyricProviders(const UltimateLyricsProvider* a, const UltimateLyricsProvider* b) {
return a->relevance() < b->relevance();
}
LyricsPage::LyricsPage(QWidget *parent)
: QWidget(parent)
// , reader(new UltimateLyricsReader(this))
, currentRequest(0)
{
setupUi(this);
providers=UltimateLyricsReader().Parse(QString(":lyrics/ultimate_providers.xml"));
foreach (UltimateLyricsProvider* provider, providers) {
connect(provider, SIGNAL(InfoReady(int, const QString &)), SLOT(resultReady(int, const QString &)));
}
// Parse the ultimate lyrics xml file in the background
// QFuture<ProviderList> future = QtConcurrent::run(reader.data(), &UltimateLyricsReader::Parse,
// QString(":lyrics/ultimate_providers.xml"));
// QFutureWatcher<ProviderList> *watcher = new QFutureWatcher<ProviderList>(this);
// watcher->setFuture(future);
// connect(watcher, SIGNAL(finished()), SLOT(ultimateLyricsParsed()));
#ifdef ENABLE_KDE_SUPPORT
KXMLGUIClient *client=dynamic_cast<KXMLGUIClient *>(parent);
if (client) {
refreshAction = client->actionCollection()->addAction("refreshlyrics");
} else {
refreshAction = new KAction(this);
}
refreshAction->setText(i18n("Refresh Lyrics"));
#else
refreshAction = new QAction(tr("Refresh Lyrics"), this);
#endif
refreshAction->setIcon(QIcon::fromTheme("view-refresh"));
connect(refreshAction, SIGNAL(triggered()), SLOT(update()));
refresh->setAutoRaise(true);
refresh->setDefaultAction(refreshAction);
}
LyricsPage::~LyricsPage()
{
}
void LyricsPage::setEnabledProviders(const QStringList &providerList)
{
foreach (UltimateLyricsProvider* provider, providers) {
provider->set_enabled(false);
provider->set_relevance(0xFFFF);
}
int relevance=0;
foreach (const QString &p, providerList) {
UltimateLyricsProvider *provider=providerByName(p);
if (provider) {
provider->set_enabled(true);
provider->set_relevance(relevance++);
}
}
qSort(providers.begin(), providers.end(), CompareLyricProviders);
}
void LyricsPage::update()
{
update(currentSong, true);
}
void LyricsPage::update(const Song &song, bool force)
{
if (force || song.artist!=currentSong.artist || song.title!=currentSong.title) {
currentRequest++;
currentSong=song;
currentProvider=-1;
if (song.title.isEmpty() || song.artist.isEmpty()) {
text->setText(QString());
return;
}
if (!mpdDir.isEmpty()) {
// Check for MPD file...
QString mpdLyrics=changeExt(mpdDir+song.file, constExtension);
if (QFile::exists(mpdLyrics)) {
QFile f(mpdLyrics);
if (f.open(QIODevice::ReadOnly)) {
text->setText(f.readAll());
f.close();
return;
}
}
}
// Check for cached file...
QString file=cacheFile(song.artist, song.title);
if (QFile::exists(file)) {
if (force) {
QFile::remove(file);
} else {
QFile f(file);
if (f.open(QIODevice::ReadOnly)) {
text->setText(f.readAll());
f.close();
return;
}
}
}
getLyrics();
}
}
void LyricsPage::resultReady(int id, const QString &lyrics)
{
if (id != currentRequest)
return;
if (lyrics.isEmpty()) {
getLyrics();
} else {
text->setText(lyrics);
QFile f(cacheFile(currentSong.artist, currentSong.title, true));
if (f.open(QIODevice::WriteOnly)) {
QTextStream(&f) << text->toPlainText();
f.close();
}
}
}
UltimateLyricsProvider* LyricsPage::providerByName(const QString &name) const
{
foreach (UltimateLyricsProvider* provider, providers) {
if (provider->name() == name) {
return provider;
}
}
return 0;
}
void LyricsPage::getLyrics()
{
for(;;) {
currentProvider++;
if (currentProvider<providers.count()) {
UltimateLyricsProvider *prov=providers.at(currentProvider++);
if (prov && prov->is_enabled()) {
#ifdef ENABLE_KDE_SUPPORT
text->setText(i18n("Fetching lyrics via %1", prov->name()));
#else
text->setText(tr("Fetching lyrics via %1").arg(prov->name()));
#endif
prov->FetchInfo(currentRequest, currentSong);
return;
}
} else {
#ifdef ENABLE_KDE_SUPPORT
text->setText(i18n("No lyrics found"));
#else
text->setText(tr("No lyrics found"));
#endif
currentProvider=-1;
return;
}
}
}
// void LyricsPage::ultimateLyricsParsed()
// {
// QFutureWatcher<ProviderList>* watcher = static_cast<QFutureWatcher<ProviderList>*>(sender());
// QStringList names;
//
// foreach (UltimateLyricsProvider* provider, watcher->result()) {
// providers.append(provider);
// connect(provider, SIGNAL(InfoReady(int, const QString &)), SLOT(resultReady(int, const QString &)));
// }
//
// watcher->deleteLater();
// reader.reset();
// emit providersUpdated();
// }