Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7724297
  • 博文数量: 961
  • 博客积分: 15795
  • 博客等级: 上将
  • 技术积分: 16612
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-07 14:23
文章分类

全部博文(961)

文章存档

2016年(1)

2015年(61)

2014年(41)

2013年(51)

2012年(235)

2011年(391)

2010年(181)

分类: 嵌入式

2011-02-24 14:14:24

  1. /*
  2.  * mp3播放器控制程序
  3.  *     功能:
  4.               k1:播放、暂停
  5.               k2:停止播放
  6.               k3:上一首
  7.               k4:下一首
  8.  * 附加:歌曲自动循环播放
  9.  *
  10.  */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <sys/ioctl.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #include <fcntl.h>
  18. #include <signal.h>
  19. #include <sys/select.h>
  20. #include <sys/time.h>
  21. #include <errno.h>
  22. #include <sys/wait.h>
  23. #include <string.h>
  24. #include <sys/ipc.h>
  25. #include <sys/shm.h>

  26. /*共享内存申请标记*/
  27. #define PERM S_IRUSR|S_IWUSR                                                    

  28. /*双向循环列表:存放歌曲名*/
  29. struct song                
  30. {
  31.     char songname[20];
  32.     struct song *prev;
  33.     struct song *next;
  34. };

  35. /*孙子进程id号*/
  36. pid_t gradchild;

  37. /*子进程id号*/
  38. pid_t pid;

  39. /*共享内存描述标记*/
  40. int shmid;

  41. char *p_addr;

  42. /*播放标记*/
  43. int first_key=1;
  44. int play_flag=0;

  45. /*************************************************
  46. Function name: play
  47. Parameter : struct song *
  48. Description     : 播放函数
  49. Return         : void
  50. Argument : void
  51. Autor & date : ada 09,12,07
  52. **************************************************/
  53. void play(struct song *currentsong)
  54. {
  55.     pid_t fd;
  56.     char *c_addr;
  57.     char *p;
  58.     int len;
  59.     char my_song[30]="/mp3/song/";
  60.     while(currentsong)
  61.     {
  62.         /*创建子进程,即孙子进程*/
  63.         fd = fork();
  64.         if(fd == -1)
  65.         {    
  66.             perror("fork");
  67.             exit(1);
  68.         }
  69.         else if(fd == 0)
  70.         {
  71.             /*把歌曲名加上根路径*/
  72.             strcat(my_song,currentsong->songname);
  73.             p = my_song;
  74.             len = strlen(p);

  75.             /*去掉文件名最后的'\n'*/
  76.             my_song[len-1]='\0';

  77.             printf("THIS SONG IS %s\n",my_song);
  78.             execl("/mp3/madplay","madplay",my_song,NULL);
  79.             printf("\n\n\n");
  80.         }
  81.         else
  82.         {
  83.             /*内存映射*/
  84.             c_addr = shmat(shmid,0,0);

  85.             /*把孙子进程的id和当前播放歌曲的节点指针传入共享内存*/
  86.             memcpy(c_addr,&fd,sizeof(pid_t));
  87.             memcpy(c_addr + sizeof(pid_t)+1,&currentsong,4);
  88.             /*使用wait阻塞孙子进程,直到孙子进程播放完才能被唤醒;
  89.              当被唤醒时,表示播放MP3期间没有按键按下,则继续顺序播放下一首MP3*/
  90.             if(fd == wait(NULL))
  91.             {
  92.                 currentsong = currentsong->next;
  93.                 printf("THE NEXT SONG IS %s\n",currentsong->songname);
  94.             }
  95.         }
  96.     }
  97. }

  98. /*************************************************
  99. Function name: creat_song_list
  100. Parameter : void
  101. Description     : 创建歌曲名的双向循环链表
  102. Return         : struct song *
  103. Argument : void
  104. Autor & date : ada 09.12.07
  105. **************************************************/
  106. struct song *creat_song_list(void)
  107. {    
  108.     FILE *fd;
  109.     size_t size;
  110.     size_t len;
  111.     char *line = NULL;
  112.     struct song *head;
  113.     struct song *p1;
  114.     struct song *p2;
  115.     system("ls /mp3/song >song_list");
  116.     fd = fopen("song_list","r");

  117.     p1 = (struct song *)malloc(sizeof(struct song));

  118.     printf("==================================song list=====================================\n");
  119.     system("ls /mp3/song");    
  120.     printf("\n");
  121.     printf("================================================================================\n");
  122.     size = getline(&line,&len,fd);

  123.     strncpy(p1->songname,line,strlen(line));
  124.     head = p1;
  125.     while((size = getline(&line,&len,fd)) != -1)
  126.     {    
  127.         p2 = p1;
  128.         p1 = (struct song *)malloc(sizeof(struct song));
  129.         strncpy(p1->songname,line,strlen(line));
  130.         p2->next = p1;
  131.         p1->prev = p2;    
  132.     }
  133.     p1->next = head;
  134.     head->prev = p1;
  135.     p1 = NULL;
  136.     p2 = NULL;
  137.     system("rm -rf song_list");
  138.     return head;
  139. }
  140. /*************************************************
  141. Function name: startplay
  142. Parameter : pid_t *,struct song *
  143. Description     : 开始播放函数
  144. Return         : void
  145. Argument : void
  146. Autor & date : ada 09.12.07
  147. **************************************************/
  148. void startplay(pid_t *childpid,struct song *my_song)
  149. {
  150.     pid_t pid;
  151.     int ret;
  152.     /*创建子进程*/
  153.     pid = fork();

  154.     if(pid > 0)
  155.     {
  156.         *childpid = pid;
  157.         play_flag = 1;
  158.         sleep(1);
  159.         /*把孙子进程的pid传给父进程*/
  160.         memcpy(&gradchild,p_addr,sizeof(pid_t));
  161.     }
  162.     else if(0 == pid)
  163.     {    
  164.         /*子进程播放MP3函数*/
  165.         play(my_song);
  166.     }
  167. }
  168. /*************************************************
  169. Function name: my_pause
  170. Parameter : pid_t
  171. Description     : 暂停函数
  172. Return         : void
  173. Argument : void
  174. Autor & date : ada 09,12,07
  175. **************************************************/
  176. void my_pause(pid_t pid)
  177. {
  178.     printf("=======================PAUSE!PRESS K1 TO CONTINUE===================\n");
  179.     kill(pid,SIGSTOP); //对孙子进程发送SKGSTOP信号

  180.     play_flag = 0;
  181. }

  182. /*************************************************
  183. Function name: my_pause
  184. Parameter : pid_t
  185. Description     : 停止播放函数
  186. Return         : void
  187. Argument : void
  188. Autor & date : ada 09,12,07
  189. **************************************************/
  190. void my_stop(pid_t g_pid)
  191. {

  192.     printf("=======================STOP!PRESS K1 TO START PLAY===================\n");
  193.     kill(g_pid,SIGKILL); //对孙子进程发送SKGKILL信号

  194.     kill(pid,SIGKILL); //对子进程发送SKGKILL信号

  195.     first_key=1;

  196. }

  197. /*************************************************
  198. Function name: conti_play
  199. Parameter : pid_t
  200. Description     : 继续函数
  201. Return         : void
  202. Argument : void
  203. Autor & date : ada 09,12,07
  204. **************************************************/
  205. void conti_play(pid_t pid)
  206. {
  207.     printf("===============================CONTINUE=============================\n");
  208.     kill(pid,SIGCONT); //对孙子进程发送SIGCONT信号

  209.     play_flag=1;
  210. }

  211. /*************************************************
  212. Function name: next
  213. Parameter : pid_t
  214. Description     : 下一首函数
  215. Return         : void
  216. Argument : void
  217. Autor & date : ada 09.12.07
  218. **************************************************/
  219. void next(pid_t next_pid)
  220. {
  221.     struct song *nextsong;

  222.     printf("===============================NEXT MP3=============================\n");
  223.     /*从共享内存获得孙子进程播放歌曲的节点指针*/
  224.     memcpy(&nextsong,p_addr + sizeof(pid_t)+1,4);
  225.     /*指向下首歌曲的节点*/
  226.     nextsong = nextsong->next;
  227.     /*杀死当前歌曲播放的子进程,孙子进程*/
  228.     kill(pid,SIGKILL);
  229.     kill(next_pid,SIGKILL);
  230.     wait(NULL);
  231.     startplay(&pid,nextsong);
  232. }

  233. /*************************************************
  234. Function name: prev
  235. Parameter : pid_t
  236. Description     : 上一首函数
  237. Return         : void
  238. Argument : void
  239. Autor & date : yuanhui 09.12.08
  240. **************************************************/
  241. void prev(pid_t prev_pid)
  242. {
  243.     struct song *prevsong;
  244.     /*从共享内存获得孙子进程播放歌曲的节点指针*/
  245.     printf("===============================PRIOR MP3=============================\n");
  246.     memcpy(&prevsong,p_addr + sizeof(pid_t)+1,4);
  247.     /*指向上首歌曲的节点*/
  248.     prevsong = prevsong->prev;
  249.     /*杀死当前歌曲播放的子进程,孙子进程*/
  250.     kill(pid,SIGKILL);
  251.     kill(prev_pid,SIGKILL);
  252.     wait(NULL);
  253.     startplay(&pid,prevsong);
  254. }

  255. /*************************************************
  256. Function name: main
  257. Parameter : void
  258. Description     : 主函数
  259. Return         : int
  260. Argument : void
  261. Autor & date : ada 09.12.07
  262. **************************************************/
  263. int main(void)
  264. {
  265.     int buttons_fd;
  266.     int key_value;
  267.     struct song *head;
  268.     /*打开设备文件*/
  269.     buttons_fd = open("/dev/buttons", 0);
  270.     if (buttons_fd < 0) {
  271.         perror("open device buttons");
  272.         exit(1);
  273.     }


  274.   /*创建播放列表*/
  275.     head = creat_song_list();
  276.     printf("===================================OPTION=======================================\n\n\n\n");
  277.     printf(" K1:START/PAUSE K2:STOP K3:NEXT K4:PRIOR\n\n\n\n");
  278.     printf("================================================================================\n");


  279.   /*共享内存:用于存放子进程ID,播放列表位置*/
  280.     if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)
  281.         exit(1);
  282.     p_addr = shmat(shmid,0,0);
  283.     memset(p_addr,'\0',1024);
  284.     
  285.     
  286.     while(1)
  287.     {
  288.         fd_set rds;
  289.         int ret;

  290.         FD_ZERO(&rds);
  291.         FD_SET(buttons_fd, &rds);

  292.         /*监听获取键值*/
  293.         ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);
  294.         if (ret < 0)
  295.         {
  296.             perror("select");
  297.             exit(1);
  298.         }
  299.         if (ret == 0)
  300.             printf("Timeout.\n");
  301.         else if (FD_ISSET(buttons_fd, &rds))
  302.         {
  303.             int ret = read(buttons_fd, &key_value, sizeof key_value);
  304.             if (ret != sizeof key_value)
  305.             {
  306.                 if (errno != EAGAIN)
  307.                     perror("read buttons\n");
  308.                 continue;
  309.             }
  310.             else
  311.             {
  312.                 //printf("buttons_value: %d\n", key_value+1);

  313.                 
  314.                 /*首次播放,必须是按键1*/
  315.                 if(first_key){
  316.                     switch(key_value)
  317.                     {    
  318.                     case 0:
  319.                         startplay(&pid,head);
  320.                         first_key=0;
  321.                         break;
  322.                     case 1:
  323.                     case 2:
  324.                     case 3:
  325.                         printf("=======================PRESS K1 TO START PLAY===================\n");
  326.                         break;
  327.                  default:
  328.                         printf("=======================PRESS K1 TO START PLAY===================\n");
  329.                         break;
  330.                     } //end switch

  331.                 }//end if(first_key)

  332.                 /*若不是首次播放,则根据不同键值处理*/
  333.                 else if(!first_key){
  334.                  switch(key_value)
  335.                     {
  336.                     case 0:
  337.                         //printf("play_flag:%d\n",play_flag);

  338.                         if(play_flag)
  339.                             my_pause(gradchild);
  340.                         else
  341.                             conti_play(gradchild);
  342.                         break;
  343.                     case 1:
  344.                         my_stop(gradchild);
  345.                         break;
  346.                     case 2:
  347.                         next(gradchild);
  348.                         break;
  349.                     case 3:
  350.                         prev(gradchild);
  351.                         break;
  352.                     } //end switch

  353.              }//end if(!first_key)


  354.             }
  355.                 
  356.         }
  357.     }

  358.     close(buttons_fd);
  359.     return 0;
  360. }
阅读(2168) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~