moneret我们相爱吧里面的歌曲所有歌曲

RetConStruct的歌_RetConStruct经典歌曲_RetConStruct最好听的歌 - 虾米音乐
Loading...
RetConStruct的热门歌曲TOP100
关注虾米:汇聚2000万达人的兴趣社区下载即送20张免费照片冲印
扫码下载App
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
这里面我们需要移植两个驱动和一个Madplay应用程序,当然播放主程序需要我们自己来写。Madplay和声卡移植可见相关章节,这里只说一下按键驱动,其实是很简单的一个杂项字符驱动,但是通过我的调试,发现按键去斗是关键,不然,按键时很容易得不到自己想要的结果,这里给出我自己修改过的按键驱动。
& #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& #include &linux/sched.h& #include &linux/gpio.h& static struct timer_list buttons_#define DEVICE_NAME&&&&&&&&&&&& "button" //设备名称 /*定义中断所用的结构体*/ struct button_irq_desc { &&&& //按键对应的中断号 &&&& //按键所对应的GPIO 端口 &&&& int pin_ //按键对应的引脚描述,实际并未用到,保留 &&&& //定义键值,以传递给应用层/用户态 &&&& char *&&& //每个按键的名称 }; /*结构体实体定义*/ static struct button_irq_desc button_irqs [] = { &&&& {IRQ_EINT8 , S3C2410_GPG(0) ,&&&&&&&& S3C2410_GPG0_EINT8&&&&&&&& , 0, "KEY0"}, &&&& {IRQ_EINT11, S3C2410_GPG(3) ,&&&&&&&& S3C2410_GPG3_EINT11 , 1, "KEY1"}, &&&& {IRQ_EINT13, S3C2410_GPG(5) ,&&&&&&&& S3C2410_GPG5_EINT13 , 2, "KEY2"}, &&&& {IRQ_EINT14, S3C2410_GPG(6) ,&&&&&&&& S3C2410_GPG6_EINT14 , 3, "KEY3"}, &&&& {IRQ_EINT15, S3C2410_GPG(7) ,&&&&&&&& S3C2410_GPG7_EINT15 , 4, "KEY4"}, &&&& {IRQ_EINT19, S3C2410_GPG(11),&&&&&&&&& S3C2410_GPG11_EINT19, 5, "KEY5"}, }; /*开发板上按键的状态变量,注意这里是’0’,对应的ASCII 码为 30*/ static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'}; static struct button_irq_desc *irq_/*因为本驱动是基于中断方式的,在此创建一个等待队列,以配合中断函数使用;当有按键按下并读取到键 值时,将会唤醒此队列,并设置中断标志,以便能通过& read 函数判断和读取键值传递到用户态;当没有按 键按下时,系统并不会轮询按键状态,以节省时钟资源*/ static DECLARE_WAIT_QUEUE_HEAD(button_waitq); /* 中断标识变量,配合上面的队列使用,中断服务程序会把它设置为1,read 函数会把它清零*/ static volatile int ev_press = 0; static irqreturn_t buttons_interrupt(int irq, void *dev_id){&/* 10ms后启动定时器 */&/*&原理当触发中断的时候,进入此函数,然后修改定时器的值10ms后&去执行定时器指定的函数,读取键值&*/&irq_pd = (struct button_irq_desc *)dev_//这里为参数传递,因为&//buttons_timer_function里没法得到传入引脚值&mod_timer(&buttons_timer, jiffies+HZ/100);&return IRQ_RETVAL(IRQ_HANDLED);}static void buttons_timer_function(unsigned long data){&&& struct button_irq_desc *button_irqs = irq_& &&/*获取被按下的按键状态*/ &&down = !s3c2410_gpio_getpin(button_irqs-&pin); &&& /*状态改变,按键被按下,从这句可以看出,当按键没有被按下的时候,寄存器的值为 1(上拉),但按 &键被按下的时候,寄存器对应的值为 0*/ &//经典 这句话,可以判断按下与弹起中断&&if (down != (key_values[button_irqs-&number] & 1)) { // Changed &&&/*如果key1 被按下,则key_value[0]就变为’1’,对应的ASCII 码为 31*/ && key_values[button_irqs-&number] = '0' + &&&& ev_press = 1; /*设置中断标志为 1*/ &&& wake_up_interruptible(&button_waitq); /*唤醒等待队列*/ &&} &}/* *在应用程序执行open(“/dev/buttons”,…)时会调用到此函数,在这里,它的作用主要是注册 6 个按键的中断。 *所用的中断类型是IRQ_TYPE_EDGE_BOTH,也就是双沿触发,在上升沿和下降沿均会产生中断,这样做 是为了更加有效地判断按键状态 */ static int s3c24xx_buttons_open(struct inode *inode, struct file *file) { && && int err = 0; && for (i = 0; i & sizeof(button_irqs)/sizeof(button_irqs[0]); i++) { &&& if (button_irqs[i].irq & 0) { &&&& &&& } &&&& /*注册中断函数*/ &&&& err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH, &&&&&&&&&button_irqs[i].name, (void *)&button_irqs[i]); &&&& if (err) &&&& && } && if (err) { &&&& /*如果出错,释放已经注册的中断,并返回*/ &&&& i--; &&&& for (; i &= 0; i--) { &&&& if (button_irqs[i].irq & 0) { &&&& &&&& } &&&& disable_irq(button_irqs[i].irq); &&&& free_irq(button_irqs[i].irq, (void *)&button_irqs[i]); &&&& } &&&& return -EBUSY; && } && /*注册成功,则中断队列标记为 1,表示可以通过read 读取*/ && ev_press = 1; && /*正常返回*/ && return 0; } /* *此函数对应应用程序的系统调用close(fd)函数,在此,它的主要作用是当关闭设备时释放6 个按键的中断* 处理函数 */ static int s3c24xx_buttons_close(struct inode *inode, struct file *file) { & & for (i = 0; i & sizeof(button_irqs)/sizeof(button_irqs[0]); i++) { && if (button_irqs[i].irq & 0) { &&&& && } & /*释放中断号,并注销中断处理函数*/ && free_irq(button_irqs[i].irq, (void *)&button_irqs[i]); & } & del_timer( &buttons_timer);& return 0; } /* *对应应用程序的read(fd,…)函数,主要用来向用户空间传递键值 */ static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { & && if (!ev_press) { && if (filp-&f_flags & O_NONBLOCK) &&&& /*当中断标识为0 时,并且该设备是以非阻塞方式打开时,返回*/ &&&& return -EAGAIN; && else &&&/*当中断标识为0 时,并且该设备是以阻塞方式打开时,进入休眠状态,等待被唤醒*/ &&&& wait_event_interruptible(button_waitq, ev_press); & } & /*把中断标识清零*/ & ev_press = 0; && /*一组键值被传递到用户空间*/ & err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count)); &&& return err ? -EFAULT : min(sizeof(key_values), count); } && static unsigned int s3c24xx_buttons_poll( struct file *file, struct poll_table_struct *wait) { && unsigned int mask = 0; && /*把调用poll 或者select 的进程挂入队列,以便被驱动程序唤醒*/ && poll_wait(file, &button_waitq, wait); && if (ev_press) && mask |= POLLIN | POLLRDNORM; && } /*设备操作集*/ 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) { & &init_timer(&buttons_timer);&buttons_timer.function = buttons_timer_&//buttons_timer.expires& = 0;&add_timer(&buttons_timer); && /*把按键设备注册为misc 设备,其设备号是自动分配的*/ &ret = misc_register(&misc); &printk (DEVICE_NAME"\tinitialized\n"); & } /*注销设备*/ static void __exit dev_exit(void) { & misc_deregister(&misc); } module_init(dev_init); //模块初始化,仅当使用insmod/podprobe 命令加载时有用,如果设备不是通过模块方 郊釉兀舜换岜坏饔?module_exit(dev_exit); //卸载模块,当该设备通过模块方式加载后,可以通过rmmod 命令卸载,将调用此函数 &&&MODULE_LICENSE("GPL");//版权信息 MODULE_AUTHOR("FriendlyARM Inc.");//作者名字 &其次,重要的就是播放主程序,这其中需要注意的又有几问题,怎么寻找不同目录下的mp3,找到后又应该怎么去播放。如/Music/silu.mp3,如果你直接madplay silu.mp3则播放不了,原因是找不到路径。而且我们应该搜索根目录下的两级目录,以查找全部的mp3文件,最终列成播放列表的时候则不应该加有路径。现结合程序分析。 #include &stdio.h&#include &unistd.h&#include &dirent.h&#include &sys/types.h&#include &stdlib.h&#include &errno.h&#include &string.h&#include &sys/ioctl.h&#include &sys/stat.h&#include &fcntl.h&#include &sys/select.h&#include &sys/time.h&#include &signal.h&#include &sys/wait.h&#include &sys/shm.h&#include &sys/ipc.h&#define MAX 40#define WORD 40int len=0;char name[MAX][WORD];typedef struct list_node{&&& char s_name[WORD];&&& struct list_node *&&& struct list_node *}node,*struct share{&long id_&char name_tmp[WORD];};&char buf[50]="/";&char *mulu[10]={NULL};&int num = 0;&/* 创建双向循环链表,将歌曲添加入链表中 */ pnode create_list(char para[][40],int n)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& {&&pnode head = NULL;&pnode new = NULL;&&&&&&&&&&&& &pnode tmp = NULL;&&& &&& head = (pnode)malloc(sizeof(node));&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&& if(head == NULL){&&&&&&& perror("malloc");&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&& exit(EXIT_FAILURE);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&& }&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&head-&next = NULL;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&& head-&prev = NULL;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &strcpy(head-&s_name,para[0]);&&tmp =&for(i=1; i&n; i++){&&new = (pnode)malloc(sizeof(node));&&if(new == NULL){&&&perror("malloc");&&&exit(EXIT_FAILURE);& &&}&&strcpy(new-&s_name,para[i]);&&tmp-&next =&&new-&prev =&&new-&next = NULL;&&tmp =&}&head-&prev =&tmp-&next =&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& }/* 遍历链表,返回当前播放歌曲所对应的节点 */pnode search_list(pnode head,char para[]){&pnode tmp = NULL;&tmp = head-&&&if(strcmp(head-&s_name,para) == 0){&&&}&else{&&&while(tmp != head)&&{&&&&if (strcmp(tmp-&s_name, para) == 0){&&&& &&&&&}&&&else {&&&&tmp= tmp-&&&&}&&}&}&return NULL;}/* 打印双向链表每个节点的值 */void print_list(pnode head){&char *temp=NULL;&&pnode tmp =&do{&&for(i = 0 ; i & i++)&&{&&&if((temp = strstr(tmp-&s_name, mulu[i])) != NULL)//扫描看一下MP3文件是否带有路径&&&&{&&&&&printf("%s\n",temp+strlen(mulu[i]) + 1);//有路径的话,去掉路径不显示而只显示MP3文件名&&&&&goto N//这里如果确实发现带路径的文件的话,直接跳过到下一首歌的测试&&&}&&}&&&//else&&//{&&&printf("%s\n",tmp-&s_name); //执行到这,表明这个MP3文件是不带路径的&&//&&&//}&&Next:&&tmp = tmp-&&}while(tmp != head);}void play(int mem_id,pnode para){&pnode node_&void *shmadd=(void *)0;&struct share *share_&&node_tmp = para-&&while(1)&{&&node_tmp = node_tmp-& //孙子进程循环播放&&if(fork() == 0){
//这里孙子进程,可不可以不要呢,咋一看,好像可以,但绝不可以,不行可试一下:结果会是播放完一首歌后&&&/* 映射共享内存 */
//将不会播放下一首,为什么会这样呢,原来execlp的原理是替换掉了原来调用它的进程进行播放,因此播放
//完一首歌后,play这个进程就被替换结束了,并不会去循环播放下一首,于是,创建孙子进程后,它跟子进程的关系是,当等待孙子进程播放完后,子进程运行,循环到下一首歌,再通过创建新孙子进程,来播放下一首歌。&&&if ((shmadd = shmat(mem_id, (void *)0, 0)) == NULL){&&&&if (shmctl(mem_id, IPC_RMID, NULL) == -1)&&&&&perror("Failed to& remove memory segment");&&&&exit(EXIT_FAILURE);&&&}&&&&/* 将ID和歌曲名信息存入共享内存 */&&&//孙子进程获取正在播放的歌曲和孙子进程ID&&&share_para = (struct share *)&&&strcpy(share_para-&name_tmp, node_tmp-&s_name);&&&share_para-&id_tmp = getpid();&&&///////////&&&if(execlp("madplay","madplay",node_tmp-&s_name,NULL)&0)&&&{&&&&perror("execlp ");&&&}&&&}&&else&&&wait(NULL);//等待子进程先执行完&}&}/*寻找多级目录下的mp3文件的函数,这里只实现两级目录*/int trave_dir(char* path, int depth){&&& DIR *d; //声明一个句柄&&& struct dirent * //readdir函数的返回值就存放在这个结构体中&&&& &&static char *temp=NULL;&static char *new_path="/";&static char *old_path="/";&&&& if(!(d = opendir(path)))&&& {&&&&&&& printf("error opendir %s!!!/n",path);&&&&&&& return -1;&&& }&if((depth-1) == 1) //说明进入了二级目录,记录目录路径&&temp=&else
//根目录不记录路径&&temp = NULL;&&& while((file = readdir(d)) != NULL)&&& {&&&&&&& //把当前目录.,上一级目录..及隐藏文件都去掉,避免死循环遍历目录&&&&&&& if(strncmp(file-&d_name, ".", 1) == 0)&&&&&&&&&&&&&if((file-&d_type == 8) && (strstr(file-&d_name,".mp3")) != NULL)&&{&&&if(temp != NULL && (depth-1) == 1) //这里面的大体意思是寻找到mp3文件后要给其加上路径,以便madplay能正确播放&&&{&&&&new_path =&&&&if(strcmp(new_path,old_path) != 0)//前后两次目录名不同才存入,也就说只存新找到并含mp3的目录&&&&&mulu[num++]=new_ //存入找到的含mp3文件的目录,以便在显示全部播放列表的时候,再去除对目录的显示&&&&strcat(buf,temp);&&&&strcat(buf,"/");//拼接完全路径并存入音乐名数组&&&&strcat(buf,file-&d_name);&&&&strcpy(name[len++], buf);&&&&for(i=0;i&50;i++)&&&&&buf[i]=0;&&&&buf[0]='/';&&&&old_path = new_&&&}&&&else&&&&strcpy(name[len++], file-&d_name); //保存遍历到的文件名&&}&&&&&&& //判断该文件是否是目录,及是否已搜索了两层,这里我定义只搜索了两层目录,太深就不搜了,省得搜出太多文件&&&&&&& if(stat(file-&d_name, &sb) == 0 && S_ISDIR(sb.st_mode) && depth &= 1)&&&&&&& {&&&&&&&&&&& trave_dir(file-&d_name, depth + 1);//递归调用&&&&&&& }&&& }&&& closedir(d);&&& return 0;}int main(int argc, char *argv[]){&int buttons_&&&& char *p=NULL;&int i=0,j;&static int key_flag1=1,key_flag2=1;& &&fd_&&&char key_value[6];& //&char key_&&&&&& //& &int id_&char next_name[WORD];&char prev_name[WORD];&struct share *share_&int memory_&pnode node_&void *shmadd=(void *)0;&&buttons_fd = open("/dev/button", 0);&if (buttons_fd & 0) {&&perror("open device buttons");&&exit(EXIT_FAILURE);& &}&trave_dir("/", 1);&printf("带路径的音乐文件\n");&for(j = 0;j&j++)&printf("%s\n",name[j]);&printf("有音乐的目录\n");&for(j = 0;j&j++)&printf("%s\n",mulu[j]);&head = create_list(name,len);&&printf("取消路径的音乐播放列表\n");&print_list(head);&&/* 父进程中使用共享内存,获取孙子进程中记录的进程ID和当前歌曲名 */&if ((memory_id = shmget(IPC_PRIVATE, sizeof(struct share), IPC_CREAT|0666)) == -1){&&perror("Failed to create shared memory segment");&&exit(EXIT_FAILURE);&}&&if ((shmadd = shmat(memory_id, (void *)0, 0)) == NULL){&&perror("shmat");//删除共享内存段&&if (shmctl(memory_id, IPC_RMID, NULL) == -1)&&&perror("Failed to& remove memory segment");&&exit(EXIT_FAILURE);&}&&share_tmp = (struct share *)&&printf("\nOperations Description \n");&printf("K1 --------start/stop\n");&printf("K2 --------pause/continue\n");&printf("K4 --------previous\n");&printf("K5 --------next\n");&&for (;;) {&&&&FD_ZERO(&rds);&&FD_SET(buttons_fd, &rds);&&/* 监测按键的变化 */&&ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);&&if (ret & 0) {&&&perror("select");&&&exit(EXIT_FAILURE);& &&}&&if (ret == 0) {&&&printf("Timeout.\n");&&}&&else if (FD_ISSET(buttons_fd, &rds)) {
//按键值确实有变化&&&&&&/* 读取按键的值到数组中 */&&&ret = read(buttons_fd, &key_value, sizeof(key_value));&&&if(ret != sizeof(key_value)){& //6&&&&if(errno != EAGAIN){&&&&&printf("read button device failed!\n");&&&&}&&&&&&&}&&&else{&&&/*&&for(i=0; i&6; i++)&&&&&{&&&&&printf("key%d=%d\n",i+1,key_value[i]-'0');&&&&&printf("key_tmp=%d\n",key_tmp);&&&&&&} */&&&&for(i=0; i&6; i++){&&&&&if(key_value[i] == '1'){&&&&&&/* 记录按键值 */&&&&&&key_tmp = i+1;&&&&&}&&&&}&&&}&&}&&&&&&&/*--------------------------------------start------------------------------------*/&&&&if(key_tmp == 1){&&&key_tmp = 0;&&&if(key_flag1 == 1){&&&&&printf("start to play\n");&&&&id_test = fork();&&&&&&&&//该子进程控制循环播放,当一首歌曲播放完成后,创建一个新的孙子进程来播放 &&&&if(id_test == 0){&&&&&play(memory_id,head);&&&&}&&&&else if(id_test &0){&&&&&&&&&}&&&}&&&else{&&&&&printf("stop playing\n");&&&&&kill(share_tmp-&id_tmp,SIGKILL);&&&&&&kill(id_test,SIGKILL);&&&&&exit(0);&&&&}&&&key_flag1 = 2;&&&printf("key_flag1 = %d\n",key_flag1);&&}&&&&&& /*--------------------------------------------------------------------------------*/&&&&if(key_tmp == 2){&& //pause&&&key_tmp = 0;&&&if(key_flag2 == 1)&&&{&&&&printf("pause playing\n");&&&&kill(share_tmp-&id_tmp, SIGSTOP);&&&&key_flag2 = 2;&&&}&&&else&&&{&&&&printf("continue to play\n");&&&&kill(share_tmp-&id_tmp,SIGCONT);&&&&key_flag2 = 1;&&&}&&}&&&&&&&& /*--------------------------------------next------------------------------------*/&&&&if(key_tmp == 4){&& //next&&&&key_tmp = 0;&&&printf("the next song\n");&&&/* kill 原来的子进程和孙子进程 */&&&kill(share_tmp-&id_tmp,SIGKILL);&&&kill(id_test,SIGKILL);&&&&&&strcpy(next_name, share_tmp-&name_tmp);&&&/* 获取原孙子进程歌曲名在链表中的位置 */&&&node_tmp = search_list(head,next_name);&&&if(node_tmp == NULL){&&&&printf("only one song \n");&&&}&&&&else{&&&&/* 节点后移一位 */&&&&node_tmp = node_tmp-&&&&}&&&//重新开启进程播放&&&id_test = fork();&&&&&&if(id_test == 0){&&&& play(memory_id,node_tmp);&&&}&&&else if(id_test &0){&&&}&&}&&&&&& /*------------------------------------------------------------------------------*/&&&&&&&&&&/*------------------------------------------------------------------------------*/&&&&if(key_tmp == 5){& //prev&&&key_tmp = 0;&&&printf("the prev song\n");&&&kill(share_tmp-&id_tmp,SIGKILL);&&&&kill(id_test,SIGKILL);&&&strcpy(prev_name,share_tmp-&name_tmp);&&& &&&node_tmp = search_list(head, prev_name);&&&if(node_tmp == NULL){&&&&printf("only one song \n");&&&}&&&&else{&&&&/* 节点前移一位 */&&&&node_tmp = node_tmp-&&&&}&&&id_test=fork();&&&if(id_test == 0){&&&&&&&&&&&&&&&&&&&&&& play( memory_id,node_tmp);&&&}&&&else if(id_test & 0){&&&}&&}&&}&/*------------------------------------------------------------------------------*/&&&close(buttons_fd);&return 0;}下面来简单总结一下上面的程序:1、进程创建与使用
本程序中使用了三级进程,父进程,子进程与孙子进程。父进程即是主程序体,子进程用于循环播放,当播放完一曲后,播放下一首,在子进程中创建了孙子进程调用madplay进程实际的播放并与父进程一起共享进程ID和歌曲名。
现在分析进程与进程之间的关系:父与子,为什么要有两个进程呢,答案:创建子进程开始播放歌曲,父进程要在主函数中扫描按键值;而且子进程是while(1)的死循环,如果不创建子进程,CPU就不能在父子之间调度,那么当执行到循环播放程序段时,将永远不返回。有了父子进程,CPU可以通过调度算法,使得两个进程都得到运行。
那么子进程与孙子进程的关系呢?可不可以不要孙子进程呢,答案是不可以的,如果不在子进程中创建新的孙子进程,那么当播放完一首歌后,将不会播放下一首。原因是execlp调用madplay的原理的替换原进程的思想,而创建了孙子进程后,当其播放完一首歌时,子进程循环到下一首歌,并再次创建另一新孙子进程去播放得到的下一首歌。这样可以使得歌曲得到不断的循环播放。
最后,播放的暂停、继续、下一首、上一首的信号使用也值得关注下。 接着,说一下,音乐文件的扫描,我这里主要用了个递归函数,通过扫描根目录“/”和根下目录的两级扫描法,得到总的MP3文件。得到后将其加入双循环链表,当然,如果音乐文件不在根目录下,是根目录下的二级目录中的文件的话,会有一段拼接上路径的小代码,好,那么实际应用中要想查看完整的播放列表时,却不需要把路径显示出来,那么这时在显示时,需要将路径部分隐去不显示,实质双循环链表中是加有路径的。下面为运行结果:[root@lyl/]#./final_mp31带路径的音乐文件/Music/silu.mp3zaijianlixiang.mp3/MP3/dongfengpo.mp3/MP3/aidedaijia.mp3/MP3/anjing.mp3qiuniao.mp3有音乐的目录MusicMP3取消路径的音乐播放列表silu.mp3zaijianlixiang.mp3dongfengpo.mp3aidedaijia.mp3anjing.mp3qiuniao.mp3Operations DescriptionK1 --------start/stopK2 --------pause/continueK4 --------previousK5 --------nextstart to playkey_flag1 = 2MPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.pause playingcontinue to playthe prev songMPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.the prev songMPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 安静&&&&&&&& Artist: 周杰伦&&&&&&&&& Album: 范特西&&&&&&&&& Track: 10&&&&&&&&&& Year: 2001&&&&&&&&& Genre: R&B&&&&&&& Comment: error: frame 0: lost synchronizationthe prev songMPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 爱的代价&&&&&&&& Artist: 李宗盛&&&&& Orchestra: 群星&&&&&&&&& Album: 原汁原味-亚洲创作人原曲汇萃&&&&&&&&& Track: 13&&&&&&&&& Genre: 流行音乐&&&&&&& Comment: the next songchild ID:1119grandson ID:1120MPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 安静&&&&&&&& Artist: 周杰伦&&&&&&&&& Album: 范特西&&&&&&&&& Track: 10&&&&&&&&&& Year: 2001&&&&&&&&& Genre: R&B&&&&&&& Comment: error: frame 0: lost synchronizationthe next songchild ID:1121grandson ID:1122MPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.the prev songMPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 安静&&&&&&&& Artist: 周杰伦&&&&&&&&& Album: 范特西&&&&&&&&& Track: 10&&&&&&&&&& Year: 2001&&&&&&&&& Genre: R&B&&&&&&& Comment: error: frame 0: lost synchronizationthe prev songMPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 爱的代价&&&&&&&& Artist: 李宗盛&&&&& Orchestra: 群星&&&&&&&&& Album: 原汁原味-亚洲创作人原曲汇萃&&&&&&&&& Track: 13&&&&&&&&& Genre: 流行音乐&&&&&&& Comment: the prev songMPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 东风破&&&&&&&& Artist: 周杰伦&&&&&&&&& Album: 叶惠美&&&&&&&&& Track: 5&&&&&&&&&& Year: 2003&&&&&&&&& Genre: Poperror: frame 0: lost synchronizationthe prev songMPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 再见理想&&&&&&&& Artist: Beyond(黄家驹)&&&&&&&&& Album: 音乐殿堂MusicPalace&&&&&&& Comment: the next songchild ID:1131grandson ID:1132MPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 东风破&&&&&&&& Artist: 周杰伦&&&&&&&&& Album: 叶惠美&&&&&&&&& Track: 5&&&&&&&&&& Year: 2003&&&&&&&&& Genre: Poperror: frame 0: lost synchronizationthe next songchild ID:1133grandson ID:1134MPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 爱的代价&&&&&&&& Artist: 李宗盛&&&&& Orchestra: 群星&&&&&&&&& Album: 原汁原味-亚洲创作人原曲汇萃&&&&&&&&& Track: 13&&&&&&&&& Genre: 流行音乐&&&&&&& Comment: the next songchild ID:1135grandson ID:1136MPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 安静&&&&&&&& Artist: 周杰伦&&&&&&&&& Album: 范特西&&&&&&&&& Track: 10&&&&&&&&&& Year: 2001&&&&&&&&& Genre: R&B&&&&&&& Comment: error: frame 0: lost synchronizationthe next songchild ID:1137grandson ID:1138MPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.the next songchild ID:1139grandson ID:1140MPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.the next songchild ID:1141grandson ID:1142MPEG Audio Decoder 0.15.2 (beta) - Copyright (C)
Robert Leslie et al.&&&&&&&&& Title: 再见理想&&&&&&&& Artist: Beyond(黄家驹)&&&&&&&&& Album: 音乐殿堂MusicPalace&&&&&&& Comment: stop playing测试结果运行良好!
阅读(878)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'嵌入式mp3',
blogAbstract:'首先,要弄明白框架:
这里面我们需要移植两个驱动和一个Madplay应用程序,当然播放主程序需要我们自己来写。Madplay和声卡移植可见相关章节,这里只说一下按键驱动,其实是很简单的一个杂项字符驱动,但是通过我的调试,发现按键去斗是关键,不然,按键时很容易得不到自己想要的结果,这里给出我自己修改过的按键驱动。
& #include &linux/module.h& #include &linux/kernel.h& #include &linux/fs.h& #include &linux/init.h& ',
blogTag:'mp3,madplay,多级目录,多进程',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:3,
publishTime:6,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}}

我要回帖

更多关于 情歌王里面的所有歌曲 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信