概述
主要功能及实现:
1,播放,暂停及继续,上一页下一页,上一首下一首和退出
2,以简单的并发来实现顺序播放等功能
3,可根据不同格式导入歌曲
4,ANSI控制码实现简单的界面制作
缺点:
1,未处理歌名太长覆盖界面的问题
2,上一页,下一页只经过简单处理,不是很方便
以下只对几个关键代码单独展示,完整源代码见文章末尾:
一、带路径的歌曲名导入链表
利用glob函数解析目录下的音乐名字并导入链表
/* 歌曲路径和名字导入链表 */
static LList_st *loading()
{
int i, ret;
musicNode name;
LList_st *head = NULL;
head = llist_create(sizeof(name));
if (head == NULL)
{
fprintf(stderr,"llist_create() faildn");
exit(1);
}
glob(PATTERN,0,NULL,&buff);
for (i = 0; i < buff.gl_pathc; i++)
{
strncpy(name.musicName,buff.gl_pathv[i],NAMESIZE);
ret = llist_insert(head,&name,BEHIND);
if (ret < 0)
{
fprintf(stderr,"llist_insert() failn");
exit(1);
}
}
return head;
}
二、创建子进程
fork一个子进程,用子进程实现音乐播放,父进程每秒给alrm_handler发送一个信号,alrm_handler函数使用waitpid函数以非阻塞的方式来给子进程收尸,当子进程正常结束时,播放下一首。
/* 信号函数,接到信号时判断子进程是否正常结束,如果正常结束就播放下一首 */
static void alrm_handler(int s)
{
int status;
int ret;
ret = waitpid(pid,&status,WNOHANG);
if (ret != 0)
{
if (WIFEXITED(status))
{
cur = cur->next;
if (cur == &head->head)
cur = cur->next;
strncpy(musicBuff,getNameFromLink(cur->data),MUSICSIZE);
showList(cur,3);
fflush(NULL);
pid = fork();
createProgress(pid,musicBuff);
}
}
}
/* 创建子进程播放歌曲并将3个标准流置null,每秒向函数发送一个信号 */
void createProgress(pid_t pid,char *musicBuff)
{
int fd;
if (pid < 0)
{
perror("fork()");
exit(1);
}
if (pid == 0)
{
fd = open("/dev/null",O_RDWR);
if (fd < 0)
{
perror("open()");
exit(1);
}
dup2(fd,0);
dup2(fd,1);
dup2(fd,2);
if (fd > 2)
close(fd);
execlp("mplayer","mplayer",musicBuff,NULL);
perror("execlp()");
exit(1);
}
else
{
signal(SIGALRM,alrm_handler);
struct itimerval new = {{1,0},{1,0}};
setitimer(ITIMER_REAL,&new,NULL);
}
}
三、主要运行函数
/* 运行函数
* 关闭系统回显和getchar()以n结尾的设置
*
* flag播放状态 0:未播放 1:正在播放 2:暂停
* tmp检测第一次是否创建了子进程,防止意外杀死主进程 0:未创建子进程 1:已创建子进程
*
*/
void operationFunction()
{
struct termios new,old;
int flag = 0;
int tmp = 0;
char ch;
tcgetattr(0,&old);
tcgetattr(0,&new);
new.c_lflag = new.c_lflag & ~(ICANON | ECHO);
new.c_cc[VMIN] = 1;
new.c_cc[VTIME] = 0;
tcsetattr(0,TCSANOW,&new);
printf("