Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
PeterJohnson committed Nov 16, 2024
1 parent 30abff4 commit 17526e4
Show file tree
Hide file tree
Showing 5 changed files with 423 additions and 96 deletions.
95 changes: 0 additions & 95 deletions glass/src/libcs/native/cpp/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,98 +452,3 @@ void CameraView::Display() {
}

void CameraView::Hidden() {}

void glass::DisplayCameraModelTable(Storage& root, int kinds) {
if (!ImGui::BeginTable("cameras", 7,
ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV |
ImGuiTableFlags_SizingFixedFit)) {
return;
}

ImGui::TableSetupColumn("Id");
ImGui::TableSetupColumn("Mode");
ImGui::TableSetupColumn("Enabled");
ImGui::TableSetupColumn("Active");
ImGui::TableSetupColumn("FPS", ImGuiTableColumnFlags_WidthFixed,
ImGui::GetFontSize() * 5);
ImGui::TableSetupColumn("Data Rate", ImGuiTableColumnFlags_WidthFixed,
ImGui::GetFontSize() * 5);
ImGui::TableSetupColumn("Actions");
ImGui::TableHeadersRow();

std::string toDelete;
for (auto&& kv : root.GetChildren()) {
CameraModel* model = kv.value().GetData<CameraModel>();
if (!model) {
continue;
}
if ((model->GetKind() & kinds) == 0) {
continue;
}

ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Selectable(model->GetId().c_str());
if (ImGui::BeginDragDropSource()) {
ImGui::SetDragDropPayload("Camera", model->GetId().data(),
model->GetId().size());
ImGui::Text("Camera: %s", model->GetId().c_str());
ImGui::EndDragDropSource();
}

ImGui::TableNextColumn();
char buf[64];
VideoModeToString(buf, sizeof(buf), model->GetVideoMode());
ImGui::TextUnformatted(buf);
ImGui::SameLine();
if (ImGui::SmallButton(">")) {
ImGui::OpenPopup("mode");
}
if (ImGui::BeginPopup("mode")) {
if (EditMode(model)) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}

ImGui::TableNextColumn();
ImGui::TextUnformatted(model->Exists() ? "Yes" : "No");

ImGui::TableNextColumn();
ImGui::TextUnformatted(model->GetSource().IsEnabled() ? "Yes" : "No");

ImGui::TableNextColumn();
ImGui::Text("%2.1f FPS", model->GetActualFPS());

ImGui::TableNextColumn();
wpi::format_to_n_c_str(buf, sizeof(buf), "{:.1f} Mbps",
model->GetActualDataRate() * 8 / 1000000);
ImGui::TextUnformatted(buf);

ImGui::TableNextColumn();
if (ImGui::SmallButton(model->GetSource().IsEnabled() ? "Stop" : "Start")) {
if (model->Exists()) {
model->Stop();
} else {
model->Start();
}
}
ImGui::SameLine();
if (ImGui::SmallButton("Delete")) {
toDelete = kv.key();
}
ImGui::SameLine();
if (ImGui::SmallButton("Properties")) {
ImGui::OpenPopup("properties");
}
if (ImGui::BeginPopup("properties")) {
EditProperties(model->GetSource());
ImGui::EndPopup();
}
}
if (!toDelete.empty()) {
root.Erase(toDelete);
}

ImGui::EndTable();
}
192 changes: 191 additions & 1 deletion glass/src/libcs/native/cpp/CameraProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,109 @@

#include "glass/camera/CameraProvider.h"

#include <wpi/SmallVector.h>
#include <wpi/StringExtras.h>

#include "glass/Storage.h"

using namespace glass;


