#include "lyrics_api.h" #include "ui/lyrics.h" #include "system/fs/fs.h" #include "app_config.h" #include "ui/ui_style.h" #if (TCFG_LRC_LYRICS_ENABLE) static u8 *lrc_info_buf = NULL; //[2324] __attribute__((aligned(4))); static volatile u8 lrc_analysis_flag = 0; static LRC_FILE_IO lrc_file_io = { .seek = fseek, .read = fread, }; static OS_MUTEX mutex; /*----------------------------------------------------------------------------*/ /**@brief 配置翻屏的速度 @param lrc_len--当前歌词长度,time_gap-与下一条歌词的间隔, @param *roll_speed - 翻屏的速度 500ms unit @return @note */ /*----------------------------------------------------------------------------*/ void lrc_roll_speed_ctrl(u8 lrc_len, u32 time_gap, u8 *roll_speed) { ///翻页滚动速度控制 ///printf("speed = %d,%d",lrc_len,time_gap); ///DVcTxt1_11 显示长度为32 bytes if (lrc_len > (LRC_DISPLAY_TEXT_LEN * 2)) { *roll_speed = ((time_gap + 2) / 3) << 1; } else if (lrc_len > LRC_DISPLAY_TEXT_LEN) { *roll_speed = time_gap; } else { *roll_speed = 250; ///never load new page } } /*----------------------------------------------------------------------------*/ /**@brief 清空显示区域 @param @return @note */ /*----------------------------------------------------------------------------*/ void clr_lrc_disp_buff(void) { /* lcd_clear_area_rect(4, 8, 0, 128); */ } /*----------------------------------------------------------------------------*/ /**@brief 歌词模块初始化 @param @return 0--成功,非0 失败 @note */ /*----------------------------------------------------------------------------*/ int lrc_init(void) { LRC_CFG t_lrc_cfg; t_lrc_cfg.once_read_len = ONCE_READ_LENGTH; t_lrc_cfg.once_disp_len = ONCE_DIS_LENGTH; t_lrc_cfg.label_temp_buf_len = LABEL_TEMP_BUF_LEN; t_lrc_cfg.roll_speed_ctrl_cb = lrc_roll_speed_ctrl; t_lrc_cfg.clr_lrc_disp_cb = NULL;//clr_lrc_disp_buff; /* t_lrc_cfg.lrc_text_id = LRC_DISPLAY_TEXT_ID; */ t_lrc_cfg.read_next_lrc_flag = 0; t_lrc_cfg.enable_save_lable_to_flash = LRC_ENABLE_SAVE_LABEL_TO_FLASH; u32 need_buf_size = LRC_SIZEOF_ALIN(sizeof(LRC_INFO), 4) + LRC_SIZEOF_ALIN(sizeof(LABEL_INFO), 4) + LRC_SIZEOF_ALIN(sizeof(SORTING_INFO), 4) + LRC_SIZEOF_ALIN(t_lrc_cfg.once_disp_len, 4) + LRC_SIZEOF_ALIN(t_lrc_cfg.label_temp_buf_len, 4) + LRC_SIZEOF_ALIN(t_lrc_cfg.once_read_len, 4); printf("---lrc need_buf_size=%d---\n", need_buf_size); /* ASSERT(sizeof(lrc_info_buf) >= need_buf_size); */ if (!lrc_info_buf) { lrc_info_buf = zalloc(need_buf_size); } /* memset(lrc_info_buf, 0, sizeof(lrc_info_buf)); */ os_mutex_create(&mutex); return lrc_param_init(&t_lrc_cfg, lrc_info_buf); } /*----------------------------------------------------------------------------*/ /**@brief 歌词模块退出 @param @return @note */ /*----------------------------------------------------------------------------*/ void lrc_exit(void) { os_mutex_pend(&mutex, 0); lrc_destroy(); if (lrc_info_buf) { free(lrc_info_buf); lrc_info_buf = NULL; } os_mutex_post(&mutex); } /*----------------------------------------------------------------------------*/ /**@brief 搜索歌词,解析 @param @return 0--成功,非0 失败 @note */ /*----------------------------------------------------------------------------*/ int lrc_find(FILE *file, FILE **newFile, void *ext_name) { u32 find_lrc_flag; find_lrc_flag = fget_file_byname_indir(file, newFile, ext_name); if (find_lrc_flag) { puts("\ncan't find lrc------\n"); return -1; } return 0; } void lrc_set_analysis_flag(u8 flag) { if (!lrc_info_buf) { return; } os_mutex_pend(&mutex, 0); lrc_analysis_flag = flag; os_mutex_post(&mutex); } bool lrc_show_api(int text_id, u16 dbtime_s, u8 btime_100ms) { bool ret = 0; if (!lrc_info_buf) { return false; } os_mutex_pend(&mutex, 0); if (lrc_analysis_flag == 1) { ret = lrc_show(text_id, dbtime_s, btime_100ms); os_mutex_post(&mutex); return ret ; } else { os_mutex_post(&mutex); return false; } } static FILE *tabfp = NULL; int read_tab(int i, char *buf, u8 read_len) { if (tabfp == NULL) { tabfp = fopen("mnt/sdfile/res/gbk2utf8.tab", "r"); } if (!tabfp) { r_printf("gbk2utf8.tab open fail"); return 1; } fseek(tabfp, (u32)(3 * i), SEEK_SET); fread(tabfp, buf, read_len); fseek(tabfp, 0, SEEK_SET); return 0; } u8 read_tab_check(int i, int offser) { u8 read_buf[3]; if (tabfp == NULL) { tabfp = fopen("mnt/sdfile/res/gbk2utf8.tab", "r"); } if (!tabfp) { r_printf("gbk2utf8.tab open fail"); return 1; } fseek(tabfp, i * 3 + offser, SEEK_SET); fread(tabfp, read_buf, 1); return read_buf[0]; } int gbk_2_utf8(const char *str, int str_len, char *buf, int buf_len) { // printf(">>>gbk_2_utf8%s",str); int i; int count = 0; if (!str || !buf) { return 0; } if (str_len == -1) { str_len = 0x7FFFFFFF; } while ((str_len > 0) && (buf_len > 0)) { unsigned char lead = *str++; unsigned char trail; if (!lead) { /* ������βNULL�ַ���*/ break; } if ((lead >= 0x81) && (lead <= 0xFE)) { if (str_len < 2) { break; /* ���󣬰������ */ } str_len -= 2; trail = *str++; /* ��λ��ʽ��*/ i = ((lead - 0x81) * 191) + (trail - 0x40); if (i >= (24066)) { //24066sizeof(gbk_2_utf8_table) / sizeof(gbk_2_utf8_table[0]) break; /* ���󣬷Ƿ���λ */ } /* �����ֽڵ�UTF8�����Ǿ��������*/ if (read_tab_check(i, 2)) { //gbk_2_utf8_table[i][2] read_one_num_check(i*3+2)|| if (buf_len < 3) { break; /* ������������ */ } read_tab(i, buf, 3); // *buf++ = (char)gbk_2_utf8_table[i][0]; // *buf++ = (char)gbk_2_utf8_table[i][1]; // *buf++ = (char)gbk_2_utf8_table[i][2]; buf += 3; // g_printf("bin:"); // put_buf(read_buf,3); // g_printf("buf:"); // put_buf(buf-3,3); buf_len -= 3; count += 3; } /* �����ֽڵ�UTF8��*/ else if (read_tab_check(i, 1)) { if (buf_len < 2) { break; /* ������������ */ } read_tab(i, buf, 2); buf += 2; buf_len -= 2; count += 2; } /* һ���ֽڵ��������ʵĿǰ���ǷǷ��ģ���trail=0x7F�Ŀ���λ������֧�� */ else { *buf++ = (char)read_tab_check(i, 0); buf_len--; count++; } } else { str_len--; if (lead < 0x80) { *buf++ = (char)lead; buf_len--; count++; } else if (lead == 0x80) { if (buf_len < 3) { break; } *buf++ = (char)0xE2; *buf++ = (char)0x82; *buf++ = (char)0xAC; buf_len -= 3; count += 3; } else { break; } } } if (buf_len > 0) { *buf = '\0'; } return count; } u16 big5_to_utf8(u8 *big5, u16 big5_len, u8 *utf8, u16 utf8_len) { static FILE *ft = NULL; if (ft == NULL) { ft = fopen("mnt/sdfile/res/big5_utf8.tab", "r"); } if (ft == NULL) { printf("file open failed"); return 0; } u16 offset; u16 i, j = 0; u8 tmp[3]; for (i = 0; i < big5_len; i++) { if (big5[i] == 0) { break; } if (j >= utf8_len) { j = utf8_len; break; } if (big5[i] <= 0x7f) { utf8[j] = big5[i]; j++; } else { if (i + 1 >= big5_len) { break; } if (big5[i] < 0xa1 || big5[i] > 0xf9 || big5[i + 1] < 0x40 || \ big5[i + 1] > 0xfe || (big5[i + 1] > 0x7e && big5[i + 1] < 0xa1)) { printf("curr code not big5 format, i: %d %d %d\n", i, big5[i], big5[i + 1]); i++; continue; } offset = (big5[i] - 0xa1) * (0x7e - 0x40 + 0xfe - 0xa1 + 2); if (big5[i + 1] >= 0x40 && big5[i + 1] <= 0x7e) { offset += (big5[i + 1] - 0x40); } else if (big5[i] >= 0xa1 && big5[i] <= 0xfe) { offset += (big5[i + 1] - 0xa1 + (0x7e - 0x40 + 1)); } offset *= 3; fseek(ft, offset, SEEK_SET); fread(ft, tmp, 3); if (j + 3 >= utf8_len) { break; } memcpy(&utf8[j], tmp, 3); i++; j += 3; } } return j; //转换后utf8编码长度 } static int ui_text_utf8_check(u8 *buf, u16 len) { int i, j; u8 code, nbytes; for (i = 0; i < len; i++) { nbytes = 0; code = buf[i]; while (code & 0x80) { code <<= 1; nbytes++; } if (nbytes == 0) { continue; } if (nbytes == 1 || nbytes > 6) { return false; } if (i + nbytes > len) { return true; } for (j = 1; j < nbytes; j++) { code = buf[i + j]; if ((code & 0xc0) != 0x80) { return false; } } i += (nbytes - 1); } return true; } u8 ui_check_ansi_type(u8 *str, u16 len) { u8 ret = ANSI_GB2312; for (u16 i = 0; i < len; i++) { if (str[i] < 0x7f) { continue; } else { if ((str[i] >= 0xf8 && str[i] <= 0xf9) || \ (str[i + 1] >= 0x40 && str[i + 1] <= 0x7e)) { ret = ANSI_BIG5; break; } i++; } } return ret; } bool user_lyric_info_get(LYRIC_INFO *info, u16 dbtime_s, u8 btime_100ms) { bool ret = 0; static u8 *utf8 = NULL; os_mutex_pend(&mutex, 0); if (lrc_analysis_flag == 1) { ret = lyric_info_get(info, dbtime_s, btime_100ms); if (info->update) { if (ui_text_utf8_check(info->buf, info->len) == 0) { if (utf8) { free(utf8); utf8 = NULL; } if (utf8 == NULL) { utf8 = zalloc(info->len * 2); } u8 ansi_type = ui_check_ansi_type(info->buf, info->len); if (ansi_type == ANSI_GB2312) { info->len = gbk_2_utf8(info->buf, info->len, utf8, info->len * 2); } else if (ansi_type == ANSI_BIG5) { info->len = big5_to_utf8(info->buf, info->len, utf8, info->len * 2); } info->buf = utf8; } } os_mutex_post(&mutex); return ret ; } else { os_mutex_post(&mutex); return false; } } bool lrc_get_api(u16 dbtime_s, u8 btime_100ms) { bool ret = 0; os_mutex_pend(&mutex, 0); if (lrc_analysis_flag == 1) { ret = lrc_get(dbtime_s, btime_100ms); return ret ; os_mutex_post(&mutex); return ret; } else { os_mutex_post(&mutex); return false; } } bool lrc_analysis_api(FILE *file, FILE **newFile) { void *ext_name = "LRC"; LRC_FILE_IO *p_lrc_file_io = &lrc_file_io; if (!lrc_info_buf) { return false; } os_mutex_pend(&mutex, 0); if (*newFile) { fclose(*newFile); *newFile = NULL; } if (0 == lrc_find(file, newFile, ext_name)) { if (false == lrc_analysis(*newFile, p_lrc_file_io)) { printf("lrc analazy err \n"); os_mutex_post(&mutex); return false; } else { printf("lrc analazy succ \n"); os_mutex_post(&mutex); return true; } } else { printf("lrc_find err\n"); os_mutex_post(&mutex); return false; } } /*----------------------------------------------------------------------------*/ /**@brief 歌词显示,默认显示两行 @param lrc_show_flag:滚动显示标志 lrc_update:显示下一条歌词内容标志 @return true--成功 @note 可以根据xi需要修改该函数的实现方法 */ /*----------------------------------------------------------------------------*/ bool lrc_ui_show(int text_id, u8 encode_type, u8 *buf, int len, u8 lrc_show_flag, u8 lrc_update) { #if(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX) static int disp_len = 0; static u8 lrc_showbytes = 0; static u8 offset = 0; if (lrc_update) { disp_len = len; lrc_showbytes = 0; offset = 0; ui_text_set_text_by_id(LRC_TEXT_ID_SEC, "", 16, FONT_DEFAULT); } if (lrc_show_flag == 1) { if (LRC_UTF16_S == encode_type) { lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_FIR, buf + offset, disp_len, FONT_ENDIAN_SMALL, FONT_DEFAULT); } else if (LRC_UTF16_B == encode_type) { lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_FIR, buf + offset, disp_len, FONT_ENDIAN_BIG, FONT_DEFAULT); } else if (LRC_UTF8 == encode_type) { lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_FIR, buf + offset, disp_len, FONT_ENDIAN_SMALL, FONT_DEFAULT | FONT_SHOW_MULTI_LINE); } else { lrc_showbytes = ui_text_set_text_by_id(LRC_TEXT_ID_FIR, buf + offset, disp_len, FONT_DEFAULT); } offset += lrc_showbytes; if (LRC_UTF16_S == encode_type) { lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_SEC, buf + offset, disp_len, FONT_ENDIAN_SMALL, FONT_DEFAULT); } else if (LRC_UTF16_B == encode_type) { lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_SEC, buf + offset, disp_len, FONT_ENDIAN_BIG, FONT_DEFAULT); } else if (LRC_UTF8 == encode_type) { lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_SEC, buf + offset, disp_len, FONT_ENDIAN_SMALL, FONT_DEFAULT | FONT_SHOW_MULTI_LINE); } else { lrc_showbytes = ui_text_set_text_by_id(LRC_TEXT_ID_SEC, buf + offset, disp_len, FONT_DEFAULT); } } #endif return true; } #endif //TCFG_LRC_LYRICS_ENABLE