Add binary to display text (#1301)
* add binary to display text * fake text needs status too * Rename to TextWindow Co-authored-by: Comma Device <device@comma.ai>albatross
parent
cfcf3f9368
commit
202a4c2011
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import subprocess
|
||||
from common.basedir import BASEDIR
|
||||
|
||||
|
||||
class TextWindow():
|
||||
def __init__(self, s):
|
||||
try:
|
||||
self.text_proc = subprocess.Popen(["./text", s],
|
||||
stdin=subprocess.PIPE,
|
||||
cwd=os.path.join(BASEDIR, "selfdrive", "ui", "text"),
|
||||
close_fds=True)
|
||||
except OSError:
|
||||
self.text_proc = None
|
||||
|
||||
def get_status(self):
|
||||
if self.text_proc is not None:
|
||||
self.text_proc.poll()
|
||||
return s.text_proc.returncode
|
||||
|
||||
return None
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def close(self):
|
||||
if self.text_proc is not None:
|
||||
self.text_proc.terminate()
|
||||
self.text_proc = None
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
self.close()
|
||||
|
||||
|
||||
class FakeTextWindow():
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def get_status(self):
|
||||
return None
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def update(self, _):
|
||||
pass
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import time
|
||||
text = """Traceback (most recent call last):
|
||||
File "./controlsd.py", line 608, in <module>
|
||||
main()
|
||||
File "./controlsd.py", line 604, in main
|
||||
controlsd_thread(sm, pm, logcan)
|
||||
File "./controlsd.py", line 455, in controlsd_thread
|
||||
1/0
|
||||
ZeroDivisionError: division by zero"""
|
||||
print(text)
|
||||
|
||||
with TextWindow(text) as s:
|
||||
for _ in range(100):
|
||||
if s.get_status() == 1:
|
||||
print("Got exit button")
|
||||
break
|
||||
time.sleep(0.1)
|
||||
print("gone")
|
|
@ -31,6 +31,7 @@ common/basedir.py
|
|||
common/filter_simple.py
|
||||
common/stat_live.py
|
||||
common/spinner.py
|
||||
common/text_window.py
|
||||
common/cython_hacks.py
|
||||
common/apk.py
|
||||
common/SConscript
|
||||
|
@ -331,6 +332,10 @@ selfdrive/ui/spinner/Makefile
|
|||
selfdrive/ui/spinner/spinner
|
||||
selfdrive/ui/spinner/spinner.c
|
||||
|
||||
selfdrive/ui/text/Makefile
|
||||
selfdrive/ui/text/text
|
||||
selfdrive/ui/text/text.c
|
||||
|
||||
selfdrive/camerad/SConscript
|
||||
selfdrive/camerad/main.cc
|
||||
selfdrive/camerad/bufs.h
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
CC = clang
|
||||
CXX = clang++
|
||||
|
||||
PHONELIBS = ../../../phonelibs
|
||||
|
||||
WARN_FLAGS = -Werror=implicit-function-declaration \
|
||||
-Werror=incompatible-pointer-types \
|
||||
-Werror=int-conversion \
|
||||
-Werror=return-type \
|
||||
-Werror=format-extra-args
|
||||
|
||||
CFLAGS = -std=gnu11 -fPIC -O2 $(WARN_FLAGS)
|
||||
CXXFLAGS = -std=c++11 -fPIC -O2 $(WARN_FLAGS)
|
||||
|
||||
NANOVG_FLAGS = -I$(PHONELIBS)/nanovg
|
||||
|
||||
OPENGL_LIBS = -lGLESv3
|
||||
|
||||
FRAMEBUFFER_LIBS = -lutils -lgui -lEGL
|
||||
|
||||
OBJS = text.o \
|
||||
../../common/framebuffer.o \
|
||||
../../../selfdrive/common/touch.o \
|
||||
$(PHONELIBS)/nanovg/nanovg.o \
|
||||
opensans_regular.o \
|
||||
|
||||
DEPS := $(OBJS:.o=.d)
|
||||
|
||||
.PHONY: all
|
||||
all: text
|
||||
|
||||
text: $(OBJS)
|
||||
@echo "[ LINK ] $@"
|
||||
$(CXX) -fPIC -o '$@' $^ \
|
||||
-s \
|
||||
$(FRAMEBUFFER_LIBS) \
|
||||
-L/system/vendor/lib64 \
|
||||
$(OPENGL_LIBS) \
|
||||
-lm -llog
|
||||
|
||||
opensans_regular.o: ../../assets/fonts/opensans_regular.ttf
|
||||
@echo "[ bin2o ] $@"
|
||||
cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
|
||||
|
||||
%.o: %.c
|
||||
mkdir -p $(@D)
|
||||
@echo "[ CC ] $@"
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) \
|
||||
-I../.. \
|
||||
-I$(PHONELIBS)/android_frameworks_native/include \
|
||||
-I$(PHONELIBS)/android_system_core/include \
|
||||
-I$(PHONELIBS)/android_hardware_libhardware/include \
|
||||
$(NANOVG_FLAGS) \
|
||||
-c -o '$@' '$<'
|
||||
|
||||
%.o: %.cc
|
||||
mkdir -p $(@D)
|
||||
@echo "[ CXX ] $@"
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) \
|
||||
-I../../selfdrive \
|
||||
-I../../ \
|
||||
-I$(PHONELIBS)/android_frameworks_native/include \
|
||||
-I$(PHONELIBS)/android_system_core/include \
|
||||
-I$(PHONELIBS)/android_hardware_libhardware/include \
|
||||
$(NANOVG_FLAGS) \
|
||||
-c -o '$@' '$<'
|
||||
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f text $(OBJS) $(DEPS)
|
||||
|
||||
-include $(DEPS)
|
Binary file not shown.
|
@ -0,0 +1,141 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <GLES3/gl3.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
#include "nanovg.h"
|
||||
#define NANOVG_GLES3_IMPLEMENTATION
|
||||
#include "nanovg_gl.h"
|
||||
#include "nanovg_gl_utils.h"
|
||||
|
||||
|
||||
#include "common/framebuffer.h"
|
||||
#include "common/touch.h"
|
||||
|
||||
|
||||
#define COLOR_WHITE nvgRGBA(255, 255, 255, 255)
|
||||
#define MAX_TEXT_SIZE 2048
|
||||
|
||||
extern const unsigned char _binary_opensans_regular_ttf_start[];
|
||||
extern const unsigned char _binary_opensans_regular_ttf_end[];
|
||||
|
||||
static void set_brightness(int brightness) {
|
||||
FILE *f = fopen("/sys/class/leds/lcd-backlight/brightness", "wb");
|
||||
if (f != NULL) {
|
||||
fprintf(f, "%d", brightness);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int err;
|
||||
|
||||
// spinner
|
||||
int fb_w, fb_h;
|
||||
FramebufferState *fb = framebuffer_init("text", 0x00001000, false,
|
||||
&fb_w, &fb_h);
|
||||
assert(fb);
|
||||
|
||||
NVGcontext *vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
|
||||
assert(vg);
|
||||
|
||||
int font = nvgCreateFontMem(vg, "regular", (unsigned char*)_binary_opensans_regular_ttf_start, _binary_opensans_regular_ttf_end-_binary_opensans_regular_ttf_start, 0);
|
||||
assert(font >= 0);
|
||||
|
||||
// Awake
|
||||
framebuffer_set_power(fb, HWC_POWER_MODE_NORMAL);
|
||||
set_brightness(255);
|
||||
|
||||
glClearColor(0.1, 0.1, 0.1, 1.0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
nvgBeginFrame(vg, fb_w, fb_h, 1.0f);
|
||||
|
||||
// background
|
||||
nvgBeginPath(vg);
|
||||
NVGpaint bg = nvgLinearGradient(vg, fb_w, 0, fb_w, fb_h,
|
||||
nvgRGBA(0, 0, 0, 175), nvgRGBA(0, 0, 0, 255));
|
||||
nvgFillPaint(vg, bg);
|
||||
nvgRect(vg, 0, 0, fb_w, fb_h);
|
||||
nvgFill(vg);
|
||||
|
||||
|
||||
// Text
|
||||
nvgFillColor(vg, COLOR_WHITE);
|
||||
nvgFontSize(vg, 75.0f);
|
||||
|
||||
if (argc >= 2) {
|
||||
float x = 150;
|
||||
float y = 150;
|
||||
|
||||
// Copy text
|
||||
char * text = malloc(MAX_TEXT_SIZE);
|
||||
strncpy(text, argv[1], MAX_TEXT_SIZE);
|
||||
|
||||
float lineh;
|
||||
nvgTextMetrics(vg, NULL, NULL, &lineh);
|
||||
|
||||
// nvgTextBox strips leading whitespace. We have to reimplement
|
||||
char * next = strtok(text, "\n");
|
||||
while (next != NULL){
|
||||
nvgText(vg, x, y, next, NULL);
|
||||
y += lineh;
|
||||
next = strtok(NULL, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Button
|
||||
int b_x = 1500;
|
||||
int b_y = 800;
|
||||
int b_w = 300;
|
||||
int b_h = 150;
|
||||
|
||||
nvgBeginPath(vg);
|
||||
nvgFillColor(vg, nvgRGBA(8, 8, 8, 255));
|
||||
nvgRoundedRect(vg, b_x, b_y, b_w, b_h, 20);
|
||||
nvgFill(vg);
|
||||
|
||||
nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
|
||||
nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
|
||||
nvgText(vg, b_x+b_w/2, b_y+b_h/2, "Exit", NULL);
|
||||
|
||||
nvgBeginPath(vg);
|
||||
nvgStrokeColor(vg, nvgRGBA(255, 255, 255, 50));
|
||||
nvgStrokeWidth(vg, 5);
|
||||
nvgRoundedRect(vg, b_x, b_y, b_w, b_h, 20);
|
||||
nvgStroke(vg);
|
||||
|
||||
// Draw to screen
|
||||
nvgEndFrame(vg);
|
||||
framebuffer_swap(fb);
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
|
||||
|
||||
// Wait for button
|
||||
TouchState touch;
|
||||
touch_init(&touch);
|
||||
|
||||
while (true){
|
||||
int touch_x = -1, touch_y = -1;
|
||||
int res = touch_poll(&touch, &touch_x, &touch_y, 0);
|
||||
if (res){
|
||||
|
||||
if (touch_x > b_x && touch_x < b_x + b_w){
|
||||
if (touch_y > b_y && touch_y < b_y + b_h){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
usleep(1000000 / 60);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue