嵌入式mp3播放器
分四部分:按键驱动,声卡驱动,Madplay播放器移植,MP3主播放器处理 按键1:播放,按键2:停止,按键3:上一曲,按键4:下一曲 UA1341内核自带声卡驱动 .解压内核: tar zxvf linux..清理中间件,配置文件:cd linux-linux2.6.29;make clean .选择参考配置文件:cp config-mp3.config .配置内核: make menuconfig ARCH=arm CROSS_COMPILE=arm-linux- 选择声卡驱动:device drivers-->sound card support-->advanced linux sound architecture-->alsa for soc audio support-->UA134x .编译内核: make uImage ARCH=arm CROSS_COMPILE=arm-linux- 内核映像uImage位于arch/arm/boot 将其拷贝到tftpboot目录 .解压rootfs.tar.gz并拷贝到nfsroot .按键驱动移植: cd SDK-MP3/driver make clean;make cp mini2440_buttons.ko /nfroot/rootfs/mp3 .madplay移植见最后 9.播放处理:cd SDK-MP3/app;make clean;makecp app-mp3 /nfsroot/rootfs/mp3 10.测试采用NFS方式起文件系统,加载按键驱动,运行mp3程序:insmod mini2440_buttons.ko./app-mp3会显示播放列表,播放option,1,2,3,4按键控制播放。
主要程序为mp3播放控制程序: /* * mp3播放器控制程序 * 功能: k1:播放、暂停 k2:停止播放 k3:上一首 k4:下一首 * 附加:歌曲自动循环播放 * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <signal.h> #include <sys/select.h> #include <sys/time.h> #include <errno.h> #include <sys/wait.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> /*共享内存申请标记*/ #define PERM S_IRUSR|S_IWUSR /*双向循环列表:存放歌曲名*/ struct song { ]; struct song *prev; struct song *next; }; /*孙子进程id号*/ pid_t gradchild; /*子进程id号*/ pid_t pid; /*共享内存描述标记*/ int shmid; char *p_addr; /*播放标记*/ ; ; /************************************************* 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; ]="/mp3/song/"; while(currentsong) { /*创建子进程,即孙子进程*/ fd = fork(); ) { perror("fork"); exit(); } ) { /*把歌曲名加上根路径*/ strcat(my_song,currentsong->songname); p = my_song; len = strlen(p); /*去掉文件名最后的'\n'*/ my_song[len-]='\0'; printf("THIS SONG IS %s\n",my_song); execl("/mp3/madplay","madplay",my_song,NULL); printf("\n\n\n"); } else { /*内存映射*/ c_addr = shmat(shmid,,); /*把孙子进程的id和当前播放歌曲的节点指针传入共享内存*/ memcpy(c_addr,&fd,sizeof(pid_t)); memcpy(c_addr + ,¤tsong,); /*使用wait阻塞孙子进程,直到孙子进程播放完才能被唤醒; 当被唤醒时,表示播放MP3期间没有按键按下,则继续顺序播放下一首MP3*/ if(fd == wait(NULL)) { currentsong = currentsong->next; printf("THE NEXT SONG IS %s\n",currentsong->songname); } } } } /************************************************* Function name: creat_song_list Parameter : void Description : 创建歌曲名的双向循环链表 Return : struct song * Argument : void Autor & date : ada 09.12.07 **************************************************/ struct song *creat_song_list(void) { FILE *fd; size_t size; size_t len; char *line = NULL; struct song *head; struct song *p1; struct song *p2; system("ls /mp3/song >song_list"); fd = fopen("song_list","r"); p1 = (struct song *)malloc(sizeof(struct song)); printf("==================================song list=====================================\n"); system("ls /mp3/song"); printf("\n"); printf("================================================================================\n"); size = getline(&line,&len,fd); strncpy(p1->songname,line,strlen(line)); head = p1; ) { p2 = p1; p1 = (struct song *)malloc(sizeof(struct song)); strncpy(p1->songname,line,strlen(line)); p2->next = p1; p1->prev = p2; } p1->next = head; head->prev = p1; p1 = NULL; p2 = NULL; system("rm -rf song_list"); return head; } /************************************************* Function name: startplay Parameter : pid_t *,struct song * Description : 开始播放函数 Return : void Argument : void Autor & date : ada 09.12.07 **************************************************/ void startplay(pid_t *childpid,struct song *my_song) { pid_t pid; int ret; /*创建子进程*/ pid = fork(); ) { *childpid = pid; play_flag = ; sleep(); /*把孙子进程的pid传给父进程*/ memcpy(&gradchild,p_addr,sizeof(pid_t)); } == pid) { /*子进程播放MP3函数*/ play(my_song); } } /************************************************* Function name: my_pause Parameter : pid_t Description : 暂停函数 Return : void Argument : void Autor & date : ada 09,12,07 **************************************************/ void my_pause(pid_t pid) { printf("=======================PAUSE!PRESS K1 TO CONTINUE===================\n"); kill(pid,SIGSTOP); //对孙子进程发送SKGSTOP信号 play_flag = ; } /************************************************* Function name: my_pause Parameter : pid_t Description : 停止播放函数 Return : void Argument : void Autor & date : ada 09,12,07 **************************************************/ void my_stop(pid_t g_pid) { printf("=======================STOP!PRESS K1 TO START PLAY===================\n"); kill(g_pid,SIGKILL); //对孙子进程发送SKGKILL信号 kill(pid,SIGKILL); //对子进程发送SKGKILL信号 first_key=; } /************************************************* Function name: conti_play Parameter : pid_t Description : 继续函数 Return : void Argument : void Autor & date : ada 09,12,07 **************************************************/ void conti_play(pid_t pid) { printf("===============================CONTINUE=============================\n"); kill(pid,SIGCONT); //对孙子进程发送SIGCONT信号 play_flag=; } /************************************************* Function name: next Parameter : pid_t Description : 下一首函数 Return : void Argument : void Autor & date : ada 09.12.07 **************************************************/ void next(pid_t next_pid) { struct song *nextsong; printf("===============================NEXT MP3=============================\n"); /*从共享内存获得孙子进程播放歌曲的节点指针*/ memcpy(&nextsong,p_addr + ,); /*指向下首歌曲的节点*/ nextsong = nextsong->next; /*杀死当前歌曲播放的子进程,孙子进程*/ kill(pid,SIGKILL); kill(next_pid,SIGKILL); wait(NULL); startplay(&pid,nextsong); } /************************************************* Function name: prev Parameter : pid_t Description : 上一首函数 Return : void Argument : void Autor & date : yuanhui 09.12.08 **************************************************/ void prev(pid_t prev_pid) { struct song *prevsong; /*从共享内存获得孙子进程播放歌曲的节点指针*/ printf("===============================PRIOR MP3=============================\n"); memcpy(&prevsong,p_addr + ,); /*指向上首歌曲的节点*/ prevsong = prevsong->prev; /*杀死当前歌曲播放的子进程,孙子进程*/ kill(pid,SIGKILL); kill(prev_pid,SIGKILL); wait(NULL); startplay(&pid,prevsong); } /************************************************* Function name: main Parameter : void Description : 主函数 Return : int Argument : void Autor & date : ada 09.12.07 **************************************************/ int main(void) { int buttons_fd; int key_value; struct song *head; /*打开设备文件*/ buttons_fd = open(); ) { perror("open device buttons"); exit(); } /*创建播放列表*/ head = creat_song_list(); printf("===================================OPTION=======================================\n\n\n\n"); printf(" K1:START/PAUSE K2:STOP K3:NEXT K4:PRIOR\n\n\n\n"); printf("================================================================================\n"); /*共享内存:用于存放子进程ID,播放列表位置*/ ,PERM))== -) exit(); p_addr = shmat(shmid,,); memset(p_addr,); ) { fd_set rds; int ret; FD_ZERO(&rds); FD_SET(buttons_fd, &rds); /*监听获取键值*/ ret = , &rds, NULL, NULL, NULL); ) { perror("select"); exit(); } ) printf("Timeout.\n"); else if (FD_ISSET(buttons_fd, &rds)) { int ret = read(buttons_fd, &key_value, sizeof key_value); if (ret != sizeof key_value) { if (errno != EAGAIN) perror("read buttons\n"); continue; } else { //printf("buttons_value: %d\n", key_value+1); /*首次播放,必须是按键1*/ if(first_key){ switch(key_value) { : startplay(&pid,head); first_key=; break; : : : printf("=======================PRESS K1 TO START PLAY===================\n"); break; default: printf("=======================PRESS K1 TO START PLAY===================\n"); break; } //end switch }//end if(first_key) /*若不是首次播放,则根据不同键值处理*/ else if(!first_key){ switch(key_value) { : //printf("play_flag:%d\n",play_flag); if(play_flag) my_pause(gradchild); else conti_play(gradchild); break; : my_stop(gradchild); break; : next(gradchild); break; : prev(gradchild); break; } //end switch }//end if(!first_key) } } } close(buttons_fd); ; }
all:
arm-linux-gcc -static app.c -o app-mp3
clean:
rm -rf app-mp3
mini2440_buttons.c #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/poll.h> #include <linux/irq.h> #include <asm/irq.h> #include <linux/interrupt.h> #include <asm/uaccess.h> #include <mach/regs-gpio.h> #include <mach/hardware.h> #include <linux/platform_device.h> #include <linux/cdev.h> #include <linux/miscdevice.h> #define DEVICE_NAME "buttons" //#define DEBUG struct button_irq_desc { int irq; int pin; int pin_setting; int number; char *name; }; #if !defined (CONFIG_QQ2440_BUTTONS) static struct button_irq_desc button_irqs [] = { {IRQ_EINT8 , S3C2410_GPG0 , S3C2410_GPG0_EINT8 , , "KEY0"}, {IRQ_EINT11, S3C2410_GPG3 , S3C2410_GPG3_EINT11 , , "KEY1"}, {IRQ_EINT13, S3C2410_GPG5 , S3C2410_GPG5_EINT13 , , "KEY2"}, {IRQ_EINT14, S3C2410_GPG6 , S3C2410_GPG6_EINT14 , , "KEY3"}, {IRQ_EINT15, S3C2410_GPG7 , S3C2410_GPG7_EINT15 , , "KEY4"}, {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, , "KEY5"}, }; #else /* means QQ */ static struct button_irq_desc button_irqs [] = { {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, , "KEY0"}, {IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG3_EINT11, , "KEY1"}, {IRQ_EINT2, S3C2410_GPF2, S3C2410_GPF2_EINT2, , "KEY2"}, {IRQ_EINT0, S3C2410_GPF0, S3C2410_GPF0_EINT0, , "KEY3"}, { -, -, -, , "KEY4"}, { -, -, -, , "KEY5"}, }; #endif //static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'}; ; static DECLARE_WAIT_QUEUE_HEAD(button_waitq); ; static irqreturn_t buttons_interrupt(int irq, void *dev_id) { struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id; int down; // udelay(0); /*上升沿触发,GPIO DAT 应该为非0 的数*/ down = !s3c2410_gpio_getpin(button_irqs->pin); if (!down) { //printk("rising\n"); key_values = button_irqs->number; ev_press = ; wake_up_interruptible(&button_waitq); } else { //printk("falling\n"); ev_press = ; ; } return IRQ_RETVAL(IRQ_HANDLED); } static int s3c24xx_buttons_open(struct inode *inode, struct file *file) { int i; ; ; i < ]); i++) { ) { continue; } /* 设置中断触发方式 IRQ_TYPE_EDGE_FALLING,IRQ_TYPE_EDGE_RISING,IRQ_TYPE_EDGE_BOTH ;我们这里设置为上升沿触发*/ //err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH, // button_irqs[i].name, (void *)&button_irqs[i]); err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_RISING, button_irqs[i].name, (void *)&button_irqs[i]); if (err) break; } if (err) { i--; ; i--) { ) { continue; } disable_irq(button_irqs[i].irq); free_irq(button_irqs[i].irq, (void *)&button_irqs[i]); } return -EBUSY; } ev_press = ; ; } static int s3c24xx_buttons_close(struct inode *inode, struct file *file) { int i; ; i < ]); i++) { ) { continue; } free_irq(button_irqs[i].irq, (void *)&button_irqs[i]); } ; } static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { unsigned long err; //int i=0; if (!ev_press) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; else wait_event_interruptible(button_waitq, ev_press); } if(count != sizeof key_values) return -EINVAL; ev_press = ; err = copy_to_user(buff, &key_values, sizeof(key_values)); return sizeof(key_values); } static unsigned int s3c24xx_buttons_poll( struct file *file, struct poll_table_struct *wait) { unsigned ; poll_wait(file, &button_waitq, wait); if (ev_press) mask |= POLLIN | POLLRDNORM; return mask; } static struct file_operations dev_fops = { .owner = THIS_MODULE, .open = s3c24xx_buttons_open, .release = s3c24xx_buttons_close, .read = s3c24xx_buttons_read, .poll = s3c24xx_buttons_poll, }; static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init dev_init(void) { int ret; ret = misc_register(&misc); #ifdef DEBUG printk("debug test\n");//ykz #endif printk (DEVICE_NAME"\tinitialized\n"); return ret; } static void __exit dev_exit(void) { misc_deregister(&misc); } module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("FriendlyARM Inc.");
ifneq ($(KERNELRELEASE),)
obj-m := mini2440_buttons.o
else
KDIR := /home/project/mp3/SDK-MP3/kernel/linux-2.6.29
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers app-key
endif
Madplay移植说明 一.准备 移植Madplay所需四个软件包分别为libid3tag-0.15.1b.tar.gz, libmad-.tar.gz,madplay-0.15.2b.tar.gz 二.解压 .mkdir /mp3 建立MP3目录 . tar -zxvf libid3tag-0.15.1b.tar.gz -C /mp3 . tar -zxvf ibmad-0.15.1b.tar.gz -C /mp3 . tar -zxvf zlib-.tar.gz -C /mp3 . tar -zxvf madplay-0.15.2b.tar.gz -C /mp3 三.编译zlib #cd /mp3/zlib- #./configure --prefix=/usr/local/arm//arm-none-linux-gnueabi/libc/usr/lib 修改Makefile AR=/usr/local/arm//bin/arm-linux-ar rcs CC=/usr/local/arm//bin/arm-linux-gcc RANLIB=/usr/local/arm//bin/arm-linux-ranlib 执行 #make #make install 四.编译libid3tag #cd /mp3/libid3tat-0.15.1d #./configure --host=arm-linux CC=arm-linux-gcc --disable-debugging --disable-shared --prefix=/usr/local/arm//arm-none-linux-gnueabi/libc/usr/lib #make #make install 五.编译libmad #cd /mp3/libmad-0.15.1b #./configure --enable-fpm=arm --host=arm-linux --disable-shared --disable-debugging --prefix=/usr/local/arm//arm-none-linux-gnueabi/libc/usr/lib 修改 Makefile 129行 去掉 –fforce-mem #make #make install 六.编译madplay #cd /mp3/madplay-0.15.2b #./configure --host=arm-linux CC=arm-linux-gcc --disable-debugging --disable-shared #make 但是,这样得到的是动态连接的。 #rm madplay 拷贝make的最后一个连接的命令,在最后加上-static 和 -lz,然后运行,得到静态连接的程序 如 arm-linux-gcc -Wall -O2 -fomit-frame-pointer -o madplay madplay.o getopt.o getopt1.o version.o resample.o filter.o tag.o crc.o rgain.o player.o audio.o audio_aiff.o audio_cdda.o audio_hex.o audio_null.o audio_raw.o audio_snd.o audio_wave.o audio_oss.o -lmad -lid3tag -lm -lz -static 最后把madplay下到板子就可以了.
嵌入式mp3播放器的更多相关文章
- 基于Stm32的MP3播放器设计与实现
原创博文,转载请注明出处 这是我高级电子技术试验课做的作业,拿来共享一下.项目在安福莱例程基础之上进行的功能完善,里面的部分内容可参考安福莱mp3例程.当然用的板子也是安福莱的板子,因为算起来总共做了 ...
- C# wave mp3 播放器探寻
C# wave mp3 播放器探寻 最近无聊,想听听歌曲.可怜新电脑上歌曲就两三首,要听其它的就得在旧电脑上播放.可是,那台古董但不失健壮的本本被老婆无情的霸占了.无奈. 思来想去,得,写个程序播 ...
- MP3播放器团队项目
一.设计思路 程序要求能播放MP3文件,因此需调用库中的播放方法:右键工具箱选择项,添加com组件,选择window media player后工具箱就会多一个控件,然后拖到窗体中就OK了.另在窗体中 ...
- 你也可以用java的swing可以做出这么炫的mp3播放器_源码下载
I had published the blog : 你用java的swing可以做出这么炫的mp3播放器吗? and to display some screenshots about this M ...
- 你用java的swing可以做出这么炫的mp3播放器吗?
这个mp3播放器是基于java的swing编写的,我认为界面还是可以拿出来和大家看一看评一评. 先说说创作的初衷,由于前段时间工作不是很忙,与其闲着,还不如找一些东西来给自己捣腾捣腾,在 之前写的 j ...
- MP3播放器的实现
今天,基本上实现了MP3播放器的基本功能,现在总结一下. 首先,下载服务器端的MP3列表,这里用到了下载技术和解析XML文件技术. 下载参考(http://blog.csdn.net/huim_lin ...
- 安卓MP3播放器开发实例(1)之音乐列表界面
学习安卓开发有一年了,想想这一年的努力,确实也收获了不少.也找到了比較如意的工作. 今天准备分享一个以前在初学阶段练习的一个项目.通过这个项目我真正的找到了开发安卓软件的感觉,从此逐渐步入安卓开发的正 ...
- 开源mp3播放器--madplay 编译和移植 简记
madplay是一款开源的mp3播放器. http://madplay.sourcearchive.com/ 下面简单记录一下madplay的编译与移植到ARM开发板上的过程 一.编译x86版本的ma ...
- x宝23大洋包邮的老式大朝华MP3播放器简单评测
(纯兴趣测评,非广告) 最近逛X宝,看到了这个古董级MP3播放器居然还在售,于是脑抽+情怀泛滥买了一个. 然后呢,从遥远的深圳跨越好几千公里邮过来了这个玩意: 那节南孚5号电池是我自己的,是为了对比一 ...
随机推荐
- 在JAVA中生成RSA秘钥对实现SSH互信
https://blog.csdn.net/u014196729/article/details/51496262 https://blog.csdn.net/u013066244/article/d ...
- day3 集合set()实例分析
集合,我们在高中的时候专门学习过集合,并集,交集,差集等,下面来看一下集合的定义,如下: 集合(简称集)是数学中一个基本概念,它是集合论的研究对象,集合论的基本理论直到19世纪才被创立.最简单 ...
- Android 之XML数据解析(2)—— SAX解析
(以下文章基本照抄郭霖大神的<第一行代码>) 在Android之 解析XML文件(1)—— Pull解析 中我们讲了Pull方式解析XML文件.今天讲另外一种方式,SAX解析XML文件. ...
- scrapy抓取拉勾网职位信息(八)——使用scrapyd对爬虫进行部署
上篇我们实现了分布式爬取,本篇来说下爬虫的部署. 分析:我们上节实现的分布式爬虫,需要把爬虫打包,上传到每个远程主机,然后解压后执行爬虫程序.这样做运行爬虫也可以,只不过如果以后爬虫有修改,需要重新修 ...
- 二进制拆位(贪心)【p2114】[NOI2014]起床困难综合症
Description 21世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm一直坚持与起床困难综合症作斗争.通过研究相关文献,他找到了 ...
- PlayMaker的Transition和Global Transition
PlayMaker的Transition和Global Transition 在PlayMaker中,Transition是指从一个状态(State)过渡到另外一个状态.它由事件(Event)实现 ...
- urllib2 调用salt restapi
1获取token #_*_coding:utf8_*_ import urllib2 import json def get_token(): url='http://10.20.32.86:8000 ...
- 【BZOJ 3747】 3747: [POI2015]Kinoman (线段树)
3747: [POI2015]Kinoman Time Limit: 60 Sec Memory Limit: 128 MBSubmit: 830 Solved: 338 Description ...
- BZOJ4552 HEOI2016排序
太棒了!思路很不错. 没想到HEOID1三道线段树. 这题我们可以二分答案,将小于他的在线段树中设成0,大于他的设成1然后模拟操作复杂度O(mlog^2n) By:大奕哥 #include<bi ...
- fpdf中文乱码,添加字符集
中文乱码 引入Olivier的chinese.php(点击下载) 支持中文,其中有Big5,GB两种 使用方法也很简单 $pdf->AddBig5Font(); $pdf->SetFont ...