From 7200f520e2cf6547988a3537c467798567713556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E7=90=BC?= Date: Sun, 4 Jan 2015 18:46:19 +0800 Subject: [PATCH] first commit --- .gitignore | 7 + KylinPlayer.icns | Bin 0 -> 31963 bytes KylinPlayer.png | Bin 0 -> 10872 bytes KylinPlayer.pro | 36 ++++ Qt.png | Bin 0 -> 22269 bytes README.md | 15 +- common.h | 44 +++++ database.cpp | 102 +++++++++++ database.h | 24 +++ main.cpp | 10 ++ network.cpp | 217 +++++++++++++++++++++++ network.h | 39 ++++ next.png | Bin 0 -> 6970 bytes osdlyricswidget.cpp | 197 +++++++++++++++++++++ osdlyricswidget.h | 41 +++++ pause.png | Bin 0 -> 6362 bytes play.png | Bin 0 -> 7602 bytes playermainwindow.cpp | 413 +++++++++++++++++++++++++++++++++++++++++++ playermainwindow.h | 71 ++++++++ playermainwindow.ui | 340 +++++++++++++++++++++++++++++++++++ prev.png | Bin 0 -> 6975 bytes resource.qrc | 10 ++ ubuntukylin.png | Bin 0 -> 10872 bytes 23 files changed, 1565 insertions(+), 1 deletion(-) create mode 100644 KylinPlayer.icns create mode 100644 KylinPlayer.png create mode 100644 KylinPlayer.pro create mode 100644 Qt.png create mode 100644 common.h create mode 100644 database.cpp create mode 100644 database.h create mode 100644 main.cpp create mode 100644 network.cpp create mode 100644 network.h create mode 100644 next.png create mode 100644 osdlyricswidget.cpp create mode 100644 osdlyricswidget.h create mode 100644 pause.png create mode 100644 play.png create mode 100644 playermainwindow.cpp create mode 100644 playermainwindow.h create mode 100644 playermainwindow.ui create mode 100644 prev.png create mode 100644 resource.qrc create mode 100644 ubuntukylin.png diff --git a/.gitignore b/.gitignore index b8bd026..10109a9 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,10 @@ *.exe *.out *.app + +#qt +*.pro.user +*.pro.user* + +#mac os x +.DS_Store diff --git a/KylinPlayer.icns b/KylinPlayer.icns new file mode 100644 index 0000000000000000000000000000000000000000..be25345e039b530352b3800d18fe29f94b1b0fcd GIT binary patch literal 31963 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 azsZfz@*dMj?Kb{t=gUbcNmh%S1phD7+Ji#? literal 0 HcmV?d00001 diff --git a/KylinPlayer.pro b/KylinPlayer.pro new file mode 100644 index 0000000..4d0a6b4 --- /dev/null +++ b/KylinPlayer.pro @@ -0,0 +1,36 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2014-07-19T11:54:34 +# +#------------------------------------------------- + +QT += core gui multimedia network sql multimediawidgets +linux { + QT += x11extras + LIBS += -lXext -lX11 +} +mac { + ICON = KylinPlayer.icns +} +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = KylinPlayer +TEMPLATE = app + + +SOURCES += main.cpp\ + playermainwindow.cpp \ + network.cpp \ + database.cpp \ + osdlyricswidget.cpp + +HEADERS += playermainwindow.h \ + network.h \ + common.h \ + database.h \ + osdlyricswidget.h + +FORMS += playermainwindow.ui + +RESOURCES += \ + resource.qrc diff --git a/Qt.png b/Qt.png new file mode 100644 index 0000000000000000000000000000000000000000..9ecfc2686478b3ce4eee18ecb9cb1b2f09f91c85 GIT binary patch literal 22269 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 +#include +#include + + +typedef struct KChannel +{ + QString id; + QString title; +}KChannel; + +typedef struct KMediaInfo +{ + int32_t id; + QString songId; + QString songName; + QString artistName; + QString albumName; + QString songPicUrl; + QString lrcUrl; + QString mp3Url; + bool operator ==(const KMediaInfo &info) + { + return this->id == info.id; + } + KMediaInfo& operator =(const KMediaInfo &info) + { + this->id = info.id; + this->albumName = info.albumName; + this->artistName = info.artistName; + this->lrcUrl = info.lrcUrl; + this->mp3Url = info.mp3Url; + this->songId = info.songId; + this->songName = info.songName; + this->songPicUrl = info.songPicUrl; + return *this; + } +}KMediaInfo; + +#endif // COMMON_H + + diff --git a/database.cpp b/database.cpp new file mode 100644 index 0000000..ecfba7f --- /dev/null +++ b/database.cpp @@ -0,0 +1,102 @@ +#include "database.h" +#include + + +#define DATABASE_CREATE_SQL "CREATE DATABASE \ + `KylinPlayer` DEFAULT CHARACTER SET utf8;" + +#define TABLE_CREATE_SQL \ + "CREATE TABLE FavoriteSong "\ + "(id INTEGER PRIMARY KEY, song_id NUMERIC, song_name TEXT, album_name TEXT, "\ + "singer_name TEXT, song_url TEXT, artcover_url TEXT, lrc_url TEXT,UNIQUE(song_id));" + +#define INSERT_SONG_SQL "REPLACE INTO FavoriteSong \ + (song_id, song_name, album_name, singer_name, \ + song_url, artcover_url, lrc_url) \ + VALUES (?, ?, ?, ?, ?, ?, ?)" + +#define SELECT_SONG_SQL "SELECT song_id, song_name, album_name, \ + singer_name,song_url,artcover_url,lrc_url \ + FROM FavoriteSong;" + + +Database::Database(QObject *parent) : + QObject(parent) +{ +} + +bool Database::initDataBase() +{ + qDebug() << QSqlDatabase::drivers(); + this->database = QSqlDatabase::addDatabase("QSQLITE"); + if(!this->database.isValid()) + { + return false; + } + qDebug() << "isValid"; + QString dbPath = QDir::homePath() + "/.KylinPlayer.db3"; + dbPath = QDir::toNativeSeparators(dbPath); + this->database.setDatabaseName(dbPath);//database name +// this->database.setConnectOptions("CLIENT_SSL=1;CLIENT_IGNORE_SPACE=1");//use SSL + if(this->database.open()) + { + qDebug()<<"open "<database.lastError().driverText(); + }else + { + qDebug()<<"open failed"; + return false; + } + qDebug()<< this->database.databaseName(); + qDebug()<< this->database.tables(); + QSqlQuery query(this->database); +#if 0 + query.exec(DATABASE_CREATE_SQL); + query.exec("use KylinPlayer;"); +#endif + bool ret = query.exec(TABLE_CREATE_SQL); + + return ret; +} + +bool Database::addFavoriteSong(KMediaInfo songInfo) +{ + QSqlQuery query(this->database); + query.prepare(INSERT_SONG_SQL); + query.addBindValue(songInfo.id); + query.addBindValue(songInfo.songName); + query.addBindValue(songInfo.albumName); + query.addBindValue(songInfo.artistName); + query.addBindValue(songInfo.mp3Url); + query.addBindValue(songInfo.songPicUrl); + query.addBindValue(songInfo.lrcUrl); + bool ret = query.exec(); + qDebug() << "qurey exec:" << ret ; + query.finish(); + return ret; +} + +QList *Database::getFavoriteSong() +{ + QSqlQuery query(this->database); + QList *mediaInfoList = new QList(); + bool ret = query.exec(SELECT_SONG_SQL); + if(!ret) + { + return NULL; + } + while(query.next()) + { + KMediaInfo info; + info.id = query.value(0).toInt(); + info.songId = QString("%1").arg(info.id); + info.songName = query.value(1).toString(); + info.albumName = query.value(2).toString(); + info.artistName = query.value(3).toString(); + info.mp3Url = query.value(4).toString(); + info.songPicUrl = query.value(5).toString(); + info.lrcUrl = query.value(6).toString(); + mediaInfoList->append(info); + } + query.finish(); + return mediaInfoList; +} diff --git a/database.h b/database.h new file mode 100644 index 0000000..83f6e81 --- /dev/null +++ b/database.h @@ -0,0 +1,24 @@ +#ifndef DATABASE_H +#define DATABASE_H + +#include +#include +#include +#include "common.h" +class Database : public QObject +{ + Q_OBJECT +public: + explicit Database(QObject *parent = 0); + +signals: + +public slots: + bool initDataBase(); + bool addFavoriteSong(KMediaInfo songInfo); + QList *getFavoriteSong(); +private: + QSqlDatabase database; +}; + +#endif // DATABASE_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..cae5fd0 --- /dev/null +++ b/main.cpp @@ -0,0 +1,10 @@ +#include "playermainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + PlayerMainWindow w; + w.show(); + return a.exec(); +} diff --git a/network.cpp b/network.cpp new file mode 100644 index 0000000..f96526e --- /dev/null +++ b/network.cpp @@ -0,0 +1,217 @@ +#include "network.h" +#include +#include +#include +#include + + +Network::Network(QObject *parent) : + QObject(parent) +{ + this->networkAccessManager = new QNetworkAccessManager(this); +} + +Network::~Network() +{ + delete networkAccessManager; +} + +void Network::getContentOfURL(QString url) +{ + QNetworkRequest request; + request.setUrl(QUrl(url)); + request.setRawHeader("User-Agent", "KylinPlayer 1.0"); + QNetworkReply *reply = this->networkAccessManager->get(request); + + connect(reply, SIGNAL(finished()), this, SLOT(handleGetFinished())); +} + +void Network::fetchChannels(QString url) +{ + QNetworkRequest request; + request.setUrl(QUrl(url)); + request.setRawHeader("User-Agent", "KylinPlayer 1.0"); + QNetworkReply *reply = this->networkAccessManager->get(request); + + connect(reply, SIGNAL(finished()), this, SLOT(handleFetchChannelsFinished())); +} + +void Network::fetchMediaInfoList(QString url) +{ + QNetworkRequest request; + request.setUrl(QUrl(url)); + request.setRawHeader("User-Agent", "KylinPlayer 1.0"); + QNetworkReply *reply = this->networkAccessManager->get(request); + + connect(reply, SIGNAL(finished()), this, SLOT(handleFetchMediaInfoListFinished())); +} + +void Network::fetchSongInfo(QString url) +{ + QNetworkRequest request; + request.setUrl(QUrl(url)); + request.setRawHeader("User-Agent", "KylinPlayer 1.0"); + QNetworkReply *reply = this->networkAccessManager->get(request); + + connect(reply, SIGNAL(finished()), this, SLOT(handleFetchSongInfoFinished())); +} + +void Network::fetchImage(QString url) +{ + QNetworkRequest request; + request.setUrl(QUrl(url)); + request.setRawHeader("User-Agent", "KylinPlayer 1.0"); + QNetworkReply *reply = this->networkAccessManager->get(request); + + connect(reply, SIGNAL(finished()), this, SLOT(handleFetchImageFinished())); +} + +void Network::fetchLyrics(QString url) +{ + QNetworkRequest request; + request.setUrl(QUrl(url)); + request.setRawHeader("User-Agent", "KylinPlayer 1.0"); + QNetworkReply *reply = this->networkAccessManager->get(request); + + connect(reply, SIGNAL(finished()), this, SLOT(handleFetchLyricsFinished())); +} + +void Network::handleGetFinished() +{ + QNetworkReply *reply = (QNetworkReply *)sender(); + if(reply->hasRawHeader("Location")){ + QString strLocation = reply->header(QNetworkRequest::LocationHeader).toString(); + qDebug() << strLocation; + this->getContentOfURL(strLocation); + return; + } + QByteArray strHttpData; + strHttpData = reply->readAll(); + emit this->contentGetted(new QByteArray(strHttpData)); +} + +void Network::handleFetchChannelsFinished() +{ + QNetworkReply *reply = (QNetworkReply *)sender(); + if(reply->hasRawHeader("Location")){ + QString strLocation = reply->header(QNetworkRequest::LocationHeader).toString(); +// qDebug() << strLocation; + this->fetchChannels(strLocation); + return; + } + QByteArray strHttpData; + strHttpData = reply->readAll(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(strHttpData); + if(jsonDoc.isNull() ||!jsonDoc.isArray()) + {// null or not array format + return; + } + QJsonArray channels = jsonDoc.array(); + QList *channelList = new QList(); + for(int i = 0; i < channels.count(); i++) + { + QJsonValue value = channels[i]; + QString id = value.toObject().value("id").toString(); + QString title = value.toObject().value("title").toString(); +// qDebug()<append(channel); + } + emit this->musicChannelsFetched(channelList); +} + +void Network::handleFetchMediaInfoListFinished() +{ + QNetworkReply *reply = (QNetworkReply *)sender(); + if(reply->hasRawHeader("Location")){ + QString strLocation = reply->header(QNetworkRequest::LocationHeader).toString(); + qDebug() << strLocation; + this->fetchMediaInfoList(strLocation); + return; + } + QByteArray strHttpData; + strHttpData = reply->readAll(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(strHttpData); + if(jsonDoc.isNull() ||!jsonDoc.isObject()) + {// null or not object format + return; + } + QJsonObject jsonObj = jsonDoc.object(); + QJsonArray mediaArray = jsonObj.value("list").toArray(); + QList *mediaList = new QList(); + for(int i = 0; i < mediaArray.count(); i++) + { + KMediaInfo mediaInfo; + QJsonObject jsonObj2 = mediaArray[i].toObject(); + mediaInfo.id = jsonObj2.value("id").toInt(); + mediaList->append(mediaInfo); +// qDebug()<<"id:"<mediaInfoListFetched(mediaList); +} + +void Network::handleFetchSongInfoFinished() +{ + QNetworkReply *reply = (QNetworkReply *)sender(); + if(reply->hasRawHeader("Location")){ + QString strLocation = reply->header(QNetworkRequest::LocationHeader).toString(); + qDebug() << strLocation; + this->fetchMediaInfoList(strLocation); + return; + } + QByteArray strHttpData; + strHttpData = reply->readAll(); + QJsonDocument jsonDoc = QJsonDocument::fromJson(strHttpData); + if(jsonDoc.isNull() ||!jsonDoc.isObject()) + {// null or not object format + return; + } + QJsonObject jsonObj = jsonDoc.object(); + QJsonArray songArray = jsonObj.value("data").toObject().value("songList").toArray(); + if(songArray.count()<=0) + { + return; + } + QJsonObject infoObj = songArray.first().toObject(); + KMediaInfo mediaInfo; + mediaInfo.id = infoObj.value("songId").toInt(); + mediaInfo.songName = infoObj.value("songName").toString(); + mediaInfo.artistName = infoObj.value("artistName").toString(); + mediaInfo.albumName = infoObj.value("albumName").toString(); + mediaInfo.songPicUrl = infoObj.value("songPicRadio").toString(); + mediaInfo.mp3Url = infoObj.value("songLink").toString(); + mediaInfo.lrcUrl = infoObj.value("lrcLink").toString(); + + + emit this->mediaInfoFetched(mediaInfo); +} + +void Network::handleFetchImageFinished() +{ + QNetworkReply *reply = (QNetworkReply *)sender(); + if(reply->hasRawHeader("Location")){ + QString strLocation = reply->header(QNetworkRequest::LocationHeader).toString(); + qDebug() << strLocation; + this->fetchMediaInfoList(strLocation); + return; + } + QByteArray strHttpData; + strHttpData = reply->readAll(); + emit this->imageDataFetched(new QByteArray(strHttpData)); +} + +void Network::handleFetchLyricsFinished() +{ + QNetworkReply *reply = (QNetworkReply *)sender(); + if(reply->hasRawHeader("Location")){ + QString strLocation = reply->header(QNetworkRequest::LocationHeader).toString(); + qDebug() << strLocation; + this->fetchMediaInfoList(strLocation); + return; + } + QByteArray strHttpData; + strHttpData = reply->readAll(); + emit this->lyricsDataFetched(new QByteArray(strHttpData)); +} diff --git a/network.h b/network.h new file mode 100644 index 0000000..b43e9c6 --- /dev/null +++ b/network.h @@ -0,0 +1,39 @@ +#ifndef NETWORK_H +#define NETWORK_H + +#include +#include +#include "common.h" + +class Network : public QObject +{ + Q_OBJECT +public: + explicit Network(QObject *parent = 0); + ~Network(); +signals: + void contentGetted(QByteArray *content); + void musicChannelsFetched(QList *channelList); + void mediaInfoListFetched(QList *mediaInfoList); + void mediaInfoFetched(KMediaInfo); + void imageDataFetched(QByteArray *imageData); + void lyricsDataFetched(QByteArray *imageData); +public slots: + void getContentOfURL(QString url); + void fetchChannels(QString url); + void fetchMediaInfoList(QString url); + void fetchSongInfo(QString url); + void fetchImage(QString url); + void fetchLyrics(QString url); + void handleGetFinished(); + void handleFetchChannelsFinished(); + void handleFetchMediaInfoListFinished(); + void handleFetchSongInfoFinished(); + void handleFetchImageFinished(); + void handleFetchLyricsFinished(); +private: + QNetworkAccessManager *networkAccessManager; + +}; + +#endif // NETWORK_H diff --git a/next.png b/next.png new file mode 100644 index 0000000000000000000000000000000000000000..95a14ea5f65b05643136607e25fa0eed4c0c9eb9 GIT binary patch literal 6970 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 C5ga-I literal 0 HcmV?d00001 diff --git a/osdlyricswidget.cpp b/osdlyricswidget.cpp new file mode 100644 index 0000000..b667300 --- /dev/null +++ b/osdlyricswidget.cpp @@ -0,0 +1,197 @@ +#include "osdlyricswidget.h" +#include +#include +#include +#include +#include +#ifdef Q_OS_LINUX +#include +#include +#endif +#ifdef Q_OS_WIN32 +#include +#endif +OSDLyricsWidget::OSDLyricsWidget(QWidget *parent) : + QWidget(parent) +{ + this->lrcLineList = new QList(); + this->timer = new QTimer(this); + this->timer->setInterval(100); + this->timer->start(); + connect(this->timer, SIGNAL(timeout()), this, SLOT(handleTimeout())); + +// this->currentLyrics = QString("戴维营教育嵌入式Linux Qt5开发培训学习作品"); + this->setFixedSize(1000,100); + this->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint); + this->setAttribute(Qt::WA_TranslucentBackground,true); + this->setAttribute(Qt::WA_TransparentForMouseEvents,true); + this->setAttribute(Qt::WA_MouseTracking,false); + this->setWindowOpacity(1); + QSize size = QApplication::screens().first()->geometry().size(); + this->move( (size.width() - this->width())/2, (size.height() - this->height()) - 100 ); +#ifdef Q_OS_LINUX + XShapeCombineRectangles(QX11Info::display(), winId(), ShapeInput, 0, + 0, NULL, 0, ShapeSet, YXBanded); +#endif +#ifdef Q_OS_WIN + SetWindowLong((HWND)winId(), GWL_EXSTYLE, GetWindowLong((HWND)winId(), GWL_EXSTYLE) | + WS_EX_TRANSPARENT | WS_EX_LAYERED); + SetWindowPos((HWND)winId(),HWND_TOP,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); +#endif +} + +OSDLyricsWidget::~OSDLyricsWidget() +{ + + delete this->lrcLineList; + delete this->timer; + +} + +void OSDLyricsWidget::mousePressEvent(QMouseEvent *event) +{ + this->windowPos = this->pos(); + QPoint mousePos = event->globalPos(); + this->dPos = mousePos - windowPos; +} + +void OSDLyricsWidget::mouseMoveEvent(QMouseEvent *event) +{ + this->move(event->globalPos() - this->dPos); +} + +void OSDLyricsWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + if(this->currentLyrics.isEmpty()) + { + return; + } + QPainter painter(this); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.setRenderHints(QPainter::TextAntialiasing|QPainter::Antialiasing); + QFont font = QFont("宋体", 36); + painter.setFont(font); + int textPixalLength = 0; +#if 1 + QFontMetrics fontMetrics = QFontMetrics(font); + textPixalLength = fontMetrics.boundingRect(this->currentLyrics).width(); +#else + textPixalLength = this->rect().width(); +#endif + QRect rect_l = this->rect(); + painter.fillRect(rect_l, Qt::transparent); + + + painter.setPen(QColor("lightgreen")); + painter.drawText(rect_l,Qt::AlignLeft|Qt::AlignVCenter,this->currentLyrics); + + float percent = 1 - (1.0*this->curLyricTimeLeft)/this->curLyricTime; + QRect rect_h(rect_l.x(), rect_l.y(),textPixalLength*percent,rect_l.height()); + painter.setPen(QColor("transparent")); + painter.drawRect(rect_h); + painter.setPen(QColor("red")); + painter.drawText(rect_h,Qt::AlignLeft|Qt::AlignVCenter,this->currentLyrics); +// qDebug()<<"lrc:"<currentLyrics << "percent:"<lrcLineList->clear(); + this->currentLyrics = ""; + if(NULL==lrcData) + { + return; + } + QStringList lrcList = QString(*lrcData).split("\n"); + foreach (QString lrc, lrcList) { + if(lrc.size()<=5) continue; + lrc = lrc.toLower().simplified(); + if(lrc.startsWith("[ti:") || lrc.startsWith("[ar:") || lrc.startsWith("[al:")) + { + continue; + } + //process lyric line + this->processLyricLine(lrc); + } + qSort(*this->lrcLineList); +} + + void OSDLyricsWidget::processLyricLine(QString line) +{ + if(!line.startsWith("[")) return; + int timeStampEndPos = line.lastIndexOf("]"); + if(timeStampEndPos < 9 ) return; + QString lrcLineStr = line.mid(timeStampEndPos+1); + QString timeStampStr = line.left(timeStampEndPos+1); + + QStringList timeStrList = timeStampStr.split("]"); + foreach (QString timeStr, timeStrList) { + if(!timeStr.startsWith("[")) continue; + timeStr.remove(0,1); + int min = 0, sec = 0, msec = 0; + ::sscanf(timeStr.toStdString().data(),"%d:%d.%d", &min, &sec, &msec); + long milliseconds = min*60*1000 + sec*1000 + msec*10; + LrcLine lrc_line; + lrc_line.milliseconds = milliseconds; + lrc_line.lineStr = lrcLineStr; + this->lrcLineList->append(lrc_line); + + } + + +} + +void OSDLyricsWidget::updateLyrics(long timePos) +{ + + for(int i = 1; i < this->lrcLineList->count(); i++) + { + LrcLine line = this->lrcLineList->at(i); + if(line.milliseconds > timePos) + { + if(this->curIndex == i) + { + break; + } + this->curIndex = i; + LrcLine prevLine = this->lrcLineList->at(i-1); + this->currentLyrics = prevLine.lineStr; + this->curLyricTimeLeft = this->curLyricTime = line.milliseconds - prevLine.milliseconds; + break; + } + } + this->update(); + this->updateGeometry(); +} + +void OSDLyricsWidget::handleTimeout() +{ + + if(this->curLyricTimeLeft > (unsigned long)this->timer->interval()) + { + this->curLyricTimeLeft -= this->timer->interval(); + }else + { + this->curLyricTimeLeft = 0; + } +// qDebug()<<"left:"<curLyricTimeLeft; + +} + +void OSDLyricsWidget::pauseTimer(bool stop) +{ + if(stop){ + this->timer->stop(); + }else + { + this->timer->start(); + } +} + + +bool LRCLine::operator <(const LRCLine &line) const +{ + return this->milliseconds < line.milliseconds; +} diff --git a/osdlyricswidget.h b/osdlyricswidget.h new file mode 100644 index 0000000..d25f702 --- /dev/null +++ b/osdlyricswidget.h @@ -0,0 +1,41 @@ +#ifndef OSDLYRICSWIDGET_H +#define OSDLYRICSWIDGET_H + +#include +#include +#include +typedef struct LRCLine{ + long milliseconds; + QString lineStr; + bool operator <(const LRCLine &line) const; +}LrcLine; + + +class OSDLyricsWidget : public QWidget +{ + Q_OBJECT +public: + explicit OSDLyricsWidget(QWidget *parent = 0); + ~OSDLyricsWidget(); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event); + +signals: + +public slots: + void handleNewLyricsData(QByteArray *lrcData); + void processLyricLine(QString line); + void updateLyrics(long timePos); + void handleTimeout(); + void pauseTimer(bool stop); +private: + QPoint windowPos, dPos; + QString currentLyrics; + int curIndex; + QList *lrcLineList; + unsigned long curLyricTime,curLyricTimeLeft; + QTimer *timer; +}; + +#endif // OSDLYRICSWIDGET_H diff --git a/pause.png b/pause.png new file mode 100644 index 0000000000000000000000000000000000000000..d3959dce177c12210bf2142e0d5e0bcdbe84edb8 GIT binary patch literal 6362 zcmdT|cT|(vwvR9~%nT!#p(zN=gi$&uHAtN?^frN!Pz)#tNC!g+B_QJyFhCfoA_0_o z6#*kvLYWZ|rG*XxCJ>~A7DEb<0C^vGy?5Vw>#lp(_1-`3dnbQ<`^)K+ySc=bPAuG(KuxPR5oOuA9^9`(|e>3i#p0K8xJ)a%gs zMs{PSwz75jQX$&g|7^?o;(*r?c1BmKia+xQ5s0&rU!GFS5c^W!lK7q3i60&l8*7YL zx8!eBL9IT@Jx0au?k5~2;#TzO>+hNGciUHE6#&=%502ZRxtEMVwNc|-w(5qUATzL` z;ZV`ZeS{V}TU)PGCDYMi=?@H-XRd_!jj39;0|~Y(edY`;_K-b|-~eOV&wsVlD&Wz$ zc9Vw}{A>V=GdwsvELZ&C!QPw$>GH;xw+%j2u{RJ?@$vdn${`tPH4tiln(O=`q3vyC z1uIfVnq*PSF@w#U>gjQ=R;QMs^g`#+<~9K+*fU2kqNixpE;@`$U$_P{%7K&w!h*we zq<7PQeR&!5%Y2o6(Xhrk+p#h?R2fpY#WIp$1y@8O934sYu({?CM0M(8wqD3=ql$E9 zsVXG&UfRGVW5-@`FvAKQfv9!ian{z>k{v{QXks9VsBwFJ_2S~f{h0e>{tDDh2a>kX zAPk;Btgffq0>+9qSr_oJmoHx~n1FP;!seyHnBo$D5$Mmb1dN~GN{f8L$3OHh8Gkbb z*wWV08f%E5lfA6KF|eK&$EIYnaub7&4)(n|dE3OS=(y8lqPj=3+MlL3yfVu6S{8SX z&LCjza^SA^>)k2*2;No;U`%xRtJ`0nk(O?QRztvvDOFF=PAK``ym`|Wi=Hn^Dyq$jgiEOc4inAC98H`5n<$xJO;q?})m5rf84|N4|a&mlt0Gwsyq`5Y*gtl?iDZu*7 zxf+CN11fO+iGyhO+gKl(Q&CuZ1hU*E{=$6IJkp7~>f_^+G()?HCO&@rxYQopMWGq& zUF>tN<%pG+mz%D!zH2WAt^K4=Nnlb7X|z5CYW8?6rbF*kJS8Tioxl=|Kr<>Y8b8vm<#ULK97exx1cq$*T4MW5Q#DAEgw zOB%gtBv~C>I%vl?Agp4hdyguod+y(r>I2>{&JiyFMoSj0i5^($5Nf68@#zO-nRJmO zrTk3{B){Y6=7hAO!)__&XphC3O_hsV8!5!+?P}D=+`*m(vOotjm_wbRe%GwqTjPH4 zbZ6(l>BW>^->#&%V=fK9?=W_uAA}B?jvcHdDN{#f^n&-kqQq{CC@3fx^Eg}aKVZF) z4fVz^u3fQ1a^Iq(mR~DnJHi|*={1V?*FRaQ;t>mRGV*T+1{$tV}$>LL%P(KO*`jHU*Lvs>oRaYfZ)wO>!oOFxQ;M)Z=?OSp{F2}h#dlOOmQ;`SKjs{7KJ z8;DO-P> zJU_U`uMA&USm=_PGg$CC{^qK|eiZ+Q1vc1bF72TW5c(psaBx1(@hnYF;9 zba6H}Nr~7DWXp(gpOT@F?$Q!omVjULIP3U~Hv~1I&+lm3(3rp~9o80MW3+&}B5%&H z^_`Y4itz+gH2dzEIKD9v!>PH;0vb*_as5efWrZ*qqZ`8Wf97d|HJ~lcra?Yuz zum71UL>Doy6S6brsD~=tlh4e^*gJA9sznl;H6eNhZid?74t7ZQHVNoSl2?=mOa08fX!d(nGmsO>grO@O&FTNkvbgol;8sP0C+$bHClyTyG79X@2oy+;%rt9_CAnm3@P>g2eI+|C+`hU)PT zplu6fPC?G_tM8~0dpsLCrh>3bFJWKR!}uha5Z2qK`M@bWIL2<0E#aUuOdDcnMyvXnfT?}2xELWyn62YhWxTlSrj zMYcYjEdMC!TMrTktGXL~9fnxP8&L59H446@!m{w;$mB6EbX62K&D?ith*j#tT+vhE z6*I)I`xkOlqXZWQZ=eB9i^=;E1bXuu2z2|Kul~01 z?(5dT&4v?05yQV*zXa}aXTAl2e*6B!rwF2gPqW44g2xxX|pxS_i6lrZVXgHBEQt6qbi`&4BWLank6$za?B7ggE%Ng;TgKxEeH&GixLOy>N% zmH+wpzZKOB(ClmD;o0zu;u&!Xp*NHL;r|s4BpcO~j{$Ang&-oaKYWG?P-CKRNzy z=N>i}0LsIKoLkRSdnNuh(EoZ5978|2>8tWRO<+5b8Rv65z! zGeI){1o)13_Xju7mF!oYD_b925v8cAj(=(S1wM88|Jws^FVw#QeE%~$6M$X~P=7o> zx&9oN*&VgpPYKg{I(-I$ipxMxeZvX_GE4dF9}t2+zj{tNIB53YQg{DS*gsr1yF&fr z{D{%29ZD2&pmN?==c6(qgv^K4db;XcUsoeV~1hzT<-p;yTBviinPnVQ*8M;$~qjKezdfV zivdSG?=AlrojRbV!qfgRxTeZ8e5!=kMw)>llOfb5t&J7=naSg?Kj(R=5m}Qi!+%(d zo4-W)bpgk&WG-KJ8BY^v7TEqm+1P7^d3cu>Z9%$M4yTt=QXWI&cfIo55$WhoV2WLF zW#dvvXhKWWYCE@LD`2i7hWoSHjJ{i7$o>C1x<7ZaA?3SI|Ecdqfm{$9+EbKdFl@Sa z>q%2)nv<#NFg|xo+jmNRhVMOSxMx$-_dO(^&P}&E7bc*_Gt8O-E{)fsqd7cqMA_hM z9w{V9g2bTq~y>)S+!jeN|1@ASUp4mIt~h{jq4Gppb}>HAL9Jx zBgr=Do=F<{o$cilvk>ZH$Xv5*0K+QxJ5ZbD%NTrF+JM}VU%KVnxdohQ8ky##UuX%N zCq`{d#i_0?Zbfg-L_o~vJ^Vr_j5`GGJ)*m@QzsUp5nu6yVoeE}RMN2oMcyNm$wWxm zgwRb}FEV)56y=z%*gsC4F2Moq2BmVkx@@mo64z~b6P7^SoK5H73Q|ja-#1(v{)cvw zq-`|+`Q}a>>;Nv@_xLM;N4CMo{DQbSO;lBr&!n)0x4w~qzEG??bI7*J%uX7qZj5hM z>ZhpvekN++_vCos(kYwxnM&T|9+bKWak#ACP}uy^uTMN>ygs7yu7?-OpLm^ zBB;$uovP|P%^8%-5}oG_5Ee3}+zp)cxLI3SqGYE0(zEW$PER>7_{r$rdQVSJuy7w$ zc5{ZX1XID*=OIn$Bb3)d^h3u{edPMo33Bf%Ob#QN*Eus0nr?2>HTmlP&1}#bWH*dr zBB`85BpQ$t#@*w0yY8KvISN>%&j6Wk|-_b0|xXZJ& z4e5o*`GBj!7i4tjsujp|1);{0&0eY41C3QSp< zYfnfz%rT2V9TNg7&?Yttd}72m+QELyT^owN4ohg=3~~~W-~>7L?UUxknkyy(lx_8K*Y<-T=(*jE!L7ufQh`E*a%@(k>I$>yMyyXZTKPvCH?W^bvO87+feN z(cd;@snMFE5y>3V*EG3k+)@NJKzWxfU8k=YKsaE-ZU(hyVEk)7_meW zSH{$gqdxlJD&4oZqoZ(rm8kEh+uJ69v8@|4Wh4PsSo9mJ`wfy95}a_bQCxB-XU;&E z-EI4YkaI5D>Qo3E;Kc%igM-V)?}Xn1I%0bV2a^WBp@#?s>QZsZxp?!4)fvtfzjNH@ z<8ZWtgTphohLwXf*EyP-7NVkTZ*XR>wZ<1Y=#`HQ1sofOP*=-7bpHxvV$(FULMTUt z4x}FqHm2+OcH+HZF>$yIdrKQr?KTXL9u;?rTo?~h@kXQ3DDmDH1@C}r|F>`KDp=_N zOSJ7-_h@l(kz@f+(1j%EH)A*!HVVN1bB4xW(j7p*ycro8>7@-}8tXS$YA8>*ogT!5 zfZ=g04UNC94g(0QHYF?(;vH4(U$}uyOATzARRH0Nd%yHQl@<$k**4o z&^0n@R|8soY}y>e8(zIyDChv|iNU5BzV7SeSB-avuY{1>_g`3)GgRT?EihQv@h2h{ zHk7rkt;2rI?)z0`TZtb)D%&YCp{}=FlK8bivknlRjpNK;?7<8>6)e%ok<@a)&Q1l` zvUCNizjKc|I3l)s^~nPWL=Km`{d9VRQuyG(426~q#RyyzdDkAx+|RV|0n(WXj<^E5 zdIp?sXm|xth|4X(SuDMSR0=uU%x$g}v}DTYdyeLe=%4<~M;nAM{0_{mzzY*$ o**VHH{Y3u{lI?&?BZ+*`ozTThU9I@~V-Ky(9bk1oUHkPv0o$o*bN~PV literal 0 HcmV?d00001 diff --git a/play.png b/play.png new file mode 100644 index 0000000000000000000000000000000000000000..5c39ba8253b6fa707787adecf52714f936c10801 GIT binary patch literal 7602 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 Y6y1;fxZ7t4$!lYhp0RHFe=gnnKg8`X@c;k- literal 0 HcmV?d00001 diff --git a/playermainwindow.cpp b/playermainwindow.cpp new file mode 100644 index 0000000..b03facd --- /dev/null +++ b/playermainwindow.cpp @@ -0,0 +1,413 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "playermainwindow.h" +#include "ui_playermainwindow.h" +#include "network.h" + +#define KMusicChannelsURL "http://raw.github.com/iosnews/test/master/baidu.json" +#define kMusicPlaylistURL "http://fm.baidu.com/dev/api/?tn=playlist&special=flash&prepend=&format=json&&id=" +#define kMusicURL "http://music.baidu.com/data/music/fmlink?type=mp3&rate=2&format=json&songIds=" +#define kMusicLRCURL "http://fm.baidu.com/" +PlayerMainWindow::PlayerMainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::PlayerMainWindow) +{ + ui->setupUi(this); + this->osdLyricsWidget = new OSDLyricsWidget(); + this->osdLyricsWidget->show(); + this->localMediaPlayList = new QMediaPlaylist(this); + this->onlineMediaPlayList = new QMediaPlaylist(this); + this->onlineMediaList = new QList(); + this->mediaPlayer = new QMediaPlayer(this); + this->mediaPlayer->setPlaylist(this->localMediaPlayList); + this->mediaPlayer->setVolume(50); + this->progressTimer = new QTimer(this); + this->progressTimer->setInterval(100); + this->network = new Network(this); + network->fetchChannels(KMusicChannelsURL); + + this->setupConnections(); + + this->dbOK = db.initDataBase(); + + +} + +PlayerMainWindow::~PlayerMainWindow() +{ + delete ui; + delete localMediaPlayList; + delete mediaPlayer; + delete progressTimer; + delete network; + delete onlineMediaList; + delete onlineMediaPlayList; + delete osdLyricsWidget; + +} + +void PlayerMainWindow::setupConnections() +{ + connect(ui->localAction, SIGNAL(triggered()), this, SLOT(openLocalMedia())); + connect(ui->netAction, SIGNAL(triggered()), this, SLOT(openInternetURL())); + connect(ui->playButton, SIGNAL(clicked()), this, SLOT(playButtonClicked())); + connect(ui->prevButton, SIGNAL(clicked()), this, SLOT(prevButtonClicked())); + connect(ui->nextButton, SIGNAL(clicked()), this, SLOT(nextButtonClicked())); + connect(ui->playTimeSlider, SIGNAL(sliderMoved(int)), this, SLOT(playSliderValueChanged(int))); + connect(ui->volumeDial, SIGNAL(valueChanged(int)), this, SLOT(volumeDialValueChanged(int))); + connect(ui->channelComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(channelIndexChanged(int))); + + connect(this->mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(playerStateChanged(QMediaPlayer::State))); + connect(this->mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus))); + + connect(this->progressTimer, SIGNAL(timeout()), this, SLOT(playProgressUpdate())); + connect(this->mediaPlayer, SIGNAL(metaDataChanged()), this, SLOT(metaDataUpdate())); + + connect(this->ui->aboutAction, SIGNAL(triggered()), this,SLOT(showAbout())); + connect(this,SIGNAL(destroyed()), this->osdLyricsWidget, SLOT(close())); + + //networks signals + connect(this->network, SIGNAL(musicChannelsFetched(QList*)), this, SLOT(channelsDownloaded(QList*))); + connect(this->network, SIGNAL(mediaInfoListFetched(QList*)), this, SLOT(mediaInfoListDownloaded(QList*))); + connect(this->network, SIGNAL(mediaInfoFetched(KMediaInfo)), this, SLOT(mediaInfoDownloaded(KMediaInfo))); + connect(this->network, SIGNAL(imageDataFetched(QByteArray*)), this,SLOT(AlbumImageDownloaded(QByteArray*))); + connect(this->network, SIGNAL(lyricsDataFetched(QByteArray*)), this->osdLyricsWidget, SLOT(handleNewLyricsData(QByteArray*))); + + //favorites + connect(this->ui->addFavAction, SIGNAL(triggered()), this, SLOT(addCurrentSongToFavorites())); + connect(this->ui->playFavAction, SIGNAL(triggered()), this, SLOT(playSongInFavorites())); +} + +void PlayerMainWindow::closeEvent(QCloseEvent *event) +{ + this->osdLyricsWidget->close(); + event->accept(); +} + +void PlayerMainWindow::openLocalMedia() +{ + QStringList fileNameList; + fileNameList = QFileDialog::getOpenFileNames(this, + tr("播放本地歌曲"), "", tr("MP3/MPEG4音频 (*.mp3 *.m4a);;")); + + if (!fileNameList.isEmpty()) + { + this->localMediaPlayList->clear(); + foreach (const QString &fileName, fileNameList) { + QMediaContent media = QMediaContent(QUrl::fromLocalFile(fileName)); + this->localMediaPlayList->addMedia(media); + } + + this->localMediaPlayList->setCurrentIndex(0); + } + else + { + //取消 + } + qDebug() << fileNameList; + return ; +} + +void PlayerMainWindow::openInternetURL() +{ + QString urlString; + bool ok; + urlString = QInputDialog::getText(this, + tr("播放网络歌曲"),tr("请输入歌曲网址(尚未实现)"),QLineEdit::Normal,"http://", &ok); + if (ok && !urlString.isEmpty()) + { + //inputed + } + qDebug() << urlString; + + return; +} + +void PlayerMainWindow::playButtonClicked() +{ + if(this->mediaPlayer->state() == QMediaPlayer::PlayingState) + { + this->mediaPlayer->pause(); + qDebug() << "pause"; + }else + { + this->mediaPlayer->setVolume(this->ui->volumeDial->value()); + this->mediaPlayer->play(); + qDebug() << "play"; + } +} + +void PlayerMainWindow::prevButtonClicked() +{ + qDebug() << "prev"; + QMediaPlaylist *currentPlayList = this->onlineMode?this->onlineMediaPlayList:this->onlineMediaPlayList; + currentPlayList->previous(); + this->osdLyricsWidget->handleNewLyricsData(NULL); +} + +void PlayerMainWindow::nextButtonClicked() +{ + qDebug() << "next"; + QMediaPlaylist *currentPlayList = this->onlineMode?this->onlineMediaPlayList:this->onlineMediaPlayList; + currentPlayList->next(); + this->osdLyricsWidget->handleNewLyricsData(NULL); +} + +void PlayerMainWindow::playSliderValueChanged(int value) +{ + qDebug() << "slider changed " << value; + float percent = (value * 1.0) / this->ui->playTimeSlider->maximum(); + int64_t pos = this->mediaPlayer->duration() * percent; + this->mediaPlayer->setPosition(pos); +} + +void PlayerMainWindow::volumeDialValueChanged(int value) +{ + qDebug() << "Dial changed " << value; + this->mediaPlayer->setVolume(value); +} + +void PlayerMainWindow::channelIndexChanged(int index) +{ + qDebug() << "combox changed " << index; + if(index < 0) + { + return; + }else if(index == 0) + { + //local media + this->onlineMode = false; + this->mediaPlayer->setPlaylist(this->localMediaPlayList); + return; + }else if(index == 1) + { + //update internet media channel + network->fetchChannels(KMusicChannelsURL); + this->onlineMode = true; + this->onlineMediaPlayList->clear(); + this->mediaPlayer->setPlaylist(this->onlineMediaPlayList); + return; + } + this->onlineMode = true; + this->onlineMediaPlayList->clear(); + this->mediaPlayer->setPlaylist(this->onlineMediaPlayList); + + QComboBox *channelComboBox = (QComboBox*)sender(); + QString channelID = channelComboBox->itemData(index).toString(); + this->network->fetchMediaInfoList(kMusicPlaylistURL + channelID); +} + +void PlayerMainWindow::playerStateChanged(QMediaPlayer::State state) +{ + if(QMediaPlayer::PlayingState == state) + { +// this->ui->playButton->setText(tr("暂停")); + this->ui->playButton->setIcon(QIcon(":/images/pause.png")); + this->progressTimer->start(); + this->osdLyricsWidget->pauseTimer(false); + }else + { +// this->ui->playButton->setText(tr("播放")); + this->ui->playButton->setIcon(QIcon(":/images/play.png")); + this->progressTimer->stop(); + this->osdLyricsWidget->pauseTimer(true); + } + qDebug() << "state changed " << state; +} + +void PlayerMainWindow::mediaStatusChanged(QMediaPlayer::MediaStatus status) +{ + switch(status) + { + case QMediaPlayer::NoMedia: + case QMediaPlayer::EndOfMedia: + this->mediaPlayer->playlist()->next(); + break; + default: + ; + } + + qDebug() << "status changed " << status; +} + +void PlayerMainWindow::playProgressUpdate() +{ + int64_t pos = this->mediaPlayer->position(); + int64_t duration = this->mediaPlayer->duration(); + int value = 100 * (1.0*pos)/duration; + this->ui->playTimeSlider->setValue(value); + this->osdLyricsWidget->updateLyrics(pos); +} + +void PlayerMainWindow::metaDataUpdate() +{ + QString title, subTitle, albumTitle, albumArtist; + QImage coverArtImage; + QPixmap pixmap; + if(!this->onlineMode) + { + title = this->mediaPlayer->metaData("Title").toString(); + subTitle = this->mediaPlayer->metaData("SubTitle").toString(); + albumTitle = this->mediaPlayer->metaData("AlbumTitle").toString(); + albumArtist = this->mediaPlayer->metaData("AlbumArtist").toString(); + coverArtImage = this->mediaPlayer->metaData("CoverArtImage").value(); + if(coverArtImage.isNull()) + { + pixmap = QPixmap(":/images/Qt.png"); + }else + { + pixmap.convertFromImage(coverArtImage); + } + }else + { + int curIndex = this->onlineMediaPlayList->currentIndex(); + if(curIndex < 0 || curIndex > this->onlineMediaList->count() - 1) + { + return; + } + KMediaInfo curInfo = this->onlineMediaList->at(curIndex); + title = curInfo.songName; + albumTitle = curInfo.albumName; + albumArtist = curInfo.artistName; + this->network->fetchImage(curInfo.songPicUrl); + this->network->fetchLyrics(kMusicLRCURL + curInfo.lrcUrl); + + } + + this->ui->singerLabel->setText("歌手: "+albumArtist); + this->ui->albumLabel->setText("专辑: "+albumTitle); + this->ui->songLabel->setText("歌名: "+title); + if(!pixmap.isNull()) + { + this->ui->artWorkLabel->setPixmap(pixmap.scaled(this->ui->artWorkLabel->size())); + } +} + +void PlayerMainWindow::playOnlineMedia(int index) +{ + this->mediaPlayer->playlist()->setCurrentIndex(index); + this->mediaPlayer->play(); + qDebug()<mediaPlayer->errorString(); +} + +void PlayerMainWindow::addCurrentSongToFavorites() +{ + if(this->onlineMode) + { + int index=this->mediaPlayer->playlist()->currentIndex(); + if(index<0||index>=this->onlineMediaList->count()) + { + return; + } + this->db.addFavoriteSong(this->onlineMediaList->at(index)); + } +} + +void PlayerMainWindow::playSongInFavorites() +{ + QList * mediaInfoList = this->db.getFavoriteSong(); + if(mediaInfoList && mediaInfoList->count()>0) + { + this->onlineMediaPlayList->clear(); + this->onlineMediaList->clear(); + this->mediaPlayer->setPlaylist(this->onlineMediaPlayList); + this->onlineMode = true; + } + for(int i = 0; mediaInfoList&&icount();i++) + { + KMediaInfo mediaInfo = mediaInfoList->at(i); + QUrl url = QUrl(mediaInfo.mp3Url); + QMediaContent content(url); + this->onlineMediaPlayList->addMedia(content); + this->onlineMediaList->append(mediaInfo); + if(this->onlineMediaPlayList->mediaCount() == 1) + { + this->playOnlineMedia(0); + } + } +} + +void PlayerMainWindow::showAbout() +{ + QMessageBox::about(this, tr("关于 ") + qApp->applicationName(), + tr("

UbuntuKylin简易网络播放器


" + " KylinPlayer 是优麒麟为" + "湖南科技职业学院
2014年国培班学员学习Qt5开发的简易音乐播放器.
" + "支持: Ubuntu Kylin/Mac OS X/Windows.

" + "作者: \t大茶园丁(戴维营教育)
" + "邮箱: \t147957232@qq.com.
" + "网站: \thttp://www.ubuntukylin.com.
" + "反馈: \t http://www.ubuntukylin.com/ukylin/

" + "")); +} + +void PlayerMainWindow::channelsDownloaded(QList *channelList) +{ + if (channelList->count() <= 0) + { + return ; + } + this->ui->channelComboBox->clear(); + this->ui->channelComboBox->addItems(QStringList()<<"本地歌曲"<<"网络歌曲"); + for(int i = 0; i < channelList->count(); i++) + { + QString id = channelList->value(i).id; + QString title = channelList->value(i).title; + this->ui->channelComboBox->addItem(title, QVariant(id)); + } + +} + +void PlayerMainWindow::mediaInfoListDownloaded(QList *mediaInfoList) +{ + if(mediaInfoList->count() <= 0) + { + return; + } + int count = mediaInfoList->count(); + this->onlineMediaList->clear(); + this->onlineMediaList->reserve(count); + for(int i = 0; i < mediaInfoList->count(); i++) + { + KMediaInfo mediaInfo = mediaInfoList->at(i); + this->network->fetchSongInfo(kMusicURL+ QString("%1").arg(mediaInfo.id)); + } + qDebug() << mediaInfoList; +} + +void PlayerMainWindow::mediaInfoDownloaded(KMediaInfo mediaInfo) +{ + QUrl url = QUrl(mediaInfo.mp3Url); + QMediaContent content(url); + this->onlineMediaPlayList->addMedia(content); + this->onlineMediaList->append(mediaInfo); + if(this->onlineMediaPlayList->mediaCount() == 1) + { + this->playOnlineMedia(0); + } + + return; +} + +void PlayerMainWindow::AlbumImageDownloaded(QByteArray *imageData) +{ + QImage img; + QPixmap pixmap; + if(imageData->isEmpty()) + { + pixmap = QPixmap(":/images/Qt.png"); + }else + { + img.loadFromData(*imageData); + pixmap.convertFromImage(img); + } + this->ui->artWorkLabel->setPixmap(pixmap.scaled(this->ui->artWorkLabel->size())); +} diff --git a/playermainwindow.h b/playermainwindow.h new file mode 100644 index 0000000..a70c5ac --- /dev/null +++ b/playermainwindow.h @@ -0,0 +1,71 @@ +#ifndef PLAYERMAINWINDOW_H +#define PLAYERMAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "database.h" +#include "osdlyricswidget.h" + +namespace Ui { +class PlayerMainWindow; +} +class Network; +class PlayerMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit PlayerMainWindow(QWidget *parent = 0); + ~PlayerMainWindow(); + void setupConnections(); + void closeEvent(QCloseEvent *event); +public slots: + void openLocalMedia(); + void openInternetURL(); + void playButtonClicked(); + void prevButtonClicked(); + void nextButtonClicked(); + void playSliderValueChanged(int value); + void volumeDialValueChanged(int value); + void channelIndexChanged(int index); + + void playerStateChanged(QMediaPlayer::State state); + void mediaStatusChanged(QMediaPlayer::MediaStatus status); + + void playProgressUpdate(); + void metaDataUpdate(); + + + void playOnlineMedia(int index); + void addCurrentSongToFavorites(); + void playSongInFavorites(); + void showAbout(); + + //networks + void channelsDownloaded(QList *channelList); + void mediaInfoListDownloaded(QList *mediaInfoList); + void mediaInfoDownloaded(KMediaInfo mediaInfo); + void AlbumImageDownloaded(QByteArray *imageData); +private: + Ui::PlayerMainWindow *ui; + QMediaPlayer *mediaPlayer; + QMediaPlaylist *localMediaPlayList, *onlineMediaPlayList; + QList *onlineMediaList; + QTimer *progressTimer; + Network *network; + bool onlineMode; + Database db; + bool dbOK; + + OSDLyricsWidget *osdLyricsWidget; +}; + +#endif // PLAYERMAINWINDOW_H diff --git a/playermainwindow.ui b/playermainwindow.ui new file mode 100644 index 0000000..a6b2043 --- /dev/null +++ b/playermainwindow.ui @@ -0,0 +1,340 @@ + + + PlayerMainWindow + + + + 0 + 0 + 320 + 480 + + + + + 320 + 480 + + + + + 320 + 480 + + + + KylinPlayer + + + + + + 20 + 320 + 211 + 21 + + + + 歌手: + + + + + + 20 + 290 + 211 + 21 + + + + 专辑: + + + + + + 20 + 260 + 211 + 21 + + + + 歌名: + + + + + + 200 + 314 + 101 + 27 + + + + + 本地歌曲 + + + + + 网络歌曲 + + + + + + + 20 + 360 + 280 + 20 + + + + Qt::NoFocus + + + 0 + + + 0 + + + true + + + Qt::Horizontal + + + false + + + + + + 20 + 390 + 64 + 64 + + + + background-color: rgba(255, 255, 255, 0); +selection-background-color: rgba(255, 255, 255, 0); + + + + + + + :/images/prev.png:/images/prev.png + + + + 48 + 48 + + + + true + + + + + + 130 + 390 + 64 + 64 + + + + Qt::LeftToRight + + + false + + + background-color: rgba(255, 255, 255, 0); +selection-background-color: rgba(255, 255, 255, 0); + + + + + + + :/images/play.png:/images/play.png + + + + 64 + 64 + + + + false + + + true + + + + + + 230 + 390 + 64 + 64 + + + + background-color: rgba(255, 255, 255, 0); +selection-background-color: rgba(255, 255, 255, 0); + + + + + + + + :/images/next.png:/images/next.png + + + + 48 + 48 + + + + true + + + + + + 230 + 250 + 71 + 61 + + + + Qt::WheelFocus + + + Qt::LeftToRight + + + false + + + 40 + + + Qt::Horizontal + + + false + + + false + + + true + + + 3.700000000000000 + + + true + + + + + + 40 + 10 + 240 + 240 + + + + 封面图 + + + Qt::AlignCenter + + + + + + + 0 + 0 + 320 + 17 + + + + + 菜单 + + + + + + + false + + + 关于 + + + + + + 收藏 + + + + + + + + + + + 本地歌曲 + + + + + 网络歌曲 + + + + + 加入收藏 + + + + + 播放收藏 + + + + + 关于KylinPlayer + + + + + + + + + diff --git a/prev.png b/prev.png new file mode 100644 index 0000000000000000000000000000000000000000..2d8f04755b1ab2ad32d6846b0342b76a58b20543 GIT binary patch literal 6975 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 + + Qt.png + play.png + pause.png + next.png + prev.png + ubuntukylin.png + + diff --git a/ubuntukylin.png b/ubuntukylin.png new file mode 100644 index 0000000000000000000000000000000000000000..57190e75b6f5515c7843ba5d54c371188bac5e47 GIT binary patch literal 10872 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 azsZfz@*dMj?Kb{t=gUbcNmh%S1phD7+Ji#? literal 0 HcmV?d00001