设计目标:

1 实现基本的音乐播放器功能

2 显示播放列表

3 实现进度条控制音乐

4 歌词显示

功能描述:

列表选歌

播放暂停,快进快退,上下切歌

设置播放模式,播放速度

调节音量、进度条

设计方案:

多线程、互斥锁、条件变量、信号

界面效果:

源码

#include "lvgl/examples/lv_examples.h"
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include<time.h>
#include <semaphore.h>extern pthread_mutex_t mutex_lv;//lvgl线程锁static char local_music_path[]="/root/player/music";//音乐路径
static char local_pic_path[]="/root/player/picture";//图片路径
static char local_words_path[]="/root/player/words";//歌词路径static char music_path[100][1024];//音乐路径
static char pic_path[100][1024];//图片路径
static char words_path[100][1024];//歌词路径
static char words_buf[5*1024]={0};  //放歌词的数组static FILE *fp_mplayer=NULL;   //播放器传回的管道,接收播放进度
static FILE *fp_words=NULL;     //歌词文件
static int fd_mplayer = 0;      //定义管道文件描述符,发送指令给mplayer
static int music_num=0;         //音乐数量
static int music_index=-1;      //当前音乐的下标值,用于寻找上下首static int percent_pos;         //当前播放百分比
static float time_length;       //歌曲长度
static float time_pos;          //当前播放进度static bool list_flag=1;    //开关列表
static bool words_flag=1;    //歌词列表
static bool play_flag=0;    //播放音乐开关
static bool start=0;        //启动,线程读mplayer返回信息static lv_style_t font_style;   //中文
static lv_obj_t *play_mode;     //下拉列表对象,播放模式
static lv_obj_t *speed_obj;     //下拉列表对象,播放速度
static lv_obj_t * music_list;   //列表对象
static lv_obj_t *pic_obj;       //图片对象
static lv_obj_t * volume_slider;  //音量滑条对象
static lv_obj_t * play_slider;  //播放进度条对象static lv_obj_t *title_label;     //图片信息标签
static lv_obj_t *words_label;     //歌词标签
static lv_obj_t * volume_label; //音量标签
static lv_obj_t *time_length_label; //时长标签
static lv_obj_t *time_pos_label; //当前时间标签
static lv_obj_t *words_list;     //歌词标签   pthread_cond_t cond;        //条件变量,用于暂停读取mplayer
pthread_cond_t cond1;
pthread_mutex_t mutex;
pthread_mutex_t mutex1;pthread_t tid_read;         //读mplayer的线程id
pthread_t tid_write;        //写mplayer的线程id//检索本地歌单
void get_music_path()
{//读目录,mp3后缀保存到数组DIR *dirp = opendir(local_music_path);if(dirp==NULL){perror(local_music_path);exit(0);}struct dirent* msg;while(1){msg = readdir(dirp);if(msg == NULL)break;if(msg->d_name[0]=='.')continue;if(strstr(msg->d_name,".mp3")){sprintf(music_path[music_num], "%s/%s", local_music_path, msg->d_name);//拼接图片与歌词路径↓char name[100]={0};strcpy(name,strtok(msg->d_name,"."));sprintf(pic_path[music_num], "S:%s/%s.jpg", local_pic_path, name);sprintf(words_path[music_num], "%s/%s.lrc", local_words_path, name);//拼接图片与歌词路径↑music_num++;puts(music_path[music_num - 1]);}}printf("检索歌单完成 共%d\n",music_num);
}
//检索本地图片
void get_pic_path()
{//读目录,图片后缀保存到数组DIR *dirp = opendir(local_pic_path);if(dirp==NULL){perror(local_pic_path);return;}struct dirent* msg;int pic_num=0;while(1){msg = readdir(dirp);if(msg == NULL)break;if(msg->d_name[0]=='.')continue;if(strstr(msg->d_name,".png")||strstr(msg->d_name,".jpg")){sprintf(pic_path[pic_num++], "S:%s/%s", local_pic_path, msg->d_name);puts(pic_path[pic_num - 1]);}}printf("检索图片完成 共%d\n",pic_num);
}
//检索歌词
void get_words_paht()
{//读目录,lrc后缀保存到数组DIR *dirp = opendir(local_words_path);if(dirp==NULL){perror(local_words_path);return;}struct dirent* msg;int words_num=0;while(1){msg = readdir(dirp);if(msg == NULL)break;if(msg->d_name[0]=='.')continue;if(strstr(msg->d_name,".lrc")){sprintf(words_path[words_num++], "%s/%s", local_words_path, msg->d_name);puts(words_path[words_num - 1]);}}printf("检索歌词完成 共%d\n",words_num);
}//初始化字体风格
void init_font_style()
{/*创建字体*/static lv_ft_info_t info;info.name = "/font/simhei.ttf";//字体位置info.weight = 18;//大小info.style = FT_FONT_STYLE_NORMAL;//风格info.mem = NULL;if(!lv_ft_font_init(&info)) {LV_LOG_ERROR("create failed.");}/*给字体设置样式*/lv_style_init(&font_style);lv_style_set_text_font(&font_style, info.font);lv_style_set_text_align(&font_style, LV_TEXT_ALIGN_CENTER);//lv_obj_add_style(label, &style, 0);
}
//初始化图片的父对象,即图片都在这个对象中显示
void init_pic_parent_obj()
{//在屏幕中创建一个对象lv_obj_t * img = lv_obj_create(lv_scr_act());//取消滚动lv_obj_clear_flag(img, LV_OBJ_FLAG_SCROLLABLE);lv_obj_set_size(img, 200, 200);lv_obj_align(img, LV_ALIGN_CENTER, 0, -60);// lv_obj_set_style_pad_all//图片对象pic_obj = lv_img_create(img);lv_obj_center(pic_obj);
}
//初始化歌曲信息的父对象
void init_title_obj()
{//在屏幕中创建一个对象lv_obj_t * title = lv_obj_create(lv_scr_act());lv_obj_clear_flag(title, LV_OBJ_FLAG_SCROLLABLE);//禁用滚动lv_obj_set_size(title, 200, 50);lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 20);//标题标签title_label = lv_label_create(title);//添加字体lv_obj_add_style(title_label, &font_style, 0);lv_obj_center(title_label);lv_label_set_text(title_label, "开启音乐之旅");//歌词标签words_label = lv_label_create(lv_scr_act());lv_obj_add_style(words_label, &font_style, 0);lv_obj_align(words_label,LV_ALIGN_CENTER,0,70);lv_label_set_text(words_label,"歌词");
}//信号任务
void signal_10_task(int arg)
{if (arg == 10){printf("收到信号 %d 线程任务(读取mplayer)暂停\n", arg);pthread_kill(tid_write,12); //停止写pthread_cond_wait(&cond, &mutex);   //停止读pthread_cond_signal(&cond1);//唤醒获取时间puts("继续工作,读mplayer");return;}
}
void signal_12_task(int arg)
{//printf("收到信号 %d\n",arg);printf("收到信号 %d 线程任务(get_time_pos)暂停\n", arg);pthread_cond_wait(&cond1, &mutex1); puts("继续工作,写mplayer");   return;
}
static char words_line[1024]={0};//找歌词
void *find_words_task(void *arg)
{  char *p=strstr(words_buf,(char *)arg);//寻找这个时间有没有歌词if(p!=NULL)                 //和歌词相同时间{            char buf[1024]={0};sscanf(p,"%s",buf);char *q = strrchr(buf,']');sscanf(++q,"%s",buf);  if(strcmp(buf,words_line))//不相同{strcpy(words_line,buf);puts(words_line);   //**********歌词标签//lv_label_set_text(words_label,words_line);pthread_mutex_lock(&mutex_lv);//上锁lv_label_set_text(words_label,words_line);pthread_mutex_unlock(&mutex_lv);}     }
}
//线程任务 读播放器返回内容
static char show_time_buf[100]={0};
void *read_mplayer_task(void *arg)
{//注册一个信号signal(10, signal_10_task);//收到10就暂停 char line[1024]={0};                //返回信息char *p;while(1){  memset(line,0,1024);fgets(line,1024,fp_mplayer);  //读取进程返回的内容 //printf("RETURN %s",line);      if(strstr(line,"ANS_TIME_POSITION"))//当前播放秒数{         p=strrchr(line,'=');p++;     sscanf(p,"%f",&time_pos);          //printf("歌曲播放时间 %.2f\n",time_pos);char tmp[100]={0};int tmp_time=time_pos;sprintf(tmp,"%02d:%02d",tmp_time/60,tmp_time % 60);if(strcmp(show_time_buf,tmp))//不相同{strcpy(show_time_buf,tmp);//lv_label_set_text(time_pos_label,show_time_buf); //设置标签pthread_mutex_lock(&mutex_lv);//上锁lv_label_set_text(time_pos_label,show_time_buf);pthread_mutex_unlock(&mutex_lv);}puts(tmp);//打印时间  00:00//*********开启线程找歌词**********//pthread_t tid;pthread_create(&tid,NULL,find_words_task,tmp);pthread_detach(tid);    //*******************//}if(strstr(line,"ANS_PERCENT_POSITION"))//播放百分比{p=strrchr(line,'=');//p++;     int percent=0;sscanf(++p,"%d",&percent); //printf("播放百分比 %d\n",percent_pos);if(percent!=percent_pos){percent_pos=percent;//lv_slider_set_value(play_slider,percent_pos,LV_ANIM_OFF);//设置进度条值pthread_mutex_lock(&mutex_lv);//上锁lv_slider_set_value(play_slider,percent_pos,LV_ANIM_OFF);pthread_mutex_unlock(&mutex_lv);}if(percent_pos>=99)//播完了{lv_label_set_text(time_pos_label,"0:00");//播放模式int mod = lv_dropdown_get_selected(play_mode);switch (mod){case 0:{pthread_kill(tid_read,10);//停止读写mplayerbreak;}case 1://循环播放break;           case 2://列表循环{if(++music_index >= music_num)music_index=0;play_one_music();break;}case 3://随机播放{srand((unsigned)time(NULL));music_index = (music_index+rand())%music_num;play_one_music();break;}               default:break;}           } }if(strstr(line,"ANS_LENGTH"))//歌曲长度{p=strrchr(line,'=');p++;     sscanf(p,"%f",&time_length); printf("歌曲长度 %.2f\n",time_length);char time_buf[100]={0};int length=time_length;sprintf(time_buf,"%02d:%02d",length/60,length % 60);puts(time_buf);pthread_mutex_lock(&mutex_lv);//上锁lv_label_set_text(time_length_label,time_buf); //设置标签pthread_mutex_unlock(&mutex_lv);}}
}
//线程任务 发送命令给mplayer
void *write_mplayer_task(void *arg)
{//注册一个信号signal(12, signal_12_task);//收到12就暂停char cmd1[1024]="get_time_pos\n";char cmd[1024]="get_percent_pos\n";while(1){write(fd_mplayer,cmd1,strlen(cmd1));//发送获取时间命令usleep(400*1000);write(fd_mplayer,cmd,strlen(cmd));//发送获取百分比usleep(400*1000);//sleep(1);       }
}
//线程任务 创建子进程播放音乐
void *play_music_task(void *arg)
{     //printf("---- %ld线程任务------------------\n",pthread_self()); //拼接命令char cmd[1024]="mplayer -slave -quiet -input file=/pipe";sprintf(cmd,"%s %s",cmd,music_path[music_index]);//puts(cmd);  //播放音乐 fp_mplayer = popen(cmd, "r");if (fp_mplayer == NULL)perror("popen fail:");puts("----线程任务(启动播放音乐)完成 -----------------------\n");strcpy(cmd,"get_time_length\n");    //获取长度write(fd_mplayer,cmd,strlen(cmd));strcpy(cmd,"get_time_pos\n");    //发送获取时间命令write(fd_mplayer,cmd,strlen(cmd));pthread_exit(NULL);//线程结束
}//播放一首音乐
void play_one_music()
{  if(play_flag!=0)//有进程在使用播放器         system("killall -9 mplayer");             play_flag=1;//printf("music_index %d\n", music_index);//开启线程播放这首歌曲     pthread_t tid;pthread_create(&tid,NULL,play_music_task,NULL);pthread_detach(tid);//分离属性,自动回收   if(!start){//第一次才开启usleep(1000);//等待启动播放器//开启一个线程读取mplayer返回的内容//pthread_t tid_read;pthread_create(&tid_read,NULL,read_mplayer_task,NULL);pthread_detach(tid_read);//分离属性,自动回收//开启一个线程发送获取时间命令pthread_create(&tid_write,NULL,write_mplayer_task,NULL);pthread_detach(tid_write);//分离属性,自动回收printf("tid_read %ld  tid_write %ld\n",tid_read,tid_write);start=1;}pthread_cond_signal(&cond);//唤醒线程读取mplayer返回的内容//***********************************************************// //显示音乐信息char tmp[100]={0};char *p = strrchr(music_path[music_index],'/');strcpy(tmp,++p);lv_label_set_text(title_label,strtok(tmp,"."));lv_label_set_text(words_label,strtok(tmp,"."));//显示音乐图片lv_img_set_src(pic_obj,pic_path[music_index]);//打开歌词文件FILE *fp = fopen(words_path[music_index],"r");memset(words_buf,0,sizeof(words_buf));if(fp!=NULL)fread(words_buf,5*1024,1,fp);fclose(fp);//lv_label_set_text(words_list,words_buf);
//设置播放属性int ret = lv_dropdown_get_selected(speed_obj);//音量int volume=(int)lv_slider_get_value(volume_slider);char cmd[1024]={0};sprintf(cmd,"volume %d 1\n",volume);write(fd_mplayer,cmd,strlen(cmd)); //修改播放速度switch (ret){case 0:{char  cmd[1024]={"speed_set 1\n"};write(fd_mplayer,cmd,strlen(cmd));break;}case 1:{        char  cmd[1024]={"speed_set 1.25\n"};        write(fd_mplayer,cmd,strlen(cmd));        break;    }case 2:{        char  cmd[1024]={"speed_set 1.5\n"};        write(fd_mplayer,cmd,strlen(cmd));        break;    }case 3:{        char  cmd[1024]={"speed_set 2\n"};        write(fd_mplayer,cmd,strlen(cmd));        break;}           default:        break;}//播放模式int mod = lv_dropdown_get_selected(play_mode);switch (mod){case 0:{char cmd[1024]={"loop -1\n"};write(fd_mplayer,cmd,strlen(cmd));break;}case 1:{ char cmd[1024]={"loop -1\n"};write(fd_mplayer,cmd,strlen(cmd));strcpy(cmd,"loop 1\n");write(fd_mplayer,cmd,strlen(cmd));        break;}case 2://列表循环{        break;    }case 3://随机播放{       break;}           default:        break;}}//列表处理函数,播放列表中的音乐
static lv_event_cb_t event_handler_music_list(lv_event_t * e)
{//获取事件码lv_event_code_t code = lv_event_get_code(e);//获取事件对象,这里是按钮lv_obj_t * obj = lv_event_get_target(e);//如果点击按钮if(code == LV_EVENT_CLICKED) {//打印按钮中的文本//LV_LOG_USER("Clicked: %s", lv_list_get_btn_text(music_list, obj));printf("Clicked  %s\n", lv_list_get_btn_text(music_list, obj));//当前播放中的音乐下标更新为点击列表的下标music_index = lv_event_get_user_data(e);play_one_music();         }
}
//显示歌单列表
static void show_list()
{/*创建列表*/music_list = lv_list_create(lv_scr_act());//添加风格lv_obj_add_style(music_list, &font_style, 0);lv_obj_set_size(music_list, 180, 300);//列表位置//lv_obj_center(music_list);lv_obj_align(music_list, LV_ALIGN_RIGHT_MID, -20, -80);//添加文本lv_list_add_text(music_list, "音乐列表");/*在列表中添加按钮*/lv_obj_t * btn;for(int i = 0; i < music_num; i++) {char tmp[100]={0};char *p = music_path[i];p = strrchr(p,'/');strcpy(tmp,++p);//裁剪到只剩音乐名字  music.mp3//参数:列表对象,图标宏,按钮名btn = lv_list_add_btn(music_list, NULL,strtok(tmp,"."));//列表按钮风格lv_obj_add_style(music_list, &font_style, 0);//触发事件,把下标传递lv_obj_add_event_cb(btn, event_handler_music_list, LV_EVENT_CLICKED, i);}
}//按钮事件
static void btn_handler(lv_event_t * e)
{lv_event_code_t code = lv_event_get_code(e);//获取传递的参数 char *msg = lv_event_get_user_data(e);if(code == LV_EVENT_CLICKED) //点击按钮{if(strcmp(msg,"pause") == 0){if(!start)return;pthread_kill(tid_read,10);//暂停读mplayer返回内容       system("killall -19 mplayer");}if(strcmp(msg,"play") == 0){if(!start)return;system("killall -18 mplayer");//播放器继续pthread_cond_signal(&cond);//唤醒读写mplayerusleep(1000);pthread_cond_signal(&cond);//防止被再次暂停}if(strcmp(msg,"forward") == 0){if(!start)return;usleep(1000);char  cmd[1024]={"seek +10\n"};write(fd_mplayer,cmd,strlen(cmd));  strcpy(cmd,"get_percent_pos\n");write(fd_mplayer,cmd,strlen(cmd));//发送获取时间命令    }if(strcmp(msg,"back") == 0){if(!start)return;usleep(10000);char  cmd[1024]={"seek -10\n"};write(fd_mplayer,cmd,strlen(cmd));  strcpy(cmd,"get_percent_pos\n");write(fd_mplayer,cmd,strlen(cmd));//发送获取时间命令  }if(strcmp(msg,"next_music") == 0){usleep(1000);//播放模式int mod = lv_dropdown_get_selected(play_mode);switch (mod){case 1:{play_one_music();break;}case 0:case 2://列表循环{if(++music_index >= music_num)music_index=0;play_one_music();break;}case 3://随机播放{srand((unsigned)time(NULL));music_index = (music_index+rand())%music_num;printf("music_index %d\n",music_index);play_one_music();break;}               default:break;}}if(strcmp(msg,"prev_music") == 0){usleep(1000);//播放模式int mod = lv_dropdown_get_selected(play_mode);switch (mod){case 1://循环播放{ char cmd[1024]={"loop -1\n"};write(fd_mplayer,cmd,strlen(cmd));strcpy(cmd,"loop 1\n");write(fd_mplayer,cmd,strlen(cmd));play_one_music();break;}case 0://单曲case 2://列表循环{if(--music_index <= 0)music_index=music_num-1;play_one_music();break;}case 3://随机播放{srand((unsigned)time(NULL));music_index = (music_index+rand())%music_num;play_one_music();break;}               default:break;}}if(strcmp(msg,"show_list") == 0){list_flag=!list_flag;if(list_flag)lv_obj_clear_flag(music_list,LV_OBJ_FLAG_HIDDEN);         elselv_obj_add_flag(music_list, LV_OBJ_FLAG_HIDDEN); }}
}
//显示按钮
void show_button()
{//风格设置static lv_style_t btn_style;lv_style_init(&btn_style);/*Set a background color and a radius*/lv_style_set_radius(&btn_style,90);lv_style_set_bg_opa(&btn_style, LV_OPA_COVER);lv_style_set_bg_color(&btn_style, lv_palette_lighten(LV_PALETTE_BLUE, 1));//按钮色/*Add a shadow*/lv_style_set_shadow_width(&btn_style, 55);lv_style_set_shadow_color(&btn_style, lv_palette_main(LV_PALETTE_BLUE));//背景色//按钮的标签lv_obj_t* label;//暂停按钮lv_obj_t *btn_pause = lv_btn_create(lv_scr_act());//按钮事件lv_obj_add_event_cb(btn_pause, btn_handler, LV_EVENT_ALL,"pause");   //位置lv_obj_align(btn_pause, LV_ALIGN_BOTTOM_MID,40,-20);//大小lv_obj_set_size(btn_pause,60,60);//图标lv_obj_set_style_bg_img_src(btn_pause,LV_SYMBOL_PAUSE,0);//添加风格lv_obj_add_style(btn_pause,&btn_style,0);//播放按钮lv_obj_t *btn_play = lv_btn_create(lv_scr_act());lv_obj_add_event_cb(btn_play, btn_handler, LV_EVENT_ALL,"play");   lv_obj_align(btn_play, LV_ALIGN_BOTTOM_MID,-40,-20);lv_obj_set_size(btn_play,60,60);lv_obj_set_style_bg_img_src(btn_play,LV_SYMBOL_PLAY,0);lv_obj_add_style(btn_play,&btn_style,0);//快进lv_obj_t *btn_forward = lv_btn_create(lv_scr_act());lv_obj_add_event_cb(btn_forward, btn_handler, LV_EVENT_ALL,"forward");lv_obj_set_size(btn_forward,60,60);lv_obj_align(btn_forward, LV_ALIGN_BOTTOM_MID,120,-20);lv_obj_set_style_bg_img_src(btn_forward,LV_SYMBOL_RIGHT LV_SYMBOL_RIGHT,0);lv_obj_add_style(btn_forward,&btn_style,0);//快退lv_obj_t *btn_back = lv_btn_create(lv_scr_act());lv_obj_add_event_cb(btn_back, btn_handler, LV_EVENT_ALL,"back");lv_obj_set_size(btn_back,60,60);lv_obj_align(btn_back, LV_ALIGN_BOTTOM_MID,-120,-20);lv_obj_set_style_bg_img_src(btn_back,LV_SYMBOL_LEFT LV_SYMBOL_LEFT,0);lv_obj_add_style(btn_back,&btn_style,0);//下一首lv_obj_t *btn_next = lv_btn_create(lv_scr_act());lv_obj_add_event_cb(btn_next, btn_handler, LV_EVENT_ALL,"next_music");lv_obj_set_size(btn_next,60,60);lv_obj_align(btn_next, LV_ALIGN_BOTTOM_MID,200,-20);lv_obj_set_style_bg_img_src(btn_next,LV_SYMBOL_NEXT,0);lv_obj_add_style(btn_next,&btn_style,0);//上一首lv_obj_t *btn_prev = lv_btn_create(lv_scr_act());lv_obj_add_event_cb(btn_prev, btn_handler, LV_EVENT_ALL,"prev_music");lv_obj_set_size(btn_prev,60,60);lv_obj_align(btn_prev, LV_ALIGN_BOTTOM_MID,-200,-20);lv_obj_set_style_bg_img_src(btn_prev,LV_SYMBOL_PREV,0);lv_obj_add_style(btn_prev,&btn_style,0);//显示,隐藏  歌单列表//风格设置static lv_style_t style;lv_style_init(&style);/*Set a background color and a radius*/lv_style_set_radius(&style, 5);lv_style_set_bg_opa(&style, LV_OPA_COVER);lv_style_set_bg_color(&style, lv_palette_lighten(LV_PALETTE_GREY, 1));/*Add a shadow*/lv_style_set_shadow_width(&style, 55);lv_style_set_shadow_color(&style, lv_palette_main(LV_PALETTE_BLUE));//歌单列表lv_obj_t *btn_list = lv_btn_create(lv_scr_act());lv_obj_add_event_cb(btn_list, btn_handler, LV_EVENT_ALL,"show_list");lv_obj_set_size(btn_list,60,60);lv_obj_align(btn_list, LV_ALIGN_BOTTOM_RIGHT,-20,-90);label = lv_label_create(btn_list);lv_obj_add_style(label, &font_style, 0);lv_label_set_text(label, "歌单");lv_obj_center(label);lv_obj_add_style(btn_list, &style, 0);}//下拉列表事件
static void dd_handler(lv_event_t * e)
{//获取事件码lv_event_code_t code = lv_event_get_code(e);//获取传递的参数 char *msg = lv_event_get_user_data(e);  if(code == LV_EVENT_VALUE_CHANGED)//值被修改{if(strcmp(msg,"speed")==0){//获取事件对象//lv_obj_t *speed = lv_event_get_target(e);int ret = lv_dropdown_get_selected(speed_obj);//printf("ret = %d\n",ret);//修改播放速度switch (ret){case 0:{char  cmd[1024]={"speed_set 1\n"};write(fd_mplayer,cmd,strlen(cmd));  break;}case 1:{char  cmd[1024]={"speed_set 1.25\n"};write(fd_mplayer,cmd,strlen(cmd));break;}case 2:{char  cmd[1024]={"speed_set 1.5\n"};write(fd_mplayer,cmd,strlen(cmd));break;}case 3:{char  cmd[1024]={"speed_set 2\n"};write(fd_mplayer,cmd,strlen(cmd));break;}           default:break;}}if(strcmp(msg,"play_mode")==0){//播放模式int mod = lv_dropdown_get_selected(play_mode);switch (mod){case 0:{char cmd[1024]={"loop -1\n"};write(fd_mplayer,cmd,strlen(cmd));break;}case 1:{ char cmd[1024]={"loop -1\n"};write(fd_mplayer,cmd,strlen(cmd));strcpy(cmd,"loop 1\n");write(fd_mplayer,cmd,strlen(cmd));        break;}case 2://列表循环{        break;    }case 3://随机播放{       break;}           default:        break;}}}
}
//显示下拉列表
static void show_drop_down()
{static const char * opts = "x1\n""x1.25\n""x1.5\n""x2";static const char * opts1 = "single\n""circle\n""list\n""random";                           //播放速度 创建一个对象speed_obj = lv_dropdown_create(lv_scr_act());//lv_dropdown_set_text(speed_obj, "Speed");//触发事件lv_obj_add_event_cb(speed_obj,dd_handler,LV_EVENT_ALL,"speed");//添加选项lv_dropdown_set_options_static(speed_obj, opts);//大小lv_obj_set_size(speed_obj,80,40);//位置lv_obj_align(speed_obj, LV_ALIGN_BOTTOM_RIGHT, -60, -20);//箭头位置,现在由低朝上lv_dropdown_set_dir(speed_obj, LV_DIR_BOTTOM);//列表弹出方向lv_dropdown_set_symbol(speed_obj, LV_SYMBOL_UP);//标签lv_obj_t *speed_label = lv_label_create(lv_scr_act());lv_obj_add_style(speed_label, &font_style, 0);lv_label_set_text(speed_label, "播放速度");lv_obj_align_to(speed_label, speed_obj, LV_ALIGN_OUT_TOP_MID, 0, 0);//播放模式play_mode = lv_dropdown_create(lv_scr_act());//添加字体//lv_obj_add_style(play_mode, &font_style, 0);lv_obj_add_event_cb(play_mode,dd_handler,LV_EVENT_ALL,"play_mode");lv_dropdown_set_options_static(play_mode, opts1);lv_obj_set_size(play_mode,100,40);//位置lv_obj_align(play_mode, LV_ALIGN_BOTTOM_LEFT, 40, -20);lv_dropdown_set_dir(play_mode, LV_DIR_BOTTOM);lv_dropdown_set_symbol(play_mode, LV_SYMBOL_UP);lv_obj_t *mode_label = lv_label_create(lv_scr_act());lv_obj_add_style(mode_label, &font_style, 0);lv_label_set_text(mode_label, "播放模式");lv_obj_align_to(mode_label, play_mode, LV_ALIGN_OUT_TOP_MID, 0, 0);}//滑动条事件
static void slider_event_cb(lv_event_t * e)
{if(!start)return;//获取传递的参数 char *msg = lv_event_get_user_data(e);//puts(msg);if(strcmp(msg,"volume")==0){   lv_obj_t * slider = lv_event_get_target(e);//获取事件对象char buf[8];int volume=(int)lv_slider_get_value(slider);//获取值lv_snprintf(buf, sizeof(buf), "%d",volume);lv_label_set_text(volume_label, buf);           //更新音量标签值lv_obj_align_to(volume_label, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);usleep(100);            //修改音量值char cmd[1024]={0};sprintf(cmd,"volume %d 1\n",volume);write(fd_mplayer,cmd,strlen(cmd));  }  if(strcmp(msg,"play")==0){puts("松开了");if(start)//启动就先暂停{pthread_kill(tid_read,10);//暂停读mplayer返回内容       system("killall -19 mplayer");}int rate = (int)lv_slider_get_value(play_slider);//获取值float new_time = time_length * rate * 0.01;int seek_time = new_time - time_pos;char  cmd[1024]={0};sprintf(cmd,"seek %d\n",seek_time);//puts(cmd);write(fd_mplayer,cmd,strlen(cmd)); system("killall -18 mplayer");//播放器继续pthread_cond_signal(&cond);//唤醒读写mplayerusleep(1000);pthread_cond_signal(&cond);//防止被再次暂停}}
//显示滑动条
static void show_slider(void)
{      //音量    volume_slider = lv_slider_create(lv_scr_act());lv_obj_align(volume_slider,LV_ALIGN_LEFT_MID,20,20);//位置    lv_obj_add_event_cb(volume_slider, slider_event_cb, LV_EVENT_VALUE_CHANGED, "volume");//事件    lv_obj_set_size(volume_slider,18,180);//大小lv_slider_set_value(volume_slider,100,LV_ANIM_OFF);//初始值  /*标签 音量大小 */volume_label = lv_label_create(lv_scr_act());lv_label_set_text(volume_label, "100");lv_obj_align_to(volume_label, volume_slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);lv_obj_t *label = lv_label_create(lv_scr_act());lv_obj_add_style(label, &font_style, 0);lv_label_set_text(label, "音量");lv_obj_align_to(label, volume_label, LV_ALIGN_OUT_TOP_MID, 0, -210);//播放进度条play_slider = lv_slider_create(lv_scr_act());lv_obj_align(play_slider,LV_ALIGN_CENTER,0,120);//位置   lv_obj_set_width(play_slider,400);//宽度 lv_obj_add_event_cb(play_slider, slider_event_cb, LV_EVENT_RELEASED , "play");//事件    lv_slider_set_value(play_slider,0,LV_ANIM_OFF);//初始值 lv_slider_set_range(play_slider, 0, 100);//范围/*在滑条下创建标签*/time_length_label = lv_label_create(lv_scr_act());lv_label_set_text(time_length_label, "0:00");lv_obj_align_to(time_length_label, play_slider, LV_ALIGN_OUT_RIGHT_BOTTOM,0,20);time_pos_label = lv_label_create(lv_scr_act());lv_label_set_text(time_pos_label, "0:00");lv_obj_align_to(time_pos_label, play_slider, LV_ALIGN_OUT_LEFT_BOTTOM,0,20);
}//显示界面
static void display_interface()
{//显示歌单列表show_list();//显示按钮show_button();//显示下拉列表show_drop_down();//显示滑动条show_slider();
}//音乐播放器
void music_player()
{//打开管道文件fd_mplayer = open("/pipe", O_RDWR);if(fd_mplayer < 0) {perror("打开管道文件失败");exit(0);}//检索本地歌单get_music_path();//初始化字体init_font_style();//初始化图片父对象init_pic_parent_obj();init_title_obj();//显示界面display_interface();}

main.c

#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/evdev.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>#define DISP_BUF_SIZE (480 * 1024)pthread_mutex_t mutex_lv;//lvgl线程锁int main(void)
{/*lvgl初始化*/lv_init();/*输出设备初始化及注册*/fbdev_init();/*A small buffer for LittlevGL to draw the screen's content*/static lv_color_t buf[DISP_BUF_SIZE];/*Initialize a descriptor for the buffer*/static lv_disp_draw_buf_t disp_buf;lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);/*Initialize and register a display driver*/static lv_disp_drv_t disp_drv;lv_disp_drv_init(&disp_drv);disp_drv.draw_buf   = &disp_buf;disp_drv.flush_cb   = fbdev_flush;disp_drv.hor_res    = 800;disp_drv.ver_res    = 480;lv_disp_drv_register(&disp_drv);//输入设备初始化及注册evdev_init();static lv_indev_drv_t indev_drv_1;lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/indev_drv_1.type = LV_INDEV_TYPE_POINTER;/*This function will be called periodically (by the library) to get the mouse position and state*/indev_drv_1.read_cb = evdev_read;lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);//官方demo//lv_demo_widgets();//音乐播放器music_player();pthread_mutex_init(&mutex_lv,NULL);/*事物处理及告知lvgl节拍数*/while(1) {pthread_mutex_lock(&mutex_lv);//上锁lv_timer_handler();//事务处理pthread_mutex_unlock(&mutex_lv);//解锁lv_tick_inc(5);//节拍累计usleep(5000);}return 0;
}/*用户节拍获取*/
uint32_t custom_tick_get(void)
{static uint64_t start_ms = 0;if(start_ms == 0) {struct timeval tv_start;gettimeofday(&tv_start, NULL);start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;}struct timeval tv_now;gettimeofday(&tv_now, NULL);uint64_t now_ms;now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;uint32_t time_ms = now_ms - start_ms;return time_ms;
}

基于lvgl与mplayer音乐播放器相关推荐

  1. Qt+MPlayer音乐播放器开发笔记(二):交叉编译MPlayer以及部署到开发板播放演示

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/119991329 长期持续带来更多项目与技术分享,咨询请 ...

  2. 基于智能手机Android平台音乐播放器全程开发实战

    基于android开发的智能手机平台的应用越来越多,目前也是一块比较热门的技术,本项目为基于android系统的音乐播放器项目,学习本项目的目的是为了让学员尽快掌握android领域的小应用的开发.项 ...

  3. 基于Amarok的跨平台音乐播放器:Clementine mac版

    Clementine是一个基于Amarok的跨平台音乐播放器,同时它也支持 Win 和 Mac 平台,属于全栖型选手.Clementine可以将歌曲目录加入"库"中以进行搜索,可以 ...

  4. iOS之基于FreeStreamer的简单音乐播放器(模仿QQ音乐)

    代码地址如下: http://www.demodashi.com/demo/11944.html 天道酬勤 前言 作为一名iOS开发者,每当使用APP的时候,总难免会情不自禁的去想想,这个怎么做的?该 ...

  5. .net vue漂亮登录界面_基于 electron-vue 开发的音乐播放器「实践」

    作者:XiaoTuGou 转发链接:https://github.com/SmallRuralDog 前言 基于 electron-vue 开发的音乐播放器,界面模仿QQ音乐. 技术栈electron ...

  6. html实现音乐界面设计,基于HTML5技术的音乐播放器的设计与实现.doc

    基于HTML5技术的音乐播放器的设计与实现 基于HTML5技术的音乐播放器的设计与实现 常志强 刘正余 杨劲楠 皖西学院电子与信息工程学院 X 关注成功! 加关注后您将方便地在 我的关注中得到本文献的 ...

  7. web html5音乐播放器设计与实现,基于HTML5技术的音乐播放器的设计与实现

    Vol.33No.11Nov.2017 赤峰学院学报(自然科学版) Journal of Chifeng University (Natural Science Edition )第33卷第11期(下 ...

  8. 【基于Python+tkinter的音乐播放器开发-哔哩哔哩】 https://b23.tv/eG2TwOL

    [基于Python+tkinter的音乐播放器开发-哔哩哔哩] https://b23.tv/eG2TwOL https://b23.tv/eG2TwOL

  9. 基于QT的网络音乐播放器(一)

    自学Qt已经有一段时间了,但是始终感觉自己还是很弱(其实并不是感觉自己很弱,是自己本来就很弱,哈哈).自己也照着书上敲了几个例子,但觉得还是要写点东西才能真正运用起来.所以,前段时间就写了个很简单的音 ...

最新文章

  1. python自定义库文件路径
  2. phy芯片测试寄存器_PCIe 5.0首秀!7nm IP方案已成熟!PCIe 5.0的芯片设计有多难?...
  3. Linux0.00 代码解析(二)
  4. Maven根据不同环境打包不同配置文件
  5. rest post无法取到request_小白学Flask第五天 | 详解很重要的request对象
  6. php pdo mysql哪个好_php pdo和mysqli对比选择
  7. 佳能fax_l150如何打印_佳能faxl150说明书下载
  8. 使用Context和Hooks来管理状态
  9. 松弛法(relaxation)
  10. MySQL 5.6 dump/load buffer pool实验
  11. golang 图片处理,剪切,base64数据转换,文件存储
  12. unity3d C#UnityEngine API 提示中文汉化
  13. 学python需要c-为什么我建议每个开发人员都需要学 Python ?
  14. Google可能退出中国
  15. 【MySQL】数据库命令练习题及答案
  16. wps怎么把ppt里的字体一起保存_WPS怎样将PPT中的文字导出为Word文档?
  17. windows10操作-虚拟桌面与关闭时间线
  18. Vivado 添加IOB方法
  19. 移动广告平台KeyMob:整合多家主流手机广告平台
  20. 设计师:设计师知识储备(硬装、软装、榻榻米、马卡龙、地台、公共空间、玄关、闭水实验)之详细攻略

热门文章

  1. java项目系统分析怎么写_销售系统项目业务分析和Java中使用邮箱
  2. uboot 设置环境变量
  3. 一文了解WebSocket(实战)----python篇
  4. 老庞互联网随想之一:世界从未改变!
  5. Q-BERT: Hessian Based Ultra Low Precision Quantization of BERT---Q-BERT:基于Hessian的超低精度BERT量化
  6. Proteus小技巧:端口的批量编号
  7. 复利mysql_0414-复利计算再升级
  8. 【java毕业设计】基于Spring Boot+mysql的酒店管理系统设计与实现(程序源码+毕业论文)-酒店管理系统
  9. Ubuntu移动文件
  10. 智慧保险大数据解决方案.ppt