Qt之音乐播放器一

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
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值