嵌入式音乐播放器

通过madplay命令进行歌曲播放,功能有:
1、实现音乐的开始播放、结束播放、继续播放、暂停播放;
2、实现歌曲上一首、下一首切换;
3、实现歌曲播放模式的选择(顺序播放、随机播放、单曲循环);
4、实现音量调节(有上限和下限);

通过两个程序控制这个音乐播放器
客户端用来发一些请求就可以了。
服务器端:至少创建三个进程,父进程,子进程阻塞,等待回收孙进程,孙进程负责播放音乐。
父进程:用于监听按键和socket请求,与孙进程进行通信(通过共享内存),告诉孙进程需要播放的歌曲名,以及发送信号给孙进程。
子进程:一直不停的创建孙进程,然后wait等待孙进程结束,再创建新的孙进程。
孙进程:读共享内存中的歌曲名,execl执行madplay,接收父进程发来的信号(暂停,杀死等信号)。
共享内存:三个进程之间的通信用共享内存实现,歌曲列表通过系统调用的函数写道链表中,再fork父子孙三进程。
音量调节:https://blog.csdn.net/zqixiao_09/article/details/50859302

用到的系统调用函数:
pid_t fork(void);
pid_t waitpid(pid_t pid,int *status, int options);
int execl(const char *pathname, const char *arg, ..., (char *)NULL);
shmid = shmget(SHMKEY, SHMSIZE, IPC_CREAT | IPC_EXCL);   //创建共享内存
shmaddr = shmat(shmid, NULL, 0);    //映射到虚拟地址空间
int ioctl(int handle, int cmd,[int *argdx, int argcx]); //控制I/O设备
 

源码:

 

main.c

#include "server.h"

struct info* shareInfo;
int total = 0;
Node *first = NULL;
pid_t pid;
//extern OnMusic[20];

int main()
{
	int shmid;
	int ret;
	int status;
	
	//初始化链表
	ret = LinkInit(&first);
	if(ret == SUCCESS)
	{
		printf("init success \n");
	}
	else
	{
		printf("init failure \n");
	}
	
	//获取歌曲名,顺便把歌曲名插入到链表中
	GetName();
	printf("total is %d \n",total);

	//显示链表
	ret = LinkShow(first);
	if(ret == SUCCESS)
	{
		printf("show success \n");
	}
	else
	{
		printf("show failure \n");
	}

	//开辟共享内存
	shmid = shmget(SHMKEY, sizeof(struct info), IPC_CREAT | IPC_EXCL);
	if(-1 == shmid)
	{
		perror("shmget");
		exit(1);
	}

	//映射到进程的虚拟内存
	shareInfo = (struct info*)shmat(shmid, NULL, 0);
	if(NULL == shareInfo)
	{
		perror("shmat");
		exit(1);
	}

	//初始化共享内存的一些参数
	strcpy(shareInfo->order, "off");
	strcpy(shareInfo->mode, "order");
	shareInfo->num = 1;
	
	//创建进程 先创建父子两个进程,再在子进程里面再次调用fork就有了孙进程
	pid = fork();
	if(pid < 0)
	{
		perror("fork");
	}
	else if(pid == 0)
	{
		//子进程代码段
		printf("clid process id: %d \n", getpid());
		//不停的创建孙进程
		while(1)
		{
			pid = fork();
			if(pid < 0)
			{
				perror("fork");
			}
			else if(pid == 0)
			{
				//孙进程代码段
				printf("grandson process id: %d \n", getpid() );
				shareInfo->ppid = getpid();
				//音乐播放函数
				MusicPlay();
			}
			else
			{
				printf("clild process id: %d \n", getpid() );
				printf("child in wait \n");
				//等待孙进程结束
				waitpid(pid, &status, 0);
				//判断孙进程结束状态
				//正常退出状态
				if(WIFEXITED(status))
				{
					printf("child exit \n");
					//查看循环模式,如果是顺序播放就把下一首音乐的歌名存到共享内存中
					ret = CheckMode();
					if(ret == SUCCESS)
					{
						printf("on music is %s\n",shareInfo->name);
					}
					else
					{
						printf("on music is %s\n",shareInfo->name);
					}
				}
				//被信号杀死而退出,什么都不做,因为再父进程那接收到socket请求的同时以及把歌曲写到共享内存中了
				else if(WIFSIGNALED(status))
				{
					printf("siganl kill \n");
				}
				else
				{
					printf("......\n");
				}
		
			}
			
		}
	}
	else
	{
		//父进程代码段
		printf("parent process id: %d \n", getpid() );
		//父进程的主函数,一直阻塞接收来自客户端socket的请求
		Parent_Recv();
	}

}




