1、实现播放歌曲
void Widget::on_playMusicButton_clicked()//点击播放歌曲按钮
{
if(currentSongIndex > songIdList.size())
return;
currentSongInfo = this->getSongRealLinkById(songIdList.at(currentSongIndex));
mediaPlayer->setMedia(QUrl(currentSongInfo.songRealLink));
mediaPlayer->play();
QString lyric = this->getLyric(currentSongInfo.lyricLink);//从网上获取歌词
lyricList = this->parse(lyric);//将lyric一行行地解析到lyricList
}
//1、获取频道列表
QList<CHANNEL_INFO> Widget::getChannelList()
{
const QString channelUrl = "http://fm.baidu.com/dev/api/?tn=channellist";
QList<CHANNEL_INFO> channelInfoList;
QNetworkRequest networkRequest;
QNetworkAccessManager *networkManager = new QNetworkAccessManager;
networkRequest.setUrl(QUrl(channelUrl));
networkManager->setCookieJar(0);
QNetworkReply *reply = networkManager->get(networkRequest);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
reply->deleteLater();
QByteArray buf = reply->readAll();
QJsonParseError jsonError;
QJsonDocument jsonRes = QJsonDocument::fromJson(buf, &jsonError);;
if(jsonError.error == QJsonParseError::NoError)
{
if(jsonRes.isObject())
{
QVariantMap result = jsonRes.toVariant().toMap();//提取花括号里的键值对
foreach(QVariant channel, result["channel_list"].toList())//提取[]里的频道
{ //由于每个频道也是一个{}
QVariantMap channelMap = channel.toMap();//提取花括号的键值对
CHANNEL_INFO channelInfo;
channelInfo.channelId = channelMap["channel_id"].toString();
channelInfo.channelName = channelMap["channel_name"].toString();
channelInfoList.append(channelInfo);
}
}
}
return channelInfoList;
}
//2、根据频道id,获取某个频道下的歌曲列表(比如推荐频道public_tuijian_spring)
QList<QString> Widget::getSongIdList(QString channelId)
{
const QString playListUrl = "http://fm.baidu.com/dev/api/?tn=playlist&format=json&id=";
QNetworkRequest networkRequest;
QNetworkAccessManager *networkManager = new QNetworkAccessManager;
networkRequest.setUrl(QUrl(playListUrl + channelId));
networkManager->setCookieJar(0);
QNetworkReply *reply = networkManager->get(networkRequest);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
reply->deleteLater();
QList<QString> songId;
QByteArray buf = reply->readAll();
QJsonParseError jsonError;
QJsonDocument jsonRes = QJsonDocument::fromJson(buf, &jsonError);;
if(jsonError.error == QJsonParseError::NoError)
{
if(jsonRes.isObject())
{
QVariantMap result = jsonRes.toVariant().toMap();
foreach(QVariant song, result["list"].toList())
{
QVariantMap songMap = song.toMap();
QString id = songMap["id"].toString();//获取歌曲id
//如果歌曲ID有效
if(!id.isEmpty())
{
songId.append(id);
}
}
}
}
return songId;
}
//3、根据songID(比如1615837),获取一首歌的歌曲名称和下载链接
SONG_INFO Widget::getSongRealLinkById(QString songId)
{
const QString downLoadLinkUrl = "http://music.baidu.com/data/music/fmlink?type=mp3&rate=320&songIds=";
QNetworkRequest networkRequest;
QNetworkAccessManager networkManager;
networkRequest.setUrl(QUrl(downLoadLinkUrl + songId));
networkManager.setCookieJar(0);
QNetworkReply *reply = networkManager.get(networkRequest);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
reply->deleteLater();
//歌曲信息
SONG_INFO songInfo;
QByteArray buf = reply->readAll();
QJsonParseError jsonError;
QJsonDocument jsonRes = QJsonDocument::fromJson(buf, &jsonError);;
if(jsonError.error == QJsonParseError::NoError)
{
if(jsonRes.isObject())
{
QVariantMap result = jsonRes.toVariant().toMap();
QVariantMap dataList = result["data"].toMap();
foreach(QVariant data, dataList["songList"].toList())
{
QVariantMap linkMap = data.toMap();
songInfo.songRealLink = linkMap["songLink"].toString();
songInfo.songName = linkMap["songName"].toString();
songInfo.artistName = linkMap["artistName"].toString();
songInfo.songPicSmall = linkMap["songPicSmall"].toString();
songInfo.songPicRadio = linkMap["songPicRadio"].toString();
songInfo.albumName = linkMap["albumName"].toString();
songInfo.lyricLink = linkMap["lrcLink"].toString();
}
}
}
return songInfo;
}
2、实现歌词显示
//根据lrcLink获取歌词
QString Widget::getLyric(QString lyricLink)//lyricLink是歌词下载地址
{
QNetworkRequest networkRequest;
QNetworkAccessManager networkManager;
networkRequest.setUrl(QUrl(lyricLink));
QNetworkReply *reply = networkManager.get(networkRequest);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
reply->deleteLater();
QString lyrc;
lyrc = reply->readAll();
return lyrc;
}
//解析从网上获取的歌词
QList<QLyric> Widget::parse(QString lyric)
{
QTextStream stream(&lyric);
QTextCodec *codec = QTextCodec::codecForName("utf-8");
stream.setCodec(codec);
currentLyricIndex = 0;
lyricList.clear();
//QRegExp解析歌词
QRegExp timeExp;
timeExp.setPatternSyntax(QRegExp::RegExp);
timeExp.setCaseSensitivity(Qt::CaseSensitive);
timeExp.setPattern("\\[([0-9]{2}):([0-9]{2})\\.([0-9]{2})\\]");
//匹配[00:02.42]
QList<QLyric> result;
while (!stream.atEnd())
{
QString line = stream.readLine();
int ret = timeExp.indexIn(line);
QList<QTime> ticks;
int lastindex = 0;
while (ret >= 0)
{
QStringList tstr = timeExp.capturedTexts();
QTime time(0, tstr[1].toInt(), tstr[2].toInt(), tstr[3].toInt());
ticks.append(time);
lastindex = ret + timeExp.matchedLength();
ret = timeExp.indexIn(line, lastindex);
}//经过测试,ticks只会含有一个项
QString lyricstr = line.right(line.size() - lastindex);//提取歌词
for (const QTime& t : ticks)//c++11
{
QLyric lyric;
lyric.time = t.minute() * 60 * 1000 + t.second() * 1000 + t.msec();//单位ms
lyric.lyric = lyricstr;
result.append(lyric);
}
}
std::sort(result.begin(), result.end(), [] (const QLyric& a, const QLyric& b) -> bool {
return a.time < b.time;
});
return result;//保存了一行行的歌词
}
//显示歌词的槽函数
void Widget::slotShowLyric(qint64 position)
{
if(lyricList.size() <= 0 || currentLyricIndex >= lyricList.size())
return;
for(int i = 0; i < lyricList.size(); i++)
{
if(position > lyricList.at(i).time)
{
currentLyricIndex = i;
}
}
//显示position之后的歌词,position之前的已经播放过了
if(position > lyricList.at(currentLyricIndex).time)
{
//始终显示作者名和歌曲名
QString lrc;
lrc.clear();
lrc += QString("<p align='center'><span style=' font-style:italic;'>");
lrc += currentSongInfo.artistName + " - " + currentSongInfo.songName;
lrc += QString("</span></p>");
//j从m_iCurrentIndex - 1开始,是为了显示出正在唱的前一句
for(int j = currentLyricIndex - 1; j < lyricList.size(); j++)
{
if(j < 0)
continue;
if(currentLyricIndex == j)//正在唱的歌词,颜色加粗
{
lrc += QString("<p align='center'><span style=' font-weight:600;'>");
lrc += lyricList.at(currentLyricIndex).lyric;
lrc += QString("</span></p>");
}
else
{
lrc += "<p align='center'>";
lrc += lyricList.at(j).lyric;
lrc += "</p>";
}
}
ui->lyricLabel->setText(lrc);
currentLyricIndex++;
}
}
3、实现歌曲下载
void Widget::on_downLoadButton_clicked()//点击下载歌曲按钮
{
QString fileName;
QDir dir;
if(!dir.exists("./download"))
{
dir.mkdir("./download");
}
fileName = "./download/" + currentSongInfo.songName + ".mp3";
this->downLoadMusic(fileName, currentSongInfo.songRealLink);
}
//从网上下载歌曲,fileName是下载之后文件名(含路径),url是歌曲下载链接
void Widget::downLoadMusic(QString fileName, QString songLink)
{
QNetworkRequest networkRequest;
QNetworkAccessManager networkManager;
networkRequest.setUrl(QUrl(songLink));
QNetworkReply *reply = networkManager.get(networkRequest);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
reply->deleteLater();
QFile file;
file.setFileName(fileName);
bool ok = file.open(QIODevice::WriteOnly);
if(ok)
{
file.write(reply->readAll());
}
}
完整代码下载: http://download.csdn.net/detail/bladeandmaster88/9750335