代码拉取完成,页面将自动刷新
#include "widget.h"
#include "ui_widget.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
#include <dirent.h>
#include <signal.h>
#include <QIcon>
#include<list>
#include<cstring>
#include<vector>
#include<algorithm>
struct mplayer
{
int fd_cmd;
int fd[2];
int pause_flag;//暂停状态
QList<QString> list;
//int song_num;//歌曲总数
int play_cur;//歌单数量索引
pthread_t pth1, pth2, pth3;//线程,全局
int num;//一个普通int变量
char *str_next[128];//指针数组存储歌曲名-下一首用
char *str_up[128];//指针数组存储歌曲名-上一首用
int volume_cur;//音量
int pos_t;//获得歌曲文件当前位置时间
int len_t;//文件总时长
int mute_flag;//静音开关。1:静音;0:取消静音
char *buf_time;
}widget;
struct Mysong
{
char *song[128];//存放歌曲字段的数组
int song_num;
int time_num;
};
Mysong mysong;
class Mysong_list//线程3中检索歌词文件使用的类,包含时间、歌词
{
public:
int time;
char *str;
Mysong_list()
{
time = 0;
str = new char[128]();
}
Mysong_list(int num, char *str_lrc)
{
this->time = num;
str = new char[128];
strcpy(str, str_lrc);
}
~Mysong_list()
{
}
};
extern Volume * volume_a = NULL;
extern TableWidget * tablewidget_a = NULL;
extern Song_listTable * song_list = NULL;
//父进程中,开启发送线程命令-发送到命名管道
void *send_cb(void *arg)
{
printf("pthread 1 \n");
widget.pause_flag = 1;//程序运行,进入线程,播放状态,就进行时间获取打印
// get_time_pos ====== 两条指令的效果
// ANS_TIME_POSITION=3.8 //当前歌曲播放时间
// get_time_length
// ANS_LENGTH=230.00 //歌曲总时长
char *send_cmd[2] = {"get_time_pos\n","get_time_length\n"};
int i = 0;
while(1)//不停的向有名管道文件发送命令
{
sleep(1);
for(i = 0; i < 2; i++)//2 条指令
{
if(widget.pause_flag == 1)//加上播放状态在发送获取时间指令,否则会冲开线程,导致播放、暂停按键失灵
{
write(widget.fd_cmd, send_cmd[i], strlen(send_cmd[i]));
}
}
}
//while(1);
}
void *recv_cb(void *arg)
{
Widget *p = (Widget*)arg;
printf("pthread 2 \n");
char buf[128] = "";
while(1)
{
memset(buf, 0, sizeof(buf));
read(widget.fd[0], buf, sizeof(buf));
// printf("---------%s---\n", buf);
if(strstr(buf, "ANS_TIME_POSITION"))
{
sscanf(buf, "%*[^=]=%d", &widget.pos_t);
char s[26] = "";
sprintf(s, "%02d : %02d", widget.pos_t/60, widget.pos_t%60);
printf("==== %s ====\n", s);
//把线程信息,发送到进程中
//发送当前歌曲时间
emit p->send_time_pos(s);
}
if(strstr(buf, "ANS_LENGTH"))
{
sscanf(buf, "%*[^=]=%d", &widget.len_t);
char s[26] = "";
sprintf(s, "%02d : %02d", widget.len_t/60, widget.len_t%60);
//把线程信息,发送到进程中
//发送歌曲总时间
emit p->send_time_len(s);
}
}
}
void *callback_3(void *arg)
{
Widget *p = (Widget*)arg;
printf("pthread 3 \n");
//mysong.song_num = 0;
char *buff;
buff = (char *)malloc(128);
strcpy(buff,widget.str_next[widget.play_cur]);
char *str1 = strtok(buff, ".");
//printf("-----Song_list---1-----/// %s ///--\n", str1);
char *buf_1 = strcat(str1, ".lrc");
//printf("-----Song_list---2-----/// %s ///--\n", buf_1);
//拼接路径
char *filename = (char *)malloc(strlen("./lyrics/")+strlen(str1)+1);
strcpy( filename ,"./lyrics/");
strcat(filename, str1);
printf("-----lyrics-----|| %s ||--\n", filename);
#if 1
FILE *fp;
fp = fopen(filename, "r+");
if(fp==NULL)
{
printf("没有该文件\n");
//return;
}
//char song[128] = {0};
//int time = 0;
int len = 0;
char *arr = NULL;
char *buf[128] = {NULL};//指针数字
int count = 0;
#endif
#if 1
if(fp == NULL)
{
printf("---fopen----\n");
perror("fopen");
}
else
{
printf("---fopen-Ok!!!---\n");
#if 1
fseek(fp, 0, SEEK_END);
len = ftell(fp);
rewind(fp);
#if 1
arr = (char *)malloc(sizeof(char) * (len +1));
fread(arr, len, 1, fp);
if(arr == NULL)
{
perror("arr=null");
fclose(fp);
}
fclose(fp);
#endif
#if 1
buf[count] = strtok(arr, "\r\n");
while(buf[count] != NULL)
{
count++;
buf[count] = strtok(NULL, "\r\n");
}
int rows = count;//行号统计
#endif
#endif
#if 1
vector<Mysong_list> qvec;
int i = 0;
//从第五行开始打印歌词和时间,一行一行拷贝
for(i = 4; i < rows; i++)
{
char *str_lrc = buf[i];
if('[' == *str_lrc)
{
int m = 0;
int s = 0;
int num[128] = {0};//存放时间
int *Pnum = num;//定义一个指针存放数组首地址,达到对数组元素地址的操作
sscanf(str_lrc, "[%d:%d", &m, &s);
*(Pnum++) = m*60 + s;
str_lrc = str_lrc + 10;
while('[' == *str_lrc)
{
sscanf(str_lrc, "[%d:%d", &m, &s);
*(Pnum++) = m*60 + s;
str_lrc = str_lrc + 10;
}
Pnum = num;
while(*Pnum)
{
qvec.push_back(Mysong_list(*Pnum, str_lrc));
Pnum++;
}
}
}
#endif
int m = 0;
int s = 0;
sscanf(widget.buf_time, "[%d:%d", &m, &s);
int time_num = m*60 + s;
while(1)
{
for(vector<Mysong_list>::iterator it = qvec.begin();it != qvec.end(); it++ )
{
if(time_num == (*it).time)
{//p->song_list->Song_listTable
//p->song_list->Song_TextEdit->setText(QString( (*it).str));
emit p->send_list((*it).str);
}
sleep(1);
}
}
}
#endif
}
void read_dir(char *path)
{
DIR *dir = opendir(path);
if(dir == NULL)
{
perror("NULL");
}
else
{
struct dirent *entry;
widget.num = 0;
while( (entry = readdir(dir)) != 0)
{
if(strstr(entry->d_name, ".mp3"))
{
widget.list.append(QString(entry->d_name));
printf("%s\n", entry->d_name);//所有歌曲名打印
}
}
//在这里直接把全部歌曲名都放到统一的指针数组中
//下一首、上一首共用一个指针数组
for(; widget.num < widget.list.size() -1; widget.num++)
{
widget.str_next[widget.num]=(char*)malloc(128);//拷贝的时候,这是个指针数组,需要为其中的每个指针分配空间!!!
strcpy( widget.str_next[widget.num], widget.list.at(widget.num).toUtf8().data());
}
}
}
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
read_dir("./music");
int ret = pipe(widget.fd);//无名管道
if(ret==0)
{
printf("fd[0]===%d:fd[1]===%d:\n",widget.fd[0],widget.fd[1]);
}
int ref = mkfifo("./fifo_cmd", 0666);//有名管道
if(ref == 0)
{
printf("有名管道ok\n");
}
pid_t pid = fork();//父子进程
this->pid = pid;
if(pid < 0)
{
perror("error");
}
else if(pid == 0)
{
//父进程中的线程,不停的给 "fifo_cmd" 有名管道写数据
//把标准输出 1 与 无名管道的写端 fd[1],绑定到一起
dup2(widget.fd[1], 1);//重定向:将写入到终端的数据,写入到无命名管道
execlp("mplayer"," mplayer ", "-slave", "-quiet","-idle","-input", "file=./fifo_cmd",\
"./music/sad_or_happy.mp3", NULL);
}
else
{
//connect(ui->)
pthread_create(&widget.pth1, NULL, send_cb, (void *)this);
pthread_create(&widget.pth2, NULL, recv_cb, (void *)this);
pthread_create(&widget.pth3, NULL, callback_3, (void *)this);
pthread_detach(widget.pth1);//分离函数调用,不会阻塞在线程那里
pthread_detach(widget.pth2);
pthread_detach(widget.pth3);
ui->setupUi(this);
this->volume_a = new Volume;
this->tablewidget_a = new TableWidget;
this->song_list = new Song_listTable;
widget.fd_cmd = open("./fifo_cmd", O_RDWR);
if(widget.fd_cmd < 0)
{
perror("widget.fd_cmd < 0");
}
//进入就获取一下当前歌曲名
ui->Song_TextEdit->setText(QString(widget.str_next[widget.play_cur]));
//静音
connect(ui->Mule_PushButton, &QPushButton::clicked, this, &Widget::Mule);
//隐藏歌词界面
connect(ui->List_Song_PushButton, &QPushButton::clicked, this, &Widget::Show_hide_List_Song);
//connect(ui->ProgressBar, &QPushButton::clicked, this, &Widget::Pause_slots);
//暂停播放器按键
connect(ui->Pause_PushButton, &QPushButton::clicked, this, &Widget::Pause_slots);
//下一首播放器按键
connect(ui->Next_PushButton, &QPushButton::clicked, this, &Widget::Next_slots);
//上一首播放器按键
connect(ui->Up_PushButton, &QPushButton::clicked, this, &Widget::Up_slots);
//显示、隐藏音量条
connect(ui->Volume_PushButton, &QPushButton::clicked, this, &Widget::Show_Hide);
//音量--滑动条控制(由volume滑动条界面发送音量数值信号)?
connect(this->volume_a, &Volume::volume_signals_verticalSlider, this, &Widget::rec_volume1);
//显示、隐藏放置歌曲名的表格
connect(ui->Table_PushButton, &QPushButton::clicked, this, &Widget::Show_hide_table);
//表格行号--点击当前表格发送的行信号
connect(this->tablewidget_a, &TableWidget::send_table_row, this, &Widget::rec_table_row);
//接收线程2中,发出的歌词总时间的信号、当前歌词时间信号
connect(this, &Widget::send_time_pos, this, &Widget::rec_time_pos);
//connect(this, &Widget::send_time_pos, song_list, &Song_listTable::Song_Listtable_02_Receive_The_widget_Response_Signal);
connect(this, &Widget::send_time_len, this, &Widget::rec_time_len);
//切歌的同时,给【歌曲列表cpp】发送'歌曲名'的字符串信号+ 序号
connect(this, &Widget::send_list, song_list, &Song_listTable::Song_Listtable_01_Receive_The_widget_Response_Signal);
//connect(ui->)
}
//close(widget.fd_cmd);
}
Widget::~Widget()
{
printf("mplayer kill !!!");
kill(pid, 9);
delete ui;
}
void Widget::Pause_slots()
{
if(widget.pause_flag == 1)
{ //border-image: url(:/new/prefix1/暂停.png);
write(widget.fd_cmd, "pause\n", strlen("pause\n"));
//设置按键图片
ui->Pause_PushButton->setStyleSheet("QPushButton{border-image: url(:/new/prefix1/picture/pause.png);border:none;color:rgb(255, 255, 255);}");
//暂停状态改变
widget.pause_flag = 0;
}
else
{
write(widget.fd_cmd, "pause\n", strlen("pause\n"));
ui->Pause_PushButton->setStyleSheet("QPushButton{border-image: url(:/new/prefix1/picture/play.png);border:none;color:rgb(255, 255, 255);}");
widget.pause_flag = 1;
}
}
void Widget::Next_slots()
{
if(widget.play_cur == widget.list.size() - 1)
{
//当前歌曲数,最后一首就归0,从头开始
widget.play_cur = 0;
}
else
{
//当前歌曲数,没到最后一首就++
widget.play_cur++;
}
char buf[256] = "";
sprintf(buf, "loadfile ./music/%s\n", widget.str_next[widget.play_cur]);
//切歌的同时,给【歌曲列表cpp】发送'歌曲名'的字符串信号 + 序号
//emit this->Send_Songlist_To_Song_listTable(widget.str_next[widget.play_cur]);
//切歌后,歌名显示在TextEdit文本表格中
//ui->Table_PushButton->
ui->Song_TextEdit->setText(QString(widget.str_next[widget.play_cur]));
write(widget.fd_cmd, buf, strlen(buf));
if(widget.pause_flag == 0)
{
//播放开始了,暂停状态变成播放状态 1
ui->Pause_PushButton->setStyleSheet("QPushButton{border-image: url(:/new/prefix1/picture/play.png);border:none;color:rgb(255, 255, 255);}");
widget.pause_flag = 1;
}
}
void Widget::Up_slots()
{
if(widget.play_cur == 0)
{
widget.play_cur = widget.list.size() -1;
}
else
{
widget.play_cur--;
}
char buf_up[128] = "";
sprintf(buf_up, "loadfile ./music/%s\n", widget.str_next[widget.play_cur]);
//切歌后,歌名显示在TextEdit文本表格中
ui->Song_TextEdit->setText(QString(widget.str_next[widget.play_cur]));
write(widget.fd_cmd, buf_up, strlen(buf_up));
if(widget.pause_flag == 0)
{
//播放开始了,暂停状态变成播放状态 1
ui->Pause_PushButton->setStyleSheet("QPushButton{border-image: url(:/new/prefix1/picture/play.png);border:none;color:rgb(255, 255, 255);}");
widget.pause_flag = 1;
}
}
void Widget::Show_Hide()
{
static char flag = 0;
if(0 == flag)
{
this->volume_a->hide();
flag = 1;
}
else
{
this->volume_a->show();
flag = 0;
}
}
void Widget::Show_hide_table()
{
static char flag = 0;
if(0 == flag)
{
this->tablewidget_a->hide();
//表格隐藏,修改一下控件 图片
ui->Table_PushButton->setStyleSheet("QPushButton{border-image: url(:/new/prefix1/picture/no_show.png);border:none;color:rgb(255, 255, 255);}");
flag = 1;
}
else
{
this->tablewidget_a->show();
ui->Table_PushButton->setStyleSheet("QPushButton{border-image: url(:/new/prefix1/picture/show.png);border:none;color:rgb(255, 255, 255);}");
flag = 0;
}
}
void Widget::Mule()
{
if(widget.mute_flag == 0)
{
write(widget.fd_cmd, "mute 1\n", strlen("mute 1\n"));
widget.mute_flag = 1;
}
else
{
write(widget.fd_cmd, "mute 0\n", strlen("mute 0\n"));
widget.mute_flag = 0;
}
if(widget.pause_flag == 1)
{
write(widget.fd_cmd, "pause\n", strlen("pause\n"));
}
}
void Widget::Show_hide_List_Song()
{
static char flag = 0;
if(0 == flag)
{
this->song_list->hide();
flag = 1;
}
else
{
this->song_list->show();
flag = 0;
}
}
void Widget::rec_volume1(int a)
{
widget.volume_cur = a;//直接拿信号发送过来的int值就行
//无需做大小判断,因为滑动条最大就是100,最小0,不会超过临界点
char str[128] = "";
sprintf(str, "volume %d 1\n", widget.volume_cur);
write(widget.fd_cmd, str, strlen(str));
if( widget.pause_flag == 1)
{
write(widget.fd_cmd,"pause\n",strlen("pause\n"));
}
}
void Widget::rec_table_row(int a)
{
widget.play_cur = a;
char buf_up[128] = "";
sprintf(buf_up, "loadfile ./music/%s\n", widget.str_next[widget.play_cur]);
//切歌后,歌名显示在TextEdit文本表格中
ui->Song_TextEdit->setText(QString(widget.str_next[widget.play_cur]));
write(widget.fd_cmd, buf_up, strlen(buf_up));
}
void Widget::rec_time_pos(char *str)//歌词时间信号
{
widget.buf_time = new char[128];
strcpy(widget.buf_time, str);
//把从线程接收的歌词时间信号显示到文本中
ui->Get_Time_Pos_TextEdit->setText(QString(widget.buf_time));
}
void Widget::rec_time_len(char *str)
{
char *buf_time2 = NULL;
buf_time2 = str;
ui->Get_Time_Length_TextEdit->setText(QString(buf_time2));
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。