实现本地音乐播放
基本逻辑
1.点击导入歌曲按钮,弹出文件选择界面设置只能选择mp3文件,得到此音乐文件的路径并利用ffmpeg解析音乐的详细信息
2.点击播放全部则发送一个信号到主界面参数为音乐信息的链表
3.双击则发送添加歌曲到播放列表的一个信号参数是该选中音乐的所有信息
(此处会做判断,判断是否当前播放列表含有该歌曲,如果有则无需添加,直接播放该首歌曲,若无则添加在播放列表最后面,播放器直接播放该首歌曲)
代码
localwget.h
#ifndef LOCALWGET_H
#define LOCALWGET_H
#include <QWidget>
#include <QTableWidget>
#include <QPushButton>
#include <QFileDialog>
#include <QStringList>
#include <QDir>
#include <QLabel>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
}
class LocalWget :public QWidget
{
Q_OBJECT
public:
explicit LocalWget(QWidget *parent = 0);
~LocalWget();
QTableWidget * songTableWidget;
QPushButton * m_pButPlayAllSong;
QPushButton* m_pButInputSong;
QPushButton* m_pButMoreCtor;
private:
struct findResult
{
QString hash;
QString songName;
QString singername;
QString album_name;
QString filesize;
QString playPath;
QString timelength;
QImage image;
QString imagePath;
}stResultList;
//
QList<findResult> m_listResult;
signals:
void playAllLocalMusic(QList<findResult>);
void addOneSongInLIst(findResult);
private slots:
void importSongs();
void mainWgetplayAllLocalMusic();
void changeMusicPlayList(int);
private:
void getMusicInfo(QString filename);
QMap<QString,QString> m_InfoMap;
AVFormatContext *m_AVFormatContext;
QString initialName;
};
#endif // LOCALWGET_H
localwget.cpp
#include "localwget.h"
#include <QLabel>
#include <QDebug>
#include <QMapIterator>
#include "mydatabase.h"
LocalWget::LocalWget(QWidget *parent):
QWidget(parent)
{
//
m_AVFormatContext = nullptr;
//
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
setFixedSize(800,500); //819,527
setAutoFillBackground(true);
songTableWidget = new QTableWidget(0, 5, this);
songTableWidget->setStyleSheet("border-color:white;\
border-style:solid;");
songTableWidget->setAutoFillBackground(true);
QStringList TableHeader;
TableHeader << QStringLiteral("歌曲") << QStringLiteral("歌手")<< QStringLiteral("专辑")<< QStringLiteral("时间");
songTableWidget->setHorizontalHeaderLabels(TableHeader);
songTableWidget->setFixedSize(760, 460);
songTableWidget->move(40, 40);
//songTableWidget->setPalette(QPalette(QColor(120, 214, 255, 255)));
songTableWidget->setShowGrid(false);
songTableWidget->setColumnWidth(0, 300);
songTableWidget->setColumnWidth(1, 160);
songTableWidget->setColumnWidth(2, 160);
songTableWidget->setColumnWidth(3, 100);
songTableWidget->setColumnHidden(4,true);
songTableWidget->setEditTriggers(QTableWidget::NoEditTriggers);
songTableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// 设置只能选择单行
songTableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
songTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);//整行选中
// 设置不显示网格
songTableWidget->setFrameShape(QFrame::NoFrame); //设置无边框
songTableWidget->setShowGrid(false);
connect(songTableWidget, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(changeMusicPlayList(int)));
this->setStyleSheet("QPushButton { \
color:black; \
border-radius:12px;\
border-width:1;\
border-color:black;\
border-style:solid;;\
background-color:rgba(0,0,0,0); \
}\
QPushButton:hover { \
color:red; \
border-radius:12px;\
border-width:1;\
border-color:red;\
border-style:solid;;\
background-color:rgba(0,0,0,0); \
}");
//
QLabel *lab = new QLabel(this);
lab->setText("▋ 本地音乐");
lab->setGeometry(40,10,100,28);
//
m_pButPlayAllSong = new QPushButton(this);
m_pButPlayAllSong->setText("►播放全部");
m_pButPlayAllSong->setGeometry(474,10,92,24);
QObject::connect(m_pButPlayAllSong,SIGNAL(clicked(bool)),this,SLOT(mainWgetplayAllLocalMusic()));
//
m_pButInputSong = new QPushButton(this);
m_pButInputSong->setText("导入歌曲");
m_pButInputSong->setGeometry(576,10,92,24);
QObject::connect(m_pButInputSong,SIGNAL(clicked(bool)),this,SLOT(importSongs()));
//
m_pButMoreCtor= new QPushButton(this);
m_pButMoreCtor->setText("┄ 更多操作");
m_pButMoreCtor->setGeometry(678,10,92,24);
}
LocalWget::~LocalWget()
{
delete songTableWidget;
delete m_pButPlayAllSong;
delete m_pButInputSong;
delete m_pButMoreCtor;
}
void LocalWget::importSongs()
{
QStringList pathList = QFileDialog::getOpenFileNames(this, QStringLiteral("选择文件"), initialName, tr("(*.mp3)"));
for (int i = 0; i < pathList.size(); ++i)
{
QString path = QDir::toNativeSeparators(pathList.at(i));
if (!path.isEmpty())
{
//m_musicPlayList->addMedia(QUrl::fromLocalFile(path));
getMusicInfo(path);
}
}
// MyDatabase::getInstance().selectAll(QString("t_mylocal"));
//MyDatabase::getInstance().deleteAll(QString("t_mylocal"));
if (pathList.size() != 0)
{
//initialName = pathList.at(0).left(pathList.at(0).lastIndexOf('/', -1));
}
}
void LocalWget::mainWgetplayAllLocalMusic()
{
emit playAllLocalMusic(m_listResult);
}
void LocalWget::changeMusicPlayList(int row)
{
if (row >= songTableWidget->rowCount())
return;
emit addOneSongInLIst(m_listResult.at(row));
}
void LocalWget::getMusicInfo(QString filename)
{
int result = avformat_open_input(&m_AVFormatContext, filename.toLocal8Bit().data(), nullptr, nullptr);
if (result != 0 || m_AVFormatContext == nullptr)
return ;
// 查找流信息,把它存入AVFormatContext中
if (avformat_find_stream_info(m_AVFormatContext, nullptr) < 0)
return ;
// int streamsCount = m_AVFormatContext->nb_streams;
m_InfoMap.clear();
// 读取详细信息
AVDictionaryEntry *tag = nullptr;
while (tag = av_dict_get(m_AVFormatContext->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))
{
QString keyString = tag->key;
QString valueString = QString::fromUtf8(tag->value);
m_InfoMap.insert(keyString, valueString);
}
//插入
int duration_s = m_AVFormatContext->duration/1000000;
int rownum = songTableWidget->rowCount();
songTableWidget->insertRow(rownum);
songTableWidget->setItem(rownum, 0, new QTableWidgetItem(m_InfoMap.value("title","未知")));
songTableWidget->setItem(rownum, 1, new QTableWidgetItem(m_InfoMap.value("artist","未知")));
songTableWidget->setItem(rownum, 2, new QTableWidgetItem(m_InfoMap.value("album","未知")));
songTableWidget->setItem(rownum, 3, new QTableWidgetItem(QString("%1:%2").arg(duration_s/60).arg(duration_s%60,2,10,QChar('0'))));
songTableWidget->setItem(rownum, 4, new QTableWidgetItem(QDir::toNativeSeparators(filename)));
findResult tmpInfo;
int streamsCount = m_AVFormatContext->nb_streams;
for (int i=0; i<streamsCount; ++i)
{
if (m_AVFormatContext->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)
{
AVPacket pkt = m_AVFormatContext->streams[i]->attached_pic;
tmpInfo.image = QImage::fromData((uchar*)pkt.data, pkt.size);
}
}
tmpInfo.songName =m_InfoMap.value("artist","未知")+"-"+m_InfoMap.value("title","未知");
tmpInfo.singername =m_InfoMap.value("artist","未知");
tmpInfo.hash ="";
tmpInfo.playPath = QUrl::fromLocalFile(filename).toString();;
tmpInfo.timelength =QString("%1:%2").arg(duration_s/60).arg(duration_s%60,2,10,QChar('0'));
tmpInfo.album_name = m_InfoMap.value("album","未知") ;
m_listResult.append(tmpInfo);
//
// QStringList list;
// list.append(QString("%1").arg(rownum));
// list.append(m_InfoMap.value("title","未知"));
// list.append(m_InfoMap.value("artist","未知"));
// list.append(m_InfoMap.value("album","未知"));
// list.append(QString("%1:%2").arg(duration_s/60).arg(duration_s%60,2,10,QChar('0')));
// list.append(filename);
// MyDatabase::getInstance().addMusicInfo(list);
//关闭
if(m_AVFormatContext)
avformat_close_input(&m_AVFormatContext);
}
主界面处理
qt提供的多媒体类:
//播放控制
QMediaPlayer * m_musicPlayer;
QMediaPlaylist* m_musicPlayList=nullptr;
注:如果要使用该类除需要添加相应的头文件外还需要在pro文件中添加
QT += multimedia
void MainWindow::slotPlayAllSong(QList<findResult> playlist)
{
m_musicPlayList->clear();
m_listResult.clear();
// int lenth =playlist.length();
ui->m_pLabPlayingSongSize->setText("0");
while ( ui->m_playingLisTableWidget->rowCount())
{
ui->m_playingLisTableWidget->removeRow(0);
}
for(int i=0;i<playlist.length();i++)
{
if(playlist.at(i).playPath.isEmpty())
{
// --lenth;
playlist.removeAt(i);
continue;
}
m_musicPlayList->addMedia(QUrl(playlist.at(i).playPath));
// qDebug() <<playlist.at(i).songName;
// qDebug() <<playlist.at(i).playPath;
int rownum = ui->m_playingLisTableWidget->rowCount();
ui->m_playingLisTableWidget->insertRow(rownum);
ui->m_playingLisTableWidget->setItem(rownum, 0, new QTableWidgetItem(playlist.at(i).songName));
ui->m_playingLisTableWidget->setItem(rownum, 1, new QTableWidgetItem(playlist.at(i).timelength));
}
ui->m_pLabPlayingSongSize->setText( QString("%1").arg(playlist.length()));
if(m_musicPlayList->isEmpty())
return;
m_listResult = playlist;
m_musicPlayer->play();
ui->m_pButSongPlay->setText("😕");
ui->m_pButSongPlay->setToolTip("暂停");
}
void MainWindow::slotAddOneSongInList(findResult songinfo)
{
if(songinfo.playPath.isEmpty())
return;
if(m_listResult.isEmpty())
{
m_musicPlayList->addMedia(QUrl(songinfo.playPath));
m_listResult.append(songinfo);
int rownum = ui->m_playingLisTableWidget->rowCount();
ui->m_playingLisTableWidget->insertRow(rownum);
ui->m_playingLisTableWidget->setItem(rownum, 0, new QTableWidgetItem(songinfo.songName));
ui->m_playingLisTableWidget->setItem(rownum, 1, new QTableWidgetItem(songinfo.timelength));
m_musicPlayList->setCurrentIndex(0);
}
else
{
for(int i=0;i<m_listResult.length();i++)
{
if(songinfo.playPath == m_listResult.at(i).playPath || songinfo.songName == m_listResult.at(i).songName)
{
m_musicPlayList->setCurrentIndex(i);
break;
}
else if(songinfo.playPath != m_listResult.at(i).playPath&&i ==m_listResult.length()-1 )
{
m_musicPlayList->addMedia(QUrl(songinfo.playPath));
m_listResult.append(songinfo);
int rownum = ui->m_playingLisTableWidget->rowCount();
ui->m_playingLisTableWidget->insertRow(rownum);
ui->m_playingLisTableWidget->setItem(rownum, 0, new QTableWidgetItem(songinfo.songName));
ui->m_playingLisTableWidget->setItem(rownum, 1, new QTableWidgetItem(songinfo.timelength));
m_musicPlayList->setCurrentIndex(rownum-1);
}
}
}
ui->m_pLabPlayingSongSize->setText( QString("%1").arg(m_listResult.length()));
m_musicPlayer->play();
ui->m_pButSongPlay->setText("😕");
ui->m_pButSongPlay->setToolTip("暂停");
}
播放模式控制
//单曲循环
void MainWindow::on_m_pButSingleCycle_clicked()
{
ui->WidgetMode->hide();
if(m_musicPlayList == nullptr)
return ;
ui->m_pButChosePlayMode->setText("₪¹");
ui->m_pButChosePlayMode->setToolTip(QStringLiteral("单曲循环"));
m_musicPlayList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
}
void MainWindow::on_m_pButRandomn_clicked()
{
ui->WidgetMode->hide();
if(!m_musicPlayList)
return ;
ui->m_pButChosePlayMode->setText("≈");
ui->m_pButChosePlayMode->setToolTip(QStringLiteral("随机播放"));
m_musicPlayList->setPlaybackMode(QMediaPlaylist::Random);
}
void MainWindow::on_m_pButAllCycle_clicked()
{
ui->WidgetMode->hide();
if(!m_musicPlayList)
return ;
ui->m_pButChosePlayMode->setToolTip(QStringLiteral("列表循环"));
ui->m_pButChosePlayMode->setText("⇄");
m_musicPlayList->setPlaybackMode(QMediaPlaylist::Loop);
}
void MainWindow::on_m_pButSequential_clicked()
{
ui->WidgetMode->hide();
if(!m_musicPlayList)
return ;
ui->m_pButChosePlayMode->setText("⇉");
ui->m_pButChosePlayMode->setToolTip(QStringLiteral("顺序播放"));
m_musicPlayList->setPlaybackMode(QMediaPlaylist::Sequential);
}