From ed4e5834e75fb535449f6ca4b33f527ac99450ac Mon Sep 17 00:00:00 2001 From: Andrew Zonenberg Date: Wed, 31 Jan 2024 16:09:25 -0800 Subject: [PATCH] Initial support for integrating markers into ProtocolAnalyzerDialog. Doesn't refresh if a marker is changed. --- lib | 2 +- src/ngscopeclient/PacketManager.cpp | 30 +++++- src/ngscopeclient/PacketManager.h | 22 +++- src/ngscopeclient/ProtocolAnalyzerDialog.cpp | 104 ++++++++++++++----- src/ngscopeclient/Session.cpp | 2 +- 5 files changed, 128 insertions(+), 32 deletions(-) diff --git a/lib b/lib index 495cad3d6..48440540d 160000 --- a/lib +++ b/lib @@ -1 +1 @@ -Subproject commit 495cad3d68a521aae1f1b5f1e83d00dd5f64e435 +Subproject commit 48440540d0f682f672440214bb3e3e7abbc2fdd1 diff --git a/src/ngscopeclient/PacketManager.cpp b/src/ngscopeclient/PacketManager.cpp index ca760dee1..b3c7f979b 100644 --- a/src/ngscopeclient/PacketManager.cpp +++ b/src/ngscopeclient/PacketManager.cpp @@ -34,14 +34,16 @@ */ #include "ngscopeclient.h" #include "PacketManager.h" +#include "Session.h" using namespace std; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Construction / destruction -PacketManager::PacketManager(PacketDecoder* pd) - : m_filter(pd) +PacketManager::PacketManager(PacketDecoder* pd, Session& session) + : m_session(session) + , m_filter(pd) { } @@ -78,20 +80,42 @@ void PacketManager::RefreshRows() times.push_back(it.first); std::sort(times.begin(), times.end()); - //Process packets from each waveform double totalHeight = 0; double lineheight = ImGui::CalcTextSize("dummy text").y; double padding = ImGui::GetStyle().CellPadding.y; + + //Process packets from each waveform for(auto wavetime : times) { auto& wpackets = m_filteredPackets[wavetime]; + + //Get markers for this waveform, if any + auto& markers = m_session.GetMarkers(wavetime); + LogDebug("Refreshing: %zu markers\n", markers.size()); + size_t imarker = 0; + int64_t lastoff = 0; + for(auto pack : wpackets) { + //Add marker before this packet if needed + if( (imarker < markers.size()) && + (markers[imarker].m_offset >= lastoff) && + (markers[imarker].m_offset < pack->m_offset) ) + { + RowData row(wavetime, markers[imarker]); + row.m_height = padding*2 + lineheight; + totalHeight += row.m_height; + row.m_totalHeight = totalHeight; + m_rows.push_back(row); + imarker ++; + } + //See if we have child packets auto children = m_filteredChildPackets[pack]; //Add an entry for the top level RowData dat(wavetime, pack); + lastoff = pack->m_offset; //Calculate row height double height = padding*2 + lineheight; diff --git a/src/ngscopeclient/PacketManager.h b/src/ngscopeclient/PacketManager.h index 73562eb59..e4752fcff 100644 --- a/src/ngscopeclient/PacketManager.h +++ b/src/ngscopeclient/PacketManager.h @@ -38,6 +38,8 @@ #include "../../lib/scopehal/PacketDecoder.h" #include "Marker.h" +class Session; + /** @brief Context data for a single row (used for culling) */ @@ -49,6 +51,7 @@ class RowData , m_totalHeight(0) , m_stamp(0, 0) , m_packet(nullptr) + , m_marker(TimePoint(0,0), 0, "") {} RowData(TimePoint t, Packet* p) @@ -56,6 +59,15 @@ class RowData , m_totalHeight(0) , m_stamp(t) , m_packet(p) + , m_marker(t, 0, "") + {} + + RowData(TimePoint t, Marker m) + : m_height(0) + , m_totalHeight(0) + , m_stamp(t) + , m_packet(nullptr) + , m_marker(m) {} ///@brief Height of this row @@ -67,8 +79,11 @@ class RowData ///@brief Timestamp of the waveform this packet came from TimePoint m_stamp; - ///@brief The packet in this row + ///@brief The packet in this row (null if m_marker is valid) Packet* m_packet; + + ///@brief The marker in this row (ignored if m_packet is valid) + Marker m_marker; }; class ProtocolDisplayFilter; @@ -133,7 +148,7 @@ class ProtocolDisplayFilter class PacketManager { public: - PacketManager(PacketDecoder* pd); + PacketManager(PacketDecoder* pd, Session& session); virtual ~PacketManager(); void Update(); @@ -177,6 +192,9 @@ class PacketManager protected: void RemoveChildHistoryFrom(Packet* pack); + ///@brief Parent session object + Session& m_session; + ///@brief Mutex controlling access to m_packets std::recursive_mutex m_mutex; diff --git a/src/ngscopeclient/ProtocolAnalyzerDialog.cpp b/src/ngscopeclient/ProtocolAnalyzerDialog.cpp index e1dd1bd9b..c50784dc0 100644 --- a/src/ngscopeclient/ProtocolAnalyzerDialog.cpp +++ b/src/ngscopeclient/ProtocolAnalyzerDialog.cpp @@ -115,6 +115,7 @@ bool ProtocolAnalyzerDialog::DoRender() //TODO: integrate length natively vs having to make the filter calculate it?? auto dataFont = m_parent.GetFontPref("Appearance.Protocol Analyzer.data_font"); + auto& prefs = m_parent.GetSession().GetPreferences(); //Figure out color for filter expression ImU32 bgcolor; @@ -200,23 +201,44 @@ bool ProtocolAnalyzerDialog::DoRender() ImGui::PushID(row.m_stamp.first); ImGui::PushID(row.m_stamp.second); - //Make sure we have the packed colors cached + //Is it a packet? auto pack = row.m_packet; - pack->RefreshColors(); + + //Make sure we have the packed colors cached + if(pack) + pack->RefreshColors(); //Instead of using packet pointer as identifier (can change if filter graph re-runs for //unrelated reasons), use timestamp instead. - ImGui::PushID(pack->m_offset); + if(pack) + ImGui::PushID(pack->m_offset); + else + { + ImGui::PushID(row.m_marker.m_offset); + ImGui::PushID("Marker"); + } ImGui::TableNextRow(ImGuiTableRowFlags_None); //Set up colors for the packet - ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, pack->m_displayBackgroundColorPacked); - ImGui::PushStyleColor(ImGuiCol_Text, pack->m_displayForegroundColorPacked); + if(pack) + { + ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, pack->m_displayBackgroundColorPacked); + ImGui::PushStyleColor(ImGuiCol_Text, pack->m_displayForegroundColorPacked); + } + else + { + ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, prefs.GetColor("Appearance.Graphs.bottom_color")); + ImGui::PushStyleColor(ImGuiCol_Text, prefs.GetColor("Appearance.Cursors.marker_color")); + } //See if we have child packets - auto children = m_mgr->GetFilteredChildPackets(pack); - bool hasChildren = !children.empty(); + bool hasChildren = false; + if(pack) + { + auto children = m_mgr->GetFilteredChildPackets(pack); + hasChildren = !children.empty(); + } float rowStart = rows[i].m_totalHeight - rows[i].m_height; bool firstRow = (i == istart); @@ -241,8 +263,20 @@ bool ProtocolAnalyzerDialog::DoRender() ImGui::TreePop(); ImGui::SameLine(); } - bool rowIsSelected = (m_selectedPacket == pack); - TimePoint packtime(row.m_stamp.GetSec(), row.m_stamp.GetFs() + pack->m_offset); + + //TODO allow selection of marker + int64_t offset = 0; + int64_t len = 0; + if(pack) + { + offset = pack->m_offset; + len = pack->m_len; + } + else + offset = row.m_marker.m_offset; + bool rowIsSelected = pack && (m_selectedPacket == pack); + TimePoint packtime(row.m_stamp.GetSec(), row.m_stamp.GetFs() + offset); + if(ImGui::Selectable( packtime.PrettyPrint().c_str(), rowIsSelected, @@ -258,35 +292,54 @@ bool ProtocolAnalyzerDialog::DoRender() m_waveformChanged = true; m_lastSelectedWaveform = row.m_stamp; - m_parent.NavigateToTimestamp(pack->m_offset, pack->m_len, StreamDescriptor(m_filter, 0)); - + m_parent.NavigateToTimestamp(offset, len, StreamDescriptor(m_filter, 0)); } - //Headers - for(size_t j=0; jm_headers[cols[j]].c_str()); + ImGui::TextUnformatted(pack->m_headers[cols[j]].c_str()); + } + } + + //Data column + if(m_filter->GetShowDataColumn()) + { + if(ImGui::TableSetColumnIndex(datacol)) + { + if(firstRow) + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - (ImGui::GetScrollY() - rowStart)); + + DoDataColumn(pack, dataFont, rows, i); + } } } - //Data column - if(m_filter->GetShowDataColumn()) + //Marker name + else { - if(ImGui::TableSetColumnIndex(datacol)) + //TODO: which column to use for marker text??) + if(m_filter->GetShowDataColumn()) { - if(firstRow) - ImGui::SetCursorPosY(ImGui::GetCursorPosY() - (ImGui::GetScrollY() - rowStart)); - - DoDataColumn(pack, dataFont, rows, i); + if(ImGui::TableSetColumnIndex(datacol)) + { + if(firstRow) + ImGui::SetCursorPosY(ImGui::GetCursorPosY() - (ImGui::GetScrollY() - rowStart)); + ImGui::TextUnformatted(row.m_marker.m_name.c_str()); + } } } ImGui::PopStyleColor(); + if(!pack) + ImGui::PopID(); ImGui::PopID(); ImGui::PopID(); ImGui::PopID(); @@ -302,7 +355,8 @@ bool ProtocolAnalyzerDialog::DoRender() rows.begin(), rows.end(), m_selectedPacket->m_offset, - [](const RowData& data, double f) { return f > data.m_packet->m_offset; }); + [](const RowData& data, double f) + { return f > (data.m_packet? data.m_packet->m_offset : data.m_marker.m_offset); }); auto& row = *sit; ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + row.m_totalHeight); diff --git a/src/ngscopeclient/Session.cpp b/src/ngscopeclient/Session.cpp index 5e192d56b..f62b23db0 100644 --- a/src/ngscopeclient/Session.cpp +++ b/src/ngscopeclient/Session.cpp @@ -3286,7 +3286,7 @@ shared_ptr Session::AddPacketFilter(PacketDecoder* filter) LogTrace("Adding packet manager for %s\n", filter->GetDisplayName().c_str()); lock_guard lock(m_packetMgrMutex); - shared_ptr ret = make_shared(filter); + shared_ptr ret = make_shared(filter, *this); m_packetmgrs[filter] = ret; return ret; }