22#define IMGUI_DEFINE_MATH_OPERATORS
24#include <imgui_internal.h>
37#include <glm/gtc/matrix_transform.hpp>
38#include <glm/gtx/euler_angles.hpp>
49 if (winsize::get().width == 0)
52 int w = 1920,
h = 1080;
56 std::vector<std::string>
const tok =
jevois::split(ws,
"\\s*[,;x]\\s*");
57 if (tok.size() == 2) { w = std::stoi(tok[0]);
h = std::stoi(tok[1]) / 2; }
58 LINFO(
"Detected framebuffer size: " << w <<
'x' <<
h);
62 winsize::set(cv::Size(w,
h));
68 std::vector<EditorItem> fixedcfg
70 {
JEVOIS_ROOT_PATH "/config/videomappings.cfg",
"JeVois videomappings.cfg", EditorSaveAction::RefreshMappings },
71 {
JEVOIS_ROOT_PATH "/config/initscript.cfg",
"JeVois initscript.cfg", EditorSaveAction::Reboot },
72 {
"params.cfg",
"Module's params.cfg", EditorSaveAction::Reload },
73 {
"script.cfg",
"Module's script.cfg", EditorSaveAction::Reload },
75 "JeVois models.yml DNN Zoo Root", EditorSaveAction::Reload },
77 "JeVois opencv.yml DNN Zoo for OpenCV models", EditorSaveAction::Reload },
79 "JeVois npu.yml DNN Zoo for A311D NPU models", EditorSaveAction::Reload },
81 "JeVois spu.yml DNN Zoo for Hailo SPU models", EditorSaveAction::Reload },
83 "JeVois tpu.yml DNN Zoo for Coral TPU models", EditorSaveAction::Reload },
85 "JeVois vpu.yml DNN Zoo for Myriad-X VPU models", EditorSaveAction::Reload },
87 "JeVois ort.yml DNN Zoo for ONNX-Runtime CPU models", EditorSaveAction::Reload },
92 {
".yaml",
".yml" }));
95 std::vector<EditorItem> fixedcode
97 {
"*",
"Module's source code", EditorSaveAction::Reload },
103 {
".py",
".C",
".H",
".cpp",
".hpp",
".c",
".h",
".txt" }));
116 itsEndFrameCalled =
true;
119 itsLastDrawnImage =
nullptr;
120 itsLastDrawnTextLine = -1;
131 itsCfgEditor->refresh();
132 itsCodeEditor->refresh();
137 std::lock_guard<std::mutex> _(itsErrorMtx);
143 itsBackend.getWindowSize(w,
h);
145 if (w == 0)
LFATAL(
"Need to call startFrame() at least once first");
147 float const fov_y = 45.0f;
149 proj = glm::perspective(glm::radians(fov_y),
float(w) /
float(
h), 1.0f,
h * 2.0f);
150 const_cast<float &
>(pixel_perfect_z) = -
float(
h) / (2.0 * tan(fov_y * M_PI / 360.0));
151#ifdef JEVOIS_PLATFORM
153 proj = glm::translate(proj, glm::vec3(0.375f, 0.375f, 0.0f));
155 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, pixel_perfect_z));
158 style::set(style::get());
165 if (std::filesystem::exists(m.
cmakepath())) itsNewMapping = m;
171 if (itsEndFrameCalled ==
false)
LFATAL(
"You need to call endFrame() at the end of your process() function");
174 itsBackend.getWindowSize(w,
h);
179 cv::Size
const siz = winsize::get();
180 bool const fs = fullscreen::get();
181 LINFO(
"OpenGL init " << siz.width <<
'x' << siz.height << (fs ?
" fullscreen" :
""));
182 itsBackend.init(siz.width, siz.height, fs, scale::get(), itsConsLock);
183 rounding::set(
int(rounding::get() * scale::get() + 0.499F));
186 unsigned short winw, winh; itsBackend.getWindowSize(winw, winh); winsize::set(cv::Size(winw, winh));
187 winsize::freeze(
true);
188 fullscreen::freeze(
true);
195 bool shouldclose =
false;
auto const now = std::chrono::steady_clock::now();
196 if (itsBackend.pollEvents(shouldclose)) itsLastEventTime = now;
198 if (shouldclose && allowquit::get())
200 LINFO(
"Closing down on user request...");
205 itsBackend.newFrame();
212 float const hs = hidesecs::get();
215 std::chrono::duration<float> elapsed = now - itsLastEventTime;
216 itsIdle = (elapsed.count() >= hs);
218 else itsIdle =
false;
221 itsEndFrameCalled =
false;
233 float oldval = param.get();
234 if (newval == oldval)
return;
236 ImGui::GetStyle().ScaleAllSizes(newval / oldval);
237 ImGui::GetIO().FontGlobalScale = newval;
238 ImGui::GetStyle().MouseCursorScale = 2.0f;
241 if (oldval) rounding::set(std::min(24,
int(rounding::get() * newval / oldval + 0.499F)));
249 case jevois::gui::GuiStyle::Dark:
250 ImGui::StyleColorsDark();
251 itsCfgEditor->SetPalette(TextEditor::GetDarkPalette());
252 itsCodeEditor->SetPalette(TextEditor::GetDarkPalette());
255 case jevois::gui::GuiStyle::Light:
256 ImGui::StyleColorsLight();
257 ImGui::GetStyle().Colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 0.92f);
258 itsCfgEditor->SetPalette(TextEditor::GetLightPalette());
259 itsCodeEditor->SetPalette(TextEditor::GetLightPalette());
262 case jevois::gui::GuiStyle::Classic:
263 ImGui::StyleColorsClassic();
264 itsCfgEditor->SetPalette(TextEditor::GetRetroBluePalette());
265 itsCodeEditor->SetPalette(TextEditor::GetRetroBluePalette());
273 auto & s = ImGui::GetStyle();
274 s.WindowRounding = newval;
275 s.ChildRounding = newval;
276 s.FrameRounding = newval;
277 s.PopupRounding = newval;
278 s.ScrollbarRounding = newval;
279 s.GrabRounding = newval;
284{
return (itsEndFrameCalled ==
false); }
288 unsigned short & w,
unsigned short &
h,
bool noalias,
bool isoverlay)
291 std::string
const imgname = name + std::to_string(img.
bufindex);
294 auto & im = itsImages[imgname];
300 im.draw(x, y, w,
h, noalias, proj * view);
303 if (isoverlay ==
false)
305 itsLastDrawnImage = & im;
306 itsUsingScaledImage =
false;
307 itsLastDrawnTextLine = -1;
313 unsigned short & w,
unsigned short &
h,
bool noalias,
bool isoverlay)
316 auto & im = itsImages[name];
322 im.draw(x, y, w,
h, noalias, proj * view);
325 if (isoverlay ==
false)
327 itsLastDrawnImage = & im;
328 itsUsingScaledImage =
false;
329 itsLastDrawnTextLine = -1;
335 unsigned short & w,
unsigned short &
h,
bool noalias,
bool casync)
339 std::string
const imgname = name + std::to_string(img.
bufindex);
342 auto & im = itsImages[imgname];
346 im.set(frame, itsBackend.getDisplay());
349 im.draw(x, y, w,
h, noalias, proj * view);
352 itsLastDrawnImage = & im;
354 itsLastDrawnTextLine = -1;
355 if (itsUsingScaledImage)
358 itsScaledImageFacX = float(img.
width) / float(img2.
width);
359 itsScaledImageFacY = float(img.
height) / float(img2.
height);
365 unsigned short & w,
unsigned short &
h,
bool noalias,
bool casync)
369 std::string
const imgname = name + std::to_string(img.
bufindex);
372 auto & im = itsImages2[imgname];
376 im.set2(frame, itsBackend.getDisplay());
379 im.draw(x, y, w,
h, noalias, proj * view);
382 itsLastDrawnImage = & im;
383 itsUsingScaledImage =
false;
384 itsLastDrawnTextLine = -1;
393 itsGlobalAlpha = std::abs(1.0F - newval / 15.0F);
396 for (
auto & ip : itsImages) ip.second.twirl(newval);
407 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
408 img = itsLastDrawnImage;
412 std::string nstr = name;
413 auto itr = itsImages.find(nstr);
414 if (itr == itsImages.end())
418 itr = itsImages.find(nstr +
'0');
419 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
425 if (itsUsingScaledImage) { p.x *= itsScaledImageFacX; p.y *= itsScaledImageFacY; }
433{
return i2d(ImVec2(x, y), name); }
443 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
444 img = itsLastDrawnImage;
448 std::string nstr = name;
449 auto itr = itsImages.find(nstr);
450 if (itr == itsImages.end())
454 itr = itsImages.find(nstr +
'0');
455 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
461 if (itsUsingScaledImage) { p.x *= itsScaledImageFacX; p.y *= itsScaledImageFacY; }
469{
return i2ds(ImVec2(x, y), name); }
474 ImGui::GetBackgroundDrawList()->AddLine(i2d(x1, y1), i2d(x2, y2), col, linethick::get());
480 auto dlb = ImGui::GetBackgroundDrawList();
481 ImVec2
const tl = i2d(x1, y1);
482 ImVec2
const br = i2d(x2, y2);
484 if (filled) dlb->AddRectFilled(tl, br, applyFillAlpha(col));
485 ImDrawFlags
constexpr flags = ImDrawFlags_None;
486 float constexpr rounding = 0.0F;
488 dlb->AddRect(tl, br, col, rounding, flags, 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 auto dlb = ImGui::GetBackgroundDrawList();
615 ImVec2
const center = i2d(x, y);
616 ImVec2
const rad = i2ds(rx, ry);
618 if (filled) dlb->AddEllipseFilled(center, rad, applyFillAlpha(col), rot, 0 );
620 dlb->AddEllipse(center, rad, col, rot, 0 , linethick::get());
626 ImGui::GetBackgroundDrawList()->AddText(i2d(x, y), col, txt);
632 drawText(x, y, txt.c_str(), col);
638 unsigned char alpha = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT;
639 alpha = (
unsigned char)(fillalpha::get() * alpha);
640 return (col & ~IM_COL32_A_MASK) | (alpha << IM_COL32_A_SHIFT);
646 if (line == -1) line = ++itsLastDrawnTextLine;
else itsLastDrawnTextLine = line;
647 ImVec2 p = i2d(0, 0, name);
649 p.y += 5.0F + (ImGui::GetFontSize() + 5.0F) * line;
656 ImU32
const c = (col == IM_COL32_BLACK_TRANS) ? ImU32(overlaycolor::get()) : col;
657 ImGui::GetBackgroundDrawList()->AddText(iline(line), c, txt);
663 itext(txt.c_str(), col, line);
668 unsigned short winw,
unsigned short winh)
670 unsigned short ww, wh;
671 if (winw == 0 || winh == 0) itsBackend.getWindowSize(ww, wh);
else { ww = winw; wh = winh; }
680 std::string
const msg =
jevois::sformat(
"%s, Camera: %s:%dx%d%s, Display: RGBA:%dx%d", fpscpu.c_str(),
682 cam2str.c_str(), ww, wh);
684 ImGui::GetBackgroundDrawList()->AddText(ImVec2(10, wh-10-ImGui::GetFontSize()), overlaycolor::get(), msg.c_str());
690 auto itr = itsImages.find(name);
691 if (itr != itsImages.end()) itsImages.erase(itr);
697 auto itr = itsImages2.find(name);
698 if (itr != itsImages2.end()) itsImages2.erase(itr);
706 float fx = 1.0F, fy = 1.0F;
710 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
711 img = itsLastDrawnImage;
712 if (itsUsingScaledImage) { fx = 1.0F / itsScaledImageFacX; fy = 1.0F / itsScaledImageFacY; }
716 std::string nstr = name;
717 auto itr = itsImages.find(nstr);
718 if (itr == itsImages.end())
722 itr = itsImages.find(nstr +
'0');
723 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
729 ImVec2 ret = img->
d2i(p);
730 ret.x *= fx; ret.y *= fy;
736{
return d2i(ImVec2(x, y), name); }
743 float fx = 1.0F, fy = 1.0F;
747 if (itsLastDrawnImage ==
nullptr)
throw std::range_error(
"You need to call drawImage() or drawInputFrame() first");
748 img = itsLastDrawnImage;
749 if (itsUsingScaledImage) { fx = 1.0F / itsScaledImageFacX; fy = 1.0F / itsScaledImageFacY; }
753 std::string nstr = name;
754 auto itr = itsImages.find(nstr);
755 if (itr == itsImages.end())
759 itr = itsImages.find(nstr +
'0');
760 if (itr == itsImages.end())
throw std::range_error(
"No previously drawn image with name [" + nstr +
"] found");
766 ImVec2 ret = img->
d2is(p);
767 ret.x *= fx; ret.y *= fy;
773{
return d2is(ImVec2(x, y), name); }
779 ImGui::GetIO().MouseDrawCursor = ! itsIdle;
782 if (itsIdle ==
false) drawJeVoisGUI();
785 if (itsCompileState != CompilationState::Idle) compileModule();
788 if (itsGlobalAlpha != 1.0F)
790 if (itsGlobalAlpha < 0.0F || itsGlobalAlpha > 1.0F)
792 LERROR(
"Invalid global alpha " << itsGlobalAlpha <<
" -- RESET TO 1.0");
793 itsGlobalAlpha = 1.0F;
797 auto dlb = ImGui::GetBackgroundDrawList();
798 cv::Size
const ws = winsize::get();
799 dlb->AddRectFilled(ImVec2(0, 0), ImVec2(ws.width, ws.height), ImColor(0.0F, 0.0F, 0.0F, 1.0F - itsGlobalAlpha));
804 if (itsBannerTitle.empty() ==
false)
806 ImGui::SetNextWindowPos(ImVec2(800, 500));
807 ImGui::SetNextWindowSize(ImVec2(1000, 400));
808 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xf0e0ffe0);
809 ImGui::Begin(
"JeVois-Pro Demo Mode",
nullptr, ImGuiWindowFlags_NoResize |
810 ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse |
811 ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings);
812 ImGui::SetWindowFontScale(1.5F);
813 ImGui::TextUnformatted(
" ");
814 ImGui::TextUnformatted(itsBannerTitle.c_str());
815 ImGui::TextUnformatted(
" ");
816 ImGui::SetWindowFontScale(1.0F);
818 int wrap = ImGui::GetWindowSize().x - ImGui::GetFontSize() * 2.0f;
819 ImGui::PushTextWrapPos(wrap);
820 ImGui::TextUnformatted(itsBannerMsg.c_str());
821 ImGui::PopTextWrapPos();
823 ImGui::SetCursorPosY(ImGui::GetWindowSize().y - ImGui::CalcTextSize(
"X").y * 2.3F);
826 if (ImGui::Button(
"Skip to Next Demo")) engine()->
nextDemo();
827 ImGui::SetItemDefaultFocus();
828 ImGui::SameLine(600);
829 if (ImGui::Button(
"Abort Demo Mode")) engine()->
abortDemo();
831 ImGui::PopStyleColor();
837 itsEndFrameCalled =
true;
844 ImGui::SetNextWindowPos(ImVec2(920, 358), ImGuiCond_FirstUseEver);
845 ImGui::SetNextWindowSize(ImVec2(941, 639), ImGuiCond_FirstUseEver);
847 if (ImGui::Begin(itsWindowTitle.c_str(),
nullptr ))
855 if (ImGui::BeginTabBar(
"##tabs", ImGuiTabBarFlags_None))
858 if (ImGui::BeginTabItem(
"Info"))
864 if (ImGui::BeginTabItem(
"Parameters"))
870 if (ImGui::BeginTabItem(
"Console"))
876 if (ImGui::BeginTabItem(
"Camera"))
882 if (ImGui::BeginTabItem(
"Config"))
884 itsCfgEditor->draw();
888 if (ImGui::BeginTabItem(
"Code"))
890 itsCodeEditor->draw();
894 if (ImGui::BeginTabItem(
"System"))
900 if (ImGui::BeginTabItem(
"Tweaks"))
912 if (itsShowStyleEditor)
914 ImGui::Begin(
"GUI Style Editor", &itsShowStyleEditor);
915 ImGui::ShowStyleEditor();
918 if (itsShowAppMetrics) ImGui::ShowMetricsWindow(&itsShowAppMetrics);
919 if (itsShowImGuiDemo) ImGui::ShowDemoWindow(&itsShowImGuiDemo);
922 if (itsShowHardSerialWin)
925 ImGui::SetNextWindowSize(ImVec2(700, 500), ImGuiCond_FirstUseEver);
928 ImGui::Begin(
"Hardware 4-pin Serial Monitor", &itsShowHardSerialWin);
932 ImGui::TextUnformatted(
"No Hardware serial port found!");
934 ImGui::TextUnformatted(
"Check engine:serialdev parameter, and");
935 ImGui::TextUnformatted(
"that engine:serialmonitors is true.");
941 if (itsShowUsbSerialWin)
944 ImGui::SetNextWindowSize(ImVec2(700, 500), ImGuiCond_FirstUseEver);
947 ImGui::Begin(
"USB Serial Monitor", &itsShowUsbSerialWin);
951 ImGui::TextUnformatted(
"No USB serial port found!");
953 ImGui::TextUnformatted(
"Check engine:usbserialdev parameter, and");
954 ImGui::TextUnformatted(
"that engine:serialmonitors is true.");
966 if (ImGui::BeginMenuBar())
968 if (ImGui::BeginMenu(
"File"))
970 if (ImGui::MenuItem(
"Quit")) engine()->
quit();
1006 if (ImGui::BeginMenu(
"Tools"))
1008 ImGui::MenuItem(
"ImGui Style Editor", NULL, &itsShowStyleEditor);
1009 ImGui::MenuItem(
"ImGui Metrics/Debugger", NULL, &itsShowAppMetrics);
1010 ImGui::MenuItem(
"ImGui Demo/Doc", NULL, &itsShowImGuiDemo);
1015 ImGui::EndMenuBar();
1022 static std::map<std::string, size_t> mods;
1024 static std::string currstr;
1027 ImGui::AlignTextToFramePadding();
1028 ImGui::TextUnformatted(
"Module:");
1030 ImGui::SetNextItemWidth(6 * ImGui::GetFontSize() + 5);
1031 if (ImGui::Combo(
"##typemachinevisionmodule", &itsVideoMappingListType,
"Pro/GUI\0Legacy\0Headless\0\0")
1032 || currstr.empty() || itsRefreshVideoMappings)
1035 itsRefreshVideoMappings =
false;
1038 switch (itsVideoMappingListType)
1073 default:
LFATAL(
"Internal error, itsVideoMappingListType=" << itsVideoMappingListType);
1077 currstr = e->getCurrentVideoMapping().menustr().c_str();
1083 if (ImGui::BeginCombo(
"##machinevisionmodule", currstr.c_str()))
1085 for (
auto const & m : mods)
1087 bool is_selected =
false;
1088 if (ImGui::Selectable(m.first.c_str(), is_selected))
1090 e->requestSetFormat(m.second);
1102 std::shared_ptr<jevois::Module> m = engine()->
module();
1106 if (itsIcon.loaded() ==
false)
1107 try { itsIcon.load(m->absolutePath(
"icon.png")); }
1111 LERROR(
"This module has no icon -- USING DEFAULT");
1114 if (engine()->getCurrentVideoMapping().ispython) itsIcon.load(
JEVOIS_SHARE_PATH "/icons/py.png");
1120 cv::Mat blank(32, 32, CV_8UC4, 0);
1121 itsIcon.load(blank);
1125 if (itsIcon.loaded())
1127 int const siz = ImGui::CalcTextSize(
" ").x;
1128 itsIcon.draw(ImGui::GetCursorScreenPos(), ImVec2(siz, siz));
1132 if (itsModName.empty())
1134 std::filesystem::path fname = m->absolutePath(
"modinfo.html");
1135 std::ifstream ifs(fname);
1136 if (ifs.is_open() ==
false)
1139 LINFO(
"Recomputing module's modinfo.html ...");
1143 std::string
const cmdout =
1145 "JEVOIS_SRC_ROOT=none jevoispro-modinfo " + vm.
modulename,
true);
1147 if (! std::filesystem::exists(fname))
1148 throw std::runtime_error(
"Failed to create " + vm.
modinfopath() +
": " + cmdout);
1150 catch (...) { itsModName = vm.
modulename; itsModAuth =
"Cannot read file: " + fname.string(); }
1156 for (std::string s; std::getline(ifs, s); )
1162 if (str.empty() ==
false) { itsModName = str; ++state; }
1169 if (str.empty() ==
false) { itsModDesc = str; ++state; }
1175 std::string
const str =
jevois::extractString(s,
"<table class=modinfoauth width=100%>",
"</table>");
1176 if (str.empty() ==
false)
1187 if (str.empty() ==
false)
1191 if (tok.size() >= 3)
1194 else itsModLang =
"Language: Python";
1196 else itsModLang =
"Language: Unknown";
1205 if (str.empty() ==
false)
1209 size_t idx = str2.find_first_not_of(
" ");
if (idx != str2.npos) str2 = str2.substr(idx);
1210 itsModDoc.emplace_back(str2);
1218 if (s ==
"</div></td></tr>") ++state;
1224 if (s.find(
"/h1>") != s.npos || s.find(
"/h2>") != s.npos || s.find(
"/h3>") != s.npos) prefix =
"* ";
1225 if (s.find(
"<li>") != s.npos) prefix =
"- ";
1230 std::string::iterator new_end =
1231 std::unique(ss.begin(), ss.end(), [](
char lhs,
char rhs) { return (lhs == rhs) && (lhs ==
' '); });
1232 ss.erase(new_end, ss.end());
1233 size_t idx = ss.find_first_not_of(
" ");
if (idx != ss.npos) ss = ss.substr(idx);
1234 itsModDoc.push_back(ss);
1245 ImGui::TextUnformatted((
" " + itsModName).c_str());
1246 ImGui::TextUnformatted((
" " + itsModDesc).c_str());
1247 ImGui::TextUnformatted((
" " + itsModAuth +
" " + itsModLang).c_str());
1248 ImGui::TextUnformatted(
" ");
1250 int wrap = ImGui::GetCursorPos().x + ImGui::GetWindowSize().x - ImGui::GetFontSize() * 2.0f;
1251 if (wrap < 200) wrap = 200;
1252 ImGui::PushTextWrapPos(wrap);
1255 for (std::string
const & s : itsModDoc)
1259 show = ImGui::CollapsingHeader(s.c_str() + 2, ImGuiTreeNodeFlags_DefaultOpen);
1264 else ImGui::TextUnformatted(s.c_str());
1267 ImGui::PopTextWrapPos();
1270 ImGui::TextUnformatted(
"No JeVois Module currently loaded.");
1284 static bool show_frozen =
true;
static bool show_system =
false;
1286 toggleButton(
"Show Frozen Parameters", &show_frozen);
1287 ImGui::SameLine(ImGui::GetWindowWidth() - ImGui::CalcTextSize(
"Show System Parameters").x - 30.0f);
1288 toggleButton(
"Show System Parameters", &show_system);
1294 if (c ==
nullptr) { ImGui::TextUnformatted(
"No module loaded.");
return; }
1297 std::set<std::string> pnames, ambig;
1300 std::map<std::string , std::vector<jevois::ParameterSummary>> psm;
1303 if (pnames.insert(psum.
name).second ==
false) ambig.insert(psum.
name);
1304 psm[psum.
category].emplace_back(psum); } );
1307 if (psm.empty()) { ImGui::TextUnformatted(
"This module has no parameters.");
return; }
1311 float maxlen = 0.0f;
1312 for (
auto const & pp : psm)
1315 if (show_frozen ==
false)
1317 bool all_frozen =
true;
1318 for (
auto const & ps : pp.second)
if (ps.frozen ==
false) { all_frozen =
false;
break; }
1319 if (all_frozen)
continue;
1323 if (ImGui::CollapsingHeader(pp.first.c_str()))
1325 ImGui::Columns(3,
"parameters");
1328 for (
auto const & ps : pp.second)
1331 if (ps.frozen && show_frozen ==
false)
continue;
1334 static char wname[16]; snprintf(wname, 16,
"##p%d", widgetnum);
1338 ImGui::AlignTextToFramePadding();
1339 std::string nam = ps.name;
1340 if (ambig.contains(nam))
1344 if (tok.size() >= 2) nam = tok[tok.size()-2] +
':' + nam;
1347 ImGui::TextUnformatted(nam.c_str());
1348 if (ImGui::IsItemHovered()) ImGui::SetTooltip(
"%s", ps.descriptor.c_str());
1349 maxlen = std::max(maxlen, ImGui::CalcTextSize(nam.c_str()).x);
1352 ImGui::NextColumn();
1353 ImGui::AlignTextToFramePadding();
1354 std::string
const & vtype = ps.valuetype;
1356 helpMarker(ps.description.c_str(), (
"Parameter type: " + vtype).c_str());
1358 helpMarker(ps.description.c_str(), (
"Parameter type: " + vtype).c_str(),
1359 (
"Allowed values: " + ps.validvalues).c_str());
1362 ImGui::NextColumn();
1363 bool const is_uchar = (vtype ==
"unsigned char");
1364 bool const is_int = (vtype ==
"short" || vtype ==
"int" || vtype ==
"long int" || vtype ==
"long long int");
1365 bool const is_uint = (is_uchar || vtype ==
"unsigned short" || vtype ==
"unsigned int" ||
1366 vtype ==
"unsigned long int" || vtype ==
"unsigned long long int" || vtype ==
"size_t");
1367 bool const is_real = (vtype ==
"float" || vtype ==
"double" || vtype ==
"long double");
1370 int textflags = ImGuiInputTextFlags_EnterReturnsTrue;
1373 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1374 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1375 textflags |= ImGuiInputTextFlags_ReadOnly;
1381 std::string vals = ps.validvalues.substr(6, ps.validvalues.size() - 7);
1384 if (vv.empty() ==
false)
1387 int index = 0;
for (
auto const & v : vv)
if (v == ps.value)
break;
else ++index;
1390 if (combo(wname, vv, index)) setparstr(ps.descriptor, vv[index]);
1400 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1405 long mi = 0, ma = 255;
1406 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &mi, &ma))
1407 setparstr(ps.descriptor, std::to_string(val));
1412 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &r.
min(), &r.
max()))
1413 setparstr(ps.descriptor, std::to_string(val));
1419 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1422 if (ImGui::SliderScalar(wname, ImGuiDataType_U64, &val, &r.
min(), &r.
max()))
1423 setparstr(ps.descriptor, std::to_string(val));
1428 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1431 if (ImGui::SliderScalar(wname, ImGuiDataType_S64, &val, &r.
min(), &r.
max()))
1432 setparstr(ps.descriptor, std::to_string(val));
1437 std::string rng = ps.validvalues.substr(7, ps.validvalues.size() - 8);
1440 if (ImGui::SliderScalar(wname, ImGuiDataType_Double, &val, &r.
min(), &r.
max()))
1441 setparstr(ps.descriptor, std::to_string(val));
1446 char buf[256]; strncpy(buf, ps.value.c_str(),
sizeof(buf)-1);
1447 if (ImGui::InputText(wname, buf,
sizeof(buf), textflags))
1448 setparstr(ps.descriptor, buf);
1452 else if (vtype ==
"jevois::Range<unsigned char>")
1456 int mi = val.
min(), ma = val.
max();
1457 if (ImGui::DragIntRange2(wname, &mi, &ma, 0, 0, 255,
"Min: %d",
"Max: %d"))
1461 else if (vtype ==
"bool")
1464 if (ImGui::Checkbox(wname, &val)) setparval(ps.descriptor, val);
1467 else if (vtype ==
"ImColor")
1470 if (ImGui::ColorEdit4(wname, (
float *)&val, ImGuiColorEditFlags_AlphaPreview)) setparval(ps.descriptor, val);
1476 char buf[256]; strncpy(buf, ps.value.c_str(),
sizeof(buf)-1);
1477 if (ImGui::InputText(wname, buf,
sizeof(buf), textflags))
1478 setparstr(ps.descriptor, buf);
1484 static char rname[24]; snprintf(rname, 24,
"Reset##%d", widgetnum);
1486 if (ImGui::Button(rname)) setparstr(ps.descriptor, ps.defaultvalue);
1492 ImGui::PopItemFlag();
1493 ImGui::PopStyleVar();
1497 ImGui::NextColumn(); ++widgetnum;
1501 ImGui::EndColumns();
1507 ImGui::Columns(3,
"parameters");
1508 ImGui::SetColumnWidth(0, maxlen + ImGui::CalcTextSize(
"XX").x);
1509 ImGui::SetColumnWidth(1, ImGui::CalcTextSize(
" (?) ").x);
1510 ImGui::SetColumnWidth(2, 2000);
1511 ImGui::EndColumns();
1521 bool slusb =
false, slhard =
false, schanged =
false;
1525 case jevois::engine::SerPort::None: slusb =
false; slhard =
false;
break;
1526 case jevois::engine::SerPort::All: slusb =
true; slhard =
true;
break;
1527 case jevois::engine::SerPort::Hard: slusb =
false; slhard =
true;
break;
1528 case jevois::engine::SerPort::USB: slusb =
true; slhard =
false;
break;
1530 ImGui::AlignTextToFramePadding();
1531 ImGui::TextUnformatted(
"Log messages:"); ImGui::SameLine();
1532 if (itsUSBserial ==
false)
1534 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1535 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1536 if (toggleButton(
"USB##serlogu", &slusb)) schanged =
true;
1537 ImGui::PopItemFlag();
1538 ImGui::PopStyleVar();
1539#ifdef JEVOIS_PLATFORM
1540 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1542 ImGui::BeginTooltip();
1543 ImGui::TextUnformatted(
"Disabled - enable USB serial in the System tab");
1544 ImGui::EndTooltip();
1547 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1549 ImGui::BeginTooltip();
1550 ImGui::TextUnformatted(
"Disabled - not available on host");
1551 ImGui::EndTooltip();
1555 else if (toggleButton(
"USB##serlogu", &slusb)) schanged =
true;
1557 ImGui::SameLine();
if (toggleButton(
"Hard##serlogh", &slhard)) schanged =
true;
1558 ImGui::SameLine(); toggleButton(
"Cons##serlogc", &itsSerLogEnabled);
1559 ImGui::SameLine(0, 50);
1561 bool sousb =
false, sohard =
false;
1565 case jevois::engine::SerPort::None: sousb =
false; sohard =
false;
break;
1566 case jevois::engine::SerPort::All: sousb =
true; sohard =
true;
break;
1567 case jevois::engine::SerPort::Hard: sousb =
false; sohard =
true;
break;
1568 case jevois::engine::SerPort::USB: sousb =
true; sohard =
false;
break;
1570 ImGui::TextUnformatted(
"Module output:"); ImGui::SameLine();
1571 if (itsUSBserial ==
false)
1573 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
1574 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
1575 if (toggleButton(
"USB##seroutu", &sousb)) schanged =
true;
1576 ImGui::PopItemFlag();
1577 ImGui::PopStyleVar();
1578#ifdef JEVOIS_PLATFORM
1579 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1581 ImGui::BeginTooltip();
1582 ImGui::TextUnformatted(
"Disabled - enable USB serial in the System tab");
1583 ImGui::EndTooltip();
1586 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
1588 ImGui::BeginTooltip();
1589 ImGui::Text(
"Disabled - not available on host");
1590 ImGui::EndTooltip();
1594 else if (toggleButton(
"USB##seroutu", &sousb)) schanged =
true;
1595 ImGui::SameLine();
if (toggleButton(
"Hard##serouth", &sohard)) schanged =
true;
1596 ImGui::SameLine(); toggleButton(
"Cons##seroutc", &itsSerOutEnabled);
1602 if (slhard) e->
setParamValUnique(
"engine:serlog", jevois::engine::SerPort::All);
1607 if (slhard) e->
setParamValUnique(
"engine:serlog", jevois::engine::SerPort::Hard);
1613 if (sohard) e->
setParamValUnique(
"engine:serout", jevois::engine::SerPort::All);
1618 if (sohard) e->
setParamValUnique(
"engine:serout", jevois::engine::SerPort::Hard);
1628 int idx = 0;
for (
auto const & v : jevois::modul::SerStyle_Values)
if (v == sp)
break;
else ++idx;
1631 if (combo(
"serstyle", jevois::modul::SerStyle_Strings, idx))
1644{
return itsSerLogEnabled; }
1648{
return itsSerOutEnabled; }
1658 char const * b1txt,
char const * b2txt)
1661 int ret = 0;
int * retptr = default_val ? default_val : &ret;
1664 if (*retptr == 1 || *retptr == 2)
return *retptr;
1667 if (itsOpenModals.find(title) == itsOpenModals.end())
1669 ImGui::OpenPopup(title.c_str());
1670 itsOpenModals.insert(title);
1674 bool dont_ask_me_next_time = (*retptr == 3);
1676 if (ImGui::BeginPopupModal(title.c_str(), NULL, ImGuiWindowFlags_AlwaysAutoResize))
1678 ImGui::TextUnformatted(text); ImGui::TextUnformatted(
" ");
1682 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
1683 ImGui::PushStyleColor(ImGuiCol_FrameBg, 0xf0ffe0e0);
1684 ImGui::Checkbox(
"Don't ask me next time", &dont_ask_me_next_time);
1685 ImGui::PopStyleColor();
1686 ImGui::PopStyleVar();
1688 float const b1w = std::max(120.0F, ImGui::CalcTextSize(b1txt).x + 20.0F);
1689 if (ImGui::Button(b1txt, ImVec2(b1w, 0))) ret = 1;
1690 ImGui::SetItemDefaultFocus();
1692 float const b2w = std::max(120.0F, ImGui::CalcTextSize(b2txt).x + 20.0F);
1693 if (ImGui::Button(b2txt, ImVec2(b2w, 0))) ret = 2;
1698 if (ret == 1 || ret == 2)
1700 ImGui::CloseCurrentPopup();
1701 itsOpenModals.erase(title);
1702 if (dont_ask_me_next_time) *retptr = ret;
1704 else *retptr = dont_ask_me_next_time ? 3 : 0;
1712 return ImGui::Combo(name.c_str(), &selected_index,
1713 [](
void * vec,
int idx,
const char ** out_text)
1715 auto & ve = *static_cast<std::vector<std::string>*>(vec);
1716 if (idx < 0 || idx >= static_cast<int>(ve.size())) return false;
1717 *out_text = ve.at(idx).c_str();
1720 const_cast<void *
>(
static_cast<void const *
>(&items)), items.size());
1725 char const * hint,
char const * hlp)
1727 static char buf[256];
1728 ImGui::AlignTextToFramePadding();
1729 ImGui::TextUnformatted(desc);
1730 ImGui::NextColumn();
1731 helpMarker(desc, hlp);
1732 ImGui::NextColumn();
1733 strncpy(buf, str.c_str(),
sizeof(buf)-1);
1734 if (ImGui::InputTextWithHint(wname, hint, buf,
sizeof(buf))) str = buf;
1735 ImGui::NextColumn();
1741 float const fontw = ImGui::GetFontSize();
1743 static int refresh = 1;
1744 static std::string cpu, mem, ver;
1745 static size_t npu, tpu, vpu, spu;
static int fan;
1759 ImGui::TextUnformatted(cpu.c_str());
1760 ImGui::TextUnformatted(mem.c_str());
1761 ImGui::Text(
"NPU: %zu, TPU: %zu, VPU: %zu, SPU: %zu. Fan: %d%%", npu, tpu, vpu, spu, fan);
1765 drawNewModuleForm();
1769 if (ImGui::Button(
"Open Hardware serial monitor...")) itsShowHardSerialWin =
true;
1771 if (ImGui::Button(
"Open USB serial monitor...")) itsShowUsbSerialWin =
true;
1775 static std::string pingstr;
1776 static int showping = 0;
1777 if (ImGui::Button(
"Ping jevois.usc.edu"))
1779 std::string ret =
jevois::system(
"/usr/bin/ping -c 1 -w 2 jevois.usc.edu");
1781 if (rvec.size() < 2) reportError(
"Unable to ping jevois.usc.edu");
1782 else { pingstr = rvec[1]; showping = 60; }
1787 ImGui::TextUnformatted(pingstr.c_str());
1794 static std::string zip;
1795 static std::string donestr;
1796 static int state = 0;
1798 ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue;
1799 if (state) flags |= ImGuiInputTextFlags_ReadOnly;
1800 ImGui::SetNextItemWidth(fontw * 6.0F);
1802 if (ImGui::InputText(
"Load Custom DNN", buf,
sizeof(buf), flags)) state = 1;
1808 ImGui::TextUnformatted(
" ");
1813 ImGui::TextUnformatted(
"-- Downloading...");
1814 zip = std::string(buf) +
".zip";
1827 if (itsDnnGetFut.valid() ==
false) { reportError(
"Unknown error while loading custom DNN"); state = 0;
break; }
1828 ImGui::TextUnformatted(
"-- Downloading...");
1829 if (itsDnnGetFut.wait_for(std::chrono::microseconds(100)) == std::future_status::ready)
1835 if (ifs.is_open() ==
false)
1837 reportError(
"Failed to download. Check network connectivity and available disk space.");
1854 if (itsDnnGetFut.valid() ==
false) { reportError(
"Unknown error while unpacking custom DNN"); state = 0;
break; }
1855 ImGui::TextUnformatted(
"-- Installing...");
1856 if (itsDnnGetFut.wait_for(std::chrono::microseconds(100)) == std::future_status::ready)
1858 std::string ret = itsDnnGetFut.get();
1861 donestr =
"-- Invalid file, check DNN download key.";
1863 donestr =
"-- Done. Reload model zoo to take effect.";
1871 ImGui::TextUnformatted(
" ");
1876 ImGui::TextUnformatted(donestr.c_str());
1881#ifdef JEVOIS_PLATFORM
1883 static int bootmode = 0;
1884 ImGui::AlignTextToFramePadding();
1885 ImGui::TextUnformatted(
"On boot, start:");
1887 if (ImGui::Combo(
"##onboot", &bootmode,
"(no change)\0JeVois-Pro\0Ubuntu Console\0Ubuntu Graphical\0\0"))
1892 case 2:
jevois::system(
"systemctl --no-reload set-default multi-user.target");
break;
1893 case 3:
jevois::system(
"systemctl --no-reload set-default graphical.target");
break;
1894 default:
jevois::system(
"systemctl --no-reload set-default jevoispro.target");
break;
1901 static bool gserial =
false;
1903 if (ImGui::Checkbox(
"Enable serial outputs/logs over mini-USB (on next reboot)", &gserial))
1906 ofs << (gserial ? 1 : 0) << std::endl;
1913 static bool show_fan_modal =
false;
1914 if (ImGui::Button(
"Edit fan settings"))
1916 itsCfgEditor->loadFile(
"/lib/systemd/system/jevoispro-fan.service");
1917 show_fan_modal =
true;
1922 static int doit_default = 0;
1923 int ret = modal(
"Ready to edit",
"File will now be loaded in the Config tab of the main window and "
1924 "ready to edit.\nPlease switch to the Config tab in the main window.\n\n"
1925 "When you save it, we will reboot the camera.",
1926 &doit_default,
"Ok",
"Thanks");
1929 case 1: show_fan_modal =
false;
break;
1930 case 2: show_fan_modal =
false;
break;
1944 unsigned int get_v4l2_fmt(
int idx)
1948 case 0:
return V4L2_PIX_FMT_YUYV;
1949 case 1:
return V4L2_PIX_FMT_RGB24;
1950 case 2:
return V4L2_PIX_FMT_RGB32;
1951 case 3:
return V4L2_PIX_FMT_GREY;
1952 case 4:
return V4L2_PIX_FMT_SBGGR16;
1957 unsigned int get_v4l2_idx(
int fcc)
1961 case V4L2_PIX_FMT_YUYV:
return 0;
1962 case V4L2_PIX_FMT_RGB24:
return 1;
1963 case V4L2_PIX_FMT_RGB32:
return 2;
1964 case V4L2_PIX_FMT_GREY:
return 3;
1965 case V4L2_PIX_FMT_SBGGR16:
return 4;
1971 void cookedCopy(std::filesystem::path
const & src, std::filesystem::path
const & dst,
1972 std::string
const & name, std::string
const & vendor, 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>());
1992 std::ofstream ofs(dst);
1993 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
1994 ofs << str << std::endl;
1995 LINFO(
"Translated copy " << src <<
" => " << dst);
1999 void cookedCmakeClone(std::filesystem::path
const & src, std::filesystem::path
const & dst,
2000 std::string
const & oldname, std::string
const & newname,
2001 std::string
const & oldvendor, std::string
const & newvendor, std::string
const & synopsis,
2002 std::string
const & author, std::string
const & email, std::string
const & website,
2003 std::string
const & license, std::string
const & videomapping)
2005 std::ifstream f(src);
2006 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
2007 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
2022 std::ofstream ofs(dst);
2023 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
2024 ofs << str << std::endl;
2025 LINFO(
"Translated copy " << src <<
" => " << dst);
2029 void cookedCodeClone(std::filesystem::path
const & src, std::filesystem::path
const & dst,
2030 std::string
const & oldname, std::string
const & newname)
2032 std::ifstream f(src);
2033 if (f.is_open() ==
false)
LFATAL(
"Cannot read " << src);
2034 std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
2052 std::ofstream ofs(dst);
2053 if (ofs.is_open() ==
false)
LFATAL(
"Cannot write " << dst <<
" -- check that you are running as root.");
2054 ofs << str << std::endl;
2055 LINFO(
"Translated copy " << src <<
" => " << dst);
2062 float const fontw = ImGui::GetFontSize();
2064 static int templ = 0;
2066 ImGui::PushStyleColor(ImGuiCol_PopupBg, 0xf0e0ffe0);
2068 if (ImGui::Button(
"Create new machine vision module..."))
2070 ImGui::OpenPopup(
"Create new machine vision module");
2071 itsIdleBlocked =
true;
2075 ImVec2
const center = ImGui::GetMainViewport()->GetCenter();
2076 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
2077 ImGui::SetNextWindowContentSize(ImVec2(940, 750));
2079 if (ImGui::BeginPopupModal(
"Create new machine vision module", NULL, ImGuiWindowFlags_AlwaysAutoResize))
2083 static std::string name, vendor, synopsis, author, email, website, license, srcvendor, srcname;
2084 static int language = 0;
2085 static int ofmt = 0;
static int ow = 320, oh = 240;
static float ofps = 30.0F;
2086 static int cmode = 0;
2087 static int wdrmode = 0;
2088 static int cfmt = 0;
static int cw = 1920, ch = 1080;
static float cfps = 30.0F;
2089 static int c2fmt = 1;
static int c2w = 512, c2h = 288;
2092 ImGui::AlignTextToFramePadding();
2093 ImGui::TextUnformatted(
"Fill out the details below, or clone from");
2096 static std::map<std::string, size_t> mods;
2097 static std::string currstr =
"...";
2103 if (ImGui::BeginCombo(
"##clonemodule", currstr.c_str()))
2105 for (
auto const & mod : mods)
2107 bool is_selected =
false;
2108 if (ImGui::Selectable(mod.first.c_str(), is_selected))
2110 m = e->getVideoMapping(mod.second);
2111 currstr = mod.first;
2117 { name =
"My" + m.
modulename + std::to_string(i++); }
2124 case jevois::CropType::CropScale: cmode = 0;
break;
2125 case jevois::CropType::Crop: cmode = 1;
break;
2126 case jevois::CropType::Scale: cmode = 2;
break;
2130 case jevois::WDRtype::Linear: wdrmode = 0;
break;
2131 case jevois::WDRtype::DOL: wdrmode = 1;
break;
2133 cfmt = get_v4l2_idx(m.
cfmt); cw = m.
cw; ch = m.
ch; cfps = m.
cfps;
2134 c2fmt = get_v4l2_idx(m.
c2fmt); c2w = m.
c2w; c2h = m.
c2h;
2144 ImGui::Columns(3,
"new module");
2146 newModEntry(
"##NewModname", name,
"Module Name",
"MyModule",
2147 "Required, even when cloning. Must start with an uppercase letter. "
2148 "Will be a folder name under /jevoispro/modules/VendorName");
2150 newModEntry(
"##NewModvendor", vendor,
"Vendor Name",
"MyVendor",
2151 "Required, even when cloning. Must start with an uppercase letter. "
2152 "Will be a folder name under /jevoispro/modules/");
2157 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2158 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2161 newModEntry(
"##NewModsynopsis", synopsis,
"Synopsis",
"Detect Object of type X",
2162 "Optional. Brief description of what the module does.");
2164 newModEntry(
"##NewModauthor", author,
"Author Name",
"John Smith",
"Optional");
2166 newModEntry(
"##NewModemail", email,
"Author Email",
"you@yourcompany.com",
"Optional");
2168 newModEntry(
"##NewModwebsite", website,
"Author Website",
"http://yourcompany.com",
"Optional");
2170 newModEntry(
"##NewModlicense", license,
"License",
"GPL v3",
"Optional");
2173 ImGui::AlignTextToFramePadding();
2174 ImGui::TextUnformatted(
"Module Language");
2175 ImGui::NextColumn();
2176 helpMarker(
"Module Language",
"Machine language to use for your module.");
2177 ImGui::NextColumn();
2178 ImGui::Combo(
"##NewModlanguage", &language,
"Python\0C++\0\0");
2179 ImGui::NextColumn();
2182 ImGui::AlignTextToFramePadding();
2183 ImGui::TextUnformatted(
"Module Template");
2184 ImGui::NextColumn();
2185 helpMarker(
"Module Template",
"Type of placeholder code that will be provided to get your module started.");
2186 ImGui::NextColumn();
2187 if (templ < 3) ImGui::Combo(
"##NewModtemplate", &templ,
"Pro/GUI\0Legacy\0Headless\0\0");
2188 else ImGui::Combo(
"##NewModtemplate", &templ,
"Pro/GUI\0Legacy\0Headless\0Clone\0\0");
2189 ImGui::NextColumn();
2192 int oflags = ImGuiInputTextFlags_None;
2195 oflags |= ImGuiInputTextFlags_ReadOnly;
2196 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2197 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2200 ImGui::AlignTextToFramePadding();
2201 ImGui::TextUnformatted(
"Module Output");
2202 ImGui::NextColumn();
2203 helpMarker(
"Module Output",
"Output video format for legacy module.");
2204 ImGui::NextColumn();
2205 ImGui::SetNextItemWidth(fontw * 5.0F);
2206 ImGui::Combo(
"##NewModofmt", &ofmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2208 ImGui::SetNextItemWidth(fontw * 4.0F);
2209 ImGui::InputInt(
"##NewModow", &ow, 0, 0, ImGuiInputTextFlags_CharsDecimal | oflags);
2211 ImGui::TextUnformatted(
"x");
2213 ImGui::SetNextItemWidth(fontw * 4.0F);
2214 ImGui::InputInt(
"##NewModoh", &oh, 0, 0, ImGuiInputTextFlags_CharsDecimal | oflags);
2216 ImGui::TextUnformatted(
"@");
2218 ImGui::SetNextItemWidth(fontw * 4.0F);
2219 ImGui::InputFloat(
"##NewModofps", &ofps, 0.0F, 0.0F,
"%.1f", ImGuiInputTextFlags_CharsDecimal | oflags);
2221 ImGui::TextUnformatted(
"fps");
2222 ImGui::NextColumn();
2226 ImGui::PopItemFlag();
2227 ImGui::PopStyleVar();
2231 ImGui::AlignTextToFramePadding();
2232 ImGui::TextUnformatted(
"Camera Mode");
2233 ImGui::NextColumn();
2234 helpMarker(
"Camera Mode",
"Camera sensor configuration for your module.");
2235 ImGui::NextColumn();
2236 ImGui::SetNextItemWidth(fontw * 18.0F);
2237 ImGui::Combo(
"##NewModcmode", &cmode,
"Dual-resolution (Crop+Scale)\0Single-resolution Crop\0"
2238 "Single-resolution Scale\0\0");
2239 ImGui::NextColumn();
2242 ImGui::AlignTextToFramePadding();
2243 ImGui::TextUnformatted(
"Camera WDR");
2244 ImGui::NextColumn();
2245 helpMarker(
"Camera WDR",
"Camera sensor wide-dynamic-range (WDR) setting for your module. Linear is for no WDR, "
2246 "DOL is for digital overlap (merging short and long exposure frames).");
2247 ImGui::NextColumn();
2248 ImGui::Combo(
"##NewModwdrmode", &wdrmode,
"Linear\0\0");
2250 ImGui::NextColumn();
2253 ImGui::AlignTextToFramePadding();
2254 ImGui::TextUnformatted(
"Camera Format");
2255 ImGui::NextColumn();
2256 helpMarker(
"Camera Format",
"Camera video format to use for input to module and for GUI display.");
2257 ImGui::NextColumn();
2258 ImGui::SetNextItemWidth(fontw * 5.0F);
2259 ImGui::Combo(
"##NewModcfmt", &cfmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2261 ImGui::SetNextItemWidth(fontw * 4.0F);
2262 ImGui::InputInt(
"##NewModcw", &cw, 0, 0, ImGuiInputTextFlags_CharsDecimal);
2264 ImGui::TextUnformatted(
"x");
2266 ImGui::SetNextItemWidth(fontw * 4.0F);
2267 ImGui::InputInt(
"##NewModch", &ch, 0, 0, ImGuiInputTextFlags_CharsDecimal);
2269 ImGui::TextUnformatted(
"@");
2271 ImGui::SetNextItemWidth(fontw * 4.0F);
2272 ImGui::InputFloat(
"##NewModcfps", &cfps, 0.0F, 0.0F,
"%.1f", ImGuiInputTextFlags_CharsDecimal);
2274 ImGui::TextUnformatted(
"fps");
2275 ImGui::NextColumn();
2278 int c2flags = ImGuiInputTextFlags_None;
2281 oflags |= ImGuiInputTextFlags_ReadOnly;
2282 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2283 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2286 ImGui::AlignTextToFramePadding();
2287 ImGui::TextUnformatted(
"Camera Format 2");
2288 ImGui::NextColumn();
2289 helpMarker(
"Camera Format 2",
"Camera video format for the second stream (for processing).");
2290 ImGui::NextColumn();
2291 ImGui::SetNextItemWidth(fontw * 5.0F);
2292 ImGui::Combo(
"##NewModc2fmt", &c2fmt,
"YUYV\0RGB\0RGBA\0GREY\0BAYER\0\0");
2294 ImGui::SetNextItemWidth(fontw * 4.0F);
2295 ImGui::InputInt(
"##NewModc2w", &c2w, 0, 0, ImGuiInputTextFlags_CharsDecimal | c2flags);
2297 ImGui::TextUnformatted(
"x");
2299 ImGui::SetNextItemWidth(fontw * 4.0F);
2300 ImGui::InputInt(
"##NewModc2h", &c2h, 0, 0, ImGuiInputTextFlags_CharsDecimal | c2flags);
2301 ImGui::NextColumn();
2305 ImGui::PopItemFlag();
2306 ImGui::PopStyleVar();
2311 ImGui::PopItemFlag();
2312 ImGui::PopStyleVar();
2316 ImGui::SetColumnWidth(0, fontw * 10.0F);
2317 ImGui::SetColumnWidth(1, ImGui::CalcTextSize(
"(?)").x + 30.0F);
2325 ImVec2
const button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
2326 if (ImGui::Button(
"Cancel", button_size))
2328 ImGui::CloseCurrentPopup();
2330 ImGui::PopStyleColor();
2331 itsIdleBlocked =
false;
2336 ImGui::SameLine(0, 540);
2339 if (ImGui::Button(
"Create", button_size))
2342 if (name.empty())
LFATAL(
"New Module cannot have an empty name.");
2343 if (name[0]<
'A' || name[0]>
'Z')
LFATAL(
"New Module name must start with an uppercase letter.");
2344 if (vendor.empty())
LFATAL(
"New Module cannot have empty vendor name.");
2345 LINFO(
"New Module data valid...");
2349 if (std::filesystem::exists(newvdir) ==
false && std::filesystem::create_directory(newvdir) ==
false)
2350 PLFATAL(
"Error creating dir " << newvdir <<
" -- check that you are running as root");
2351 std::filesystem::path
const newmdir = newvdir / name;
2359 std::filesystem::path srcpath = m.
srcpath();
2360 std::filesystem::path cmakepath = m.
cmakepath();
2368 srcname.c_str(), newmdir.c_str());
2370 LINFO(
"Cloned module using: " << copycmd);
2373 unlink((m.
path() +
'/' + srcname +
".C").c_str());
2374 unlink((m.
path() +
'/' + srcname +
".py").c_str());
2375 unlink((m.
path() +
'/' + srcname +
".so").c_str());
2376 std::filesystem::remove_all(m.
path() +
"/__pycache__");
2377 std::filesystem::remove_all(m.
path() +
"/build");
2380 std::ostringstream oss; oss << m; vmstr = oss.
str();
2381 cookedCodeClone(srcpath, m.srcpath(), srcname, name);
2386 if (std::filesystem::exists(cmakepath))
2387 cookedCmakeClone(cmakepath, m.cmakepath(), srcname, name, srcvendor, vendor, synopsis, author,
2388 email, website, license, vmstr);
2391 name, vendor, synopsis, author, email, website, license, vmstr);
2399 if (std::filesystem::exists(newmdir))
2400 LFATAL(
"Directory [" << newmdir <<
"] already exists -- Choose another name");
2401 if (std::filesystem::create_directory(newmdir) ==
false)
2402 PLFATAL(
"Error creating directory [" << newmdir <<
"] for new module. Maybe not running as root?");
2403 LINFO(
"Created new Module directory: " << newmdir);
2410 case 1: m.
ofmt = get_v4l2_fmt(ofmt); m.
ow = ow; m.
oh = oh; m.
ofps = ofps;
break;
2411 case 2: m.
ofmt = 0;
break;
2415 m.
cfmt = get_v4l2_fmt(cfmt);
2416 m.
cw = cw; m.
ch = ch; m.
cfps = cfps;
2423 case 0: m.
wdr = jevois::WDRtype::Linear;
break;
2424 case 1: m.
wdr = jevois::WDRtype::DOL;
break;
2430 case 0: m.
crop = jevois::CropType::CropScale;
2431 m.
c2fmt = get_v4l2_fmt(c2fmt);
2432 m.
c2w = c2w; m.
c2h = c2h;
2434 case 1: m.
crop = jevois::CropType::Crop;
break;
2435 case 2: m.
crop = jevois::CropType::Scale;
break;
2440 std::ostringstream oss; oss << m; vmstr = oss.
str();
2443 std::string code; std::string tname;
2447 tname =
"PyModule.py";
2456 std::filesystem::path dstcmak = m.cmakepath();
2457 cookedCopy(srccmak, dstcmak, name, vendor, synopsis, author, email, website, license, vmstr);
2461 default:
LFATAL(
"Invalid language " << language);
2465 std::filesystem::path dstmod = m.srcpath();
2466 cookedCopy(srcmod, dstmod, name, vendor, synopsis, author, email, website, license, vmstr);
2471 LINFO(
"Added videomapping: " << vmstr);
2478 if (language == 0) runNewModule();
2479 else itsCompileState = CompilationState::Start;
2482 name.clear(); vendor.clear(); synopsis.clear(); currstr =
"...";
2484 ImGui::CloseCurrentPopup();
2485 itsIdleBlocked =
false;
2488 catch (...) { reportAndIgnoreException(); }
2494 ImGui::PopStyleColor();
2501 size_t idx = 0;
size_t foundidx = 12345678;
2503 {
if (itsNewMapping.isSameAs(mm)) foundidx = idx; ++idx; });
2506 else LFATAL(
"Internal error, could not find the module we just created -- CHECK LOGS");
2508 itsRefreshVideoMappings =
true;
2513 else if (itsNewMapping.ofmt != 0 && itsNewMapping.ofmt !=
JEVOISPRO_FMT_GUI) itsVideoMappingListType = 1;
2514 else if (itsNewMapping.ofmt == 0) itsVideoMappingListType = 2;
2515 else LERROR(
"Internal error: cannot determine video mapping list type -- IGNORED");
2521#define L(i,x,y,z)for(F i=x;i<y;i+=z)
2522#define Q(y)sin((y+t)*.03)*(1-sin(t*3)*cos(y/99+t))*9
2523#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);
2524#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)}
2525#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)
2527F 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);}}
2528h=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);
2529 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)}
2534 if (ImGui::Button(
"Open Style Editor")) itsShowStyleEditor =
true;
2536 if (ImGui::Button(
"Open App Metrics")) itsShowAppMetrics =
true;
2538 if (ImGui::Button(
"Open ImGui Demo")) itsShowImGuiDemo =
true;
2542 float camz = pixel_perfect_z;
2546 static float fudgex = 0.375f;
2547 static float fudgey = 0.375f;
2548 static float fudgez = 0.0f;
2549 unsigned short winw, winh; itsBackend.getWindowSize(winw, winh);
2551 ImGui::SliderFloat(
"OpenGL Camera z", &camz, -2.0f * winh, -1.0f);
2552 ImGui::SliderAngle(
"OpenGL yaw", &yaw, -179.0f, 180.0f);
2553 ImGui::SliderAngle(
"OpenGL pitch", &pitch, -179.0f, 180.0f);
2554 ImGui::SliderAngle(
"OpenGL roll", &roll, -179.0f, 180.0f);
2556 ImGui::SliderFloat(
"fudge x", &fudgex, -1.0f, 1.0f);
2557 ImGui::SliderFloat(
"fudge y", &fudgey, -1.0f, 1.0f);
2558 ImGui::SliderFloat(
"fudge z", &fudgez, -1.0f, 1.0f);
2561 proj = glm::perspective(glm::radians(45.0f),
float(winw) /
float(winh), 1.0f, winh * 2.0f);
2562 proj = glm::translate(proj, glm::vec3(fudgex, fudgey, fudgez));
2565 view = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, camz));
2566 view *= glm::yawPitchRoll(yaw, pitch, roll);
2582 ImGuiIO& io = ImGui::GetIO();
2583 ImGui::Begin(
"Tiny OpenGL demo", NULL, ImGuiWindowFlags_AlwaysAutoResize);
2584 ImVec2 size(320.0f, 180.0f);
2585 ImGui::InvisibleButton(
"canvas", size);
2586 ImVec2 p0 = ImGui::GetItemRectMin();
2587 ImVec2 p1 = ImGui::GetItemRectMax();
2588 ImDrawList* draw_list = ImGui::GetWindowDrawList();
2589 draw_list->PushClipRect(p0, p1);
2592 mouse_data.x = (io.MousePos.x - p0.x) / size.x;
2593 mouse_data.y = (io.MousePos.y - p0.y) / size.y;
2594 mouse_data.z = io.MouseDownDuration[0];
2595 mouse_data.w = io.MouseDownDuration[1];
2597 drawTinyImGUIdemo(draw_list, p0, p1, size, mouse_data, (
float)ImGui::GetTime());
2598 draw_list->PopClipRect();
2607 auto now = std::chrono::steady_clock::now();
2609 std::lock_guard<std::mutex> _(itsErrorMtx);
2612 for (
auto & e : itsErrors)
if (e.err == err) { e.lasttime = now;
return; }
2615 if (itsErrors.size() > 10)
return;
2616 else if (itsErrors.size() == 10)
2618 ErrorData d {
"Too many errors -- TRUNCATING", now, now };
2619 itsErrors.emplace(itsErrors.end(), std::move(d));
2625 itsErrors.emplace(itsErrors.end(), std::move(d));
2633 std::lock_guard<std::mutex> _(itsErrorMtx);
2643 catch (std::exception
const & e)
2644 { reportError(e.what()); }
2645 catch (boost::python::error_already_set & e)
2648 { reportError(
"Unknown error"); }
2653 catch (std::exception
const & e)
2654 { reportError(prefix +
": " + e.what()); }
2655 catch (boost::python::error_already_set & e)
2658 { reportError(prefix +
": Unknown error"); }
2665 reportAndIgnoreException(prefix);
2672 std::lock_guard<std::mutex> _(itsErrorMtx);
2673 if (itsErrors.empty())
return;
2675 ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize |
2676 ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNav;
2678 ImGui::SetNextWindowPos(ImVec2(10.0f, 10.0f), ImGuiCond_Always);
2679 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xc0e0e0ff);
2681 static bool show =
true;
2683 if (ImGui::Begin(
"Error detected!", &show, window_flags))
2685 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
2686 ImGui::TextUnformatted(
"Error detected!");
2688 auto itr = itsErrors.begin();
2689 while (itr != itsErrors.end())
2692 std::chrono::duration<float> d = std::chrono::steady_clock::now() - itr->lasttime;
2693 std::chrono::duration<float> d2 = std::chrono::steady_clock::now() - itr->firsttime;
2694 if (d.count() >= 1.0f && d2.count() >= 10.0f && ImGui::IsWindowHovered() ==
false)
2695 itr = itsErrors.erase(itr);
2700 ImGui::TextUnformatted(itr->err.c_str());
2704 ImGui::PopTextWrapPos();
2708 ImGui::PopStyleColor();
2715 ImGui::TextUnformatted(
"(?)");
2716 if (ImGui::IsItemHovered())
2718 ImGui::BeginTooltip();
2719 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
2720 ImGui::TextUnformatted(msg);
2721 if (msg2) { ImGui::Separator(); ImGui::TextUnformatted(msg2); }
2722 if (msg3) { ImGui::Separator(); ImGui::TextUnformatted(msg3); }
2723 ImGui::PopTextWrapPos();
2724 ImGui::EndTooltip();
2731 bool changed =
false;
2734 ImGui::PushID(name);
2735 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(4.0f/7.0f, 1.0f, 1.0f));
2736 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(4.0f/7.0f, 1.0f, 1.0f));
2737 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(4.0f/7.0f, 0.5f, 0.5f));
2738 if (ImGui::Button(name)) { *val =
false; changed =
true; }
2739 ImGui::PopStyleColor(3);
2742 else if (ImGui::Button(name)) { *val =
true; changed =
true; }
2750 unsigned short winw, winh;
2751 startFrame(winw, winh);
2753 if (itsHeadless.loaded() ==
false)
2758 cv::Mat blank(winh, winw, CV_8UC4, 0);
2759 itsHeadless.load(blank);
2762 if (itsHeadless.loaded()) itsHeadless.draw(ImVec2(0, 0), ImVec2(winw, winh), ImGui::GetBackgroundDrawList());
2770 ImGui::PushStyleColor(ImGuiCol_Text, 0xff0000ff);
2771 ImGui::TextUnformatted(str.c_str());
2772 ImGui::PopStyleColor();
2779 itsBannerTitle = title;
2786 if (itsCompileState == CompilationState::Cmake || itsCompileState == CompilationState::Make ||
2787 itsCompileState == CompilationState::Install || itsCompileState == CompilationState::CPack)
2788 reportError(
"Still compiling... Try again later...");
2789 else if (std::filesystem::exists(itsNewMapping.srcpath()) && std::filesystem::exists(itsNewMapping.cmakepath()))
2790 itsCompileState = CompilationState::Start;
2795 std::filesystem::path
const & fpath = itsCodeEditor->getLoadedFilePath();
2796 std::filesystem::path
const fn = fpath.filename();
2798 if (fn ==
"CMakeLists.txt" || fn.extension() ==
".C")
2800 itsNewMapping = { };
2801 std::filesystem::path p = fpath.parent_path();
2802 itsNewMapping.modulename = p.filename();
2803 itsNewMapping.vendor = p.parent_path().filename();
2804 itsNewMapping.ispython =
false;
2807 if (std::filesystem::exists(itsNewMapping.srcpath()) && std::filesystem::exists(itsNewMapping.cmakepath()))
2808 itsCompileState = CompilationState::Start;
2809 else reportError(
"Cannot find " + itsNewMapping.srcpath() +
" or " + itsNewMapping.cmakepath() +
" -- IGNORED");
2811 else reportError(
"Cannot compile " + fpath.string() +
" -- IGNORED");
2818 ImGui::PushStyleColor(ImGuiCol_WindowBg, 0xf0e0ffe0);
2820 ImGui::SetNextWindowSize(ImVec2(800, 680), ImGuiCond_FirstUseEver);
2823 int constexpr flags = ImGuiWindowFlags_HorizontalScrollbar;
2824 bool keep_window_open =
true;
2825 if (itsCompileState == CompilationState::Error) ImGui::Begin(
"C++ Module Compilation", &keep_window_open, flags);
2826 else ImGui::Begin(
"C++ Module Compilation",
nullptr, flags);
2828 ImGui::TextUnformatted((
"Compiling " + itsNewMapping.srcpath()).c_str());
2829 ImGui::TextUnformatted((
"Using " + itsNewMapping.cmakepath()).c_str());
2831 std::string
const modpath = itsNewMapping.path();
2832 std::string
const buildpath = modpath +
"/build";
2836 switch (itsCompileState)
2839 case CompilationState::Start:
2840 LINFO(
"Start compiling " << itsNewMapping.srcpath());
2841 itsIdleBlocked =
true;
2842 for (std::string & s : itsCompileMessages) s.clear();
2843 std::filesystem::remove_all(buildpath);
2844 itsCompileState = CompilationState::Cmake;
2849 std::filesystem::path sp(modpath +
"/rebuild.sh");
2851 std::ofstream ofs(sp);
2852 if (ofs.is_open() ==
false)
2853 reportError(
"Cannot write " + sp.string() +
" -- check that you are running as root.");
2857 ofs <<
"#!/bin/sh" << std::endl <<
"set -e" << std::endl;
2858 ofs <<
"cmake -S " << modpath <<
" -B " << buildpath <<
" -DJEVOIS_HARDWARE=PRO"
2859#ifdef JEVOIS_PLATFORM
2860 <<
" -DJEVOIS_PLATFORM=ON -DJEVOIS_NATIVE=ON"
2863 ofs <<
"JEVOIS_SRC_ROOT=none cmake --build " << buildpath << std::endl;
2864 ofs <<
"cmake --install " << buildpath << std::endl;
2865 ofs <<
"cd " << buildpath <<
2866 " && cpack && mkdir -p /jevoispro/debs && /bin/mv *.deb /jevoispro/debs/" << std::endl;
2870 using std::filesystem::perms;
2871 std::filesystem::permissions(sp, perms::owner_all | perms::group_read | perms::group_exec |
2872 perms::others_read | perms::others_exec);
2878 case CompilationState::Cmake:
2879 if (compileCommand(
"cmake -S " + modpath +
" -B " + buildpath +
2880 " -DJEVOIS_HARDWARE=PRO"
2881#ifdef JEVOIS_PLATFORM
2882 " -DJEVOIS_PLATFORM=ON -DJEVOIS_NATIVE=ON"
2884 , itsCompileMessages[0]))
2885 itsCompileState = CompilationState::Make;
2889 case CompilationState::Make:
2890 if (compileCommand(
"JEVOIS_SRC_ROOT=none cmake --build " + buildpath, itsCompileMessages[1]))
2891 itsCompileState = CompilationState::Install;
2895 case CompilationState::Install:
2896 if (compileCommand(
"cmake --install " + buildpath, itsCompileMessages[2]))
2897 itsCompileState = CompilationState::CPack;
2901 case CompilationState::CPack:
2902 if (compileCommand(
"cd " + buildpath +
" && cpack && mkdir -p /jevoispro/debs && /bin/mv *.deb /jevoispro/debs/",
2903 itsCompileMessages[3]))
2904 itsCompileState = CompilationState::Success;
2908 case CompilationState::Success:
2910 ImGui::TextUnformatted(
"Compilation success!");
2911 ImGui::TextUnformatted(
"See below for details...");
2913 static int run_default = 0;
2914 int ret = modal(
"Success! Run the module now?",
"Compilation success!\n\nA deb package of your module is in "
2915 "/jevoispro/debs/\nif you want to share it.\n\nLoad and run the new module now?",
2916 &run_default,
"Yes",
"No");
2921 itsIdleBlocked =
false;
2922 itsCompileState = CompilationState::Idle;
2927 itsIdleBlocked =
false;
2928 itsCompileState = CompilationState::Idle;
2930 itsRefreshVideoMappings =
true;
2938 case CompilationState::Error:
2940 itsIdleBlocked =
false;
2941 highlightText(
"Compilation failed!");
2942 ImGui::TextUnformatted(
"You may need to edit the two files above.");
2943 ImGui::TextUnformatted(
"See below for details...");
2945 static bool show_modal =
false;
2947 ImGui::AlignTextToFramePadding();
2948 if (ImGui::Button(
"Edit CMakeLists.txt"))
2949 { itsCodeEditor->loadFile(itsNewMapping.cmakepath()); show_modal =
true; }
2951 ImGui::SameLine(); ImGui::TextUnformatted(
" "); ImGui::SameLine();
2952 if (ImGui::Button((
"Edit " + itsNewMapping.modulename +
".C").c_str()))
2953 { itsCodeEditor->loadFile(itsNewMapping.srcpath()); show_modal =
true; }
2955 ImGui::SameLine(); ImGui::TextUnformatted(
" "); ImGui::SameLine();
2956 if (ImGui::Button(
"Compile again")) itsCompileState = CompilationState::Start;
2962 static int doit_default = 0;
2963 int ret = modal(
"Ready to edit",
"File will now be loaded in the Code tab of the main window and "
2964 "ready to edit. Please switch to the Code tab in the main window.\n\n"
2965 "When you save it, we will try to compile it again.",
2966 &doit_default,
"Close Compilation Window",
"Keep Open");
2969 case 1: show_modal =
false; itsCompileState = CompilationState::Idle;
break;
2970 case 2: show_modal =
false;
break;
2979 LERROR(
"Internal error: invalid compilation state " <<
int(itsCompileState) <<
" -- RESET TO IDLE");
2980 itsCompileState = CompilationState::Idle;
2981 itsIdleBlocked =
false;
2983 }
catch (...) { reportAndIgnoreException(); }
2986 for (std::string & s : itsCompileMessages)
2987 if (s.empty() ==
false)
2989 ImGui::TextUnformatted(s.c_str());
2994 ImGui::PopStyleColor();
2997 if (keep_window_open ==
false) { itsIdleBlocked =
false; itsCompileState = CompilationState::Idle; }
3004 if (itsCompileFut.valid() ==
false)
3007 msg =
"Running: " + cmd +
"\nPlease wait ...\n";
3008 LINFO(
"Running: " + cmd);
3010 else if (itsCompileFut.wait_for(std::chrono::milliseconds(1)) == std::future_status::ready)
3013 msg += itsCompileFut.get() +
"\nSuccess!";
3014 LINFO(
"Success running: " << cmd);
3019 LERROR(
"Failed running: " << cmd);
3020 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.
void drawEllipse(float x, float y, float rx, float ry, float rot=0.0F, ImU32 col=IM_COL32(128, 255, 128, 255), bool filled=true)
Draw ellipse 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 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 join(std::vector< T > const &tokens, std::string const &delimiter)
Concatenate a vector of tokens into 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