/********************* * INCLUDES *********************/ #ifndef _DEFAULT_SOURCE #define _DEFAULT_SOURCE /* needed for usleep() */ #endif #include #include #include #include #include #include #include #include "lvgl/lvgl.h" #include "e_port_disp.h" #include "e_player_list.h" #include "display/fbdev.h" // 全局变量声明 volatile sig_atomic_t running = true; // ✅ 新增:LVGL 9.x 要求的 Tick 回调(替代纯 tick_inc 线程) static uint32_t my_tick_cb(void) { struct timeval tv; gettimeofday(&tv, NULL); return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); } // 工具函数:字符串复制(安全处理) static void safe_strcpy(char *dest, const char *src, size_t max_len) { if (src && dest && max_len > 0) { strncpy(dest, src, max_len - 1); dest[max_len - 1] = '\0'; } } void *tick_thread(void *arg) { (void)arg; struct timespec ts = {0, 1000000}; // 1ms 休眠(nanosleep 比 usleep 更稳定) while (running) { // pthread_mutex_lock(&lvgl_mutex); lv_tick_inc(1); // pthread_mutex_unlock(&lvgl_mutex); nanosleep(&ts, NULL); // 替代 usleep,降低 CPU 占用 } return NULL; } // 信号处理函数 void handle_signal(int sig) { (void)sig; running = false; LV_LOG_USER("signal_handler:sig=%d", sig); } int main(int argc, char **argv) { (void)argc; /*Unused*/ (void)argv; /*Unused*/ if (argc > 1 && strcmp(argv[1], "--version") == 0) { // 输出格式:键=值,便于解析 printf("version=%s\n", APP_VERSION); printf("display_count=%d\n", DISP_COUNT); printf("protocol_version=%d\n", PROTOCOL_VERSION); printf("width=%d\n", LV_USE_HOR_SIZE); printf("height=%d\n", LV_USE_VER_SIZE); return 0; } running = true; // 设置信号处理 signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); signal(SIGABRT, handle_signal); /* 初始化LVGL */ lv_init(); lv_tick_set_cb(my_tick_cb); /* 初始化显示驱动 */ int ret = init_dev(); if (ret != 0) { printf("display init fail \n"); return 1; } pthread_t tick_tid; pthread_create(&tick_tid, NULL, tick_thread, NULL); pthread_detach(tick_tid); printf("Starting LVGL tick thread\n"); /*初始化文件系统 - 必须在加载图片前调用*/ lv_fs_posix_init(); disp_handle_t disp = get_front_display(); /* 创建 tag.gif 全屏背景动画 */ lv_obj_t *tag_gif = lv_gif_create(disp.root_obj); lv_gif_set_src(tag_gif, "A:usrdata/pic/tag.gif"); lv_obj_set_pos(tag_gif, 0, 0); /* 全屏 */ lv_obj_set_size(tag_gif, 800, 1280); lv_obj_clear_flag(tag_gif, LV_OBJ_FLAG_HIDDEN); lv_gif_restart(tag_gif); /* 创建 02.gif 小动画 - 右下角,缩小到 120x120 减少负载 */ lv_obj_t *small_gif = lv_gif_create(disp.root_obj); lv_gif_set_src(small_gif, "A:usrdata/pic/02.gif"); lv_obj_set_pos(small_gif, 800 - 150, 1280 - 150); /* 右下角:(680, 1160) */ lv_obj_set_size(small_gif, 150, 150); lv_obj_clear_flag(small_gif, LV_OBJ_FLAG_HIDDEN); lv_gif_restart(small_gif); //创建视频播放器 VideoPlayer *video_player=video_player_init(0); e_player_area area={0}; area.x = 0; area.y = 0; area.width = 800; area.height = 640; video_player_set_size(video_player,area); MediaPath *media_path = (MediaPath *)malloc(sizeof(MediaPath)); if (!media_path) { printf("[download_callback] 内存不足,添加播放列表失败"); return -1; } memset(media_path, 0, sizeof(MediaPath)); safe_strcpy(media_path->path, "/usrdata/downloads/lemon.MOV", MAX_URL_LEN); safe_strcpy(media_path->item_id, "", MAX_ID_LEN); safe_strcpy(media_path->deviceId, "700000000010", MAX_DEVICE_ID); safe_strcpy(media_path->downloadUrl, "", MAX_URL_LEN); safe_strcpy(media_path->file_name, "/usrdata/downloads/lemon.MOV", MAX_NAME_LEN); media_path->type = 1; // 视频 video_player_add_item(video_player, media_path); video_player_play(video_player); printf("[MAIN] 启动主循环\n"); fflush(stdout); // /* 主循环 */ while (running) { uint32_t wait_ms = lv_timer_handler(); // pthread_mutex_unlock(&lvgl_mutex); // LOGI("启动主循环---------<<<"); // 边界处理:避免 CPU 满载 wait_ms = (wait_ms == 0) ? 1 : wait_ms; wait_ms = (wait_ms > 500) ? 500 : wait_ms; lv_delay_ms(wait_ms); // ✅ LVGL 9.x 替代 lv_tick_wait 的正确方式 } disp_exit(); printf("app exit3 ~~~~~~~~~~\n"); return 0; }