大家好,欢迎来到IT知识分享网。
一、基础原理
1、多进程系统编程
通过execlp(“mplayer”,“mplayer”,“-slave”,“-quiet”,“-idle”,“-input”,“file=./myfifo”,“-playlist”,“./list.txt”,NULL);
将造作可以通过有名管道./myfifo传给mplayer。
2、C语言对于文本的操作
对歌词文本进行解析。
二、myplayer的工作模式
1)键盘模式:
按下一个按键,程序开始工作
启动方法:
mplayer 歌曲路径名
启动mplayer后可以通过键盘按键来控制mplayer播放
基本控制键:
left or right 向后/向前搜索10秒
up or down 向后/向前搜索1分钟
pageup or pagedown 向后/向前搜索10分钟
p or SPACE 暂停播放(按任意键继续)
q or ESC 停止播放并退出
0 or 9 音量控制(音量循环模式)
2)slave模式:(——-用于项目)
启动方法:
./mplayer -idle -slave -quiet 歌曲路径名
-ac mad 这两个参数的意思是指定用mad解码器
-idle 播放文件至文件末尾后mplayer不退出
-slave 指定mplayer运行在slave模式下
-quiet 指定mplayer不向屏幕上,打印乱码信息
slave模式下的控制命令:
loadfile string //播放string指定的歌曲。
loadlist listname //播放列表文件
volume x 1 //设置音量,x为音量的大小。
mute 1/0 //静音开关。1:静音;0:取消静音。
pause //暂停/取消暂停。
seek value //快进或快退参数value指定的秒数
当value为正时,快进;当value为负时,快退。
get_percent_pos //获得文件的播放进度(百分比:0–100)。
get_time_pos //获得文件的当前位置,以秒为单位,精确到小数位1位。
get_file_name //获得文件的文件名。
get_time_length //获得文件的长度,以秒为单位。
get_meta_album //获得文件的 ‘专辑’ 的元数据。
get_meta_artist //获得文件的 ‘艺术家’ 的元数据。
get_meta_comment //获得文件的 ‘评论’ 的元数据。
get_meta_genre //获得文件的 ‘流派’ 的元数据。
get_meta_title //获得文件的 ‘标题’ 的元数据。
get_meta_year //获得文件的 ‘年份’ 的元数据。
三、对歌词的解析操作
在Qt中我们可以针对歌词创建一个类
lyc.h
#ifndef LYC_H #define LYC_H #include <iostream> # include <vector> #include <string.h> #include <stdlib.h> #include <QObject> class LrcContent{
public: int lrc_time; char lrc_content[256]; }; class Lyc {
public: Lyc(char * filename); ~Lyc(); void getSongMsg(); void getSongLrc(); public: //歌词文件名 char lyc_name[256]; //歌曲名 char song_name[256]; //歌曲作者 char song_atuther[256]; //专辑名 char song_album[256]; //所有的歌词内容 std::vector <LrcContent *> lrcVector; //单句歌词的操作句柄 LrcContent * lrc; //歌词文件指针 FILE * fd; int lrc_time; }; #endif // LYC_H
lyc.c
#include "lyc.h" #include <QDebug> char tempbuff[256]={
}; Lyc::Lyc(char * filename) {
//根据歌曲名找到歌词名 char * temp = strtok(filename,".");//因为在解析歌曲的同时就顺便将歌词的也解析了,所以传来的的是.mp3结尾的字符串 sprintf(lyc_name,"%s.lrc",temp);//字符串的拼接 //打开歌词文件 fd = fopen(lyc_name,"r+"); //未发现歌词文件 if(fd==NULL) {
perror("fopen:"); //歌曲名 //char song_name[256]; memset(song_name,0,sizeof(song_name)); strcpy(song_name,"无"); //歌曲作者 //har song_atuther[256]; memset(song_atuther,0,sizeof(song_atuther)); strcpy(song_atuther,"无"); //专辑名 //char song_album[256]; memset(song_album,0,sizeof(song_album)); strcpy(song_album,"无"); } else {
//获取歌曲信息 getSongMsg(); //获取歌曲信息 getSongLrc(); } } Lyc::~Lyc() {
fclose(fd); } //解析歌曲信息 char * DealMsgString(char *buff) {
memset(tempbuff,0,sizeof(tempbuff)); buff+=4; int i=0; while(*buff !=']') {
tempbuff[i]=*buff; i++; buff++; } return tempbuff; } void Lyc::getSongMsg() {
char buff[256]={
}; for(int i=0;i<3;i++) {
//如果前三行没有内容 if(fgets(buff,256,fd)==NULL) {
//歌曲名 //char song_name[256]; memset(song_name,0,sizeof(song_name)); strcpy(song_name,"无"); //歌曲作者 //char song_atuther[256]; memset(song_atuther,0,sizeof(song_atuther)); strcpy(song_atuther,"无"); //专辑名 //char song_album[256]; memset(song_album,0,sizeof(song_album)); strcpy(song_album,"无"); } if(strncmp(buff,"[ti:",4)==0) {
char *temp= DealMsgString(buff); memset(song_name,0,sizeof(song_name)); strcpy(song_name,temp); } else if(strncmp(buff,"[ar:",4)==0) {
char *temp= DealMsgString(buff); memset(song_atuther,0,sizeof(song_atuther)); strcpy(song_atuther,temp); } else if(strncmp(buff,"[al:",4)==0) {
char *temp= DealMsgString(buff); memset(song_album,0,sizeof(song_album)); strcpy(song_album,temp); } else {
//歌曲名 memset(song_name,0,sizeof(song_name)); strcpy(song_name,"无"); //歌曲作者 memset(song_atuther,0,sizeof(song_atuther)); strcpy(song_atuther,"无"); //专辑名 memset(song_album,0,sizeof(song_album)); strcpy(song_album,"无"); } } } void Lyc::getSongLrc() {
this->lrcVector.clear();; char text[256]={
}; int min=0; int sec=0; while(fgets(text,256,fd) != NULL) {
char * temp = text; int lrctime; //非空行 if(text[0] == '[') {
if(text[1]>='0'||text[1]<='9') {
//解析时间 sscanf(text,"[%d:%d",&min,&sec); lrctime = min*60+sec; temp+=10; } //判断是否为停顿 if(*temp=='\0'||*temp=='\n') {
continue; } lrc = new LrcContent; memset(lrc->lrc_content,0,sizeof(lrc->lrc_content)); strcpy(lrc->lrc_content,temp); lrc->lrc_time=lrctime; lrcVector.push_back(lrc); } } }
四、对mplayer的命令操作
//创建歌单 void createPlaylist(const char* music_folder,const char* playlist_file) {
//read directory(get song name) DIR* dir; struct dirent* entry; FILE* file; dir=opendir(music_folder); if(dir == NULL) {
printf("Open dir tmpdir fail\n"); return; } file = fopen(playlist_file,"w"); if(file==NULL) {
printf("无法创建歌单文件\n"); closedir(dir); return; } while ((entry = readdir(dir)) != NULL) {
// 如果是以.mp3或.wav结尾的文件,则将其写入歌单文件 if (strcasecmp(entry->d_name + strlen(entry->d_name) - 4, ".mp3") == 0 || strcasecmp(entry->d_name + strlen(entry->d_name) - 4, ".wav") == 0) {
fprintf(file, "%s/%s\n", music_folder, entry->d_name); strcpy(song_lry[j++],entry->d_name); qDebug()<<entry->d_name; } } fclose(file); closedir(dir); printf("歌单创建成功!\n"); return ; }
//判断有名管道是否打开 if(fd < 0)//全局变量(已经定义好的有名管道) {
perror("open:"); } //create pipe pipe(pipe_fd); //create parent child process pid = vfork(); if(pid == 0)//子进程 {
dup2(pipe_fd[1],1);//输出重定向,可以读到输出的内容 execlp("mplayer","mplayer","-slave","-quiet","-idle","-input","file=./myfifo","-playlist","./list.txt",NULL); } else if(pid > 0) {
sleep(1); char buff1[20]; char buff[1024];//清除管道中的数据 read(pipe_fd[0],buff,sizeof(buff));//清除管道中的数据 ui->horizontalSlider_2->setMaximum(lyc->lrcVector.back()->lrc_time);//设置歌曲进度条的最大值 ui->horizontalSlider_2->setMinimum(0);//设置歌曲进度条的最小值 //歌曲进度条的时间 int min = 0; int sec = 0; min = song_time/60; sec = song_time%60; char mytime[6]={
}; sprintf(mytime,"%02d:%02d",min,sec); this->ui->label_3->setText(mytime);//进度条右边的歌曲时间 int timelast = lyc->lrcVector.back()->lrc_time; min = timelast/60; sec = timelast%60; mytime[6]={
}; sprintf(mytime,"%02d:%02d",min,sec); this->ui->label_4->setText(mytime);//进度条左边的歌曲总时间 //获取歌曲音量 write(fd,"get_property volume\n",strlen("get_property volume\n"));//向有名管道写时间 memset(buff1,0,sizeof(buff1)); read(pipe_fd[0],buff1,sizeof(buff1)); int value; sscanf(buff1,"ANS_volume=%d",&value); ui->horizontalSlider->setMaximum(100); ui->horizontalSlider->setMinimum(0); ui->horizontalSlider->setValue(value); volume=value; //时间函数,让歌曲时间每秒加一 timer = new QTimer(this); connect(timer,SIGNAL(timeout()),this,SLOT(on_horizontalSlider_2_add())); //connect(timer,SIGNAL(timeout()),this,SLOT(timeUpdate()));//连接信号槽 sleep(3); timer->start(1000);
2、上一首和下一首播放
ui->listWidget->clear();//清空屏幕的歌词 timer->stop();//歌词时间暂停 song_time=0;//歌曲时间,为全局变量 vecterpos=0;//全局变量 delete lyc; char buff2[100]; i--; if(i<0)//第一首不能再加 {
i=0; } sprintf(buff2,"%s%s",song_lry_location,song_lry[i]); lyc = new Lyc(buff2); ui->label_2->setText(lyc->song_name);//歌曲名 ui->label_5->setText(lyc->song_atuther);//歌手 ui->label_6->setText(lyc->song_album);//专辑名 write(fd,"pt_step -1\n",strlen("pt_step -1\n")); ui->horizontalSlider_2->setMaximum(lyc->lrcVector.back()->lrc_time);//设置歌曲进度条的最大值 ui->horizontalSlider_2->setMinimum(0);//设置歌曲进度条的最小值 //歌曲进度条的时间 int min = 0; int sec = 0; min = song_time/60; sec = song_time%60; char mytime[6]={
}; sprintf(mytime,"%02d:%02d",min,sec); this->ui->label_3->setText(mytime); int timelast = lyc->lrcVector.back()->lrc_time; min = timelast/60; sec = timelast%60; mytime[6]={
}; sprintf(mytime,"%02d:%02d",min,sec); this->ui->label_4->setText(mytime); timer->start(1000);
下一首
ui->listWidget->clear(); timer->stop(); song_time=0; vecterpos=0; delete lyc; char buff2[100]; i++; if(i>=j) {
i=j-1; } sprintf(buff2,"%s%s",song_lry_location,song_lry[i]); lyc = new Lyc(buff2); ui->label_2->setText(lyc->song_name);//歌曲名 ui->label_5->setText(lyc->song_atuther);//歌手 ui->label_6->setText(lyc->song_album);//专辑名 write(fd,"pt_step 1\n",strlen("pt_step 1\n")); ui->horizontalSlider_2->setMaximum(lyc->lrcVector.back()->lrc_time);//设置歌曲进度条的最大值 ui->horizontalSlider_2->setMinimum(0);//设置歌曲进度条的最小值 //歌曲进度条的时间 int min = 0; int sec = 0; min = song_time/60; sec = song_time%60; char mytime[6]={
}; sprintf(mytime,"%02d:%02d",min,sec); this->ui->label_3->setText(mytime); int timelast = lyc->lrcVector.back()->lrc_time; min = timelast/60; sec = timelast%60; mytime[6]={
}; sprintf(mytime,"%02d:%02d",min,sec); this->ui->label_4->setText(mytime); timer->start(1000);
3、计时器
song_time++;//每秒++ int min = 0; int sec = 0; min = song_time/60; sec = song_time%60; char mytime[6]={
}; sprintf(mytime,"%02d:%02d",min,sec); this->ui->label_3->setText(mytime); ui->horizontalSlider_2->setValue(song_time); //qDebug()<<song_time; //qDebug()<<lyc->lrcVector[vecterpos]->lrc_time; if(song_time>=lyc->lrcVector[vecterpos]->lrc_time) {
ui->listWidget->clear(); for(int j=vecterpos;j<vecterpos+5;j++) {
this->item = new QListWidgetItem(lyc->lrcVector[j]->lrc_content); ui->listWidget->addItem(this->item); this->item->setTextColor(Qt::black); this->item->setFont(QFont("宋体",16)); } vecterpos++; }
4、歌曲进度条的拖动
timer->stop(); int position = ui->horizontalSlider_2->value(); ui->horizontalSlider_2->setValue(position); int diff=position - song_time; song_time=position; char str[20]; char str1[20]="seek "; sprintf(str,"%d\n",diff); strcat(str1,str); write(fd,str1,strlen(str1)); //歌词播放的回退或者前进 if(diff>0) {
while(song_time>lyc->lrcVector[vecterpos]->lrc_time) {
vecterpos++; } } else if(diff<0) {
while(song_time<lyc->lrcVector[vecterpos]->lrc_time) {
vecterpos--; } } timer->start(1000);
5、音量的大小
int position = ui->horizontalSlider->value(); ui->horizontalSlider->setValue(position); volume=position; char str[20]; char str1[20]="volume "; sprintf(str,"%d 1\n",volume); strcat(str1,str); write(fd,str1,strlen(str1));//主要是通过命令实现的
这些就是这个音乐播放器的大的框架,现在已经把骨架搭好了,还需要自己去填充其他的内容。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/145378.html