server.c


#include "server.h"

int ret;
int sound = 1;  //音量参数
//int number = 1;
extern struct info* shareInfo; //共享内存地址
extern Node *first; //链表首地址
//char OnMusic[20] = "../music/111.mp3";
int devmask, stereodevs;  //调节音量的
const char *sound_device_names[] = SOUND_DEVICE_NAMES;  //存放可用的音频设备
int devfd; //打开的音频设备的文件描述符
extern int total; //总共的歌曲数目
extern pid; 

//音频设备的初始化
int DeviceInit(char *dev)
{
	int i;
	int status;
	devfd = open("/dev/mixer", O_RDONLY);
	if (devfd == -1) 
	{
		perror("unable to open /dev/mixer");
		return FAILURE;
	}

	status = ioctl(devfd, SOUND_MIXER_READ_DEVMASK, &devmask);
	if (status == -1)
	{
		perror("SOUND_MIXER_READ_DEVMASK ioctl failed");
		return FAILURE;
	}
	status = ioctl(devfd, SOUND_MIXER_READ_STEREODEVS, &stereodevs);
	if (status == -1)
	{
		perror("SOUND_MIXER_READ_STEREODEVS ioctl failed");
  		return FAILURE;
	}

	for (i = 0 ; i < SOUND_MIXER_NRDEVICES ; i++)
	{
		if (((1 << i) & devmask) && !strcmp(dev, sound_device_names[i]))
		{
			break;
		}
	}
	if(i == SOUND_MIXER_NRDEVICES) 
	{ 
		fprintf(stderr, "%s is not a valid mixer device\n", dev);
		return FAILURE;
	}

	return i;
}

