久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6002|回復: 0
打印 上一主題 下一主題
收起左側

為madplay編寫應用程序

[復制鏈接]
跳轉到指定樓層
樓主
ID:72519 發表于 2015-1-20 02:29 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

這篇文章的app程序是參考國嵌的。

在編寫app之前我們要編譯好madplay


準備工作一:

編譯madplay

首先解壓三個壓縮文件

[root@localhost ~]# cd /work/projects/sound/

[root@localhost sound]# ls

libid3tag-0.15.1b.tar.gz libmad-0.15.1b.tar.gz madplay-0.15.2b.tar.gz

[root@localhost sound]# tar xzf libid3tag-0.15.1b.tar.gz  //從名字上看是個庫

[root@localhost sound]# tar xzf libmad-0.15.1b.tar.gz     //這個也是庫

[root@localhost sound]# tar xzf madplay-0.15.2b.tar.gz  //這個是應用程序,它依賴這兩個庫

[root@localhost sound]#


[root@localhost sound]# cd libid3tag-0.15.1b

[root@localhost libid3tag-0.15.1b]# ./configure--host=arm-linux --prefix=/work/projects/sound/tmp

configure: WARNING: If you wanted to set the --build type, don't use--host.

    If a cross compiler isdetected then cross compile mode will be used.

checking for a BSD-compatible install... /usr/bin/install -c

checking whether build environment is sane... yes


然后再

make

make install
再按照上面的方法進入libmad-0.15.1b文件夾編譯

./configure --host=arm-linux --prefix=/work/projects/sound/tmpLDFLAGS="-L/work/projects/sound/tmp/lib" CFLAGS="-I/work/projects/sound/tmp/include"

注意: -L/work…..

這個-L與/之間沒有空格.

然后再

make

make install

