From d3d57000569b8d56be0b593f8c07a09c72fbd872 Mon Sep 17 00:00:00 2001 From: Scott Hanson Date: Thu, 20 Jun 2024 18:07:08 -0400 Subject: [PATCH] For FPP 8, Added Proxy Descriptions, Tag/Remove xLights generated models in FPP. Added Compiler Version to About Dialog --- xLights/controllers/FPP.cpp | 115 ++++++++++++++++++++++++++---------- xLights/controllers/FPP.h | 20 +++---- xLights/xLightsMain.cpp | 10 ++++ 3 files changed, 104 insertions(+), 41 deletions(-) diff --git a/xLights/controllers/FPP.cpp b/xLights/controllers/FPP.cpp index e550f7717b..ca5aa550b7 100644 --- a/xLights/controllers/FPP.cpp +++ b/xLights/controllers/FPP.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -308,13 +309,13 @@ bool FPP::GetURLAsString(const std::string& url, std::string& val, bool recordEr } return response_code == 200; } -int FPP::PostToURL(const std::string& url, const std::vector &val, const std::string &contentType) { +int FPP::PostToURL(const std::string& url, const std::vector& val, const std::string& contentType) const { return TransferToURL(url, val, contentType, true); } -int FPP::PutToURL(const std::string& url, const std::vector &val, const std::string &contentType) { +int FPP::PutToURL(const std::string& url, const std::vector& val, const std::string& contentType) const { return TransferToURL(url, val, contentType, false); } -int FPP::TransferToURL(const std::string& url, const std::vector &val, const std::string &contentType, bool isPost) { +int FPP::TransferToURL(const std::string& url, const std::vector& val, const std::string& contentType, bool isPost) const { std::string fullUrl = ipAddress + url; std::string ipAddForGet = ipAddress; @@ -615,8 +616,7 @@ int FPP::PostJSONToURLAsFormData(const std::string& url, const std::string &extr return PostToURL(url, memBuffPost, "application/x-www-form-urlencoded; charset=UTF-8"); } -void FPP::DumpJSON(const wxJSONValue& json) -{ +void FPP::DumpJSON(const wxJSONValue& json) const { static log4cpp::Category& logger_base = log4cpp::Category::getInstance(std::string("log_base")); wxString str; wxJSONWriter writer(wxJSONWRITER_STYLED, 0, 3); @@ -624,12 +624,12 @@ void FPP::DumpJSON(const wxJSONValue& json) logger_base.debug(ToUTF8(str)); } -int FPP::PostToURL(const std::string& url, const std::string &val, const std::string &contentType) { +int FPP::PostToURL(const std::string& url, const std::string& val, const std::string& contentType) const { std::vector memBuffPost; addString(memBuffPost, val); return PostToURL(url, memBuffPost, contentType); } -int FPP::PutToURL(const std::string& url, const std::string &val, const std::string &contentType) { +int FPP::PutToURL(const std::string& url, const std::string& val, const std::string& contentType) const { std::vector memBuffPost; addString(memBuffPost, val); return PutToURL(url, memBuffPost, contentType); @@ -1350,7 +1350,7 @@ bool FPP::UploadUDPOut(const wxJSONValue &udp) { } } } - PostJSONToURL("/api/channel/output/universeOutputs", newudp); + PostJSONToURL("/api/channel/output/universeOutputs", newudp); return false; } @@ -1391,6 +1391,9 @@ wxJSONValue FPP::CreateModelMemoryMap(ModelManager* allmodels, int32_t startChan jm["ChannelCount"] = model->GetActChanCount(); jm["StartChannel"] = ch; jm["ChannelCountPerNode"] = model->GetChanCountPerNode(); + if (IsVersionAtLeast(8, 0)) { + jm["xLights"] = true; + } MatrixModel *mm = dynamic_cast(model); if (mm) { @@ -1440,9 +1443,19 @@ wxJSONValue FPP::CreateModelMemoryMap(ModelManager* allmodels, int32_t startChan } } - if (ogModels->Item(i).HasMember("StartChannel") && ogModels->Item(i)["StartChannel"].IsInt32()) { - auto ogStartChan = ogModels->Item(i)["StartChannel"].AsInt32(); - if (ogStartChan < startChan || ogStartChan > endChannel ) { + if (!IsVersionAtLeast(8, 0)) { + //I don't think this works + if (ogModels->Item(i).HasMember("StartChannel") && ogModels->Item(i)["StartChannel"].IsInt32()) { + auto ogStartChan = ogModels->Item(i)["StartChannel"].AsInt32(); + if (ogStartChan < startChan || ogStartChan > endChannel ) { + continue; + } + } + } + + if (ogModels->Item(i).HasMember("xLights") && ogModels->Item(i)["xLights"].IsBool()) { + auto isfromXlights = ogModels->Item(i)["xLights"].AsBool(); + if (isfromXlights) { continue; } } @@ -2842,25 +2855,53 @@ bool FPP::UploadPixelOutputs(ModelManager* allmodels, bool FPP::UploadControllerProxies(OutputManager* outputManager) { - auto currentProxies = GetProxies(); - std::vector newProxies; + if(IsVersionAtLeast(8, 0)) { + auto currentProxies = GetProxies(); + for (const auto& it : outputManager->GetControllers()) { + auto c = dynamic_cast(it); + if (c != nullptr) { + std::string proxy_ip = ip_utils::ResolveIP(c->GetFPPProxy()); + if (ipAddress.compare(proxy_ip) == 0) { + auto const& controller_ip = c->GetIP(); + auto const& controller_name = c->GetName(); + if (std::find_if(currentProxies.begin(), currentProxies.end(), + [controller_ip](auto const& pro) { return get<0>(pro) == controller_ip; }) == currentProxies.end()) { + currentProxies.emplace_back(controller_ip, controller_name); + } + } + } + } - for (const auto& it : outputManager->GetControllers()) { - auto c = dynamic_cast(it); - if (c != nullptr) { - std::string proxy_ip = ip_utils::ResolveIP(c->GetFPPProxy()); - if (ipAddress.compare(proxy_ip) == 0) { - auto controllerip = c->GetIP(); - if (std::find(currentProxies.begin(), currentProxies.end(), controllerip) == currentProxies.end()) { - newProxies.push_back(controllerip); - currentProxies.push_back(controllerip); + wxJSONValue proxies; + for (const auto& [ip, description] : currentProxies) { + wxJSONValue proxy; + proxy["host"] = ip; + proxy["description"] = description; + proxies.Append(proxy); + } + + return PostJSONToURL("/api/proxies", proxies); + } else { + auto currentProxies = GetProxyList(); + std::vector newProxies; + + for (const auto& it : outputManager->GetControllers()) { + auto c = dynamic_cast(it); + if (c != nullptr) { + std::string proxy_ip = ip_utils::ResolveIP(c->GetFPPProxy()); + if (ipAddress.compare(proxy_ip) == 0) { + auto controllerip = c->GetIP(); + if (std::find(currentProxies.begin(), currentProxies.end(), controllerip) == currentProxies.end()) { + newProxies.push_back(controllerip); + currentProxies.push_back(controllerip); + } } } } - } - for (const auto& nprox : newProxies) { - PostToURL("/api/proxies/" + nprox, "", "text/plain"); + for (const auto& nprox : newProxies) { + PostToURL("/api/proxies/" + nprox, "", "text/plain"); + } } return false; } @@ -3156,7 +3197,12 @@ static void ProcessFPPProxies(Discovery &discovery, const std::string &ip, const DiscoveredData *ipinst = discovery.FindByIp(ip, "", true); ipinst->extraData["httpConnected"] = true; for (int x = 0; x < origJson.Size(); x++) { - std::string proxy = ToUTF8(origJson[x].AsString()); + std::string proxy; + if (origJson[x].IsString()) { + proxy = ToUTF8(origJson[x].AsString()); + } else if (origJson[x].IsObject()) {//FPP 8 change + proxy = ToUTF8(origJson[x]["host"].AsString()); + } DiscoveredData *inst = discovery.FindByIp(proxy, "", true); if (!inst->extraData.HasMember("httpConnected")) { inst->extraData["httpConnected"] = false; @@ -3729,11 +3775,15 @@ void FPP::TypeIDtoControllerType(int typeId, FPP* inst) { } } -std::vector FPP::GetProxies() -{ +std::vector FPP::GetProxyList() { + auto kp = std::views::keys(GetProxies()); + return { kp.begin(), kp.end() }; +} + +std::vector> FPP::GetProxies() { static log4cpp::Category& logger_base = log4cpp::Category::getInstance(std::string("log_base")); - std::vector res; + std::vector> res; if (IsConnected()) { wxJSONValue val; @@ -3741,7 +3791,10 @@ std::vector FPP::GetProxies() for (int x = 0; x < val.Size(); x++) { if (val[x].IsString()) { logger_base.debug("FPP %s proxies %s.", (const char*)ipAddress.c_str(), (const char*)val[x].AsString().c_str()); - res.push_back(ToUTF8(val[x].AsString())); + res.push_back({ ToUTF8(val[x].AsString()), std::string() }); + } else if (val[x].IsObject()) { // FPP 8 change + logger_base.debug("FPP %s proxies %s.", (const char*)ipAddress.c_str(), (const char*)val[x]["host"].AsString().c_str()); + res.push_back({ ToUTF8(val[x]["host"].AsString()), ToUTF8(val[x]["description"].AsString()) }); } } } @@ -3755,7 +3808,7 @@ bool FPP::ValidateProxy(const std::string& to, const std::string& via) { FPP fpp(via); if (fpp.IsConnected()) { - for (const auto& it : fpp.GetProxies()) { + for (const auto& it : fpp.GetProxyList()) { if (to == it) return true; } } diff --git a/xLights/controllers/FPP.h b/xLights/controllers/FPP.h index 83ac9c0bd9..fb89dcb4f2 100644 --- a/xLights/controllers/FPP.h +++ b/xLights/controllers/FPP.h @@ -77,7 +77,7 @@ class FPP : public BaseController void SetNewRanges(const std::map &rngs); bool IsDDPInputEnabled(); - bool IsVersionAtLeast(uint32_t maj, uint32_t min, uint32_t patch = 0) const; + [[nodiscard]] bool IsVersionAtLeast(uint32_t maj, uint32_t min, uint32_t patch = 0) const; #ifndef DISCOVERYONLY bool PrepareUploadSequence(FSEQFile *file, @@ -120,7 +120,8 @@ class FPP : public BaseController bool SetRestartFlag(); bool Restart(bool ifNeeded = false); void SetDescription(const std::string &st); - std::vector GetProxies(); + [[nodiscard]] std::vector GetProxyList(); + [[nodiscard]] std::vector> GetProxies(); static void PrepareDiscovery(Discovery &discovery); static void PrepareDiscovery(Discovery &discovery, const std::list &addresses, bool broadcastPing = true); @@ -152,20 +153,19 @@ class FPP : public BaseController FPPUploadProgressDialog *progressDialog = nullptr; wxGauge *progress = nullptr; - void DumpJSON(const wxJSONValue& json); + void DumpJSON(const wxJSONValue& json) const; bool GetURLAsJSON(const std::string& url, wxJSONValue& val, bool recordError = true); bool GetURLAsString(const std::string& url, std::string& val, bool recordError = true); int PostJSONToURL(const std::string& url, const wxJSONValue& val); int PostJSONToURLAsFormData(const std::string& url, const std::string &extra, const wxJSONValue& val); - int PostToURL(const std::string& url, const std::string &val, const std::string &contentType = "application/octet-stream"); - int PostToURL(const std::string& url, const std::vector &val, const std::string &contentType = "application/octet-stream"); - int PutToURL(const std::string& url, const std::string &val, const std::string &contentType = "application/octet-stream"); - int PutToURL(const std::string& url, const std::vector &val, const std::string &contentType = "application/octet-stream"); - int TransferToURL(const std::string& url, const std::vector &val, const std::string &contentType, bool isPost); + int PostToURL(const std::string& url, const std::string& val, const std::string& contentType = "application/octet-stream") const; + int PostToURL(const std::string& url, const std::vector& val, const std::string& contentType = "application/octet-stream") const; + int PutToURL(const std::string& url, const std::string& val, const std::string& contentType = "application/octet-stream") const; + int PutToURL(const std::string& url, const std::vector& val, const std::string& contentType = "application/octet-stream") const; + int TransferToURL(const std::string& url, const std::vector& val, const std::string& contentType, bool isPost) const; - bool uploadOrCopyFile(const std::string &filename, const std::string &file, const std::string &dir); @@ -184,7 +184,7 @@ class FPP : public BaseController bool IsCompatible(const ControllerCaps *rules, std::string &origVend, std::string &origMod, std::string origVar, const std::string &origId, std::string &driver); - + class PlaylistEntry { public: std::string sequence; diff --git a/xLights/xLightsMain.cpp b/xLights/xLightsMain.cpp index c2fb0849cc..d9b79b392a 100644 --- a/xLights/xLightsMain.cpp +++ b/xLights/xLightsMain.cpp @@ -2312,6 +2312,16 @@ void xLightsFrame::OnAbout(wxCommandEvent& event) { wxString hdg = wxString::Format(_("About xLights %s"), GetDisplayVersionString()); wxString ver = wxString::Format(_("Version: %s\n%s"), GetDisplayVersionString(), wxVERSION_STRING); +#if defined(_MSC_VER) + ver += wxString::Format("\nVisual C++ %d" ,_MSC_VER); +#endif +#if defined(__clang_version__) + ver += wxString::Format("\nClang %s", __clang_version__); +#else +#if defined(__GNUC__)//clang also defines this + ver += wxString::Format("\nGCC %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); +#endif +#endif AboutDialog dlg(this); dlg.IconBitmap->SetIcon(wxArtProvider::GetIconBundle("xlART_xLights_Icons", wxART_FRAME_ICON).GetIcon(wxSize(128, 128)));