STM32MP157开发板Linux+Qt项目实战:音乐播放器
stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux+单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器,集成2个Cortex-A7核和1个Cortex-M4 核,A7核上可以跑Linux操作系统,M4核上可以跑FreeRTOS、RT-Thread等实时操作系统。开发板搭配仿真器、显示屏、摄像头、资源扩展板等丰富的扩展模块,可拓展物联网、人工智能等相关技术学习,还可以拓展丰富的项目实战,非常贴合企业当下开发需求,是一款嵌入式Linux入门进阶必备开发板!
可学习技术:嵌入式Linux应用/系统/驱动开发、ARM裸机开发、Qt界面编程、STM32单片机、FreeRTOS、人工智能机器视觉等。其中ARM Cortex-A7裸机开发课程是华清远见独有特色课程,可关注:https://www.bilibili.com/video/BV1Xe4y1i7vm/,持续更新中。
![](https://www.0419af.com/wp-content/uploads/2023/02/1675237774-46a309f1022ff0c.png)
可实战项目:14个Linux+Qt综合项目案例,8个MP1A物联网拓展项目
项目配套文档及源码,可在下方评论区留言索取~~
1、Linux+Qt综合项目案例:华清远见stm32mp157开发板优势特色部分,包括音乐播放器、智慧家庭、智能工业电表、智能出行助手、智能猫眼、环境监测、智能安防、智能语音识别等10余个项目案例,涉及家居、医疗、农业多种应用方向,在案例中使用了多种物联网和嵌入式技术,包括OT开发、linux应用开发、linux驱动开发、物联网云端接入、MQTT协议、json字符串等知识点。
基于Linux+Qt的音乐播放器项目
开发平台:
华清远见stm32mp157开发板豪华套餐(开发板+仿真器+五寸屏+摄像头+资源扩展板+tf卡+读卡器)
项目功能:
1.批量从本地导入歌曲到歌曲列表中。
2.清空歌曲列表。
3.删除歌曲列表中选中的歌曲。
4.用进度条显示歌曲播放的进度,并显示时间。
5.用“播放/暂停”、“停止”、“上一曲”、“下一曲”四个按钮对歌曲
进行控制。
6.用滑动器对歌曲音量进行控制。
7.右键会弹出菜单,可以对程序进行相应的控制。
8.提取歌曲的歌词,并解析歌词,根据歌曲的播放进度显示歌词。
项目展示:
项目实战:
源码分析
UI 界面设计
使用三个 pushbutton 来添加歌曲、删除歌曲和清空歌曲列表。使用四个
toolbutton 来控制歌曲的播放、停止、上一曲、下一曲。使用 ListWidget 控
件来存放歌曲列表。使用 slider 来控制音量和歌曲进度。
文件配置
因为下面要使用音频播放功能,所以需要在 pro 文件引入
QT += core gui multimedia
歌词类(Lyrics)
这个类通过 readLine 这个函数循环读取每一行的歌词,读取到使用
analysisLyricsFile()函数进行解析,使用正则表达式解析 lrc 歌词文件,
获取歌词和时间。
while((line=file.readLine())>0){
analysisLyricsFile(line);
}
lyrics.h
#ifndef LYRICS_H
#define LYRICS_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class Lyrics
{
private:
QString lyricsPath;
public:
QList listLyricsText;
QList listLyricsTime;
public:
Lyrics(QString lyricsPath);
Lyrics();
bool readLyricsFile(QString lyricsPath);
bool analysisLyricsFile(QString line);
QList getListLyricsText() const;
QList getListLyricsTime() const;
};
#endif // LYRICS_H
Lyrics.c
#include “lyrics.h”
QList Lyrics::getListLyricsText() const{
return listLyricsText;
}
QList Lyrics::getListLyricsTime() const{
return listLyricsTime;
}
Lyrics::Lyrics(QString lyricsPath){
this->lyricsPath = lyricsPath;
}
bool Lyrics::readLyricsFile(QString lyricsPath)
{
QFile file(lyricsPath);
qDebug()
qDebug()
qDebug()
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void addSongs();
void playPause();
void playStop();
void playNext();
void playPrevious();
void posChanged(qint64 pos);
void durChanged(qint64 dur);
void setPos(int pos);
void clearList();
void delectSong();
void volumeSilence();
void setVol(int vol);
void hideShow();
void redVolume();
void addVolume();
void setPlayTime();
private:
Ui::Widget *ui;
private:
QMediaPlayer* player;
QMediaPlaylist* playList;
QAction* action_hideShow;
QAction* action_addSongs;
QAction* action_playPause;
QAction* action_stop;
QAction* action_previous;
QAction* action_next;
QAction* action_addVolume;
QAction* action_redVolume;
QAction* action_quit;
Lyrics lyrics;
int lyricsID = 0;
QString playPath;
QString presentTime;
QString totalTime;
protected:
void contextMenuEvent(QContextMenuEvent* );
};
#endif // WIDGET_H
Widget.cpp
#include “widget.h”
#include “ui_widget.h”
#include
#include
#include
#include
#define BOARD_TYPE_RGB 0
#define BOARD_TYPE_MIPI 1
static int get_board_type(void)
{
char searchText[]=”-mipi050″;
int len_searchText;
FILE *file;
char string[128];
int len_string;
int i = 0;
memset(string, 0x0, sizeof(string));
file = fopen(“/proc/device-tree/compatible”, “r”);
if (file == NULL) {
printf(“fails to open /proc/device-tree/compatible\n”);
return -1;
}
len_searchText = strlen(searchText);
while(fgets(string, sizeof(string), file) != 0)
{
len_string = strlen(string);
for(i = 0 ; i < len_string ; i++) {
if(strncmp(searchText, (string + i), len_searchText)
== 0) {
fclose(file);
return BOARD_TYPE_MIPI;
}
}
}
fclose(file);
return BOARD_TYPE_RGB;
}
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
// 适配屏幕大小
int board_type = 0;
board_type = get_board_type();
qDebug()setPalette(palette);
ui->volumeSlider->setRange(0,100);
this->setWindowTitle(tr(“hqyj 音乐播放器”));
this->playList=new QMediaPlaylist(this);
playList->setPlaybackMode(QMediaPlaylist::Loop);
this->player=new QMediaPlayer(this);
player->setPlaylist(playList);
player->setVolume(50);
ui->volumeSlider->setValue(50);
ui->songsList->setStyleSheet(“backgroundcolor:transparent;color: white”);
ui->addSongsButton->setStyleSheet(“QPushButton{background:
none;border:none;color: white}”);
ui->clearButton->setStyleSheet(“QPushButton{background:
none;border:none;color: white}”);
ui->delectButton->setStyleSheet(“QPushButton{background:
none;border:none;color: white}”);
ui->volumeButton->setStyleSheet(“QToolButton{borderradius:5px;border-width:0px;}”);
connect(ui->volumeSlider,SIGNAL(valueChanged(int)),this,SLOT(setV
ol(int)));
connect(ui->addSongsButton,SIGNAL(clicked()),this,SLOT(addSongs()
));
connect(ui->playPauseButton,SIGNAL(clicked()),this,SLOT(playPause
()));
connect(ui->stoptButton,SIGNAL(clicked()),this,SLOT(playStop()));
connect(ui->previousButton,SIGNAL(clicked()),this,SLOT(playPrevio
us()));
connect(ui->nextButton,SIGNAL(clicked()),this,SLOT(playNext()));
connect(player,SIGNAL(durationChanged(qint64)),this,SLOT(durChang
ed(qint64)));
connect(player,SIGNAL(positionChanged(qint64)),this,SLOT(posChang
ed(qint64)));
connect(ui->processSlider,SIGNAL(valueChanged(int)),this,SLOT(set
Pos(int)));
connect(ui->clearButton,SIGNAL(clicked()),this,SLOT(clearList()));
connect(ui->delectButton,SIGNAL(clicked()),this,SLOT(delectSong()
));
connect(ui->volumeButton,SIGNAL(clicked()),this,SLOT(volumeSilenc
e()));
ui->stoptButton->setStyleSheet(“border:2px groove
gray;border-radius:10px;padding:2px 4px;”);
ui->playPauseButton->setStyleSheet(“border:2px groove
gray;border-radius:10px;padding:2px 4px;”);
ui->previousButton->setStyleSheet(“border:2px groove
gray;border-radius:10px;padding:2px 4px;”);
ui->nextButton->setStyleSheet(“border:2px groove
gray;border-radius:10px;padding:2px 4px;”);
action_hideShow=new QAction(tr(“隐藏/显示窗口部件”),this);
action_addSongs=new QAction(tr(“添加本地歌曲”),this);
action_playPause=new QAction(tr(“播放/暂停”),this);
action_stop=new QAction(tr(“停止”),this);
action_previous=new QAction(tr(“上一曲”),this);
action_next=new QAction(tr(“下一曲”),this);
action_addVolume=new QAction(tr(“音量+(5%)”),this);
action_redVolume=new QAction(tr(“音量-(5%)”),this);
action_quit=new QAction(tr(“退出”),this);
connect(action_hideShow,SIGNAL(triggered()),this,SLOT(hideShow())
);
connect(action_addSongs,SIGNAL(triggered()),this,SLOT(addSongs())
);
connect(action_playPause,SIGNAL(triggered()),this,SLOT(playPause(
)));
connect(action_stop,SIGNAL(triggered()),this,SLOT(playStop()));
connect(action_previous,SIGNAL(triggered()),this,SLOT(playPreviou
s()));
connect(action_next,SIGNAL(triggered()),this,SLOT(playNext()));
connect(action_addVolume,SIGNAL(triggered()),this,SLOT(addVolume(
)));
connect(action_redVolume,SIGNAL(triggered()),this,SLOT(redVolume(
)));
connect(action_quit,SIGNAL(triggered()),this,SLOT(close()));
}
Widget::~Widget()
{
delete ui;
}
//每当音量进度条改变,会触发这个槽函数重新设置音量大小
void Widget::setVol(int vol)
{
player->setVolume(vol);
}
//选择要添加的所有歌曲,添加到 QStringList 中,遍历 QStringList 中的所
有.MP3 文件
//添加到 playList 中,并且添加到 ui 界面的 QlistWight 中
void Widget::addSongs()
{
QStringList songsList=QFileDialog::getOpenFileNames(this,”
选择文件”,QDir::homePath(),”*.mp3″);
for(int i=0;i
ui->processSlider->setEnabled(true);
if(“播放”==ui->playPauseButton->text())
{
int index=ui->songsList->currentRow();
if(-1!=index)
{
//歌曲名字
QString songname
=ui->songsList->item(index)->text().left(ui->songsList->item(inde
x)->text().lastIndexOf(“.”));
playList->setCurrentIndex(index);
player->play();
ui->playPauseButton->setText(“暂停”);
ui->playPauseButton->setIcon(QIcon(“:/images/pause.png”));
// 读取歌词文件
if(!lyrics.readLyricsFile(playPath+”/”+songname+”.lrc”)){
ui->label->setText(“未检测到歌词文件”);
ui->label_2->setText(“请检查歌词文件是否存在”);
}
lyricsID = 0;
}
}
else
{
player->pause();
ui->playPauseButton->setText(“播放”);
ui->playPauseButton->setIcon(QIcon(“:/images/play.png”));
}
}
//播放/停止
void Widget::playStop()
{
ui->processSlider->setEnabled(false);
this->player->stop();
// 清空歌词
ui->label->clear();
ui->label_2->clear();
lyrics.listLyricsText.clear();
}
//播放上一曲
void Widget::playPrevious()
{
player->stop();
int index=playList->currentIndex();
if(0==index)
index=playList->mediaCount()-1;
else
index–;
playList->setCurrentIndex(index);
ui->songsList->setCurrentRow(index);
// player->play();
ui->playPauseButton->setText(“播放”);
ui->playPauseButton->setIcon(QIcon(“:/images/play.png”));
// 清空歌词
ui->label->clear();
ui->label_2->clear();
lyrics.listLyricsText.clear();
}
//播放下一曲
void Widget::playNext()
{
player->stop();
int index=playList->currentIndex();
if(index==playList->mediaCount()-1)
index=0;
else
index++;
playList->setCurrentIndex(index);
ui->songsList->setCurrentRow(index);
ui->playPauseButton->setText(“播放”);
ui->playPauseButton->setIcon(QIcon(“:/images/play.png”));
// 清空歌词
ui->label->clear();
ui->label_2->clear();
lyrics.listLyricsText.clear();
}
//设置进度条显示范围,并计算歌曲总时间,显示出来
void Widget::durChanged(qint64 dur)
{
ui->processSlider->setRange(0,dur);
totalTime.clear();
dur/=1000;
totalTime+=QString::number(dur/60);
totalTime+=’:’;
if(dur%60totalTimeLabel->setText(totalTime);
}
//设置进度条的值,并计算当前时间,显示出来
void Widget::posChanged(qint64 pos)
{
presentTime.clear();
ui->processSlider->setValue(pos);
pos/=1000;
presentTime+=QString::number(pos/60);
presentTime+=’:’;
if(pos%60presentTimeLabel->setText(presentTime);
if(presentTime==totalTime)
{
presentTime.clear();
player->stop();
ui->label->clear();
ui->label_2->clear();
}
//根据播放进度的改变设置播放进度
void Widget::setPos(int pos)
{
player->setPosition(pos);
setPlayTime();
}
//清空播放列表
void Widget::clearList()
{
playList->clear();
ui->songsList->clear();
}
//在播放列表中删除某首歌曲
void Widget::delectSong()
{
int index=ui->songsList->currentRow();
if(-1!=index)
{
ui->songsList->takeItem(index);
playList->removeMedia(index);
}
}
//设置有音量和静音
void Widget::volumeSilence()
{
if(ui->volumeButton->text()==tr(“音量”))
{
ui->volumeButton->setText(tr(“静音”));
ui->volumeSlider->setValue(0);
ui->volumeButton->setIcon(QIcon(“:/images/silence.png”));
}
else
{
ui->volumeButton->setText(tr(“音量”));
ui->volumeButton->setIcon(QIcon(“:/images/volume.png”));
ui->volumeSlider->setValue(50);
}
}
/*鼠标右击事件
*每次鼠标右击都会显示菜单*/
void Widget::contextMenuEvent(QContextMenuEvent*)
{
QMenu* menu=new QMenu(this);
menu->addAction(action_hideShow);
menu->addAction(action_addSongs);
menu->addSeparator();
menu->addAction(action_playPause);
menu->addAction(action_stop);
menu->addAction(action_previous);
menu->addAction(action_next);
menu->addSeparator();
menu->addAction(action_addVolume);
menu->addAction(action_redVolume);
menu->addSeparator();
menu->addAction(action_quit);
menu->move(cursor().pos());
menu->show();
}
//控件隐藏/显示
void Widget::hideShow()
{
if(ui->songsList->isVisible())
{
ui->addSongsButton->setVisible(false);
ui->clearButton->setVisible(false);
ui->delectButton->setVisible(false);
ui->songsList->setVisible(false);
ui->processSlider->setVisible(false);
ui->presentTimeLabel->setVisible(false);
ui->totalTimeLabel->setVisible(false);
ui->volumeButton->setVisible(false);
ui->volumeSlider->setVisible(false);
}
else
{
ui->addSongsButton->setVisible(true);
ui->clearButton->setVisible(true);
ui->delectButton->setVisible(true);
ui->songsList->setVisible(true);
ui->processSlider->setVisible(true);
ui->presentTimeLabel->setVisible(true);
ui->totalTimeLabel->setVisible(true);
ui->volumeButton->setVisible(true);
ui->volumeSlider->setVisible(true);
}
}
//每触发一次,音量+5%,设置到音量进度条上。
void Widget::addVolume()
{
int vol=ui->volumeSlider->value();
vol+=5;
if(vol>100)
vol=100;
ui->volumeSlider->setValue(vol);
}
//每触发一次,音量-5%,设置到音量进度条上。
void Widget::redVolume()
{
int vol=ui->volumeSlider->value();
vol-=5;
if(volvolumeSlider->setValue(vol);
}
void Widget::setPlayTime()
{
if(!lyrics.getListLyricsTime().empty()&&player->position()>=lyric
s.getListLyricsTime().at(lyricsID)&&lyricsID
ui->processSlider->setRange(0,dur);
totalTime.clear();
dur/=1000;
totalTime+=QString::number(dur/60);
totalTime+=’:’;
if(dur%60totalTimeLabel->setText(totalTime);
}
设置进度条显示范围,并计算歌曲总时间,显示出来。
setPlayTime()
在歌词显示栏里设置读取到的歌词。
void Widget::setPlayTime()
{
if(!lyrics.getListLyricsTime().empty()&&player->position()>=lyric
s.getListLyricsTime().at(lyricsID)&&lyricsID