MP3播放器

Linux系统学习项目之MP3播放器


做一个MP3播放器的项目,播放命令为madplay.

/*************************************************************************
  > 文件路径: main.c
  > 作者: Moliam
  > 邮箱: 2515826079@qq.com 
  > 文件创建时间: 2019年03月08日 星期五 09时41分20秒
 ************************************************************************/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <signal.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/ptrace.h>

char *  song[100];//指向歌名的指针数组
char song_buf[100];//存放将要播放的歌的歌名
char cmd_buf[100];//存放命令
int name[100];//存放播放过的歌曲名字,最多保存100首
int all = 0;//歌曲总数
int i;//
int com=0;//当前歌
int flag=1;//默认列表播放    0为随机播放  1为列表播放  2为随机播放
int n;
int a;

void findmusic(void);//查找mp3文件
void getname(void);//获取mp3文件名字
void play_singlecircle_music1(int);//单曲循环
void play_listcircle_music1(int);//列表循环
void play_random_music(int);//随机播放
void last_music(int a);//上一首歌
void next_music(int a);//下一首歌
void text(void);//测试是否正在播放歌曲
void savename(void);//保存歌曲
void Name(void);//播放歌曲超过100时丢掉保存的第一首歌
int m=48;//0的ASCII值为48

void savename(void)
{
	if(n<100){name[n++]=com;//将当前歌存放在数组里
	}
	else
	Name();//当超过100首歌时,丢弃掉数组里存放的第一首歌
}
void fun(int a)//父子进程成功通讯测试函数
{
	printf("父子进程通讯成功!\n");
}
/*由于madplay不是由该进程产生的子进程,所以获取当前有没有播放歌曲,如果有的话也不能用waitpid来等待,所以查找了好多资料
然后找到了可以用ps -ef | grep -w madplay | grep -v grep | wc -l终端命令来测试是否madplay正在运行,如果运行,执行结果为1,否则为0*/
void text(void)
{
	FILE *fp;
	FILE *fp2;
	char buf[15] ={"it's finish!"};//在这里随便定义了一个buf,反正最后只是用来承接终端命令返回值,并且只有第0位用的到
	memset(buf,'\0',10);
	fp = popen("ps -ef | grep -w madplay |grep -v grep |wc -l ","r");//使用FIFO管道执行外部程序,获得的返回值用fread读
	fread(buf,1,1,fp);
	pclose(fp);
	m=(int)buf[0];//这里获得的0和1为ASCII值
}
int main(void)
{
	int ch;
	int flag=0;
	getname();//获取当前目录下的mp3文件
	pid_t pid=fork();
	if(pid<0)
	{
		perror("fork");
		return -1;
	}
	else if(pid==0)
	{
		signal(20,fun);//测试
		signal(4,play_singlecircle_music1);//使用信号4当作单曲循环信号,觉得可以用,但是会不会影响性能并不清楚,下同
		signal(5,play_listcircle_music1);
		signal(6,play_random_music);
		signal(7,last_music);
		signal(8,next_music);
		while(1);//不让子进程直接执行完毕,等待父进程的信号
	}
	else{
	printf("共找到以上本地MP3文件:\n");
	sleep(2);
	kill(pid,20);//测试父子进程通讯
y:	
	printf("*********************************\n");//菜单
	printf("            按1暂停播放            \n");
	printf("            按2继续播放            \n");
	printf("            按3单曲循环            \n");
	printf("            按4列表循环            \n");
	printf("            按5随机播放            \n");
	printf("            按6上一首歌            \n");
	printf("            按7下一首歌            \n");
	printf("            按0退出系统            \n");
	printf("*********************************\n");
	while(1)
	{
z:		printf("请输入你需要进行的操作\n");
		scanf("%d",&ch);
		if(ch<0&&ch>7)
		{printf("输入有误!\n");goto z;}
		switch (ch)
		{
			case 1:printf("暂停\n");
				sprintf(cmd_buf,"killall -SIGSTOP madplay");system(cmd_buf);break;//暂停,给madplay发送暂停信号
			case 2:printf("播放\n");
				sprintf(cmd_buf,"killall -SIGCONT madplay");system(cmd_buf);break;//播放
			case 3:printf("单曲循环\n");
				kill(pid,4);break;//单曲循环,给子进程发送信号,进入相应的服务函数
			case 4:printf("列表循环\n");
				kill(pid,5);break;//列表循环
			case 5:printf("随机播放\n");
				kill(pid,6);break;//随机播放
			case 6:
				kill(pid,7);break;//上一首
			case 7:
				kill(pid,8);break;//下一首
			case 0:
				kill(pid,9);//关闭全部进程
				sprintf(song_buf,"killall -9 madplay");
				system(song_buf);
				raise(9);
				break;
			default :break;
		}
		goto y;
	}}
	wait(NULL);
	return 0;
}
void next_music(int a)
{
	sprintf(song_buf,"killall -9 madplay");
	system(song_buf);
	switch(flag)
	{
		case 0:
			savename();
			text();
			if(m!=48)//如果当前正在播放歌曲,则杀死madplay进程
			{sprintf(song_buf,"killall -9 madplay");
			system(song_buf);}
			printf("n = %d\n",n);
			sprintf(song_buf,"madplay -o wav:- /root/System_project/mp3/ %s 2> /dev/null | aplay 2>/dev/null &",song[com]);
			system(song_buf);
			raise(4);
			break;
		case 1:
			savename();
			printf("n = %d\n",n);
			if(com==(all-1))
				com=-1;
			com++;
			text();
			if(m!=48)
			{sprintf(song_buf,"killall -9 madplay");
			system(song_buf);}
			sprintf(song_buf,"madplay -o wav:- /root/System_project/mp3/ %s 2> /dev/null | aplay 2>/dev/null &",song[com]);
			system(song_buf);
			raise(5);
			break;
		case 2:
			savename();
			printf("n = %d\n",n);
			srand((int)time(NULL));
			int r=rand()%(all);
			com=r;
			text();
			if(m!=48)
			{sprintf(song_buf,"killall -9 madplay");
			system(song_buf);}
			sprintf(song_buf,"madplay -o wav:- /root/System_project/mp3/ %s 2> /dev/null | aplay 2>/dev/null &",song[com]);
			system(song_buf);
			raise(6);
			break;
	}
	sleep(1);
}
void last_music(int a)
{
	sprintf(song_buf,"killall -9 madplay");
	system(song_buf);
	if(n<0)
	{
		printf("当前已是第一首\n");
		n=0;
	}
	com=name[n-1];
	n--;
	//printf("n = %d\n",n);
	//printf("com = %d\n",com);
	sprintf(song_buf,"madplay -o wav:- /root/System_project/mp3/ %s 2> /dev/null | aplay 2>/dev/null &",song[com]);
	system(song_buf);
	sleep(1);
	if(flag==0)
	raise(4);
	else if(flag==1)
	raise(5);
	else if(flag==2)
	raise(6);
}
void play_random_music(int a)
{
	int r;
	flag=2;
	while(1)
	{
text:		
		text();
		if(m!=48)//还是madplay进程的问题,每延时3s查询一次是不是正在播放歌曲,总觉得很鸡肋,却又没找到其他的解决办法
		{sleep(3);
		goto text;}
repeat:
		srand((int)time(NULL));
		r=rand()%(all);
		if (r>all-1)
		{
			goto repeat;//产生随机数如果大于i,重新获取,一般是不会的
		}
		savename();
		//printf("n = %d\n",n);
		com=r;
		sprintf(song_buf,"madplay -o wav:- /root/System_project/mp3/ %s 2> /dev/null | aplay 2>/dev/null &",song[com]);
		system(song_buf);
	}
}
void play_listcircle_music1(int a)
{
	flag=1;
	while(1)
	{
text:		text();
		if(m!=48)
		{sleep(3);
		goto text;}
		savename();
		//printf("n = %d\n",n);
		com++;
		if(com>all-1)
		{com=0;}
		sprintf(song_buf,"madplay -o wav:- /root/System_project/mp3/ %s 2> /dev/null | aplay 2>/dev/null &",song[com]);
		system(song_buf);
	}
}
void play_singlecircle_music1(int a)
{
	flag=0;
	while(1)
	{
text:		
		text();
		if(m!=48)
		{sleep(3);
		goto text;}
		savename();
		//printf("n = %d\n",n);
		sprintf(song_buf,"madplay -o wav:- /root/System_project/mp3/ %s 2> /dev/null | aplay 2>/dev/null &",song[com]);
		system(song_buf);
	}
}

void Name(void)
{
	for(int j=0;j<99;j++)
	{
		name[j]=name[j+1];
	}
	n--;
}

/*
这里使用脚本查询,但是小白并没有用到,因为这样查询后不能存放歌曲名,或者可以我不知道,所以查询采用的是getname函数
脚本文件内容如下
find *.mp3
*/
void findmusic(void)
{
	system("./find.sh");
}

void getname(void)
{
	int len;
	static char *buf;
	DIR *dir;
	all=0;
	struct dirent *ptr;
	dir = opendir(".");//在当前目录下查找MP3歌曲,如果还有其他路径,就把这里改为其他路径
	while((ptr = readdir(dir))!=NULL)
	{
		len=strlen(ptr->d_name);
		len=len-4;
		if((strcmp(ptr->d_name+len,".mp3"))==0)//后四位进行比较,是否为“.mp3”
		{
			buf=(char*)malloc(100);//不开辟空间会导致数组里存放的歌曲全为最后一首歌
			memset(buf,0,sizeof(buf));
			strcat(buf,ptr->d_name);
			song[all++]=buf;	
		}
	}
	for(int j=0;j<all;j++)
	{
		printf("%s\n",song[j]);
	}
}

  • 7
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值