把tmp/bin/*  tmp/lib/*so* -d把庫文件復制到開發板lib文件夾,bin文件復制到開發板的bin文件夾


# madplay --tty-control /mnt/mp3/beyond.mp3

MPEG Audio Decoder 0.15.2 (beta) - Copyright (C) 2000-2004 RobertLeslie et al.

s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66

         Artist: Beyond£¨»Æ¼ò¾Ô£©

          Album:òôàÖμîìÃMusicPalace

        Comment:http://music.zkinfo.ha.cn

s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66


到這里時候測試下自己的開發板能否播放mp3音樂。

注意事項:確保自己的開發板已經有聲卡了,想提高播放音樂的音量不能用madplay提供的方法(聲音加大會破掉,而且音質會變得很差),如果你的開發板有QT界面直接調整音量滑塊。


準備工作二:

編寫開發板上的驅動程序。我的開發板是TQ2440。

key_drv_irq.c

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/fs.h>
  4. #include <linux/init.h>
  5. #include <linux/delay.h>
  6. #include <linux/irq.h>
  7. #include <asm/uaccess.h>
  8. #include <asm/irq.h>
  9. #include <asm/io.h>
  10. #include <asm/arch/regs-gpio.h>
  11. #include <asm/hardware.h>

  12. static int major;
  13. static struct class *key_class;
  14. static struct class_device        *key_class_dev;

  15. volatile unsigned long *gpfcon;
  16. volatile unsigned long *gpfdat;

  17. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

  18. /* 中斷事件標志, 中斷服務程序將它置1,third_drv_read將它清0 */
  19. static volatile int ev_press = 0;


  20. struct pin_desc{
  21.         unsigned int pin;
  22.         unsigned int key_val;
  23. };


  24. /* 鍵值: 按下時, 0x01, 0x02, 0x03, 0x04 */
  25. /* 鍵值: 松開時, 0x81, 0x82, 0x83, 0x84 */
  26. static unsigned char key_val;

  27. struct pin_desc pins_desc[4] = {
  28.         {S3C2410_GPF1, 0x01},
  29.         {S3C2410_GPF4, 0x02},
  30.         {S3C2410_GPF2, 0x03},
  31.         {S3C2410_GPF0, 0x04},
  32. };

  33. /*
  34.   * 確定按鍵值
  35.   */
  36. static irqreturn_t buttons_irq(int irq, void *dev_id)
  37. {
  38.         struct pin_desc * pindesc = (struct pin_desc *)dev_id;
  39.         unsigned int pinval;
  40.        
  41.         pinval = s3c2410_gpio_getpin(pindesc->pin);

  42.         if (pinval)
  43.         {
  44.                 /* 松開 */
  45.                 key_val = 0x80 | pindesc->key_val;
  46.         }
  47.         else
  48.         {
  49.                 /* 按下 */
  50.                 key_val = pindesc->key_val;
  51.         }

  52.   ev_press = 1;                  /* 表示中斷發生了 */
  53.   wake_up_interruptible(&button_waitq);   /* 喚醒休眠的進程 */
  54.        
  55.         return IRQ_RETVAL(IRQ_HANDLED);
  56. }

  57. static int key_drv_open(struct inode *inode, struct file *file)
  58. {
  59.   /* 配置成輸入模式 */
  60.   request_irq(IRQ_EINT1, buttons_irq, IRQT_BOTHEDGE, "K1", &pins_desc[0]);
  61.   request_irq(IRQ_EINT4, buttons_irq, IRQT_BOTHEDGE, "K2", &pins_desc[1]);  
  62.   request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, "K3", &pins_desc[2]);
  63.   request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "K4", &pins_desc[3]);
  64.    
  65.   return 0;
  66. }

  67. static ssize_t key_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
  68. {
  69.         if (size != 1)
  70.                 return -EINVAL;

  71.         /* 如果沒有按鍵動作, 休眠 */
  72.         wait_event_interruptible(button_waitq, ev_press);

  73.         /* 如果有按鍵動作, 返回鍵值 */
  74.         copy_to_user(buf, &key_val, 1);
  75.         ev_press = 0;
  76.        
  77.         return 1;
  78. }

  79. int key_dev_close(struct inode *inode, struct file *file)
  80. {
  81.         free_irq(IRQ_EINT1, &pins_desc[0]);
  82.         free_irq(IRQ_EINT4, &pins_desc[1]);
  83.         free_irq(IRQ_EINT2, &pins_desc[2]);
  84.         free_irq(IRQ_EINT0, &pins_desc[3]);
  85.   return 0;
  86. }
  87.             
  88. static struct file_operations key_drv_fops={
  89.   .owner=THIS_MODULE,
  90.   .open=key_drv_open,
  91.   .read=key_drv_read,
  92.   .release=key_dev_close,
  93. };

  94. static int key_drv_init(void)
  95. {
  96.   major=register_chrdev(0, "key_drv", &key_drv_fops);
  97.   key_class=class_create(THIS_MODULE, "keydrv");
  98.   key_class_dev=class_device_create(key_class, NULL, MKDEV(major,0), NULL,"buttons"); /* dev/buttons */
  99.   
  100.   gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16); //0x56000010是的GPIOB的
  101.         gpfdat = gpfcon + 1;
  102.        
  103.   return 0;
  104. }

  105. static void key_drv_exit(void)
  106. {
  107.   unregister_chrdev(major, "key_drv");
  108.   class_device_unregister(key_class_dev);
  109.   class_destroy(key_class);   //class_destory(key_class);
  110.   iounmap(gpfcon);
  111. }

  112. module_init(key_drv_init);
  113. module_exit(key_drv_exit);

  114. MODULE_LICENSE("GPL");
復制代碼

準備工作三:

app-mp3.c

  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/";
  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("/bin/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,¤tsong,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_list");
  116.         fd = fopen("song_list","r");

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

  118.         printf("==================================song list=====================================\n");
  119.         system("ls /mp3");       
  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. //linux C中的wait(NULL)是什么意思?請問_百度知道
  254. //答:等待子進程退出。NULL的意思是退出狀態不關注。如果要獲取退出狀態應該寫成wait(&status);
  255.         startplay(&pid,prevsong);
  256. }

  257. /*************************************************
  258. Function name: main
  259. Parameter    : void
  260. Description         : 主函數
  261. Return                 : int
  262. Argument     : void
  263. Autor & date : ada 09.12.07
  264. **************************************************/
  265. int main(void)
  266. {
  267.         int buttons_fd;
  268.         int key_value;
  269.         struct song *head;
  270.         /*打開設備文件*/
  271.         buttons_fd = open("/dev/buttons", O_RDWR);
  272.         if (buttons_fd < 0) {
  273.                 perror("open /dev/buttons fail!!!");
  274.                 exit(1);
  275.         }


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


  281.   /*共享內存:用于存放子進程ID,播放列表位置*/
  282.         if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)
  283.                 exit(1);
  284.         p_addr = shmat(shmid,0,0);
  285.         memset(p_addr,'\0',1024);
  286.        
  287.        
  288.         while(1)
  289.         {
  290.                         unsigned char key_value;
  291.                        
  292.                         read(buttons_fd, &key_value, 1);       
  293.                         key_value--;
  294.       /*首次播放,必須是按鍵1*/
  295.       if(first_key) {
  296.         switch(key_value)
  297.         {       
  298.           case 0:
  299.               startplay(&pid,head);
  300.               first_key=0;
  301.             break;
  302.           case 1:
  303.           case 2:
  304.           case 3:
  305.             printf("=======================PRESS K1 TO START PLAY===================\n");
  306.           break;
  307.          default:
  308.             printf("=======================PRESS K1 TO START PLAY===================\n");
  309.           break;
  310.         } //end switch
  311.       }//end if(first_key)
  312.       /*若不是首次播放,則根據不同鍵值處理*/
  313.       else if(!first_key) {
  314.         switch(key_value)
  315.         {
  316.           case 0:
  317.           //printf("play_flag:%d\n",play_flag);
  318.           if(play_flag)
  319.           my_pause(gradchild);
  320.           else
  321.           conti_play(gradchild);
  322.           break;
  323.           case 1:
  324.           my_stop(gradchild);
  325.           break;
  326.           case 2:
  327.           next(gradchild);
  328.           break;
  329.           case 3:
  330.           prev(gradchild);
  331.           break;
  332.         } //end switch
  333.       }//end if(!first_key)
  334.         }

  335.         close(buttons_fd);
  336.         return 0;
  337. }
