这篇文章的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
#include #include #include #include #include #include #include #include #include #include #include static int major; static struct class *key_class; static struct class_device *key_class_dev; volatile unsigned long *gpfcon; volatile unsigned long *gpfdat; static DECLARE_WAIT_QUEUE_HEAD(button_waitq); /* 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0 */ static volatile int ev_press = 0; struct pin_desc{ unsigned int pin; unsigned int key_val; }; /* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 */ /* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */ static unsigned char key_val; struct pin_desc pins_desc[4] = { {S3C2410_GPF1, 0x01}, {S3C2410_GPF4, 0x02}, {S3C2410_GPF2, 0x03}, {S3C2410_GPF0, 0x04}, }; /* * 确定按键值 */ static irqreturn_t buttons_irq(int irq, void *dev_id) { struct pin_desc * pindesc = (struct pin_desc *)dev_id; unsigned int pinval; pinval = s3c2410_gpio_getpin(pindesc->pin); if (pinval) { /* 松开 */ key_val = 0x80 | pindesc->key_val; } else { /* 按下 */ key_val = pindesc->key_val; } ev_press = 1; /* 表示中断发生了 */ wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */ return IRQ_RETVAL(IRQ_HANDLED); } static int key_drv_open(struct inode *inode, struct file *file) { /* 配置成输入模式 */ request_irq(IRQ_EINT1, buttons_irq, IRQT_BOTHEDGE, "K1", &pins_desc[0]); request_irq(IRQ_EINT4, buttons_irq, IRQT_BOTHEDGE, "K2", &pins_desc[1]); request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, "K3", &pins_desc[2]); request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "K4", &pins_desc[3]); return 0; } static ssize_t key_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { if (size != 1) return -EINVAL; /* 如果没有按键动作, 休眠 */ wait_event_interruptible(button_waitq, ev_press); /* 如果有按键动作, 返回键值 */ copy_to_user(buf, &key_val, 1); ev_press = 0; return 1; } int key_dev_close(struct inode *inode, struct file *file) { free_irq(IRQ_EINT1, &pins_desc[0]); free_irq(IRQ_EINT4, &pins_desc[1]); free_irq(IRQ_EINT2, &pins_desc[2]); free_irq(IRQ_EINT0, &pins_desc[3]); return 0; } static struct file_operations key_drv_fops={ .owner=THIS_MODULE, .open=key_drv_open, .read=key_drv_read, .release=key_dev_close, }; static int key_drv_init(void) { major=register_chrdev(0, "key_drv", &key_drv_fops); key_class=class_create(THIS_MODULE, "keydrv"); key_class_dev=class_device_create(key_class, NULL, MKDEV(major,0), NULL,"buttons"); /* dev/buttons */ gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16); //0x56000010是的GPIOB的 gpfdat = gpfcon + 1; return 0; } static void key_drv_exit(void) { unregister_chrdev(major, "key_drv"); class_device_unregister(key_class_dev); class_destroy(key_class); //class_destory(key_class); iounmap(gpfcon); } module_init(key_drv_init); module_exit(key_drv_exit); MODULE_LICENSE("GPL"); 准备工作三: app-mp3.c /* * mp3播放器控制程序 * 功能: k1:播放、暂停 k2:停止播放 k3:上一首 k4:下一首 * 附加:歌曲自动循环播放 * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*共享内存申请标记*/ #define PERM S_IRUSR|S_IWUSR /*双向循环列表:存放歌曲名*/ struct song { char songname[20]; struct song *prev; struct song *next; }; /*孙子进程id号*/ pid_t gradchild; /*子进程id号*/ pid_t pid; /*共享内存描述标记*/ int shmid; char *p_addr; /*播放标记*/ int first_key=1; int play_flag=0; /************************************************* Function name: play Parameter : struct song * Description : 播放函数 Return : void Argument : void Autor & date : ada 09,12,07 **************************************************/ void play(struct song *currentsong) { pid_t fd; char *c_addr; char *p; int len; char my_song[30]="/mp3/"; while(currentsong) { /*创建子进程,即孙子进程*/ fd = fork(); if(fd == -1) { perror("fork"); exit(1); } else if(fd == 0) { /*把歌曲名加上根路径*/ strcat(my_song,currentsong->songname); p = my_song; len = strlen(p); /*去掉文件名最后的'n'*/ my_song[len-1]='