mp3播放器

#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>

#define MAX 40
#define WORD 40

typedef struct list_node{
    char s_name[WORD];
    struct list_node *next;
    struct list_node *prev;
}node,*pnode;

struct share{
	long id_tmp;
	char name_tmp[WORD];
};

 /* 创建双向循环链表,将歌曲添加入链表中 */ 
pnode create_list(char para[][40],int n)                                                      
{
	int i;
	pnode head = NULL;
	pnode new = NULL;             
	pnode tmp = NULL;
    
    head = (pnode)malloc(sizeof(node));                                           
    if(head == NULL){
        perror("malloc");                                                         
        exit(EXIT_FAILURE);                                                                
    }                                                                             	
	head->next = NULL;                                                            
        head->prev = NULL;                                                           
	strcpy(head->s_name,para[0]);
	
	tmp = head;
	for(i=1; i<n; i++){
		new = (pnode)malloc(sizeof(node));
		if(new == NULL){
			perror("malloc");
			exit(EXIT_FAILURE);  
		}
		strcpy(new->s_name,para[i]);
		tmp->next = new;
		new->prev = tmp;
		new->next = NULL;
		tmp = new;
	}
	head->prev = tmp;
	tmp->next = head;
    return head;                                                                  
}


/* 遍历链表,返回当前播放歌曲所对应的节点 */
pnode search_list(pnode head,char para[])
{
	pnode tmp = NULL;
	tmp = head->next;
	
	if(strcmp(head->s_name,para) == 0){
		return head;
	}
	else{	
		while(tmp != head)
		{	
			if (strcmp(tmp->s_name, para) == 0){
				return tmp; 		
			}
			else {
				tmp= tmp->next;
			}
		}
	}
	return NULL;
}

/* 打印双向链表每个节点的值 */
void print_list(pnode head)
{
	pnode tmp = head->next;
	printf("\nThe song of Current directory:\n\n");
	printf("head:%s\n",head->s_name);
	while(tmp != head){
		printf("node:%s\n",tmp->s_name);
		tmp = tmp->next;
	}
}


void play(int mem_id,pnode para)
{
	pnode node_tmp;
	void *shmadd=(void *)0;
	struct share *share_para;
	
	node_tmp = para->prev;
	while(1)
	{
		node_tmp = node_tmp->next;
		if(fork() == 0){
			/* 映射共享内存 */
			if ((shmadd = shmat(mem_id, (void *)0, 0)) == NULL){
				if (shmctl(mem_id, IPC_RMID, NULL) == -1)
					perror("Failed to  remove memory segment");
				exit(EXIT_FAILURE);
			}	
			/* 将ID和歌曲名信息存入共享内存 */
			share_para = (struct share *)shmadd;
			strcpy(share_para->name_tmp, node_tmp->s_name);
			share_para->id_tmp = getpid();
			
			if(execlp("madplay","madplay",node_tmp->s_name,NULL)<0)
				perror("execlp ");
		}
		else
			wait(NULL);
	}
	
}



