diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript index 643951fff311cb..78e9967b4e6125 100644 --- a/selfdrive/ui/SConscript +++ b/selfdrive/ui/SConscript @@ -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"] @@ -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 = [ @@ -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 diff --git a/selfdrive/ui/installer/installer.cc b/selfdrive/ui/installer/installer.cc index 17f6ba19abd08f..f3ee18cdd47d11 100644 --- a/selfdrive/ui/installer/installer.cc +++ b/selfdrive/ui/installer/installer.cc @@ -1,34 +1,21 @@ #include -#include -#include +#include +#include #include #include -#include -#include -#include -#include -#include +#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" @@ -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; } @@ -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::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> 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); @@ -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; } diff --git a/selfdrive/ui/installer/installer.h b/selfdrive/ui/installer/installer.h deleted file mode 100644 index de3af0ff395021..00000000000000 --- a/selfdrive/ui/installer/installer.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class Installer : public QWidget { - Q_OBJECT - -public: - explicit Installer(QWidget *parent = 0); - -private slots: - void updateProgress(int percent); - - void readProgress(); - void cloneFinished(int exitCode, QProcess::ExitStatus exitStatus); - -private: - QLabel *val; - QProgressBar *bar; - QProcess proc; - - void doInstall(); - void freshClone(); - void cachedFetch(const QString &cache); -}; diff --git a/selfdrive/ui/translations/main_ar.ts b/selfdrive/ui/translations/main_ar.ts index 5f254e9cd4ba51..8e9e1380fcd16f 100644 --- a/selfdrive/ui/translations/main_ar.ts +++ b/selfdrive/ui/translations/main_ar.ts @@ -311,7 +311,7 @@ Installer Installing... - جارٍ التثبيت... + جارٍ التثبيت... diff --git a/selfdrive/ui/translations/main_de.ts b/selfdrive/ui/translations/main_de.ts index 4f5997228a7724..c1ffd8fbd7d91e 100644 --- a/selfdrive/ui/translations/main_de.ts +++ b/selfdrive/ui/translations/main_de.ts @@ -307,7 +307,7 @@ Installer Installing... - Installiere... + Installiere... diff --git a/selfdrive/ui/translations/main_es.ts b/selfdrive/ui/translations/main_es.ts index fa50f33f15366a..fdc8b1c98bb992 100644 --- a/selfdrive/ui/translations/main_es.ts +++ b/selfdrive/ui/translations/main_es.ts @@ -307,7 +307,7 @@ Installer Installing... - Instalando... + Instalando... diff --git a/selfdrive/ui/translations/main_fr.ts b/selfdrive/ui/translations/main_fr.ts index 566ed32f114c86..14abf0fb3763e6 100644 --- a/selfdrive/ui/translations/main_fr.ts +++ b/selfdrive/ui/translations/main_fr.ts @@ -307,7 +307,7 @@ Installer Installing... - Installation... + Installation... diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index 90c8aba00bfbf2..2c9c08c7a21042 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -306,7 +306,7 @@ Installer Installing... - インストールしています... + インストールしています... diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index 6d01b1289f65a3..52bf7b27690aa6 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -306,7 +306,7 @@ Installer Installing... - 설치 중... + 설치 중... diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index ba50e971418168..ee0cd807b0e24c 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -307,7 +307,7 @@ Installer Installing... - Instalando... + Instalando... diff --git a/selfdrive/ui/translations/main_th.ts b/selfdrive/ui/translations/main_th.ts index 6d89c049b18a84..0be4d61c2be1fd 100644 --- a/selfdrive/ui/translations/main_th.ts +++ b/selfdrive/ui/translations/main_th.ts @@ -306,7 +306,7 @@ Installer Installing... - กำลังติดตั้ง... + กำลังติดตั้ง... diff --git a/selfdrive/ui/translations/main_tr.ts b/selfdrive/ui/translations/main_tr.ts index 663ad8c2813645..010cef56d4553a 100644 --- a/selfdrive/ui/translations/main_tr.ts +++ b/selfdrive/ui/translations/main_tr.ts @@ -306,7 +306,7 @@ Installer Installing... - Yükleniyor... + Yükleniyor... diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 494b1bc170f4c6..8d4dbbb8ca21e3 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -306,7 +306,7 @@ Installer Installing... - 正在安装…… + 正在安装…… diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index 7ce6ac6d208606..afa4e8ef51c567 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -306,7 +306,7 @@ Installer Installing... - 安裝中… + 安裝中…