diff --git a/mainwindow.cpp b/mainwindow.cpp index 1060448..05ef24b 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -8,6 +8,11 @@ MainWindow::MainWindow(QWidget *parent) 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() @@ -54,20 +59,19 @@ void MainWindow::initMainWindow() void MainWindow::mplayerInit() { // 创建一个无名管道 - int fd[2]; pipe(fd); // 创建有名管道 - mkfifo("fifo_cmd",0666); + mkfifo("fifo_cmd", 0666); // 创建 子进程启动 mplayer pid_t pid = fork(); if(pid == 0) // 子进程 { // 重定向标准输出 - dup2(fd[1],1); + 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","/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); // 异常退出 } @@ -75,11 +79,122 @@ void MainWindow::mplayerInit() { // 打开管道 // 以写的方式打开(阻塞到某进程 以读的方式打开) - int fifo_fd = open("fifo_cmd",O_WRONLY); + fifo_fd = open("fifo_cmd", O_WRONLY); if(fifo_fd < 0){ perror("open"); -// return 0; - _exit(-1); + // 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", ¤tProgress); + // 给 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); +} diff --git a/mainwindow.h b/mainwindow.h index e507986..6f746fc 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -2,12 +2,19 @@ #define MAINWINDOW_H #include +#include #include #include #include #include #include +#include +#include +#include +#include + +using namespace std; QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } @@ -17,13 +24,32 @@ class MainWindow : public QMainWindow { Q_OBJECT +private: + int fd[2]; // 声明无名管道 + int fifo_fd; // 声明有名管道 + int index = 0; // 歌曲索引 + vector vectorSong; // 歌曲名动态数组 + public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); public: - void initMainWindow(); + void initMainWindow(); // 主窗体初始化 void mplayerInit(); // 初始化 mplayer + void scanSong(); // 扫描歌曲文件 + void *getTimerThreadFunc(void *arg); // 发送获取当前时间的 mplayer 命令 + void *readPipeMSG(void *arg); // 获取当前时间的线程 + + +public slots: + void playNextSong(); // 切换歌曲槽函数I + void setCurrentTimeLabel(int time); // 设置当前时间标签槽函数 + void setCurrentSlider(int currentProgress); // 设置当前进度条 + +signals: + void currentTimeSignal(int time); // 当前时间信号 + void currentProgressSignal(int currentProgress); // 当前进度信号 private: Ui::MainWindow *ui;