主题 : 冒泡,发个MP3项目改进版本代码 复制链接 | 浏览器收藏 | 打印
:)
级别: 骑士
UID: 61588
精华: 5
发帖: 248
金钱: 1500 两
威望: 300 点
综合积分: 596 分
注册时间: 2012-01-02
最后登录: 2018-03-05
楼主  发表于: 2013-04-04 21:26

 冒泡,发个MP3项目改进版本代码

原来的按键驱动改为了mini2440上自带的,madplayer没有移植直接调用mini2440上移植好的,具体解决的问题是按键键值的问题,用select监听的话,按键按下,弹起都会读一下。这个就很不好了,不过这个问题解决了。代码如下:
复制代码
  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 DEBUG
  28. #ifdef    DEBUG
  29. #define debug(fmt,args...)    printf (fmt ,##args)
  30. #define debugX(level,fmt,args...) if (DEBUG>=level) printf(fmt,##args);
  31. #else
  32. #define debug(fmt,args...)
  33. #define debugX(level,fmt,args...)
  34. #endif    /* DEBUG */
  35. /*共享内存申请标记*/
  36. #define PERM S_IRUSR|S_IWUSR                                                    
  37. /*双向循环列表:存放歌曲名*/
  38. struct song                
  39. {
  40.     char songname[20];
  41.     struct song *prev;
  42.     struct song *next;
  43. };
  44. /*孙子进程id号*/
  45. pid_t gradchild;
  46. /*子进程id号*/
  47. pid_t pid;
  48. /*共享内存描述标记*/
  49. int shmid;
  50. char *p_addr;
  51. /*播放标记*/
  52. int first_key=1;
  53. int play_flag=0;
  54. /*************************************************
  55. Function name: play
  56. Parameter    : struct song *
  57. Description     : 播放函数
  58. Return         : void
  59. Argument     : void
  60. Autor & date : ada 09,12,07
  61. **************************************************/
  62. void play(struct song *currentsong)
  63. {
  64.     pid_t fd;
  65.     char *c_addr;
  66.     char *p;
  67.     int len;
  68.     char my_song[30]="/mp3/song/";
  69.     while(currentsong)
  70.     {
  71.         /*创建子进程,即孙子进程*/
  72.         fd = fork();
  73.         if(fd == -1)
  74.         {    
  75.             perror("fork");
  76.             exit(1);
  77.         }
  78.         else if(fd == 0)
  79.         {
  80.             /*把歌曲名加上根路径*/
  81.             strcat(my_song,currentsong->songname);
  82.             p = my_song;
  83.             len = strlen(p);
  84.             /*去掉文件名最后的'\n'*/
  85.             my_song[len-1]='\0';
  86.             printf("THIS SONG IS %s\n",my_song);
  87.             execl("/usr/bin/madplay","madplay",my_song,NULL);
  88.             printf("\n\n\n");
  89.         }
  90.         else
  91.         {
  92.             /*内存映射*/
  93.             c_addr = shmat(shmid,0,0);
  94.             /*把孙子进程的id和当前播放歌曲的节点指针传入共享内存*/
  95.             memcpy(c_addr,&fd,sizeof(pid_t));
  96.             memcpy(c_addr + sizeof(pid_t)+1,&currentsong,4);
  97.             /*使用wait阻塞孙子进程,直到孙子进程播放完才能被唤醒;
  98.               当被唤醒时,表示播放MP3期间没有按键按下,则继续顺序播放下一首MP3*/
  99.             if(fd == wait(NULL))
  100.             {
  101.                 currentsong = currentsong->next;
  102.                 printf("THE NEXT SONG IS %s\n",currentsong->songname);
  103.             }
  104.         }
  105.     }
  106. }
  107. /*************************************************
  108. Function name: creat_song_list
  109. Parameter    : void
  110. Description     : 创建歌曲名的双向循环链表
  111. Return         : struct song *
  112. Argument     : void
  113. Autor & date : ada 09.12.07
  114. **************************************************/
  115. struct song *creat_song_list(void)
  116. {    
  117.     FILE *fd;
  118.     size_t size;
  119.     size_t len;
  120.     char *line = NULL;
  121.     struct song *head;
  122.     struct song *p1;
  123.     struct song *p2;
  124.     system("ls /mp3/song >song_list");
  125.     fd = fopen("song_list","r");
  126.     p1 = (struct song *)malloc(sizeof(struct song));
  127.     printf("==================================song list=====================================\n");
  128.     system("ls /mp3/song");    
  129.     printf("\n");
  130.     printf("================================================================================\n");
  131.     size = getline(&line,&len,fd);
  132.     strncpy(p1->songname,line,strlen(line));
  133.     head = p1;
  134.     while((size = getline(&line,&len,fd)) != -1)
  135.     {    
  136.         p2 = p1;
  137.         p1 = (struct song *)malloc(sizeof(struct song));
  138.         strncpy(p1->songname,line,strlen(line));
  139.         p2->next = p1;
  140.         p1->prev = p2;    
  141.     }
  142.     p1->next = head;
  143.     head->prev = p1;
  144.     p1 = NULL;
  145.     p2 = NULL;
  146.     system("rm -rf song_list");
  147.     return head;
  148. }
  149. /*************************************************
  150. Function name: startplay
  151. Parameter    : pid_t *,struct song *
  152. Description     : 开始播放函数
  153. Return         : void
  154. Argument     : void
  155. Autor & date : ada 09.12.07
  156. **************************************************/
  157. void startplay(pid_t *childpid,struct song *my_song)
  158. {
  159.     pid_t pid;
  160.     int ret;
  161.     /*创建子进程*/
  162.     pid = fork();
  163.     if(pid > 0)
  164.     {
  165.         *childpid = pid;
  166.         play_flag = 1;
  167.         sleep(1);
  168.         /*把孙子进程的pid传给父进程*/
  169.         memcpy(&gradchild,p_addr,sizeof(pid_t));
  170.     }
  171.     else if(0 == pid)
  172.     {    
  173.         /*子进程播放MP3函数*/
  174.         play(my_song);
  175.     }
  176. }
  177. /*************************************************
  178. Function name: my_pause
  179. Parameter    : pid_t
  180. Description     : 暂停函数
  181. Return         : void
  182. Argument     : void
  183. Autor & date : ada 09,12,07
  184. **************************************************/
  185. void my_pause(pid_t pid)
  186. {
  187.     printf("=======================PAUSE!PRESS K1 TO CONTINUE===================\n");
  188.     kill(pid,SIGSTOP); //对孙子进程发送SKGSTOP信号
  189.     play_flag = 0;
  190. }
  191. /*************************************************
  192. Function name: my_pause
  193. Parameter    : pid_t
  194. Description     : 停止播放函数
  195. Return         : void
  196. Argument     : void
  197. Autor & date : ada 09,12,07
  198. **************************************************/
  199. void my_stop(pid_t g_pid)
  200. {
  201.     printf("=======================STOP!PRESS K1 TO START PLAY===================\n");
  202.     kill(g_pid,SIGKILL); //对孙子进程发送SKGKILL信号
  203.     kill(pid,SIGKILL);   //对子进程发送SKGKILL信号
  204.     first_key=1;
  205. }
  206. /*************************************************
  207. Function name: conti_play
  208. Parameter    : pid_t
  209. Description     : 继续函数
  210. Return         : void
  211. Argument     : void
  212. Autor & date : ada 09,12,07
  213. **************************************************/
  214. void conti_play(pid_t pid)
  215. {
  216.     printf("===============================CONTINUE=============================\n");
  217.     kill(pid,SIGCONT); //对孙子进程发送SIGCONT信号
  218.     play_flag=1;
  219. }
  220. /*************************************************
  221. Function name: next
  222. Parameter    : pid_t
  223. Description     : 下一首函数
  224. Return         : void
  225. Argument     : void
  226. Autor & date : ada 09.12.07
  227. **************************************************/
  228. void next(pid_t next_pid)
  229. {
  230.     struct song *nextsong;
  231.     printf("===============================NEXT MP3=============================\n");
  232.     /*从共享内存获得孙子进程播放歌曲的节点指针*/
  233.     memcpy(&nextsong,p_addr + sizeof(pid_t)+1,4);
  234.     /*指向下首歌曲的节点*/
  235.     nextsong = nextsong->next;
  236.     /*杀死当前歌曲播放的子进程,孙子进程*/
  237.     kill(pid,SIGKILL);
  238.     kill(next_pid,SIGKILL);
  239.     wait(NULL);
  240.     startplay(&pid,nextsong);
  241. }
  242. /*************************************************
  243. Function name: prev
  244. Parameter    : pid_t
  245. Description     : 上一首函数
  246. Return         : void
  247. Argument     : void
  248. Autor & date : yuanhui 09.12.08
  249. **************************************************/
  250. void prev(pid_t prev_pid)
  251. {
  252.     struct song *prevsong;
  253.     /*从共享内存获得孙子进程播放歌曲的节点指针*/
  254.     printf("===============================PRIOR MP3=============================\n");
  255.     memcpy(&prevsong,p_addr + sizeof(pid_t)+1,4);
  256.     /*指向上首歌曲的节点*/
  257.     prevsong = prevsong->prev;
  258.     /*杀死当前歌曲播放的子进程,孙子进程*/
  259.     kill(pid,SIGKILL);
  260.     kill(prev_pid,SIGKILL);
  261.     wait(NULL);
  262.     startplay(&pid,prevsong);
  263. }
  264. /*************************************************
  265. Function name: main
  266. Parameter    : void
  267. Description     : 主函数
  268. Return         : int
  269. Argument     : void
  270. Autor & date : ada 09.12.07
  271. **************************************************/
  272. int main(void)
  273. {
  274.     int buttons_fd;
  275.     int key_value=0;
  276.     struct song *head;
  277.     /*打开设备文件*/
  278.     buttons_fd = open("/dev/buttons", 0);
  279.     if (buttons_fd < 0) {
  280.         perror("open device buttons");
  281.         exit(1);
  282.     }
  283.   /*创建播放列表*/
  284.     head = creat_song_list();
  285.     printf("===================================OPTION=======================================\n\n\n\n");
  286.     printf("        K1:START/PAUSE     K2:STOP   K3:NEXT      K4:PRIOR\n\n\n\n");
  287.     printf("================================================================================\n");
  288.   /*共享内存:用于存放子进程ID,播放列表位置*/
  289.     if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)
  290.         exit(1);
  291.     p_addr = shmat(shmid,0,0);
  292.     memset(p_addr,'\0',1024);
  293.     
  294.     while(1)
  295.     {
  296.         fd_set rds;
  297.         int ret;
  298.         FD_ZERO(&rds);
  299.         FD_SET(buttons_fd, &rds);
  300.         /*监听获取键值*/
  301.         ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);
  302.         debug("guo select\n");
  303.         if (ret < 0)
  304.         {
  305.             perror("select");
  306.             exit(1);
  307.         }
  308.         if (ret == 0)
  309.             printf("Timeout.\n");
  310.         else if (FD_ISSET(buttons_fd, &rds))
  311.         {
  312.             debug("jin FD_ISSET\n");
  313.             char current_buttons[6] = {'0', '0', '0', '0', '0', '0'};
  314.             int count_of_changed_key;
  315.             int i;
  316.             if (read(buttons_fd, current_buttons, sizeof current_buttons) != sizeof current_buttons) {
  317.                 perror("read buttons:");
  318.                 exit(1);
  319.             }
  320.             debug("guo read\n");
  321.             key_value = 4;//缓一下
  322.             for (i = 0, count_of_changed_key = 0; i < sizeof current_buttons / sizeof current_buttons[0]; i++) {
  323.                 if (current_buttons[i] != '0') {
  324.                     debug("key %d is up!\n", i);
  325.                     count_of_changed_key++;
  326.                     key_value = i;
  327.                     debug("nei_buttons_value: %d\n", key_value+1);
  328.                 }
  329.             }
  330.             debug("over\n");
  331.             
  332.             /*按键范围0-3*/
  333.             if( key_value == 4)
  334.                 continue;
  335.             
  336.             else
  337.             {
  338.                 //key_value = 4;//缓一下
  339.                 printf("\n");
  340.                 debug("buttons_value: %d\n", key_value+1);
  341.                 
  342.                 /*首次播放,必须是按键1*/
  343.                 if(first_key){
  344.                     switch(key_value)
  345.                     {    
  346.                     case 0:
  347.                         startplay(&pid,head);
  348.                         first_key=0;
  349.                         break;
  350.                     case 1:
  351.                     case 2:
  352.                     case 3:
  353.                         printf("=======================PRESS K1 TO START PLAY===================\n");
  354.                         break;
  355.                     default:
  356.                         printf("default\n");
  357.                         printf("=======================PRESS K1 TO START PLAY===================\n");
  358.                         break;
  359.                     } //end switch
  360.                 }//end if(first_key)
  361.                 /*若不是首次播放,则根据不同键值处理*/
  362.                 else if(!first_key){
  363.                     switch(key_value)
  364.                     {
  365.                     case 0:
  366.                         //printf("play_flag:%d\n",play_flag);
  367.                         if(play_flag)
  368.                             my_pause(gradchild);
  369.                         else
  370.                             conti_play(gradchild);
  371.                         break;
  372.                     case 1:
  373.                         my_stop(gradchild);
  374.                         break;
  375.                     case 2:
  376.                         next(gradchild);
  377.                         break;
  378.                     case 3:
  379.                         prev(gradchild);
  380.                         break;
  381.                     } //end switch
  382.              }//end if(!first_key)
  383.             }
  384.                 
  385.         }
  386.     }
  387.     close(buttons_fd);
  388.     return 0;
  389. }


具体的目录结构是:
/->mp3
        ->song
               -> dida.mp3  chunuanhuakai.mp3
        ->app-mp3

歌曲的目录不能变,是绝对路径。直接编译就可以运行了。
:)
级别: 骑士
UID: 61588
精华: 5
发帖: 248
金钱: 1500 两
威望: 300 点
综合积分: 596 分
注册时间: 2012-01-02
最后登录: 2018-03-05
1楼  发表于: 2013-04-04 21:33
图片:
补个图:
级别: 新手上路
UID: 34985
精华: 0
发帖: 35
金钱: 180 两
威望: 36 点
综合积分: 70 分
注册时间: 2010-12-24
最后登录: 2014-04-14
2楼  发表于: 2013-06-19 00:54
void play(struct song *currentsong)里面的c_addr = shmat(shmid,0,0);出现转换错误