Qt ui for PC (#2023)
* qt ui boilerplate
* this kinda works
* cleanup
* render inside other widget
* cleanup
* more cleanup
* Not needed
* Handle click
* Draw at 20Hz
* create paint.hpp
* move stuff around
* update sidebar
* Draw vision
* this works again
* add clickable settings button
* Only collapse sidebar when started
* always use qt on linux
* fix width
* scrollable area
* talk to NetworkManager
* code to add a connection
* params toggles
* small cleanup
* add qt5 to dockerfile
* Qt on mac
* Add qt to release files
* fix macos build
* nore more ifdefs needed
* add icons
* make a bit nicer
* Hide scrollbar
Co-authored-by: Comma Device <device@comma.ai>
old-commit-hash: e115c51452
commatwo_master
parent
4fd9d6467b
commit
473fb11d34
57 changed files with 1095 additions and 544 deletions
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:7d183563de9d3a758e97af1d376cf3771e58c724ea77ad3be61ec201c5aa74ec |
||||||
|
size 2236 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:c38f169583bac8f1a2f3c20926ebb70874b3e4235f3d62fb2f2c7c6a8d42d58c |
||||||
|
size 12277 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:0d68f2739bd1b8fc990e0d171923c58c382714c7d8ec6cd43f1f808ac87f963c |
||||||
|
size 8910 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:1b99b5fc3158cd5a33a7f18951dbbed94bde96019676a0fe72e8962e68406085 |
||||||
|
size 4471 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:d4909d776263e223853ee49d9101e18dd220909cc8667c45bb040ea1d213ddf4 |
||||||
|
size 1420 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:2e60d6b92ff6351b2bb23e8a21544e11abd0714b02c761b5526957daba33399e |
||||||
|
size 24265 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:86d34123647fc0f21f055417e7a7e327775ee37ee24a47bfabe31435b14f7d68 |
||||||
|
size 8624 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:57a92adcf88c7223b07697f8c2b315f4f4a34b32a866284610d5250144863c6f |
||||||
|
size 28235 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:7e950f121f7ed564b149dd430527c8f0ef976b6d9af66a61fb7b5ebaf7170185 |
||||||
|
size 29822 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:ae8c4922909415dcf51cca6ac54790d3019cc934bf719bda112aa7a9cba8eae3 |
||||||
|
size 635 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:f27f3dfeaa105c7757b5211cbee99b8e0c86cd059f13ac7e9a0807374f1633e7 |
||||||
|
size 604 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:8d2c5640258911c94475615b9c4abc1485c74239f65bef70e0bab9ca84619772 |
||||||
|
size 2577 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:0bcd5b336b2112f43a6f63937aedec4a85047f14a8c3f482e0f85988e1abbeea |
||||||
|
size 58679 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:6eec8334979c2ba5751560a9b6b322d2a5852970b0f783b68112e92bb7c82826 |
||||||
|
size 39872 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:a3cd3b91673eded1282e2082be0efa8e54ed477b5feb3580e521d08078e18ed1 |
||||||
|
size 42640 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:df7d69023cd68d5d49dd073f33f0ca5344911986a26db32fc04cfbfbdfb06474 |
||||||
|
size 18150 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:89d762d8de790460caf5a0d9b545f191d8f8586f11d693e294e7a71e49fc7ecb |
||||||
|
size 14623 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:fa3f1c39a4e82adfb52d43fc0ad6773a70dbaa4fc79109a7d6b6c1f73b298eac |
||||||
|
size 2833 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:735fa47333bddaa91af6d120fd2f76dc562657962abdc55de810d9a77d6e5516 |
||||||
|
size 6674 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:a522be46c662753063fce319bd29f252df1b2ec082eb4dbd6518d59bdf6a5fa4 |
||||||
|
size 13369 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:c37ee59b9d273193cedae3408ce29b22d8b2d27732235c62065e78c5eca5812d |
||||||
|
size 42462 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:28a131696208124a61d08f49f2ad6f76e783a405354a8c52a7fa1b9d87fd4e51 |
||||||
|
size 3321 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:05da2ff02bd1d7d82c22b948e90eb3f8a2270dcd01833115a3d4a0edc244ec55 |
||||||
|
size 15798 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:1535245dbb4e102e07edda7c41e3f993a521e8a18711c6c797ec82c2a94e7db8 |
||||||
|
size 8002 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:ab5348b245a239ed67972bdb69ec2d5e60d87255238328ae8018ba9fd5906cc2 |
||||||
|
size 1265 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:73e1bc396026bfaf8e61a27add5baca4fb29131990bd19acfd6c2052d6fdf874 |
||||||
|
size 6608 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:163cc50c861ca3137c81ddb3cc6938e1076bd3616d96657c012539675da8cbe5 |
||||||
|
size 6331 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:5861d3b84e80ef664806dbf2c2592a46a67e2f88d192ba3723fe3b95ba0f8788 |
||||||
|
size 268080 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:ea18f3366732c57ea1bc9c10792f32a06f182f759f69bc2a0b1b00cc389f5bc6 |
||||||
|
size 69907 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:72be2ebd471ddc4308dda5b3f5ba59f5d56eadb6c9dc80861697b01859550ffc |
||||||
|
size 1515 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:e2e44f54137ee5a5a6edc3d82b16e146f0b45feb57146dbb9c334e06c5de603f |
||||||
|
size 2054 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:eed7cde35bf5d10963201cda9299252167b79f470d021c349db1f5eb4b9c2e67 |
||||||
|
size 3038 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:1ba6e92b7d7e99f5b62eacd6997925c7585e9d88e6cb9d552904b94b3650758c |
||||||
|
size 3270 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:755dd7fa5a92ac4cd5f800e37ab337a5870739a025d051bcc1c86828a7b277e6 |
||||||
|
size 3087 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:6f6856440f343735eab487559e9fa83ef570e3d221a3631d3cec3229588aa1a3 |
||||||
|
size 3121 |
@ -0,0 +1,3 @@ |
|||||||
|
version https://git-lfs.github.com/spec/v1 |
||||||
|
oid sha256:296ca507b947f18e4212180799be14d261e723aedeb49b0612b61b805183f87d |
||||||
|
size 3186 |
@ -0,0 +1 @@ |
|||||||
|
moc_* |
@ -1,17 +1,26 @@ |
|||||||
Import('env', 'arch', 'common', 'messaging', 'gpucommon', 'visionipc', 'cereal') |
Import('env', 'qt_env', 'arch', 'common', 'messaging', 'gpucommon', 'visionipc', 'cereal') |
||||||
|
|
||||||
src = ['ui.cc', 'paint.cc', 'sidebar.cc', '#phonelibs/nanovg/nanovg.c'] |
src = ['ui.cc', 'paint.cc', 'sidebar.cc', '#phonelibs/nanovg/nanovg.c'] |
||||||
libs = [common, 'zmq', 'czmq', 'capnp', 'kj', 'm', cereal, messaging, gpucommon, visionipc] |
libs = [common, 'zmq', 'czmq', 'capnp', 'kj', 'm', cereal, messaging, gpucommon, visionipc] |
||||||
|
|
||||||
if arch == "aarch64": |
|
||||||
|
if qt_env is None: |
||||||
src += ['sound.cc'] |
src += ['sound.cc'] |
||||||
libs += ['EGL', 'GLESv3', 'gnustl_shared', 'log', 'utils', 'gui', 'hardware', 'ui', 'CB', 'gsl', 'adreno_utils', 'OpenSLES', 'cutils', 'uuid', 'OpenCL'] |
libs += ['EGL', 'GLESv3', 'gnustl_shared', 'log', 'utils', 'gui', 'hardware', 'ui', 'CB', 'gsl', 'adreno_utils', 'OpenSLES', 'cutils', 'uuid', 'OpenCL'] |
||||||
linkflags = ['-Wl,-rpath=/system/lib64,-rpath=/system/comma/usr/lib'] |
linkflags = ['-Wl,-rpath=/system/lib64,-rpath=/system/comma/usr/lib'] |
||||||
else: |
|
||||||
src += ['linux.cc'] |
|
||||||
libs += ['pthread', 'glfw'] |
|
||||||
linkflags = [] |
|
||||||
|
|
||||||
env.Program('_ui', src, |
src = ["android_ui.cc"] + src |
||||||
|
env.Program('_ui', src, |
||||||
LINKFLAGS=linkflags, |
LINKFLAGS=linkflags, |
||||||
LIBS=libs) |
LIBS=libs) |
||||||
|
|
||||||
|
else: |
||||||
|
qt_libs = ["GL", "pthread"] |
||||||
|
|
||||||
|
if arch == "Darwin": |
||||||
|
qt_env["FRAMEWORKS"] += ["QtWidgets", "QtGui", "QtCore", "QtDBus"] |
||||||
|
else: |
||||||
|
qt_libs += ["Qt5Widgets", "Qt5Gui", "Qt5Core", "Qt5DBus"] |
||||||
|
|
||||||
|
qt_src = ["qt/ui.cc", "qt/window.cc", "qt/settings.cc"] + src |
||||||
|
qt_env.Program("_ui", qt_src, LIBS=qt_libs + libs) |
||||||
|
@ -0,0 +1,360 @@ |
|||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <sys/resource.h> |
||||||
|
#include <czmq.h> |
||||||
|
|
||||||
|
#include "common/util.h" |
||||||
|
#include "common/utilpp.h" |
||||||
|
#include "common/params.h" |
||||||
|
#include "common/touch.h" |
||||||
|
#include "common/timing.h" |
||||||
|
#include "common/swaglog.h" |
||||||
|
|
||||||
|
#include "ui.hpp" |
||||||
|
#include "paint.hpp" |
||||||
|
|
||||||
|
// Includes for light sensor
|
||||||
|
#include <cutils/properties.h> |
||||||
|
#include <hardware/sensors.h> |
||||||
|
#include <utils/Timers.h> |
||||||
|
|
||||||
|
volatile sig_atomic_t do_exit = 0; |
||||||
|
static void set_do_exit(int sig) { |
||||||
|
do_exit = 1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
static void* light_sensor_thread(void *args) { |
||||||
|
set_thread_name("light_sensor"); |
||||||
|
|
||||||
|
int err; |
||||||
|
UIState *s = (UIState*)args; |
||||||
|
s->light_sensor = 0.0; |
||||||
|
|
||||||
|
struct sensors_poll_device_t* device; |
||||||
|
struct sensors_module_t* module; |
||||||
|
|
||||||
|
hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); |
||||||
|
sensors_open(&module->common, &device); |
||||||
|
|
||||||
|
// need to do this
|
||||||
|
struct sensor_t const* list; |
||||||
|
module->get_sensors_list(module, &list); |
||||||
|
|
||||||
|
int SENSOR_LIGHT = 7; |
||||||
|
|
||||||
|
err = device->activate(device, SENSOR_LIGHT, 0); |
||||||
|
if (err != 0) goto fail; |
||||||
|
err = device->activate(device, SENSOR_LIGHT, 1); |
||||||
|
if (err != 0) goto fail; |
||||||
|
|
||||||
|
device->setDelay(device, SENSOR_LIGHT, ms2ns(100)); |
||||||
|
|
||||||
|
while (!do_exit) { |
||||||
|
static const size_t numEvents = 1; |
||||||
|
sensors_event_t buffer[numEvents]; |
||||||
|
|
||||||
|
int n = device->poll(device, buffer, numEvents); |
||||||
|
if (n < 0) { |
||||||
|
LOG_100("light_sensor_poll failed: %d", n); |
||||||
|
} |
||||||
|
if (n > 0) { |
||||||
|
s->light_sensor = buffer[0].light; |
||||||
|
} |
||||||
|
} |
||||||
|
sensors_close(device); |
||||||
|
return NULL; |
||||||
|
|
||||||
|
fail: |
||||||
|
LOGE("LIGHT SENSOR IS MISSING"); |
||||||
|
s->light_sensor = 255; |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
static void ui_set_brightness(UIState *s, int brightness) { |
||||||
|
static int last_brightness = -1; |
||||||
|
if (last_brightness != brightness && (s->awake || brightness == 0)) { |
||||||
|
if (set_brightness(brightness)) { |
||||||
|
last_brightness = brightness; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int event_processing_enabled = -1; |
||||||
|
static void enable_event_processing(bool yes) { |
||||||
|
if (event_processing_enabled != 1 && yes) { |
||||||
|
system("service call window 18 i32 1"); // enable event processing
|
||||||
|
event_processing_enabled = 1; |
||||||
|
} else if (event_processing_enabled != 0 && !yes) { |
||||||
|
system("service call window 18 i32 0"); // disable event processing
|
||||||
|
event_processing_enabled = 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void set_awake(UIState *s, bool awake) { |
||||||
|
if (awake) { |
||||||
|
// 30 second timeout
|
||||||
|
s->awake_timeout = 30*UI_FREQ; |
||||||
|
} |
||||||
|
if (s->awake != awake) { |
||||||
|
s->awake = awake; |
||||||
|
|
||||||
|
// TODO: replace command_awake and command_sleep with direct calls to android
|
||||||
|
if (awake) { |
||||||
|
LOGW("awake normal"); |
||||||
|
framebuffer_set_power(s->fb, HWC_POWER_MODE_NORMAL); |
||||||
|
enable_event_processing(true); |
||||||
|
} else { |
||||||
|
LOGW("awake off"); |
||||||
|
ui_set_brightness(s, 0); |
||||||
|
framebuffer_set_power(s->fb, HWC_POWER_MODE_OFF); |
||||||
|
enable_event_processing(false); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void handle_vision_touch(UIState *s, int touch_x, int touch_y) { |
||||||
|
if (s->started && (touch_x >= s->scene.ui_viz_rx - bdr_s) |
||||||
|
&& (s->active_app != cereal::UiLayoutState::App::SETTINGS)) { |
||||||
|
if (!s->scene.frontview) { |
||||||
|
s->scene.uilayout_sidebarcollapsed = !s->scene.uilayout_sidebarcollapsed; |
||||||
|
} else { |
||||||
|
write_db_value("IsDriverViewEnabled", "0", 1); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void handle_sidebar_touch(UIState *s, int touch_x, int touch_y) { |
||||||
|
if (!s->scene.uilayout_sidebarcollapsed && touch_x <= sbr_w) { |
||||||
|
if (touch_x >= settings_btn_x && touch_x < (settings_btn_x + settings_btn_w) |
||||||
|
&& touch_y >= settings_btn_y && touch_y < (settings_btn_y + settings_btn_h)) { |
||||||
|
s->active_app = cereal::UiLayoutState::App::SETTINGS; |
||||||
|
} |
||||||
|
else if (touch_x >= home_btn_x && touch_x < (home_btn_x + home_btn_w) |
||||||
|
&& touch_y >= home_btn_y && touch_y < (home_btn_y + home_btn_h)) { |
||||||
|
if (s->started) { |
||||||
|
s->active_app = cereal::UiLayoutState::App::NONE; |
||||||
|
s->scene.uilayout_sidebarcollapsed = true; |
||||||
|
} else { |
||||||
|
s->active_app = cereal::UiLayoutState::App::HOME; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static void update_offroad_layout_state(UIState *s) { |
||||||
|
static int timeout = 0; |
||||||
|
static bool prev_collapsed = false; |
||||||
|
static cereal::UiLayoutState::App prev_app = cereal::UiLayoutState::App::NONE; |
||||||
|
if (timeout > 0) { |
||||||
|
timeout--; |
||||||
|
} |
||||||
|
if (prev_collapsed != s->scene.uilayout_sidebarcollapsed || prev_app != s->active_app || timeout == 0) { |
||||||
|
capnp::MallocMessageBuilder msg; |
||||||
|
auto event = msg.initRoot<cereal::Event>(); |
||||||
|
event.setLogMonoTime(nanos_since_boot()); |
||||||
|
auto layout = event.initUiLayoutState(); |
||||||
|
layout.setActiveApp(s->active_app); |
||||||
|
layout.setSidebarCollapsed(s->scene.uilayout_sidebarcollapsed); |
||||||
|
s->pm->send("offroadLayout", msg); |
||||||
|
LOGD("setting active app to %d with sidebar %d", (int)s->active_app, s->scene.uilayout_sidebarcollapsed); |
||||||
|
prev_collapsed = s->scene.uilayout_sidebarcollapsed; |
||||||
|
prev_app = s->active_app; |
||||||
|
timeout = 2 * UI_FREQ; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
int main(int argc, char* argv[]) { |
||||||
|
int err; |
||||||
|
setpriority(PRIO_PROCESS, 0, -14); |
||||||
|
|
||||||
|
zsys_handler_set(NULL); |
||||||
|
signal(SIGINT, (sighandler_t)set_do_exit); |
||||||
|
|
||||||
|
UIState uistate = {}; |
||||||
|
UIState *s = &uistate; |
||||||
|
ui_init(s); |
||||||
|
set_awake(s, true); |
||||||
|
|
||||||
|
enable_event_processing(true); |
||||||
|
|
||||||
|
pthread_t connect_thread_handle; |
||||||
|
err = pthread_create(&connect_thread_handle, NULL, |
||||||
|
vision_connect_thread, s); |
||||||
|
assert(err == 0); |
||||||
|
|
||||||
|
pthread_t light_sensor_thread_handle; |
||||||
|
err = pthread_create(&light_sensor_thread_handle, NULL, |
||||||
|
light_sensor_thread, s); |
||||||
|
assert(err == 0); |
||||||
|
|
||||||
|
TouchState touch = {0}; |
||||||
|
touch_init(&touch); |
||||||
|
s->touch_fd = touch.fd; |
||||||
|
|
||||||
|
// light sensor scaling params
|
||||||
|
const bool LEON = util::read_file("/proc/cmdline").find("letv") != std::string::npos; |
||||||
|
|
||||||
|
float brightness_b, brightness_m; |
||||||
|
int result = read_param(&brightness_b, "BRIGHTNESS_B", true); |
||||||
|
result += read_param(&brightness_m, "BRIGHTNESS_M", true); |
||||||
|
|
||||||
|
if(result != 0){ |
||||||
|
brightness_b = LEON ? 10.0 : 5.0; |
||||||
|
brightness_m = LEON ? 2.6 : 1.3; |
||||||
|
write_param_float(brightness_b, "BRIGHTNESS_B", true); |
||||||
|
write_param_float(brightness_m, "BRIGHTNESS_M", true); |
||||||
|
} |
||||||
|
|
||||||
|
float smooth_brightness = brightness_b; |
||||||
|
|
||||||
|
const int MIN_VOLUME = LEON ? 12 : 9; |
||||||
|
const int MAX_VOLUME = LEON ? 15 : 12; |
||||||
|
assert(s->sound.init(MIN_VOLUME)); |
||||||
|
|
||||||
|
int draws = 0; |
||||||
|
|
||||||
|
while (!do_exit) { |
||||||
|
bool should_swap = false; |
||||||
|
if (!s->started) { |
||||||
|
// Delay a while to avoid 9% cpu usage while car is not started and user is keeping touching on the screen.
|
||||||
|
// Don't hold the lock while sleeping, so that vision_connect_thread have chances to get the lock.
|
||||||
|
usleep(30 * 1000); |
||||||
|
} |
||||||
|
pthread_mutex_lock(&s->lock); |
||||||
|
double u1 = millis_since_boot(); |
||||||
|
|
||||||
|
// light sensor is only exposed on EONs
|
||||||
|
float clipped_brightness = (s->light_sensor*brightness_m) + brightness_b; |
||||||
|
if (clipped_brightness > 512) clipped_brightness = 512; |
||||||
|
smooth_brightness = clipped_brightness * 0.01 + smooth_brightness * 0.99; |
||||||
|
if (smooth_brightness > 255) smooth_brightness = 255; |
||||||
|
ui_set_brightness(s, (int)smooth_brightness); |
||||||
|
ui_update_sizes(s); |
||||||
|
|
||||||
|
// poll for touch events
|
||||||
|
int touch_x = -1, touch_y = -1; |
||||||
|
int touched = touch_poll(&touch, &touch_x, &touch_y, 0); |
||||||
|
if (touched == 1) { |
||||||
|
set_awake(s, true); |
||||||
|
handle_sidebar_touch(s, touch_x, touch_y); |
||||||
|
handle_vision_touch(s, touch_x, touch_y); |
||||||
|
} |
||||||
|
|
||||||
|
if (!s->started) { |
||||||
|
// always process events offroad
|
||||||
|
check_messages(s); |
||||||
|
|
||||||
|
if (s->started) { |
||||||
|
s->controls_timeout = 5 * UI_FREQ; |
||||||
|
} |
||||||
|
} else { |
||||||
|
set_awake(s, true); |
||||||
|
// Car started, fetch a new rgb image from ipc
|
||||||
|
if (s->vision_connected){ |
||||||
|
ui_update(s); |
||||||
|
} |
||||||
|
|
||||||
|
check_messages(s); |
||||||
|
|
||||||
|
// Visiond process is just stopped, force a redraw to make screen blank again.
|
||||||
|
if (!s->started) { |
||||||
|
s->scene.uilayout_sidebarcollapsed = false; |
||||||
|
ui_draw(s); |
||||||
|
glFinish(); |
||||||
|
should_swap = true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// manage wakefulness
|
||||||
|
if (s->awake_timeout > 0) { |
||||||
|
s->awake_timeout--; |
||||||
|
} else { |
||||||
|
set_awake(s, false); |
||||||
|
} |
||||||
|
|
||||||
|
// manage hardware disconnect
|
||||||
|
if (s->hardware_timeout > 0) { |
||||||
|
s->hardware_timeout--; |
||||||
|
} else { |
||||||
|
s->scene.hwType = cereal::HealthData::HwType::UNKNOWN; |
||||||
|
} |
||||||
|
|
||||||
|
// Don't waste resources on drawing in case screen is off
|
||||||
|
if (s->awake) { |
||||||
|
ui_draw(s); |
||||||
|
glFinish(); |
||||||
|
should_swap = true; |
||||||
|
} |
||||||
|
|
||||||
|
s->sound.setVolume(fmin(MAX_VOLUME, MIN_VOLUME + s->scene.controls_state.getVEgo() / 5)); // up one notch every 5 m/s
|
||||||
|
|
||||||
|
if (s->controls_timeout > 0) { |
||||||
|
s->controls_timeout--; |
||||||
|
} else if (s->started && !s->scene.frontview) { |
||||||
|
if (!s->controls_seen) { |
||||||
|
// car is started, but controlsState hasn't been seen at all
|
||||||
|
s->scene.alert_text1 = "openpilot Unavailable"; |
||||||
|
s->scene.alert_text2 = "Waiting for controls to start"; |
||||||
|
s->scene.alert_size = cereal::ControlsState::AlertSize::MID; |
||||||
|
} else { |
||||||
|
// car is started, but controls is lagging or died
|
||||||
|
LOGE("Controls unresponsive"); |
||||||
|
|
||||||
|
if (s->scene.alert_text2 != "Controls Unresponsive") { |
||||||
|
s->sound.play(AudibleAlert::CHIME_WARNING_REPEAT); |
||||||
|
} |
||||||
|
|
||||||
|
s->scene.alert_text1 = "TAKE CONTROL IMMEDIATELY"; |
||||||
|
s->scene.alert_text2 = "Controls Unresponsive"; |
||||||
|
s->scene.alert_size = cereal::ControlsState::AlertSize::FULL; |
||||||
|
update_status(s, STATUS_ALERT); |
||||||
|
} |
||||||
|
ui_draw_vision_alert(s, s->scene.alert_size, s->status, s->scene.alert_text1.c_str(), s->scene.alert_text2.c_str()); |
||||||
|
} |
||||||
|
|
||||||
|
read_param_timeout(&s->is_metric, "IsMetric", &s->is_metric_timeout); |
||||||
|
read_param_timeout(&s->longitudinal_control, "LongitudinalControl", &s->longitudinal_control_timeout); |
||||||
|
read_param_timeout(&s->limit_set_speed, "LimitSetSpeed", &s->limit_set_speed_timeout); |
||||||
|
read_param_timeout(&s->speed_lim_off, "SpeedLimitOffset", &s->limit_set_speed_timeout); |
||||||
|
int param_read = read_param_timeout(&s->last_athena_ping, "LastAthenaPingTime", &s->last_athena_ping_timeout); |
||||||
|
if (param_read != -1) { // Param was updated this loop
|
||||||
|
if (param_read != 0) { // Failed to read param
|
||||||
|
s->scene.athenaStatus = NET_DISCONNECTED; |
||||||
|
} else if (nanos_since_boot() - s->last_athena_ping < 70e9) { |
||||||
|
s->scene.athenaStatus = NET_CONNECTED; |
||||||
|
} else { |
||||||
|
s->scene.athenaStatus = NET_ERROR; |
||||||
|
} |
||||||
|
} |
||||||
|
update_offroad_layout_state(s); |
||||||
|
|
||||||
|
pthread_mutex_unlock(&s->lock); |
||||||
|
|
||||||
|
// the bg thread needs to be scheduled, so the main thread needs time without the lock
|
||||||
|
// safe to do this outside the lock?
|
||||||
|
if (should_swap) { |
||||||
|
double u2 = millis_since_boot(); |
||||||
|
if (u2-u1 > 66) { |
||||||
|
// warn on sub 15fps
|
||||||
|
LOGW("slow frame(%d) time: %.2f", draws, u2-u1); |
||||||
|
} |
||||||
|
draws++; |
||||||
|
framebuffer_swap(s->fb); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
set_awake(s, true); |
||||||
|
|
||||||
|
// wake up bg thread to exit
|
||||||
|
pthread_mutex_lock(&s->lock); |
||||||
|
pthread_mutex_unlock(&s->lock); |
||||||
|
|
||||||
|
// join light_sensor_thread?
|
||||||
|
err = pthread_join(connect_thread_handle, NULL); |
||||||
|
assert(err == 0); |
||||||
|
delete s->sm; |
||||||
|
delete s->pm; |
||||||
|
return 0; |
||||||
|
} |
@ -1,107 +0,0 @@ |
|||||||
#include <stdio.h> |
|
||||||
#include <stdint.h> |
|
||||||
#include <stdlib.h> |
|
||||||
#include <assert.h> |
|
||||||
#include <string.h> |
|
||||||
|
|
||||||
#include "ui.hpp" |
|
||||||
|
|
||||||
#ifndef __APPLE__ |
|
||||||
#define GLFW_INCLUDE_ES2 |
|
||||||
#else |
|
||||||
#define GLFW_INCLUDE_GLCOREARB |
|
||||||
#endif |
|
||||||
|
|
||||||
#define GLFW_INCLUDE_GLEXT |
|
||||||
#include <GLFW/glfw3.h> |
|
||||||
|
|
||||||
typedef struct FramebufferState FramebufferState; |
|
||||||
typedef struct TouchState TouchState; |
|
||||||
|
|
||||||
extern "C" { |
|
||||||
|
|
||||||
FramebufferState* framebuffer_init( |
|
||||||
const char* name, int32_t layer, int alpha, |
|
||||||
int *out_w, int *out_h) { |
|
||||||
glfwInit(); |
|
||||||
|
|
||||||
#ifndef __APPLE__ |
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); |
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); |
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); |
|
||||||
#else |
|
||||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); |
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); |
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); |
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); |
|
||||||
#endif |
|
||||||
glfwWindowHint(GLFW_RESIZABLE, 0); |
|
||||||
GLFWwindow* window; |
|
||||||
window = glfwCreateWindow(1920, 1080, "ui", NULL, NULL); |
|
||||||
if (!window) { |
|
||||||
printf("glfwCreateWindow failed\n"); |
|
||||||
} |
|
||||||
|
|
||||||
glfwMakeContextCurrent(window); |
|
||||||
glfwSwapInterval(1); |
|
||||||
|
|
||||||
// clear screen
|
|
||||||
glClearColor(0.2f, 0.2f, 0.2f, 1.0f); |
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
|
||||||
framebuffer_swap((FramebufferState*)window); |
|
||||||
|
|
||||||
if (out_w) *out_w = 1920; |
|
||||||
if (out_h) *out_h = 1080; |
|
||||||
|
|
||||||
return (FramebufferState*)window; |
|
||||||
} |
|
||||||
|
|
||||||
void framebuffer_set_power(FramebufferState *s, int mode) { |
|
||||||
} |
|
||||||
|
|
||||||
void framebuffer_swap(FramebufferState *s) { |
|
||||||
glfwSwapBuffers((GLFWwindow*)s); |
|
||||||
glfwPollEvents(); |
|
||||||
} |
|
||||||
|
|
||||||
bool set_brightness(int brightness) { return true; } |
|
||||||
|
|
||||||
void touch_init(TouchState *s) { |
|
||||||
printf("touch_init\n"); |
|
||||||
} |
|
||||||
|
|
||||||
int touch_poll(TouchState *s, int* out_x, int* out_y, int timeout) { |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
int touch_read(TouchState *s, int* out_x, int* out_y) { |
|
||||||
return -1; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
#include "sound.hpp" |
|
||||||
|
|
||||||
bool Sound::init(int volume) { return true; } |
|
||||||
bool Sound::play(AudibleAlert alert) { printf("play sound: %d\n", (int)alert); return true; } |
|
||||||
void Sound::stop() {} |
|
||||||
void Sound::setVolume(int volume) {} |
|
||||||
Sound::~Sound() {} |
|
||||||
|
|
||||||
#include "common/visionimg.h" |
|
||||||
#include <sys/mman.h> |
|
||||||
|
|
||||||
GLuint visionimg_to_gl(const VisionImg *img, EGLImageKHR *pkhr, void **pph) { |
|
||||||
unsigned int texture; |
|
||||||
glGenTextures(1, &texture); |
|
||||||
glBindTexture(GL_TEXTURE_2D, texture); |
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img->width, img->height, 0, GL_RGB, GL_UNSIGNED_BYTE, *pph); |
|
||||||
glGenerateMipmap(GL_TEXTURE_2D); |
|
||||||
*pkhr = (EGLImageKHR)1; // not NULL
|
|
||||||
return texture; |
|
||||||
} |
|
||||||
|
|
||||||
void visionimg_destroy_gl(EGLImageKHR khr, void *ph) { |
|
||||||
// empty
|
|
||||||
} |
|
||||||
|
|
@ -0,0 +1,11 @@ |
|||||||
|
#pragma once |
||||||
|
#include "ui.hpp" |
||||||
|
|
||||||
|
|
||||||
|
void ui_draw_vision_alert(UIState *s, cereal::ControlsState::AlertSize va_size, int va_color, |
||||||
|
const char* va_text1, const char* va_text2); |
||||||
|
void ui_draw(UIState *s); |
||||||
|
void ui_draw_image(NVGcontext *vg, float x, float y, float w, float h, int image, float alpha); |
||||||
|
void ui_draw_rect(NVGcontext *vg, float x, float y, float w, float h, NVGcolor color, float r = 0, int width = 0); |
||||||
|
void ui_draw_rect(NVGcontext *vg, float x, float y, float w, float h, NVGpaint &paint, float r = 0); |
||||||
|
void ui_nvg_init(UIState *s); |
@ -0,0 +1,140 @@ |
|||||||
|
#include <string> |
||||||
|
#include <iostream> |
||||||
|
#include <sstream> |
||||||
|
#include <cassert> |
||||||
|
|
||||||
|
#include "qt/settings.hpp" |
||||||
|
|
||||||
|
#include <QVBoxLayout> |
||||||
|
#include <QHBoxLayout> |
||||||
|
#include <QPushButton> |
||||||
|
#include <QLabel> |
||||||
|
#include <QScrollArea> |
||||||
|
#include <QScroller> |
||||||
|
#include <QScrollerProperties> |
||||||
|
#include <QDebug> |
||||||
|
#include <QPixmap> |
||||||
|
|
||||||
|
#include "common/params.h" |
||||||
|
|
||||||
|
ParamsToggle::ParamsToggle(QString param, QString title, QString description, QString icon, QWidget *parent): QFrame(parent) , param(param) { |
||||||
|
QHBoxLayout *hlayout = new QHBoxLayout; |
||||||
|
QVBoxLayout *vlayout = new QVBoxLayout; |
||||||
|
|
||||||
|
hlayout->addSpacing(25); |
||||||
|
if (icon.length()){ |
||||||
|
QPixmap pix(icon); |
||||||
|
QLabel *icon = new QLabel(); |
||||||
|
icon->setPixmap(pix.scaledToWidth(100, Qt::SmoothTransformation)); |
||||||
|
icon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); |
||||||
|
hlayout->addWidget(icon); |
||||||
|
} else{ |
||||||
|
hlayout->addSpacing(100); |
||||||
|
} |
||||||
|
hlayout->addSpacing(25); |
||||||
|
|
||||||
|
checkbox = new QCheckBox(title); |
||||||
|
QLabel *label = new QLabel(description); |
||||||
|
label->setWordWrap(true); |
||||||
|
|
||||||
|
vlayout->addWidget(checkbox); |
||||||
|
vlayout->addWidget(label); |
||||||
|
hlayout->addLayout(vlayout); |
||||||
|
|
||||||
|
setLayout(hlayout); |
||||||
|
|
||||||
|
auto p = read_db_bytes(param.toStdString().c_str()); |
||||||
|
if (p.size()){ |
||||||
|
checkbox->setChecked(p[0] == '1'); |
||||||
|
} |
||||||
|
|
||||||
|
setStyleSheet(R"( |
||||||
|
QCheckBox { font-size: 40px } |
||||||
|
QLabel { font-size: 20px } |
||||||
|
* { |
||||||
|
background-color: #114265; |
||||||
|
} |
||||||
|
)"); |
||||||
|
|
||||||
|
QObject::connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(checkboxClicked(int))); |
||||||
|
} |
||||||
|
|
||||||
|
void ParamsToggle::checkboxClicked(int state){ |
||||||
|
char value = state ? '1': '0'; |
||||||
|
write_db_value(param.toStdString().c_str(), &value, 1); |
||||||
|
} |
||||||
|
|
||||||
|
SettingsWindow::SettingsWindow(QWidget *parent) : QWidget(parent) { |
||||||
|
QWidget *container = new QWidget(this); |
||||||
|
|
||||||
|
QVBoxLayout *settings_list = new QVBoxLayout(); |
||||||
|
settings_list->addWidget(new ParamsToggle("OpenpilotEnabledToggle", |
||||||
|
"Enable Openpilot", |
||||||
|
"Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off.", |
||||||
|
"../assets/offroad/icon_openpilot.png" |
||||||
|
)); |
||||||
|
settings_list->addWidget(new ParamsToggle("LaneChangeEnabled", |
||||||
|
"Enable Lane Change Assist", |
||||||
|
"Perform assisted lane changes with openpilot by checking your surroundings for safety, activating the turn signal and gently nudging the steering wheel towards your desired lane. openpilot is not capable of checking if a lane change is safe. You must continuously observe your surroundings to use this feature.", |
||||||
|
"../assets/offroad/icon_road.png" |
||||||
|
)); |
||||||
|
settings_list->addWidget(new ParamsToggle("IsLdwEnabled", |
||||||
|
"Enable Lane Departure Warnings", |
||||||
|
"Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31mph (50kph).", |
||||||
|
"../assets/offroad/icon_warning.png" |
||||||
|
)); |
||||||
|
settings_list->addWidget(new ParamsToggle("RecordFront", |
||||||
|
"Record and Upload Driver Camera", |
||||||
|
"Upload data from the driver facing camera and help improve the driver monitoring algorithm.", |
||||||
|
"../assets/offroad/icon_network.png" |
||||||
|
)); |
||||||
|
settings_list->addWidget(new ParamsToggle("IsRHD", |
||||||
|
"Enable Right-Hand Drive", |
||||||
|
"Allow openpilot to obey left-hand traffic conventions and perform driver monitoring on right driver seat.", |
||||||
|
"../assets/offroad/icon_openpilot_mirrored.png" |
||||||
|
)); |
||||||
|
settings_list->addWidget(new ParamsToggle("IsMetric", |
||||||
|
"Use Metric System", |
||||||
|
"Display speed in km/h instead of mp/h.", |
||||||
|
"../assets/offroad/icon_metric.png" |
||||||
|
)); |
||||||
|
settings_list->addWidget(new ParamsToggle("CommunityFeaturesToggle", |
||||||
|
"Enable Community Features", |
||||||
|
"Use features from the open source community that are not maintained or supported by comma.ai and have not been confirmed to meet the standard safety model. These features include community supported cars and community supported hardware. Be extra cautious when using these features", |
||||||
|
"../assets/offroad/icon_shell.png" |
||||||
|
)); |
||||||
|
|
||||||
|
settings_list->setSpacing(25); |
||||||
|
|
||||||
|
container->setLayout(settings_list); |
||||||
|
container->setFixedWidth(1650); |
||||||
|
|
||||||
|
QScrollArea *scrollArea = new QScrollArea; |
||||||
|
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
||||||
|
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
||||||
|
scrollArea->setWidget(container); |
||||||
|
|
||||||
|
QScrollerProperties sp; |
||||||
|
sp.setScrollMetric(QScrollerProperties::DecelerationFactor, 2.0); |
||||||
|
|
||||||
|
QScroller* qs = QScroller::scroller(scrollArea); |
||||||
|
qs->setScrollerProperties(sp); |
||||||
|
|
||||||
|
QHBoxLayout *main_layout = new QHBoxLayout; |
||||||
|
main_layout->addSpacing(50); |
||||||
|
main_layout->addWidget(scrollArea); |
||||||
|
|
||||||
|
QPushButton * button = new QPushButton("Close"); |
||||||
|
main_layout->addWidget(button); |
||||||
|
main_layout->addSpacing(20); |
||||||
|
|
||||||
|
setLayout(main_layout); |
||||||
|
|
||||||
|
QScroller::grabGesture(scrollArea, QScroller::LeftMouseButtonGesture); |
||||||
|
QObject::connect(button, SIGNAL(clicked()), this, SIGNAL(closeSettings())); |
||||||
|
|
||||||
|
setStyleSheet(R"( |
||||||
|
QPushButton { font-size: 40px } |
||||||
|
)"); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,28 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <QWidget> |
||||||
|
#include <QFrame> |
||||||
|
#include <QTimer> |
||||||
|
#include <QCheckBox> |
||||||
|
|
||||||
|
class ParamsToggle : public QFrame { |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
private: |
||||||
|
QCheckBox *checkbox; |
||||||
|
QString param; |
||||||
|
public: |
||||||
|
explicit ParamsToggle(QString param, QString title, QString description, QString icon, QWidget *parent = 0); |
||||||
|
public slots: |
||||||
|
void checkboxClicked(int state); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SettingsWindow : public QWidget { |
||||||
|
Q_OBJECT |
||||||
|
public: |
||||||
|
explicit SettingsWindow(QWidget *parent = 0); |
||||||
|
signals: |
||||||
|
void closeSettings(); |
||||||
|
}; |
@ -0,0 +1,15 @@ |
|||||||
|
#include <QApplication> |
||||||
|
|
||||||
|
#include "window.hpp" |
||||||
|
|
||||||
|
int main(int argc, char *argv[]) |
||||||
|
{ |
||||||
|
QApplication a(argc, argv); |
||||||
|
|
||||||
|
MainWindow w; |
||||||
|
|
||||||
|
w.setFixedSize(vwp_w, vwp_h); |
||||||
|
w.show(); |
||||||
|
|
||||||
|
return a.exec(); |
||||||
|
} |
@ -0,0 +1,69 @@ |
|||||||
|
#include <QtDBus> |
||||||
|
#include <QDebug> |
||||||
|
|
||||||
|
typedef QMap<QString, QMap<QString, QVariant> > Connection; |
||||||
|
Q_DECLARE_METATYPE(Connection) |
||||||
|
|
||||||
|
void wifi_stuff(){ |
||||||
|
qDBusRegisterMetaType<Connection>(); |
||||||
|
|
||||||
|
QString nm_path = "/org/freedesktop/NetworkManager"; |
||||||
|
QString nm_settings_path = "/org/freedesktop/NetworkManager/Settings"; |
||||||
|
|
||||||
|
QString nm_iface = "org.freedesktop.NetworkManager"; |
||||||
|
QString props_iface = "org.freedesktop.DBus.Properties"; |
||||||
|
QString nm_settings_iface = "org.freedesktop.NetworkManager.Settings"; |
||||||
|
|
||||||
|
QString nm_service = "org.freedesktop.NetworkManager"; |
||||||
|
QString device_service = "org.freedesktop.NetworkManager.Device"; |
||||||
|
|
||||||
|
QDBusConnection bus = QDBusConnection::systemBus(); |
||||||
|
|
||||||
|
// Get devices
|
||||||
|
QDBusInterface nm(nm_service, nm_path, nm_iface, bus); |
||||||
|
QDBusMessage response = nm.call("GetDevices"); |
||||||
|
QVariant first = response.arguments().at(0); |
||||||
|
|
||||||
|
const QDBusArgument &args = first.value<QDBusArgument>(); |
||||||
|
args.beginArray(); |
||||||
|
while (!args.atEnd()) { |
||||||
|
QDBusObjectPath path; |
||||||
|
args >> path; |
||||||
|
|
||||||
|
// Get device type
|
||||||
|
QDBusInterface device_props(nm_service, path.path(), props_iface, bus); |
||||||
|
QDBusMessage response = device_props.call("Get", device_service, "DeviceType"); |
||||||
|
QVariant first = response.arguments().at(0); |
||||||
|
QDBusVariant dbvFirst = first.value<QDBusVariant>(); |
||||||
|
QVariant vFirst = dbvFirst.variant(); |
||||||
|
uint device_type = vFirst.value<uint>(); |
||||||
|
qDebug() << path.path() << device_type; |
||||||
|
} |
||||||
|
args.endArray(); |
||||||
|
|
||||||
|
|
||||||
|
// Add connection
|
||||||
|
Connection connection; |
||||||
|
connection["connection"]["type"] = "802-11-wireless"; |
||||||
|
connection["connection"]["uuid"] = QUuid::createUuid().toString().remove('{').remove('}'); |
||||||
|
connection["connection"]["id"] = "Connection 1"; |
||||||
|
|
||||||
|
connection["802-11-wireless"]["ssid"] = QByteArray("<ssid>"); |
||||||
|
connection["802-11-wireless"]["mode"] = "infrastructure"; |
||||||
|
|
||||||
|
connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk"; |
||||||
|
connection["802-11-wireless-security"]["auth-alg"] = "open"; |
||||||
|
connection["802-11-wireless-security"]["psk"] = "<password>"; |
||||||
|
|
||||||
|
connection["ipv4"]["method"] = "auto"; |
||||||
|
connection["ipv6"]["method"] = "ignore"; |
||||||
|
|
||||||
|
|
||||||
|
QDBusInterface nm_settings(nm_service, nm_settings_path, nm_settings_iface, bus); |
||||||
|
QDBusReply<QDBusObjectPath> result = nm_settings.call("AddConnection", QVariant::fromValue(connection)); |
||||||
|
if (!result.isValid()) { |
||||||
|
qDebug() << result.error().name() << result.error().message(); |
||||||
|
} else { |
||||||
|
qDebug() << result.value().path(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,143 @@ |
|||||||
|
#include <cassert> |
||||||
|
#include <iostream> |
||||||
|
#include <cmath> |
||||||
|
#include <iostream> |
||||||
|
#include <signal.h> |
||||||
|
|
||||||
|
#include <QVBoxLayout> |
||||||
|
#include <QMouseEvent> |
||||||
|
#include <QPushButton> |
||||||
|
#include <QGridLayout> |
||||||
|
|
||||||
|
#include "window.hpp" |
||||||
|
#include "settings.hpp" |
||||||
|
|
||||||
|
#include "paint.hpp" |
||||||
|
#include "sound.hpp" |
||||||
|
|
||||||
|
volatile sig_atomic_t do_exit = 0; |
||||||
|
|
||||||
|
MainWindow::MainWindow(QWidget *parent) : QWidget(parent) { |
||||||
|
main_layout = new QStackedLayout; |
||||||
|
|
||||||
|
GLWindow * glWindow = new GLWindow(this); |
||||||
|
main_layout->addWidget(glWindow); |
||||||
|
|
||||||
|
SettingsWindow * settingsWindow = new SettingsWindow(this); |
||||||
|
main_layout->addWidget(settingsWindow); |
||||||
|
|
||||||
|
|
||||||
|
main_layout->setMargin(0); |
||||||
|
setLayout(main_layout); |
||||||
|
QObject::connect(glWindow, SIGNAL(openSettings()), this, SLOT(openSettings())); |
||||||
|
QObject::connect(settingsWindow, SIGNAL(closeSettings()), this, SLOT(closeSettings())); |
||||||
|
|
||||||
|
setStyleSheet(R"( |
||||||
|
* { |
||||||
|
color: white; |
||||||
|
background-color: #072339; |
||||||
|
} |
||||||
|
)"); |
||||||
|
} |
||||||
|
|
||||||
|
void MainWindow::openSettings(){ |
||||||
|
main_layout->setCurrentIndex(1); |
||||||
|
} |
||||||
|
|
||||||
|
void MainWindow::closeSettings(){ |
||||||
|
main_layout->setCurrentIndex(0); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GLWindow::GLWindow(QWidget *parent) : QOpenGLWidget(parent) { |
||||||
|
timer = new QTimer(this); |
||||||
|
QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timerUpdate())); |
||||||
|
} |
||||||
|
|
||||||
|
GLWindow::~GLWindow() { |
||||||
|
makeCurrent(); |
||||||
|
doneCurrent(); |
||||||
|
} |
||||||
|
|
||||||
|
void GLWindow::initializeGL() { |
||||||
|
initializeOpenGLFunctions(); |
||||||
|
|
||||||
|
ui_state = new UIState(); |
||||||
|
ui_init(ui_state); |
||||||
|
ui_state->fb_w = vwp_w; |
||||||
|
ui_state->fb_h = vwp_h; |
||||||
|
|
||||||
|
int err = pthread_create(&connect_thread_handle, NULL, |
||||||
|
vision_connect_thread, ui_state); |
||||||
|
assert(err == 0); |
||||||
|
|
||||||
|
timer->start(50); |
||||||
|
} |
||||||
|
|
||||||
|
void GLWindow::timerUpdate(){ |
||||||
|
pthread_mutex_lock(&ui_state->lock); |
||||||
|
|
||||||
|
ui_update_sizes(ui_state); |
||||||
|
|
||||||
|
check_messages(ui_state); |
||||||
|
if (ui_state->vision_connected){ |
||||||
|
ui_update(ui_state); |
||||||
|
} |
||||||
|
pthread_mutex_unlock(&ui_state->lock); |
||||||
|
|
||||||
|
update(); |
||||||
|
} |
||||||
|
|
||||||
|
void GLWindow::resizeGL(int w, int h) { |
||||||
|
std::cout << "resize " << w << "x" << h << std::endl; |
||||||
|
} |
||||||
|
|
||||||
|
void GLWindow::paintGL() { |
||||||
|
pthread_mutex_lock(&ui_state->lock); |
||||||
|
ui_draw(ui_state); |
||||||
|
pthread_mutex_unlock(&ui_state->lock); |
||||||
|
} |
||||||
|
|
||||||
|
void GLWindow::mousePressEvent(QMouseEvent *e) { |
||||||
|
// Settings button click
|
||||||
|
if (!ui_state->scene.uilayout_sidebarcollapsed && e->x() <= sbr_w) { |
||||||
|
if (e->x() >= settings_btn_x && e->x() < (settings_btn_x + settings_btn_w) |
||||||
|
&& e->y() >= settings_btn_y && e->y() < (settings_btn_y + settings_btn_h)) { |
||||||
|
emit openSettings(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Vision click
|
||||||
|
if (ui_state->started && (e->x() >= ui_state->scene.ui_viz_rx - bdr_s)){ |
||||||
|
ui_state->scene.uilayout_sidebarcollapsed = !ui_state->scene.uilayout_sidebarcollapsed; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* HACKS */ |
||||||
|
bool Sound::init(int volume) { return true; } |
||||||
|
bool Sound::play(AudibleAlert alert) { printf("play sound: %d\n", (int)alert); return true; } |
||||||
|
void Sound::stop() {} |
||||||
|
void Sound::setVolume(int volume) {} |
||||||
|
Sound::~Sound() {} |
||||||
|
|
||||||
|
GLuint visionimg_to_gl(const VisionImg *img, EGLImageKHR *pkhr, void **pph) { |
||||||
|
unsigned int texture; |
||||||
|
glGenTextures(1, &texture); |
||||||
|
glBindTexture(GL_TEXTURE_2D, texture); |
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img->width, img->height, 0, GL_RGB, GL_UNSIGNED_BYTE, *pph); |
||||||
|
glGenerateMipmap(GL_TEXTURE_2D); |
||||||
|
*pkhr = (EGLImageKHR)1; // not NULL
|
||||||
|
return texture; |
||||||
|
} |
||||||
|
|
||||||
|
void visionimg_destroy_gl(EGLImageKHR khr, void *ph) { |
||||||
|
// empty
|
||||||
|
} |
||||||
|
|
||||||
|
FramebufferState* framebuffer_init(const char* name, int32_t layer, int alpha, |
||||||
|
int *out_w, int *out_h) { |
||||||
|
return (FramebufferState*)1; // not null
|
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <QWidget> |
||||||
|
#include <QTimer> |
||||||
|
#include <QGuiApplication> |
||||||
|
#include <QOpenGLWidget> |
||||||
|
#include <QOpenGLFunctions> |
||||||
|
#include <QStackedLayout> |
||||||
|
|
||||||
|
#include "ui/ui.hpp" |
||||||
|
|
||||||
|
class MainWindow : public QWidget |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
explicit MainWindow(QWidget *parent = 0); |
||||||
|
|
||||||
|
private: |
||||||
|
QStackedLayout *main_layout; |
||||||
|
|
||||||
|
public slots: |
||||||
|
void openSettings(); |
||||||
|
void closeSettings(); |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
class GLWindow : public QOpenGLWidget, protected QOpenGLFunctions |
||||||
|
{ |
||||||
|
Q_OBJECT |
||||||
|
|
||||||
|
public: |
||||||
|
using QOpenGLWidget::QOpenGLWidget; |
||||||
|
explicit GLWindow(QWidget *parent = 0); |
||||||
|
~GLWindow(); |
||||||
|
|
||||||
|
protected: |
||||||
|
void mousePressEvent(QMouseEvent *e) override; |
||||||
|
void initializeGL() override; |
||||||
|
void resizeGL(int w, int h) override; |
||||||
|
void paintGL() override; |
||||||
|
|
||||||
|
|
||||||
|
private: |
||||||
|
QTimer * timer; |
||||||
|
UIState * ui_state; |
||||||
|
pthread_t connect_thread_handle; |
||||||
|
|
||||||
|
public slots: |
||||||
|
void timerUpdate(); |
||||||
|
|
||||||
|
signals: |
||||||
|
void openSettings(); |
||||||
|
}; |
@ -0,0 +1,4 @@ |
|||||||
|
#pragma once |
||||||
|
#include "ui.hpp" |
||||||
|
|
||||||
|
void ui_draw_sidebar(UIState *s); |
Loading…
Reference in new issue