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
Willem Melching 2020-03-31 20:14:26 -07:00 committed by GitHub
parent cfcf3f9368
commit 202a4c2011
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 293 additions and 0 deletions

View File

@ -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")

View File

@ -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

View File

@ -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.

View File

@ -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;
}