//父进程的函数
void Parent_Recv()
{
	int fd, sockfd;
	int length = sizeof(client_addr);
	int ppid;
	int device;
	char choise[10];
	Info1 RecvInfo;
	char vol[10] = "vol";

	
	sockfd = SocketInit();

	fd = accept(sockfd, (struct sockaddr *)&client_addr, &length);	
	if(fd == -1)
	{
		perror("accept");
	}
	else
	{
		printf("client connect success \n");
		printf("port is %d fd is %d \n", client_addr.sin_port, fd);	
	}

	ret = MusicCopy(first, 1);
	if(ret == SUCCESS)
	{
		printf("init music copy success \n");
		printf("success on music is %s \n",shareInfo->name);
	}
	else
	{
		printf("init music copy fialure \n");
		printf("failure on music is %s \n",shareInfo->name);
	}

	device = DeviceInit(vol);
	if(device == FAILURE)
	{
		printf("device init failure \n");
	}
	else
	{
		printf("device init success \n");
	}

		
	while(1)
	{
		printf("in parent while\n");
		
		ret = recv(fd ,&RecvInfo, sizeof(RecvInfo), 0);
		if(ret == -1)
		{
			perror("recv");
		}
		if(strcmp(RecvInfo.flag, "on") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			strcpy(shareInfo->order, "on");
			printf("chareinfo order : %s \n", shareInfo->order);
			kill(shareInfo->ppid, SIGCONT);
		}
		else if(strcmp(RecvInfo.flag, "off") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			strcpy(shareInfo->order, "off");
			printf("chareinfo order : %s \n", shareInfo->order);
			kill(shareInfo->ppid, SIGKILL);
		}
		else if(strcmp(RecvInfo.flag, "stop") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			strcpy(shareInfo->order, "stop");
			printf("chareinfo order : %s \n", shareInfo->order);
			kill(shareInfo->ppid, SIGSTOP);
		}
		else if(strcmp(RecvInfo.flag, "next") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			kill(shareInfo->ppid, SIGKILL);
			strcpy(shareInfo->order, "next");
			printf("chareinfo order : %s \n", shareInfo->order);
			(shareInfo->num)++;
			if((shareInfo->num) > total)
			{
				shareInfo->num = 1;
			}
			printf("num is %d \n", shareInfo->num);
			ret = MusicCopy(first, shareInfo->num);
			if(ret == SUCCESS)
			{
				printf("music copy success \n");
				printf("success on music is %s \n",shareInfo->name);
			}
			else
			{
				printf("music copy fialure \n");
				printf(" fial on music is %s \n",shareInfo->name);
			}

		}
		else if(strcmp(RecvInfo.flag, "front") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			kill(shareInfo->ppid, SIGKILL);
			strcpy(shareInfo->order, "front");
			printf("chareinfo order : %s \n", shareInfo->order);
			(shareInfo->num)--;
			if((shareInfo->num) <= 0)
			{
				shareInfo->num = total;
			}
			printf("num is %d \n", shareInfo->num);
			ret = MusicCopy(first, shareInfo->num);
			if(ret == SUCCESS)
			{
				printf("music copy success \n");
				printf("success on music is %s \n",shareInfo->name);
			}
			else
			{
				printf("music copy fialure \n");
				printf("failure on music is %s \n",shareInfo->name);
			}

		}
		else if(strcmp(RecvInfo.flag, "poweron") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			sound++;
			printf("soud is %d \n", sound);
			ret = Sound(device, sound);
			if(ret == SUCCESS)
			{
				printf("soud is %d\n", sound);
			}
			else
			{
				printf("sound failure \n");
			}
		}
		else if(strcmp(RecvInfo.flag, "poweroff") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			sound--;
			printf("soud is %d \n", sound);
			ret = Sound(device, sound);
			if(ret == SUCCESS)
			{
				printf("soud is %d\n", sound);
			}
			else
			{
				printf("sound failure \n");
			}
		}
		else if(strcmp(RecvInfo.flag, "sigal") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			strcpy(shareInfo->mode, "sigal");
		}
		else if(strcmp(RecvInfo.flag, "order") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			strcpy(shareInfo->mode, "order");
		}
		else if(strcmp(RecvInfo.flag, "random") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			strcpy(shareInfo->mode, "random");
		}
		else if(strcmp(RecvInfo.flag, "quit") == 0) 
		{
			printf("recv flag : %s \n", RecvInfo.flag);
			kill(shareInfo->ppid, SIGKILL);
			kill(pid,SIGKILL);
			exit(1);
		}
		else
		{
			sleep(3);
			printf("wait client \n");
		}
	}

}


//调节音量 dev:设备名 num:音量参数
int Sound(int dev, int num)
{
	int left, right, level;
	int status;
	if(num > 5 || num < 0)
	{
		return FAILURE;
	}
	switch(num)
	{
		case 1:
		left = 50;
		right = 50;
		level = (right << 8) + left;
		status = ioctl(devfd, MIXER_WRITE(dev), &level);
		if (status == -1) 
		{
			perror("MIXER_WRITE ioctl failed");
			return FAILURE;
		}
		left = level & 0xff;
		right = (level & 0xff00) >> 8;
		fprintf(stderr, "%s gain set to %d%% / %d%%\n", dev, left, right);
			break;

		case 2:
		left = 60;
		right = 60;
		level = (right << 8) + left;
		status = ioctl(devfd, MIXER_WRITE(dev), &level);
		if (status == -1) 
		{
			perror("MIXER_WRITE ioctl failed");
			return FAILURE;
		}
		left = level & 0xff;
		right = (level & 0xff00) >> 8;
		fprintf(stderr, "%s gain set to %d%% / %d%%\n", dev, left, right);
			break;

		case 3:
		left = 70;
		right = 70;
		level = (right << 8) + left;
		status = ioctl(devfd, MIXER_WRITE(dev), &level);
		if (status == -1) 
		{
			perror("MIXER_WRITE ioctl failed");
			return FAILURE;
		}
		left = level & 0xff;
		right = (level & 0xff00) >> 8;
		fprintf(stderr, "%s gain set to %d%% / %d%%\n", dev, left, right);
			break;

		case 4:
		left = 80;
		right = 80;
		level = (right << 8) + left;
		status = ioctl(devfd, MIXER_WRITE(dev), &level);
		if (status == -1) 
		{
			perror("MIXER_WRITE ioctl failed");
			return FAILURE;
		}
		left = level & 0xff;
		right = (level & 0xff00) >> 8;
		fprintf(stderr, "%s gain set to %d%% / %d%%\n", dev, left, right);
			break;

		case 5:
		left = 90;
		right = 90;
		level = (right << 8) + left;
		status = ioctl(devfd, MIXER_WRITE(dev), &level);
		if (status == -1) 
		{
			perror("MIXER_WRITE ioctl failed");
			return FAILURE;
		}
		left = level & 0xff;
		right = (level & 0xff00) >> 8;
		fprintf(stderr, "%s gain set to %d%% / %d%%\n", dev, left, right);
			break;

		case 6:
		left = 100;
		right = 100;
		level = (right << 8) + left;
		status = ioctl(devfd, MIXER_WRITE(dev), &level);
		if (status == -1) 
		{
			perror("MIXER_WRITE ioctl failed");
			return FAILURE;
		}
		left = level & 0xff;
		right = (level & 0xff00) >> 8;
		fprintf(stderr, "%s gain set to %d%% / %d%%\n", dev, left, right);
			break;

	}
	return SUCCESS;
}


