分四部分:按键驱动,声卡驱动,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 + ,&currentsong,);
            /*使用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播放器的更多相关文章

  1. 基于Stm32的MP3播放器设计与实现

    原创博文,转载请注明出处 这是我高级电子技术试验课做的作业,拿来共享一下.项目在安福莱例程基础之上进行的功能完善,里面的部分内容可参考安福莱mp3例程.当然用的板子也是安福莱的板子,因为算起来总共做了 ...

  2. C# wave mp3 播放器探寻

    C# wave mp3 播放器探寻   最近无聊,想听听歌曲.可怜新电脑上歌曲就两三首,要听其它的就得在旧电脑上播放.可是,那台古董但不失健壮的本本被老婆无情的霸占了.无奈. 思来想去,得,写个程序播 ...

  3. MP3播放器团队项目

    一.设计思路 程序要求能播放MP3文件,因此需调用库中的播放方法:右键工具箱选择项,添加com组件,选择window media player后工具箱就会多一个控件,然后拖到窗体中就OK了.另在窗体中 ...

  4. 你也可以用java的swing可以做出这么炫的mp3播放器_源码下载

    I had published the blog : 你用java的swing可以做出这么炫的mp3播放器吗? and to display some screenshots about this M ...

  5. 你用java的swing可以做出这么炫的mp3播放器吗?

    这个mp3播放器是基于java的swing编写的,我认为界面还是可以拿出来和大家看一看评一评. 先说说创作的初衷,由于前段时间工作不是很忙,与其闲着,还不如找一些东西来给自己捣腾捣腾,在 之前写的 j ...

  6. MP3播放器的实现

    今天,基本上实现了MP3播放器的基本功能,现在总结一下. 首先,下载服务器端的MP3列表,这里用到了下载技术和解析XML文件技术. 下载参考(http://blog.csdn.net/huim_lin ...

  7. 安卓MP3播放器开发实例(1)之音乐列表界面

    学习安卓开发有一年了,想想这一年的努力,确实也收获了不少.也找到了比較如意的工作. 今天准备分享一个以前在初学阶段练习的一个项目.通过这个项目我真正的找到了开发安卓软件的感觉,从此逐渐步入安卓开发的正 ...

  8. 开源mp3播放器--madplay 编译和移植 简记

    madplay是一款开源的mp3播放器. http://madplay.sourcearchive.com/ 下面简单记录一下madplay的编译与移植到ARM开发板上的过程 一.编译x86版本的ma ...

  9. x宝23大洋包邮的老式大朝华MP3播放器简单评测

    (纯兴趣测评,非广告) 最近逛X宝,看到了这个古董级MP3播放器居然还在售,于是脑抽+情怀泛滥买了一个. 然后呢,从遥远的深圳跨越好几千公里邮过来了这个玩意: 那节南孚5号电池是我自己的,是为了对比一 ...

随机推荐

  1. MVC 之AjaxHelper

    http://www.cnblogs.com/jyan/archive/2012/07/23/2604958.html 除了传统的Ajax方法之外,MVC提供了AjaxHelper类: Helper ...

  2. Roman to Integer & Integer to Roman

    题目: Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from ...

  3. Robot Framework自动化测试的应用

    Robot Framework自动化测试的应用(一) 最近尝试用Robot Framework代替之前全部采用python实现测试case,开始对Robot Framework进行些了解学习. 1. ...

  4. 在LoadRunner中从数组类型的参数随机取值的方法

    在LoadRunner中从数组类型的参数随机取值的方法 使用web_reg_save_param做关联后,有时候会有多个匹配值. 为了模仿用户行为随机取一个值为后续transcation所用,可以使用 ...

  5. QT在windows平台安装使用MInGW编译

    首先,Qt 5.9 的安装包与之前相比,不再区分 VS 版本和 MinGW 版本,而是全都整合到了一个安装包中.因此,与之前的安装包相比,体积也是大了不少,以前是 1G 多,现在是 2G 多. 双击启 ...

  6. 在CentOS7命令行模式下安装虚拟机

    转载:https://blog.csdn.net/sunnyfg/article/details/51493602 1.主机环境描述: 操作系统:CentOS7 系统GUI:无 CPU:Intel4代 ...

  7. jquery控制元素的显示与隐藏

    比如要控制div的显示与隐藏,一句话就搞定了.$("#id").show()表示display:block,$("#id").hide()表示display:n ...

  8. C++ STL 全排列函数详解

    一.概念 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列.当m=n时所有的排列情况叫全排列.如果这组数有n个,那么全排列数为n!个. 比如a ...

  9. windows下eclipse搭建android_ndk开发环境

    安装cygwin: 由于NDK编译代码时必须要用到make和gcc,所以你必须先搭建一个linux环境, cygwin是一个在windows平台上运行的unix模拟环境,它对于学习unix/linux ...

  10. 在Ubuntu下编译hadoop2.5.x

    在Ubuntu下编译hadoop2.5.x 参考博客:http://www.aboutyun.com/thread-8130-1-1.html 1 下载hadoop源码: (1) http://www ...