23#define IMGUI_DEFINE_MATH_OPERATORS
24#include <imgui_internal.h>
38#include <imgui_internal.h>
39#include <glm/gtc/matrix_transform.hpp>
40#include <glm/gtx/euler_angles.hpp>
51 if (winsize::get().width == 0)
54 int w = 1920,
h = 1080;
58 std::vector<std::string>
const tok =
jevois::split(ws,
"\\s*[,;x]\\s*");
59 if (tok.size() == 2) { w = std::stoi(tok[0]);
h = std::stoi(tok[1]) / 2; }
60 LINFO(
"Detected framebuffer size: " << w <<
'x' <<
h);
64 winsize::set(cv::Size(w,
h));
70 std::vector<EditorItem> fixedcfg
72 {
JEVOIS_ROOT_PATH "/config/videomappings.cfg",
"JeVois videomappings.cfg", EditorSaveAction::RefreshMappings },
73 {
JEVOIS_ROOT_PATH "/config/initscript.cfg",
"JeVois initscript.cfg", EditorSaveAction::Reboot },
74 {
"params.cfg",
"Module's params.cfg", EditorSaveAction::Reload },
75 {
"script.cfg",
"Module's script.cfg", EditorSaveAction::Reload },
77 "JeVois models.yml DNN Zoo Root", EditorSaveAction::Reload },
79 "JeVois opencv.yml DNN Zoo for OpenCV models", EditorSaveAction::Reload },
81 "JeVois npu.yml DNN Zoo for A311D NPU models", EditorSaveAction::Reload },
83 "JeVois spu.yml DNN Zoo for Hailo SPU models", EditorSaveAction::Reload },
85 "JeVois tpu.yml DNN Zoo for Coral TPU models", EditorSaveAction::Reload },
87 "JeVois vpu.yml DNN Zoo for Myriad-X VPU models", EditorSaveAction::Reload },
89 "JeVois ort.yml DNN Zoo for ONNX-Runtime CPU models", EditorSaveAction::Reload },
94 {
".yaml",
".yml" }));
97 std::vector<EditorItem> fixedcode
99 {
"*",
"Module's source code", EditorSaveAction::Reload },
105 {
".py",
".C",
".H",
".cpp",
".hpp",
".c",
".h",
".txt" }));
118 itsEndFrameCalled =
true;
121 itsLastDrawnImage =
nullptr;
122 itsLastDrawnTextLine = -1;
133 itsCfgEditor->refresh();
134 itsCodeEditor->refresh();
139 std::lock_guard<std::mutex> _(itsErrorMtx);
145 itsBackend.getWindowSize(w,
h);
147 if (w == 0)
LFATAL(
"Need to call startFrame() at least once first");
149 float const fov_y = 45.0f;
151 proj = glm::perspective(glm::radians(fov_y),
float(w) /
float(
h), 1.0f,
h * 2.0f);
152 const_cast<float &
>(pixel_perfect_z) = -
float(
h) / (2.0 * tan(fov_y * M_PI / 360.0));
153#ifdef JEVOIS_PLATFORM
155 proj = glm::translate(proj, glm::vec3(0.375f, 0.375f, 0.0f));
157 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, pixel_perfect_z));
160 style::set(style::get());
167 if (std::filesystem::exists(m.
cmakepath())) itsNewMapping = m;
173 if (itsEndFrameCalled ==
false)
LFATAL(
"You need to call endFrame() at the end of your process() function");
176 itsBackend.getWindowSize(w,
h);
181 cv::Size
const siz = winsize::get();
182 bool const fs = fullscreen::get();
183 LINFO(
"OpenGL init " << siz.width <<
'x' << siz.height << (fs ?
" fullscreen" :
""));
184 itsBackend.init(siz.width, siz.height, fs, scale::get(), itsConsLock);
185 rounding::set(
int(rounding::get() * scale::get() + 0.499F));
188 unsigned short winw, winh; itsBackend.getWindowSize(winw, winh); winsize::set(cv::Size(winw, winh));
189 winsize::freeze(
true);
190 fullscreen::freeze(
true);
197 bool shouldclose =
false;
auto const now = std::chrono::steady_clock::now();
198 if (itsBackend.pollEvents(shouldclose)) itsLastEventTime = now;
200 if (shouldclose && allowquit::get())
202 LINFO(
"Closing down on user request...");
207 itsBackend.newFrame();
214 float const hs = hidesecs::get();
217 std::chrono::duration<float> elapsed = now - itsLastEventTime;
218 itsIdle = (elapsed.count() >= hs);
220 else itsIdle =
false;
223 itsEndFrameCalled =
false;
235 float oldval = param.get();
236 if (newval == oldval)
return;
238 ImGui::GetStyle().ScaleAllSizes(newval / oldval);
239 ImGui::GetIO().FontGlobalScale = newval;
240 ImGui::GetStyle().MouseCursorScale = 2.0f;
243 if (oldval) rounding::set(std::min(24,
int(rounding::get() * newval / oldval + 0.499F)));
251 case jevois::gui::GuiStyle::Dark:
252 ImGui::StyleColorsDark();
253 itsCfgEditor->SetPalette(TextEditor::GetDarkPalette());
254 itsCodeEditor->SetPalette(TextEditor::GetDarkPalette());
257 case jevois::gui::GuiStyle::Light:
258 ImGui::StyleColorsLight();
259 ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 0.92f);
260 itsCfgEditor->SetPalette(TextEditor::GetLightPalette());
261 itsCodeEditor->SetPalette(TextEditor::GetLightPalette());
264 case jevois::gui::GuiStyle::Classic:
265 ImGui::StyleColorsClassic();
266 itsCfgEditor->SetPalette(TextEditor::GetRetroBluePalette());
267 itsCodeEditor->SetPalette(TextEditor::GetRetroBluePalette());
275 auto & s = ImGui::GetStyle();
276 s.WindowRounding = newval;
277 s.ChildRounding = newval;
278 s.FrameRounding = newval;
279 s.PopupRounding = newval;
280 s.ScrollbarRounding = newval;
281 s.GrabRounding = newval;
286{
return (itsEndFrameCalled ==
false); }
290 unsigned short & w,
unsigned short &
h,
bool noalias,
bool isoverlay)
293 std::string
const imgname = name + std::to_string(img.
bufindex);
296 auto & im = itsImages[imgname];
302 im.draw(x, y, w,
h, noalias, proj * view);
305 if (isoverlay ==
false)
307 itsLastDrawnImage = & im;
308 itsUsingScaledImage =
false;
309 itsLastDrawnTextLine = -1;
315 unsigned short & w,
unsigned short &
h,
bool noalias,
bool isoverlay)
318 auto & im = itsImages[name];
324 im.draw(x, y, w,
h, noalias, proj * view);
327 if (isoverlay ==
false)
329 itsLastDrawnImage = & im;
330 itsUsingScaledImage =
false;
331 itsLastDrawnTextLine = -1;
337 unsigned short & w,
unsigned short &
h,
bool noalias,
bool casync)
341 std::string
const imgname = name + std::to_string(img.
bufindex);
344 auto & im = itsImages[imgname];
348 im.set(frame, itsBackend.getDisplay());
351 im.draw(x, y, w,
h, noalias, proj * view);
354 itsLastDrawnImage = & im;
356 itsLastDrawnTextLine = -1;
357 if (itsUsingScaledImage)
360 itsScaledImageFacX = float(img.
width) / float(img2.
width);
361 itsScaledImageFacY = float(img.
height) / float(img2.
height);
367 unsigned short & w,
unsigned short &
h,
bool noalias,
bool casync)
371 std::string
const imgname = name + std::to_string(img.
bufindex);
374 auto & im = itsImages2[imgname];
378 im.set2(frame, itsBackend.getDisplay());
381 im.draw(x, y, w,
h, noalias, proj * view);
384 itsLastDrawnImage = & im;
385 itsUsingScaledImage =
false;
386 itsLastDrawnTextLine = -1;
395 itsGlobalAlpha = std::abs(1.0F - newval / 15.0F);
398 for (
auto & ip : itsImages) ip.second.twirl(newval);
409 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
410 img = itsLastDrawnImage;
414 std::string nstr = name;
415 auto itr = itsImages.find(nstr);
416 if (itr == itsImages.end())
420 itr = itsImages.find(nstr +
'0');
421 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
427 if (itsUsingScaledImage) { p.x *= itsScaledImageFacX; p.y *= itsScaledImageFacY; }
435{
return i2d(ImVec2(x, y), name); }
445 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
446 img = itsLastDrawnImage;
450 std::string nstr = name;
451 auto itr = itsImages.find(nstr);
452 if (itr == itsImages.end())
456 itr = itsImages.find(nstr +
'0');
457 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
463 if (itsUsingScaledImage) { p.x *= itsScaledImageFacX; p.y *= itsScaledImageFacY; }
471{
return i2ds(ImVec2(x, y), name); }
476 ImGui::GetBackgroundDrawList()->AddLine(i2d(x1, y1), i2d(x2, y2), col, linethick::get());
482 auto dlb = ImGui::GetBackgroundDrawList();
483 ImVec2
const tl = i2d(x1, y1);
484 ImVec2
const br = i2d(x2, y2);
486 if (filled) dlb->AddRectFilled(tl, br, applyFillAlpha(col));
488 dlb->AddRect(tl, br, col, 0.0F, ImDrawCornerFlags_All, linethick::get());
494 auto dlb = ImGui::GetBackgroundDrawList();
495 float const thick = linethick::get();
497 if (filled) dlb->AddConvexPolyFilled(pts, npts, applyFillAlpha(col));
501 for (
size_t i = 0; i < npts - 1; ++i)
503 ImVec2
const & p1 = pts[i];
504 ImVec2
const & p2 = pts[i + 1];
507 if (p1.x != p2.x || p1.y != p2.y) dlb->AddLine(p1, p2, col, thick);
509 dlb->AddLine(pts[npts - 1], pts[0], col, thick);
516 size_t const npts = pts.size();
517 if (npts < 3)
return;
520 for (
int i = 0;
auto const & p : pts) iv[i++] = i2d(p.x, p.y);
522 drawPolyInternal(iv, npts, col, filled);
528 size_t const npts = pts.size();
529 if (npts < 3)
return;
532 for (
int i = 0;
auto const & p : pts) iv[i++] = i2d(p.x, p.y);
534 drawPolyInternal(iv, npts, col, filled);
540 float const * ptr = pts.ptr<
float>(0);
546 if (pts.rows == 1 || pts.cols == 1)
549 int n = std::max(pts.rows, pts.cols);
551 if (std::min(pts.rows, pts.cols) < 3)
return;
552 n /= 2; ImVec2 p[n];
for (
int i = 0; i < n; ++i) { p[i] = i2d(ptr[0], ptr[1]); ptr += 2; }
553 drawPolyInternal(p, n, col, filled);
555 else if (pts.rows == 2)
558 if (pts.cols < 3)
return;
559 ImVec2 p[pts.cols];
for (
int i = 0; i < pts.cols; ++i) { p[i] = i2d(ptr[0], ptr[pts.cols]); ++ptr; }
560 drawPolyInternal(p, pts.cols, col, filled);
562 else if (pts.cols == 2)
565 if (pts.rows < 3)
return;
566 ImVec2 p[pts.rows];
for (
int i = 0; i < pts.rows; ++i) { p[i] = i2d(ptr[0], ptr[1]); ptr += 2; }
567 drawPolyInternal(p, pts.rows, col, filled);
578 if (pts.cols < 3)
return;
579 ImVec2 p[pts.cols];
for (
int i = 0; i < pts.cols; ++i) { p[i] = i2d(ptr[0], ptr[1]); ptr += 2; }
580 drawPolyInternal(p, pts.cols, col, filled);
582 else if (pts.cols == 1)
585 if (pts.rows < 3)
return;
586 ImVec2 p[pts.rows];
for (
int i = 0; i < pts.rows; ++i) { p[i] = i2d(ptr[0], ptr[1]); ptr += 2; }
587 drawPolyInternal(p, pts.rows, col, filled);
600 auto dlb = ImGui::GetBackgroundDrawList();
602 ImVec2
const center = i2d(x, y);
603 float const rad = i2ds(r, 0).x;
605 if (filled) dlb->AddCircleFilled(center, rad, applyFillAlpha(col), 0);
607 dlb->AddCircle(center, rad, col, 0, linethick::get());
613 ImGui::GetBackgroundDrawList()->AddText(i2d(x, y), col, txt);
619 drawText(x, y, txt.c_str(), col);
625 unsigned char alpha = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
626 alpha = (
unsigned char)(fillalpha::get() * alpha);
627 return (col & ~IM_COL32_A_MASK) | (alpha << IM_COL32_A_SHIFT);
633 if (line == -1) line = ++itsLastDrawnTextLine;
else itsLastDrawnTextLine = line;
634 ImVec2 p = i2d(0, 0, name);
636 p.y += 5.0F + (ImGui::GetFontSize() + 5.0F) * line;
643 ImU32
const c = (col == IM_COL32_BLACK_TRANS) ? ImU32(overlaycolor::get()) : col;
644 ImGui::GetBackgroundDrawList()->AddText(iline(line), c, txt);
650 itext(txt.c_str(), col, line);
655 unsigned short winw,
unsigned short winh)
657 unsigned short ww, wh;
658 if (winw == 0 || winh == 0) itsBackend.getWindowSize(ww, wh);
else { ww = winw; wh = winh; }
667 std::string
const msg =
jevois::sformat(
"%s, Camera: %s:%dx%d%s, Display: RGBA:%dx%d", fpscpu.c_str(),
669 cam2str.c_str(), ww, wh);
671 ImGui::GetBackgroundDrawList()->AddText(ImVec2(10, wh-10-ImGui::GetFontSize()), overlaycolor::get(), msg.c_str());
677 auto itr = itsImages.find(name);
678 if (itr != itsImages.end()) itsImages.erase(itr);
684 auto itr = itsImages2.find(name);
685 if (itr != itsImages2.end()) itsImages2.erase(itr);
693 float fx = 1.0F, fy = 1.0F;
697 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
698 img = itsLastDrawnImage;
699 if (itsUsingScaledImage) { fx = 1.0F / itsScaledImageFacX; fy = 1.0F / itsScaledImageFacY; }
703 std::string nstr = name;
704 auto itr = itsImages.find(nstr);
705 if (itr == itsImages.end())
709 itr = itsImages.find(nstr +
'0');
710 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
716 ImVec2 ret = img->
d2i(p);
717 ret.x *= fx; ret.y *= fy;
723{
return d2i(ImVec2(x, y), name); }
730 float fx = 1.0F, fy = 1.0F;
734 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
735 img = itsLastDrawnImage;
736 if (itsUsingScaledImage) { fx = 1.0F / itsScaledImageFacX; fy = 1.0F / itsScaledImageFacY; }
740 std::string nstr = name;
741 auto itr = itsImages.find(nstr);
742 if (itr == itsImages.end())
746 itr = itsImages.find(nstr +
'0');
747 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
753 ImVec2 ret = img->
d2is(p);
754 ret.x *= fx; ret.y *= fy;
760{
return d2is(ImVec2(x, y), name); }
766 ImGui::GetIO().MouseDrawCursor = ! itsIdle;
769 if (itsIdle ==
false) drawJeVoisGUI();
772 if (itsCompileState != CompilationState::Idle) compileModule();
775 if (itsGlobalAlpha != 1.0F)
777 if (itsGlobalAlpha < 0.0F || itsGlobalAlpha > 1.0F)
779 LERROR(
"Invalid global alpha " << itsGlobalAlpha <<
" -- RESET TO 1.0");
780 itsGlobalAlpha = 1.0F;
784 auto dlb = ImGui::GetBackgroundDrawList();
785 cv::Size
const ws = winsize::get();
786 dlb->AddRectFilled(ImVec2(0, 0), ImVec2(ws.width, ws.height), ImColor(0.0F, 0.0F, 0.0F, 1.0F - itsGlobalAlpha));
791 if (itsBannerTitle.empty() ==
false)
793 ImGui::SetNextWindowPos(ImVec2(800, 500));
794 ImGui::SetNextWindowSize(ImVec2(1000, 400));
795 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xf0e0ffe0);
796 ImGui::Begin(
"JeVois-Pro Demo Mode",
nullptr, ImGuiWindowFlags_NoResize |
797 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse |
798 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings);
799 ImGui::SetWindowFontScale(1.5F);
800 ImGui::TextUnformatted(
" ");
801 ImGui::TextUnformatted(itsBannerTitle.c_str());
802 ImGui::TextUnformatted(
" ");
803 ImGui::SetWindowFontScale(1.0F);
805 int wrap = ImGui::GetWindowSize().x - ImGui::GetFontSize() * 2.0f;
806 ImGui::PushTextWrapPos(wrap);
807 ImGui::TextUnformatted(itsBannerMsg.c_str());
808 ImGui::PopTextWrapPos();
810 ImGui::SetCursorPosY(ImGui::GetWindowSize().y - ImGui::CalcTextSize(
"X").y * 2.3F);
813 if (ImGui::Button(
"Skip to Next Demo")) engine()->
nextDemo();
814 ImGui::SetItemDefaultFocus();
815 ImGui::SameLine(600);
816 if (ImGui::Button(
"Abort Demo Mode")) engine()->
abortDemo();
818 ImGui::PopStyleColor();
824 itsEndFrameCalled =
true;
831 ImGui::SetNextWindowPos(ImVec2(920, 358), ImGuiCond_FirstUseEver);
832 ImGui::SetNextWindowSize(ImVec2(941, 639), ImGuiCond_FirstUseEver);
834 if (ImGui::Begin(itsWindowTitle.c_str(),
nullptr ))
842 if (ImGui::BeginTabBar(
"##tabs", ImGuiTabBarFlags_None))
845 if (ImGui::BeginTabItem(
"Info"))
851 if (ImGui::BeginTabItem(
"Parameters"))
857 if (ImGui::BeginTabItem(
"Console"))
863 if (ImGui::BeginTabItem(
"Camera"))
869 if (ImGui::BeginTabItem(
"Config"))
871 itsCfgEditor->draw();
875 if (ImGui::BeginTabItem(
"Code"))
877 itsCodeEditor->draw();
881 if (ImGui::BeginTabItem(
"System"))
887 if (ImGui::BeginTabItem(
"Tweaks"))
899 if (itsShowStyleEditor)
901 ImGui::Begin(
"GUI Style Editor", &itsShowStyleEditor);
902 ImGui::ShowStyleEditor();
905 if (itsShowAppMetrics) ImGui::ShowMetricsWindow(&itsShowAppMetrics);
906 if (itsShowImGuiDemo) ImGui::ShowDemoWindow(&itsShowImGuiDemo);
909 if (itsShowHardSerialWin)
912 ImGui::SetNextWindowSize(ImVec2(700, 500), ImGuiCond_FirstUseEver);
915 ImGui::Begin(
"Hardware 4-pin Serial Monitor", &itsShowHardSerialWin);
919 ImGui::TextUnformatted(
"No Hardware serial port found!");
921 ImGui::TextUnformatted(
"Check engine:serialdev parameter, and");
922 ImGui::TextUnformatted(
"that engine:serialmonitors is true.");
928 if (itsShowUsbSerialWin)
931 ImGui::SetNextWindowSize(ImVec2(700, 500), ImGuiCond_FirstUseEver);
934 ImGui::Begin(
"USB Serial Monitor", &itsShowUsbSerialWin);
938 ImGui::TextUnformatted(
"No USB serial port found!");
940 ImGui::TextUnformatted(
"Check engine:usbserialdev parameter, and");
941 ImGui::TextUnformatted(
"that engine:serialmonitors is true.");
953 if (ImGui::BeginMenuBar())
955 if (ImGui::BeginMenu(
"File"))
957 if (ImGui::MenuItem(
"Quit")) engine()->
quit();
993 if (ImGui::BeginMenu(
"Tools"))
995 ImGui::MenuItem(
"ImGui Style Editor", NULL, &itsShowStyleEditor);
996 ImGui::MenuItem(
"ImGui Metrics/Debugger", NULL, &itsShowAppMetrics);
997 ImGui::MenuItem(
"ImGui Demo/Doc", NULL, &itsShowImGuiDemo);
1002 ImGui::EndMenuBar();
1009 static std::map<std::string, size_t> mods;
1011 static std::string currstr;
1014 ImGui::AlignTextToFramePadding();
1015 ImGui::Text(
"Module:");
1017 ImGui::SetNextItemWidth(6 * ImGui::GetFontSize() + 5);
1018 if (ImGui::Combo(
"##typemachinevisionmodule", &itsVideoMappingListType,
"Pro/GUI\0Legacy\0Headless\0\0")
1019 || currstr.empty() || itsRefreshVideoMappings)
1022 itsRefreshVideoMappings =
false;
1025 switch (itsVideoMappingListType)
1060 default:
LFATAL(
"Internal error, itsVideoMappingListType=" << itsVideoMappingListType);
1064 currstr = e->getCurrentVideoMapping().menustr().c_str();
1070 if (ImGui::BeginCombo(
"##machinevisionmodule", currstr.c_str()))
1072 for (
auto const & m : mods)
1074 bool is_selected =
false;
1075 if (ImGui::Selectable(m.first.c_str(), is_selected))
1077 e->requestSetFormat(m.second);
1089 std::shared_ptr<jevois::Module> m = engine()->
module();
1093 if (itsIcon.loaded() ==
false)
1094 try { itsIcon.load(m->absolutePath(
"icon.png")); }
1098 LERROR(
"This module has no icon -- USING DEFAULT");
1101 if (engine()->getCurrentVideoMapping().ispython) itsIcon.load(
JEVOIS_SHARE_PATH "/icons/py.png");
1107 cv::Mat blank(32, 32, CV_8UC4, 0);
1108 itsIcon.load(blank);
1112 if (itsIcon.loaded())
1114 int const siz = ImGui::CalcTextSize(
" ").x;
1115 itsIcon.draw(ImGui::GetCursorScreenPos(), ImVec2(siz, siz));
1119 if (itsModName.empty())
1121 std::filesystem::path fname = m->absolutePath(
"modinfo.html");
1122 std::ifstream ifs(fname);
1123 if (ifs.is_open() ==
false)
1126 LINFO(
"Recomputing module's modinfo.html ...");
1130 std::string
const cmdout =
1132 "JEVOIS_SRC_ROOT=none jevoispro-modinfo " + vm.
modulename,
true);
1134 if (! std::filesystem::exists(fname))
1135 throw std::runtime_error(
"Failed to create " + vm.
modinfopath() +
": " + cmdout);
1137 catch (...) { itsModName = vm.
modulename; itsModAuth =
"Cannot read file: " + fname.string(); }
1143 for (std::string s; std::getline(ifs, s); )
1149 if (str.empty() ==
false) { itsModName = str; ++state; }
1156 if (str.empty() ==
false) { itsModDesc = str; ++state; }
1162 std::string
const str =
jevois::extractString(s,
"<table class=modinfoauth width=100%>",
"</table>");
1163 if (str.empty() ==
false)
1174 if (str.empty() ==
false)
1178 if (tok.size() >= 3)
1181 else itsModLang =
"Language: Python";
1183 else itsModLang =
"Language: Unknown";
1192 if (str.empty() ==
false)
1196 size_t idx = str2.find_first_not_of(
" ");
if (idx != str2.npos) str2 = str2.substr(idx);
1197 itsModDoc.emplace_back(str2);
1205 if (s ==
"</div></td></tr>") ++state;
1211 if (s.find(
"/h1>") != s.npos || s.find(
"/h2>") != s.npos || s.find(
"/h3>") != s.npos) prefix =
"* ";
1212 if (s.find(
"<li>") != s.npos) prefix =
"- ";
1217 std::string::iterator new_end =
1218 std::unique(ss.begin(), ss.end(), [](
char lhs,
char rhs) { return (lhs == rhs) && (lhs ==
' '); });
1219 ss.erase(new_end, ss.end());
1220 size_t idx = ss.find_first_not_of(
" ");
if (idx != ss.npos) ss = ss.substr(idx);
1221 itsModDoc.push_back(ss);
1232 ImGui::TextUnformatted((
" " + itsModName).c_str());
1233 ImGui::TextUnformatted((
" " + itsModDesc).c_str());
1234 ImGui::TextUnformatted((
" " + itsModAuth +
" " + itsModLang).c_str());
1235 ImGui::TextUnformatted(
" ");
1237 int wrap = ImGui::GetCursorPos().x + ImGui::GetWindowSize().x - ImGui::GetFontSize() * 2.0f;
1238 if (wrap < 200) wrap = 200;
1239 ImGui::PushTextWrapPos(wrap);
1242 for (std::string
const & s : itsModDoc)
1246 show = ImGui::CollapsingHeader(s.c_str() + 2, ImGuiTreeNodeFlags_DefaultOpen);
1251 else ImGui::TextUnformatted(s.c_str());
1254 ImGui::PopTextWrapPos();
1257 ImGui::TextUnformatted(
"No JeVois Module currently loaded.");
1271 static bool show_frozen =
true;
static bool show_system =
false;
1273 toggleButton(
"Show Frozen Parameters", &show_frozen);
1274 ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::CalcTextSize(
"Show System Parameters").x - 30.0f);
1275 toggleButton(
"Show System Parameters", &show_system);
1281 if (c ==
nullptr) { ImGui::TextUnformatted(
"No module loaded.");
return; }
1284 std::set<std::string> pnames, ambig;
1287 std::map<std::string , std::vector<jevois::ParameterSummary>> psm;
1290 if (pnames.insert(psum.
name).second ==
false) ambig.insert(psum.
name);
1291 psm[psum.
category].push_back(std::move(psum)); } );
1294 if (psm.empty()) { ImGui::Text(
"This module has no parameters.");
return; }
1298 float maxlen = 0.0f;
1299 for (
auto const & pp : psm)
1302 if (show_frozen ==
false)
1304 bool all_frozen =
true;
1305 for (
auto const & ps : pp.second)
if (ps.frozen ==
false) { all_frozen =
false;
break; }
1306 if (all_frozen)
continue;
1310 if (ImGui::CollapsingHeader(pp.first.c_str()))
1312 ImGui::Columns(3,
"parameters");
1315 for (
auto const & ps : pp.second)
1318 if (ps.frozen && show_frozen ==
false)
continue;
1321 static char wname[16]; snprintf(wname, 16,
"##p%d", widgetnum);
1325 ImGui::AlignTextToFramePadding();
1326 std::string nam = ps.name;
1327 if (ambig.contains(nam))
1331 if (tok.size() >= 2) nam = tok[tok.size()-2] +
':' + nam;
1334 ImGui::TextUnformatted(nam.c_str());
1335 if (ImGui::IsItemHovered()) ImGui::SetTooltip(
"%s", ps.descriptor.c_str());
1336 maxlen = std::max(maxlen, ImGui::CalcTextSize(nam.c_str()).x);
1339 ImGui::NextColumn();
1340 ImGui::AlignTextToFramePadding();
1341 std::string
const & vtype = ps.valuetype;
1343 helpMarker(ps.description.c_str(), (
"Parameter type: " + vtype).c_str());
1345 helpMarker(ps.description.c_str(), (
"Parameter type: " + vtype).c_str(),
1346 (
"Allowed values: " + ps.validvalues).c_str());
1349 ImGui::NextColumn();
1350 bool const is_uchar = (vtype ==
"unsigned char");
1351 bool const is_int = (vtype ==
"short" || vtype ==
"int" || vtype ==
"long int" || vtype ==
"long long int");
1352 bool const is_uint = (is_uchar || vtype ==
"unsigned short" || vtype ==
"unsigned int" ||
1353 vtype ==
"unsigned long int" || vtype ==
"unsigned long long int" || vtype ==
"size_t");
1354 bool const is_real = (vtype ==
"float" || vtype ==
"double" || vtype ==
"long double");
1357 int textflags = ImGuiInputTextFlags_EnterReturnsTrue;
1360 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1361 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1362 textflags |= ImGuiInputTextFlags_ReadOnly;
1368 std::string vals = ps.validvalues.substr(6, ps.validvalues.size() - 7);
1371 if (vv.empty() ==
false)
1374 int index = 0;
for (
auto const & v : vv)
if (v == ps.value)
break;
else ++index;
1377 if (combo(wname, vv, index)) setparstr(ps.descriptor, vv[index]);
1387 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1392 long mi = 0, ma = 255;
1393 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &mi, &ma))
1394 setparstr(ps.descriptor, std::to_string(val));
1399 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &r.
min(), &r.
max()))
1400 setparstr(ps.descriptor, std::to_string(val));
1406 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1409 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &r.
min(), &r.
max()))
1410 setparstr(ps.descriptor, std::to_string(val));
1415 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1418 if (ImGui::SliderScalar(wname, ImGuiDataType_S64, &val, &r.
min(), &r.
max()))
1419 setparstr(ps.descriptor, std::to_string(val));
1424 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1427 if (ImGui::SliderScalar(wname, ImGuiDataType_Double, &val, &r.
min(), &r.
max()))
1428 setparstr(ps.descriptor, std::to_string(val));
1433 char buf[256]; strncpy(buf, ps.value.c_str(),
sizeof(buf)-1);
1434 if (ImGui::InputText(wname, buf,
sizeof(buf), textflags))
1435 setparstr(ps.descriptor, buf);
1439 else if (vtype ==
"jevois::Range<unsigned char>")
1443 int mi = val.
min(), ma = val.
max();
1444 if (ImGui::DragIntRange2(wname, &mi, &ma, 0, 0, 255,
"Min: %d",
"Max: %d"))
1448 else if (vtype ==
"bool")
1451 if (ImGui::Checkbox(wname, &val)) setparval(ps.descriptor, val);
1454 else if (vtype ==
"ImColor")
1457 if (ImGui::ColorEdit4(wname, (
float *)&val, ImGuiColorEditFlags_AlphaPreview)) setparval(ps.descriptor, val);
1463 char buf[256]; strncpy(buf, ps.value.c_str(),
sizeof(buf)-1);
1464 if (ImGui::InputText(wname, buf,
sizeof(buf), textflags))
1465 setparstr(ps.descriptor, buf);
1471 static char rname[18]; snprintf(rname, 18,
"Reset##%d", widgetnum);
1473 if (ImGui::Button(rname)) setparstr(ps.descriptor, ps.defaultvalue);
1479 ImGui::PopItemFlag();
1480 ImGui::PopStyleVar();
1484 ImGui::NextColumn(); ++widgetnum;
1494 ImGui::Columns(3,
"parameters");
1495 ImGui::SetColumnWidth(0, maxlen + ImGui::CalcTextSize(
"XX").x);
1496 ImGui::SetColumnWidth(1, ImGui::CalcTextSize(
" (?) ").x);
1497 ImGui::SetColumnWidth(2, 2000);
1508 bool slusb =
false, slhard =
false, schanged =
false;
1512 case jevois::engine::SerPort::None: slusb =
false; slhard =
false;
break;
1513 case jevois::engine::SerPort::All: slusb =
true; slhard =
true;
break;
1514 case jevois::engine::SerPort::Hard: slusb =
false; slhard =
true;
break;
1515 case jevois::engine::SerPort::USB: slusb =
true; slhard =
false;
break;
1517 ImGui::AlignTextToFramePadding();
1518 ImGui::Text(
"Log messages:"); ImGui::SameLine();
1519 if (itsUSBserial ==
false)
1521 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1522 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1523 if (toggleButton(
"USB##serlogu", &slusb)) schanged =
true;
1524 ImGui::PopItemFlag();
1525 ImGui::PopStyleVar();
1526#ifdef JEVOIS_PLATFORM
1527 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1528 { ImGui::BeginTooltip(); ImGui::Text(
"Disabled - enable USB serial in the System tab"); ImGui::EndTooltip(); }
1530 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1531 { ImGui::BeginTooltip(); ImGui::Text(
"Disabled - not available on host"); ImGui::EndTooltip(); }
1534 else if (toggleButton(
"USB##serlogu", &slusb)) schanged =
true;
1536 ImGui::SameLine();
if (toggleButton(
"Hard##serlogh", &slhard)) schanged =
true;
1537 ImGui::SameLine(); toggleButton(
"Cons##serlogc", &itsSerLogEnabled);
1538 ImGui::SameLine(0, 50);
1540 bool sousb =
false, sohard =
false;
1544 case jevois::engine::SerPort::None: sousb =
false; sohard =
false;
break;
1545 case jevois::engine::SerPort::All: sousb =
true; sohard =
true;
break;
1546 case jevois::engine::SerPort::Hard: sousb =
false; sohard =
true;
break;
1547 case jevois::engine::SerPort::USB: sousb =
true; sohard =
false;
break;
1549 ImGui::Text(
"Module output:"); ImGui::SameLine();
1550 if (itsUSBserial ==
false)
1552 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1553 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1554 if (toggleButton(
"USB##seroutu", &sousb)) schanged =
true;
1555 ImGui::PopItemFlag();
1556 ImGui::PopStyleVar();
1557#ifdef JEVOIS_PLATFORM
1558 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1559 { ImGui::BeginTooltip(); ImGui::Text(
"Disabled - enable USB serial in the System tab"); ImGui::EndTooltip(); }
1561 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1562 { ImGui::BeginTooltip(); ImGui::Text(
"Disabled - not available on host"); ImGui::EndTooltip(); }
1565 else if (toggleButton(
"USB##seroutu", &sousb)) schanged =
true;
1566 ImGui::SameLine();
if (toggleButton(
"Hard##serouth", &sohard)) schanged =
true;
1567 ImGui::SameLine(); toggleButton(
"Cons##seroutc", &itsSerOutEnabled);
1573 if (slhard) e->
setParamValUnique(
"engine:serlog", jevois::engine::SerPort::All);
1578 if (slhard) e->
setParamValUnique(
"engine:serlog", jevois::engine::SerPort::Hard);
1584 if (sohard) e->
setParamValUnique(
"engine:serout", jevois::engine::SerPort::All);
1589 if (sohard) e->
setParamValUnique(
"engine:serout", jevois::engine::SerPort::Hard);
1599 int idx = 0;
for (
auto const & v : jevois::modul::SerStyle_Values)
if (v == sp)
break;
else ++idx;
1602 if (combo(
"serstyle", jevois::modul::SerStyle_Strings, idx))
1615{
return itsSerLogEnabled; }
1619{
return itsSerOutEnabled; }
1629 char const * b1txt,
char const * b2txt)
1632 int ret = 0;
int * retptr = default_val ? default_val : &ret;
1635 if (*retptr == 1 || *retptr == 2)
return *retptr;
1638 if (itsOpenModals.find(title) == itsOpenModals.end())
1640 ImGui::OpenPopup(title.c_str());
1641 itsOpenModals.insert(title);
1645 bool dont_ask_me_next_time = (*retptr == 3);
1647 if (ImGui::BeginPopupModal(title.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize))
1649 ImGui::TextUnformatted(text); ImGui::TextUnformatted(
" ");
1653 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
1654 ImGui::PushStyleColor(ImGuiCol_FrameBg, 0xf0ffe0e0);
1655 ImGui::Checkbox(
"Don't ask me next time", &dont_ask_me_next_time);
1656 ImGui::PopStyleColor();
1657 ImGui::PopStyleVar();
1659 float const b1w = std::max(120.0F, ImGui::CalcTextSize(b1txt).x + 20.0F);
1660 if (ImGui::Button(b1txt, ImVec2(b1w, 0))) ret = 1;
1661 ImGui::SetItemDefaultFocus();
1663 float const b2w = std::max(120.0F, ImGui::CalcTextSize(b2txt).x + 20.0F);
1664 if (ImGui::Button(b2txt, ImVec2(b2w, 0))) ret = 2;
1669 if (ret == 1 || ret == 2)
1671 ImGui::CloseCurrentPopup();
1672 itsOpenModals.erase(title);
1673 if (dont_ask_me_next_time) *retptr = ret;
1675 else *retptr = dont_ask_me_next_time ? 3 : 0;
1683 return ImGui::Combo(name.c_str(), &selected_index,
1684 [](
void * vec,
int idx,
const char ** out_text)
1686 auto & ve = *static_cast<std::vector<std::string>*>(vec);
1687 if (idx < 0 || idx >= static_cast<int>(ve.size())) return false;
1688 *out_text = ve.at(idx).c_str();
1691 const_cast<void *
>(
static_cast<void const *
>(&items)), items.size());
1696 char const * hint,
char const * hlp)
1698 static char buf[256];
1699 ImGui::AlignTextToFramePadding();
1700 ImGui::TextUnformatted(desc);
1701 ImGui::NextColumn();
1702 helpMarker(desc, hlp);
1703 ImGui::NextColumn();
1704 strncpy(buf, str.c_str(),
sizeof(buf)-1);
1705 if (ImGui::InputTextWithHint(wname, hint, buf,
sizeof(buf))) str = buf;
1706 ImGui::NextColumn();
1712 float const fontw = ImGui::GetFontSize();
1714 static int refresh = 1;
1715 static std::string cpu, mem, ver;
1716 static size_t npu, tpu, vpu, spu;
static int fan;
1730 ImGui::Text(cpu.c_str());
1731 ImGui::Text(mem.c_str());
1732 ImGui::Text(
"NPU: %d, TPU: %d, VPU: %d, SPU: %d. Fan: %d%%", npu, tpu, vpu, spu, fan);
1736 drawNewModuleForm();
1740 if (ImGui::Button(
"Open Hardware serial monitor...")) itsShowHardSerialWin =
true;
1742 if (ImGui::Button(
"Open USB serial monitor...")) itsShowUsbSerialWin =
true;
1746 static std::string pingstr;
1747 static int showping = 0;
1748 if (ImGui::Button(
"Ping jevois.usc.edu"))
1750 std::string ret =
jevois::system(
"/usr/bin/ping -c 1 -w 2 jevois.usc.edu");
1752 if (rvec.size() < 2) reportError(
"Unable to ping jevois.usc.edu");
1753 else { pingstr = rvec[1]; showping = 60; }
1758 ImGui::Text(pingstr.c_str());
1765 static std::string zip;
1766 static std::string donestr;
1767 static int state = 0;
1769 ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue;
1770 if (state) flags |= ImGuiInputTextFlags_ReadOnly;
1771 ImGui::SetNextItemWidth(fontw * 6.0F);
1773 if (ImGui::InputText(
"Load Custom DNN", buf,
sizeof(buf), flags)) state = 1;
1784 ImGui::Text(
"-- Downloading...");
1785 zip = std::string(buf) +
".zip";
1798 if (itsDnnGetFut.valid() ==
false) { reportError(
"Unknown error while loading custom DNN"); state = 0;
break; }
1799 ImGui::Text(
"-- Downloading...");
1800 if (itsDnnGetFut.wait_for(std::chrono::microseconds(100)) == std::future_status::ready)
1806 if (ifs.is_open() ==
false)
1808 reportError(
"Failed to download. Check network connectivity and available disk space.");
1825 if (itsDnnGetFut.valid() ==
false) { reportError(
"Unknown error while unpacking custom DNN"); state = 0;
break; }
1826 ImGui::Text(
"-- Installing...");
1827 if (itsDnnGetFut.wait_for(std::chrono::microseconds(100)) == std::future_status::ready)
1829 std::string ret = itsDnnGetFut.get();
1832 donestr =
"-- Invalid file, check DNN download key.";
1834 donestr =
"-- Done. Reload model zoo to take effect.";
1847 ImGui::Text(donestr.c_str());
1852#ifdef JEVOIS_PLATFORM
1854 static int bootmode = 0;
1855 ImGui::AlignTextToFramePadding();
1856 ImGui::Text(
"On boot, start:");
1858 if (ImGui::Combo(
"##onboot", &bootmode,
"(no change)\0JeVois-Pro\0Ubuntu Console\0Ubuntu Graphical\0\0"))
1863 case 2:
jevois::system(
"systemctl --no-reload set-default multi-user.target");
break;
1864 case 3:
jevois::system(
"systemctl --no-reload set-default graphical.target");
break;
1865 default:
jevois::system(
"systemctl --no-reload set-default jevoispro.target");
break;
1872 static bool gserial =
false;
1874 if (ImGui::Checkbox(
"Enable serial outputs/logs over mini-USB (on next reboot)", &gserial))
1877 ofs << (gserial ? 1 : 0) << std::endl;
1884 static bool show_fan_modal =
false;
1885 if (ImGui::Button(
"Edit fan settings"))
1887 itsCfgEditor->loadFile(
"/lib/systemd/system/jevoispro-fan.service");
1888 show_fan_modal =
true;
1893 static int doit_default = 0;
1894 int ret = modal(
"Ready to edit",
"File will now be loaded in the Config tab of the main window and "
1895 "ready to edit.\nPlease switch to the Config tab in the main window.\n\n"
1896 "When you save it, we will reboot the camera.",
1897 &doit_default,
"Ok",
"Thanks");
1900 case 1: show_fan_modal =
false;
break;
1901 case 2: show_fan_modal =
false;
break;
1915 unsigned int get_v4l2_fmt(
int idx)
1919 case 0:
return V4L2_PIX_FMT_YUYV;
1920 case 1:
return V4L2_PIX_FMT_RGB24;
1921 case 2:
return V4L2_PIX_FMT_RGB32;
1922 case 3:
return V4L2_PIX_FMT_GREY;
1923 case 4:
return V4L2_PIX_FMT_SBGGR16;
1928 unsigned int get_v4l2_idx(
int fcc)
1932 case V4L2_PIX_FMT_YUYV:
return 0;
1933 case V4L2_PIX_FMT_RGB24:
return 1;
1934 case V4L2_PIX_FMT_RGB32:
return 2;
1935 case V4L2_PIX_FMT_GREY:
return 3;
1936 case V4L2_PIX_FMT_SBGGR16:
return 4;
1942 void cookedCopy(std::filesystem::path
const & src, std::filesystem::path
const & dst,
1943 std::string
const & name, std::string
const & vendor, std::string
const & synopsis,
1944 std::string
const & author, std::string
const & email, std::string
const & website,
1945 std::string
const & license, std::string
const & videomapping)
1947 std::ifstream f(src);
1948 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
1949 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
1963 std::ofstream ofs(dst);
1964 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
1965 ofs << str << std::endl;
1966 LINFO(
"Translated copy " << src <<
" => " << dst);
1970 void cookedCmakeClone(std::filesystem::path
const & src, std::filesystem::path
const & dst,
1971 std::string
const & oldname, std::string
const & newname,
1972 std::string
const & oldvendor, std::string
const & newvendor, std::string
const & synopsis,
1973 std::string
const & author, std::string
const & email, std::string
const & website,
1974 std::string
const & license, std::string
const & videomapping)
1976 std::ifstream f(src);
1977 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
1978 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
1993 std::ofstream ofs(dst);
1994 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
1995 ofs << str << std::endl;
1996 LINFO(
"Translated copy " << src <<
" => " << dst);
2000 void cookedCodeClone(std::filesystem::path
const & src, std::filesystem::path
const & dst,
2001 std::string
const & oldname, std::string
const & newname)
2003 std::ifstream f(src);
2004 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
2005 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
2023 std::ofstream ofs(dst);
2024 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
2025 ofs << str << std::endl;
2026 LINFO(
"Translated copy " << src <<
" => " << dst);
2033 float const fontw = ImGui::GetFontSize();
2035 static int templ = 0;
2037 ImGui::PushStyleColor(ImGuiCol_PopupBg, 0xf0e0ffe0);
2039 if (ImGui::Button(
"Create new machine vision module..."))
2041 ImGui::OpenPopup(
"Create new machine vision module");
2042 itsIdleBlocked =
true;
2046 ImVec2
const center = ImGui::GetMainViewport()->GetCenter();
2047 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
2048 ImGui::SetNextWindowContentSize(ImVec2(940, 750));
2050 if (ImGui::BeginPopupModal(
"Create new machine vision module", NULL, ImGuiWindowFlags_AlwaysAutoResize))
2054 static std::string name, vendor, synopsis, author, email, website, license, srcvendor, srcname;
2055 static int language = 0;
2056 static int ofmt = 0;
static int ow = 320, oh = 240;
static float ofps = 30.0F;
2057 static int cmode = 0;
2058 static int wdrmode = 0;
2059 static int cfmt = 0;
static int cw = 1920, ch = 1080;
static float cfps = 30.0F;
2060 static int c2fmt = 1;
static int c2w = 512, c2h = 288;
2063 ImGui::AlignTextToFramePadding();
2064 ImGui::Text(
"Fill out the details below, or clone from");
2067 static std::map<std::string, size_t> mods;
2068 static std::string currstr =
"...";
2074 if (ImGui::BeginCombo(
"##clonemodule", currstr.c_str()))
2076 for (
auto const & mod : mods)
2078 bool is_selected =
false;
2079 if (ImGui::Selectable(mod.first.c_str(), is_selected))
2081 m = e->getVideoMapping(mod.second);
2082 currstr = mod.first;
2088 { name =
"My" + m.
modulename + std::to_string(i++); }
2095 case jevois::CropType::CropScale: cmode = 0;
break;
2096 case jevois::CropType::Crop: cmode = 1;
break;
2097 case jevois::CropType::Scale: cmode = 2;
break;
2101 case jevois::WDRtype::Linear: wdrmode = 0;
break;
2102 case jevois::WDRtype::DOL: wdrmode = 1;
break;
2104 cfmt = get_v4l2_idx(m.
cfmt); cw = m.
cw; ch = m.
ch; cfps = m.
cfps;
2105 c2fmt = get_v4l2_idx(m.
c2fmt); c2w = m.
c2w; c2h = m.
c2h;
2115 ImGui::Columns(3,
"new module");
2117 newModEntry(
"##NewModname", name,
"Module Name",
"MyModule",
2118 "Required, even when cloning. Must start with an uppercase letter. "
2119 "Will be a folder name under /jevoispro/modules/VendorName");
2121 newModEntry(
"##NewModvendor", vendor,
"Vendor Name",
"MyVendor",
2122 "Required, even when cloning. Must start with an uppercase letter. "
2123 "Will be a folder name under /jevoispro/modules/");
2128 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2129 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2132 newModEntry(
"##NewModsynopsis", synopsis,
"Synopsis",
"Detect Object of type X",
2133 "Optional. Brief description of what the module does.");
2135 newModEntry(
"##NewModauthor", author,
"Author Name",
"John Smith",
"Optional");
2137 newModEntry(
"##NewModemail", email,
"Author Email",
"you@yourcompany.com",
"Optional");
2139 newModEntry(
"##NewModwebsite", website,
"Author Website",
"http://yourcompany.com",
"Optional");
2141 newModEntry(
"##NewModlicense", license,
"License",
"GPL v3",
"Optional");
2144 ImGui::AlignTextToFramePadding();
2145 ImGui::TextUnformatted(
"Module Language");
2146 ImGui::NextColumn();
2147 helpMarker(
"Module Language",
"Machine language to use for your module.");
2148 ImGui::NextColumn();
2149 ImGui::Combo(
"##NewModlanguage", &language,
"Python\0C++\0\0");
2150 ImGui::NextColumn();
2153 ImGui::AlignTextToFramePadding();
2154 ImGui::TextUnformatted(
"Module Template");
2155 ImGui::NextColumn();
2156 helpMarker(
"Module Template",
"Type of placeholder code that will be provided to get your module started.");
2157 ImGui::NextColumn();
2158 if (templ < 3) ImGui::Combo(
"##NewModtemplate", &templ,
"Pro/GUI\0Legacy\0Headless\0\0");
2159 else ImGui::Combo(
"##NewModtemplate", &templ,
"Pro/GUI\0Legacy\0Headless\0Clone\0\0");
2160 ImGui::NextColumn();
2163 int oflags = ImGuiInputTextFlags_None;
2166 oflags |= ImGuiInputTextFlags_ReadOnly;
2167 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2168 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2171 ImGui::AlignTextToFramePadding();
2172 ImGui::TextUnformatted(
"Module Output");
2173 ImGui::NextColumn();
2174 helpMarker(
"Module Output",
"Output video format for legacy module.");
2175 ImGui::NextColumn();
2176 ImGui::SetNextItemWidth(fontw * 5.0F);
2177 ImGui::Combo(
"##NewModofmt", &ofmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2179 ImGui::SetNextItemWidth(fontw * 4.0F);
2180 ImGui::InputInt(
"##NewModow", &ow, 0, 0, ImGuiInputTextFlags_CharsDecimal | oflags);
2184 ImGui::SetNextItemWidth(fontw * 4.0F);
2185 ImGui::InputInt(
"##NewModoh", &oh, 0, 0, ImGuiInputTextFlags_CharsDecimal | oflags);
2189 ImGui::SetNextItemWidth(fontw * 4.0F);
2190 ImGui::InputFloat(
"##NewModofps", &ofps, 0.0F, 0.0F,
"%.1f", ImGuiInputTextFlags_CharsDecimal | oflags);
2193 ImGui::NextColumn();
2197 ImGui::PopItemFlag();
2198 ImGui::PopStyleVar();
2202 ImGui::AlignTextToFramePadding();
2203 ImGui::TextUnformatted(
"Camera Mode");
2204 ImGui::NextColumn();
2205 helpMarker(
"Camera Mode",
"Camera sensor configuration for your module.");
2206 ImGui::NextColumn();
2207 ImGui::SetNextItemWidth(fontw * 18.0F);
2208 ImGui::Combo(
"##NewModcmode", &cmode,
"Dual-resolution (Crop+Scale)\0Single-resolution Crop\0"
2209 "Single-resolution Scale\0\0");
2210 ImGui::NextColumn();
2213 ImGui::AlignTextToFramePadding();
2214 ImGui::TextUnformatted(
"Camera WDR");
2215 ImGui::NextColumn();
2216 helpMarker(
"Camera WDR",
"Camera sensor wide-dynamic-range (WDR) setting for your module. Linear is for no WDR, "
2217 "DOL is for digital overlap (merging short and long exposure frames).");
2218 ImGui::NextColumn();
2219 ImGui::Combo(
"##NewModwdrmode", &wdrmode,
"Linear\0\0");
2221 ImGui::NextColumn();
2224 ImGui::AlignTextToFramePadding();
2225 ImGui::TextUnformatted(
"Camera Format");
2226 ImGui::NextColumn();
2227 helpMarker(
"Camera Format",
"Camera video format to use for input to module and for GUI display.");
2228 ImGui::NextColumn();
2229 ImGui::SetNextItemWidth(fontw * 5.0F);
2230 ImGui::Combo(
"##NewModcfmt", &cfmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2232 ImGui::SetNextItemWidth(fontw * 4.0F);
2233 ImGui::InputInt(
"##NewModcw", &cw, 0, 0, ImGuiInputTextFlags_CharsDecimal);
2237 ImGui::SetNextItemWidth(fontw * 4.0F);
2238 ImGui::InputInt(
"##NewModch", &ch, 0, 0, ImGuiInputTextFlags_CharsDecimal);
2242 ImGui::SetNextItemWidth(fontw * 4.0F);
2243 ImGui::InputFloat(
"##NewModcfps", &cfps, 0.0F, 0.0F,
"%.1f", ImGuiInputTextFlags_CharsDecimal);
2246 ImGui::NextColumn();
2249 int c2flags = ImGuiInputTextFlags_None;
2252 oflags |= ImGuiInputTextFlags_ReadOnly;
2253 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2254 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2257 ImGui::AlignTextToFramePadding();
2258 ImGui::TextUnformatted(
"Camera Format 2");
2259 ImGui::NextColumn();
2260 helpMarker(
"Camera Format 2",
"Camera video format for the second stream (for processing).");
2261 ImGui::NextColumn();
2262 ImGui::SetNextItemWidth(fontw * 5.0F);
2263 ImGui::Combo(
"##NewModc2fmt", &c2fmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2265 ImGui::SetNextItemWidth(fontw * 4.0F);
2266 ImGui::InputInt(
"##NewModc2w", &c2w, 0, 0, ImGuiInputTextFlags_CharsDecimal | c2flags);
2270 ImGui::SetNextItemWidth(fontw * 4.0F);
2271 ImGui::InputInt(
"##NewModc2h", &c2h, 0, 0, ImGuiInputTextFlags_CharsDecimal | c2flags);
2272 ImGui::NextColumn();
2276 ImGui::PopItemFlag();
2277 ImGui::PopStyleVar();
2282 ImGui::PopItemFlag();
2283 ImGui::PopStyleVar();
2287 ImGui::SetColumnWidth(0, fontw * 10.0F);
2288 ImGui::SetColumnWidth(1, ImGui::CalcTextSize(
"(?)").x + 30.0F);
2296 ImVec2
const button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
2297 if (ImGui::Button(
"Cancel", button_size))
2299 ImGui::CloseCurrentPopup();
2301 ImGui::PopStyleColor();
2302 itsIdleBlocked =
false;
2307 ImGui::SameLine(0, 540);
2310 if (ImGui::Button(
"Create", button_size))
2313 if (name.empty())
LFATAL(
"New Module cannot have an empty name.");
2314 if (name[0]<
'A' || name[0]>
'Z')
LFATAL(
"New Module name must start with an uppercase letter.");
2315 if (vendor.empty())
LFATAL(
"New Module cannot have empty vendor name.");
2316 LINFO(
"New Module data valid...");
2320 if (std::filesystem::exists(newvdir) ==
false && std::filesystem::create_directory(newvdir) ==
false)
2321 PLFATAL(
"Error creating dir " << newvdir <<
" -- check that you are running as root");
2322 std::filesystem::path
const newmdir = newvdir / name;
2330 std::filesystem::path srcpath = m.
srcpath();
2331 std::filesystem::path cmakepath = m.
cmakepath();
2339 srcname.c_str(), newmdir.c_str());
2341 LINFO(
"Cloned module using: " << copycmd);
2344 unlink((m.
path() +
'/' + srcname +
".C").c_str());
2345 unlink((m.
path() +
'/' + srcname +
".py").c_str());
2346 unlink((m.
path() +
'/' + srcname +
".so").c_str());
2347 std::filesystem::remove_all(m.
path() +
"/__pycache__");
2348 std::filesystem::remove_all(m.
path() +
"/build");
2351 std::ostringstream oss; oss << m; vmstr = oss.
str();
2352 cookedCodeClone(srcpath, m.srcpath(), srcname, name);
2357 if (std::filesystem::exists(cmakepath))
2358 cookedCmakeClone(cmakepath, m.cmakepath(), srcname, name, srcvendor, vendor, synopsis, author,
2359 email, website, license, vmstr);
2362 name, vendor, synopsis, author, email, website, license, vmstr);
2370 if (std::filesystem::exists(newmdir))
2371 LFATAL(
"Directory [" << newmdir <<
"] already exists -- Choose another name");
2372 if (std::filesystem::create_directory(newmdir) ==
false)
2373 PLFATAL(
"Error creating directory [" << newmdir <<
"] for new module. Maybe not running as root?");
2374 LINFO(
"Created new Module directory: " << newmdir);
2381 case 1: m.
ofmt = get_v4l2_fmt(ofmt); m.
ow = ow; m.
oh = oh; m.
ofps = ofps;
break;
2382 case 2: m.
ofmt = 0;
break;
2386 m.
cfmt = get_v4l2_fmt(cfmt);
2387 m.
cw = cw; m.
ch = ch; m.
cfps = cfps;
2394 case 0: m.
wdr = jevois::WDRtype::Linear;
break;
2395 case 1: m.
wdr = jevois::WDRtype::DOL;
break;
2401 case 0: m.
crop = jevois::CropType::CropScale;
2402 m.
c2fmt = get_v4l2_fmt(c2fmt);
2403 m.
c2w = c2w; m.
c2h = c2h;
2405 case 1: m.
crop = jevois::CropType::Crop;
break;
2406 case 2: m.
crop = jevois::CropType::Scale;
break;
2411 std::ostringstream oss; oss << m; vmstr = oss.
str();
2414 std::string code; std::string tname;
2418 tname =
"PyModule.py";
2427 std::filesystem::path dstcmak = m.cmakepath();
2428 cookedCopy(srccmak, dstcmak, name, vendor, synopsis, author, email, website, license, vmstr);
2432 default:
LFATAL(
"Invalid language " << language);
2436 std::filesystem::path dstmod = m.srcpath();
2437 cookedCopy(srcmod, dstmod, name, vendor, synopsis, author, email, website, license, vmstr);
2442 LINFO(
"Added videomapping: " << vmstr);
2449 if (language == 0) runNewModule();
2450 else itsCompileState = CompilationState::Start;
2453 name.clear(); vendor.clear(); synopsis.clear(); currstr =
"...";
2455 ImGui::CloseCurrentPopup();
2456 itsIdleBlocked =
false;
2459 catch (...) { reportAndIgnoreException(); }
2465 ImGui::PopStyleColor();
2472 size_t idx = 0;
size_t foundidx = 12345678;
2474 {
if (itsNewMapping.isSameAs(mm)) foundidx = idx; ++idx; });
2477 else LFATAL(
"Internal error, could not find the module we just created -- CHECK LOGS");
2479 itsRefreshVideoMappings =
true;
2484 else if (itsNewMapping.ofmt != 0 && itsNewMapping.ofmt !=
JEVOISPRO_FMT_GUI) itsVideoMappingListType = 1;
2485 else if (itsNewMapping.ofmt == 0) itsVideoMappingListType = 2;
2486 else LERROR(
"Internal error: cannot determine video mapping list type -- IGNORED");
2492#define L(i,x,y,z)for(F i=x;i<y;i+=z)
2493#define Q(y)sin((y+t)*.03)*(1-sin(t*3)*cos(y/99+t))*9
2494#define H(p,w)L(k,0,5,1)d->AddCircleFilled(p+V(1,-1)*w*k/8,w*(1-k/5),k<4?0xff000000+k*0x554400:-1);
2495#define J(b)L(i,0,h,1){TinyImGUIdemo&o=G[int(i)];if(b*o.z>0)H(o.p,(o.z*.3+4)*o.w)}
2496#define O(b)i=t+1.6+j/99;if(b*sin(i)>0)H(c+v*j+u*(cos(i)*40+Q(j)),30)
2498F w=0;
L(z,4,20,1){w+=z;
L(yy,-l,l,z*2){
F y=yy+fmod(t*z*10,z*2);
L(i,-1,2,2)d->AddCircle(c+v*y+u*i*(w+sin((y+t)/25)*w/30),z,0xff000000+0x110e00*
int(z*z*z/384),12,z/2);}}
2499h=0;
L(y,-l,l,15)
L(b,0,16,1){i=t+b*.2+y/99;
G[
h++]={c+v*y+u*(cos(i)*60+
Q(y)),sinf(i),(b<1||b>14)?2.f:1.5f};}std::sort(
G,
G+
h);
2500 F j=(-2+fmod(t*3,5))*99;
J(-1)
O(-1)a=c+v*-l;
L(y,-l,l,15){b=c+v*y+u*((15-rand())&31)*.1;
L(k,0,9,1)d->AddLine(a-v,b,k<8?0x11222200*k:-1,(9-k)*4);a=b;}
O(1)
J(1)}
2505 if (ImGui::Button(
"Open Style Editor")) itsShowStyleEditor =
true;
2507 if (ImGui::Button(
"Open App Metrics")) itsShowAppMetrics =
true;
2509 if (ImGui::Button(
"Open ImGui Demo")) itsShowImGuiDemo =
true;
2513 float camz = pixel_perfect_z;
2517 static float fudgex = 0.375f;
2518 static float fudgey = 0.375f;
2519 static float fudgez = 0.0f;
2520 unsigned short winw, winh; itsBackend.getWindowSize(winw, winh);
2522 ImGui::SliderFloat(
"OpenGL Camera z", &camz, -2.0f * winh, -1.0f);
2523 ImGui::SliderAngle(
"OpenGL yaw", &yaw, -179.0f, 180.0f);
2524 ImGui::SliderAngle(
"OpenGL pitch", &pitch, -179.0f, 180.0f);
2525 ImGui::SliderAngle(
"OpenGL roll", &roll, -179.0f, 180.0f);
2527 ImGui::SliderFloat(
"fudge x", &fudgex, -1.0f, 1.0f);
2528 ImGui::SliderFloat(
"fudge y", &fudgey, -1.0f, 1.0f);
2529 ImGui::SliderFloat(
"fudge z", &fudgez, -1.0f, 1.0f);
2532 proj = glm::perspective(glm::radians(45.0f),
float(winw) /
float(winh), 1.0f, winh * 2.0f);
2533 proj = glm::translate(proj, glm::vec3(fudgex, fudgey, fudgez));
2536 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, camz));
2537 view *= glm::yawPitchRoll(yaw, pitch, roll);
2553 ImGuiIO& io = ImGui::GetIO();
2554 ImGui::Begin(
"Tiny OpenGL demo", NULL, ImGuiWindowFlags_AlwaysAutoResize);
2555 ImVec2 size(320.0f, 180.0f);
2556 ImGui::InvisibleButton(
"canvas", size);
2557 ImVec2 p0 = ImGui::GetItemRectMin();
2558 ImVec2 p1 = ImGui::GetItemRectMax();
2559 ImDrawList* draw_list = ImGui::GetWindowDrawList();
2560 draw_list->PushClipRect(p0, p1);
2563 mouse_data.x = (io.MousePos.x - p0.x) / size.x;
2564 mouse_data.y = (io.MousePos.y - p0.y) / size.y;
2565 mouse_data.z = io.MouseDownDuration[0];
2566 mouse_data.w = io.MouseDownDuration[1];
2568 drawTinyImGUIdemo(draw_list, p0, p1, size, mouse_data, (
float)ImGui::GetTime());
2569 draw_list->PopClipRect();
2578 auto now = std::chrono::steady_clock::now();
2580 std::lock_guard<std::mutex> _(itsErrorMtx);
2583 for (
auto & e : itsErrors)
if (e.err == err) { e.lasttime = now;
return; }
2586 if (itsErrors.size() > 10)
return;
2587 else if (itsErrors.size() == 10)
2589 ErrorData d {
"Too many errors -- TRUNCATING", now, now };
2590 itsErrors.emplace(itsErrors.end(), std::move(d));
2596 itsErrors.emplace(itsErrors.end(), std::move(d));
2604 std::lock_guard<std::mutex> _(itsErrorMtx);
2614 catch (std::exception
const & e)
2615 { reportError(e.what()); }
2616 catch (boost::python::error_already_set & e)
2619 { reportError(
"Unknown error"); }
2624 catch (std::exception
const & e)
2625 { reportError(prefix +
": " + e.what()); }
2626 catch (boost::python::error_already_set & e)
2629 { reportError(prefix +
": Unknown error"); }
2636 reportAndIgnoreException(prefix);
2643 std::lock_guard<std::mutex> _(itsErrorMtx);
2644 if (itsErrors.empty())
return;
2646 ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
2647 ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNav;
2649 ImGui::SetNextWindowPos(ImVec2(10.0f, 10.0f), ImGuiCond_Always);
2650 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xc0e0e0ff);
2652 static bool show =
true;
2654 if (ImGui::Begin(
"Error detected!", &show, window_flags))
2656 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
2657 ImGui::Text(
"Error detected!");
2659 auto itr = itsErrors.begin();
2660 while (itr != itsErrors.end())
2663 std::chrono::duration<float> d = std::chrono::steady_clock::now() - itr->lasttime;
2664 std::chrono::duration<float> d2 = std::chrono::steady_clock::now() - itr->firsttime;
2665 if (d.count() >= 1.0f && d2.count() >= 10.0f && ImGui::IsWindowHovered() ==
false)
2666 itr = itsErrors.erase(itr);
2671 ImGui::TextUnformatted(itr->err.c_str());
2675 ImGui::PopTextWrapPos();
2679 ImGui::PopStyleColor();
2687 if (ImGui::IsItemHovered())
2689 ImGui::BeginTooltip();
2690 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
2691 ImGui::TextUnformatted(msg);
2692 if (msg2) { ImGui::Separator(); ImGui::TextUnformatted(msg2); }
2693 if (msg3) { ImGui::Separator(); ImGui::TextUnformatted(msg3); }
2694 ImGui::PopTextWrapPos();
2695 ImGui::EndTooltip();
2702 bool changed =
false;
2705 ImGui::PushID(name);
2706 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(4.0f/7.0f, 1.0f, 1.0f));
2707 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(4.0f/7.0f, 1.0f, 1.0f));
2708 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(4.0f/7.0f, 0.5f, 0.5f));
2709 if (ImGui::Button(name)) { *val =
false; changed =
true; }
2710 ImGui::PopStyleColor(3);
2713 else if (ImGui::Button(name)) { *val =
true; changed =
true; }
2721 unsigned short winw, winh;
2722 startFrame(winw, winh);
2724 if (itsHeadless.loaded() ==
false)
2729 cv::Mat blank(winh, winw, CV_8UC4, 0);
2730 itsHeadless.load(blank);
2733 if (itsHeadless.loaded()) itsHeadless.draw(ImVec2(0, 0), ImVec2(winw, winh), ImGui::GetBackgroundDrawList());
2741 ImGui::PushStyleColor(ImGuiCol_Text, 0xff0000ff);
2742 ImGui::TextUnformatted(str.c_str());
2743 ImGui::PopStyleColor();
2750 itsBannerTitle = title;
2757 if (itsCompileState == CompilationState::Cmake || itsCompileState == CompilationState::Make ||
2758 itsCompileState == CompilationState::Install || itsCompileState == CompilationState::CPack)
2759 reportError(
"Still compiling... Try again later...");
2760 else if (std::filesystem::exists(itsNewMapping.srcpath()) && std::filesystem::exists(itsNewMapping.cmakepath()))
2761 itsCompileState = CompilationState::Start;
2766 std::filesystem::path
const & fpath = itsCodeEditor->getLoadedFilePath();
2767 std::filesystem::path
const fn = fpath.filename();
2769 if (fn ==
"CMakeLists.txt" || fn.extension() ==
".C")
2771 itsNewMapping = { };
2772 std::filesystem::path p = fpath.parent_path();
2773 itsNewMapping.modulename = p.filename();
2774 itsNewMapping.vendor = p.parent_path().filename();
2775 itsNewMapping.ispython =
false;
2778 if (std::filesystem::exists(itsNewMapping.srcpath()) && std::filesystem::exists(itsNewMapping.cmakepath()))
2779 itsCompileState = CompilationState::Start;
2780 else reportError(
"Cannot find " + itsNewMapping.srcpath() +
" or " + itsNewMapping.cmakepath() +
" -- IGNORED");
2782 else reportError(
"Cannot compile " + fpath.string() +
" -- IGNORED");
2789 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xf0e0ffe0);
2791 ImGui::SetNextWindowSize(ImVec2(800, 680), ImGuiCond_FirstUseEver);
2794 int constexpr flags = ImGuiWindowFlags_HorizontalScrollbar;
2795 bool keep_window_open =
true;
2796 if (itsCompileState == CompilationState::Error) ImGui::Begin(
"C++ Module Compilation", &keep_window_open, flags);
2797 else ImGui::Begin(
"C++ Module Compilation",
nullptr, flags);
2799 ImGui::TextUnformatted((
"Compiling " + itsNewMapping.srcpath()).c_str());
2800 ImGui::TextUnformatted((
"Using " + itsNewMapping.cmakepath()).c_str());
2802 std::string
const modpath = itsNewMapping.path();
2803 std::string
const buildpath = modpath +
"/build";
2807 switch (itsCompileState)
2810 case CompilationState::Start:
2811 LINFO(
"Start compiling " << itsNewMapping.srcpath());
2812 itsIdleBlocked =
true;
2813 for (std::string & s : itsCompileMessages) s.clear();
2814 std::filesystem::remove_all(buildpath);
2815 itsCompileState = CompilationState::Cmake;
2820 std::filesystem::path sp(modpath +
"/rebuild.sh");
2822 std::ofstream ofs(sp);
2823 if (ofs.is_open() ==
false)
2824 reportError(
"Cannot write " + sp.string() +
" -- check that you are running as root.");
2828 ofs <<
"#!/bin/sh" << std::endl <<
"set -e" << std::endl;
2829 ofs <<
"cmake -S " << modpath <<
" -B " << buildpath <<
" -DJEVOIS_HARDWARE=PRO"
2830#ifdef JEVOIS_PLATFORM
2831 <<
" -DJEVOIS_PLATFORM=ON -DJEVOIS_NATIVE=ON"
2834 ofs <<
"JEVOIS_SRC_ROOT=none cmake --build " << buildpath << std::endl;
2835 ofs <<
"cmake --install " << buildpath << std::endl;
2836 ofs <<
"cd " << buildpath <<
2837 " && cpack && mkdir -p /jevoispro/debs && /bin/mv *.deb /jevoispro/debs/" << std::endl;
2841 using std::filesystem::perms;
2842 std::filesystem::permissions(sp, perms::owner_all | perms::group_read | perms::group_exec |
2843 perms::others_read | perms::others_exec);
2849 case CompilationState::Cmake:
2850 if (compileCommand(
"cmake -S " + modpath +
" -B " + buildpath +
2851 " -DJEVOIS_HARDWARE=PRO"
2852#ifdef JEVOIS_PLATFORM
2853 " -DJEVOIS_PLATFORM=ON -DJEVOIS_NATIVE=ON"
2855 , itsCompileMessages[0]))
2856 itsCompileState = CompilationState::Make;
2860 case CompilationState::Make:
2861 if (compileCommand(
"JEVOIS_SRC_ROOT=none cmake --build " + buildpath, itsCompileMessages[1]))
2862 itsCompileState = CompilationState::Install;
2866 case CompilationState::Install:
2867 if (compileCommand(
"cmake --install " + buildpath, itsCompileMessages[2]))
2868 itsCompileState = CompilationState::CPack;
2872 case CompilationState::CPack:
2873 if (compileCommand(
"cd " + buildpath +
" && cpack && mkdir -p /jevoispro/debs && /bin/mv *.deb /jevoispro/debs/",
2874 itsCompileMessages[3]))
2875 itsCompileState = CompilationState::Success;
2879 case CompilationState::Success:
2881 ImGui::TextUnformatted(
"Compilation success!");
2882 ImGui::TextUnformatted(
"See below for details...");
2884 static int run_default = 0;
2885 int ret = modal(
"Success! Run the module now?",
"Compilation success!\n\nA deb package of your module is in "
2886 "/jevoispro/debs/\nif you want to share it.\n\nLoad and run the new module now?",
2887 &run_default,
"Yes",
"No");
2892 itsIdleBlocked =
false;
2893 itsCompileState = CompilationState::Idle;
2898 itsIdleBlocked =
false;
2899 itsCompileState = CompilationState::Idle;
2901 itsRefreshVideoMappings =
true;
2909 case CompilationState::Error:
2911 itsIdleBlocked =
false;
2912 highlightText(
"Compilation failed!");
2913 ImGui::TextUnformatted(
"You may need to edit the two files above.");
2914 ImGui::TextUnformatted(
"See below for details...");
2916 static bool show_modal =
false;
2918 ImGui::AlignTextToFramePadding();
2919 if (ImGui::Button(
"Edit CMakeLists.txt"))
2920 { itsCodeEditor->loadFile(itsNewMapping.cmakepath()); show_modal =
true; }
2922 ImGui::SameLine(); ImGui::Text(
" "); ImGui::SameLine();
2923 if (ImGui::Button((
"Edit " + itsNewMapping.modulename +
".C").c_str()))
2924 { itsCodeEditor->loadFile(itsNewMapping.srcpath()); show_modal =
true; }
2926 ImGui::SameLine(); ImGui::Text(
" "); ImGui::SameLine();
2927 if (ImGui::Button(
"Compile again")) itsCompileState = CompilationState::Start;
2933 static int doit_default = 0;
2934 int ret = modal(
"Ready to edit",
"File will now be loaded in the Code tab of the main window and "
2935 "ready to edit. Please switch to the Code tab in the main window.\n\n"
2936 "When you save it, we will try to compile it again.",
2937 &doit_default,
"Close Compilation Window",
"Keep Open");
2940 case 1: show_modal =
false; itsCompileState = CompilationState::Idle;
break;
2941 case 2: show_modal =
false;
break;
2950 LERROR(
"Internal error: invalid compilation state " <<
int(itsCompileState) <<
" -- RESET TO IDLE");
2951 itsCompileState = CompilationState::Idle;
2952 itsIdleBlocked =
false;
2954 }
catch (...) { reportAndIgnoreException(); }
2957 for (std::string & s : itsCompileMessages)
2958 if (s.empty() ==
false)
2960 ImGui::TextUnformatted(s.c_str());
2965 ImGui::PopStyleColor();
2968 if (keep_window_open ==
false) { itsIdleBlocked =
false; itsCompileState = CompilationState::Idle; }
2975 if (itsCompileFut.valid() ==
false)
2978 msg =
"Running: " + cmd +
"\nPlease wait ...\n";
2979 LINFO(
"Running: " + cmd);
2981 else if (itsCompileFut.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready)
2984 msg += itsCompileFut.get() +
"\nSuccess!";
2985 LINFO(
"Success running: " << cmd);
2990 LERROR(
"Failed running: " << cmd);
2991 itsCompileState = CompilationState::Error;
#define JEVOIS_MODULE_PATH
Base path for modules.
#define JEVOIS_CUSTOM_DNN_URL
URL where custom converted DNN models can be downloaded:
#define JEVOIS
Helper string that evaluates to "jevois" or "jevoispro" depending on values of JEVOIS_A33 and JEVOIS_...
#define JEVOIS_VERSION_STRING
Software version, as string.
#define JEVOIS_CUSTOM_DNN_PATH
Directory where custom DNN models are stored:
#define JEVOISPRO_GSERIAL_FILE
Flag file for whether to enable g_serial at boot on jevoispro.
#define JEVOIS_SHARE_PATH
Base path for shared files (e.g., neural network weights, etc)
#define JEVOIS_PYDNN_PATH
Directory where python pre/net/post DNN processors are stored:
#define JEVOIS_ROOT_PATH
Root path for runtime jevois config files, videomappings.cfg, modules, etc.
void drawTinyImGUIdemo(ImDrawList *d, V a, V b, V, ImVec4, F t)
#define JEVOIS_WAIT_GET_FUTURE(f)
Wait for a future to become ready for 5 seconds, get(), warn and ignore exception,...
#define JEVOISPRO_FMT_GUI
JeVois-Pro zero-copy display of camera input frame (to be used as output mode in VideoMapping)
A component of a model hierarchy.
void setParamValUnique(std::string const ¶mdescriptor, T const &val)
Set a parameter value, simple version assuming only one parameter match.
void foreachParam(std::function< void(std::string const &compname, ParameterBase *p)> func, std::string const &cname="")
Run a function on every param we hold.
std::string getParamStringUnique(std::string const ¶mdescriptor) const
Get a parameter value by string, simple version assuming only one parameter match.
void setParamStringUnique(std::string const ¶mdescriptor, std::string const &val)
Set a parameter value by string, simple version assuming only one parameter match.
T getParamValUnique(std::string const ¶mdescriptor) const
Get a parameter value, simple version assuming only one parameter match.
JeVois processing engine - gets images from camera sensor, processes them, and sends results over USB...
void requestSetFormat(int idx)
Use this to request a format change from within process()
void drawCameraGUI()
Draw all camera controls into our GUI.
void nextDemo()
When in demo mode, switch to next demo.
std::shared_ptr< Module > module() const
Get a pointer to our current module (may be null)
void abortDemo()
When in demo mode, abort demo mode.
void quit()
Terminate the program.
VideoMapping const & getCurrentVideoMapping() const
Get the current video mapping.
void reloadVideoMappings()
Re-load video mappings from videomappings.cfg.
void foreachVideoMapping(std::function< void(VideoMapping const &m)> &&func)
Run a function on every video mapping.
Class to hold a GPUtexture, GPUprogram, and other data associated with rendering an image in OpenGL.
ImVec2 i2ds(ImVec2 const &p)
Convert a 2D size from within a rendered image to on-screen.
ImVec2 i2d(ImVec2 const &p)
Convert coordinates of a point from within a rendered image to on-screen.
ImVec2 d2i(ImVec2 const &p)
Convert coordinates of a point from on-screen to within a rendered image.
ImVec2 d2is(ImVec2 const &p)
Convert a 2D size from on-screen to within a rendered image.
Simple console with coloring and completion.
void draw()
Render into ImGui.
Editor panel for JeVois-Pro GUI.
void drawCircle(float x, float y, float r, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
Draw circle over an image.
void endFrame()
Finish current frame and render it.
bool seroutEnabled() const
Tell whether user enabled serout messages to GUI console.
bool combo(std::string const &name, std::vector< std::string > const &items, int &selected_index)
Helper to draw a combobox from a vector of strings.
void resetstate(bool modulechanged=true)
Reset to default state, typically called on Module or video format change.
std::shared_ptr< GUIeditor > itsCfgEditor
ImVec2 iline(int line=-1, char const *name=nullptr)
Get coordinates of the start of a given line of text to be drawn as overlay on top of an image.
void reportAndIgnoreException(std::string const &prefix="")
Report current exception in a modal dialog, then ignore it.
void drawInputFrame(char const *name, InputFrame const &frame, int &x, int &y, unsigned short &w, unsigned short &h, bool noalias=false, bool casync=false)
Draw the input video frame from the camera using zero-copy.
bool startFrame(unsigned short &w, unsigned short &h)
Start a new rendering frame.
ImVec2 i2ds(ImVec2 p, char const *name=nullptr)
Convert a 2D size from within a rendered image to on-screen.
void drawText(float x, float y, char const *txt, ImU32 col=IM_COL32(128, 255, 128, 255))
Draw text over an image.
virtual ~GUIhelper()
Destructor.
void drawRect(float x1, float y1, float x2, float y2, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
Draw rectangular box over an image.
void onParamChange(gui::scale const ¶m, float const &newval) override
bool frameStarted() const
Helper to indicate that startFrame() was called, and thus endFrame() should be called.
void startCompilation()
Compile a newly created module.
void drawInputFrame2(char const *name, InputFrame const &frame, int &x, int &y, unsigned short &w, unsigned short &h, bool noalias=false, bool casync=false)
Draw the second (scaled) input video frame from the camera using zero-copy.
std::shared_ptr< GUIeditor > itsCodeEditor
void clearErrors()
Clear all errors currently displayed in the JeVois-Pro GUI.
void newModEntry(char const *wname, std::string &str, char const *desc, char const *hint, char const *hlp)
void releaseImage(char const *name)
Release an image.
void iinfo(jevois::InputFrame const &inframe, std::string const &fpscpu, unsigned short winw=0, unsigned short winh=0)
Display processing and video info at bottom of screen.
void helpMarker(char const *msg, char const *msg2=nullptr, char const *msg3=nullptr)
Display a (?) label and show tooltip when it is hovered.
void demoBanner(std::string const &title="", std::string const &msg="")
Display some text in a big banner, used by demo mode.
void highlightText(std::string const &str)
Like ImGui::Textunformatted but in a highlight color (typically, red)
void reportError(std::string const &err)
Report an error in an overlay window.
void headlessDisplay()
Show a message that we are running headless.
ImVec2 i2d(ImVec2 p, char const *name=nullptr)
Convert coordinates of a point from within a rendered image to on-screen.
void reportAndRethrowException(std::string const &prefix="")
Report current exception in a modal dialog, then re-throw it.
bool idle() const
Check for idle in case startFrame() was called elsewhere.
ImVec2 d2is(ImVec2 p, char const *name=nullptr)
Convert a 2D size from on-screen to within a rendered image.
void drawLine(float x1, float y1, float x2, float y2, ImU32 col=IM_COL32(128, 255, 128, 255))
Draw line over an image.
void itext(char const *txt, ImU32 const &col=IM_COL32_BLACK_TRANS, int line=-1)
Draw some overlay text on top of an image.
void releaseImage2(char const *name)
Release an image, second video stream.
ImU32 applyFillAlpha(ImU32 col) const
int modal(std::string const &title, char const *text, int *default_val=nullptr, char const *b1txt="Ok", char const *b2txt="Cancel")
Helper to draw a modal with 2 choices.
void drawPoly(std::vector< cv::Point > const &pts, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
Draw polygon over an image.
void drawPolyInternal(ImVec2 const *pts, size_t npts, ImU32 col, bool filled)
void setparstr(std::string const &descriptor, std::string const &val)
std::string itsWindowTitle
bool compileCommand(std::string const &cmd, std::string &msg)
GUIhelper(std::string const &instance, bool conslock=false)
Constructor.
ImVec2 d2i(ImVec2 p, char const *name=nullptr)
Convert coordinates of a point from on-screen to within a rendered image.
bool toggleButton(char const *name, bool *val)
Helper to draw a toggle button.
void drawImage(char const *name, RawImage const &img, int &x, int &y, unsigned short &w, unsigned short &h, bool noalias=false, bool isoverlay=false)
Draw a RawImage, copying pixel data to an OpenGL texture.
bool serlogEnabled() const
Tell whether user enabled serlog messages to GUI console.
Simple class to monitor a serial port in the JeVois-Pro GUI.
std::shared_ptr< Comp > getComponent(std::string const &instanceName) const
Get a top-level component by instance name.
Base class for Parameter.
virtual ParameterSummary const summary() const =0
Get summary info about this parameter.
ParameterSummary provides a summary about a parameter.
std::string name
Plain name of the parameter.
std::string category
Category of the parameter, as a string.
T const & min() const
Return the minimum value.
T const & max() const
Return the maximum value.
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
unsigned int fmt
Pixel format as a V4L2_PIX_FMT_XXX.
size_t bufindex
The index of the data buffer in the kernel driver.
unsigned int width
Image width in pixels.
unsigned int height
Image height in pixels.
Base class for a module that supports standardized serial messages.
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
std::string getSysInfoCPU()
Get CPU info: frequency, thermal, load.
std::string warnAndIgnoreException(std::string const &prefix="")
Convenience function to catch an exception, issue some LERROR (depending on type),...
#define PLFATAL(msg)
Like LDEBUG but appends errno and strerror(errno), to be used when some system call fails.
std::string getSysInfoMem()
Get memory info.
std::string getSysInfoVersion()
Get O.S. version info.
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
std::string getPythonExceptionString(boost::python::error_already_set &)
Python exception translation to string so we can print the traceback to our serlog stream.
std::string shapestr(cv::Mat const &m)
Get a string of the form: "nD AxBxC... TYPE" from an n-dimensional cv::Mat with data type TYPE.
void paramStringToVal(std::string const &valstring, T &result)
Machine-readable conversion from string to T, for use in jevois::Parameter.
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async(Function &&f, Args &&... args)
Async execution using a thread pool.
std::string join(std::vector< std::string > const &strings, std::string const &delimiter)
Concatenate a vector of tokens into a string.
std::string extractString(std::string const &str, std::string const &startsep, std::string const &endsep)
Extract a portion of a string between two delimiters.
std::string tolower(std::string const &str)
Convert string to lowercase.
std::string getFileString(char const *fname, int skip=0)
Read one line from a file and return it as a string.
std::string system(std::string const &cmd, bool errtoo=true)
Execute a command and grab stdout output to a string.
std::string sformat(char const *fmt,...) __attribute__((format(__printf__
Create a string using printf style arguments.
size_t replaceStringAll(std::string &str, std::string const &from, std::string const &to)
Replace all instances of 'from' with 'to'.
bool stringStartsWith(std::string const &str, std::string const &prefix)
Return true if str starts with prefix (including if both strings are equal)
std::string fccstr(unsigned int fcc)
Convert a V4L2 four-cc code (V4L2_PIX_FMT_...) to a 4-char string.
std::vector< std::string > split(std::string const &input, std::string const ®ex="\\s+")
Split string into vector of tokens using a regex to specify what to split on; default regex splits by...
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async_little(Function &&f, Args &&... args)
Async execution using a thread pool.
Main namespace for all JeVois classes and functions.
size_t getNumInstalledVPUs()
Get the number of Myriad-X VPUs present on this system.
int getFanSpeed()
Get fan speed in percent, only meaningful on JeVois-Pro Platform, all others return 0.
size_t getNumInstalledNPUs()
Get the number of JeVois-Pro NPUs present on this system.
size_t getNumInstalledTPUs()
Get the number of Coral TPUs present on this system.
size_t getNumInstalledSPUs()
Get the number of Hailo8 SPUs present on this system.
bool operator<(TinyImGUIdemo &o)
Simple struct to hold video mapping definitions for the processing Engine.
WDRtype wdr
Type of wide-dynamic-range (WDR) to use, if sensor supports it.
unsigned int cfmt
camera pixel format
unsigned int ow
output width
unsigned int c2fmt
When crop is CropScale, pixel format of the scaled images, otherwise 0.
std::string modinfopath() const
Return the full absolute path and file name of the module's modinfo.html file.
unsigned int c2w
When crop is CropScale, width of the scaled images, otherwise 0.
CropType crop
Type of crop/scale to apply if camera size does not match sensor native.
std::string modulename
Name of the Module that will process this mapping.
std::string str() const
Convenience function to print out the whole mapping in a human-friendly way.
float cfps
camera frame rate in frames/sec
bool ispython
True if the module is written in Python; affects behavior of sopath() only.
std::string menustr2() const
Convenience function to print out the whole mapping in a human-friendly way to be used in a menu.
std::string path() const
Return the full absolute path the module's directory.
unsigned int cw
camera width
float ofps
output frame rate in frames/sec
unsigned int c2h
When crop is CropScale, height of the scaled images, otherwise 0.
unsigned int ch
camera height
unsigned int oh
output height
std::string srcpath() const
Return the full absolute path and file name of the module's .C or .py file.
std::string menustr() const
Convenience function to print out the whole mapping in a human-friendly way to be used in a menu.
std::string vendor
Module creator name, used as a directory to organize the modules.
std::string cmakepath() const
Return the full absolute path and file name of the module's CMakeLists.txt file.
unsigned int ofmt
output pixel format, or 0 for no output over USB