Split the echonest images and biographies into different classes, fetch tags and similar artists from echonest.

This commit is contained in:
David Sansome 2010-10-10 21:45:01 +00:00
parent 0940d88862
commit 35988411e1
49 changed files with 585 additions and 73 deletions

View File

@ -273,5 +273,6 @@
<file>providers/mog.png</file> <file>providers/mog.png</file>
<file>providers/mtvmusic.png</file> <file>providers/mtvmusic.png</file>
<file>providers/cdbaby.png</file> <file>providers/cdbaby.png</file>
<file>providers/echonest.png</file>
</qresource> </qresource>
</RCC> </RCC>

BIN
data/providers/echonest.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

View File

@ -131,7 +131,10 @@ set(SOURCES
songinfo/artistinfoview.cpp songinfo/artistinfoview.cpp
songinfo/collapsibleinfoheader.cpp songinfo/collapsibleinfoheader.cpp
songinfo/collapsibleinfopane.cpp songinfo/collapsibleinfopane.cpp
songinfo/echonestartistinfo.cpp songinfo/echonestbiographies.cpp
songinfo/echonestimages.cpp
songinfo/echonestsimilarartists.cpp
songinfo/echonesttags.cpp
songinfo/lastfmtrackinfoprovider.cpp songinfo/lastfmtrackinfoprovider.cpp
songinfo/lyricsettings.cpp songinfo/lyricsettings.cpp
songinfo/songinfobase.cpp songinfo/songinfobase.cpp
@ -275,7 +278,10 @@ set(HEADERS
songinfo/artistinfoview.h songinfo/artistinfoview.h
songinfo/collapsibleinfoheader.h songinfo/collapsibleinfoheader.h
songinfo/collapsibleinfopane.h songinfo/collapsibleinfopane.h
songinfo/echonestartistinfo.h songinfo/echonestbiographies.h
songinfo/echonestimages.h
songinfo/echonestsimilarartists.h
songinfo/echonesttags.h
songinfo/lastfmtrackinfoprovider.h songinfo/lastfmtrackinfoprovider.h
songinfo/lyricsettings.h songinfo/lyricsettings.h
songinfo/songinfobase.h songinfo/songinfobase.h

View File

@ -15,14 +15,20 @@
*/ */
#include "artistinfoview.h" #include "artistinfoview.h"
#include "echonestartistinfo.h" #include "echonestbiographies.h"
#include "echonestimages.h"
#include "echonestsimilarartists.h"
#include "echonesttags.h"
#include "songinfofetcher.h" #include "songinfofetcher.h"
#include "widgets/prettyimageview.h" #include "widgets/prettyimageview.h"
ArtistInfoView::ArtistInfoView(NetworkAccessManager* network, QWidget *parent) ArtistInfoView::ArtistInfoView(NetworkAccessManager* network, QWidget *parent)
: SongInfoBase(network, parent) : SongInfoBase(network, parent)
{ {
fetcher_->AddProvider(new EchoNestArtistInfo); fetcher_->AddProvider(new EchoNestBiographies);
fetcher_->AddProvider(new EchoNestImages);
fetcher_->AddProvider(new EchoNestSimilarArtists);
fetcher_->AddProvider(new EchoNestTags);
} }
ArtistInfoView::~ArtistInfoView() { ArtistInfoView::~ArtistInfoView() {

View File

@ -34,6 +34,7 @@ public:
enum Type { enum Type {
Type_PlayCounts, Type_PlayCounts,
Type_Tags, Type_Tags,
Type_Similar,
Type_Biography, Type_Biography,
Type_Lyrics, Type_Lyrics,

View File

@ -14,24 +14,21 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>. along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "echonestartistinfo.h" #include "echonestbiographies.h"
#include "widgets/autosizedtextedit.h" #include "widgets/autosizedtextedit.h"
#include <echonest/Artist.h> #include <echonest/Artist.h>
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
struct EchoNestArtistInfo::Request { struct EchoNestBiographies::Request {
Request(int id) : id_(id), artist_(new Echonest::Artist) {} Request(int id) : id_(id), artist_(new Echonest::Artist) {}
bool is_finished() const { return pending_replies_.isEmpty(); }
int id_; int id_;
boost::scoped_ptr<Echonest::Artist> artist_; boost::scoped_ptr<Echonest::Artist> artist_;
QList<QNetworkReply*> pending_replies_;
}; };
EchoNestArtistInfo::EchoNestArtistInfo() { EchoNestBiographies::EchoNestBiographies() {
site_relevance_["wikipedia"] = 100; site_relevance_["wikipedia"] = 100;
site_relevance_["lastfm"] = 60; site_relevance_["lastfm"] = 60;
site_relevance_["amazon"] = 30; site_relevance_["amazon"] = 30;
@ -46,58 +43,28 @@ EchoNestArtistInfo::EchoNestArtistInfo() {
site_icons_["wikipedia"] = QIcon(":/providers/wikipedia.png"); site_icons_["wikipedia"] = QIcon(":/providers/wikipedia.png");
} }
void EchoNestArtistInfo::FetchInfo(int id, const Song& metadata) { void EchoNestBiographies::FetchInfo(int id, const Song& metadata) {
boost::shared_ptr<Request> request(new Request(id)); boost::shared_ptr<Request> request(new Request(id));
request->artist_->setName(metadata.artist()); request->artist_->setName(metadata.artist());
ConnectReply(request, request->artist_->fetchBiographies(), SLOT(BiographiesFinished())); QNetworkReply* reply = request->artist_->fetchBiographies();
ConnectReply(request, request->artist_->fetchImages(), SLOT(ImagesFinished())); connect(reply, SIGNAL(finished()), SLOT(RequestFinished()));
requests_[reply] = request;
requests_ << request;
} }
void EchoNestArtistInfo::ConnectReply( void EchoNestBiographies::RequestFinished() {
boost::shared_ptr<Request> request, QNetworkReply* reply, const char* slot) { QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
request->pending_replies_ << reply; if (!reply || !requests_.contains(reply))
connect(reply, SIGNAL(finished()), slot); return;
}
EchoNestArtistInfo::RequestPtr EchoNestArtistInfo::ReplyFinished(QNetworkReply* reply) {
reply->deleteLater(); reply->deleteLater();
foreach (RequestPtr request, requests_) { RequestPtr request = requests_.take(reply);
if (request->pending_replies_.contains(reply)) {
try {
request->artist_->parseProfile(reply);
} catch (Echonest::ParseError e) {
qWarning() << "Error parsing echonest reply:" << e.errorType() << e.what();
}
request->pending_replies_.removeAll(reply); try {
request->artist_->parseProfile(reply);
if (request->is_finished()) { } catch (Echonest::ParseError e) {
requests_.removeAll(request); qWarning() << "Error parsing echonest reply:" << e.errorType() << e.what();
}
return request;
}
} }
return RequestPtr();
}
void EchoNestArtistInfo::ImagesFinished() {
RequestPtr request = ReplyFinished(qobject_cast<QNetworkReply*>(sender()));
foreach (const Echonest::ArtistImage& image, request->artist_->images()) {
emit ImageReady(request->id_, image.url());
}
if (request->is_finished())
emit Finished(request->id_);
}
void EchoNestArtistInfo::BiographiesFinished() {
RequestPtr request = ReplyFinished(qobject_cast<QNetworkReply*>(sender()));
QSet<QString> already_seen; QSet<QString> already_seen;
@ -125,6 +92,5 @@ void EchoNestArtistInfo::BiographiesFinished() {
emit InfoReady(request->id_, data); emit InfoReady(request->id_, data);
} }
if (request->is_finished()) emit Finished(request->id_);
emit Finished(request->id_);
} }

View File

@ -14,40 +14,34 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>. along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef ECHONESTARTISTINFO_H #ifndef ECHONESTBIOGRAPHIES_H
#define ECHONESTARTISTINFO_H #define ECHONESTBIOGRAPHIES_H
#include "songinfoprovider.h" #include "songinfoprovider.h"
#include <QMap>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
class QNetworkReply; class QNetworkReply;
class EchoNestArtistInfo : public SongInfoProvider { class EchoNestBiographies : public SongInfoProvider {
Q_OBJECT Q_OBJECT
public: public:
EchoNestArtistInfo(); EchoNestBiographies();
void FetchInfo(int id, const Song& metadata); void FetchInfo(int id, const Song& metadata);
private slots: private slots:
void BiographiesFinished(); void RequestFinished();
void ImagesFinished();
private: private:
QMap<QString, int> site_relevance_;
QMap<QString, QIcon> site_icons_;
struct Request; struct Request;
typedef boost::shared_ptr<Request> RequestPtr; typedef boost::shared_ptr<Request> RequestPtr;
void ConnectReply(RequestPtr request, QNetworkReply* reply, const char* slot); QMap<QNetworkReply*, RequestPtr> requests_;
RequestPtr ReplyFinished(QNetworkReply* reply);
private:
QList<RequestPtr> requests_;
QMap<QString, int> site_relevance_;
QMap<QString, QIcon> site_icons_;
}; };
#endif // ECHONESTARTISTINFO_H #endif // ECHONESTBIOGRAPHIES_H

View File

@ -0,0 +1,58 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "echonestimages.h"
#include <echonest/Artist.h>
#include <boost/scoped_ptr.hpp>
struct EchoNestImages::Request {
Request(int id) : id_(id), artist_(new Echonest::Artist) {}
int id_;
boost::scoped_ptr<Echonest::Artist> artist_;
};
void EchoNestImages::FetchInfo(int id, const Song& metadata) {
boost::shared_ptr<Request> request(new Request(id));
request->artist_->setName(metadata.artist());
QNetworkReply* reply = request->artist_->fetchImages();
connect(reply, SIGNAL(finished()), SLOT(RequestFinished()));
requests_[reply] = request;
}
void EchoNestImages::RequestFinished() {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
if (!reply || !requests_.contains(reply))
return;
reply->deleteLater();
RequestPtr request = requests_.take(reply);
try {
request->artist_->parseProfile(reply);
} catch (Echonest::ParseError e) {
qWarning() << "Error parsing echonest reply:" << e.errorType() << e.what();
}
foreach (const Echonest::ArtistImage& image, request->artist_->images()) {
emit ImageReady(request->id_, image.url());
}
emit Finished(request->id_);
}

View File

@ -0,0 +1,42 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ECHONESTIMAGES_H
#define ECHONESTIMAGES_H
#include "songinfoprovider.h"
#include <boost/shared_ptr.hpp>
class QNetworkReply;
class EchoNestImages : public SongInfoProvider {
Q_OBJECT
public:
void FetchInfo(int id, const Song& metadata);
private slots:
void RequestFinished();
private:
struct Request;
typedef boost::shared_ptr<Request> RequestPtr;
QMap<QNetworkReply*, RequestPtr> requests_;
};
#endif // ECHONESTIMAGES_H

View File

@ -0,0 +1,74 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "echonestsimilarartists.h"
#include "tagwidget.h"
#include "ui/iconloader.h"
#include <echonest/Artist.h>
Q_DECLARE_METATYPE(QVector<QString>);
void EchoNestSimilarArtists::FetchInfo(int id, const Song& metadata) {
using Echonest::Artist;
Artist::SearchParams params;
params << Artist::SearchParamEntry(Artist::Name, metadata.artist());
params << Artist::SearchParamEntry(Artist::MinHotttnesss, 0.5);
QNetworkReply* reply = Echonest::Artist::fetchSimilar(params);
connect(reply, SIGNAL(finished()), SLOT(RequestFinished()));
requests_[reply] = id;
}
void EchoNestSimilarArtists::RequestFinished() {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
if (!reply || !requests_.contains(reply))
return;
reply->deleteLater();
int id = requests_.take(reply);
Echonest::Artists artists;
try {
artists = Echonest::Artist::parseSimilar(reply);
} catch (Echonest::ParseError e) {
qWarning() << "Error parsing echonest reply:" << e.errorType() << e.what();
}
if (!artists.isEmpty()) {
CollapsibleInfoPane::Data data;
data.title_ = tr("Similar artists");
data.type_ = CollapsibleInfoPane::Data::Type_Similar;
data.icon_ = QIcon(":/providers/echonest.png");
TagWidget* widget = new TagWidget;
data.contents_ = widget;
widget->SetIcon(QIcon(":/icons/22x22/x-clementine-artist.png"));
widget->SetUrlPattern("lastfm://artist/%1/similarartists");
foreach (const Echonest::Artist& artist, artists) {
widget->AddTag(artist.name());
if (widget->count() >= 10)
break;
}
emit InfoReady(id, data);
}
emit Finished(id);
}

View File

@ -0,0 +1,37 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ECHONESTSIMILARARTISTS_H
#define ECHONESTSIMILARARTISTS_H
#include "songinfoprovider.h"
class QNetworkReply;
class EchoNestSimilarArtists : public SongInfoProvider {
Q_OBJECT
public:
void FetchInfo(int id, const Song& metadata);
private slots:
void RequestFinished();
private:
QMap<QNetworkReply*, int> requests_;
};
#endif // ECHONESTSIMILARARTISTS_H

View File

@ -0,0 +1,77 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include "echonesttags.h"
#include "tagwidget.h"
#include <echonest/Artist.h>
#include <boost/scoped_ptr.hpp>
struct EchoNestTags::Request {
Request(int id) : id_(id), artist_(new Echonest::Artist) {}
int id_;
boost::scoped_ptr<Echonest::Artist> artist_;
};
void EchoNestTags::FetchInfo(int id, const Song& metadata) {
boost::shared_ptr<Request> request(new Request(id));
request->artist_->setName(metadata.artist());
QNetworkReply* reply = request->artist_->fetchTerms();
connect(reply, SIGNAL(finished()), SLOT(RequestFinished()));
requests_[reply] = request;
}
void EchoNestTags::RequestFinished() {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
if (!reply || !requests_.contains(reply))
return;
reply->deleteLater();
RequestPtr request = requests_.take(reply);
try {
request->artist_->parseProfile(reply);
} catch (Echonest::ParseError e) {
qWarning() << "Error parsing echonest reply:" << e.errorType() << e.what();
}
if (!request->artist_->terms().isEmpty()) {
CollapsibleInfoPane::Data data;
data.title_ = tr("Artist tags");
data.type_ = CollapsibleInfoPane::Data::Type_Tags;
data.icon_ = QIcon(":/last.fm/icon_tag.png");
TagWidget* widget = new TagWidget;
data.contents_ = widget;
widget->SetIcon(data.icon_);
widget->SetUrlPattern("lastfm://globaltags/%1");
foreach (const Echonest::Term& term, request->artist_->terms()) {
widget->AddTag(term.name());
if (widget->count() >= 10)
break;
}
emit InfoReady(request->id_, data);
}
emit Finished(request->id_);
}

View File

@ -0,0 +1,42 @@
/* This file is part of Clementine.
Clementine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Clementine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ECHONESTTAGS_H
#define ECHONESTTAGS_H
#include "songinfoprovider.h"
#include <boost/shared_ptr.hpp>
class QNetworkReply;
class EchoNestTags : public SongInfoProvider {
Q_OBJECT
public:
void FetchInfo(int id, const Song& metadata);
private slots:
void RequestFinished();
private:
struct Request;
typedef boost::shared_ptr<Request> RequestPtr;
QMap<QNetworkReply*, RequestPtr> requests_;
};
#endif // ECHONESTTAGS_H

View File

@ -104,5 +104,7 @@ void TagWidget::AddTag(const QString& tag) {
if (tag.isEmpty()) if (tag.isEmpty())
return; return;
layout()->addWidget(new TagWidgetTag(icon_, tag, this)); TagWidgetTag* widget = new TagWidgetTag(icon_, tag, this);
layout()->addWidget(widget);
tags_ << widget;
} }

View File

@ -64,10 +64,12 @@ public:
void SetIcon(const QIcon& icon) { icon_ = icon; } void SetIcon(const QIcon& icon) { icon_ = icon; }
void AddTag(const QString& tag); void AddTag(const QString& tag);
int count() const { return tags_.count(); }
private: private:
QString url_pattern_; QString url_pattern_;
QIcon icon_; QIcon icon_;
QStringList tags_; QList<TagWidgetTag*> tags_;
}; };
#endif // TAGWIDGET_H #endif // TAGWIDGET_H

View File

@ -275,6 +275,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1686,6 +1689,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "" msgstr ""

View File

@ -276,6 +276,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1687,6 +1690,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "" msgstr ""

View File

@ -284,6 +284,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Radio de l'artista" msgstr "Radio de l'artista"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Inicials de l'artista" msgstr "Inicials de l'artista"
@ -1716,6 +1719,9 @@ msgstr "Llista de reproducció aleatòria"
msgid "Sign out" msgid "Sign out"
msgstr "Tancar la sessió" msgstr "Tancar la sessió"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -277,6 +277,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Rádio umělce" msgstr "Rádio umělce"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1691,6 +1694,9 @@ msgstr "Zamíchat seznam skladeb"
msgid "Sign out" msgid "Sign out"
msgstr "Odhlásit" msgstr "Odhlásit"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -277,6 +277,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Kunstnerradio" msgstr "Kunstnerradio"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Kunstner's initial" msgstr "Kunstner's initial"
@ -1694,6 +1697,9 @@ msgstr "Bland spilleliste"
msgid "Sign out" msgid "Sign out"
msgstr "Log ud" msgstr "Log ud"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -283,6 +283,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Interpreten-Radio" msgstr "Interpreten-Radio"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Initialen des Künstlers" msgstr "Initialen des Künstlers"
@ -1717,6 +1720,9 @@ msgstr "Wiedergabeliste mischen"
msgid "Sign out" msgid "Sign out"
msgstr "Abmelden" msgstr "Abmelden"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -284,6 +284,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Ραδιόφωνο καλλιτέχνη" msgstr "Ραδιόφωνο καλλιτέχνη"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Αρχικά του καλλιτέχνη" msgstr "Αρχικά του καλλιτέχνη"
@ -1720,6 +1723,9 @@ msgstr "Ανακάτεμα λίστας"
msgid "Sign out" msgid "Sign out"
msgstr "Αποσύνδεση" msgstr "Αποσύνδεση"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -275,6 +275,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Artist radio" msgstr "Artist radio"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1691,6 +1694,9 @@ msgstr "Shuffle playlist"
msgid "Sign out" msgid "Sign out"
msgstr "Sign out" msgstr "Sign out"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -275,6 +275,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Artist radio" msgstr "Artist radio"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1688,6 +1691,9 @@ msgstr "Shuffle playlist"
msgid "Sign out" msgid "Sign out"
msgstr "Sign out" msgstr "Sign out"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -284,6 +284,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Radio del artista" msgstr "Radio del artista"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Iniciales del artista" msgstr "Iniciales del artista"
@ -1721,6 +1724,9 @@ msgstr "Mezclar lista de reproducción"
msgid "Sign out" msgid "Sign out"
msgstr "Cerrar sesión" msgstr "Cerrar sesión"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -276,6 +276,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1689,6 +1692,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "Kirjaudu ulos" msgstr "Kirjaudu ulos"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -287,6 +287,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Radio par artiste" msgstr "Radio par artiste"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Initiale de l'artiste" msgstr "Initiale de l'artiste"
@ -1725,6 +1728,9 @@ msgstr "Mélanger la liste de lecture"
msgid "Sign out" msgid "Sign out"
msgstr "Se déconnecter" msgstr "Se déconnecter"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -276,6 +276,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Artista da rádio" msgstr "Artista da rádio"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Iniciáis do artista" msgstr "Iniciáis do artista"
@ -1693,6 +1696,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -281,6 +281,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Előadó rádió" msgstr "Előadó rádió"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Előadó kezdése" msgstr "Előadó kezdése"
@ -1715,6 +1718,9 @@ msgstr "Lejátszási lista véletlenszerűen"
msgid "Sign out" msgid "Sign out"
msgstr "Kijelentkezés" msgstr "Kijelentkezés"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -288,6 +288,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Radio dell'artista" msgstr "Radio dell'artista"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Iniziale dell'artista" msgstr "Iniziale dell'artista"
@ -1725,6 +1728,9 @@ msgstr "Mescola la scaletta"
msgid "Sign out" msgid "Sign out"
msgstr "Disconnetti" msgstr "Disconnetti"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -275,6 +275,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1688,6 +1691,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ска" msgstr "Ска"

View File

@ -276,6 +276,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1687,6 +1690,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "" msgstr ""

View File

@ -276,6 +276,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Artistradio" msgstr "Artistradio"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1690,6 +1693,9 @@ msgstr "Bland spilleliste"
msgid "Sign out" msgid "Sign out"
msgstr "Logg ut" msgstr "Logg ut"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -284,6 +284,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Artiestradio" msgstr "Artiestradio"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Artiest's initiaal" msgstr "Artiest's initiaal"
@ -1720,6 +1723,9 @@ msgstr "Afspeellijst schudden"
msgid "Sign out" msgid "Sign out"
msgstr "Afmelden" msgstr "Afmelden"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -275,6 +275,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1686,6 +1689,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -284,6 +284,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Radio wykonawcy" msgstr "Radio wykonawcy"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Inicjał autora" msgstr "Inicjał autora"
@ -1716,6 +1719,9 @@ msgstr "Zamieszaj playlistę"
msgid "Sign out" msgid "Sign out"
msgstr "Wyloguj" msgstr "Wyloguj"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -283,6 +283,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Rádio do artista" msgstr "Rádio do artista"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Iniciais do artista" msgstr "Iniciais do artista"
@ -1717,6 +1720,9 @@ msgstr "Baralhar lista de reprodução"
msgid "Sign out" msgid "Sign out"
msgstr "Sair" msgstr "Sair"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -281,6 +281,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Rádio do artista" msgstr "Rádio do artista"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Artista inicial" msgstr "Artista inicial"
@ -1705,6 +1708,9 @@ msgstr "Misturar lista de reprodução"
msgid "Sign out" msgid "Sign out"
msgstr "Sair" msgstr "Sair"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -275,6 +275,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1687,6 +1690,9 @@ msgstr "Amestecă lista de melodii"
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -279,6 +279,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Радио исполнителя" msgstr "Радио исполнителя"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Инициалы исполнителя" msgstr "Инициалы исполнителя"
@ -1709,6 +1712,9 @@ msgstr "Перемешать список воспроизведения"
msgid "Sign out" msgid "Sign out"
msgstr "Выйти" msgstr "Выйти"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -281,6 +281,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Rádio interpréta" msgstr "Rádio interpréta"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Interprétov prvotný" msgstr "Interprétov prvotný"
@ -1710,6 +1713,9 @@ msgstr "Zamiešať playlist"
msgid "Sign out" msgid "Sign out"
msgstr "Odhlásiť" msgstr "Odhlásiť"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -280,6 +280,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Radio izvajalca" msgstr "Radio izvajalca"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Začetnice izvajalca" msgstr "Začetnice izvajalca"
@ -1710,6 +1713,9 @@ msgstr "Premešaj seznam predvajanja"
msgid "Sign out" msgid "Sign out"
msgstr "Odjavi se" msgstr "Odjavi se"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -276,6 +276,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Иницијали извођача" msgstr "Иницијали извођача"
@ -1692,6 +1695,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "Одјави се" msgstr "Одјави се"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ска" msgstr "Ска"

View File

@ -276,6 +276,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Artistradio" msgstr "Artistradio"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Artistens initialer" msgstr "Artistens initialer"
@ -1696,6 +1699,9 @@ msgstr "Slumpsportera spellista"
msgid "Sign out" msgid "Sign out"
msgstr "Logga ut" msgstr "Logga ut"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -280,6 +280,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Sanatçı radyosu" msgstr "Sanatçı radyosu"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Sanatçının kısaltması" msgstr "Sanatçının kısaltması"
@ -1713,6 +1716,9 @@ msgstr "Çalma listesini karıştır"
msgid "Sign out" msgid "Sign out"
msgstr "Çıkış yap" msgstr "Çıkış yap"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"

View File

@ -266,6 +266,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1677,6 +1680,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "" msgstr ""

View File

@ -280,6 +280,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "Радіо виконавця" msgstr "Радіо виконавця"
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "Ініціали виконавця" msgstr "Ініціали виконавця"
@ -1710,6 +1713,9 @@ msgstr "Перемішати список відтворення"
msgid "Sign out" msgid "Sign out"
msgstr "Вийти" msgstr "Вийти"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "Ска" msgstr "Ска"

View File

@ -275,6 +275,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1686,6 +1689,9 @@ msgstr ""
msgid "Sign out" msgid "Sign out"
msgstr "" msgstr ""
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "" msgstr ""

View File

@ -280,6 +280,9 @@ msgstr ""
msgid "Artist radio" msgid "Artist radio"
msgstr "" msgstr ""
msgid "Artist tags"
msgstr ""
msgid "Artist's initial" msgid "Artist's initial"
msgstr "" msgstr ""
@ -1692,6 +1695,9 @@ msgstr "隨機排列播放清單"
msgid "Sign out" msgid "Sign out"
msgstr "登出" msgstr "登出"
msgid "Similar artists"
msgstr ""
msgid "Ska" msgid "Ska"
msgstr "" msgstr ""