2 Star 1 Fork 0

朱洪君/QT-MediaPlayer

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
mediawidget.cpp 13.40 KB
一键复制 编辑 原始数据 按行查看 历史
朱洪君 提交于 2023-12-29 10:57 . base func and test
#include "mediawidget.h"
#include "ui_mediawidget.h"
#include <QDir>
#include <QFileDialog>
#include <QDebug>
#include <QRegularExpression>
#include <QTextCodec>
#include <QMediaMetaData>
#include <QEvent>
#include <QCloseEvent>
#include <QMessageBox>
#include <QMenu>
#include <QSettings>
MediaWidget::MediaWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MediaWidget)
{
ui->setupUi(this);
musicMsgMap = new QMap<QString, QMap<QString, QString> *>();
tableModel = new TableModel();
lyricLabel = new LyricLabel(this);
tableWidget = new MusicTableView(this);
tableWidget->installEventFilter(this);
tableWidget->setModel(tableModel);
connect(tableWidget, &MusicTableView::doubleClicked, this, &MediaWidget::playClickedMedia);
initMediaPlayer();
}
MediaWidget::~MediaWidget()
{
delete ui;
}
void MediaWidget::initMediaPlayer()
{
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
setWindowTitle(tr("音乐播放控制器"));
setWindowIcon(QIcon(":/images/icon.png"));
setMinimumSize(410, 210);
setMaximumSize(1920, 1080);
QSettings settings;
settings.value("mediaWidget/rect").isNull() ? setGeometry(QRect(400,200,410,210)) : setGeometry(settings.value("mediaWidget/rect").toRect());
settings.value("mediaWidget/playState").isNull() ? wasPlaying = false : wasPlaying = settings.value("mediaWidget/playState").toBool();
//设置音乐播放对象
player = new QMediaPlayer();
output = new QAudioOutput();
player->setAudioOutput(output);
// player->setSource(QUrl::fromLocalFile("C:/Users/Administrator/Documents/QT Code/Qt Improve/build-MyMediaPlayer-Desktop_Qt_6_6_0_MinGW_64_bit-Debug/music/我是明星.mp3"));
isReady = false;
//设置桌面轮盘
trayIcon = new QSystemTrayIcon(this);
trayIcon->setIcon(QIcon(":/images/icon.png"));
trayIcon->setToolTip("PitchMusic播放器");
QMenu *trayMenu = new QMenu;
trayMenu->addAction("播放", player, &QMediaPlayer::play);
trayMenu->addAction("暂停", player, &QMediaPlayer::pause);
trayMenu->addAction("上一首", this, &MediaWidget::fastBackward);
trayMenu->addAction("下一首", this, &MediaWidget::fastForward);
trayMenu->addSeparator();
trayMenu->addAction("桌面歌词", lyricLabel, &QLabel::show);
trayMenu->addAction("播放列表", this, &MediaWidget::showMusicListWidget);
trayMenu->addAction("退出", this, &MediaWidget::quit);
trayIcon->setContextMenu(trayMenu);
connect(trayIcon, &QSystemTrayIcon::activated, this, &MediaWidget::activateTrayIcon);
connect(trayIcon, &QSystemTrayIcon::messageClicked, this, &MediaWidget::show);
trayIcon->show();
connect(ui->resourceBtn, &QPushButton::clicked, this, &MediaWidget::openMedia);
connect(ui->controlBtn, &QPushButton::toggled, this, &MediaWidget::controlMedia);
connect(ui->resetBtn, &QPushButton::clicked, this, &MediaWidget::resetMedia);
connect(ui->fastBackBtn, &QPushButton::clicked, this, &MediaWidget::fastBackward);
connect(ui->fastForwBtn, &QPushButton::clicked, this, &MediaWidget::fastForward);
connect(ui->silentBtn, &QPushButton::clicked, this, &MediaWidget::silent);
connect(ui->processSlider, &QSlider::sliderMoved, this, &MediaWidget::mapSliderToPosition);
connect(ui->volumnSlider, &QSlider::sliderMoved, this, &MediaWidget::changeVolumn);
connect(player, &QMediaPlayer::positionChanged, this, &MediaWidget::processChanged);
connect(player, &QMediaPlayer::mediaStatusChanged, this, &MediaWidget::setReady);
connect(player, &QMediaPlayer::playbackStateChanged, this, &MediaWidget::updateWidget);
connect(ui->PlBtn, &QPushButton::clicked, this, &MediaWidget::showMusicListWidget);
connect(ui->LrcBtn, &QPushButton::clicked, lyricLabel, &LyricLabel::show);
output->setVolume(0.5);
ui->volumnSlider->setValue(50);
if(!settings.value("mediaWidget/curMusicPath").isNull()){
QString fileName = settings.value("mediaWidget/curMusicPath").toUrl().toLocalFile();
curIndex = tableModel->getIndexByFileName(fileName);
openMediaByName(fileName);
}
if(!settings.value("tableWidget/isVisible").isNull()){
if(settings.value("tableWidget/isVisible").toBool()) showMusicListWidget();
}
if(!settings.value("lyricLabel/isVisible").isNull()){
if(settings.value("lyricLabel/isVisible").toBool()) lyricLabel->show();
}
}
void MediaWidget::playClickedMedia(const QModelIndex &index)
{
qDebug() << index;
if(index.row() == curIndex.row()){
resetMedia();
wasPlaying = true;
ui->controlBtn->setChecked(true);
player->play();
return;
}
wasPlaying = true;
QString fileName = tableModel->getFileNameByIndex(index);
openMediaByName(fileName);
}
void MediaWidget::openMedia()
{
isReady = false;
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Media File"),
QDir::currentPath(),
tr("Media (*.mp3)"));
openMediaByName(fileName);
}
void MediaWidget::openMediaByName(QString fileName)
{
if(fileName.isEmpty()) return;
qDebug() << fileName;
player->setSource(QUrl::fromLocalFile(fileName));
QMediaMetaData metaData = player->metaData();
musicMsg = new QMap<QString, QString>();
if(!metaData.value(QMediaMetaData::Title).toString().isEmpty())
musicMsg->insert("ti", metaData.value(QMediaMetaData::Title).toString());
else{
QList<QString> splitList = fileName.split("/");
musicMsg->insert("ti", splitList.at(splitList.size() - 1).left(splitList.at(splitList.size() - 1).size() - 4));
}
musicMsg->insert("al", metaData.value(QMediaMetaData::ContributingArtist).toString());
int msec = metaData.value(QMediaMetaData::Duration).toInt();
QTime time(0, 0);
time = time.addMSecs(msec);
musicMsg->insert("len", time.toString("mm:ss"));
QModelIndex index = tableModel->getIndexByFileName(fileName);
if(index.row() == -1){ //只在新增时插入
musicMsgMap->insert(fileName, musicMsg);
curIndex = tableModel->setMusicMsg(fileName, musicMsg);
}else{
curIndex = index;
}
QString lyricName = fileName.left(fileName.length() - 4) + ".lrc";
loadLyric(lyricName);
}
void MediaWidget::loadLyric(QString fileName)
{
qDebug() << fileName;
lyric.clear();
QFile file(fileName);
if(!file.open(QFile::ReadOnly)){
lyricLabel->stopTimer();
lyricLabel->setText("欢迎使用PitchMusic桌面歌词");
return;
}
QTextStream in(&file);
in.setEncoding(QStringConverter::Utf8); //必须设置,否则中文读取乱码
while (!in.atEnd()) {
QString line = in.readLine();
process_line(line);
}
}
void MediaWidget::process_line(QString line)
{
// qDebug() << "line: "<< line;
QString pattern1 = "\\[(?<key>[a-z]+):(?<value>.*)\\]"; //匹配msg行,如[ti:我是明星]
QString pattern2 = "\\[(?<min>\\d+):(?<sec>\\d+).(?<tenMsec>\\d+)\\]"; //匹配lyric行,如[01:10.79][00:14.65]
QRegularExpression re;
re.setPattern(pattern1);
QRegularExpressionMatch match = re.match(line);
if(match.hasMatch()){/*
qDebug() << "caputured key: "<< match.captured("key") << "caputured value: "<< match.captured("value");*/
musicMsg->insert(match.captured("key"), match.captured("value"));
}else{
re.setPattern(pattern2);
QRegularExpressionMatchIterator it = re.globalMatch(line);
int len = 0;
QList<int> *keyList = new QList<int>();
while(it.hasNext()){
QRegularExpressionMatch match = it.next();
len += match.capturedLength();
int min = match.captured("min").toInt();
int sec = match.captured("sec").toInt();
int tenMsec = match.captured("tenMsec").toInt();
keyList->append(tenMsec * 10 + sec * 1000 + min * 60 * 1000);
}
QString value = line.right(line.length() - len);
foreach (int key, *keyList) {
// qDebug() << "caputured key: "<< key << "caputured value: "<< value;
lyric.insert(key, value);
}
}
}
void MediaWidget::fastForward()
{
playClickedMedia(tableModel->getNextData(curIndex));
}
void MediaWidget::fastBackward()
{
playClickedMedia(tableModel->getBackData(curIndex));
}
void MediaWidget::controlMedia(bool isPlay)
{
if(!isReady) {
ui->controlBtn->setCheckable(false);
return;
}
if(isPlay){
qDebug() << "播放音乐";
if(isReady) player->play();
}else{
qDebug() << "音乐暂停";
if(isReady) player->pause();
}
}
void MediaWidget::resetMedia()
{
changeProcess(0);
}
void MediaWidget::silent()
{
ui->volumnSlider->setSliderDown(true);
ui->volumnSlider->setValue(0);
}
void MediaWidget::changeVolumn(int vol)
{
output->setVolume(static_cast<float>(vol) / 100.0);
}
void MediaWidget::mapSliderToPosition(float val)
{
if(isReady){
changeProcess((val / 100) * player->duration());
}
}
void MediaWidget::changeProcess(int val)
{
if(isReady){
if(val < 0) val = 0;
if(val > player->duration()) val = player->duration();
player->setPosition(val);
}
}
void MediaWidget::processChanged(int val)
{
//更新三个内容,一个是slider条,一个是processText文本,一个是lyric文本
if(!ui->processSlider->isSliderDown()){ //当检测到slider正在拖动,此时不应在此处更改slider的位置
ui->processSlider->setSliderDown(false);
ui->processSlider->setValue(val * 100 / player->duration());
}
updateLyric(val);
updateProcessText(val);
}
void MediaWidget::updateLyric(int curMsec)
{
if(!lyric.isEmpty()){
QMap<int, QString>::iterator it = lyric.upperBound(curMsec); //此时获取的是第一个大于的it(如果不存在,会返回指向end()的指针,end()-1即末尾元素)
if(lyric.begin() == it){
ui->lyricText->setText("");
return;
}
int total;
if(lyric.end() == it){
total = player->duration() - (it - 1).key();
}else{
total = it.key() - (it - 1).key();
}
it--; //向前移动1,找到最后一个不大于的it
if(it.key() == curLyricStartTime) return;
curLyricStartTime = it.key();
ui->lyricText->setText(it.value());
lyricLabel->setText(it.value());
lyricLabel->setAddWidthByTotal(total);
}
}
void MediaWidget::updateProcessText(int val)
{
QTime cur(0, 0);
cur = cur.addMSecs(val);
QTime dur(0, 0);
dur = dur.addMSecs(player->duration());
ui->processText->setText(tr("%1/%2").arg(cur.toString("mm:ss")).arg(dur.toString("mm:ss")));
}
void MediaWidget::setReady(QMediaPlayer::MediaStatus status)
{
if(player->mediaStatus() >= QMediaPlayer::LoadedMedia and player->mediaStatus() <= QMediaPlayer::BufferedMedia){
qDebug() << "音乐资源加载完成"<<"加载状态"<<status << "上次播放状态" << wasPlaying;
isReady = true;
ui->controlBtn->setCheckable(true);
if(wasPlaying)
ui->controlBtn->setChecked(true);
}else if(player->mediaStatus() == QMediaPlayer::EndOfMedia){
qDebug() << "音乐资源播放结束" << "加载状态"<<status;
playClickedMedia(tableModel->getNextData(curIndex, curType));
}
else {
qDebug() << "音乐资源加载失败" << "加载状态"<<status;
isReady = false;
ui->controlBtn->setCheckable(false);
}
}
void MediaWidget::updateWidget(QMediaPlayer::PlaybackState state)
{
qDebug() << "当前播放状态 state: "<<state;
if(state == QMediaPlayer::PlayingState){
setWindowTitle("正在播放: " + musicMsg->value("ti"));
wasPlaying = true;
}else{
if(state == QMediaPlayer::PausedState) {
wasPlaying = false;
}
setWindowTitle("音乐播放控制器");
}
}
void MediaWidget::showMusicListWidget()
{
tableWidget->show();
}
void MediaWidget::quit()
{
//保存播放记录
tableModel->saveData();
writeSettings();
//关闭其他窗口
tableWidget->close();
qApp->quit();
}
bool MediaWidget::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::Close){
if(obj->metaObject()->className() == QTableView::staticMetaObject.className()){
// 关闭窗口时执行的清理内容
tableWidget->hide();
event->ignore();
}
}
return QWidget::eventFilter(obj, event);
}
void MediaWidget::closeEvent(QCloseEvent *event)
{
if(isVisible()){
hide();
tableWidget->hide();
// trayIcon->showMessage("PitchMusic播放器", "点我重新进入主界面");
event->ignore();
}
}
void MediaWidget::writeSettings()
{
QSettings settings;
settings.setValue("mediaWidget/rect", geometry());
settings.setValue("mediaWidget/playState", player->playbackState() == QMediaPlayer::PlayingState);
settings.setValue("mediaWidget/curMusicPath", player->source());
settings.setValue("tableWidget/rect", tableWidget->geometry());
settings.setValue("tableWidget/isVisible", tableWidget->isVisible());
settings.setValue("lyricLabel/rect", lyricLabel->geometry());
settings.setValue("lyricLabel/isVisible", lyricLabel->isVisible());
}
void MediaWidget::activateTrayIcon(QSystemTrayIcon::ActivationReason reason)
{
if(reason == QSystemTrayIcon::Trigger){
show();
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zhu_hong_jun/qt-media-player.git
git@gitee.com:zhu_hong_jun/qt-media-player.git
zhu_hong_jun
qt-media-player
QT-MediaPlayer
master

搜索帮助