int main(int argc, char *argv[])
{
	int buttons_fd;
  	char cwd_buf[80];	
  	DIR *dir;
	struct dirent *ptr;
        char *p=NULL;
	int i=0;
	char name[MAX][WORD];
  	
  	pnode head;
	
	fd_set rds;
	int ret;	
	int key_value[6];
	int key_tmp;

	int key_count=1;
	int id_test;
	char next_name[WORD];
	char prev_name[WORD];



	struct share *share_tmp;

	int memory_id;
	pnode node_tmp;
	void *shmadd=(void *)0;
		
	buttons_fd = open("/dev/button", 0);
	if (buttons_fd < 0) {
		perror("open device buttons");
		exit(EXIT_FAILURE);  
	}
	
	/* 获取当前目录 */
  	getcwd(cwd_buf,sizeof(cwd_buf));
  	
  	if((dir = opendir(cwd_buf)) == NULL){
  		perror("opendir");
  		exit(EXIT_FAILURE);  
  	}
	
	/* 遍历整个目录 */
  	while((ptr = readdir(dir)) != NULL){
	       /*查找后缀名为mp3的普通文件  */
		if((ptr->d_type == 8) && (p=strstr(ptr->d_name,".mp3")) != NULL)
			{      
				strcpy(name[i++],ptr->d_name);
			}
	}
	
	head = create_list(name,i);	
	print_list(head);

	
	/* 父进程中使用共享内存,获取孙子进程中记录的进程ID和当前歌曲名 */
	if ((memory_id = shmget(IPC_PRIVATE, sizeof(struct share), IPC_CREAT|0666)) == -1){
		perror("Failed to create shared memory segment");
		exit(EXIT_FAILURE);
	}
	
	if ((shmadd = shmat(memory_id, (void *)0, 0)) == NULL){
		perror("shmat");
		if (shmctl(memory_id, IPC_RMID, NULL) == -1)
			perror("Failed to  remove memory segment");
		exit(EXIT_FAILURE);
	}
	
	share_tmp = (struct share *)shmadd;

	
	printf("\nOperations Description \n");
	printf("K1 --------start play\n");
	printf("K2 --------pause\n");
	printf("K3 --------continue to play\n");
	printf("K4 --------previous one\n");
	printf("K5 --------next one\n");

	
	for (;;) {
		
		FD_ZERO(&rds);
		FD_SET(buttons_fd, &rds);

		/* 监测按键的变化 */
		ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);
		if (ret < 0) {
			perror("select");
			exit(EXIT_FAILURE);  
		}
		if (ret == 0) {
			printf("Timeout.\n");
		}
		else if (FD_ISSET(buttons_fd, &rds)) {
			
			/* 读取按键的值到数组中 */
			ret = read(buttons_fd, &key_value, sizeof(key_value));
			if(ret != sizeof(key_value)){
				if(errno != EAGAIN){
					printf("read button device failed!\n");
				}
				continue;
			}
			else{			
				for(i=0; i<6; i++){
					if(key_value[i] == 0){
						/* 记录按键值 */
						key_tmp = i+1;
					}
				}
			}
		}
					

		/*--------------------------------------start------------------------------------*/		
		if(key_tmp == 1){
			printf("\nk1 down start\n");
			if(key_count){	
				key_count = 0;
				id_test = fork();
				
				//该子进程控制循环播放,当一首歌曲播放完成后,创建一个新的孙子进程来播放 
				if(id_test == 0){
					play(memory_id,head);
				}
				else if(id_test >0){					
				}
			}
			else{
				;
			}
		}
       /*--------------------------------------------------------------------------------*/		

		if(key_tmp == 2){   //pause
			printf("\nk2 down pause\n");
			kill(share_tmp->id_tmp, SIGSTOP);
		}
		
		if(key_tmp == 3){   //continue
			printf("\nk3 down continue\n");
			kill(share_tmp->id_tmp,SIGCONT);		
		}

       /*--------------------------------------next------------------------------------*/		
		if(key_tmp == 4){   //next	
			printf("\nk4 down next\n");

			/* kill 原来的子进程和孙子进程 */
			kill(share_tmp->id_tmp,SIGKILL);
			kill(id_test,SIGKILL);
			
			strcpy(next_name, share_tmp->name_tmp);

			/* 获取原孙子进程歌曲名在链表中的位置 */
			node_tmp = search_list(head,next_name);
			if(node_tmp == NULL){
				printf("only one song \n");
			}	
			else{
				/* 节点后移一位 */
				node_tmp = node_tmp->next;
			}
			id_test = fork();
			
			if(id_test == 0){
				 play(memory_id,node_tmp);
			}
			else if(id_test >0){
			}
		}
       /*------------------------------------------------------------------------------*/		
						
		/*------------------------------------------------------------------------------*/		
		if(key_tmp == 5){  //prev
			printf("\nk5 down prev\n");
			kill(share_tmp->id_tmp,SIGKILL);	
			kill(id_test,SIGKILL);

			strcpy(prev_name,share_tmp->name_tmp);
			 
			node_tmp = search_list(head, prev_name);
			if(node_tmp == NULL){
				printf("only one song \n");
			}	
			else{
				/* 节点前移一位 */
				node_tmp = node_tmp->prev;
			}
			id_test=fork();
			if(id_test == 0){			
	                   play( memory_id,node_tmp);
			}
			else if(id_test > 0){
			}
		}	
	}
	/*------------------------------------------------------------------------------*/		

	close(buttons_fd);
  	closedir(dir);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值