自己的MP3 maplay+ucGUi+tslib+歌词同显+频谱
来源:互联网 发布:上海沧澜网络可信吗 编辑:程序博客网 时间:2024/05/18 17:58
madplay的移植在前几篇文章有过了,但是在移植后对madplay进行控制很不方便,于是在找工作的几天,写一段程序用socket添加在madplay中作为和主程序的通讯接口
# if defined(USE_TTY) && !defined(_WIN32) if ((player->options & PLAYER_OPTION_TTYCONTROL) && setup_tty() == -1) player->options &= ~PLAYER_OPTION_TTYCONTROL; socket_fd = setup_socket(); //sxbg# endif修改player.c添加socket客户端初始化程序
int readkey(int blocking){# if !defined(_WIN32) unsigned char key; ssize_t count = 0; if (!blocking) { /* tty_fd should be a tty in noncanonical mode with VMIN = VTIME = 0 */ count = read(tty_fd, &key, 1); if(count == 0) { if(socket_fd > 0) count = recv(socket_fd, &key, 1, MSG_DONTWAIT); } if (count == -1 && errno != EINTR && errno != EAGAIN) { error("tty", ":read"); return -1; } return (count == 1) ? key : 0; } else { struct termios tty, save_tty; if (tcgetattr(tty_fd, &tty) == -1) { error("tty", ":tcgetattr"); return -1; } save_tty = tty; /* change terminal temporarily to get a blocking read() */ tty.c_cc[VMIN] = 1; if (tcsetattr(tty_fd, TCSANOW, &tty) == -1) { error("tty", ":tcsetattr"); return -1; } do { //count = read(tty_fd, &key, 1); if(count == 0) { if(socket_fd > 0) { recv(socket_fd, &key, 1, MSG_DONTWAIT); count = recv(socket_fd, &key, 1, 0); } } } while (count == -1 && errno == EINTR); if (count == -1) error("tty", ":read"); if (tcsetattr(tty_fd, TCSANOW, &save_tty) == -1) { error("tty", ":tcsetattr"); return -1; } if (count == -1) return -1; return (count == 1) ? key : 0; }
修改以上代码,通过socket两者之间通信
这样主进程就能控制madplay的播放,停止,音量等功能,修改部分代码完成当前播放时间和剩余时间的查询以便为进度条做准备,
int get_lrc_Info(FILE *fp, unsigned int second, LRC_INFO *lrc_info){char data;unsigned long file_len;unsigned long cur_ofs;unsigned long start_ofs;unsigned long end_ofs;unsigned long mark_ofs;unsigned int time_s;unsigned int status;fseek(fp, 0L, SEEK_END);file_len = ftell(fp);start_ofs= 0;end_ofs= file_len-1;_RE_SCAN:cur_ofs = (start_ofs>end_ofs)?(start_ofs>end_ofs):(end_ofs-start_ofs);if(cur_ofs>100){cur_ofs = (start_ofs + end_ofs)/2;}else{cur_ofs = start_ofs;}fseek(fp,cur_ofs,SEEK_SET);status = 0;mark_ofs = cur_ofs;while(cur_ofs<end_ofs){fread(&data,1,1,fp);cur_ofs++;if(cur_ofs == end_ofs) return -1;switch(status){case 0:if(data=='['){status++;mark_ofs = cur_ofs;}if(data == ']'){mark_ofs = cur_ofs;}break;case 1:if((data>=0x30)&&(data<=0x39)) // 0 ~ 9{time_s = (data-0x30)*10*60;status++;}break;case 2:time_s += (data-0x30)*60;status++;break;case 3:if(data!=':'){while(1);}status++;break;case 4:time_s += (data-0x30)*10;status++;break;case 5:time_s += (data-0x30); status++;break;case 6:if(data == ']'){if(time_s == second){lrc_info->time_s = time_s;lrc_info->offset = cur_ofs;status++;}else if(time_s > second){end_ofs = cur_ofs;goto _RE_SCAN;}else{start_ofs = cur_ofs;goto _RE_SCAN;}}break;case 7:if(data == 0x0A){lrc_info->length = cur_ofs - lrc_info->offset;if(lrc_info->length <= 2) {start_ofs = cur_ofs;goto _RE_SCAN;}status++;return 0;}break;default:break;}if(status==8){break;}}if(status!=8){end_ofs = mark_ofs;goto _RE_SCAN;}return -1;}void get_play_info(PLY_INFO *plyinfo){ char cmd_tmp; char msg[64]; int i = 0, j = 0, n; cmd_tmp = 'i'; if(server_fd > 0) { recv(server_fd, msg, 64, MSG_DONTWAIT); n = send(server_fd, &cmd_tmp, 1, 0); n = recv(server_fd, msg, 64, 0); } else return ; msg[n] = '\0'; printf("msg:%s\n", msg); while(i < n-6) { if(msg[i] == ':' && msg[i+3] == ':' && msg[i+6] == ' ' && msg[i+10] == ':') { break; } i++; } if(i < n-6) { plyinfo->time_s = (msg[i+2]-0x30)*60 + (msg[i+4]-0x30)*10 + (msg[i+5]-0x30); current_time = plyinfo->time_s; remain_time = (msg[i+12]-0x30)*60 + (msg[i+14]-0x30)*10 + (msg[i+15]-0x30); j = 0; while(msg[i+17+j] != '.') { plyinfo->name[j] = msg[i+17+j]; j++; } plyinfo->name[j] = '\0'; } }void *lrc_thread(void *arg){ FILE* fp;unsigned int second;unsigned int i;unsigned char data; unsigned char cmd[16]; unsigned char str[64]; for(;;) { get_play_info(&ply_info); current_time = ply_info.time_s; sprintf(cmd, "%s.lrc", ply_info.name); //printf("cmd*********%s\n", cmd); fp = fopen(cmd,"rd"); if(fp == NULL) { perror("Lrc cannot open !\n"); /*GUI_SetColor(GUI_BLUE); GUI_SetBkColor(GUI_GREEN); GUI_ClearRect(0, 160, 319, 184); GUI_SetFont(&GUI_FontHZ24); GUI_SetTextAlign(GUI_TA_HCENTER); GUI_DispStringAt("没找到相应的歌词!", 160, 160);*/ sleep(1); continue ; } if(get_lrc_Info(fp, ply_info.time_s, &lrc_info) == 0) { fseek(fp,lrc_info.offset,SEEK_SET); bzero(str, sizeof(str)); fread(str, 1, lrc_info.length, fp); fseek(fp,lrc_info.offset,SEEK_SET); /*i = 0; while(lrc_info.length) { lrc_info.length--; fread(&data, 1, 1, fp); printf("%c", data); i++; }*/ str[lrc_info.length]= '\0'; GUI_SetColor(GUI_BLUE); GUI_SetBkColor(GUI_GREEN); GUI_ClearRect(0, 160, 319, 184); GUI_SetFont(&GUI_FontHZ24); GUI_SetTextAlign(GUI_TA_HCENTER); GUI_DispStringAt(str, 160, 160); PROGBAR_SetValue(ahProgBar,get_ratio()); //printf("ratio:%d**********\n", get_ratio()); } fclose(fp); sleep(1); } return ((void *)1);}
歌词同步进程,ucgui显示汉子要添加hzk24.c字库,具体方法添加hzk24.c到ucGUI的font目录下,然后调用Disp_String_At函数即可,歌词的编码要改为ascii格式,因为unicode是不可以的,这样就能动态的显示汉字了,折腾好久才发现这里的原因。
void *touch_thread(void *arg){ struct tsdev *ts; GUI_PID_STATE state; int retval; int x, y; unsigned int i; struct ts_sample samp; char *tsdevice = NULL; static unsigned last_state = 0; printf("touch_thread begin, pid:%d\n", getpid()); if((tsdevice = getenv("TSLIB_TSDEVICE")) == NULL) { tsdevice = strdup("/dev/input/event0"); } ts = ts_open(tsdevice, 0); if(!ts) { printf("open error\n"); return ((void *)1); } if(ts_config(ts)) { perror("ts_config"); return ((void *)1); } while(1) { retval = ts_read(ts, &samp, 1); if(retval != 1) continue; printf("%6d %6d %6d\n", samp.x, samp.y, samp.pressure); state.x = samp.x; state.y = samp.y; state.Pressed = samp.pressure; if(state.Pressed != last_state) { printf("there have a key pressed!\n"); GUI_PID_StoreState(&state); last_state = state.Pressed; } } return ((void *)1); }
触摸线程
void *exec_thread(void *arg){ printf("exec_thread for touch screen,pid:%d\n", getpid()); for(;;) { GUI_Exec(); usleep(200); } return ((void *)1);}
ucGUI执行线程
void *socket_thread(void *arg){ struct sockaddr_in server_addr; int opt = 1, ret; int listen_socket = -1; fd_set rfds; struct timeval tv; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htons(INADDR_ANY); server_addr.sin_port = htons(6666); listen_socket = socket(PF_INET,SOCK_STREAM,0); if( listen_socket < 0) { printf("Create Socket Failed!"); exit(1); } setsockopt(listen_socket,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); setsockopt(listen_socket,IPPROTO_TCP,TCP_NODELAY,&opt,sizeof(opt)); if(bind(listen_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))) { printf("Server Bind Port Failed!"); exit(1); } if(listen(listen_socket, 5)) { printf("Server Listen Failed!"); exit(1); } while (1) { FD_ZERO(&rfds); if (listen_socket >= 0) { FD_SET(listen_socket, &rfds); } ret = select(listen_socket + 1, &rfds, NULL, NULL, &tv); if (ret <= 0) continue; if (listen_socket >= 0 && FD_ISSET(listen_socket, &rfds)) { if (server_fd >= 0) { shutdown(server_fd, SHUT_RDWR); } server_fd = accept(listen_socket, NULL, 0); printf("socket success!\n"); } } return ((void *)1);}
服务器端socket线程
int main(int argc, char *argv) { int fd; int err; volatile int keyvalue, i, count, j; struct input_event ev; pthread_t tid1, tid2, tid3, tid4, tid5; void *tret; DIR *dir; struct dirent *ptr; char *p = NULL; int n = 0; char name[MAX_NUM][NAME_LEN]; pnode node_tmp; err = pthread_create(&tid1, NULL, touch_thread, NULL); err = pthread_create(&tid2, NULL, exec_thread, NULL); err = pthread_create(&tid3, NULL, socket_thread, NULL); sleep(1); err = pthread_create(&tid4, NULL, ctrl_thread, NULL); err = pthread_create(&tid5, NULL, lrc_thread, NULL); if(chdir("/mymusic") < 0) perror("chdir"); if((dir = opendir("/mymusic")) == NULL) { perror("opendir"); exit(EXIT_FAILURE); } while((ptr = readdir(dir)) != NULL) { if((p=strstr(ptr->d_name, ".mp3")) != NULL) { strcpy(name[n++], ptr->d_name); } } cur_head = create_list(name, n); print_list(cur_head); for(;;) { play(cur_head); sleep(1); } pthread_join(tid1, &tret); pthread_join(tid2, &tret); pthread_join(tid3, &tret); pthread_join(tid4, &tret); pthread_join(tid5, &tret); closedir(dir); close(fd); return 0;}主进程
整整两天过去了,看着自己的劳动成果有一点小小的欣慰,但是频谱的是虚拟的,本来想分析源码从底层取出数据做FFT变换,但是这段时间在找工作,没有太大的精力去完成,今天的面试题有一个shell脚本的,可惜笔者时间久没看了,做的不好。
来张图片吧
有的东西看着很难但只要你做就会有成果,有的东西看着很简单当你做的时候也许会遇到很多问题,高手就是从遇到问题解决问题走过来的。
0 0
- 自己的MP3 maplay+ucGUi+tslib+歌词同显+频谱
- 自己的频谱控件
- 简单的AS3 MP3音频频谱
- DIY自己的MP3
- 如何制作MP3歌词
- 用JavaScript在Web中显示Mp3的歌词
- 汪峰-怒放的生命 MP3试听,歌词下载
- Flash Mp3播放器中写的Lrc歌词解析函数
- MP3歌词的同步与拖拽设计
- 会呼吸的痛歌词/梁静茹会呼吸的痛歌词/试听/MP3/下载
- 【转】基于SAM3U + CooCox CoOS + UCGUI的MP3设计 (1)
- MP3歌词文件格式-Lrc格式
- MP3中歌词怎么弄?
- 用linux建立自己的mp3广播站
- 用Linux建立自己的Mp3广播站
- 如何创建您自己的MP3铃声
- 做我的爱人试听,歌曲做我的爱人mp3下载,歌词 - 陈志朋
- android示例:简单的播放MP3并显示歌词的应用(待更新)
- 递推方程的求解
- 复制(拷贝)构造函数
- MAC安装luasocket
- mysql中int、bigint、smallint 和 tinyint的区别
- hibernate中lazy的使用
- 自己的MP3 maplay+ucGUi+tslib+歌词同显+频谱
- 黑马程序员-Java高新技术(二)
- MyBatis+MySQL 返回插入记录的主键ID
- 一张图告诉你Git的全部命令
- 黑马程序员---Java中的集合(一)
- js的鼠标事件整理-------Day47
- C++语言笔记系列之十——静态成员
- Ubuntu下搭建FTP服务器
- java编程之路每天进步一点点之2014年6月24日