復制代碼

準備工作四:

在開發板根目錄建立mp3文件夾,拷貝幾首MP3文件進去,注意文件名不要超過20個字符。



現在可以運行這個app-mp3應用程序了。

=======================PRESS K1 TO START PLAY===================
=======================PRESS K1 TO START PLAY===================
=======================PRESS K1 TO START PLAY===================
THIS SONG IS /mp3/Tank.mp3
MPEG Audio Decoder 0.15.2 (beta) - Copyright (C) 2000-2004 Robert Leslie et al.
s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66
          Title: 販販販        Artist: Tank(販s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66
===============================NEXT MP3=============================
THIS SONG IS /mp3/beyond.mp3
MPEG Audio Decoder 0.15.2 (beta) - Copyright (C) 2000-2004 Robert Leslie et al.
s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66
         Artist: Beyond(黃家駒)
          Album: 音樂殿堂Musics3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66
Palace
        Comment: http://music.zkinfo.ha.cn
error: frame 12346: lost synchronization
12346 frames decoded (0:05:22.5), +0.6 dB peak amplitude, 19 clipped samples
THE NEXT SONG IS huanghun.mp3


THIS SONG IS /mp3/huanghun.mp3
MPEG Audio Decoder 0.15.2 (beta) - Copyright (C) 2000-2004 Robert Leslie et al.
s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66
          Title: 黃昏
         Artist: 周傳雄 (小剛)
          s3c2410-uda1341-superlp: audio_set_dsp_speed:44100 prescaler:66
Album: transfer
           Year: 2000
          Genre: Pop
        Comment: mp3.attin.com




分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 91视频在线看 | 国产精品无码久久久久 | h视频免费在线观看 | 欧美日韩精品久久久免费观看 | 理论片午午伦夜理片影院 | 色综合天天天天做夜夜夜夜做 | 国产日韩在线观看一区 | 欧美日韩精品亚洲 | 精品久久久久久久人人人人传媒 | av在线免费播放 | 亚洲自拍一区在线观看 | 成人免费观看男女羞羞视频 | 欧美色综合一区二区三区 | 98久久| 精品久久久久久久久久久久 | 国产亚洲精品久久久久久牛牛 | 欧美日韩综合 | 激情国产视频 | 91精品国产综合久久精品图片 | 欧美一级欧美一级在线播放 | 国产精品成人国产乱一区 | 欧美日韩亚洲系列 | 久久高清 | 国产精品久久久久久久久久三级 | 亚洲精品乱码久久久久久蜜桃 | www.av在线| 欧美在线视频a | 欧美精品中文 | 成人国产精品久久 | 欧美日韩电影一区 | 亚洲精品久久久久中文字幕欢迎你 | 亚洲精品1区2区3区 91免费看片 | 91福利电影在线观看 | 91麻豆产精品久久久久久夏晴子 | 欧美一级毛片在线播放 | 亚洲第一免费播放区 | 亚洲免费在线观看视频 | 久久久久久久av | 午夜伦4480yy私人影院 | 在线观看免费av网站 | 日韩久久久久久 |