static void DisplayCameraModelTable(Storage& root, int kinds) {
if (!ImGui::BeginTable("cameras", 4,
ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV |
ImGuiTableFlags_SizingFixedFit)) {
return;
}

ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("FPS", ImGuiTableColumnFlags_WidthFixed,
ImGui::GetFontSize() * 5);
ImGui::TableSetupColumn("Data Rate", ImGuiTableColumnFlags_WidthFixed,
ImGui::GetFontSize() * 5);
ImGui::TableSetupColumn("Actions");
ImGui::TableHeadersRow();

std::string toDelete;
for (auto&& kv : root.GetChildren()) {
CameraModel* model = kv.value().GetData<CameraModel>();

Check failure on line 32 in glass/src/libcs/native/cpp/CameraProvider.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'CameraModel': undeclared identifier

Check failure on line 32 in glass/src/libcs/native/cpp/CameraProvider.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'model': undeclared identifier

Check failure on line 32 in glass/src/libcs/native/cpp/CameraProvider.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'CameraModel': undeclared identifier

Check failure on line 32 in glass/src/libcs/native/cpp/CameraProvider.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'glass::Storage::GetData': no matching overloaded function found
if (!model) {

Check failure on line 33 in glass/src/libcs/native/cpp/CameraProvider.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'model': undeclared identifier
continue;
}
if ((model->GetKind() & kinds) == 0) {

Check failure on line 36 in glass/src/libcs/native/cpp/CameraProvider.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'model': undeclared identifier
continue;
}

ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Selectable(model->GetId().c_str());

Check failure on line 42 in glass/src/libcs/native/cpp/CameraProvider.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'model': undeclared identifier
if (ImGui::BeginDragDropSource()) {
ImGui::SetDragDropPayload("Camera", model->GetId().data(),

Check failure on line 44 in glass/src/libcs/native/cpp/CameraProvider.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'model': undeclared identifier
model->GetId().size());

Check failure on line 45 in glass/src/libcs/native/cpp/CameraProvider.cpp

View workflow job for this annotation

GitHub Actions / Build - Windows

'model': undeclared identifier
ImGui::Text("Camera: %s", model->GetId().c_str());
ImGui::EndDragDropSource();
}

ImGui::TableNextColumn();
char buf[64];
VideoModeToString(buf, sizeof(buf), model->GetVideoMode());
ImGui::TextUnformatted(buf);
ImGui::SameLine();
if (ImGui::SmallButton(">")) {
ImGui::OpenPopup("mode");
}
if (ImGui::BeginPopup("mode")) {
if (EditMode(model)) {
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}

ImGui::TableNextColumn();
ImGui::TextUnformatted(model->Exists() ? "Yes" : "No");

ImGui::TableNextColumn();
ImGui::TextUnformatted(model->GetSource().IsEnabled() ? "Yes" : "No");

ImGui::TableNextColumn();
ImGui::Text("%2.1f FPS", model->GetActualFPS());

ImGui::TableNextColumn();
wpi::format_to_n_c_str(buf, sizeof(buf), "{:.1f} Mbps",
model->GetActualDataRate() * 8 / 1000000);
ImGui::TextUnformatted(buf);

ImGui::TableNextColumn();
if (ImGui::SmallButton(model->GetSource().IsEnabled() ? "Stop" : "Start")) {
if (model->Exists()) {
model->Stop();
} else {
model->Start();
}
}
ImGui::SameLine();
if (ImGui::SmallButton("Delete")) {
toDelete = kv.key();
}
ImGui::SameLine();
if (ImGui::SmallButton("Properties")) {
ImGui::OpenPopup("properties");
}
if (ImGui::BeginPopup("properties")) {
EditProperties(model->GetSource());
ImGui::EndPopup();
}
}
if (!toDelete.empty()) {
root.Erase(toDelete);
}

ImGui::EndTable();
}

void DisplayCameraList() {
if (glass::imm::BeginWindow(gCameraListWindow)) {
glass::DisplayCameraModelTable(cameras);
DisplayCameraModelTable(cameras);
if (ImGui::Button("Add USB")) {
ImGui::OpenPopup("Add USB Camera");
}
Expand Down Expand Up @@ -57,6 +153,100 @@ void DisplayCameraList() {
glass::PopStorageStack();
}
#endif

CameraProvider::CameraProvider(Storage& storage)
: CameraProvider{storage, nt::NetworkTableInstance::GetDefault()} {}

CameraProvider::CameraProvider(Storage& storage,
nt::NetworkTableInstance inst)
: WindowManager{storage}, m_inst{inst}, m_poller{inst} {
m_listener =
m_poller.AddListener({{"/CameraPublisher/"}},
nt::EventFlags::kTopic | nt::EventFlags::kValueAll);
}

void NTCameraProvider::Update() {
for (nt::Event& event : m_poller.ReadQueue()) {
if (nt::TopicInfo* topicInfo = event.GetTopicInfo()) {
wpi::SmallVector<std::string_view, 4> parts;
wpi::split(topicInfo->name, parts, '/', -1, false);
if (parts.size() < 3) {
continue;
}

// find/create NTSourceInfo by name
std::string_view sourceName = parts[1];
auto it = std::find_if(
m_sourceInfo.begin(), m_sourceInfo.end(),
[&](const auto& info) { return info->name == sourceName; });
NTSourceInfo* info;
if (it == m_sourceInfo.end()) {
info =
m_sourceInfo.emplace_back(std::make_unique<NTSourceInfo>()).get();
info->name = sourceName;
// keep sorted by name
std::sort(
m_sourceInfo.begin(), m_sourceInfo.end(),
[](const auto& a, const auto& b) { return a->name < b->name; });
} else {
info = it->get();
}

// update NTSourceInfo
std::string_view key = parts[2];
if ((event.flags & NT_EVENT_PUBLISH) != 0) {
if (key == "description" && topicInfo->type == NT_STRING) {
info->descTopic = topicInfo->topic;
m_topicMap.try_emplace(topicInfo->topic, info);
} else if (key == "connected" && topicInfo->type == NT_BOOLEAN) {
info->connTopic = topicInfo->topic;
m_topicMap.try_emplace(topicInfo->topic, info);
} else if (key == "streams" && topicInfo->type == NT_STRING_ARRAY) {
info->streamsTopic = topicInfo->topic;
m_topicMap.try_emplace(topicInfo->topic, info);
}
} else if ((event.flags & NT_EVENT_UNPUBLISH) != 0) {
if (key == "description") {
m_topicMap.erase(info->connTopic);
info->descTopic = 0;
} else if (key == "connected") {
m_topicMap.erase(info->connTopic);
info->connTopic = 0;
info->connected = false;
} else if (key == "streams") {
m_topicMap.erase(info->connTopic);
info->streamsTopic = 0;
}
}
}

if (nt::ValueEventData* valueData = event.GetValueEventData()) {
auto it = m_topicMap.find(valueData->topic);
if (it != m_topicMap.end()) {
NTSourceInfo* info = it->getSecond();
if (valueData->topic == info->descTopic &&
valueData->value.IsString()) {
info->description = valueData->value.GetString();
} else if (valueData->topic == info->connTopic &&
valueData->value.IsBoolean()) {
info->connected = valueData->value.GetBoolean();
} else if (valueData->topic == info->streamsTopic &&
valueData->value.IsStringArray()) {
info->streams.clear();
for (auto&& stream : valueData->value.GetStringArray()) {
if (wpi::starts_with(stream, "mjpg:")) {
info->streams.emplace_back(wpi::drop_front(stream, 5));
}
}
if (info->camera) {
info->camera->SetUrls(info->streams);
}
}
}
}
}
}

CameraProvider::CameraProvider(Storage& storage) : WindowManager{storage} {
storage.SetCustomApply([this] {
// loop over windows
Expand Down
Loading

0 comments on commit 17526e4

Please sign in to comment.