Skip to content

Commit 371f604

Browse files
authored
replay: refactor ConsoleUI to remove Qt dependency (commaai#33826)
Refactor ConsoleUI to remove Qt dependency
1 parent 30853a2 commit 371f604

File tree

4 files changed

+66
-70
lines changed

4 files changed

+66
-70
lines changed

tools/replay/consoleui.cc

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <QApplication>
99

10+
#include "common/ratekeeper.h"
1011
#include "common/util.h"
1112
#include "common/version.h"
1213

@@ -57,7 +58,7 @@ void add_str(WINDOW *w, const char *str, Color color = Color::Default, bool bold
5758

5859
} // namespace
5960

60-
ConsoleUI::ConsoleUI(Replay *replay, QObject *parent) : replay(replay), sm({"carState", "liveParameters"}), QObject(parent) {
61+
ConsoleUI::ConsoleUI(Replay *replay) : replay(replay), sm({"carState", "liveParameters"}) {
6162
// Initialize curses
6263
initscr();
6364
clear();
@@ -80,24 +81,16 @@ ConsoleUI::ConsoleUI(Replay *replay, QObject *parent) : replay(replay), sm({"car
8081

8182
initWindows();
8283

83-
qRegisterMetaType<uint64_t>("uint64_t");
84-
qRegisterMetaType<ReplyMsgType>("ReplyMsgType");
8584
installMessageHandler([this](ReplyMsgType type, const std::string msg) {
86-
emit logMessageSignal(type, QString::fromStdString(msg));
85+
std::scoped_lock lock(mutex);
86+
logs.emplace_back(type, msg);
8787
});
8888
installDownloadProgressHandler([this](uint64_t cur, uint64_t total, bool success) {
89-
emit updateProgressBarSignal(cur, total, success);
89+
std::scoped_lock lock(mutex);
90+
progress_cur = cur;
91+
progress_total = total;
92+
download_success = success;
9093
});
91-
92-
QObject::connect(replay, &Replay::streamStarted, this, &ConsoleUI::updateSummary);
93-
QObject::connect(&notifier, SIGNAL(activated(int)), SLOT(readyRead()));
94-
QObject::connect(this, &ConsoleUI::updateProgressBarSignal, this, &ConsoleUI::updateProgressBar);
95-
QObject::connect(this, &ConsoleUI::logMessageSignal, this, &ConsoleUI::logMessage);
96-
97-
sm_timer.callOnTimeout(this, &ConsoleUI::updateStatus);
98-
sm_timer.start(100);
99-
getch_timer.start(1000, this);
100-
readyRead();
10194
}
10295

10396
ConsoleUI::~ConsoleUI() {
@@ -136,9 +129,7 @@ void ConsoleUI::initWindows() {
136129
}
137130
}
138131

139-
void ConsoleUI::timerEvent(QTimerEvent *ev) {
140-
if (ev->timerId() != getch_timer.timerId()) return;
141-
132+
void ConsoleUI::updateSize() {
142133
if (is_term_resized(max_height, max_width)) {
143134
for (auto win : w) {
144135
if (win) delwin(win);
@@ -149,7 +140,6 @@ void ConsoleUI::timerEvent(QTimerEvent *ev) {
149140
initWindows();
150141
rWarning("resize term %dx%d", max_height, max_width);
151142
}
152-
updateTimeline();
153143
}
154144

155145
void ConsoleUI::updateStatus() {
@@ -169,12 +159,6 @@ void ConsoleUI::updateStatus() {
169159

170160
sm.update(0);
171161

172-
if (status != Status::Paused) {
173-
auto events = replay->events();
174-
uint64_t current_mono_time = replay->routeStartNanos() + replay->currentSeconds() * 1e9;
175-
bool playing = !events->empty() && events->back().mono_time > current_mono_time;
176-
status = playing ? Status::Playing : Status::Waiting;
177-
}
178162
auto [status_str, status_color] = status_text[status];
179163
write_item(0, 0, "STATUS: ", status_str, " ", false, status_color);
180164
std::string current_segment = " - " + std::to_string((int)(replay->currentSeconds() / 60));
@@ -218,7 +202,7 @@ void ConsoleUI::displayTimelineDesc() {
218202
}
219203
}
220204

221-
void ConsoleUI::logMessage(ReplyMsgType type, const QString &msg) {
205+
void ConsoleUI::logMessage(ReplyMsgType type, const std::string &msg) {
222206
if (auto win = w[Win::Log]) {
223207
Color color = Color::Default;
224208
if (type == ReplyMsgType::Debug) {
@@ -228,19 +212,19 @@ void ConsoleUI::logMessage(ReplyMsgType type, const QString &msg) {
228212
} else if (type == ReplyMsgType::Critical) {
229213
color = Color::Red;
230214
}
231-
add_str(win, qPrintable(msg + "\n"), color);
215+
add_str(win, (msg + "\n").c_str(), color);
232216
wrefresh(win);
233217
}
234218
}
235219

236-
void ConsoleUI::updateProgressBar(uint64_t cur, uint64_t total, bool success) {
220+
void ConsoleUI::updateProgressBar() {
237221
werase(w[Win::DownloadBar]);
238-
if (success && cur < total) {
222+
if (download_success && progress_cur < progress_total) {
239223
const int width = 35;
240-
const float progress = cur / (double)total;
224+
const float progress = progress_cur / (double)progress_total;
241225
const int pos = width * progress;
242226
wprintw(w[Win::DownloadBar], "Downloading [%s>%s] %d%% %s", std::string(pos, '=').c_str(),
243-
std::string(width - pos, ' ').c_str(), int(progress * 100.0), formattedDataSize(total).c_str());
227+
std::string(width - pos, ' ').c_str(), int(progress * 100.0), formattedDataSize(progress_total).c_str());
244228
}
245229
wrefresh(w[Win::DownloadBar]);
246230
}
@@ -288,24 +272,16 @@ void ConsoleUI::updateTimeline() {
288272
wrefresh(win);
289273
}
290274

291-
void ConsoleUI::readyRead() {
292-
int c;
293-
while ((c = getch()) != ERR) {
294-
handleKey(c);
295-
}
296-
}
297-
298275
void ConsoleUI::pauseReplay(bool pause) {
299276
replay->pause(pause);
300-
status = pause ? Status::Paused : Status::Waiting;
277+
status = pause ? Status::Paused : Status::Playing;
301278
}
302279

303280
void ConsoleUI::handleKey(char c) {
304281
if (c == '\n') {
305282
// pause the replay and blocking getchar()
306283
pauseReplay(true);
307284
updateStatus();
308-
getch_timer.stop();
309285
curs_set(true);
310286
nodelay(stdscr, false);
311287

@@ -330,7 +306,6 @@ void ConsoleUI::handleKey(char c) {
330306
nodelay(stdscr, true);
331307
curs_set(false);
332308
refresh();
333-
getch_timer.start(1000, this);
334309

335310
} else if (c == '+' || c == '=') {
336311
auto it = std::upper_bound(speed_array.begin(), speed_array.end(), replay->getSpeed());
@@ -367,7 +342,37 @@ void ConsoleUI::handleKey(char c) {
367342
replay->seekTo(-10, true);
368343
} else if (c == ' ') {
369344
pauseReplay(!replay->isPaused());
370-
} else if (c == 'q' || c == 'Q') {
371-
qApp->exit();
372345
}
373346
}
347+
348+
int ConsoleUI::exec() {
349+
RateKeeper rk("Replay", 20);
350+
while (true) {
351+
int c = getch();
352+
if (c == 'q' || c == 'Q') {
353+
break;
354+
}
355+
handleKey(c);
356+
357+
if (rk.frame() % 25) {
358+
updateSize();
359+
updateSummary();
360+
}
361+
362+
updateTimeline();
363+
updateStatus();
364+
365+
{
366+
std::scoped_lock lock(mutex);
367+
updateProgressBar();
368+
for (auto &[type, msg] : logs) {
369+
logMessage(type, msg);
370+
}
371+
logs.clear();
372+
}
373+
374+
qApp->processEvents();
375+
rk.keepTime();
376+
}
377+
return 0;
378+
}

tools/replay/consoleui.h

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
#pragma once
22

33
#include <array>
4-
#include <QBasicTimer>
5-
#include <QObject>
6-
#include <QSocketNotifier>
7-
#include <QTimer>
8-
#include <QTimerEvent>
4+
#include <mutex>
5+
#include <vector>
96

107
#include "tools/replay/replay.h"
118
#include <ncurses.h>
129

13-
class ConsoleUI : public QObject {
14-
Q_OBJECT
15-
10+
class ConsoleUI {
1611
public:
17-
ConsoleUI(Replay *replay, QObject *parent = 0);
12+
ConsoleUI(Replay *replay);
1813
~ConsoleUI();
14+
int exec();
1915
inline static const std::array speed_array = {0.2f, 0.5f, 1.0f, 2.0f, 3.0f};
2016

2117
private:
@@ -27,25 +23,21 @@ class ConsoleUI : public QObject {
2723
void updateSummary();
2824
void updateStatus();
2925
void pauseReplay(bool pause);
26+
void updateSize();
27+
void updateProgressBar();
28+
void logMessage(ReplyMsgType type, const std::string &msg);
3029

31-
enum Status { Waiting, Playing, Paused };
30+
enum Status { Playing, Paused };
3231
enum Win { Title, Stats, Log, LogBorder, DownloadBar, Timeline, TimelineDesc, Help, CarState, Max};
3332
std::array<WINDOW*, Win::Max> w{};
3433
SubMaster sm;
3534
Replay *replay;
36-
QBasicTimer getch_timer;
37-
QTimer sm_timer;
38-
QSocketNotifier notifier{0, QSocketNotifier::Read, this};
3935
int max_width, max_height;
40-
Status status = Status::Waiting;
41-
42-
signals:
43-
void updateProgressBarSignal(uint64_t cur, uint64_t total, bool success);
44-
void logMessageSignal(ReplyMsgType type, const QString &msg);
36+
Status status = Status::Playing;
4537

46-
private slots:
47-
void readyRead();
48-
void timerEvent(QTimerEvent *ev);
49-
void updateProgressBar(uint64_t cur, uint64_t total, bool success);
50-
void logMessage(ReplyMsgType type, const QString &msg);
38+
std::mutex mutex;
39+
std::vector<std::pair<ReplyMsgType, std::string>> logs;
40+
uint64_t progress_cur = 0;
41+
uint64_t progress_total = 0;
42+
bool download_success = false;
5143
};

tools/replay/main.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,5 @@ int main(int argc, char *argv[]) {
151151

152152
ConsoleUI console_ui(replay);
153153
replay->start(config.start_seconds);
154-
return app.exec();
154+
return console_ui.exec();
155155
}

tools/replay/replay.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum class FindFlag {
4343

4444
enum class TimelineType { None, Engaged, AlertInfo, AlertWarning, AlertCritical, UserFlag };
4545
typedef bool (*replayEventFilter)(const Event *, void *);
46+
typedef std::map<int, std::unique_ptr<Segment>> SegmentMap;
4647
Q_DECLARE_METATYPE(std::shared_ptr<LogReader>);
4748

4849
class Replay : public QObject {
@@ -82,8 +83,7 @@ class Replay : public QObject {
8283
inline double maxSeconds() const { return max_seconds_; }
8384
inline void setSpeed(float speed) { speed_ = speed; }
8485
inline float getSpeed() const { return speed_; }
85-
inline const std::vector<Event> *events() const { return &events_; }
86-
inline const std::map<int, std::unique_ptr<Segment>> &segments() const { return segments_; }
86+
inline const SegmentMap &segments() const { return segments_; }
8787
inline const std::string &carFingerprint() const { return car_fingerprint_; }
8888
inline const std::vector<std::tuple<double, double, TimelineType>> getTimeline() {
8989
std::lock_guard lk(timeline_lock);
@@ -102,7 +102,6 @@ protected slots:
102102
void segmentLoadFinished(bool success);
103103

104104
protected:
105-
typedef std::map<int, std::unique_ptr<Segment>> SegmentMap;
106105
std::optional<uint64_t> find(FindFlag flag);
107106
void pauseStreamThread();
108107
void startStream(const Segment *cur_segment);

0 commit comments

Comments
 (0)