From 6c86afee16c706a3c8e787d576ead509373e6b55 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 6 Nov 2020 18:44:04 -0800 Subject: [PATCH] Qt spinner (#2494) * move android spinner * qt spinner * rotation * nothing by default * spin spin * fix rotate * style * spinner for all * -2 * unused --- common/spinner.py | 19 ++- common/text_window.py | 2 - release/files_common | 10 +- .../boardd/tests/test_boardd_loopback.py | 3 +- selfdrive/common/spinner.h | 14 -- selfdrive/manager.py | 3 +- selfdrive/ui/.gitignore | 3 + selfdrive/ui/SConscript | 3 +- selfdrive/ui/{ => android}/spinner/Makefile | 18 +-- selfdrive/ui/{ => android}/spinner/spinner | Bin .../{common => ui/android/spinner}/spinner.c | 3 +- selfdrive/ui/qt/spinner.cc | 126 ++++++++++++++++++ selfdrive/ui/qt/spinner.hpp | 27 ++++ selfdrive/ui/spinner | 8 ++ selfdrive/ui/spinner/spinner.c | 21 --- 15 files changed, 192 insertions(+), 68 deletions(-) delete mode 100644 selfdrive/common/spinner.h rename selfdrive/ui/{ => android}/spinner/Makefile (77%) rename selfdrive/ui/{ => android}/spinner/spinner (100%) rename selfdrive/{common => ui/android/spinner}/spinner.c (99%) create mode 100644 selfdrive/ui/qt/spinner.cc create mode 100644 selfdrive/ui/qt/spinner.hpp create mode 100755 selfdrive/ui/spinner delete mode 100644 selfdrive/ui/spinner/spinner.c diff --git a/common/spinner.py b/common/spinner.py index 53e8ee52..1232371d 100644 --- a/common/spinner.py +++ b/common/spinner.py @@ -4,17 +4,14 @@ from common.basedir import BASEDIR class Spinner(): - def __init__(self, noop=False): - # spinner is currently only implemented for android - self.spinner_proc = None - if not noop: - try: - self.spinner_proc = subprocess.Popen(["./spinner"], - stdin=subprocess.PIPE, - cwd=os.path.join(BASEDIR, "selfdrive", "ui", "spinner"), - close_fds=True) - except OSError: - self.spinner_proc = None + def __init__(self): + try: + self.spinner_proc = subprocess.Popen(["./spinner"], + stdin=subprocess.PIPE, + cwd=os.path.join(BASEDIR, "selfdrive", "ui"), + close_fds=True) + except OSError: + self.spinner_proc = None def __enter__(self): return self diff --git a/common/text_window.py b/common/text_window.py index af7d9bbf..bea3a149 100755 --- a/common/text_window.py +++ b/common/text_window.py @@ -7,8 +7,6 @@ from common.basedir import BASEDIR class TextWindow: def __init__(self, text): - # text window is only implemented for android currently - self.text_proc = None try: self.text_proc = subprocess.Popen(["./text", text], stdin=subprocess.PIPE, diff --git a/release/files_common b/release/files_common index dcc5d309..ec54ac1a 100644 --- a/release/files_common +++ b/release/files_common @@ -219,8 +219,6 @@ selfdrive/common/visionbuf.h selfdrive/common/visionbuf_ion.c selfdrive/common/visionimg.cc selfdrive/common/visionimg.h -selfdrive/common/spinner.c -selfdrive/common/spinner.h selfdrive/common/gpio.cc selfdrive/common/gpio.h @@ -344,9 +342,11 @@ selfdrive/ui/SConscript selfdrive/ui/*.cc selfdrive/ui/*.hpp selfdrive/ui/ui -selfdrive/ui/spinner/Makefile -selfdrive/ui/spinner/spinner -selfdrive/ui/spinner/spinner.c +selfdrive/ui/text +selfdrive/ui/spinner +selfdrive/ui/android/spinner/Makefile +selfdrive/ui/android/spinner/spinner +selfdrive/ui/android/spinner/spinner.c selfdrive/ui/android/text/Makefile selfdrive/ui/android/text/text diff --git a/selfdrive/boardd/tests/test_boardd_loopback.py b/selfdrive/boardd/tests/test_boardd_loopback.py index d4b2fe39..85f1199b 100755 --- a/selfdrive/boardd/tests/test_boardd_loopback.py +++ b/selfdrive/boardd/tests/test_boardd_loopback.py @@ -8,7 +8,6 @@ from functools import wraps import cereal.messaging as messaging from cereal import car from common.basedir import BASEDIR -from common.hardware import ANDROID from common.params import Params from common.spinner import Spinner from panda import Panda @@ -36,7 +35,7 @@ os.environ['BASEDIR'] = BASEDIR @with_processes(['boardd']) def test_boardd_loopback(): # wait for boardd to init - spinner = Spinner(noop=(not ANDROID)) + spinner = Spinner() time.sleep(2) # boardd blocks on CarVin and CarParams diff --git a/selfdrive/common/spinner.h b/selfdrive/common/spinner.h deleted file mode 100644 index fd35dcc7..00000000 --- a/selfdrive/common/spinner.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef COMMON_SPINNER_H -#define COMMON_SPINNER_H - -#ifdef __cplusplus -extern "C" { -#endif - -int spin(int argc, char** argv); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/selfdrive/manager.py b/selfdrive/manager.py index 959ea5d9..29b8835f 100755 --- a/selfdrive/manager.py +++ b/selfdrive/manager.py @@ -78,7 +78,7 @@ import traceback from multiprocessing import Process # Run scons -spinner = Spinner(noop=(__name__ != "__main__" or not ANDROID)) +spinner = Spinner() spinner.update("0") if not prebuilt: @@ -138,7 +138,6 @@ if not prebuilt: cloudlog.error("scons build failed\n" + error_s) # Show TextWindow - no_ui = __name__ != "__main__" or not ANDROID error_s = "\n \n".join(["\n".join(textwrap.wrap(e, 65)) for e in errors]) with TextWindow("openpilot failed to build\n \n" + error_s) as t: t.wait_for_exit() diff --git a/selfdrive/ui/.gitignore b/selfdrive/ui/.gitignore index a7656353..de2e5791 100644 --- a/selfdrive/ui/.gitignore +++ b/selfdrive/ui/.gitignore @@ -1,2 +1,5 @@ moc_* +*.moc + qt/text +qt/spinner diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index 00f7d9c0..1090a32a 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -72,5 +72,6 @@ else: qt_src = ["qt/ui.cc", "qt/window.cc", "qt/qt_sound.cc", "qt/offroad/settings.cc", "qt/offroad/onboarding.cc"] + src qt_env.Program("_ui", qt_src, LIBS=qt_libs + libs) - # text window + # spinner and text window qt_env.Program("qt/text", ["qt/text.cc"], LIBS=qt_libs + libs) + qt_env.Program("qt/spinner", ["qt/spinner.cc"], LIBS=qt_libs + libs) diff --git a/selfdrive/ui/spinner/Makefile b/selfdrive/ui/android/spinner/Makefile similarity index 77% rename from selfdrive/ui/spinner/Makefile rename to selfdrive/ui/android/spinner/Makefile index 49401067..7ceea5f6 100644 --- a/selfdrive/ui/spinner/Makefile +++ b/selfdrive/ui/android/spinner/Makefile @@ -1,7 +1,9 @@ CC = clang CXX = clang++ -PHONELIBS = ../../../phonelibs +ROOT_DIR = ../../.. +PHONELIBS = $(ROOT_DIR)/phonelibs +COMMON = $(ROOT)/selfdrive/common WARN_FLAGS = -Werror=implicit-function-declaration \ -Werror=incompatible-pointer-types \ @@ -19,10 +21,10 @@ OPENGL_LIBS = -lGLESv3 FRAMEBUFFER_LIBS = -lutils -lgui -lEGL OBJS = spinner.o \ - ../../common/framebuffer.o \ - ../../common/util.o \ + $(COMMON)/framebuffer.o \ + $(COMMON)/util.o \ $(PHONELIBS)/nanovg/nanovg.o \ - ../../common/spinner.o \ + $(COMMON)/spinner.o \ opensans_semibold.o \ img_spinner_track.o \ img_spinner_comma.o @@ -41,7 +43,7 @@ spinner: $(OBJS) $(OPENGL_LIBS) \ -lm -llog -../../common/framebuffer.o: ../../common/framebuffer.cc +$(COMMON)/framebuffer.o: $(COMMON)/framebuffer.cc @echo "[ CXX ] $@" $(CXX) $(CXXFLAGS) -MMD \ -I$(PHONELIBS)/android_frameworks_native/include \ @@ -49,15 +51,15 @@ spinner: $(OBJS) -I$(PHONELIBS)/android_hardware_libhardware/include \ -c -o '$@' '$<' -opensans_semibold.o: ../../assets/fonts/opensans_semibold.ttf +opensans_semibold.o: $(ROOT_DIR)/selfdrive/assets/fonts/opensans_semibold.ttf @echo "[ bin2o ] $@" cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)' -img_spinner_track.o: ../../assets/img_spinner_track.png +img_spinner_track.o: $(ROOT_DIR)/selfdrive/assets/img_spinner_track.png @echo "[ bin2o ] $@" cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)' -img_spinner_comma.o: ../../assets/img_spinner_comma.png +img_spinner_comma.o: $(ROOT_DIR)/selfdrive/assets/img_spinner_comma.png @echo "[ bin2o ] $@" cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)' diff --git a/selfdrive/ui/spinner/spinner b/selfdrive/ui/android/spinner/spinner similarity index 100% rename from selfdrive/ui/spinner/spinner rename to selfdrive/ui/android/spinner/spinner diff --git a/selfdrive/common/spinner.c b/selfdrive/ui/android/spinner/spinner.c similarity index 99% rename from selfdrive/common/spinner.c rename to selfdrive/ui/android/spinner/spinner.c index 2054229c..33ebf7cd 100644 --- a/selfdrive/common/spinner.c +++ b/selfdrive/ui/android/spinner/spinner.c @@ -42,8 +42,7 @@ bool stdin_input_available() { return (FD_ISSET(0, &fds)); } -int spin(int argc, char** argv) { - int err; +int main(int argc, char** argv) { bool draw_progress = false; float progress_val = 0.0; diff --git a/selfdrive/ui/qt/spinner.cc b/selfdrive/ui/qt/spinner.cc new file mode 100644 index 00000000..9c032316 --- /dev/null +++ b/selfdrive/ui/qt/spinner.cc @@ -0,0 +1,126 @@ +#include +#include +#include + +#include +#include +#include +#include + +#ifdef QCOM2 +#include +#include +#include +#endif + +#include "spinner.hpp" + + +Spinner::Spinner(QWidget *parent) { + QGridLayout *main_layout = new QGridLayout(); + main_layout->setSpacing(0); + main_layout->setMargin(50); + + const int img_size = 500; + + comma = new QLabel(); + comma->setPixmap(QPixmap("../assets/img_spinner_comma.png").scaled(img_size, img_size, Qt::KeepAspectRatio)); + comma->setFixedSize(img_size, img_size); + main_layout->addWidget(comma, 0, 0, Qt::AlignHCenter | Qt::AlignVCenter); + + track_img = QPixmap("../assets/img_spinner_track.png").scaled(img_size, img_size, Qt::KeepAspectRatio); + track = new QLabel(); + track->setPixmap(track_img); + track->setFixedSize(img_size, img_size); + main_layout->addWidget(track, 0, 0, Qt::AlignHCenter | Qt::AlignVCenter); + + text = new QLabel("building boardd"); + text->setVisible(false); + text->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + main_layout->addWidget(text, 1, 0, Qt::AlignHCenter); + + progress_bar = new QProgressBar(); + progress_bar->setMinimum(5); + progress_bar->setMaximum(100); + progress_bar->setTextVisible(false); + progress_bar->setVisible(false); + progress_bar->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + main_layout->addWidget(progress_bar, 1, 0, Qt::AlignHCenter); + + setLayout(main_layout); + setStyleSheet(R"( + Spinner { + background-color: black; + } + QLabel { + color: white; + font-size: 80px; + } + QProgressBar { + background-color: #373737; + border: none; + margin: 100px; + height: 50px; + width: 1000px; + } + QProgressBar::chunk { + background-color: white; + } + )"); + + rotate_timer = new QTimer(this); + rotate_timer->start(1000/30.); + QObject::connect(rotate_timer, SIGNAL(timeout()), this, SLOT(rotate())); + + notifier = new QSocketNotifier(fileno(stdin), QSocketNotifier::Read); + QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(update(int))); +}; + +void Spinner::rotate() { + transform.rotate(5); + + QPixmap r = track_img.transformed(transform); + int x = (r.width() - track_img.width()) / 2; + int y = (r.height() - track_img.height()) / 2; + track->setPixmap(r.copy(x, y, track_img.width(), track_img.height())); +}; + +void Spinner::update(int n) { + std::string line; + std::getline(std::cin, line); + + if (line.length()) { + bool number = std::all_of(line.begin(), line.end(), ::isdigit); + text->setVisible(!number); + progress_bar->setVisible(number); + text->setText(QString::fromStdString(line)); + if (number) { + progress_bar->setValue(std::stoi(line)); + } + } +} + +int main(int argc, char *argv[]) { + QApplication a(argc, argv); + + Spinner *spinner = new Spinner(); + + // TODO: get size from QScreen, doesn't work on tici +#ifdef QCOM2 + int w = 2160, h = 1080; +#else + int w = 1920, h = 1080; +#endif + spinner->setFixedSize(w, h); + spinner->show(); + +#ifdef QCOM2 + QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface(); + wl_surface *s = reinterpret_cast(native->nativeResourceForWindow("surface", spinner->windowHandle())); + wl_surface_set_buffer_transform(s, WL_OUTPUT_TRANSFORM_270); + wl_surface_commit(s); + spinner->showFullScreen(); +#endif + + return a.exec(); +} diff --git a/selfdrive/ui/qt/spinner.hpp b/selfdrive/ui/qt/spinner.hpp new file mode 100644 index 00000000..ea0f8afd --- /dev/null +++ b/selfdrive/ui/qt/spinner.hpp @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include + +class Spinner : public QWidget { + Q_OBJECT + +public: + explicit Spinner(QWidget *parent = 0); + +private: + QPixmap track_img; + QTimer *rotate_timer; + QLabel *comma, *track; + QLabel *text; + QProgressBar *progress_bar; + QTransform transform; + QSocketNotifier *notifier; + +public slots: + void rotate(); + void update(int n); +}; diff --git a/selfdrive/ui/spinner b/selfdrive/ui/spinner new file mode 100755 index 00000000..8f7353a0 --- /dev/null +++ b/selfdrive/ui/spinner @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ -f /EON ]; then + export LD_LIBRARY_PATH="/system/lib64:$LD_LIBRARY_PATH" + exec ./android/spinner/spinner "$1" +else + exec ./qt/spinner "$1" +fi diff --git a/selfdrive/ui/spinner/spinner.c b/selfdrive/ui/spinner/spinner.c deleted file mode 100644 index 14b452a4..00000000 --- a/selfdrive/ui/spinner/spinner.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "common/framebuffer.h" -#include "common/spinner.h" - -int main(int argc, char** argv) { - int err; - - spin(argc, argv); - - return 0; -}