//把链表中的第num首歌写道共享内存中
int MusicCopy(Node *l, int num)
{
	int k = 1;
	printf("node is %s \n", l);
	if(NULL == l)
	{
		printf("l is null\n");
		return FAILURE;
	}

	Node *p = l;
	
	while(k <= num && p != NULL)
	{
		printf("k < num failure \n");
		p = p->next;
		k++;
	}

	if((k > (num + 1)) || p == NULL)
	{
		printf("k > num failure \n");
		return FAILURE;
	}

	strcpy(shareInfo->name, p->music_name);
	printf("share music name is:%s \n",shareInfo->name);

	return SUCCESS;
}



//socket初始化
int SocketInit()
{
	int sockfd;

	sockfd = socket(PF_INET, SOCK_STREAM, 0);
	if(-1 == sockfd)
	{
		perror("socket");
		//exit(1);
	}

	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = PF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr.s_addr = inet_addr("192.168.162.128");
	ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
	if(ret < 0)
	{
		perror("bind");
	//	exit(1);
	}

	ret = listen(sockfd, 5);
	if(ret < 0)
	{
		perror("listen");
	//	exit(1);
	}

	return sockfd;
}


//获取歌曲的名字
void GetName()
{
	char name[20];
	char flag[10];
    DIR *dirp;
    struct dirent *dp;
	const char *dirpath = "./music";

    dirp = opendir(dirpath);
    if (dirp  == NULL) 
	{
        printf("opendir failed on '%s'", dirpath);
        return;
    }

	while(1)
	{
        dp = readdir(dirp);
        if (dp == NULL)
		{
			break;
		}
		else if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
		{
			continue;          
		}
        else
		{
			strcpy(name, dirpath);
			strcat(name, "/");
			strcat(name, dp->d_name);
		}

		ret = LinkInsert(first, name);
		if(ret == SUCCESS)
		{
			total++;
			printf("insert success \n");
		}
		else
		{
			printf("insert failure \n");
		}
		printf("total is %d \n",total);
	}
}

//链表初始化
int LinkInit(Node **l)
{
	*l = (Node *)malloc(sizeof(Node));
	if(NULL == *l)
	{
		return FAILURE;
	}

	(*l)->next = NULL;
	
	return SUCCESS;
}


int LinkInsert(Node *l, char *name)
{
	if(l == NULL)
	{
		return FAILURE;
	}
	
	if(name == NULL)
	{
		return FAILURE;
	}

	Node *p = l;
	while(p->next != NULL)
	{
		p = p->next;
	}
	Node *n = (Node *)malloc(sizeof(Node));

	p->next = n;

	strcpy(n->music_name, name);
	
	n->next = NULL;

	return SUCCESS;
}


