mirror of https://github.com/jetkvm/kvm.git
move event handling to native
This commit is contained in:
parent
b3243b2742
commit
b707596f89
20
config.go
20
config.go
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/logging"
|
||||
|
@ -102,6 +103,25 @@ type Config struct {
|
|||
DefaultLogLevel string `json:"default_log_level"`
|
||||
}
|
||||
|
||||
func (c *Config) GetDisplayRotation() uint16 {
|
||||
rotationInt, err := strconv.ParseUint(c.DisplayRotation, 10, 16)
|
||||
if err != nil {
|
||||
logger.Warn().Err(err).Msg("invalid display rotation, using default")
|
||||
return 270
|
||||
}
|
||||
return uint16(rotationInt)
|
||||
}
|
||||
|
||||
func (c *Config) SetDisplayRotation(rotation string) error {
|
||||
_, err := strconv.ParseUint(rotation, 10, 16)
|
||||
if err != nil {
|
||||
logger.Warn().Err(err).Msg("invalid display rotation, using default")
|
||||
return err
|
||||
}
|
||||
c.DisplayRotation = rotation
|
||||
return nil
|
||||
}
|
||||
|
||||
const configPath = "/userdata/kvm_config.json"
|
||||
|
||||
var defaultConfig = &Config{
|
||||
|
|
38
display.go
38
display.go
|
@ -153,13 +153,6 @@ func waitCtrlAndRequestDisplayUpdate(shouldWakeDisplay bool) {
|
|||
func updateStaticContents() {
|
||||
//contents that never change
|
||||
nativeInstance.UpdateLabelIfChanged("home_info_mac_addr", networkState.MACString())
|
||||
systemVersion, appVersion, err := GetLocalVersion()
|
||||
if err == nil {
|
||||
nativeInstance.UpdateLabelIfChanged("boot_screen_version", systemVersion.String())
|
||||
nativeInstance.UpdateLabelIfChanged("boot_screen_app_version", appVersion.String())
|
||||
nativeInstance.UpdateLabelAndChangeVisibility("system_version", systemVersion.String())
|
||||
nativeInstance.UpdateLabelAndChangeVisibility("app_version", appVersion.String())
|
||||
}
|
||||
|
||||
// get cpu info
|
||||
cpuInfo, err := os.ReadFile("/proc/cpuinfo")
|
||||
|
@ -266,34 +259,6 @@ func wakeDisplay(force bool) {
|
|||
backlightState = 0
|
||||
}
|
||||
|
||||
// watchTsEvents monitors the touchscreen for events and simply calls wakeDisplay() to ensure the
|
||||
// touchscreen interface still works even with LCD dimming/off.
|
||||
// TODO: This is quite a hack, really we should be getting an event from jetkvm_native, or the whole display backlight
|
||||
// control should be hoisted up to jetkvm_native.
|
||||
func watchTsEvents() {
|
||||
ts, err := os.OpenFile(touchscreenDevice, os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
displayLogger.Warn().Err(err).Msg("failed to open touchscreen device")
|
||||
return
|
||||
}
|
||||
|
||||
defer ts.Close()
|
||||
|
||||
// This buffer is set to 24 bytes as that's the normal size of events on /dev/input
|
||||
// Reference: https://www.kernel.org/doc/Documentation/input/input.txt
|
||||
// This could potentially be set higher, to require multiple events to wake the display.
|
||||
buf := make([]byte, 24)
|
||||
for {
|
||||
_, err := ts.Read(buf)
|
||||
if err != nil {
|
||||
displayLogger.Warn().Err(err).Msg("failed to read from touchscreen device")
|
||||
return
|
||||
}
|
||||
|
||||
wakeDisplay(false)
|
||||
}
|
||||
}
|
||||
|
||||
// startBacklightTickers starts the two tickers for dimming and switching off the display
|
||||
// if they're not already set. This is done separately to the init routine as the "never dim"
|
||||
// option has the value set to zero, but time.NewTicker only accept positive values.
|
||||
|
@ -347,7 +312,6 @@ func initDisplay() {
|
|||
go func() {
|
||||
displayLogger.Info().Msg("setting initial display contents")
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
_, _ = nativeInstance.DisplaySetRotation(config.DisplayRotation)
|
||||
updateStaticContents()
|
||||
displayInited = true
|
||||
displayLogger.Info().Msg("display inited")
|
||||
|
@ -355,6 +319,4 @@ func initDisplay() {
|
|||
wakeDisplay(true)
|
||||
requestDisplayUpdate(true)
|
||||
}()
|
||||
|
||||
go watchTsEvents()
|
||||
}
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
build
|
||||
deps
|
||||
ui_index.c
|
File diff suppressed because it is too large
Load Diff
|
@ -1,53 +1,43 @@
|
|||
cmake_minimum_required(VERSION 3.14)
|
||||
include(FetchContent)
|
||||
include(ExternalProject)
|
||||
|
||||
project(jknative LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Specify path to own LVGL config header
|
||||
set(
|
||||
LV_CONF_PATH
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lv_conf.h
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
|
||||
set(
|
||||
LV_DRIVERS_PUBLIC_HEADERS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lv_drv_conf.h
|
||||
CACHE STRING "" FORCE
|
||||
)
|
||||
|
||||
# Rockchip SDK paths
|
||||
set(RK_SDK_BASE "/opt/jetkvm-native-buildkit")
|
||||
set(RK_MEDIA_OUTPUT "${RK_SDK_BASE}/media/out")
|
||||
set(RK_MEDIA_INCLUDE_PATH "${RK_MEDIA_OUTPUT}/include")
|
||||
set(RK_APP_MEDIA_LIBS_PATH "${RK_MEDIA_OUTPUT}/lib")
|
||||
|
||||
set(LV_BUILD_EXAMPLES 0 CACHE BOOL "" FORCE)
|
||||
set(LV_USE_KCONFIG ON CACHE BOOL "" FORCE)
|
||||
set(LV_BUILD_DEFCONFIG_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lvgl_defconfig CACHE PATH "" FORCE)
|
||||
|
||||
# # libgpiod
|
||||
|
||||
# ExternalProject_Add(libgpiod-project
|
||||
# URL https://mirrors.edge.kernel.org/pub/software/libs/libgpiod/libgpiod-2.2.tar.gz
|
||||
# URL_HASH SHA256=f89c2176250f1a9563265479eb8ad5f22a63f42db6a1f438effc570f0254d2f5
|
||||
# SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/libgpiod
|
||||
# BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/libgpiod
|
||||
# CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env CPPFLAGS=-fPIC ${CMAKE_CURRENT_SOURCE_DIR}/deps/libgpiod/configure --enable-tools=no CC=${CMAKE_C_COMPILER} --host=${CMAKE_HOST_SYSTEM_PROCESSOR}
|
||||
# BUILD_COMMAND make && make install
|
||||
# BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/deps/libgpiod/lib/libgpiod.a
|
||||
# )
|
||||
|
||||
|
||||
# Fetch LVGL from GitHub
|
||||
FetchContent_Declare(
|
||||
lvgl
|
||||
GIT_REPOSITORY https://github.com/lvgl/lvgl.git
|
||||
GIT_TAG v8.3.11
|
||||
GIT_TAG v9.3.0
|
||||
GIT_SHALLOW 1
|
||||
UPDATE_DISCONNECTED 1
|
||||
PATCH_COMMAND
|
||||
git apply ${CMAKE_CURRENT_SOURCE_DIR}/lvgl-no-examples.patch
|
||||
COMMAND rm -rf demos examples
|
||||
)
|
||||
)
|
||||
FetchContent_MakeAvailable(lvgl)
|
||||
|
||||
# Fetch LVGL drivers from GitHub
|
||||
FetchContent_Declare(
|
||||
lv_drivers
|
||||
GIT_REPOSITORY https://github.com/lvgl/lv_drivers.git
|
||||
GIT_TAG v8.3.0
|
||||
UPDATE_DISCONNECTED 1
|
||||
)
|
||||
FetchContent_MakeAvailable(lv_drivers)
|
||||
|
||||
# Get source files, excluding CMake generated files
|
||||
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "*.c" "ui/*.c")
|
||||
list(FILTER sources EXCLUDE REGEX "CMakeFiles.*CompilerId.*\\.c$")
|
||||
|
@ -60,18 +50,21 @@ target_include_directories(jknative PRIVATE
|
|||
${RK_MEDIA_INCLUDE_PATH}/libdrm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ui
|
||||
${CMAKE_CURRENT_BINARY_DIR}/deps/libgpiod/include
|
||||
)
|
||||
|
||||
# Set library search path
|
||||
target_link_directories(jknative PRIVATE ${RK_APP_MEDIA_LIBS_PATH})
|
||||
|
||||
# target_link_directories(jknative PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/deps/libgpiod/lib)
|
||||
|
||||
target_link_libraries(jknative PRIVATE
|
||||
lvgl::lvgl
|
||||
lvgl::drivers
|
||||
pthread
|
||||
rockit
|
||||
rockchip_mpp
|
||||
rga
|
||||
m
|
||||
)
|
||||
# libgpiod
|
||||
)
|
||||
|
||||
install(TARGETS jknative DESTINATION lib)
|
File diff suppressed because it is too large
Load Diff
|
@ -1,19 +1,53 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
C_RST="$(tput sgr0)"
|
||||
C_ERR="$(tput setaf 1)"
|
||||
C_OK="$(tput setaf 2)"
|
||||
C_WARN="$(tput setaf 3)"
|
||||
C_INFO="$(tput setaf 5)"
|
||||
|
||||
msg() { printf '%s%s%s\n' $2 "$1" $C_RST; }
|
||||
|
||||
msg_info() { msg "$1" $C_INFO; }
|
||||
msg_ok() { msg "$1" $C_OK; }
|
||||
msg_err() { msg "$1" $C_ERR; }
|
||||
msg_warn() { msg "$1" $C_WARN; }
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
BUILD_DIR=${SCRIPT_DIR}/build
|
||||
|
||||
CMAKE_TOOLCHAIN_FILE=/opt/jetkvm-native-buildkit/rv1106-jetkvm-v2.cmake
|
||||
CLEAN_ALL=${CLEAN_ALL:-0}
|
||||
|
||||
if [ "$CLEAN_ALL" -eq 1 ]; then
|
||||
find . -name build -exec rm -r {} +
|
||||
rm -rf "${BUILD_DIR}"
|
||||
fi
|
||||
|
||||
set -x
|
||||
VERBOSE=1 cmake -B build \
|
||||
TMP_DIR=$(mktemp -d)
|
||||
pushd "${SCRIPT_DIR}" > /dev/null
|
||||
|
||||
msg_info "▶ Generating UI index"
|
||||
./ui_index.gen.sh
|
||||
|
||||
msg_info "▶ Building native library"
|
||||
VERBOSE=1 cmake -B "${BUILD_DIR}" \
|
||||
-DCMAKE_SYSTEM_PROCESSOR=armv7l \
|
||||
-DCMAKE_SYSTEM_NAME=Linux \
|
||||
-DCMAKE_CROSSCOMPILING=1 \
|
||||
-DCMAKE_TOOLCHAIN_FILE=$CMAKE_TOOLCHAIN_FILE \
|
||||
-DLV_BUILD_USE_KCONFIG=ON \
|
||||
-DLV_BUILD_DEFCONFIG_PATH=${SCRIPT_DIR}/lvgl_defconfig \
|
||||
-DCONFIG_LV_BUILD_EXAMPLES=OFF \
|
||||
-DCONFIG_LV_BUILD_DEMOS=OFF \
|
||||
-DSKIP_GLIBC_NAMES=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="${TMP_DIR}"
|
||||
|
||||
cmake --build build
|
||||
msg_info "▶ Copying built library and header files"
|
||||
cmake --build "${BUILD_DIR}" --target install
|
||||
cp -r "${TMP_DIR}/include" ../
|
||||
cp -r "${TMP_DIR}/lib" ../
|
||||
rm -rf "${TMP_DIR}"
|
||||
|
||||
popd > /dev/null
|
||||
|
|
|
@ -30,6 +30,15 @@ void jetkvm_set_video_handler(jetkvm_video_handler_t *handler) {
|
|||
video_handler = handler;
|
||||
}
|
||||
|
||||
void jetkvm_set_indev_handler(jetkvm_indev_handler_t *handler) {
|
||||
lvgl_set_indev_handler(handler);
|
||||
}
|
||||
|
||||
const char *jetkvm_ui_event_code_to_name(int code) {
|
||||
lv_event_code_t cCode = (lv_event_code_t)code;
|
||||
return lv_event_code_get_name(code);
|
||||
}
|
||||
|
||||
void video_report_format(bool ready, const char *error, u_int16_t width, u_int16_t height, double frame_per_second)
|
||||
{
|
||||
state.ready = ready;
|
||||
|
@ -174,8 +183,8 @@ const char *jetkvm_ui_get_var(const char *name) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void jetkvm_ui_init() {
|
||||
lvgl_init();
|
||||
void jetkvm_ui_init(u_int16_t rotation) {
|
||||
lvgl_init(rotation);
|
||||
}
|
||||
|
||||
void jetkvm_ui_tick() {
|
||||
|
@ -186,19 +195,9 @@ void jetkvm_set_video_state_handler(jetkvm_video_state_handler_t *handler) {
|
|||
video_state_handler = handler;
|
||||
}
|
||||
|
||||
void jetkvm_ui_set_rotation(u_int8_t rotation)
|
||||
void jetkvm_ui_set_rotation(u_int16_t rotation)
|
||||
{
|
||||
printf("setting rotation to %d\n", rotation);
|
||||
if (rotation == 90)
|
||||
{
|
||||
lv_disp_set_rotation(NULL, LV_DISP_ROT_90);
|
||||
} else if (rotation == 180) {
|
||||
lv_disp_set_rotation(NULL, LV_DISP_ROT_180);
|
||||
} else if (rotation == 270) {
|
||||
lv_disp_set_rotation(NULL, LV_DISP_ROT_270);
|
||||
} else {
|
||||
lv_disp_set_rotation(NULL, LV_DISP_ROT_NONE);
|
||||
}
|
||||
lvgl_set_rotation(NULL, rotation);
|
||||
}
|
||||
|
||||
const char *jetkvm_ui_get_current_screen() {
|
||||
|
|
|
@ -16,21 +16,22 @@ typedef struct
|
|||
|
||||
typedef void (jetkvm_video_state_handler_t)(jetkvm_video_state_t *state);
|
||||
typedef void (jetkvm_log_handler_t)(int level, const char *filename, const char *funcname, int line, const char *message);
|
||||
|
||||
typedef void (jetkvm_video_handler_t)(const uint8_t *frame, ssize_t len);
|
||||
typedef void (jetkvm_indev_handler_t)(int code);
|
||||
|
||||
void jetkvm_set_log_handler(jetkvm_log_handler_t *handler);
|
||||
void jetkvm_set_video_handler(jetkvm_video_handler_t *handler);
|
||||
void jetkvm_set_indev_handler(jetkvm_indev_handler_t *handler);
|
||||
void jetkvm_set_video_state_handler(jetkvm_video_state_handler_t *handler);
|
||||
|
||||
void jetkvm_ui_set_var(const char *name, const char *value);
|
||||
const char *jetkvm_ui_get_var(const char *name);
|
||||
|
||||
void jetkvm_ui_init();
|
||||
void jetkvm_ui_init(u_int16_t rotation);
|
||||
void jetkvm_ui_tick();
|
||||
|
||||
void jetkvm_set_video_state_handler(jetkvm_video_state_handler_t *handler);
|
||||
|
||||
void jetkvm_ui_set_rotation(u_int8_t rotation);
|
||||
void jetkvm_ui_set_rotation(u_int16_t rotation);
|
||||
const char *jetkvm_ui_get_current_screen();
|
||||
void jetkvm_ui_load_screen(const char *obj_name);
|
||||
int jetkvm_ui_set_text(const char *obj_name, const char *text);
|
||||
|
@ -42,6 +43,8 @@ void jetkvm_ui_set_opacity(const char *obj_name, u_int8_t opacity);
|
|||
int jetkvm_ui_add_flag(const char *obj_name, const char *flag_name);
|
||||
int jetkvm_ui_clear_flag(const char *obj_name, const char *flag_name);
|
||||
|
||||
const char *jetkvm_ui_event_code_to_name(int code);
|
||||
|
||||
int jetkvm_video_init();
|
||||
void jetkvm_video_shutdown();
|
||||
void jetkvm_video_start();
|
||||
|
@ -55,4 +58,6 @@ jetkvm_video_state_t *jetkvm_video_get_status();
|
|||
void video_report_format(bool ready, const char *error, u_int16_t width, u_int16_t height, double frame_per_second);
|
||||
int video_send_frame(const uint8_t *frame, ssize_t len);
|
||||
|
||||
|
||||
|
||||
#endif //VIDEO_DAEMON_CTRL_H
|
||||
|
|
|
@ -1,608 +0,0 @@
|
|||
/**
|
||||
* @file lv_conf.h
|
||||
* Configuration file for v8.1.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copy this file as `lv_conf.h`
|
||||
* 1. simply next to the `lvgl` folder
|
||||
* 2. or any other places and
|
||||
* - define `LV_CONF_INCLUDE_SIMPLE`
|
||||
* - add the path as include path
|
||||
*/
|
||||
|
||||
/* clang-format off */
|
||||
#if 1 /*Set it to "1" to enable content*/
|
||||
|
||||
#ifndef LV_CONF_H
|
||||
#define LV_CONF_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*====================
|
||||
COLOR SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
|
||||
#define LV_COLOR_DEPTH 16
|
||||
|
||||
/*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/
|
||||
#define LV_COLOR_16_SWAP 0
|
||||
|
||||
/*Enable more complex drawing routines to manage screens transparency.
|
||||
*Can be used if the UI is above another layer, e.g. an OSD menu or video player.
|
||||
*Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/
|
||||
#define LV_COLOR_SCREEN_TRANSP 0
|
||||
|
||||
/* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently.
|
||||
* 0: round down, 64: round up from x.75, 128: round up from half, 192: round up from x.25, 254: round up */
|
||||
#define LV_COLOR_MIX_ROUND_OFS (LV_COLOR_DEPTH == 32 ? 0: 128)
|
||||
|
||||
/*Images pixels with this color will not be drawn if they are chroma keyed)*/
|
||||
#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00) /*pure green*/
|
||||
|
||||
/*=========================
|
||||
MEMORY SETTINGS
|
||||
*=========================*/
|
||||
|
||||
/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
|
||||
#define LV_MEM_CUSTOM 1
|
||||
#if LV_MEM_CUSTOM == 0
|
||||
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
|
||||
# define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/
|
||||
|
||||
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
|
||||
# define LV_MEM_ADR 0 /*0: unused*/
|
||||
/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/
|
||||
#if LV_MEM_ADR == 0
|
||||
//#define LV_MEM_POOL_INCLUDE your_alloc_library /* Uncomment if using an external allocator*/
|
||||
//#define LV_MEM_POOL_ALLOC your_alloc /* Uncomment if using an external allocator*/
|
||||
#endif
|
||||
|
||||
#else /*LV_MEM_CUSTOM*/
|
||||
# define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/
|
||||
# define LV_MEM_CUSTOM_ALLOC malloc
|
||||
# define LV_MEM_CUSTOM_FREE free
|
||||
# define LV_MEM_CUSTOM_REALLOC realloc
|
||||
#endif /*LV_MEM_CUSTOM*/
|
||||
|
||||
/*Number of the intermediate memory buffer used during rendering and other internal processing mechanisms.
|
||||
*You will see an error log message if there wasn't enough buffers. */
|
||||
#define LV_MEM_BUF_MAX_NUM 16
|
||||
|
||||
/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/
|
||||
#define LV_MEMCPY_MEMSET_STD 0
|
||||
|
||||
/*====================
|
||||
HAL SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*Default display refresh period. LVG will redraw changed areas with this period time*/
|
||||
#define LV_DISP_DEF_REFR_PERIOD 10 /*[ms]*/
|
||||
|
||||
/*Input device read period in milliseconds*/
|
||||
#define LV_INDEV_DEF_READ_PERIOD 10 /*[ms]*/
|
||||
|
||||
/*Use a custom tick source that tells the elapsed time in milliseconds.
|
||||
*It removes the need to manually update the tick with `lv_tick_inc()`)*/
|
||||
// #define LV_TICK_CUSTOM 0
|
||||
// #if LV_TICK_CUSTOM
|
||||
// #define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
|
||||
// #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
|
||||
// #endif /*LV_TICK_CUSTOM*/
|
||||
#define LV_TICK_CUSTOM 1
|
||||
#if LV_TICK_CUSTOM
|
||||
#define LV_TICK_CUSTOM_INCLUDE <stdint.h> /*Header for the system time function*/
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (custom_tick_get()) /*Expression evaluating to current system time in ms*/
|
||||
#endif /*LV_TICK_CUSTOM*/
|
||||
|
||||
/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.
|
||||
*(Not so important, you can adjust it to modify default sizes and spaces)*/
|
||||
#define LV_DPI_DEF 130 /*[px/inch]*/
|
||||
|
||||
/*=======================
|
||||
* FEATURE CONFIGURATION
|
||||
*=======================*/
|
||||
|
||||
/*-------------
|
||||
* Drawing
|
||||
*-----------*/
|
||||
|
||||
/*Enable complex draw engine.
|
||||
*Required to draw shadow, gradient, rounded corners, circles, arc, skew lines, image transformations or any masks*/
|
||||
#define LV_DRAW_COMPLEX 1
|
||||
#if LV_DRAW_COMPLEX != 0
|
||||
|
||||
/*Allow buffering some shadow calculation.
|
||||
*LV_SHADOW_CACHE_SIZE is the max. shadow size to buffer, where shadow size is `shadow_width + radius`
|
||||
*Caching has LV_SHADOW_CACHE_SIZE^2 RAM cost*/
|
||||
#define LV_SHADOW_CACHE_SIZE 0
|
||||
|
||||
/* Set number of maximally cached circle data.
|
||||
* The circumference of 1/4 circle are saved for anti-aliasing
|
||||
* radius * 4 bytes are used per circle (the most often used radiuses are saved)
|
||||
* 0: to disable caching */
|
||||
#define LV_CIRCLE_CACHE_SIZE 4
|
||||
|
||||
#endif /*LV_DRAW_COMPLEX*/
|
||||
|
||||
/*Default image cache size. Image caching keeps the images opened.
|
||||
*If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added)
|
||||
*With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
|
||||
*However the opened images might consume additional RAM.
|
||||
*0: to disable caching*/
|
||||
#define LV_IMG_CACHE_DEF_SIZE 0
|
||||
|
||||
/*Maximum buffer size to allocate for rotation. Only used if software rotation is enabled in the display driver.*/
|
||||
#define LV_DISP_ROT_MAX_BUF (10*1024)
|
||||
|
||||
/*-------------
|
||||
* GPU
|
||||
*-----------*/
|
||||
|
||||
/*Use STM32's DMA2D (aka Chrom Art) GPU*/
|
||||
#define LV_USE_GPU_STM32_DMA2D 0
|
||||
#if LV_USE_GPU_STM32_DMA2D
|
||||
/*Must be defined to include path of CMSIS header of target processor
|
||||
e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
|
||||
#define LV_GPU_DMA2D_CMSIS_INCLUDE
|
||||
#endif
|
||||
|
||||
/*Use NXP's PXP GPU iMX RTxxx platforms*/
|
||||
#define LV_USE_GPU_NXP_PXP 0
|
||||
#if LV_USE_GPU_NXP_PXP
|
||||
/*1: Add default bare metal and FreeRTOS interrupt handling routines for PXP (lv_gpu_nxp_pxp_osa.c)
|
||||
* and call lv_gpu_nxp_pxp_init() automatically during lv_init(). Note that symbol SDK_OS_FREE_RTOS
|
||||
* has to be defined in order to use FreeRTOS OSA, otherwise bare-metal implementation is selected.
|
||||
*0: lv_gpu_nxp_pxp_init() has to be called manually before lv_init()
|
||||
*/
|
||||
#define LV_USE_GPU_NXP_PXP_AUTO_INIT 0
|
||||
#endif
|
||||
|
||||
/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/
|
||||
#define LV_USE_GPU_NXP_VG_LITE 0
|
||||
|
||||
/*Use exnternal renderer*/
|
||||
#define LV_USE_EXTERNAL_RENDERER 0
|
||||
|
||||
/*Use SDL renderer API. Requires LV_USE_EXTERNAL_RENDERER*/
|
||||
#define LV_USE_GPU_SDL 0
|
||||
#if LV_USE_GPU_SDL
|
||||
# define LV_GPU_SDL_INCLUDE_PATH <SDL2/SDL.h>
|
||||
#endif
|
||||
|
||||
/*-------------
|
||||
* Logging
|
||||
*-----------*/
|
||||
|
||||
/*Enable the log module*/
|
||||
#define LV_USE_LOG 0
|
||||
#if LV_USE_LOG
|
||||
|
||||
/*How important log should be added:
|
||||
*LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
|
||||
*LV_LOG_LEVEL_INFO Log important events
|
||||
*LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem
|
||||
*LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
|
||||
*LV_LOG_LEVEL_USER Only logs added by the user
|
||||
*LV_LOG_LEVEL_NONE Do not log anything*/
|
||||
# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||
|
||||
/*1: Print the log with 'printf';
|
||||
*0: User need to register a callback with `lv_log_register_print_cb()`*/
|
||||
# define LV_LOG_PRINTF 0
|
||||
|
||||
/*Enable/disable LV_LOG_TRACE in modules that produces a huge number of logs*/
|
||||
# define LV_LOG_TRACE_MEM 1
|
||||
# define LV_LOG_TRACE_TIMER 1
|
||||
# define LV_LOG_TRACE_INDEV 1
|
||||
# define LV_LOG_TRACE_DISP_REFR 1
|
||||
# define LV_LOG_TRACE_EVENT 1
|
||||
# define LV_LOG_TRACE_OBJ_CREATE 1
|
||||
# define LV_LOG_TRACE_LAYOUT 1
|
||||
# define LV_LOG_TRACE_ANIM 1
|
||||
|
||||
#endif /*LV_USE_LOG*/
|
||||
|
||||
/*-------------
|
||||
* Asserts
|
||||
*-----------*/
|
||||
|
||||
/*Enable asserts if an operation is failed or an invalid data is found.
|
||||
*If LV_USE_LOG is enabled an error message will be printed on failure*/
|
||||
#define LV_USE_ASSERT_NULL 1 /*Check if the parameter is NULL. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MALLOC 1 /*Checks is the memory is successfully allocated or no. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_STYLE 0 /*Check if the styles are properly initialized. (Very fast, recommended)*/
|
||||
#define LV_USE_ASSERT_MEM_INTEGRITY 0 /*Check the integrity of `lv_mem` after critical operations. (Slow)*/
|
||||
#define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/
|
||||
|
||||
/*Add a custom handler when assert happens e.g. to restart the MCU*/
|
||||
#define LV_ASSERT_HANDLER_INCLUDE <stdint.h>
|
||||
#define LV_ASSERT_HANDLER while(1); /*Halt by default*/
|
||||
|
||||
/*-------------
|
||||
* Others
|
||||
*-----------*/
|
||||
|
||||
/*1: Show CPU usage and FPS count in the right bottom corner*/
|
||||
#define LV_USE_PERF_MONITOR 0
|
||||
#if LV_USE_PERF_MONITOR
|
||||
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
|
||||
#endif
|
||||
|
||||
/*1: Show the used memory and the memory fragmentation in the left bottom corner
|
||||
* Requires LV_MEM_CUSTOM = 0*/
|
||||
#define LV_USE_MEM_MONITOR 0
|
||||
#if LV_USE_PERF_MONITOR
|
||||
#define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT
|
||||
#endif
|
||||
|
||||
/*1: Draw random colored rectangles over the redrawn areas*/
|
||||
#define LV_USE_REFR_DEBUG 0
|
||||
|
||||
/*Change the built in (v)snprintf functions*/
|
||||
#define LV_SPRINTF_CUSTOM 0
|
||||
#if LV_SPRINTF_CUSTOM
|
||||
# define LV_SPRINTF_INCLUDE <stdio.h>
|
||||
# define lv_snprintf snprintf
|
||||
# define lv_vsnprintf vsnprintf
|
||||
#else /*LV_SPRINTF_CUSTOM*/
|
||||
# define LV_SPRINTF_USE_FLOAT 0
|
||||
#endif /*LV_SPRINTF_CUSTOM*/
|
||||
|
||||
#define LV_USE_USER_DATA 1
|
||||
|
||||
/*Garbage Collector settings
|
||||
*Used if lvgl is bound to higher level language and the memory is managed by that language*/
|
||||
#define LV_ENABLE_GC 0
|
||||
#if LV_ENABLE_GC != 0
|
||||
# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
|
||||
#endif /*LV_ENABLE_GC*/
|
||||
|
||||
/*=====================
|
||||
* COMPILER SETTINGS
|
||||
*====================*/
|
||||
|
||||
/*For big endian systems set to 1*/
|
||||
#define LV_BIG_ENDIAN_SYSTEM 0
|
||||
|
||||
/*Define a custom attribute to `lv_tick_inc` function*/
|
||||
#define LV_ATTRIBUTE_TICK_INC
|
||||
|
||||
/*Define a custom attribute to `lv_timer_handler` function*/
|
||||
#define LV_ATTRIBUTE_TIMER_HANDLER
|
||||
|
||||
/*Define a custom attribute to `lv_disp_flush_ready` function*/
|
||||
#define LV_ATTRIBUTE_FLUSH_READY
|
||||
|
||||
/*Required alignment size for buffers*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1
|
||||
|
||||
/*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default).
|
||||
* E.g. __attribute__((aligned(4)))*/
|
||||
#define LV_ATTRIBUTE_MEM_ALIGN
|
||||
|
||||
/*Attribute to mark large constant arrays for example font's bitmaps*/
|
||||
#define LV_ATTRIBUTE_LARGE_CONST
|
||||
|
||||
/*Complier prefix for a big array declaration in RAM*/
|
||||
#define LV_ATTRIBUTE_LARGE_RAM_ARRAY
|
||||
|
||||
/*Place performance critical functions into a faster memory (e.g RAM)*/
|
||||
#define LV_ATTRIBUTE_FAST_MEM
|
||||
|
||||
/*Prefix variables that are used in GPU accelerated operations, often these need to be placed in RAM sections that are DMA accessible*/
|
||||
#define LV_ATTRIBUTE_DMA
|
||||
|
||||
/*Export integer constant to binding. This macro is used with constants in the form of LV_<CONST> that
|
||||
*should also appear on LVGL binding API such as Micropython.*/
|
||||
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning /*The default value just prevents GCC warning*/
|
||||
|
||||
/*Extend the default -32k..32k coordinate range to -4M..4M by using int32_t for coordinates instead of int16_t*/
|
||||
#define LV_USE_LARGE_COORD 0
|
||||
|
||||
/*==================
|
||||
* FONT USAGE
|
||||
*===================*/
|
||||
|
||||
/*Montserrat fonts with ASCII range and some symbols using bpp = 4
|
||||
*https://fonts.google.com/specimen/Montserrat*/
|
||||
#define LV_FONT_MONTSERRAT_8 0
|
||||
#define LV_FONT_MONTSERRAT_10 0
|
||||
#define LV_FONT_MONTSERRAT_12 0
|
||||
#define LV_FONT_MONTSERRAT_14 1
|
||||
#define LV_FONT_MONTSERRAT_16 0
|
||||
#define LV_FONT_MONTSERRAT_18 0
|
||||
#define LV_FONT_MONTSERRAT_20 0
|
||||
#define LV_FONT_MONTSERRAT_22 0
|
||||
#define LV_FONT_MONTSERRAT_24 0
|
||||
#define LV_FONT_MONTSERRAT_26 0
|
||||
#define LV_FONT_MONTSERRAT_28 0
|
||||
#define LV_FONT_MONTSERRAT_30 0
|
||||
#define LV_FONT_MONTSERRAT_32 0
|
||||
#define LV_FONT_MONTSERRAT_34 0
|
||||
#define LV_FONT_MONTSERRAT_36 0
|
||||
#define LV_FONT_MONTSERRAT_38 0
|
||||
#define LV_FONT_MONTSERRAT_40 0
|
||||
#define LV_FONT_MONTSERRAT_42 0
|
||||
#define LV_FONT_MONTSERRAT_44 0
|
||||
#define LV_FONT_MONTSERRAT_46 0
|
||||
#define LV_FONT_MONTSERRAT_48 0
|
||||
|
||||
/*Demonstrate special features*/
|
||||
#define LV_FONT_MONTSERRAT_12_SUBPX 0
|
||||
#define LV_FONT_MONTSERRAT_28_COMPRESSED 0 /*bpp = 3*/
|
||||
#define LV_FONT_DEJAVU_16_PERSIAN_HEBREW 0 /*Hebrew, Arabic, Perisan letters and all their forms*/
|
||||
#define LV_FONT_SIMSUN_16_CJK 0 /*1000 most common CJK radicals*/
|
||||
|
||||
/*Pixel perfect monospace fonts*/
|
||||
#define LV_FONT_UNSCII_8 0
|
||||
#define LV_FONT_UNSCII_16 0
|
||||
|
||||
/*Optionally declare custom fonts here.
|
||||
*You can use these fonts as default font too and they will be available globally.
|
||||
*E.g. #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) LV_FONT_DECLARE(my_font_2)*/
|
||||
#define LV_FONT_CUSTOM_DECLARE
|
||||
|
||||
/*Always set a default font*/
|
||||
#define LV_FONT_DEFAULT &lv_font_montserrat_14
|
||||
|
||||
/*Enable handling large font and/or fonts with a lot of characters.
|
||||
*The limit depends on the font size, font face and bpp.
|
||||
*Compiler error will be triggered if a font needs it.*/
|
||||
#define LV_FONT_FMT_TXT_LARGE 0
|
||||
|
||||
/*Enables/disables support for compressed fonts.*/
|
||||
#define LV_USE_FONT_COMPRESSED 0
|
||||
|
||||
/*Enable subpixel rendering*/
|
||||
#define LV_USE_FONT_SUBPX 0
|
||||
#if LV_USE_FONT_SUBPX
|
||||
/*Set the pixel order of the display. Physical order of RGB channels. Doesn't matter with "normal" fonts.*/
|
||||
#define LV_FONT_SUBPX_BGR 0 /*0: RGB; 1:BGR order*/
|
||||
#endif
|
||||
|
||||
/*=================
|
||||
* TEXT SETTINGS
|
||||
*=================*/
|
||||
|
||||
/**
|
||||
* Select a character encoding for strings.
|
||||
* Your IDE or editor should have the same character encoding
|
||||
* - LV_TXT_ENC_UTF8
|
||||
* - LV_TXT_ENC_ASCII
|
||||
*/
|
||||
#define LV_TXT_ENC LV_TXT_ENC_UTF8
|
||||
|
||||
/*Can break (wrap) texts on these chars*/
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||
|
||||
/*If a word is at least this long, will break wherever "prettiest"
|
||||
*To disable, set to a value <= 0*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 0
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line before a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
|
||||
/*Minimum number of characters in a long word to put on a line after a break.
|
||||
*Depends on LV_TXT_LINE_BREAK_LONG_LEN.*/
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
|
||||
/*The control character to use for signalling text recoloring.*/
|
||||
#define LV_TXT_COLOR_CMD "#"
|
||||
|
||||
/*Support bidirectional texts. Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
*The direction will be processed according to the Unicode Bidirectional Algorithm:
|
||||
*https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
|
||||
#define LV_USE_BIDI 0
|
||||
#if LV_USE_BIDI
|
||||
/*Set the default direction. Supported values:
|
||||
*`LV_BASE_DIR_LTR` Left-to-Right
|
||||
*`LV_BASE_DIR_RTL` Right-to-Left
|
||||
*`LV_BASE_DIR_AUTO` detect texts base direction*/
|
||||
#define LV_BIDI_BASE_DIR_DEF LV_BASE_DIR_AUTO
|
||||
#endif
|
||||
|
||||
/*Enable Arabic/Persian processing
|
||||
*In these languages characters should be replaced with an other form based on their position in the text*/
|
||||
#define LV_USE_ARABIC_PERSIAN_CHARS 0
|
||||
|
||||
/*==================
|
||||
* WIDGET USAGE
|
||||
*================*/
|
||||
|
||||
/*Documentation of the widgets: https://docs.lvgl.io/latest/en/html/widgets/index.html*/
|
||||
|
||||
#define LV_USE_ARC 1
|
||||
|
||||
#define LV_USE_ANIMIMG 1
|
||||
|
||||
#define LV_USE_BAR 1
|
||||
|
||||
#define LV_USE_BTN 1
|
||||
|
||||
#define LV_USE_BTNMATRIX 1
|
||||
|
||||
#define LV_USE_CANVAS 1
|
||||
|
||||
#define LV_USE_CHECKBOX 1
|
||||
|
||||
#define LV_USE_DROPDOWN 0 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_IMG 1 /*Requires: lv_label*/
|
||||
|
||||
#define LV_USE_LABEL 1
|
||||
#if LV_USE_LABEL
|
||||
# define LV_LABEL_TEXT_SELECTION 1 /*Enable selecting text of the label*/
|
||||
# define LV_LABEL_LONG_TXT_HINT 1 /*Store some extra info in labels to speed up drawing of very long texts*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_LINE 1
|
||||
|
||||
#define LV_USE_ROLLER 0 /*Requires: lv_label*/
|
||||
#if LV_USE_ROLLER
|
||||
# define LV_ROLLER_INF_PAGES 7 /*Number of extra "pages" when the roller is infinite*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_SLIDER 1 /*Requires: lv_bar*/
|
||||
|
||||
#define LV_USE_SWITCH 1
|
||||
|
||||
#define LV_USE_TEXTAREA 1 /*Requires: lv_label*/
|
||||
#if LV_USE_TEXTAREA != 0
|
||||
# define LV_TEXTAREA_DEF_PWD_SHOW_TIME 1500 /*ms*/
|
||||
#endif
|
||||
|
||||
#define LV_USE_TABLE 0
|
||||
|
||||
/*==================
|
||||
* EXTRA COMPONENTS
|
||||
*==================*/
|
||||
|
||||
/*-----------
|
||||
* Widgets
|
||||
*----------*/
|
||||
#define LV_USE_CALENDAR 0
|
||||
#if LV_USE_CALENDAR
|
||||
# define LV_CALENDAR_WEEK_STARTS_MONDAY 0
|
||||
# if LV_CALENDAR_WEEK_STARTS_MONDAY
|
||||
# define LV_CALENDAR_DEFAULT_DAY_NAMES {"Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"}
|
||||
# else
|
||||
# define LV_CALENDAR_DEFAULT_DAY_NAMES {"Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"}
|
||||
# endif
|
||||
|
||||
# define LV_CALENDAR_DEFAULT_MONTH_NAMES {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
|
||||
# define LV_USE_CALENDAR_HEADER_ARROW 1
|
||||
# define LV_USE_CALENDAR_HEADER_DROPDOWN 1
|
||||
#endif /*LV_USE_CALENDAR*/
|
||||
|
||||
#define LV_USE_CHART 0
|
||||
|
||||
#define LV_USE_COLORWHEEL 0
|
||||
|
||||
#define LV_USE_IMGBTN 1
|
||||
|
||||
#define LV_USE_KEYBOARD 1
|
||||
|
||||
#define LV_USE_LED 0
|
||||
|
||||
#define LV_USE_LIST 1
|
||||
|
||||
#define LV_USE_METER 0
|
||||
|
||||
#define LV_USE_MSGBOX 0
|
||||
|
||||
#define LV_USE_SPINBOX 0
|
||||
|
||||
#define LV_USE_SPINNER 0
|
||||
|
||||
#define LV_USE_TABVIEW 0
|
||||
|
||||
#define LV_USE_TILEVIEW 0
|
||||
|
||||
#define LV_USE_WIN 0
|
||||
|
||||
#define LV_USE_SPAN 1
|
||||
#if LV_USE_SPAN
|
||||
/*A line text can contain maximum num of span descriptor */
|
||||
# define LV_SPAN_SNIPPET_STACK_SIZE 64
|
||||
#endif
|
||||
|
||||
/*-----------
|
||||
* Themes
|
||||
*----------*/
|
||||
|
||||
/*A simple, impressive and very complete theme*/
|
||||
#define LV_USE_THEME_DEFAULT 1
|
||||
#if LV_USE_THEME_DEFAULT
|
||||
|
||||
/*0: Light mode; 1: Dark mode*/
|
||||
# define LV_THEME_DEFAULT_DARK 0
|
||||
|
||||
/*1: Enable grow on press*/
|
||||
# define LV_THEME_DEFAULT_GROW 1
|
||||
|
||||
/*Default transition time in [ms]*/
|
||||
# define LV_THEME_DEFAULT_TRANSITION_TIME 80
|
||||
#endif /*LV_USE_THEME_DEFAULT*/
|
||||
|
||||
/*A very simple theme that is a good starting point for a custom theme*/
|
||||
#define LV_USE_THEME_BASIC 1
|
||||
|
||||
/*A theme designed for monochrome displays*/
|
||||
#define LV_USE_THEME_MONO 0
|
||||
|
||||
/*-----------
|
||||
* Layouts
|
||||
*----------*/
|
||||
|
||||
/*A layout similar to Flexbox in CSS.*/
|
||||
#define LV_USE_FLEX 1
|
||||
|
||||
/*A layout similar to Grid in CSS.*/
|
||||
#define LV_USE_GRID 1
|
||||
|
||||
/*---------------------
|
||||
* 3rd party libraries
|
||||
*--------------------*/
|
||||
|
||||
/*File system interfaces for common APIs
|
||||
*To enable set a driver letter for that API*/
|
||||
#define LV_USE_FS_STDIO '\0' /*Uses fopen, fread, etc*/
|
||||
//#define LV_FS_STDIO_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */
|
||||
|
||||
#define LV_USE_FS_POSIX '\0' /*Uses open, read, etc*/
|
||||
//#define LV_FS_POSIX_PATH "/home/john/" /*Set the working directory. If commented it will be "./" */
|
||||
|
||||
#define LV_USE_FS_WIN32 '\0' /*Uses CreateFile, ReadFile, etc*/
|
||||
//#define LV_FS_WIN32_PATH "C:\\Users\\john\\" /*Set the working directory. If commented it will be ".\\" */
|
||||
|
||||
#define LV_USE_FS_FATFS '\0' /*Uses f_open, f_read, etc*/
|
||||
|
||||
/*PNG decoder library*/
|
||||
#define LV_USE_PNG 0
|
||||
|
||||
/*BMP decoder library*/
|
||||
#define LV_USE_BMP 0
|
||||
|
||||
/* JPG + split JPG decoder library.
|
||||
* Split JPG is a custom format optimized for embedded systems. */
|
||||
#define LV_USE_SJPG 0
|
||||
|
||||
/*GIF decoder library*/
|
||||
#define LV_USE_GIF 0
|
||||
|
||||
/*QR code library*/
|
||||
#define LV_USE_QRCODE 0
|
||||
|
||||
/*FreeType library*/
|
||||
#define LV_USE_FREETYPE 0
|
||||
#if LV_USE_FREETYPE
|
||||
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
|
||||
# define LV_FREETYPE_CACHE_SIZE (16 * 1024)
|
||||
#endif
|
||||
|
||||
/*Rlottie library*/
|
||||
#define LV_USE_RLOTTIE 0
|
||||
|
||||
/*-----------
|
||||
* Others
|
||||
*----------*/
|
||||
|
||||
/*1: Enable API to take snapshot for object*/
|
||||
#define LV_USE_SNAPSHOT 1
|
||||
|
||||
|
||||
/*==================
|
||||
* EXAMPLES
|
||||
*==================*/
|
||||
|
||||
/*Enable the examples to be built with the library*/
|
||||
#define LV_BUILD_EXAMPLES 0
|
||||
|
||||
/*--END OF LV_CONF_H--*/
|
||||
|
||||
#endif /*LV_CONF_H*/
|
||||
|
||||
#endif /*End of "Content enable"*/
|
|
@ -0,0 +1,23 @@
|
|||
CONFIG_LV_OS_PTHREAD=y
|
||||
CONFIG_LV_USE_OBJ_ID=y
|
||||
CONFIG_LV_USE_OBJ_NAME=y
|
||||
CONFIG_LV_USE_OBJ_ID_BUILTIN=y
|
||||
CONFIG_LV_USE_OBJ_PROPERTY=y
|
||||
CONFIG_LV_USE_OBJ_PROPERTY_NAME=y
|
||||
CONFIG_LV_USE_PRIVATE_API=y
|
||||
# CONFIG_LV_USE_CALENDAR is not set
|
||||
# CONFIG_LV_USE_CHART is not set
|
||||
# CONFIG_LV_USE_CHECKBOX is not set
|
||||
# CONFIG_LV_USE_MSGBOX is not set
|
||||
# CONFIG_LV_USE_ROLLER is not set
|
||||
# CONFIG_LV_USE_SCALE is not set
|
||||
# CONFIG_LV_USE_SLIDER is not set
|
||||
# CONFIG_LV_USE_TABLE is not set
|
||||
# CONFIG_LV_USE_TABVIEW is not set
|
||||
# CONFIG_LV_USE_TILEVIEW is not set
|
||||
CONFIG_LV_USE_QRCODE=y
|
||||
CONFIG_LV_USE_LINUX_FBDEV=y
|
||||
CONFIG_LV_USE_EVDEV=y
|
||||
CONFIG_LV_USE_ST7789=y
|
||||
CONFIG_LV_BUILD_EXAMPLES=n
|
||||
CONFIG_LV_BUILD_DEMOS=n
|
|
@ -6,45 +6,74 @@
|
|||
#include "log.h"
|
||||
#include "screen.h"
|
||||
#include <lvgl.h>
|
||||
#include <display/fbdev.h>
|
||||
#include <indev/evdev.h>
|
||||
// #include "st7789/lcd.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ui_index.h"
|
||||
|
||||
#define DISP_BUF_SIZE (300 * 240 * 2)
|
||||
static lv_color_t buf[DISP_BUF_SIZE];
|
||||
static lv_disp_draw_buf_t disp_buf;
|
||||
static lv_disp_drv_t disp_drv;
|
||||
static lv_indev_drv_t indev_drv;
|
||||
|
||||
void lvgl_init(void) {
|
||||
indev_handler_t *indev_handler = NULL;
|
||||
|
||||
void lvgl_set_indev_handler(indev_handler_t *handler) {
|
||||
indev_handler = handler;
|
||||
}
|
||||
|
||||
void handle_indev_event(lv_event_t *e) {
|
||||
if (indev_handler == NULL) {
|
||||
return;
|
||||
}
|
||||
indev_handler(lv_event_get_code(e));
|
||||
}
|
||||
|
||||
void lvgl_init(u_int16_t rotation) {
|
||||
log_trace("initalizing lvgl");
|
||||
|
||||
/*LittlevGL init*/
|
||||
lv_init();
|
||||
|
||||
log_trace("initalizing fbdev");
|
||||
fbdev_init();
|
||||
lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);
|
||||
lv_disp_drv_init(&disp_drv);
|
||||
disp_drv.draw_buf = &disp_buf;
|
||||
disp_drv.flush_cb = fbdev_flush;
|
||||
disp_drv.hor_res = 240;
|
||||
disp_drv.ver_res = 300;
|
||||
disp_drv.rotated = LV_DISP_ROT_270;
|
||||
disp_drv.sw_rotate = true;
|
||||
// disp_drv.full_refresh = true;
|
||||
/*Linux frame buffer device init*/
|
||||
|
||||
lv_disp_drv_register(&disp_drv);
|
||||
/*Linux frame buffer device init*/
|
||||
lv_display_t *disp = lv_linux_fbdev_create();
|
||||
// lv_display_set_physical_resolution(disp, 240, 300);
|
||||
lv_display_set_resolution(disp, 240, 300);
|
||||
lv_linux_fbdev_set_file(disp, "/dev/fb0");
|
||||
|
||||
log_trace("initalizing evdev");
|
||||
evdev_init();
|
||||
evdev_set_file("/dev/input/event1");
|
||||
lvgl_set_rotation(disp, rotation);
|
||||
|
||||
lv_indev_drv_init(&indev_drv);
|
||||
indev_drv.type = LV_INDEV_TYPE_POINTER;
|
||||
indev_drv.read_cb = evdev_read;
|
||||
lv_indev_drv_register(&indev_drv);
|
||||
// lv_display_t *disp = lv_st7789_create(LCD_H_RES, LCD_V_RES, LV_LCD_FLAG_NONE, lcd_send_cmd, lcd_send_color);
|
||||
// lv_display_set_resolution(disp, 240, 300);
|
||||
// lv_display_set_rotation(disp, LV_DISP_ROTATION_270);
|
||||
|
||||
// lv_color_t * buf1 = NULL;
|
||||
// lv_color_t * buf2 = NULL;
|
||||
|
||||
// uint32_t buf_size = LCD_H_RES * LCD_V_RES / 10 * lv_color_format_get_size(lv_display_get_color_format(disp));
|
||||
|
||||
// buf1 = lv_malloc(buf_size);
|
||||
// if(buf1 == NULL) {
|
||||
// log_error("display draw buffer malloc failed");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// buf2 = lv_malloc(buf_size);
|
||||
// if(buf2 == NULL) {
|
||||
// log_error("display buffer malloc failed");
|
||||
// lv_free(buf1);
|
||||
// return;
|
||||
// }
|
||||
// lv_display_set_buffers(disp, buf1, buf2, buf_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||
|
||||
/* Linux input device init */
|
||||
lv_indev_t *mouse = lv_evdev_create(LV_INDEV_TYPE_POINTER, "/dev/input/event1");
|
||||
lv_indev_set_group(mouse, lv_group_get_default());
|
||||
lv_indev_set_display(mouse, disp);
|
||||
|
||||
lv_indev_add_event_cb(mouse, handle_indev_event, LV_EVENT_ALL, NULL);
|
||||
|
||||
log_trace("initalizing ui");
|
||||
|
||||
ui_init();
|
||||
|
||||
log_info("ui initalized");
|
||||
|
@ -58,6 +87,45 @@ void lvgl_tick(void) {
|
|||
ui_tick();
|
||||
}
|
||||
|
||||
void lvgl_set_rotation(lv_display_t *disp, u_int16_t rotation) {
|
||||
log_info("setting rotation to %d", rotation);
|
||||
if (rotation == 0) {
|
||||
lv_display_set_rotation(disp, LV_DISP_ROTATION_0);
|
||||
} else if (rotation == 90) {
|
||||
lv_display_set_rotation(disp, LV_DISP_ROTATION_90);
|
||||
} else if (rotation == 180) {
|
||||
lv_display_set_rotation(disp, LV_DISP_ROTATION_180);
|
||||
} else if (rotation == 270) {
|
||||
lv_display_set_rotation(disp, LV_DISP_ROTATION_270);
|
||||
} else {
|
||||
log_error("invalid rotation %d", rotation);
|
||||
}
|
||||
|
||||
lv_style_t *flex_screen_style = ui_get_style("flex_screen");
|
||||
if (flex_screen_style == NULL) {
|
||||
log_error("flex_screen style not found");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_style_t *flex_screen_menu_style = ui_get_style("flex_screen_menu");
|
||||
if (flex_screen_menu_style == NULL) {
|
||||
log_error("flex_screen_menu style not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rotation == 90) {
|
||||
lv_style_set_pad_left(flex_screen_style, 24);
|
||||
lv_style_set_pad_right(flex_screen_style, 44);
|
||||
} else if (rotation == 270) {
|
||||
lv_style_set_pad_left(flex_screen_style, 44);
|
||||
lv_style_set_pad_right(flex_screen_style, 24);
|
||||
}
|
||||
|
||||
log_info("refreshing objects");
|
||||
lv_obj_report_style_change(&flex_screen_style);
|
||||
lv_obj_report_style_change(&flex_screen_menu_style);
|
||||
}
|
||||
|
||||
uint32_t custom_tick_get(void)
|
||||
{
|
||||
static uint64_t start_ms = 0;
|
||||
|
@ -85,6 +153,16 @@ lv_obj_t *ui_get_obj(const char *name) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
lv_style_t *ui_get_style(const char *name) {
|
||||
for (size_t i = 0; i < ui_styles_size; i++) {
|
||||
if (strcmp(ui_styles[i].name, name) == 0) {
|
||||
return ui_styles[i].getter();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const char *ui_get_current_screen() {
|
||||
lv_obj_t *scr = lv_scr_act();
|
||||
if (scr == NULL) {
|
||||
|
|
|
@ -3,11 +3,19 @@
|
|||
|
||||
#include <lvgl.h>
|
||||
|
||||
void lvgl_init(void);
|
||||
typedef void (indev_handler_t)(lv_event_code_t code);
|
||||
|
||||
void lvgl_set_indev_handler(indev_handler_t *handler);
|
||||
|
||||
void lvgl_init(u_int16_t rotation);
|
||||
void lvgl_tick(void);
|
||||
|
||||
void lvgl_set_rotation(lv_display_t *disp, u_int16_t rotation);
|
||||
|
||||
void ui_set_text(const char *name, const char *text);
|
||||
|
||||
lv_obj_t *ui_get_obj(const char *name);
|
||||
lv_style_t *ui_get_style(const char *name);
|
||||
lv_img_dsc_t *ui_get_image(const char *name);
|
||||
|
||||
#endif // SCREEN_H
|
||||
|
|
|
@ -12,6 +12,14 @@ done)
|
|||
|
||||
const int ui_objects_size = sizeof(ui_objects) / sizeof(ui_objects[0]);
|
||||
|
||||
ui_style_map ui_styles[] = {
|
||||
$(grep 'lv_style_t \*get_style_' ui/styles.h | sed 's/lv_style_t \*get_style_//g' | sed 's/_MAIN_DEFAULT();//g' | sed 's/\r//' | while read -r line; do
|
||||
echo " {\"$line\", &get_style_${line}_MAIN_DEFAULT},"
|
||||
done)
|
||||
};
|
||||
|
||||
const int ui_styles_size = sizeof(ui_styles) / sizeof(ui_styles[0]);
|
||||
|
||||
ui_img_map ui_images[] = {
|
||||
$(grep "extern const lv_img_dsc_t " ui/images.h | sed 's/extern const lv_img_dsc_t //g' | sed 's/;//g' | while read -r line; do
|
||||
echo " {\"$line\", &$line},"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "ui/ui.h"
|
||||
#include "ui/screens.h"
|
||||
#include "ui/styles.h"
|
||||
#include "ui/images.h"
|
||||
#include "ui/vars.h"
|
||||
|
||||
|
@ -14,6 +15,14 @@ typedef struct {
|
|||
extern ui_obj_map ui_objects[];
|
||||
extern const int ui_objects_size;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
lv_style_t *(*getter)();
|
||||
} ui_style_map;
|
||||
|
||||
extern ui_style_map ui_styles[];
|
||||
extern const int ui_styles_size;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const lv_img_dsc_t *img; // Pointer to the image descriptor const
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
//go:build linux
|
||||
|
||||
package native
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -Llib -ljknative -llvgl
|
||||
#cgo CFLAGS: -Iinclude
|
||||
#include "ctrl.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef const char cchar_t;
|
||||
typedef const uint8_t cuint8_t;
|
||||
|
||||
extern void jetkvm_go_log_handler(int level, cchar_t *filename, cchar_t *funcname, int line, cchar_t *message);
|
||||
static inline void jetkvm_cgo_setup_log_handler() {
|
||||
jetkvm_set_log_handler(&jetkvm_go_log_handler);
|
||||
}
|
||||
|
||||
extern void jetkvm_go_video_state_handler(jetkvm_video_state_t *state);
|
||||
static inline void jetkvm_cgo_setup_video_state_handler() {
|
||||
jetkvm_set_video_state_handler(&jetkvm_go_video_state_handler);
|
||||
}
|
||||
|
||||
extern void jetkvm_go_video_handler(cuint8_t *frame, ssize_t len);
|
||||
static inline void jetkvm_cgo_setup_video_handler() {
|
||||
jetkvm_set_video_handler(&jetkvm_go_video_handler);
|
||||
}
|
||||
|
||||
extern void jetkvm_go_indev_handler(int code);
|
||||
static inline void jetkvm_cgo_setup_indev_handler() {
|
||||
jetkvm_set_indev_handler(&jetkvm_go_indev_handler);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
//export jetkvm_go_video_state_handler
|
||||
func jetkvm_go_video_state_handler(state *C.jetkvm_video_state_t) {
|
||||
videoState := VideoState{
|
||||
Ready: bool(state.ready),
|
||||
Error: C.GoString(state.error),
|
||||
Width: int(state.width),
|
||||
Height: int(state.height),
|
||||
FramePerSecond: float64(state.frame_per_second),
|
||||
}
|
||||
videoStateChan <- videoState
|
||||
}
|
||||
|
||||
//export jetkvm_go_log_handler
|
||||
func jetkvm_go_log_handler(level C.int, filename *C.cchar_t, funcname *C.cchar_t, line C.int, message *C.cchar_t) {
|
||||
logMessage := nativeLogMessage{
|
||||
Level: zerolog.Level(level),
|
||||
Message: C.GoString(message),
|
||||
File: C.GoString(filename),
|
||||
FuncName: C.GoString(funcname),
|
||||
Line: int(line),
|
||||
}
|
||||
|
||||
logChan <- logMessage
|
||||
}
|
||||
|
||||
//export jetkvm_go_video_handler
|
||||
func jetkvm_go_video_handler(frame *C.cuint8_t, len C.ssize_t) {
|
||||
videoFrameChan <- C.GoBytes(unsafe.Pointer(frame), C.int(len))
|
||||
}
|
||||
|
||||
//export jetkvm_go_indev_handler
|
||||
func jetkvm_go_indev_handler(code C.int) {
|
||||
indevEventChan <- int(code)
|
||||
}
|
||||
|
||||
var eventCodeToNameMap = map[int]string{}
|
||||
|
||||
func uiEventCodeToName(code int) string {
|
||||
name, ok := eventCodeToNameMap[code]
|
||||
if !ok {
|
||||
cCode := C.int(code)
|
||||
cName := C.jetkvm_ui_event_code_to_name(cCode)
|
||||
name = C.GoString(cName)
|
||||
eventCodeToNameMap[code] = name
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
func setUpNativeHandlers() {
|
||||
C.jetkvm_cgo_setup_log_handler()
|
||||
C.jetkvm_cgo_setup_video_state_handler()
|
||||
C.jetkvm_cgo_setup_video_handler()
|
||||
C.jetkvm_cgo_setup_indev_handler()
|
||||
}
|
||||
|
||||
func uiInit(rotation uint16) {
|
||||
cRotation := C.u_int16_t(rotation)
|
||||
defer C.free(unsafe.Pointer(&cRotation))
|
||||
|
||||
C.jetkvm_ui_init(cRotation)
|
||||
}
|
||||
|
||||
func uiTick() {
|
||||
C.jetkvm_ui_tick()
|
||||
}
|
||||
|
||||
func videoInit() error {
|
||||
ret := C.jetkvm_video_init()
|
||||
if ret != 0 {
|
||||
return fmt.Errorf("failed to initialize video: %d", ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func videoShutdown() {
|
||||
C.jetkvm_video_shutdown()
|
||||
}
|
||||
|
||||
func videoStart() {
|
||||
C.jetkvm_video_start()
|
||||
}
|
||||
|
||||
func videoStop() {
|
||||
C.jetkvm_video_stop()
|
||||
}
|
||||
|
||||
func uiSetVar(name string, value string) {
|
||||
nameCStr := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(nameCStr))
|
||||
|
||||
valueCStr := C.CString(value)
|
||||
defer C.free(unsafe.Pointer(valueCStr))
|
||||
|
||||
C.jetkvm_ui_set_var(nameCStr, valueCStr)
|
||||
}
|
||||
|
||||
func uiGetVar(name string) string {
|
||||
nameCStr := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(nameCStr))
|
||||
|
||||
return C.GoString(C.jetkvm_ui_get_var(nameCStr))
|
||||
}
|
||||
|
||||
func uiSwitchToScreen(screen string) {
|
||||
screenCStr := C.CString(screen)
|
||||
defer C.free(unsafe.Pointer(screenCStr))
|
||||
C.jetkvm_ui_load_screen(screenCStr)
|
||||
}
|
||||
|
||||
func uiGetCurrentScreen() string {
|
||||
screenCStr := C.jetkvm_ui_get_current_screen()
|
||||
return C.GoString(screenCStr)
|
||||
}
|
||||
|
||||
func uiObjSetState(objName string, state string) (bool, error) {
|
||||
objNameCStr := C.CString(objName)
|
||||
defer C.free(unsafe.Pointer(objNameCStr))
|
||||
stateCStr := C.CString(state)
|
||||
defer C.free(unsafe.Pointer(stateCStr))
|
||||
C.jetkvm_ui_set_state(objNameCStr, stateCStr)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// TODO: use Enum instead of string but it's not a hot path and performance is not a concern now
|
||||
func uiObjAddFlag(objName string, flag string) (bool, error) {
|
||||
objNameCStr := C.CString(objName)
|
||||
defer C.free(unsafe.Pointer(objNameCStr))
|
||||
flagCStr := C.CString(flag)
|
||||
defer C.free(unsafe.Pointer(flagCStr))
|
||||
C.jetkvm_ui_add_flag(objNameCStr, flagCStr)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func uiObjClearFlag(objName string, flag string) (bool, error) {
|
||||
objNameCStr := C.CString(objName)
|
||||
defer C.free(unsafe.Pointer(objNameCStr))
|
||||
flagCStr := C.CString(flag)
|
||||
defer C.free(unsafe.Pointer(flagCStr))
|
||||
C.jetkvm_ui_clear_flag(objNameCStr, flagCStr)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func uiObjHide(objName string) (bool, error) {
|
||||
return uiObjAddFlag(objName, "LV_OBJ_FLAG_HIDDEN")
|
||||
}
|
||||
|
||||
func uiObjShow(objName string) (bool, error) {
|
||||
return uiObjClearFlag(objName, "LV_OBJ_FLAG_HIDDEN")
|
||||
}
|
||||
|
||||
func uiObjSetOpacity(objName string, opacity int) (bool, error) {
|
||||
objNameCStr := C.CString(objName)
|
||||
defer C.free(unsafe.Pointer(objNameCStr))
|
||||
|
||||
C.jetkvm_ui_set_opacity(objNameCStr, C.u_int8_t(opacity))
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func uiObjFadeIn(objName string, duration uint32) (bool, error) {
|
||||
objNameCStr := C.CString(objName)
|
||||
defer C.free(unsafe.Pointer(objNameCStr))
|
||||
|
||||
C.jetkvm_ui_fade_in(objNameCStr, C.u_int32_t(duration))
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func uiObjFadeOut(objName string, duration uint32) (bool, error) {
|
||||
objNameCStr := C.CString(objName)
|
||||
defer C.free(unsafe.Pointer(objNameCStr))
|
||||
|
||||
C.jetkvm_ui_fade_out(objNameCStr, C.u_int32_t(duration))
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func uiLabelSetText(objName string, text string) (bool, error) {
|
||||
objNameCStr := C.CString(objName)
|
||||
defer C.free(unsafe.Pointer(objNameCStr))
|
||||
|
||||
textCStr := C.CString(text)
|
||||
defer C.free(unsafe.Pointer(textCStr))
|
||||
|
||||
ret := C.jetkvm_ui_set_text(objNameCStr, textCStr)
|
||||
if ret < 0 {
|
||||
return false, fmt.Errorf("failed to set text: %d", ret)
|
||||
}
|
||||
return ret == 0, nil
|
||||
}
|
||||
|
||||
func uiImgSetSrc(objName string, src string) (bool, error) {
|
||||
objNameCStr := C.CString(objName)
|
||||
defer C.free(unsafe.Pointer(objNameCStr))
|
||||
|
||||
srcCStr := C.CString(src)
|
||||
defer C.free(unsafe.Pointer(srcCStr))
|
||||
|
||||
C.jetkvm_ui_set_image(objNameCStr, srcCStr)
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func uiDispSetRotation(rotation uint16) (bool, error) {
|
||||
nativeLogger.Info().Uint16("rotation", rotation).Msg("setting rotation")
|
||||
|
||||
cRotation := C.u_int16_t(rotation)
|
||||
defer C.free(unsafe.Pointer(&cRotation))
|
||||
|
||||
C.jetkvm_ui_set_rotation(cRotation)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func videoGetStreamQualityFactor() (float64, error) {
|
||||
factor := C.jetkvm_video_get_quality_factor()
|
||||
return float64(factor), nil
|
||||
}
|
||||
|
||||
func videoSetStreamQualityFactor(factor float64) error {
|
||||
C.jetkvm_video_set_quality_factor(C.float(factor))
|
||||
return nil
|
||||
}
|
||||
|
||||
func videoGetEDID() (string, error) {
|
||||
edidCStr := C.jetkvm_video_get_edid_hex()
|
||||
return C.GoString(edidCStr), nil
|
||||
}
|
||||
|
||||
func videoSetEDID(edid string) error {
|
||||
edidCStr := C.CString(edid)
|
||||
defer C.free(unsafe.Pointer(edidCStr))
|
||||
C.jetkvm_video_set_edid(edidCStr)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
//go:build !linux
|
||||
|
||||
package native
|
||||
|
||||
func panicPlatformNotSupported() {
|
||||
panic("platform not supported")
|
||||
}
|
||||
|
||||
func setUpNativeHandlers() {
|
||||
panicPlatformNotSupported()
|
||||
}
|
||||
|
||||
func uiSetVar(name string, value string) {
|
||||
panicPlatformNotSupported()
|
||||
}
|
||||
|
||||
func uiGetVar(name string) string {
|
||||
panicPlatformNotSupported()
|
||||
return ""
|
||||
}
|
||||
|
||||
func uiSwitchToScreen(screen string) {
|
||||
panicPlatformNotSupported()
|
||||
}
|
||||
|
||||
func uiGetCurrentScreen() string {
|
||||
panicPlatformNotSupported()
|
||||
return ""
|
||||
}
|
||||
|
||||
func uiObjSetState(objName string, state string) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiObjAddFlag(objName string, flag string) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiObjClearFlag(objName string, flag string) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiObjHide(objName string) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiObjShow(objName string) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiObjSetOpacity(objName string, opacity int) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiObjFadeIn(objName string, duration uint32) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiObjFadeOut(objName string, duration uint32) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiLabelSetText(objName string, text string) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiImgSetSrc(objName string, src string) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiDispSetRotation(rotation uint16) (bool, error) {
|
||||
panicPlatformNotSupported()
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func uiEventCodeToName(code int) string {
|
||||
panicPlatformNotSupported()
|
||||
return ""
|
||||
}
|
||||
|
||||
func videoGetStreamQualityFactor() (float64, error) {
|
||||
panicPlatformNotSupported()
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func videoSetStreamQualityFactor(factor float64) error {
|
||||
panicPlatformNotSupported()
|
||||
return nil
|
||||
}
|
||||
|
||||
func videoGetEDID() (string, error) {
|
||||
panicPlatformNotSupported()
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func videoSetEDID(edid string) error {
|
||||
panicPlatformNotSupported()
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package native
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var (
|
||||
videoFrameChan chan []byte = make(chan []byte)
|
||||
videoStateChan chan VideoState = make(chan VideoState)
|
||||
logChan chan nativeLogMessage = make(chan nativeLogMessage)
|
||||
indevEventChan chan int = make(chan int)
|
||||
)
|
||||
|
||||
func (n *Native) handleVideoFrameChan() {
|
||||
lastFrame := time.Now()
|
||||
for {
|
||||
frame := <-videoFrameChan
|
||||
now := time.Now()
|
||||
sinceLastFrame := now.Sub(lastFrame)
|
||||
lastFrame = now
|
||||
n.onVideoFrameReceived(frame, sinceLastFrame)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Native) handleVideoStateChan() {
|
||||
for {
|
||||
state := <-videoStateChan
|
||||
n.onVideoStateChange(state)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Native) handleLogChan() {
|
||||
for {
|
||||
entry := <-logChan
|
||||
l := n.l.With().
|
||||
Str("file", entry.File).
|
||||
Str("func", entry.FuncName).
|
||||
Int("line", entry.Line).
|
||||
Logger()
|
||||
|
||||
switch entry.Level {
|
||||
case zerolog.DebugLevel:
|
||||
l.Debug().Msg(entry.Message)
|
||||
case zerolog.InfoLevel:
|
||||
l.Info().Msg(entry.Message)
|
||||
case zerolog.WarnLevel:
|
||||
l.Warn().Msg(entry.Message)
|
||||
case zerolog.ErrorLevel:
|
||||
l.Error().Msg(entry.Message)
|
||||
case zerolog.PanicLevel:
|
||||
l.Panic().Msg(entry.Message)
|
||||
case zerolog.FatalLevel:
|
||||
l.Fatal().Msg(entry.Message)
|
||||
case zerolog.TraceLevel:
|
||||
l.Trace().Msg(entry.Message)
|
||||
case zerolog.NoLevel:
|
||||
l.Info().Msg(entry.Message)
|
||||
default:
|
||||
l.Info().Msg(entry.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Native) handleIndevEventChan() {
|
||||
for {
|
||||
event := <-indevEventChan
|
||||
name := uiEventCodeToName(event)
|
||||
n.onIndevEvent(name)
|
||||
}
|
||||
}
|
|
@ -7,10 +7,11 @@ import (
|
|||
|
||||
func (n *Native) setUIVars() {
|
||||
uiSetVar("app_version", n.appVersion.String())
|
||||
uiSetVar("system_version", n.systemVersion.String())
|
||||
}
|
||||
|
||||
func (n *Native) initUI() {
|
||||
uiInit()
|
||||
uiInit(n.displayRotation)
|
||||
n.setUIVars()
|
||||
}
|
||||
|
||||
|
@ -61,7 +62,7 @@ func (n *Native) UIObjSetImageSrc(objName string, image string) (bool, error) {
|
|||
return uiImgSetSrc(objName, image)
|
||||
}
|
||||
|
||||
func (n *Native) DisplaySetRotation(rotation string) (bool, error) {
|
||||
func (n *Native) DisplaySetRotation(rotation uint16) (bool, error) {
|
||||
return uiDispSetRotation(rotation)
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"navigation": {
|
||||
"selectedUserPageObject": "[jetkvm.eez-project]:/userPages/0",
|
||||
"selectedUserWidgetObject": "[jetkvm.eez-project]:/userWidgets/-1",
|
||||
"selectedActionObject": "[jetkvm.eez-project]:/actions/7",
|
||||
"selectedGlobalVariableObject": "[jetkvm.eez-project]:/variables/globalVariables/0",
|
||||
"selectedUserPageObject": "[jetkvm.eez-project]:/userPages/5",
|
||||
"selectedActionObject": "[jetkvm.eez-project]:/actions/0",
|
||||
"selectedGlobalVariableObject": "[jetkvm.eez-project]:/variables/globalVariables/1",
|
||||
"selectedStyleObject": "[jetkvm.eez-project]:/lvglStyles/styles/0",
|
||||
"selectedThemeObject": "[jetkvm.eez-project]:/themes/0",
|
||||
"selectedFontObject": "[jetkvm.eez-project]:/fonts/1",
|
||||
"selectedFontObject": "[jetkvm.eez-project]:/fonts/4",
|
||||
"selectedBitmapObject": "[jetkvm.eez-project]:/bitmaps/11",
|
||||
"subnavigationSelectedItems": {
|
||||
"variables-tab/sub-navigation/selected-item": "Global"
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
|||
},
|
||||
{
|
||||
"type": "border",
|
||||
"selected": 4,
|
||||
"selected": 2,
|
||||
"size": 113.5,
|
||||
"location": "right",
|
||||
"children": [
|
||||
|
@ -77,7 +77,7 @@
|
|||
},
|
||||
{
|
||||
"type": "border",
|
||||
"selected": 0,
|
||||
"selected": 1,
|
||||
"location": "bottom",
|
||||
"children": [
|
||||
{
|
||||
|
@ -130,7 +130,6 @@
|
|||
"type": "tabset",
|
||||
"id": "#2e3d9a08-c69c-42b5-b434-525109f2a5a7",
|
||||
"weight": 1,
|
||||
"selected": 1,
|
||||
"enableClose": false,
|
||||
"children": [
|
||||
{
|
||||
|
@ -189,7 +188,8 @@
|
|||
"enableClose": false,
|
||||
"icon": "svg:variable"
|
||||
}
|
||||
]
|
||||
],
|
||||
"active": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -197,46 +197,46 @@
|
|||
"type": "tabset",
|
||||
"id": "EDITORS",
|
||||
"weight": 49.31058517127421,
|
||||
"selected": 1,
|
||||
"selected": 4,
|
||||
"enableDeleteWhenEmpty": false,
|
||||
"enableClose": false,
|
||||
"children": [
|
||||
{
|
||||
"type": "tab",
|
||||
"id": "#467ae6a9-0f08-4392-a580-25f8916524e4",
|
||||
"name": "BootScreen",
|
||||
"id": "#aec56ae8-5b75-4a2f-ad81-f0d7d683c77a",
|
||||
"name": "FontBook24",
|
||||
"component": "editor",
|
||||
"config": {
|
||||
"objectPath": "[jetkvm.eez-project]:/userPages/0",
|
||||
"objectPath": "[jetkvm.eez-project]:/fonts/4",
|
||||
"permanent": false
|
||||
},
|
||||
"icon": "material:font_download"
|
||||
},
|
||||
{
|
||||
"type": "tab",
|
||||
"id": "#c8dece00-e490-46b8-8a14-5dcfa8bbce36",
|
||||
"name": "AboutScreen",
|
||||
"component": "editor",
|
||||
"config": {
|
||||
"objectPath": "[jetkvm.eez-project]:/userPages/5",
|
||||
"permanent": false
|
||||
},
|
||||
"icon": "svg:page"
|
||||
},
|
||||
{
|
||||
"type": "tab",
|
||||
"id": "#d1704ae1-993d-4a7d-bade-0903bb61e9c6",
|
||||
"name": "AboutScreen",
|
||||
"id": "#e9afee88-d3be-4069-aa77-22930d1efcf3",
|
||||
"name": "HomeScreen",
|
||||
"component": "editor",
|
||||
"config": {
|
||||
"objectPath": "[jetkvm.eez-project]:/userPages/5",
|
||||
"objectPath": "[jetkvm.eez-project]:/userPages/1",
|
||||
"permanent": true
|
||||
},
|
||||
"icon": "svg:page"
|
||||
},
|
||||
{
|
||||
"type": "tab",
|
||||
"id": "#b444e818-4663-4332-ab40-a34acb670c8c",
|
||||
"name": "MenuAdvancedScreen",
|
||||
"component": "editor",
|
||||
"config": {
|
||||
"objectPath": "[jetkvm.eez-project]:/userPages/4",
|
||||
"permanent": true
|
||||
},
|
||||
"icon": "svg:page"
|
||||
},
|
||||
{
|
||||
"type": "tab",
|
||||
"id": "#f8258cf3-e12a-4be9-8021-33199674dbe6",
|
||||
"id": "#f5a057a5-977c-46be-8702-5447d603a34f",
|
||||
"name": "MenuScreen",
|
||||
"component": "editor",
|
||||
"config": {
|
||||
|
@ -247,7 +247,7 @@
|
|||
},
|
||||
{
|
||||
"type": "tab",
|
||||
"id": "#5dcfc8a4-36a7-4dea-a0cc-8dbeb4aab914",
|
||||
"id": "#8af97439-79ee-4705-be34-53ca8814f3a0",
|
||||
"name": "Settings",
|
||||
"component": "editor",
|
||||
"config": {
|
||||
|
@ -257,8 +257,7 @@
|
|||
},
|
||||
"icon": "material:settings"
|
||||
}
|
||||
],
|
||||
"active": true
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "row",
|
||||
|
@ -1066,7 +1065,8 @@
|
|||
"0": {
|
||||
"0": {
|
||||
"0": {
|
||||
"1": {}
|
||||
"1": {},
|
||||
"$selected": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1090,6 +1090,7 @@
|
|||
"0": {
|
||||
"0": {
|
||||
"0": {
|
||||
"0": {},
|
||||
"1": {
|
||||
"0": {}
|
||||
}
|
||||
|
@ -1101,7 +1102,9 @@
|
|||
"3": {
|
||||
"0": {
|
||||
"0": {},
|
||||
"1": {}
|
||||
"1": {
|
||||
"$selected": true
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"0": {},
|
||||
|
@ -1154,8 +1157,8 @@
|
|||
},
|
||||
"transform": {
|
||||
"translate": {
|
||||
"x": -194,
|
||||
"y": -454
|
||||
"x": -230,
|
||||
"y": -94
|
||||
},
|
||||
"scale": 1
|
||||
},
|
||||
|
@ -1171,9 +1174,8 @@
|
|||
"0": {
|
||||
"0": {
|
||||
"0": {
|
||||
"0": {
|
||||
"$selected": true
|
||||
}
|
||||
"0": {},
|
||||
"$selected": true
|
||||
},
|
||||
"1": {
|
||||
"0": {
|
||||
|
@ -1201,11 +1203,28 @@
|
|||
}
|
||||
},
|
||||
"[jetkvm.eez-project]:/userPages/4[flow-state]": {
|
||||
"selection": {},
|
||||
"selection": {
|
||||
"0": {
|
||||
"0": {
|
||||
"0": {
|
||||
"0": {
|
||||
"$selected": true
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"0": {
|
||||
"0": {},
|
||||
"1": {},
|
||||
"2": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"transform": {
|
||||
"translate": {
|
||||
"x": -150,
|
||||
"y": -120
|
||||
"x": -176,
|
||||
"y": -127
|
||||
},
|
||||
"scale": 1
|
||||
},
|
||||
|
@ -1226,12 +1245,19 @@
|
|||
"1": {
|
||||
"0": {
|
||||
"0": {},
|
||||
"1": {},
|
||||
"1": {
|
||||
"1": {}
|
||||
},
|
||||
"2": {},
|
||||
"3": {},
|
||||
"4": {},
|
||||
"5": {},
|
||||
"6": {}
|
||||
"5": {
|
||||
"1": {
|
||||
"$selected": true
|
||||
}
|
||||
},
|
||||
"6": {},
|
||||
"7": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1266,6 +1292,38 @@
|
|||
"secondToPx": 200,
|
||||
"scrollLeft": 0
|
||||
}
|
||||
},
|
||||
"[jetkvm.eez-project]:/userPages/6[flow-state]": {
|
||||
"selection": {
|
||||
"0": {
|
||||
"0": {
|
||||
"0": {},
|
||||
"1": {
|
||||
"0": {
|
||||
"0": {},
|
||||
"2": {
|
||||
"1": {
|
||||
"$selected": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"transform": {
|
||||
"translate": {
|
||||
"x": -138,
|
||||
"y": -122
|
||||
},
|
||||
"scale": 1
|
||||
},
|
||||
"timeline": {
|
||||
"isEditorActive": false,
|
||||
"position": 0,
|
||||
"secondToPx": 200,
|
||||
"scrollLeft": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"activeOutputSection": 0,
|
||||
|
@ -1281,13 +1339,10 @@
|
|||
"logsPanelFilter": "all",
|
||||
"selectedStylePropertyName": "",
|
||||
"lvglPart": "MAIN",
|
||||
"lvglState": "DEFAULT",
|
||||
"lvglState": "DISABLED",
|
||||
"lvglExpandedPropertiesGroup": [
|
||||
"POSITION AND SIZE",
|
||||
"PADDING",
|
||||
"MARGIN",
|
||||
"TEXT",
|
||||
"BACKGROUND"
|
||||
"TEXT"
|
||||
],
|
||||
"showInactiveFlowsInDebugger": true,
|
||||
"globalFlowZoom": true,
|
||||
|
|
|
@ -13,15 +13,19 @@ type Native struct {
|
|||
lD *zerolog.Logger
|
||||
systemVersion *semver.Version
|
||||
appVersion *semver.Version
|
||||
displayRotation uint16
|
||||
onVideoStateChange func(state VideoState)
|
||||
onVideoFrameReceived func(frame []byte, duration time.Duration)
|
||||
onIndevEvent func(event string)
|
||||
}
|
||||
|
||||
type NativeOptions struct {
|
||||
SystemVersion *semver.Version
|
||||
AppVersion *semver.Version
|
||||
DisplayRotation uint16
|
||||
OnVideoStateChange func(state VideoState)
|
||||
OnVideoFrameReceived func(frame []byte, duration time.Duration)
|
||||
OnIndevEvent func(event string)
|
||||
}
|
||||
|
||||
func NewNative(opts NativeOptions) *Native {
|
||||
|
@ -39,14 +43,23 @@ func NewNative(opts NativeOptions) *Native {
|
|||
}
|
||||
}
|
||||
|
||||
onIndevEvent := opts.OnIndevEvent
|
||||
if onIndevEvent == nil {
|
||||
onIndevEvent = func(event string) {
|
||||
nativeLogger.Info().Str("event", event).Msg("indev event")
|
||||
}
|
||||
}
|
||||
|
||||
return &Native{
|
||||
ready: make(chan struct{}),
|
||||
l: nativeLogger,
|
||||
lD: displayLogger,
|
||||
systemVersion: opts.SystemVersion,
|
||||
appVersion: opts.AppVersion,
|
||||
displayRotation: opts.DisplayRotation,
|
||||
onVideoStateChange: opts.OnVideoStateChange,
|
||||
onVideoFrameReceived: opts.OnVideoFrameReceived,
|
||||
onIndevEvent: opts.OnIndevEvent,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,6 +72,7 @@ func (n *Native) Start() {
|
|||
go n.handleLogChan()
|
||||
go n.handleVideoStateChan()
|
||||
go n.handleVideoFrameChan()
|
||||
go n.handleIndevEventChan()
|
||||
|
||||
n.initUI()
|
||||
go n.tickUI()
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package native
|
||||
|
||||
import "sync"
|
||||
|
||||
var (
|
||||
instance *Native
|
||||
instanceLock sync.RWMutex
|
||||
)
|
||||
|
||||
func setInstance(n *Native) {
|
||||
instanceLock.Lock()
|
||||
defer instanceLock.Unlock()
|
||||
|
||||
if instance == nil {
|
||||
instance = n
|
||||
}
|
||||
|
||||
if instance != n {
|
||||
panic("instance is already set")
|
||||
}
|
||||
}
|
25
jsonrpc.go
25
jsonrpc.go
|
@ -286,14 +286,25 @@ func rpcTryUpdate() error {
|
|||
}
|
||||
|
||||
func rpcSetDisplayRotation(params DisplayRotationSettings) error {
|
||||
var err error
|
||||
_, err = nativeInstance.DisplaySetRotation(params.Rotation)
|
||||
if err == nil {
|
||||
config.DisplayRotation = params.Rotation
|
||||
if err := SaveConfig(); err != nil {
|
||||
return fmt.Errorf("failed to save config: %w", err)
|
||||
}
|
||||
currentRotation := config.DisplayRotation
|
||||
if currentRotation == params.Rotation {
|
||||
return nil
|
||||
}
|
||||
|
||||
err := config.SetDisplayRotation(params.Rotation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = nativeInstance.DisplaySetRotation(config.GetDisplayRotation())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := SaveConfig(); err != nil {
|
||||
return fmt.Errorf("failed to save config: %w", err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
10
native.go
10
native.go
|
@ -11,14 +11,20 @@ import (
|
|||
var nativeInstance *native.Native
|
||||
|
||||
func initNative(systemVersion *semver.Version, appVersion *semver.Version) {
|
||||
|
||||
nativeInstance = native.NewNative(native.NativeOptions{
|
||||
SystemVersion: systemVersion,
|
||||
AppVersion: appVersion,
|
||||
SystemVersion: systemVersion,
|
||||
AppVersion: appVersion,
|
||||
DisplayRotation: config.GetDisplayRotation(),
|
||||
OnVideoStateChange: func(state native.VideoState) {
|
||||
lastVideoState = state
|
||||
triggerVideoStateUpdate()
|
||||
requestDisplayUpdate(true)
|
||||
},
|
||||
OnIndevEvent: func(event string) {
|
||||
nativeLogger.Trace().Str("event", event).Msg("indev event received")
|
||||
wakeDisplay(false)
|
||||
},
|
||||
OnVideoFrameReceived: func(frame []byte, duration time.Duration) {
|
||||
if currentSession != nil {
|
||||
err := currentSession.VideoTrack.WriteSample(media.Sample{Data: frame, Duration: duration})
|
||||
|
|
Loading…
Reference in New Issue