#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;
}
mp3播放器
最新推荐文章于 2022-01-16 16:43:06 发布