From d3106c2b4b8a0f168496837eab88f95fac74cc87 Mon Sep 17 00:00:00 2001 From: Trey Moen <50057480+greatgitsby@users.noreply.github.com> Date: Sun, 13 Sep 2026 16:43:53 -0700 Subject: [PATCH] cabana: unify video and live stream titles (#38908) * cabana: unify video and live stream titles * cabana: put stream before dbc in window title * cabana: show fingerprint in route details --- openpilot/tools/cabana/ui/mainwin.cc | 13 ++++++++----- openpilot/tools/cabana/ui/mainwin.h | 2 +- openpilot/tools/cabana/ui/tools/routeinfo.cc | 6 ++++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/openpilot/tools/cabana/ui/mainwin.cc b/openpilot/tools/cabana/ui/mainwin.cc index 2e42b79242..674f2c3aa1 100644 --- a/openpilot/tools/cabana/ui/mainwin.cc +++ b/openpilot/tools/cabana/ui/mainwin.cc @@ -156,7 +156,7 @@ void MainWindow::drawMenuBar() { if (dropdown::Item("Full Screen", shortcut("F11").c_str())) toggleFullScreen(); ImGui::Separator(); dropdown::Item(messages_widget_ ? messages_widget_->title().c_str() : "MESSAGES", nullptr, &messages_visible_); - dropdown::Item(video_dock_title_.empty() ? "Video" : video_dock_title_.c_str(), nullptr, &video_visible_); + dropdown::Item(videoPanelTitle(), nullptr, &video_visible_); dropdown::Item("Charts", nullptr, &charts_visible_); ImGui::Separator(); if (dropdown::Item("Reset Window Layout")) { @@ -199,11 +199,15 @@ void MainWindow::showStatusMessage(const std::string &msg, int timeout_ms) { void MainWindow::updateWindowTitle() { std::string title; - for (auto f : dbc()->allDBCFiles()) { + for (auto f : dbc()->nonEmptyDBCFiles()) { if (!title.empty()) title += " | "; title += "(" + toString(dbc()->sources(f)) + ") " + f->name(); } if (window_modified_) title += "*"; + if (hasStream()) { + const std::string stream_title = can->liveStreaming() ? videoPanelTitle() : can->routeName(); + title = title.empty() ? stream_title : stream_title + " \xe2\x80\x94 " + title; + } if (!title.empty()) title += " \xe2\x80\x94 "; // em dash separator title += "Cabana"; glfwSetWindowTitle(window_, title.c_str()); @@ -362,12 +366,12 @@ void MainWindow::startStream(std::unique_ptr stream, const std:: MessageBox::warning("Error", msg); })); can->start(); + updateWindowTitle(); loadFile(dbc_file, SOURCE_ALL, [this]() { showStatusMessage("Stream [" + can->routeName() + "] started", 2000); createDockWidgets(); - video_dock_title_ = can->routeName(); // Don't overwrite already loaded DBC if (!dbc()->nonEmptyDBCCount()) { newFile(); @@ -391,7 +395,6 @@ void MainWindow::startStream(std::unique_ptr stream, const std:: void MainWindow::eventsMerged() { const std::string fingerprint = can->carFingerprint(); if (!can->liveStreaming() && std::exchange(car_fingerprint_, fingerprint) != fingerprint) { - video_dock_title_ = "ROUTE: " + can->routeName() + " FINGERPRINT: " + (car_fingerprint_.empty() ? "Unknown Car" : car_fingerprint_); // Don't overwrite already loaded DBC auto it = fingerprint_to_dbc_.find(car_fingerprint_); if (!dbc()->nonEmptyDBCCount() && it != fingerprint_to_dbc_.end()) { @@ -866,7 +869,7 @@ void MainWindow::drawMessagesPanel() { } void MainWindow::drawVideoPanel() { - const std::string name = (video_dock_title_.empty() ? "Video" : video_dock_title_) + VIDEO_PANEL; + const std::string name = std::string(videoPanelTitle()) + VIDEO_PANEL; setNextPanelClass(); const bool video_open = beginPanel(name.c_str(), &video_visible_); const bool floating = floatingOut(); diff --git a/openpilot/tools/cabana/ui/mainwin.h b/openpilot/tools/cabana/ui/mainwin.h index 840ca0990a..b7afa1769d 100644 --- a/openpilot/tools/cabana/ui/mainwin.h +++ b/openpilot/tools/cabana/ui/mainwin.h @@ -45,6 +45,7 @@ public: private: bool hasStream() const { return dynamic_cast(can) == nullptr; } + const char *videoPanelTitle() const { return hasStream() && can->liveStreaming() ? "Live Stream" : "Video"; } void releaseStream(); void startStream(std::unique_ptr stream, const std::string &dbc_file); void loadStartupStream(const std::string &dbc_file); @@ -101,7 +102,6 @@ private: std::vector opendbc_names_; enum { MAX_RECENT_FILES = 15 }; std::string car_fingerprint_; - std::string video_dock_title_; bool messages_visible_ = true; bool video_visible_ = true; bool charts_visible_ = true; diff --git a/openpilot/tools/cabana/ui/tools/routeinfo.cc b/openpilot/tools/cabana/ui/tools/routeinfo.cc index 1761da2a1f..92b77cf2a8 100644 --- a/openpilot/tools/cabana/ui/tools/routeinfo.cc +++ b/openpilot/tools/cabana/ui/tools/routeinfo.cc @@ -16,10 +16,12 @@ bool RouteInfoDlg::draw() { static const char *headers[] = {"", "rlog", "narrow road", "wide road", "driver", "qlog", "qcam"}; auto yn = [](const std::string &s) { return s.empty() ? "--" : "Yes"; }; const auto &segments = replay_->route().segments(); - // minimum size: header + min(rowCount, 13) rows + // minimum size: fingerprint, header, and min(rowCount, 13) rows float row_h = ImGui::GetTextLineHeightWithSpacing(); - float min_h = row_h * (std::min((int)segments.size(), 13) + 1) + ImGui::GetFrameHeightWithSpacing() + ImGui::GetStyle().WindowPadding.y * 2; + float min_h = row_h * (std::min((int)segments.size(), 13) + 2) + ImGui::GetFrameHeightWithSpacing() + ImGui::GetStyle().WindowPadding.y * 2; if (begin(ImVec2(520, min_h))) { + const std::string fingerprint = replay_->carFingerprint(); + ImGui::TextWrapped("Fingerprint: %s", fingerprint.empty() ? "Unknown" : fingerprint.c_str()); const ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_ScrollY | ImGuiTableFlags_SizingFixedFit; if (ImGui::BeginTable("table", 7, flags, ImVec2(0, 0))) { ImGui::TableSetupScrollFreeze(0, 1);