- Per-process stderr logging to /data/log2/{session}/ with time-safe
directory naming (boot-xxx renamed once GPS/NTP sets clock)
- Aggregate session.log with major events (start/stop, transitions)
- 30-day log rotation cleanup on manager startup
- build_only.sh: compile without starting manager, non-blocking error
display, kills stale processes
- build.py: copies updated spinner binary after successful build
- Onroad park mode: show splash screen when car is on but in park,
switch to camera view when shifted to drive, honor screen on/off
- Spinner: full-screen boot logo background from /usr/comma/bg.jpg
with white progress bar overlay
- Boot logo: auto-regenerate when boot_logo.png changes, 140% scale
- launch_openpilot.sh: cd to /data/openpilot for reliable execution
- launch_chffrplus.sh: kill stale text error displays on startup
- spinner shell wrapper: prefer freshly built _spinner over prebuilt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
111 lines
2.8 KiB
C++
Executable File
111 lines
2.8 KiB
C++
Executable File
#include "selfdrive/ui/qt/spinner.h"
|
|
|
|
#include <algorithm>
|
|
#include <cstdio>
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
#include <QApplication>
|
|
#include <QGridLayout>
|
|
#include <QPainter>
|
|
#include <QString>
|
|
#include <QTransform>
|
|
|
|
#include "system/hardware/hw.h"
|
|
#include "selfdrive/ui/qt/qt_window.h"
|
|
#include "selfdrive/ui/qt/util.h"
|
|
|
|
// CLEARPILOT: full-screen boot logo background with progress bar overlay
|
|
|
|
Spinner::Spinner(QWidget *parent) : QWidget(parent) {
|
|
// Load boot logo as full-screen background, rotated 90° CCW
|
|
// (bg.jpg is pre-rotated 90° CW for the raw framebuffer)
|
|
QPixmap boot_logo("/usr/comma/bg.jpg");
|
|
if (!boot_logo.isNull()) {
|
|
QTransform rot;
|
|
rot.rotate(-90);
|
|
bg_img = boot_logo.transformed(rot);
|
|
}
|
|
|
|
QGridLayout *main_layout = new QGridLayout(this);
|
|
main_layout->setSpacing(0);
|
|
main_layout->setMargin(0);
|
|
|
|
// Spacer to push progress bar toward bottom
|
|
main_layout->setRowStretch(0, 1);
|
|
|
|
text = new QLabel();
|
|
text->setWordWrap(true);
|
|
text->setVisible(false);
|
|
text->setAlignment(Qt::AlignCenter);
|
|
main_layout->addWidget(text, 1, 0, Qt::AlignHCenter);
|
|
|
|
progress_bar = new QProgressBar();
|
|
progress_bar->setRange(5, 100);
|
|
progress_bar->setTextVisible(false);
|
|
progress_bar->setVisible(false);
|
|
progress_bar->setFixedHeight(20);
|
|
main_layout->addWidget(progress_bar, 2, 0, Qt::AlignHCenter | Qt::AlignBottom);
|
|
|
|
// Bottom margin for progress bar
|
|
main_layout->setContentsMargins(0, 0, 0, 80);
|
|
|
|
setStyleSheet(R"(
|
|
Spinner {
|
|
background-color: black;
|
|
}
|
|
QLabel {
|
|
color: white;
|
|
font-size: 80px;
|
|
background-color: transparent;
|
|
}
|
|
QProgressBar {
|
|
background-color: #373737;
|
|
width: 1000px;
|
|
border solid white;
|
|
border-radius: 10px;
|
|
}
|
|
QProgressBar::chunk {
|
|
border-radius: 10px;
|
|
background-color: white;
|
|
}
|
|
)");
|
|
|
|
notifier = new QSocketNotifier(fileno(stdin), QSocketNotifier::Read);
|
|
QObject::connect(notifier, &QSocketNotifier::activated, this, &Spinner::update);
|
|
}
|
|
|
|
void Spinner::paintEvent(QPaintEvent *event) {
|
|
QPainter p(this);
|
|
p.fillRect(rect(), Qt::black);
|
|
if (!bg_img.isNull()) {
|
|
QPixmap scaled = bg_img.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
|
int x = (width() - scaled.width()) / 2;
|
|
int y = (height() - scaled.height()) / 2;
|
|
p.drawPixmap(x, y, scaled);
|
|
}
|
|
}
|
|
|
|
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[]) {
|
|
initApp(argc, argv);
|
|
QApplication a(argc, argv);
|
|
Spinner spinner;
|
|
setMainWindow(&spinner);
|
|
return a.exec();
|
|
}
|