source: a synthetic probe kind, and sessions that remember their source kind

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-10-31 20:04:42 +01:00
1 parent 4ae91bd58b
commit 059b660586
9 files changed
+231 -3

No files matched your search

+15
View File
@@ -322,6 +322,10 @@ std::vector<KnownSource> known_sources() {
s.capture_packets = st.capture_packets;
s.multicast = st.multicast;
s.interface_addr = st.interface_addr;
if (!st.source_kind.empty()) {
s.kind = st.source_kind;
s.opts = st.source_opts;
}
s.rows = static_cast<int>(st.rows.size());
for (const LayoutState::Row& row : st.rows) {
for (const std::string& sig : row.signals) {
@@ -558,6 +562,11 @@ bool load_layout(const std::string& path, LayoutState& out) {
st.multicast = strip_quote(value);
} else if (key == "interface") {
st.interface_addr = strip_quote(value);
} else if (key == "source_kind") {
st.source_kind = strip_quote(value);
} else if (key.rfind("source_opt_", 0) == 0) {
const std::string k = key.substr(11);
if (SourceConfig::valid_key(k)) st.source_opts.set(k, strip_quote(value));
} else if (key == "comment") {
st.comment = strip_quote(value);
} else if (key == "buffer_mb") {
@@ -699,6 +708,12 @@ bool save_layout(const std::string& path, const LayoutState& state) {
if (!state.interface_addr.empty()) {
o << "interface = " << toml_escape(state.interface_addr) << "\n";
}
if (!state.source_kind.empty() && state.source_kind != "udps") {
o << "source_kind = " << toml_escape(state.source_kind) << "\n";
for (const auto& kv : state.source_opts.items()) {
o << "source_opt_" << kv.first << " = " << toml_escape(kv.second) << "\n";
}
}
// Top level, before any table. Emitted after the `[[calibration]]` tables it belonged to the last
// of them -- a bare key after a header is that table's key in TOML -- so the parser, correctly,
// never saw it and a session's enable state was silently lost.