嵌入式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号电池是我自己的,是为了对比一 ...
随机推荐
- Jmeter------将JDBC Request的查询结果作为另一个接口的请求参数
一.前言 jmeter已配置连接成功数据库,不会的可查看:https://www.cnblogs.com/syw20170419/p/9832402.html 二.需求 将JDBC Request的r ...
- ssh客户端乱码
export LC_ALL=zh_CN.GB2312;export LANG=zh_CN.GB2312
- GUC-3 模拟CAS算法
/* * 模拟 CAS 算法 */ public class TestCompareAndSwap { public static void main(String[] args) { final C ...
- ubuntu sublime text 3 集成 nodejs 插件
下载nodejs插件地址:https://github.com/tanepiper/SublimeText-Nodejs 解压重命名文件夹为Nodejs打开sublime text : prefere ...
- oracle 内连接、外连接、自然连接、交叉连接练习
oracle 内连接.外连接.自然连接.交叉连接练习 --查询员工信息 select * from emp; --查询部门信息 select * from dept; --需求:查询员工姓名.薪资和所 ...
- 【转】Vue v-bind与v-model的区别
v-model 指令在表单控件元素上创建双向数据绑定,所谓双向绑定,指的就是我们在js中的vue实例中 的data与其渲染的dom元素上的内容保持一致,两者无论谁被改变,另一方也会相应的更新为相同的数 ...
- 洛谷P2231 [HNOI2002]跳蚤 [数论,容斥原理]
题目传送门 跳蚤 题目描述 Z城市居住着很多只跳蚤.在Z城市周六生活频道有一个娱乐节目.一只跳蚤将被请上一个高空钢丝的正中央.钢丝很长,可以看作是无限长.节目主持人会给该跳蚤发一张卡片.卡片上写有N+ ...
- 二进制拆位(贪心)【p2114】[NOI2014]起床困难综合症
Description 21世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm一直坚持与起床困难综合症作斗争.通过研究相关文献,他找到了 ...
- Java中的强引用,软引用,弱引用
作者:winterSunshine链接:https://www.zhihu.com/question/37401125/answer/100981172来源:知乎著作权归作者所有.商业转载请联系作者获 ...
- Vue.js 系列教程 3:Vue
原文:intro-to-vue-3-vue-cli-lifecycle-hooks 译者:nzbin 这是 JavaScript 框架 Vue.js 五篇教程的第三部分.在这一部分,我们将学习 Vue ...