呵呵
分类: LINUX
2012-10-23 21:07:45
一.准备
移植Madplay所需四个软件包分别为libid3tag-0.15.1b.tar.gz,
libmad-0.15.1b.tar.gz,zlib-1.1.4.tar.gz,madplay-0.15.2b.tar.gz
二.解压
1.mkdir /mp3 建立MP3目录
2. tar -zxvf libid3tag-0.15.1b.tar.gz -C /mp3
3. tar -zxvf ibmad-0.15.1b.tar.gz -C /mp3
4. tar -zxvf zlib-1.1.4.tar.gz -C /mp3
5. tar -zxvf madplay-0.15.2b.tar.gz -C /mp3
三.编译zlib
#cd /mp3/zlib-1.1.4
#./configure --prefix=/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/lib
修改Makefile
AR=/usr/local/arm/4.3.2/bin/arm-linux-ar rcs
CC=/usr/local/arm/4.3.2/bin/arm-linux-gcc
RANLIB=/usr/local/arm/4.3.2/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/4.3.2/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/4.3.2/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下到板子就可以了.
1.下载地址
2. tar xxvf MPlayer-1.1.tar.xz
cd MPlayer-1.1
3. 修改./configure 文件的
4./configure –cc=mipsel-unknown-linux-gnu-gcc –prefix=/nfsboot/mips/ –target=mipsel-unknown-linux –as=mipsel-unknown-linux-gun-as –extra-cflags=-march=mips2
make
make install
mplayer移植到mips上
2592 _install_strip="-s"
为
2592 #_install_strip="-s"
2593 _install_strip=
应用程序:
/*
* 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/song/";
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]='\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,0,0);
/*把孙子进程的id和当前播放歌曲的节点指针传入共享内存*/
memcpy(c_addr,&fd,sizeof(pid_t));
memcpy(c_addr + sizeof(pid_t)+1,¤tsong,4);
/*使用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;
while((size = getline(&line,&len,fd)) != -1)
{
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();
if(pid > 0)
{
*childpid = pid;
play_flag = 1;
sleep(1);
/*把孙子进程的pid传给父进程*/
memcpy(&gradchild,p_addr,sizeof(pid_t));
}
else if(0 == 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 = 0;
}
/*************************************************
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=1;
}
/*************************************************
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=1;
}
/*************************************************
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 + sizeof(pid_t)+1,4);
/*指向下首歌曲的节点*/
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 + sizeof(pid_t)+1,4);
/*指向上首歌曲的节点*/
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("/dev/buttons", 0);
if (buttons_fd < 0) {
perror("open device buttons");
exit(1);
}
/*创建播放列表*/
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,播放列表位置*/
if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)
exit(1);
p_addr = shmat(shmid,0,0);
memset(p_addr,'\0',1024);
while(1)
{
fd_set rds;
int ret;
FD_ZERO(&rds);
FD_SET(buttons_fd, &rds);
/*监听获取键值*/
ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);
if (ret < 0)
{
perror("select");
exit(1);
}
if (ret == 0)
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)
{
case 0:
startplay(&pid,head);
first_key=0;
break;
case 1:
case 2:
case 3:
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)
{
case 0:
//printf("play_flag:%d\n",play_flag);
if(play_flag)
my_pause(gradchild);
else
conti_play(gradchild);
break;
case 1:
my_stop(gradchild);
break;
case 2:
next(gradchild);
break;
case 3:
prev(gradchild);
break;
} //end switch
}//end if(!first_key)
}
}
}
close(buttons_fd);
return 0;
}
驱动程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 , 0, "KEY0"},
{IRQ_EINT11, S3C2410_GPG3 , S3C2410_GPG3_EINT11 , 1, "KEY1"},
{IRQ_EINT13, S3C2410_GPG5 , S3C2410_GPG5_EINT13 , 2, "KEY2"},
{IRQ_EINT14, S3C2410_GPG6 , S3C2410_GPG6_EINT14 , 3, "KEY3"},
{IRQ_EINT15, S3C2410_GPG7 , S3C2410_GPG7_EINT15 , 4, "KEY4"},
{IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, "KEY5"},
};
#else /* means QQ */
static struct button_irq_desc button_irqs [] = {
{IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 0, "KEY0"},
{IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG3_EINT11, 1, "KEY1"},
{IRQ_EINT2, S3C2410_GPF2, S3C2410_GPF2_EINT2, 2, "KEY2"},
{IRQ_EINT0, S3C2410_GPF0, S3C2410_GPF0_EINT0, 3, "KEY3"},
{ -1, -1, -1, 4, "KEY4"},
{ -1, -1, -1, 5, "KEY5"},
};
#endif
//static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'};
static int key_values = 0;
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static volatile int ev_press = 0;
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 = 1;
wake_up_interruptible(&button_waitq);
}
else {
//printk("falling\n");
ev_press = 0;
return 0;
}
return IRQ_RETVAL(IRQ_HANDLED);
}
static int s3c24xx_buttons_open(struct inode *inode, struct file *file)
{
int i;
int err = 0;
for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
if (button_irqs[i].irq < 0) {
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--;
for (; i >= 0; i--) {
if (button_irqs[i].irq < 0) {
continue;
}
disable_irq(button_irqs[i].irq);
free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
}
return -EBUSY;
}
ev_press = 0;
return 0;
}
static int s3c24xx_buttons_close(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {
if (button_irqs[i].irq < 0) {
continue;
}
free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);
}
return 0;
}
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 = 0;
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 int mask = 0;
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.");