📄 final_mp3.c
字号:
#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 40typedef 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -