Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui: refactor installer using raylib #33756

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions selfdrive/ui/SConscript
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
import json
Import('qt_env', 'arch', 'common', 'messaging', 'visionipc', 'transformations')
Import('env', 'qt_env', 'arch', 'common', 'messaging', 'visionipc', 'transformations')

base_libs = [common, messaging, visionipc, transformations,
'm', 'OpenCL', 'ssl', 'crypto', 'pthread'] + qt_env["LIBS"]
Expand Down Expand Up @@ -84,8 +84,10 @@ if GetOption('extras') and arch != "Darwin":
qt_env.Program("qt/setup/updater", ["qt/setup/updater.cc", asset_obj], LIBS=qt_libs)

# build installers
senv = qt_env.Clone()
senv['LINKFLAGS'].append('-Wl,-strip-debug')
raylib_env = env.Clone()
raylib_env['LIBPATH'] += [f'#third_party/raylib/{arch}/']
raylib_frameworks = ['CoreVideo', 'Cocoa', 'GLUT', 'CoreFoundation', 'OpenGL', 'IOKit'] if arch == 'Darwin' else []
raylib_env['LINKFLAGS'].append('-Wl,-strip-debug')

release = "release3"
installers = [
Expand All @@ -95,15 +97,15 @@ if GetOption('extras') and arch != "Darwin":
("openpilot_internal", "master"),
]

cont = senv.Command(f"installer/continue_openpilot.o", f"installer/continue_openpilot.sh",
cont = raylib_env.Command(f"installer/continue_openpilot.o", f"installer/continue_openpilot.sh",
"ld -r -b binary -o $TARGET $SOURCE")
for name, branch in installers:
d = {'BRANCH': f"'\"{branch}\"'"}
if "internal" in name:
d['INTERNAL'] = "1"

obj = senv.Object(f"installer/installers/installer_{name}.o", ["installer/installer.cc"], CPPDEFINES=d)
f = senv.Program(f"installer/installers/installer_{name}", [obj, cont], LIBS=qt_libs)
obj = raylib_env.Object(f"installer/installers/installer_{name}.o", ["installer/installer.cc"], CPPDEFINES=d)
f = raylib_env.Program(f"installer/installers/installer_{name}", [obj, cont], LIBS=['raylib', common], FRAMEWORKS=raylib_frameworks)
# keep installers small
assert f[0].get_size() < 370*1e3

Expand Down
207 changes: 73 additions & 134 deletions selfdrive/ui/installer/installer.cc
Original file line number Diff line number Diff line change
@@ -1,34 +1,21 @@
#include <time.h>
#include <unistd.h>

#include <cstdlib>
#include <array>
#include <cassert>
#include <fstream>
#include <map>
#include <string>

#include <QDebug>
#include <QDir>
#include <QTimer>
#include <QVBoxLayout>
#include "common/swaglog.h"
#include "common/util.h"
#include "third_party/raylib/include/raylib.h"

#include "selfdrive/ui/installer/installer.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/qt_window.h"

std::string get_str(std::string const s) {
std::string::size_type pos = s.find('?');
assert(pos != std::string::npos);
return s.substr(0, pos);
}

// Leave some extra space for the fork installer
const std::string GIT_URL = get_str("https://github.com/commaai/openpilot.git" "? ");
const std::string BRANCH_STR = get_str(BRANCH "? ");
const std::string GIT_URL = "https://github.com/commaai/openpilot.git";
const std::string BRANCH_STR = BRANCH;

#define GIT_SSH_URL "git@github.com:commaai/openpilot.git"
#define CONTINUE_PATH "/data/continue.sh"

const QString CACHE_PATH = "/data/openpilot.cache";
const std::string CACHE_PATH = "/data/openpilot.cache";

#define INSTALL_PATH "/data/openpilot"
#define TMP_INSTALL_PATH "/data/tmppilot"
Expand All @@ -39,7 +26,6 @@ extern const uint8_t str_continue_end[] asm("_binary_selfdrive_ui_installer_cont
bool time_valid() {
time_t rawtime;
time(&rawtime);

struct tm * sys_time = gmtime(&rawtime);
return (1900 + sys_time->tm_year) >= 2020;
}
Expand All @@ -49,124 +35,68 @@ void run(const char* cmd) {
assert(err == 0);
}

Installer::Installer(QWidget *parent) : QWidget(parent) {
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(150, 290, 150, 150);
layout->setSpacing(0);

QLabel *title = new QLabel(tr("Installing..."));
title->setStyleSheet("font-size: 90px; font-weight: 600;");
layout->addWidget(title, 0, Qt::AlignTop);

layout->addSpacing(170);

bar = new QProgressBar();
bar->setRange(0, 100);
bar->setTextVisible(false);
bar->setFixedHeight(72);
layout->addWidget(bar, 0, Qt::AlignTop);

layout->addSpacing(30);

val = new QLabel("0%");
val->setStyleSheet("font-size: 70px; font-weight: 300;");
layout->addWidget(val, 0, Qt::AlignTop);

layout->addStretch();

QObject::connect(&proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &Installer::cloneFinished);
QObject::connect(&proc, &QProcess::readyReadStandardError, this, &Installer::readProgress);

QTimer::singleShot(100, this, &Installer::doInstall);

setStyleSheet(R"(
* {
font-family: Inter;
color: white;
background-color: black;
}
QProgressBar {
border: none;
background-color: #292929;
}
QProgressBar::chunk {
background-color: #364DEF;
}
)");
void renderProgress(int progress) {
BeginDrawing();
ClearBackground(BLACK);
DrawText("Installing...", 150, 290, 90, WHITE);
Rectangle bar = {150, 500, (float)GetScreenWidth() - 300, 72};
DrawRectangleRounded(bar, 0.5f, 10, GRAY);
progress = std::clamp(progress, 0, 100);
bar.width *= progress / 100.0f;
DrawRectangleRounded(bar, 0.5f, 10, RAYWHITE);
DrawText((std::to_string(progress) + "%").c_str(), 150, 600, 70, WHITE);
EndDrawing();
}

void Installer::updateProgress(int percent) {
bar->setValue(percent);
val->setText(QString("%1%").arg(percent));
update();
}

void Installer::doInstall() {
// wait for valid time
while (!time_valid()) {
usleep(500 * 1000);
qDebug() << "Waiting for valid time";
}

// cleanup previous install attempts
run("rm -rf " TMP_INSTALL_PATH " " INSTALL_PATH);
int executeGitCommand(const std::string &cmd) {
static const std::array stages = {
std::pair{"Receiving objects: ", 91},
std::pair{"Resolving deltas: ", 2},
std::pair{"Updating files: ", 7},
};

// do the install
if (QDir(CACHE_PATH).exists()) {
cachedFetch(CACHE_PATH);
} else {
freshClone();
FILE *pipe = popen(cmd.c_str(), "r");
if (!pipe) return -1;

char buffer[512];
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
std::string line(buffer);
int base = 0;
for (const auto &[text, weight] : stages) {
if (line.find(text) != std::string::npos) {
size_t percentPos = line.find('%');
if (percentPos != std::string::npos && percentPos >= 3) {
int percent = std::stoi(line.substr(percentPos - 3, 3));
int progress = base + (percent / 100.0f) * weight;
renderProgress(progress);
}
break;
}
base += weight;
}
}
return pclose(pipe);
}

void Installer::freshClone() {
qDebug() << "Doing fresh clone";
proc.start("git", {"clone", "--progress", GIT_URL.c_str(), "-b", BRANCH_STR.c_str(),
"--depth=1", "--recurse-submodules", TMP_INSTALL_PATH});
}

void Installer::cachedFetch(const QString &cache) {
qDebug() << "Fetching with cache: " << cache;

run(QString("cp -rp %1 %2").arg(cache, TMP_INSTALL_PATH).toStdString().c_str());
int err = chdir(TMP_INSTALL_PATH);
assert(err == 0);
run(("git remote set-branches --add origin " + BRANCH_STR).c_str());

updateProgress(10);

proc.setWorkingDirectory(TMP_INSTALL_PATH);
proc.start("git", {"fetch", "--progress", "origin", BRANCH_STR.c_str()});
int freshClone() {
LOGD("Doing fresh clone");
// Create the git command with redirection of stderr to stdout (2>&1)
std::string cmd = util::string_format("git clone --progress %s -b %s --depth=1 --recurse-submodules %s 2>&1",
GIT_URL.c_str(), BRANCH_STR.c_str(), TMP_INSTALL_PATH);
return executeGitCommand(cmd);
}

void Installer::readProgress() {
const QVector<QPair<QString, int>> stages = {
// prefix, weight in percentage
{"Receiving objects: ", 91},
{"Resolving deltas: ", 2},
{"Updating files: ", 7},
};

auto line = QString(proc.readAllStandardError());

int base = 0;
for (const QPair kv : stages) {
if (line.startsWith(kv.first)) {
auto perc = line.split(kv.first)[1].split("%")[0];
int p = base + int(perc.toFloat() / 100. * kv.second);
updateProgress(p);
break;
}
base += kv.second;
}
int cachedFetch(const std::string &cache) {
LOGD("Fetching with cache: %s", cache.c_str());
run(util::string_format("cp -rp %s %s", cache.c_str(), TMP_INSTALL_PATH).c_str());
run((util::string_format("cd %s && git remote set-branches --add origin %s", TMP_INSTALL_PATH, BRANCH_STR.c_str()).c_str()));
return executeGitCommand(util::string_format("cd %s && git fetch --progress origin %s 2>&1", TMP_INSTALL_PATH, BRANCH_STR.c_str()));
}

void Installer::cloneFinished(int exitCode, QProcess::ExitStatus exitStatus) {
qDebug() << "git finished with " << exitCode;
void cloneFinished(int exitCode) {
LOGD("git finished with %d", exitCode);
assert(exitCode == 0);

updateProgress(100);

// ensure correct branch is checked out
int err = chdir(TMP_INSTALL_PATH);
assert(err == 0);
Expand Down Expand Up @@ -211,13 +141,22 @@ void Installer::cloneFinished(int exitCode, QProcess::ExitStatus exitStatus) {
run("mv /data/continue.sh.new " CONTINUE_PATH);

// wait for the installed software's UI to take over
QTimer::singleShot(60 * 1000, &QCoreApplication::quit);
util::sleep_for(60 * 1000);
}

int main(int argc, char *argv[]) {
initApp(argc, argv);
QApplication a(argc, argv);
Installer installer;
setMainWindow(&installer);
return a.exec();
InitWindow(0, 0, "Installer");

renderProgress(0);
while (!time_valid()) {
util::sleep_for(1000);
}

run("rm -rf " TMP_INSTALL_PATH " " INSTALL_PATH); // cleanup previous install attempts
int result = util::file_exists(CACHE_PATH) ? cachedFetch(CACHE_PATH) : freshClone();
cloneFinished(result);
renderProgress(100);

CloseWindow();
return 0;
}
28 changes: 0 additions & 28 deletions selfdrive/ui/installer/installer.h

This file was deleted.

2 changes: 1 addition & 1 deletion selfdrive/ui/translations/main_ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@
<name>Installer</name>
<message>
<source>Installing...</source>
<translation>جارٍ التثبيت...</translation>
<translation type="vanished">جارٍ التثبيت...</translation>
</message>
</context>
<context>
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/ui/translations/main_de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@
<name>Installer</name>
<message>
<source>Installing...</source>
<translation>Installiere...</translation>
<translation type="vanished">Installiere...</translation>
</message>
</context>
<context>
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/ui/translations/main_es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@
<name>Installer</name>
<message>
<source>Installing...</source>
<translation>Instalando...</translation>
<translation type="vanished">Instalando...</translation>
</message>
</context>
<context>
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/ui/translations/main_fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@
<name>Installer</name>
<message>
<source>Installing...</source>
<translation>Installation...</translation>
<translation type="vanished">Installation...</translation>
</message>
</context>
<context>
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/ui/translations/main_ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@
<name>Installer</name>
<message>
<source>Installing...</source>
<translation>インストールしています...</translation>
<translation type="vanished">インストールしています...</translation>
</message>
</context>
<context>
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/ui/translations/main_ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@
<name>Installer</name>
<message>
<source>Installing...</source>
<translation>설치 중...</translation>
<translation type="vanished">설치 중...</translation>
</message>
</context>
<context>
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/ui/translations/main_pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@
<name>Installer</name>
<message>
<source>Installing...</source>
<translation>Instalando...</translation>
<translation type="vanished">Instalando...</translation>
</message>
</context>
<context>
Expand Down
2 changes: 1 addition & 1 deletion selfdrive/ui/translations/main_th.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@
<name>Installer</name>
<message>
<source>Installing...</source>
<translation>กำลังติดตั้ง...</translation>
<translation type="vanished">กำลังติดตั้ง...</translation>
</message>
</context>
<context>
Expand Down
Loading
Loading