int LinkShow(Node *l)
{
	if(NULL == l)
	{
		return FAILURE;
	}
	
	Node *p = l;

	while(p->next != NULL)
	{
		p = p->next;
		printf("link info :%s \n", p->music_name);
	}

	return SUCCESS;
}
/*
char* GetLink(Node *l, int num)
{
	char buf[10] = "false";
	char *name;
	name = (char *)malloc(10);
	int k = 1;
	if(NULL == l)
	{
		return buf;
	}

	Node *p = l;
	
	while(k <= num && p != NULL)
	{
		p = p->next;
		k++;
	}

	if(k > num || p == NULL)
	{
		return buf;
	}

	strcpy(name, p->music_name);
	return name;
}
*/


//**********************************

//检查播放模式
int CheckMode()
{
	printf("this mode is %s \n", shareInfo->mode);
	if(strcmp(shareInfo->mode, "sigal") == 0)
	{
		ret = MusicCopy(first, shareInfo->num);
		if(ret == SUCCESS)
		{
			printf("music copy success \n");
			printf("success on music is %s \n",shareInfo->name);
		}
		else
		{
			printf("music copy fialure \n");
			printf("fail on music is %s \n",shareInfo->name);
		}
	}
	else if(strcmp(shareInfo->mode, "order") == 0)
	{
		(shareInfo->num)++;
		if((shareInfo->num) > total)
		{
			shareInfo->num = 1;
		}
		printf("set mode num is %d \n", shareInfo->num);
		ret = MusicCopy(first, shareInfo->num);
		if(ret == SUCCESS)
		{
			printf("music copy success \n");
			printf("success on music is %s \n",shareInfo->name);
		}
		else
		{
			printf("music copy fialure \n");
			printf("fail on music is %s \n",shareInfo->name);
		}
	}
	else if(strcmp(shareInfo->mode, "random") == 0)
	{
		shareInfo->num = rand()%total;
		ret = MusicCopy(first, shareInfo->num);
		if(ret == SUCCESS)
		{
			printf("music copy success \n");
			printf("success on music is %s \n",shareInfo->name);
		}
		else
		{
			printf("music copy fialure \n");
			printf("fail on music is %s \n",shareInfo->name);
		}
	}
	else
	{
		return FAILURE;
	}

	return SUCCESS;
}

void KillPro()
{
	printf("kill signal \n");
}

void StopPro()
{
//	printf("stop signal \n");
}

void ContPro()
{
//	printf("cont signal \n");
}

//孙进程的音乐播放函数
void MusicPlay()
{
	char opt[10] = " ";
	signal(SIGKILL, KillPro);
	signal(SIGSTOP, StopPro);
	signal(SIGCONT, ContPro);
/*	ret = CheckMode();
	if(ret == SUCCESS)
	{
		printf("on music is %s\n",shareInfo->name);
	}
	else
	{
		printf("on music is %s\n",shareInfo->name);
	}
*/
	while(1)
	{

		printf("madplay share info music is : %s \n", shareInfo->name);
		printf("madplay share info order is : %s \n", shareInfo->order);
		printf("madplay No%d \n",shareInfo->num);
		if(strcmp(shareInfo->order, "off") != 0)
		{
			execl("/usr/local/bin/madplay" , opt , shareInfo->name , NULL);
		}
		{
			sleep(3);
			printf("wait client \n");
		}
		
	}
}




















server.h


#ifndef MUSIC_H
#define MUSIC_H

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>



#define SHMKEY		1234
#define PORT 		7777
#define FAILURE		10000
#define SUCCESS		10001
#define TRUE		10002
#define FALSE		10003

struct sockaddr_in server_addr;
struct sockaddr_in client_addr;


struct info
{
	int ppid;
	int num;
	char name[20];
	char order[10];
	char mode[10];
};
typedef struct info Info;

struct info1
{
	char flag[10];
	char music[20];
};
typedef struct info1 Info1;

struct node
{
	char music_name[20];
	struct node *next;

};
typedef struct node Node;

int LinkShow(Node *l);
void Parent_Recv();
int SocketInit();
void Child_Pro();
void GetName();
int LinkInit(Node **l);
int LinkInsert(Node *l, char *name);
void MusicPlay();




#endif



 

  • 9
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值