qtmplayer/mainwindow.cpp

201 lines
6.6 KiB
C++

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
initMainWindow(); // 初始化主界面
mplayerInit(); // 初始化 mplayer
// 捕获当前时间信号
connect(this, SIGNAL(currentTimeSignal(int)), this, SLOT(setCurrentTimeLabel(int)));
// 建立滑块修改信号通讯
connect(this, SIGNAL(currentProgressSignal(int)), this, SLOT(setCurrentSlider(int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initMainWindow()
{
// 设置主窗体属性
setWindowTitle("音乐播放器");
// 设置子组件背景透明
ui->song_list_widget->setAttribute(Qt::WA_TranslucentBackground);
ui->label_artist->setAttribute(Qt::WA_TranslucentBackground);
ui->label_song_list->setAttribute(Qt::WA_TranslucentBackground);
ui->label_song_name->setAttribute(Qt::WA_TranslucentBackground);
ui->label_meta_album->setAttribute(Qt::WA_TranslucentBackground);
ui->contrl_widget->setAttribute(Qt::WA_TranslucentBackground);
ui->widget_show->setAttribute(Qt::WA_TranslucentBackground);
ui->volume_widget->setAttribute(Qt::WA_TranslucentBackground);
ui->widget_3->setAttribute(Qt::WA_TranslucentBackground);
ui->time_left_label->setAttribute(Qt::WA_TranslucentBackground);
ui->time_right_label->setAttribute(Qt::WA_TranslucentBackground);
ui->time_widget->setAttribute(Qt::WA_TranslucentBackground);
// 设置滑块属性
ui->time_slider->setStyleSheet("QSlider::groove:horizontal { background-color: white; }"
"QSlider::handle:horizontal { background-color: blue; width: 20px;}");
ui->volume_slider->setStyleSheet("QSlider::groove:horizontal { background-color: gray; }"
"QSlider::handle:horizontal { background-color: yellow; width: 20px;}");
ui->volume_slider->setMinimum(0); // 最小音量 0
ui->volume_slider->setMaximum(100); // 最大音量 100
// 当前音量从 mplayer 属性获取
// QSlider* slider = new QSlider(Qt::Horizontal);
// slider->setMinimum(0); // 设置最小值
// slider->setMaximum(100); // 设置最大值
// slider->setValue(50); // 设置当前值
// slider->setSingleStep(1); // 设置步长
}
void MainWindow::mplayerInit()
{
// 创建一个无名管道
pipe(fd);
// 创建有名管道
mkfifo("fifo_cmd", 0666);
// 创建 子进程启动 mplayer
pid_t pid = fork();
if(pid == 0) // 子进程
{
// 重定向标准输出
dup2(fd[1], 1);
// 使用 exec 启动 mplayer
// execlp("mplayer","mplayer","-idle","-slave","-quiet","/home/flykhan/qtmplayer/song/StopLove.mp3",NULL);
execlp("mplayer","mplayer","-idle","-slave","-quiet","-input","file=fifo_cmd","/home/flykhan/qtmplayer/song/StopLove.mp3",NULL);
_exit(-1); // 异常退出
}
else if(pid>0) // 父进程
{
// 打开管道
// 以写的方式打开(阻塞到某进程 以读的方式打开)
fifo_fd = open("fifo_cmd", O_WRONLY);
if(fifo_fd < 0){
perror("open");
// return 0;
_exit(0); // 管道打开失败直接返回
}
}
}
void MainWindow::scanSong()
{
// 1. 得到目录句柄
DIR *dir = opendir("./song");
if(NULL == dir)
{
perror("opendir");
_exit(0); // 目录为空返回
}
// 2. 根据目录句柄扫描当前文件
while(1)
{
// 读取文件目录
struct dirent *dirent = readdir(dir);
if(NULL==dirent)
break;
// 判断类型为 DT_REG->文件类型
if(dirent->d_type == DT_REG)
{
// 如果扫描到的文件名包含 ".mp3",则将该文件名添加到向量数组中
if(strstr(dirent->d_name, ".mp3") != NULL)
{
vectorSong.push_back(string(dirent->d_name));
}
}
}
// 关闭目录句柄
closedir(dir);
}
void MainWindow::playNextSong(void)
{
index++;
if(index == vectorSong.size())
index = 0; // 当索引到达歌曲最后一个时,将索引置为 0 ,循环索引
char changeSongBuf[128] = "";
// 将 loadfile 'song_name_path' 写入字符数组
int len = sprintf(changeSongBuf, "loadfile ./song/%s\n", vectorSong[index].c_str());
qDebug() << changeSongBuf << endl; // 控制台打印下一首歌的名字
write(this->fifo_fd, changeSongBuf, len); // 将获取的下一首歌曲名写入到有名管道中
}
void *MainWindow::getTimerThreadFunc(void *arg)
{
MainWindow *p = (MainWindow *)arg;
while (1)
{
// 发送获取的当前时间的命令
// 发送 get_time_pos 命令到管道中
write(p->fifo_fd, "get_time_pos\n", strlen("get_time_pos\n"));
usleep(500*1000); // 休眠 0.5 秒
// 发送获取当前歌曲进度的命令
write(p->fifo_fd,"get_percent_pos\n",strlen("get_percent_pos\n"));
usleep(500*1000); // 休眠 0.5 秒
}
}
void *MainWindow::readPipeMSG(void *arg)
{
MainWindow *p = (MainWindow *)arg;
// 不停的获取无名管道的数据
while (1)
{
char buf[256] = "";
int ret = read(p->fd[0], buf, sizeof(buf)); // 从无名管道读取内容到 buf
if(ret > 0)
{
// 判断消息的类型 :
// 如果消息是 "当前歌曲播放时间位置"
if(strncmp(buf,"ANS_TIME_POSITION",strlen("ANS_TIME_POSITION")) == 0)
{
int time = 0;
sscanf(buf,"ANS_TIME_POSITION=%d",&time); // 从数据流 buf 中读取时间到 time
// 给 UI 发送当前时间信号
emit p->currentTimeSignal(time);
}
// 如果消息是 "当前歌曲播放进度"
else if(strncmp(buf,"ANS_PERCENT_POSITION", strlen("ANS_PERCENT_POSITION")) == 0)
{
int currentProgress = 0;
sscanf(buf, "ANS_PERCENT_POSITION=%d", &currentProgress);
// 给 UI 发送进度信号
emit p->currentProgressSignal(currentProgress);
}
}
}
}
void MainWindow::setCurrentTimeLabel(int time)
{
int m = 0, s = 0;
m = time / 60; // 算分钟
s = time % 60; // 算秒钟
char buf[32] = "";
sprintf(buf,"%02d:%02d",m,s);
// 将歌曲当前时间设置到 label
ui->time_left_label->setText(QString(buf));
}
void MainWindow::setCurrentSlider(int currentProgress)
{
// 设置时间滑动条状态
ui->time_slider->setValue(currentProgress);
}