请看如下代码:使用队列将选中加载元数据并显示出来
void LocalDownload::loadNextSong() {
if (!m_songQueue.isEmpty()) {
this->m_mediaPath = m_songQueue.dequeue(); // 取出队列中的下一首歌路径
qDebug()<<"取出歌曲 : "<<this->m_mediaPath<<"=================";
// 在加载新媒体前,重置媒体状态
this->m_player->stop();
this->m_player->setSource(QUrl()); // 清空当前媒体源
this->m_player->play();
this->m_player->setSource(QUrl::fromLocalFile(this->m_mediaPath));
this->m_player->play(); // 触发状态改变信号,获取元数据信息
}
}
void LocalDownload::on_local_add_toolButton_clicked() {
QString musicPath = QStandardPaths::standardLocations(QStandardPaths::MusicLocation).first();
QStringList paths = QFileDialog::getOpenFileNames(this, QStringLiteral("添加音乐"), musicPath, "Music (*.mp3 *.aac *.wav)");
if (paths.isEmpty())return;
//QString fileName = QUrl::fromLocalFile(path).fileName();
//qDebug() << "插入:"<<paths.size()<<"条数据";
for(auto& path : paths) {
//qDebug()<<"添加歌曲 :"<<path;
this->m_songQueue.enqueue(path);
}
this->loadNextSong();
}
connect(m_player.get(), &QMediaPlayer::mediaStatusChanged, [=](const QMediaPlayer::MediaStatus& status) {
if (status == QMediaPlayer::LoadedMedia) {
//qDebug()<<"媒体状态改变,加载完成";
//qDebug()<<"元数据加载完成";
const QMediaMetaData data = this->m_player->metaData();
for(auto val : data.keys()) {
qDebug()<<val<<": "<<data.value(val).toString();
}
// 停止播放
this->m_player->stop();
//获取标题
auto title = data.value(QMediaMetaData::Title).toString();
if(!re.match(title).hasMatch()) {
title = QUrl::fromLocalFile(this->m_mediaPath).fileName();
title = title.first(title.lastIndexOf('.'));
}
//获取歌手
auto singer = data.value(QMediaMetaData::ContributingArtist).toString();
if(!re.match(singer).hasMatch())singer = QStringLiteral("网络歌手");
//获取封面
auto cover = data.value(QMediaMetaData::ThumbnailImage).value<QPixmap>();
if(cover.isNull()) {
//qDebug()<<"封面为空";
cover = QPixmap(QString("://Res/tablisticon/pix%1.png").arg(QRandomGenerator::global()->bounded(1,11)));
}
//获取时长
const auto duration = data.value(QMediaMetaData::Duration).value<qint64>();
//信息赋值
SongInfor tempInformation;
tempInformation.index = this->m_locationMusicVector.size()+1;//让他先加1
tempInformation.cover = cover;
tempInformation.songName = title;
tempInformation.signer = singer;
tempInformation.duration = QTime::fromMSecsSinceStartOfDay(duration).toString("mm:ss");
tempInformation.mediaPath = this->m_mediaPath;
tempInformation.addTime = QDateTime::currentDateTime();
//判重(通过元数据信息)
auto it = std::find(this->m_locationMusicVector.begin(),
this->m_locationMusicVector.end(),tempInformation);
if(it == this->m_locationMusicVector.end())this->m_locationMusicVector.emplace_back(tempInformation);
else {
//qDebug()<<title<<"已存在,请勿重复插入";
//加载下一首歌
loadNextSong();
return;
}
//向parent发送添加MediaPath的信号
emit addSongInfo(tempInformation);
//加载相关信息
auto item = new MusicItemWidget(tempInformation, this);
item->setFillColor(QColor(QStringLiteral("#B0EDF6")));
item->setRadius(12);
item->setInterval(1);
auto index = tempInformation.index;// 捕获当前的 index
connect(item, &MusicItemWidget::playRequest, this, [index, this] {
emit playMusic(index);
});
dynamic_cast<QVBoxLayout*>(ui->local_song_list_widget->layout())->insertWidget(ui->local_song_list_widget->layout()->count() - 1, item);
ui->local_music_number_label->setText(QString::number(this->m_locationMusicVector.size()));
//加载下一首歌
loadNextSong();
}
});
再重复选中相同的歌曲后,会出现如下情况:
实际元数据集信息与歌曲不符,有明显的滞后嫌疑,但是我已经尽量做到在加载新媒体前,重置媒体状态,还是没用。不得已出此下策:每次加载元数据前重置player。这是迫不得已的做法,非常无奈。如下:
void LocalDownload::getMetaData() {
//经过一段时间的搜索得到的结论,如果想不调用play()就获得元数据信息是不现实的,能做到的也就只有加载完成之后立马停止
connect(m_player.get(), &QMediaPlayer::mediaStatusChanged, [=](const QMediaPlayer::MediaStatus& status) {
if (status == QMediaPlayer::LoadedMedia) {
//qDebug()<<"媒体状态改变,加载完成";
//qDebug()<<"元数据加载完成";
const QMediaMetaData data = this->m_player->metaData();
for(auto val : data.keys()) {
qDebug()<<val<<": "<<data.value(val).toString();
}
// 停止播放
this->m_player->stop();
//获取标题
auto title = data.value(QMediaMetaData::Title).toString();
if(!re.match(title).hasMatch()) {
title = QUrl::fromLocalFile(this->m_mediaPath).fileName();
title = title.first(title.lastIndexOf('.'));
}
//获取歌手
auto singer = data.value(QMediaMetaData::ContributingArtist).toString();
if(!re.match(singer).hasMatch())singer = QStringLiteral("网络歌手");
//获取封面
auto cover = data.value(QMediaMetaData::ThumbnailImage).value<QPixmap>();
if(cover.isNull()) {
//qDebug()<<"封面为空";
cover = QPixmap(QString("://Res/tablisticon/pix%1.png").arg(QRandomGenerator::global()->bounded(1,11)));
}
//获取时长
const auto duration = data.value(QMediaMetaData::Duration).value<qint64>();
//信息赋值
SongInfor tempInformation;
tempInformation.index = this->m_locationMusicVector.size()+1;//让他先加1
tempInformation.cover = cover;
tempInformation.songName = title;
tempInformation.signer = singer;
tempInformation.duration = QTime::fromMSecsSinceStartOfDay(duration).toString("mm:ss");
tempInformation.mediaPath = this->m_mediaPath;
tempInformation.addTime = QDateTime::currentDateTime();
//判重(通过元数据信息)
auto it = std::find(this->m_locationMusicVector.begin(),
this->m_locationMusicVector.end(),tempInformation);
if(it == this->m_locationMusicVector.end())this->m_locationMusicVector.emplace_back(tempInformation);
else {
//qDebug()<<title<<"已存在,请勿重复插入";
//加载下一首歌
loadNextSong();
return;
}
//向parent发送添加MediaPath的信号
emit addSongInfo(tempInformation);
//加载相关信息
auto item = new MusicItemWidget(tempInformation, this);
item->setFillColor(QColor(QStringLiteral("#B0EDF6")));
item->setRadius(12);
item->setInterval(1);
auto index = tempInformation.index;// 捕获当前的 index
connect(item, &MusicItemWidget::playRequest, this, [index, this] {
emit playMusic(index);
});
dynamic_cast<QVBoxLayout*>(ui->local_song_list_widget->layout())->insertWidget(ui->local_song_list_widget->layout()->count() - 1, item);
ui->local_music_number_label->setText(QString::number(this->m_locationMusicVector.size()));
//加载下一首歌
loadNextSong();
}
});
}
void LocalDownload::loadNextSong() {
if (!m_songQueue.isEmpty()) {
this->m_mediaPath = m_songQueue.dequeue(); // 取出队列中的下一首歌路径
//qDebug()<<"取出歌曲 : "<<this->m_mediaPath<<"=================";
/*// 在加载新媒体前,重置媒体状态
this->m_player->stop();
this->m_player->setSource(QUrl()); // 清空当前媒体源
this->m_player->play();*/ //不起效果
// 释放并重建 QMediaPlayer 对象
this->m_player = std::make_unique<QMediaPlayer>(this);//它会自动释放之前的对象
getMetaData();
this->m_player->setSource(QUrl::fromLocalFile(this->m_mediaPath));
this->m_player->play(); // 触发状态改变信号,获取元数据信息
}
}