From ac6e84bb1cf0db3fe10cee2b9caa9122785e02be Mon Sep 17 00:00:00 2001 From: Bruno Date: Mon, 24 May 2021 20:39:56 +0200 Subject: [PATCH] New InfoVisitor: get string to describe sources Unified code in ImGui visitor and Player --- CMakeLists.txt | 1 + ImGuiVisitor.cpp | 43 +++---- ImGuiVisitor.h | 3 + InfoVisitor.cpp | 268 +++++++++++++++++++++++++++++++++++++++ InfoVisitor.h | 37 ++++++ MediaPlayer.cpp | 2 +- UserInterfaceManager.cpp | 46 ++----- Visitor.h | 4 +- 8 files changed, 345 insertions(+), 59 deletions(-) create mode 100644 InfoVisitor.cpp create mode 100644 InfoVisitor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 40e0bf8..12c1d2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -319,6 +319,7 @@ set(VMIX_SRCS SearchVisitor.cpp ImGuiToolkit.cpp ImGuiVisitor.cpp + InfoVisitor.cpp GstToolkit.cpp GlmToolkit.cpp SystemToolkit.cpp diff --git a/ImGuiVisitor.cpp b/ImGuiVisitor.cpp index 2be3e3a..fb58b0c 100644 --- a/ImGuiVisitor.cpp +++ b/ImGuiVisitor.cpp @@ -554,10 +554,9 @@ void ImGuiVisitor::visit (MediaSource& s) ImGui::Text("Video File"); // Media info - MediaPlayer *mp = s.mediaplayer(); ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - ImGui::Text("%s\n%d x %d px, %s", SystemToolkit::filename(s.path()).c_str(), - mp->width(), mp->height(), mp->media().codec_name.c_str()); + s.accept(info); + ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); // icon (>) to open player @@ -591,8 +590,8 @@ void ImGuiVisitor::visit (SessionFileSource& s) // info ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - ImGui::Text("%d sources in %s\n%d x %d px, RGB", s.session()->numSource(), SystemToolkit::filename(s.path()).c_str(), - s.session()->frame()->width(), s.session()->frame()->height() ); + s.accept(info); + ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); // icon (>) to open player @@ -646,7 +645,8 @@ void ImGuiVisitor::visit (SessionGroupSource& s) // info ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - ImGui::Text("%d sources in group\n%d x %d px, RGB", s.session()->numSource(), s.session()->frame()->width(), s.session()->frame()->height() ); + s.accept(info); + ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); // icon (>) to open player @@ -691,9 +691,9 @@ void ImGuiVisitor::visit (PatternSource& s) ImGui::Text("Pattern"); // stream info - Pattern *mp = s.pattern(); ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - ImGui::Text("%d x %d px, RGB", mp->width(), mp->height() ); + s.accept(info); + ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); // icon (>) to open player @@ -729,15 +729,10 @@ void ImGuiVisitor::visit (DeviceSource& s) ImGui::SameLine(0, 10); ImGui::Text("Device"); - // device info - DeviceConfigSet confs = Device::manager().config( Device::manager().index(s.device().c_str())); - if ( !confs.empty()) { - DeviceConfig best = *confs.rbegin(); - float fps = static_cast(best.fps_numerator) / static_cast(best.fps_denominator); - ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - ImGui::Text("%d x %d px @%.1ffps, %s %s ", best.width, best.height, fps, best.stream.c_str(), best.format.c_str()); - ImGui::PopTextWrapPos(); - } + ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + s.accept(info); + ImGui::Text("%s", info.str().c_str()); + ImGui::PopTextWrapPos(); // icon (>) to open player if ( s.playable() ) { @@ -772,14 +767,14 @@ void ImGuiVisitor::visit (NetworkSource& s) ImGui::SameLine(0, 10); ImGui::Text("Network stream"); - // network info - ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_STREAM, 0.9f)); ImGui::Text("%s", s.connection().c_str()); ImGui::PopStyleColor(1); - NetworkStream *ns = s.networkStream(); - ImGui::Text("%d x %d px, %s\nServer address %s", ns->resolution().x, ns->resolution().y, - NetworkToolkit::protocol_name[ns->protocol()], ns->serverAddress().c_str()); + + // network info + ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + s.accept(info); + ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); // icon (>) to open player @@ -809,8 +804,8 @@ void ImGuiVisitor::visit (MultiFileSource& s) // information text ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - ImGui::Text("%d numbered images [%d %d]\n%d x %d px, %s", s.sequence().max - s.sequence().min + 1, - s.sequence().min, s.sequence().max, s.sequence().width, s.sequence().height, s.sequence().codec.c_str()); + s.accept(info); + ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); // icon (>) to open player diff --git a/ImGuiVisitor.h b/ImGuiVisitor.h index 2fa46d2..818d625 100644 --- a/ImGuiVisitor.h +++ b/ImGuiVisitor.h @@ -2,9 +2,12 @@ #define IMGUIVISITOR_H #include "Visitor.h" +#include "InfoVisitor.h" class ImGuiVisitor: public Visitor { + InfoVisitor info; + public: ImGuiVisitor(); diff --git a/InfoVisitor.cpp b/InfoVisitor.cpp new file mode 100644 index 0000000..d2e3299 --- /dev/null +++ b/InfoVisitor.cpp @@ -0,0 +1,268 @@ +#include "InfoVisitor.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include "tinyxml2Toolkit.h" + +#include "defines.h" +#include "Log.h" +#include "Scene.h" +#include "Primitives.h" +#include "ImageShader.h" +#include "ImageProcessingShader.h" +#include "MediaPlayer.h" +#include "MediaSource.h" +#include "SessionSource.h" +#include "PatternSource.h" +#include "DeviceSource.h" +#include "NetworkSource.h" +#include "MultiFileSource.h" +#include "SessionCreator.h" +#include "SessionVisitor.h" +#include "Settings.h" +#include "Mixer.h" +#include "ActionManager.h" + +#include "BaseToolkit.h" +#include "UserInterfaceManager.h" +#include "SystemToolkit.h" + + +InfoVisitor::InfoVisitor(bool brief) : brief_(brief), current_id_(0) +{ + +} + + +void InfoVisitor::visit(Node &n) +{ +} + +void InfoVisitor::visit(Group &n) +{ +} + +void InfoVisitor::visit(Switch &n) +{ +} + +void InfoVisitor::visit(Scene &n) +{ +} + +void InfoVisitor::visit(Primitive &n) +{ +} + + + +void InfoVisitor::visit(MediaPlayer &mp) +{ + std::ostringstream oss; + if (brief_) { + oss << SystemToolkit::filename(mp.filename()) << std::endl; + oss << mp.width() << " x " << mp.height() << ", "; + oss << mp.media().codec_name.substr(0, mp.media().codec_name.find_first_of(',')); + if (!mp.isImage()) + oss << ", " << std::fixed << std::setprecision(1) << mp.frameRate() << " fps"; + } + else { + oss << mp.filename() << std::endl; + oss << mp.media().codec_name << std::endl; + oss << mp.width() << " x " << mp.height() ; + if (!mp.isImage()) + oss << ", " << std::fixed << std::setprecision(1) << mp.frameRate() << " fps"; + } + information_ = oss.str(); +} + +void InfoVisitor::visit(Stream &n) +{ + std::ostringstream oss; + if (brief_) { + + } + else { + + } + information_ = oss.str(); +} + + +void InfoVisitor::visit (MediaSource& s) +{ + if (current_id_ == s.id()) + return; + + s.mediaplayer()->accept(*this); + + current_id_ = s.id(); +} + +void InfoVisitor::visit (SessionFileSource& s) +{ + if (current_id_ == s.id() || s.session() == nullptr) + return; + + std::ostringstream oss; + if (brief_) { + oss << SystemToolkit::filename(s.path()) << " ("; + oss << s.session()->numSource() << " sources)" << std::endl; + oss << s.session()->frame()->width() << " x " << s.session()->frame()->height() << ", "; + oss << "RGB"; + } + else { + oss << s.path() << std::endl; + oss << s.session()->frame()->width() << " x " << s.session()->frame()->height() << ", "; + oss << "RGB"; + } + + information_ = oss.str(); + current_id_ = s.id(); +} + +void InfoVisitor::visit (SessionGroupSource& s) +{ + if (current_id_ == s.id() || s.session() == nullptr) + return; + + std::ostringstream oss; + if (brief_) { + oss << s.session()->numSource() << " sources in group" << std::endl; + oss << s.session()->frame()->width() << " x " << s.session()->frame()->height() << ", "; + oss << "RGB"; + } + else { + oss << s.session()->numSource() << " sources in group" << std::endl; + oss << s.session()->frame()->width() << " x " << s.session()->frame()->height() << ", "; + oss << "RGB"; + } + + information_ = oss.str(); + current_id_ = s.id(); +} + +void InfoVisitor::visit (RenderSource& s) +{ + if (current_id_ == s.id()) + return; + + information_ = "Rendering Output"; + current_id_ = s.id(); +} + +void InfoVisitor::visit (CloneSource& s) +{ + if (current_id_ == s.id()) + return; + + information_ = "Clone of " + s.origin()->name(); + current_id_ = s.id(); +} + +void InfoVisitor::visit (PatternSource& s) +{ + if (current_id_ == s.id()) + return; + + std::ostringstream oss; + if (brief_) { + oss << s.pattern()->width() << " x " << s.pattern()->height(); + oss << ", RGB"; + } + else { + std::string desc = s.stream()->description(); + oss << desc.substr(0, desc.find_first_of('!')) << std::endl; + oss << s.pattern()->width() << " x " << s.pattern()->height(); + oss << ", RGB"; + } + + information_ = oss.str(); + current_id_ = s.id(); +} + +void InfoVisitor::visit (DeviceSource& s) +{ + if (current_id_ == s.id()) + return; + + std::ostringstream oss; + + DeviceConfigSet confs = Device::manager().config( Device::manager().index(s.device().c_str())); + if ( !confs.empty()) { + DeviceConfig best = *confs.rbegin(); + float fps = static_cast(best.fps_numerator) / static_cast(best.fps_denominator); + + if (brief_) { + oss << best.width << " x " << best.height << ", "; + oss << best.stream << " " << best.format << ", "; + oss << std::fixed << std::setprecision(1) << fps << " fps"; + } + else { + oss << s.device() << std::endl; + oss << best.width << " x " << best.height << ", "; + oss << best.stream << " " << best.format << ", "; + oss << std::fixed << std::setprecision(1) << fps << " fps"; + } + } + + information_ = oss.str(); + current_id_ = s.id(); +} + +void InfoVisitor::visit (NetworkSource& s) +{ + if (current_id_ == s.id()) + return; + + NetworkStream *ns = s.networkStream(); + + std::ostringstream oss; + if (brief_) { + oss << ns->resolution().x << " x " << ns->resolution().y << ", "; + oss << NetworkToolkit::protocol_name[ns->protocol()] << std::endl; + oss << "IP " << ns->serverAddress(); + } + else { + oss << s.connection() << " (IP " << ns->serverAddress() << ")" << std::endl; + oss << ns->resolution().x << " x " << ns->resolution().y << ", "; + oss << NetworkToolkit::protocol_name[ns->protocol()]; + } + + information_ = oss.str(); + current_id_ = s.id(); +} + + +void InfoVisitor::visit (MultiFileSource& s) +{ + if (current_id_ == s.id()) + return; + + std::ostringstream oss; + if (brief_) { + oss << s.sequence().width << " x " << s.sequence().height << ", "; + oss << s.sequence().codec << std::endl; + oss << s.sequence().max - s.sequence().min + 1 << " images ["; + oss << s.sequence().min << " - " << s.sequence().max << "]"; + } + else { + oss << SystemToolkit::path_filename(s.sequence().location) ; + oss << " " << s.sequence().max - s.sequence().min + 1 << " images ["; + oss << s.sequence().min << " - " << s.sequence().max << "]" << std::endl; + oss << s.sequence().width << " x " << s.sequence().height << ", "; + oss << s.sequence().codec; + } + + information_ = oss.str(); + current_id_ = s.id(); +} diff --git a/InfoVisitor.h b/InfoVisitor.h new file mode 100644 index 0000000..2db7616 --- /dev/null +++ b/InfoVisitor.h @@ -0,0 +1,37 @@ +#ifndef INFOVISITOR_H +#define INFOVISITOR_H + +#include "Visitor.h" + +class InfoVisitor : public Visitor +{ + std::string information_; + bool brief_; + uint64_t current_id_; + +public: + InfoVisitor(bool brief = true); + inline std::string str() const { return information_; } + + // Elements of Scene + void visit (Scene& n) override; + void visit (Node& n) override; + void visit (Group& n) override; + void visit (Switch& n) override; + void visit (Primitive& n) override; + + // Elements with attributes + void visit (Stream& n) override; + void visit (MediaPlayer& n) override; + void visit (MediaSource& s) override; + void visit (SessionFileSource& s) override; + void visit (SessionGroupSource& s) override; + void visit (RenderSource& s) override; + void visit (CloneSource& s) override; + void visit (PatternSource& s) override; + void visit (DeviceSource& s) override; + void visit (NetworkSource& s) override; + void visit (MultiFileSource& s) override; +}; + +#endif // INFOVISITOR_H diff --git a/MediaPlayer.cpp b/MediaPlayer.cpp index 46a2653..a3019a6 100644 --- a/MediaPlayer.cpp +++ b/MediaPlayer.cpp @@ -186,7 +186,7 @@ MediaInfo MediaPlayer::UriDiscoverer(const std::string &uri) if ( tags ) { gchar *container = NULL; if ( gst_tag_list_get_string (tags, GST_TAG_CONTAINER_FORMAT, &container) ) - video_stream_info.codec_name += " " + std::string(container); + video_stream_info.codec_name += ", " + std::string(container); if (container) g_free(container); } diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index 5d2fdd3..87614c6 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -2404,26 +2404,17 @@ void SourceController::RenderSingleSource(Source *s) ImGui::Text("%s %s", ICON_FA_SNOWFLAKE, GstToolkit::time_to_string(s->playtime()).c_str() ); ImGui::PopFont(); - StreamSource *sts = dynamic_cast(s); - if (sts !=nullptr){ - ImGui::SetCursorScreenPos(top + ImVec2(framesize.x - ImGui::GetTextLineHeightWithSpacing(), _v_space)); - ImGui::Text(ICON_FA_INFO_CIRCLE); - if (ImGui::IsItemHovered()){ - std::ostringstream tooltip; - std::string desc = sts->stream()->description(); - desc = desc.substr(0, desc.find_first_of('!')); - tooltip << desc << "\n "; - tooltip << sts->stream()->width() << " x " << sts->stream()->height() << " px, "; - tooltip << std::fixed << std::setprecision(2) << sts->stream()->updateFrameRate() << " fps "; + ImGui::SetCursorScreenPos(top + ImVec2(framesize.x - ImGui::GetTextLineHeightWithSpacing(), _v_space)); + ImGui::Text(ICON_FA_INFO_CIRCLE); + if (ImGui::IsItemHovered()){ + static InfoVisitor info(false); + s->accept(info); - float tooltip_height = 2.f * ImGui::GetTextLineHeightWithSpacing(); - - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - draw_list->AddRectFilled(top, top + ImVec2(framesize.x, tooltip_height), IMGUI_COLOR_OVERLAY); - - ImGui::SetCursorScreenPos(top + ImVec2(0, _v_space)); - ImGui::Text(" %s", tooltip.str().c_str()); - } + float tooltip_height = 2.f * ImGui::GetTextLineHeightWithSpacing(); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRectFilled(top, top + ImVec2(framesize.x, tooltip_height), IMGUI_COLOR_OVERLAY); + ImGui::SetCursorScreenPos(top + ImVec2(_h_space, _v_space)); + ImGui::Text("%s", info.str().c_str()); } /// @@ -2474,23 +2465,14 @@ void SourceController::RenderMediaPlayer(MediaPlayer *mp) ImGui::SetCursorScreenPos(top + ImVec2(framesize.x - ImGui::GetTextLineHeightWithSpacing(), _v_space)); ImGui::Text(ICON_FA_INFO_CIRCLE); if (ImGui::IsItemHovered()){ - - std::ostringstream tooltip; - tooltip << mp->filename() << "\n "; - tooltip << mp->media().codec_name; - if (Settings::application.render.gpu_decoding && !mp->hardwareDecoderName().empty() ) - tooltip << " (" << mp->hardwareDecoderName() << " hardware decoder)"; - tooltip << " \n " << mp->width() << " x " << mp->height() << " px, "; - if ( mp->frameRate() > 1.f ) - tooltip << std::fixed << std::setprecision(2) << mp->updateFrameRate() << " / " << mp->frameRate() << " fps "; + static InfoVisitor info(false); + mp->accept(info); float tooltip_height = 3.f * ImGui::GetTextLineHeightWithSpacing(); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); draw_list->AddRectFilled(top, top + ImVec2(framesize.x, tooltip_height), IMGUI_COLOR_OVERLAY); - - ImGui::SetCursorScreenPos(top + ImVec2(0, _v_space)); - ImGui::Text(" %s", tooltip.str().c_str()); + ImGui::SetCursorScreenPos(top + ImVec2(_h_space, _v_space)); + ImGui::Text("%s", info.str().c_str()); } /// diff --git a/Visitor.h b/Visitor.h index b6e0262..af4dc0f 100644 --- a/Visitor.h +++ b/Visitor.h @@ -63,14 +63,14 @@ public: virtual void visit (Handles&) {} virtual void visit (Symbol&) {} virtual void visit (Disk&) {} - virtual void visit (Stream&) {} - virtual void visit (MediaPlayer&) {} virtual void visit (Shader&) {} virtual void visit (ImageShader&) {} virtual void visit (MaskShader&) {} virtual void visit (ImageProcessingShader&) {} // utility + virtual void visit (Stream&) {} + virtual void visit (MediaPlayer&) {} virtual void visit (MixingGroup&) {} virtual void visit (Source&) {} virtual void visit (MediaSource&) {}