diff options
author | Arno <arno@disconnect.de> | 2017-07-06 10:33:13 +0200 |
---|---|---|
committer | Arno <arno@disconnect.de> | 2017-07-06 10:33:13 +0200 |
commit | dbc19ad71cbac5166aa0b82c97b726b464f4fdca (patch) | |
tree | 11b6de922f37b830eba36a9961b4deaefd68668c | |
parent | f9771c52ff6b350c29db70216b79bb4f60081763 (diff) | |
download | BeetPlayer-dbc19ad71cbac5166aa0b82c97b726b464f4fdca.tar.gz BeetPlayer-dbc19ad71cbac5166aa0b82c97b726b464f4fdca.tar.bz2 BeetPlayer-dbc19ad71cbac5166aa0b82c97b726b464f4fdca.zip |
Implemented MusicBrainz lookup
Wow, what a convoluted api, to say the least...
They have documentation, which is good, but the query syntax definitely
needs more explaining, foremost how to encode non-ASCII characters and
names with whitspaces...
Well, it kinda works, but the Other Albums sections can be waaaaay
off...
-rw-r--r-- | BeetPlayer.pro | 8 | ||||
-rw-r--r-- | playerwidget.cpp | 58 | ||||
-rw-r--r-- | playerwidget.h | 9 | ||||
-rw-r--r-- | webdownloader.cpp | 49 | ||||
-rw-r--r-- | webdownloader.h | 32 |
5 files changed, 145 insertions, 11 deletions
diff --git a/BeetPlayer.pro b/BeetPlayer.pro index 0598033..0af8894 100644 --- a/BeetPlayer.pro +++ b/BeetPlayer.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui multimedia sql +QT += core gui multimedia sql network QT += KGlobalAccel KWindowSystem greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -32,7 +32,8 @@ SOURCES += main.cpp\ playerwidget.cpp \ beetview.cpp \ indexerdialog.cpp \ - helper.cpp + helper.cpp \ + webdownloader.cpp HEADERS += beetplayer.h \ configurationdialog.h \ @@ -41,7 +42,8 @@ HEADERS += beetplayer.h \ playerwidget.h \ beetview.h \ indexerdialog.h \ - helper.h + helper.h \ + webdownloader.h LIBS += -ltag diff --git a/playerwidget.cpp b/playerwidget.cpp index c00db32..6eb5821 100644 --- a/playerwidget.cpp +++ b/playerwidget.cpp @@ -3,6 +3,7 @@ #include <QPushButton> #include <QLabel> #include <QTextEdit> +#include <QTextBrowser> #include <QSlider> #include <QTreeView> #include <QSplitter> @@ -35,11 +36,14 @@ #include "indexerdialog.h" #include "globals.h" #include "helper.h" +#include "webdownloader.h" PlayerWidget::PlayerWidget(QWidget *parent) : QWidget(parent), mDurSecs(0), mPlayListLength(0){ mStarting = true; setupGui(); createActions(); + mWebDownloader = new WebDownloader(this); + connect(mWebDownloader, &WebDownloader::done, this, &PlayerWidget::webDlDone); mStarting = false; } @@ -203,7 +207,8 @@ void PlayerWidget::setupGui(){ //misc info QString leftInfoGBS = QString(tr("%1 Misc. %1")).arg(QChar(0x26A5)); QGroupBox *leftInfoGB = new QGroupBox(leftInfoGBS); - mLeftTE = new QTextEdit; + mLeftTE = new QTextBrowser; + mLeftTE->setOpenExternalLinks(true); mLeftTE->setFont(QFont("courier")); mLeftTE->setReadOnly(true); QVBoxLayout *leftInfoL = new QVBoxLayout; @@ -354,8 +359,10 @@ void PlayerWidget::createActions(){ helpA->setMenu(helpM); QAction *miscPrintA = new QAction(QIcon(":/clean_tampon.png"), tr("List selected"), this); connect(miscPrintA, &QAction::triggered, this, &PlayerWidget::printList); - QAction *miscMusicBrainzA = new QAction(QIcon(":/bizarre_amputee.png"), tr("Search Musicbrainz"), this); - connect(miscMusicBrainzA, &QAction::triggered, this, &PlayerWidget::searchMusicbrainz); + QAction *miscMusicBrainzRightA = new QAction(QIcon(":/bizarre_amputee.png"), tr("Search Musicbrainz"), this); + connect(miscMusicBrainzRightA, &QAction::triggered, this, &PlayerWidget::searchMusicbrainzRight); + QAction *miscMusicBrainzLeftA = new QAction(QIcon(":/bizarre_amputee.png"), tr("Search Musicbrainz"), this); + connect(miscMusicBrainzLeftA, &QAction::triggered, this, &PlayerWidget::searchMusicbrainzLeft); mView->addAction(addToPlayListA); mView->addAction(addToPlayListAndClearA); mView->addAction(Helper::createSeparator(this)); @@ -367,13 +374,14 @@ void PlayerWidget::createActions(){ mView->addAction(mDeleteFilesA); mView->addAction(Helper::createSeparator(this)); mView->addAction(miscPrintA); + mView->addAction(miscMusicBrainzLeftA); mView->addAction(Helper::createSeparator(this)); mView->addAction(mRefreshA); mView->addAction(Helper::createSeparator(this)); mView->addAction(randomPlayA); mPlayListView->addAction(removeFromPlayListA); mPlayListView->addAction(Helper::createSeparator(this)); - mPlayListView->addAction(miscMusicBrainzA); + mPlayListView->addAction(miscMusicBrainzRightA); mPlayListView->addAction(Helper::createSeparator(this)); mPlayListView->addAction(shufflePlayistA); mPlayListView->addAction(clearPlayListA); @@ -959,6 +967,8 @@ void PlayerWidget::addSong(const QModelIndex &idx){ len = Helper::lengthInSeconds(idx.data(FullPathRole).toString()); } item->setData(len, LengthRole); + item->setData(artist, ArtistRole); + item->setData(album, AlbumRole); root->appendRow(item); mPlayListLength += len; } @@ -1179,6 +1189,8 @@ void PlayerWidget::randomPlay(){ item->setIcon(songIcon); item->setData(randomQ.value(2), FullPathRole); item->setData(randomQ.value(6), LengthRole); + item->setData(randomQ.value(4), ArtistRole); + item->setData(randomQ.value(5), AlbumRole); mPlayListLength += randomQ.value(6).toInt(); root->appendRow(item); } @@ -1213,11 +1225,45 @@ void PlayerWidget::printList(){ output.append(t); } } - mLeftTE->setText(output); + mLeftTE->clear(); + mLeftTE->setPlainText(output); } -void PlayerWidget::searchMusicbrainz(){ +void PlayerWidget::searchMusicbrainzRight(){ + QModelIndex idx = mPlayListView->selectionModel()->currentIndex(); + if(!idx.isValid()){ + return; + } + QString artist = idx.data(ArtistRole).toString(); + QString album = idx.data(AlbumRole).toString(); + mWebDownloader->fetchData(artist, album); +} + +void PlayerWidget::searchMusicbrainzLeft(){ + QModelIndex idx = mView->selectionModel()->currentIndex(); + if(!idx.isValid()){ + return; + } + QString artist = idx.data(ArtistRole).toString().toLower(); + QString album = idx.data(AlbumRole).toString().toLower(); + mWebDownloader->fetchData(artist, album); +} + +void PlayerWidget::webDlDone(){ + QString text(tr("<b>Musicbrainz:</b><ul>")); + text.append(QString(tr("<li>Artist: %1</li>")).arg(mWebDownloader->artist())); + text.append(QString(tr("<li>Album: %1</li>")).arg(mWebDownloader->album())); + foreach(QString rg, mWebDownloader->data()){ + text.append(QString("<li><a href=\"https://musicbrainz.org/release-group/%1\">%1</a></li>").arg(rg)); + } + text.append("</ul>"); + text.append(tr("<b>Other Albums</b><ul>")); + for(QMap<QString, QString>::const_iterator it = mWebDownloader->otherData().constBegin(); it != mWebDownloader->otherData().constEnd(); ++it){ + text.append(QString("<li><a href=\"https://musicbrainz.org/release-group/%1\">%2</a></li>").arg(it.value()).arg(it.key())); + } + text.append("</ul>"); + mLeftTE->setText(text); } void PlayerWidget::play(const QString &fullPath){ diff --git a/playerwidget.h b/playerwidget.h index ad58ea4..738b72e 100644 --- a/playerwidget.h +++ b/playerwidget.h @@ -13,6 +13,7 @@ class QLineEdit; class QLabel; class QSlider; class QTextEdit; +class QTextBrowser; class QMediaPlayer; class QToolBar; class QAction; @@ -21,6 +22,7 @@ class QStackedLayout; class BeetPlayerProxy; class BeetView; class QSystemTrayIcon; +class WebDownloader; class PlayerWidget : public QWidget { Q_OBJECT @@ -65,7 +67,9 @@ class PlayerWidget : public QWidget { void randomPlay(); void playCurrent(const QModelIndex &index); void printList(); - void searchMusicbrainz(); + void searchMusicbrainzRight(); + void searchMusicbrainzLeft(); + void webDlDone(); void mute(bool triggered); void volumeChanged(int volume); @@ -117,7 +121,7 @@ class PlayerWidget : public QWidget { QSlider *mVolumeSlider; QLabel *mVolumePos; QTextEdit *mCurrentTE; - QTextEdit *mLeftTE; + QTextBrowser *mLeftTE; QTextEdit *mRightTE; BeetView *mPlayListView; QStandardItemModel *mPlayListModel; @@ -140,6 +144,7 @@ class PlayerWidget : public QWidget { QTimer *mVolumeTimer; bool mStarting; QStackedLayout *mSearchDirStack; + WebDownloader *mWebDownloader; }; #endif // PLAYERWIDGET_H diff --git a/webdownloader.cpp b/webdownloader.cpp new file mode 100644 index 0000000..8035fe1 --- /dev/null +++ b/webdownloader.cpp @@ -0,0 +1,49 @@ +#include <QNetworkReply> +#include <QNetworkRequest> +#include <QJsonDocument> +#include <QJsonObject> +#include <QJsonArray> + +#include "webdownloader.h" + +WebDownloader::WebDownloader(QObject *parent) : QObject(parent) { + mAccessMgr = new QNetworkAccessManager(this); + connect(mAccessMgr, &QNetworkAccessManager::finished, this, &WebDownloader::dlFinished); +} + +void WebDownloader::fetchData(QString artist, QString album){ + mArtist = artist; + mAlbum = album; + QString artistQ = QString("artist:\"%1\"").arg(artist); + QByteArray peq = QUrl::toPercentEncoding(artistQ); + QString url = QString("https://musicbrainz.org/ws/2/release/?query=%1&fmt=json&limit=100").arg(QString(peq)); + QUrl aUrl(url); + QNetworkRequest req(aUrl); + req.setHeader(QNetworkRequest::UserAgentHeader, "Beetplayer/1.0.0 (beetplayer@d-tor.org"); + mAccessMgr->get(req); +} + +void WebDownloader::dlFinished(QNetworkReply *reply){ + mData.clear(); + mOtherData.clear(); + QByteArray res = reply->readAll(); + QJsonParseError err; + QJsonDocument jDoc = QJsonDocument::fromJson(res, &err); + QJsonObject docObj = jDoc.object(); + QJsonArray relArr = docObj.value("releases").toArray(); + for(QJsonArray::const_iterator it = relArr.constBegin(); it != relArr.constEnd(); ++it){ + QJsonValue v = *it; + QString title = v.toObject().value("title").toString().toLower(); + QString curId = v.toObject().value("release-group").toObject().value("id").toString(); + qDebug() << mAlbum << title; + if(mAlbum == title){ + if(!mData.contains(curId)){ + mData << curId; + } + }else{ + mOtherData.insert(title, curId); + } + } + reply->deleteLater(); + emit done(); +} diff --git a/webdownloader.h b/webdownloader.h new file mode 100644 index 0000000..522ec86 --- /dev/null +++ b/webdownloader.h @@ -0,0 +1,32 @@ +#ifndef WEBDOWNLOADER_H +#define WEBDOWNLOADER_H + +#include <QObject> +#include <QNetworkAccessManager> +#include <QMap> + +class WebDownloader : public QObject { + Q_OBJECT + public: + WebDownloader(QObject *parent = 0); + void fetchData(QString artist, QString album); + const QString album() const { return mAlbum; } + const QString artist() const { return mArtist; } + const QStringList data() const { return mData; } + const QMap<QString, QString> otherData() const { return mOtherData; } + + signals: + void done(); + + private slots: + void dlFinished(QNetworkReply *reply); + + private: + QNetworkAccessManager *mAccessMgr; + QString mArtist; + QString mAlbum; + QStringList mData; + QMap<QString, QString> mOtherData; +}; + +#endif // WEBDOWNLOADER_H |