/*
项目需求:
1.实现音乐基本功能:播放,暂停及继续,下一首,上一首,退出。
2.自动生成歌曲列表文件。(重定向)
3. 实现单曲循环。
思路:
1.由于学了fork(),exec函数,想到在进程里创建一个子进程来播放音乐。
2.暂停及继续,我们可以使用信号来控制。
3.上一首和下一首切换,用双链表是最好的选择,简单方便。
4.注意:一定要关闭当前的音乐播放,再放下一首,要不然会出现设备繁忙。
*/
#include "doublelist.h"
int main()
{
//同一个标准输入 控制输入
int choose=0;
pid_t pid;
int flag=0; //0 停止 1 播放 2 暂停
char pathname[]="../music/";
char buf[50]={0};
autofile();
pstu head,pstr,p;
head=LoadInfo();
head->prev;
pstr=head->next;
pstr->prev=head;
while(1)
{
system("clear");
print_Node(head);
printf("\t\t\t\t\t\t ***************************************\n");
printf("\t\t\t\t\t\t\t 音乐播放器 \n");
printf("\t\t\t\t\t\t ***************************************\n");
printf("\t\t\t\t\t\t\t 主界面\n\n");
printf("\t\t\t\t\t\t\t 1 播放 2 暂停/继续\n\n");
printf("\t\t\t\t\t\t\t 3 下一首 4 上一首\n\n");
printf("\t\t\t\t\t\t\t 5 退出\n");
printf("\t\t\t\t\t\t ***************************************\n");
scanf("%d",&choose);
switch(choose)
{
case 1:
{
//播放
flag=1;
pid =fork();
if(pid==0)
{
close(0);
sprintf(buf,"../music/%s",pstr->name);
execlp("madplay","madplay",buf,"-r",NULL);
perror("execlp");
exit(0);
}
break;
}
case 2:
if(flag==1)
{
kill(pid,19);
flag=2;
}
else if(flag==2)
{
kill(pid,18);
flag=1;
}
break;
case 3:
{
kill(pid,9);
p=Find_DownNode(pstr);
if(p==NULL)
{
p=head->next;
}
pstr=p;
flag=1;
pid =fork();
if(pid==0)
{
close(0); //关闭标准输入
sprintf(buf,"../music/%s",p->name);
execlp("madplay","madplay",buf,NULL);
perror("execlp");
exit(0);
}
break;
}
case 4:
{
kill(pid,9);
p=Find_UpNode(pstr);
if(p==head)
{
p=head->next;
}
pstr=p;
flag=1;
pid =fork();
if(pid==0)
{
close(0); //关闭标准输入
sprintf(buf,"../music/%s",p->name);
execlp("madplay","madplay",buf,NULL);
perror("execlp");
exit(0);
}
break;
}
case 5:
kill(pid,9);
exit(0);
default:
printf("输入错误\n");
}
sleep(1);
}
return 0;
}
#include "doublelist.h"
#include "lib.h"
typedef struct node
{
char name[20];
struct node *prev;
struct node *next;
}stu,*pstu;
#define SIZE sizeof(stu)
pstu LoadInfo();
void print_Node(pstu head);
pstu Find_DownNode(pstu head);
pstu Find_UpNode(pstu head);
void autofile();
#include "doublelist.h"
//自动生成音乐目录集
void autofile()
{
system("ls ../music > ../songname");
}
//加载数据
pstu LoadInfo()
{
char name[20];
char filename[]="../songname";
FILE *fp;
pstu head,ptr,tmp;
//创建头文件
head=calloc(1,SIZE);
ptr=head;
ptr->next=NULL;
if((fp=fopen(filename,"r"))==NULL)
{
perror("fopen");
exit(0);
}
tmp=(pstu)calloc(1,SIZE);
while(fscanf(fp,"%s\n",name)!=EOF)
{
strcpy(tmp->name, name);
ptr->next=tmp;
tmp->prev=ptr;
ptr = tmp;
tmp = (pstu)calloc(1,SIZE);
}
free(tmp);
fclose(fp); //关闭文件,已得到保存data信息的链表head
return head;
}
pstu Find_DownNode(pstu head)
{
pstu p;
p=head->next;
return p;
}
pstu Find_UpNode(pstu head)
{
pstu p;
p=head->prev;
return p;
}
void print_Node(pstu head)
{
pstu ptr=head;
pstu p=ptr->next;
printf("\t\t\t\t\t\t\t\t 歌 单\n\n");
printf("\t\t\t\t\t\t\t\t============== \n");
while(p!=NULL)
{
printf("\t\t\t\t\t\t\t\t %s\n",p->name);
p=p->next;
}
printf("\t\t\t\t\t\t\t\t============== \n\n");
}
截图:
项目总结:
做过一个单链表的学生管理系统和双链表的音乐播放器,有个小技巧想和大家分享一下,就是在创建头节点的时候,我一般倾向于创建一个空的头节点,后续添加的节点直接放在头的后面。这样做的好处是省了对头节点的判断,思路简单。
补充:
lib.h头文件里的内容
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include