diff --git a/src/Connection.h b/src/Connection.h index e33fce2..06fb74a 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -2,10 +2,12 @@ #define CONNECTION_H #include +#include #include #include -#include "NetworkToolkit.h" +#include +#include #define MAX_HANDSHAKE 20 #define HANDSHAKE_PORT 71310 diff --git a/src/ImGuiVisitor.cpp b/src/ImGuiVisitor.cpp index e1af4b9..f101dca 100644 --- a/src/ImGuiVisitor.cpp +++ b/src/ImGuiVisitor.cpp @@ -380,13 +380,14 @@ void ImGuiVisitor::visit (Source& s) const float preview_height = 4.5f * ImGui::GetFrameHeightWithSpacing(); const float space = ImGui::GetStyle().ItemSpacing.y; + ImGui::PushID(std::to_string(s.id()).c_str()); + + // blending selection + s.blendingShader()->accept(*this); + + // Draw different info if failed or succeed if ( !s.failed() ) { - ImGui::PushID(std::to_string(s.id()).c_str()); - - // blending selection - s.blendingShader()->accept(*this); - // remember where we were... ImVec2 pos = ImGui::GetCursorPos(); @@ -538,10 +539,6 @@ void ImGuiVisitor::visit (Source& s) s.processingShader()->accept(*this); } - ImGui::Spacing(); - - ImGui::PopID(); - } else { @@ -568,12 +565,15 @@ void ImGuiVisitor::visit (Source& s) // back ImGui::SetCursorPos( ImVec2( pos.x, pos.y + preview_height)); - ImGui::Spacing(); } + ImGui::PopID(); + + ImGui::Spacing(); ImGuiToolkit::Icon(s.icon().x, s.icon().y); ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::Text("%s", s.info().c_str()); + } void ImGuiVisitor::visit (MediaSource& s) @@ -584,32 +584,28 @@ void ImGuiVisitor::visit (MediaSource& s) ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); - // icon (>) to open player - if ( s.playable() ) { - ImVec2 pos = ImGui::GetCursorPos(); - ImGui::SameLine(0, 0); - ImGui::SameLine(0, 10.f + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) - UserInterface::manager().showSourceEditor(&s); - ImGui::SetCursorPos(pos); + if ( !s.failed() ) { + // icon (>) to open player + if ( s.playable() ) { + ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SameLine(0, 0); + ImGui::SameLine(0, 10.f + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) + UserInterface::manager().showSourceEditor(&s); + ImGui::SetCursorPos(pos); + } } + else + info.reset(); // folder std::string path = SystemToolkit::path_filename(s.path()); std::string label = BaseToolkit::truncated(path, 25); label = BaseToolkit::transliterate(label); ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) ); - ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::Text("Folder"); -// ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); -// if ( ImGui::Button("Replace") ) { - -// s.setPath("/home/bh/Videos/iss.mov"); -// Mixer::manager().recreateSource( Mixer::manager().findSource( s.id() ) ); - -// } } void ImGuiVisitor::visit (SessionFileSource& s) @@ -623,58 +619,65 @@ void ImGuiVisitor::visit (SessionFileSource& s) ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); - // icon (>) to open player - if ( s.playable() ) { - ImVec2 pos = ImGui::GetCursorPos(); - ImGui::SameLine(0, 0); - ImGui::SameLine(0, 10.f + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) - UserInterface::manager().showSourceEditor(&s); - ImGui::SetCursorPos(pos); - } + if ( !s.failed() ) { - if ( ImGui::Button( ICON_FA_SIGN_OUT_ALT " Import", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) - Mixer::manager().import( &s ); - ImGui::SameLine(0, IMGUI_SAME_LINE); - ImGui::Text("Sources"); - - // versions - SessionSnapshots *versions = s.session()->snapshots(); - if (versions->keys_.size()>0) { - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::BeginCombo("Version", ICON_FA_CODE_BRANCH " Select" ) ) - { - for (auto v = versions->keys_.crbegin() ; v != versions->keys_.crend(); ++v){ - std::string label = std::to_string(*v); - const tinyxml2::XMLElement *snap = versions->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(*v).c_str() ); - if (snap) - label = snap->Attribute("label"); - if (ImGui::Selectable( label.c_str() )) { - s.session()->applySnapshot(*v); - } - } - ImGui::EndCombo(); + // icon (>) to open player + if ( s.playable() ) { + ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SameLine(0, 0); + ImGui::SameLine(0, 10.f + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) + UserInterface::manager().showSourceEditor(&s); + ImGui::SetCursorPos(pos); } - } - // fading - if (ImGuiToolkit::IconButton(2, 1)) s.session()->setFadingTarget(0.f); - int f = 100 - int(s.session()->fading() * 100.f); - ImGui::SameLine(0, IMGUI_SAME_LINE); - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::SliderInt("Fading", &f, 0, 100, f > 99 ? "None" : "%d %%") ) - s.session()->setFadingTarget( float(100 - f) * 0.01f ); - if (ImGui::IsItemDeactivatedAfterEdit()){ - std::ostringstream oss; - oss << s.name() << ": Fading " << f << " %"; - Action::manager().store(oss.str()); - } + if ( ImGui::Button( ICON_FA_SIGN_OUT_ALT " Import", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) + Mixer::manager().import( &s ); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::Text("Sources"); + + // versions + SessionSnapshots *versions = s.session()->snapshots(); + if (versions->keys_.size()>0) { + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + if (ImGui::BeginCombo("Version", ICON_FA_CODE_BRANCH " Select" ) ) + { + for (auto v = versions->keys_.crbegin() ; v != versions->keys_.crend(); ++v){ + std::string label = std::to_string(*v); + const tinyxml2::XMLElement *snap = versions->xmlDoc_->FirstChildElement( SNAPSHOT_NODE(*v).c_str() ); + if (snap) + label = snap->Attribute("label"); + if (ImGui::Selectable( label.c_str() )) { + s.session()->applySnapshot(*v); + } + } + ImGui::EndCombo(); + } + } + + // fading + if (ImGuiToolkit::IconButton(2, 1)) s.session()->setFadingTarget(0.f); + int f = 100 - int(s.session()->fading() * 100.f); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + if (ImGui::SliderInt("Fading", &f, 0, 100, f > 99 ? "None" : "%d %%") ) + s.session()->setFadingTarget( float(100 - f) * 0.01f ); + if (ImGui::IsItemDeactivatedAfterEdit()){ + std::ostringstream oss; + oss << s.name() << ": Fading " << f << " %"; + Action::manager().store(oss.str()); + } + + // file open + if ( ImGui::Button( ICON_FA_FILE_UPLOAD " Open", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) + Mixer::manager().set( s.detach() ); + ImGui::SameLine(0, IMGUI_SAME_LINE); + ImGui::Text("File"); + + } + else + info.reset(); - // file open - if ( ImGui::Button( ICON_FA_FILE_UPLOAD " Open", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) - Mixer::manager().set( s.detach() ); - ImGui::SameLine(0, IMGUI_SAME_LINE); - ImGui::Text("File"); // file path std::string path = SystemToolkit::path_filename(s.path()); std::string label = BaseToolkit::truncated(path, 25); @@ -698,7 +701,7 @@ void ImGuiVisitor::visit (SessionGroupSource& s) ImGui::PopTextWrapPos(); // icon (>) to open player - if ( s.playable() ) { + if ( s.playable() && !s.failed() ) { ImVec2 pos = ImGui::GetCursorPos(); ImGui::SameLine(0, 0); ImGui::SameLine(0, 10.f + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); @@ -1078,21 +1081,27 @@ void ImGuiVisitor::visit (PatternSource& s) ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); - // icon (>) to open player - if ( s.playable() ) { - ImVec2 pos = ImGui::GetCursorPos(); - ImGui::SameLine(0, 0); - ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) - UserInterface::manager().showSourceEditor(&s); - ImGui::SetCursorPos(pos); + if ( !s.failed() ) { + // icon (>) to open player + if ( s.playable() ) { + ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SameLine(0, 0); + ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) + UserInterface::manager().showSourceEditor(&s); + ImGui::SetCursorPos(pos); + } } + else + info.reset(); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::BeginCombo("##Patterns", Pattern::get(s.pattern()->type()).label.c_str()) ) + if (ImGui::BeginCombo("##Patterns", Pattern::get(s.pattern()->type()).label.c_str(), ImGuiComboFlags_HeightLarge) ) { for (uint p = 0; p < Pattern::count(); ++p){ - if (ImGui::Selectable( Pattern::get(p).label.c_str() )) { + pattern_descriptor pattern = Pattern::get(p); + std::string label = pattern.label + (pattern.animated ? " " ICON_FA_CARET_RIGHT : " "); + if (pattern.available && ImGui::Selectable( label.c_str(), p == s.pattern()->type() )) { s.setPattern(p, s.pattern()->resolution()); info.reset(); std::ostringstream oss; @@ -1113,15 +1122,19 @@ void ImGuiVisitor::visit (DeviceSource& s) ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); - // icon (>) to open player - if ( s.playable() ) { - ImVec2 pos = ImGui::GetCursorPos(); - ImGui::SameLine(0, 0); - ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) - UserInterface::manager().showSourceEditor(&s); - ImGui::SetCursorPos(pos); + if ( !s.failed() ) { + // icon (>) to open player + if ( s.playable() ) { + ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SameLine(0, 0); + ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) + UserInterface::manager().showSourceEditor(&s); + ImGui::SetCursorPos(pos); + } } + else + info.reset(); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); if (ImGui::BeginCombo("Device", s.device().c_str())) @@ -1152,21 +1165,25 @@ void ImGuiVisitor::visit (NetworkSource& s) ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); - // icon (>) to open player - if ( s.playable() ) { - ImVec2 pos = ImGui::GetCursorPos(); - ImGui::SameLine(0, 0); - ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) - UserInterface::manager().showSourceEditor(&s); - ImGui::SetCursorPos(pos); + if ( !s.failed() ) { + // icon (>) to open player + if ( s.playable() ) { + ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SameLine(0, 0); + ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) + UserInterface::manager().showSourceEditor(&s); + ImGui::SetCursorPos(pos); + } } - - if ( ImGui::Button( ICON_FA_REPLY " Reconnect", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) - { - s.setConnection(s.connection()); + else info.reset(); - } + +// if ( ImGui::Button( ICON_FA_REPLY " Reconnect", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) +// { +// s.setConnection(s.connection()); +// info.reset(); +// } } @@ -1180,54 +1197,59 @@ void ImGuiVisitor::visit (MultiFileSource& s) ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); - // icon (>) to open player - if ( s.playable() ) { - ImVec2 pos = ImGui::GetCursorPos(); - ImGui::SameLine(0, 0); - ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) - UserInterface::manager().showSourceEditor(&s); - ImGui::SetCursorPos(pos); - } + if ( !s.failed() ) { - // Filename pattern - ImGuiTextBuffer info; - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f)); - info.appendf("%s", SystemToolkit::base_filename(s.sequence().location).c_str()); - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - ImGui::InputText("Filenames", (char *)info.c_str(), info.size(), ImGuiInputTextFlags_ReadOnly); - ImGui::PopStyleColor(1); + // icon (>) to open player + if ( s.playable() ) { + ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SameLine(0, 0); + ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) + UserInterface::manager().showSourceEditor(&s); + ImGui::SetCursorPos(pos); + } - // change range - static int _begin = -1; - if (_begin < 0 || id != s.id()) - _begin = s.begin(); - static int _end = -1; - if (_end < 0 || id != s.id()) - _end = s.end(); - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - ImGui::DragIntRange2("Range", &_begin, &_end, 1, s.sequence().min, s.sequence().max); - if (ImGui::IsItemDeactivatedAfterEdit()){ - s.setRange( _begin, _end ); - std::ostringstream oss; - oss << s.name() << ": Range " << _begin << "-" << _end; - Action::manager().store(oss.str()); - _begin = _end = -1; - } + // Filename pattern + ImGuiTextBuffer info; + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f)); + info.appendf("%s", SystemToolkit::base_filename(s.sequence().location).c_str()); + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + ImGui::InputText("Filenames", (char *)info.c_str(), info.size(), ImGuiInputTextFlags_ReadOnly); + ImGui::PopStyleColor(1); - // change framerate - static int _fps = -1; - if (_fps < 0 || id != s.id()) - _fps = s.framerate(); - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - ImGui::SliderInt("Framerate", &_fps, 1, 30, "%d fps"); - if (ImGui::IsItemDeactivatedAfterEdit()){ - s.setFramerate(_fps); - std::ostringstream oss; - oss << s.name() << ": Framerate " << _fps << " fps"; - Action::manager().store(oss.str()); - _fps = -1; + // change range + static int _begin = -1; + if (_begin < 0 || id != s.id()) + _begin = s.begin(); + static int _end = -1; + if (_end < 0 || id != s.id()) + _end = s.end(); + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + ImGui::DragIntRange2("Range", &_begin, &_end, 1, s.sequence().min, s.sequence().max); + if (ImGui::IsItemDeactivatedAfterEdit()){ + s.setRange( _begin, _end ); + std::ostringstream oss; + oss << s.name() << ": Range " << _begin << "-" << _end; + Action::manager().store(oss.str()); + _begin = _end = -1; + } + + // change framerate + static int _fps = -1; + if (_fps < 0 || id != s.id()) + _fps = s.framerate(); + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + ImGui::SliderInt("Framerate", &_fps, 1, 30, "%d fps"); + if (ImGui::IsItemDeactivatedAfterEdit()){ + s.setFramerate(_fps); + std::ostringstream oss; + oss << s.name() << ": Framerate " << _fps << " fps"; + Action::manager().store(oss.str()); + _fps = -1; + } } + else + info.reset(); // offer to open file browser at location std::string path = SystemToolkit::path_filename(s.sequence().location); @@ -1251,15 +1273,19 @@ void ImGuiVisitor::visit (GenericStreamSource& s) ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); - // icon (>) to open player - if ( s.playable() ) { - ImVec2 pos = ImGui::GetCursorPos(); - ImGui::SameLine(0, 0); - ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) - UserInterface::manager().showSourceEditor(&s); - ImGui::SetCursorPos(pos); + if ( !s.failed() ) { + // icon (>) to open player + if ( s.playable() ) { + ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SameLine(0, 0); + ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) + UserInterface::manager().showSourceEditor(&s); + ImGui::SetCursorPos(pos); + } } + else + info.reset(); // Prepare display pipeline text static int numlines = 0; @@ -1284,15 +1310,19 @@ void ImGuiVisitor::visit (SrtReceiverSource& s) ImGui::Text("%s", info.str().c_str()); ImGui::PopTextWrapPos(); - // icon (>) to open player - if ( s.playable() ) { - ImVec2 pos = ImGui::GetCursorPos(); - ImGui::SameLine(0, 0); - ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); - if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) - UserInterface::manager().showSourceEditor(&s); - ImGui::SetCursorPos(pos); + if ( !s.failed() ) { + // icon (>) to open player + if ( s.playable() ) { + ImVec2 pos = ImGui::GetCursorPos(); + ImGui::SameLine(0, 0); + ImGui::SameLine(0, IMGUI_SAME_LINE + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN); + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Open in Player")) + UserInterface::manager().showSourceEditor(&s); + ImGui::SetCursorPos(pos); + } } + else + info.reset(); // if ( ImGui::Button( ICON_FA_REPLY " Reconnect", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) // { diff --git a/src/InfoVisitor.cpp b/src/InfoVisitor.cpp index de40043..1aa86dd 100644 --- a/src/InfoVisitor.cpp +++ b/src/InfoVisitor.cpp @@ -27,15 +27,8 @@ #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 "CloneSource.h" @@ -46,13 +39,8 @@ #include "NetworkSource.h" #include "SrtReceiverSource.h" #include "MultiFileSource.h" -#include "SessionCreator.h" -#include "SessionVisitor.h" -#include "Settings.h" -#include "Mixer.h" -#include "ActionManager.h" +#include "Session.h" #include "BaseToolkit.h" -#include "UserInterfaceManager.h" #include "SystemToolkit.h" #include "InfoVisitor.h" @@ -102,19 +90,24 @@ void InfoVisitor::visit(MediaPlayer &mp) return; std::ostringstream oss; - if (brief_) { - oss << SystemToolkit::filename(mp.filename()) << std::endl; - oss << mp.media().codec_name.substr(0, mp.media().codec_name.find_first_of(" (,")) << ", "; - oss << mp.width() << " x " << mp.height(); - if (!mp.isImage()) - oss << ", " << std::fixed << std::setprecision(0) << mp.frameRate() << "fps"; + if (mp.failed()) { + oss << mp.filename() << std::endl << mp.log(); } 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"; + if (brief_) { + oss << SystemToolkit::filename(mp.filename()) << std::endl; + oss << mp.media().codec_name.substr(0, mp.media().codec_name.find_first_of(" (,")) << ", "; + oss << mp.width() << " x " << mp.height(); + if (!mp.isImage() && mp.frameRate() > 0.) + oss << ", " << std::fixed << std::setprecision(0) << 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() && mp.frameRate() > 0.) + oss << ", " << std::fixed << std::setprecision(1) << mp.frameRate() << " fps"; + } } information_ = oss.str(); @@ -139,7 +132,12 @@ void InfoVisitor::visit(Stream &n) void InfoVisitor::visit (MediaSource& s) { + if (current_id_ == s.id()) + return; + s.mediaplayer()->accept(*this); + + current_id_ = s.id(); } void InfoVisitor::visit (SessionFileSource& s) @@ -254,16 +252,24 @@ void InfoVisitor::visit (PatternSource& s) return; std::ostringstream oss; - if (s.pattern()) { - if (brief_) { - oss << "RGBA, " << s.pattern()->width() << " x " << s.pattern()->height(); - } + + Pattern *ptn = s.pattern(); + if (ptn) { + if (ptn->failed()) + oss << ptn->description() << std::endl << ptn->log(); else { - oss << Pattern::get(s.pattern()->type()).label << " pattern" << std::endl; - oss << "RGBA" << std::endl; - oss << s.pattern()->width() << " x " << s.pattern()->height(); + if (brief_) { + oss << "RGBA, " << ptn->width() << " x " << ptn->height(); + } + else { + oss << Pattern::get(ptn->type()).label << " pattern" << std::endl; + oss << "RGBA" << std::endl; + oss << ptn->width() << " x " << ptn->height(); + } } } + else + oss << "Undefined"; information_ = oss.str(); current_id_ = s.id(); @@ -294,6 +300,9 @@ void InfoVisitor::visit (DeviceSource& s) oss << std::fixed << std::setprecision(1) << fps << " fps"; } } + else { + oss << s.device() << " not available."; + } information_ = oss.str(); current_id_ = s.id(); @@ -304,20 +313,29 @@ void InfoVisitor::visit (NetworkSource& s) if (current_id_ == s.id()) return; - NetworkStream *ns = s.networkStream(); + std::ostringstream oss; - std::ostringstream oss; - if (brief_) { - oss << NetworkToolkit::stream_protocol_label[ns->protocol()] << std::endl; - oss << "IP " << ns->serverAddress() << std::endl; - oss << ns->resolution().x << " x " << ns->resolution().y; - } - else { - oss << s.connection() << std::endl; - oss << NetworkToolkit::stream_protocol_label[ns->protocol()]; - oss << " shared from IP " << ns->serverAddress() << std::endl; - oss << ns->resolution().x << " x " << ns->resolution().y; + NetworkStream *ns = s.networkStream(); + if (ns) { + if (ns->failed()) { + oss << s.stream()->log(); + } + else { + if (brief_) { + oss << NetworkToolkit::stream_protocol_label[ns->protocol()] << std::endl; + oss << "IP " << ns->serverAddress() << std::endl; + oss << ns->resolution().x << " x " << ns->resolution().y; + } + else { + oss << s.connection() << std::endl; + oss << NetworkToolkit::stream_protocol_label[ns->protocol()]; + oss << " shared from IP " << ns->serverAddress() << std::endl; + oss << ns->resolution().x << " x " << ns->resolution().y; + } + } } + else + oss << "Undefined"; information_ = oss.str(); current_id_ = s.id(); @@ -330,18 +348,26 @@ void InfoVisitor::visit (MultiFileSource& s) return; std::ostringstream oss; - if (brief_) { - oss << s.sequence().max - s.sequence().min + 1 << " images ["; - oss << s.sequence().min << " - " << s.sequence().max << "]" << std::endl; - oss << s.sequence().codec << ", "; - oss << s.sequence().width << " x " << s.sequence().height; - } - else { - oss << s.sequence().location << " ["; - oss << s.sequence().min << " - " << s.sequence().max << "]" << std::endl; - oss << s.sequence().max - s.sequence().min + 1 << " "; - oss << s.sequence().codec << " images" << std::endl; - oss << s.sequence().width << " x " << s.sequence().height << ", " << s.framerate() << " fps"; + + if (s.stream()) { + if (s.stream()->failed()) { + oss << s.sequence().location << std::endl << s.stream()->log(); + } + else { + if (brief_) { + oss << s.sequence().max - s.sequence().min + 1 << " images ["; + oss << s.sequence().min << " - " << s.sequence().max << "]" << std::endl; + oss << s.sequence().codec << ", "; + oss << s.sequence().width << " x " << s.sequence().height; + } + else { + oss << s.sequence().location << " ["; + oss << s.sequence().min << " - " << s.sequence().max << "]" << std::endl; + oss << s.sequence().max - s.sequence().min + 1 << " "; + oss << s.sequence().codec << " images" << std::endl; + oss << s.sequence().width << " x " << s.sequence().height << ", " << s.framerate() << " fps"; + } + } } information_ = oss.str(); @@ -354,18 +380,25 @@ void InfoVisitor::visit (GenericStreamSource& s) return; std::ostringstream oss; - if (s.stream()) { - std::string src_element = s.gstElements().front(); - if (brief_) { - src_element = src_element.substr(0, src_element.find(" ")); - oss << "gstreamer '" << src_element << "'" << std::endl; - oss << "RGBA, " << s.stream()->width() << " x " << s.stream()->height(); + Stream *stm = s.stream(); + if (stm) { + if (stm->failed()) { + oss << stm->log(); } else { - oss << "gstreamer '" << src_element << "'" << std::endl; - oss << "RGBA" << std::endl; - oss << s.stream()->width() << " x " << s.stream()->height(); + std::string src_element = s.gstElements().front(); + + if (brief_) { + src_element = src_element.substr(0, src_element.find(" ")); + oss << "gstreamer '" << src_element << "'" << std::endl; + oss << "RGBA, " << stm->width() << " x " << stm->height(); + } + else { + oss << "gstreamer '" << src_element << "'" << std::endl; + oss << "RGBA" << std::endl; + oss << stm->width() << " x " << stm->height(); + } } } else @@ -382,13 +415,19 @@ void InfoVisitor::visit (SrtReceiverSource& s) std::ostringstream oss; - if (s.stream()) { - if (brief_) - oss << s.uri() << std::endl; + Stream *stm = s.stream(); + if (stm) { + if (stm->failed()) { + oss << s.uri() << std::endl << stm->log(); + } else { - oss << "SRT Receiver " << s.uri() << std::endl; - oss << "H264 (" << s.stream()->decoderName() << ")" << std::endl; - oss << s.stream()->width() << " x " << s.stream()->height(); + if (brief_) + oss << s.uri() << std::endl; + else { + oss << "SRT Receiver " << s.uri() << std::endl; + oss << "H264 (" << stm->decoderName() << ")" << std::endl; + oss << stm->width() << " x " << stm->height(); + } } } else diff --git a/src/MediaPlayer.cpp b/src/MediaPlayer.cpp index 96a418f..820ab3e 100644 --- a/src/MediaPlayer.cpp +++ b/src/MediaPlayer.cpp @@ -137,22 +137,22 @@ MediaInfo MediaPlayer::UriDiscoverer(const std::string &uri) GstDiscovererResult result = gst_discoverer_info_get_result (info); switch (result) { case GST_DISCOVERER_URI_INVALID: - Log::Warning("'%s': Invalid URI", uri.c_str()); + video_stream_info.log = "Invalid URI"; break; case GST_DISCOVERER_ERROR: - Log::Warning("'%s': %s", uri.c_str(), err->message); + video_stream_info.log = err->message; break; case GST_DISCOVERER_TIMEOUT: - Log::Warning("'%s': Timeout loading", uri.c_str()); + video_stream_info.log = "Timeout loading"; break; case GST_DISCOVERER_BUSY: - Log::Warning("'%s': Busy", uri.c_str()); + video_stream_info.log = "Busy"; break; case GST_DISCOVERER_MISSING_PLUGINS: { const GstStructure *s = gst_discoverer_info_get_misc (info); gchar *str = gst_structure_to_string (s); - Log::Info("'%s': Unknown file format (%s)", uri.c_str(), str); + video_stream_info.log = "Unknown format " + std::string(str); g_free (str); } break; @@ -218,10 +218,10 @@ MediaInfo MediaPlayer::UriDiscoverer(const std::string &uri) } if (!video_stream_info.valid) - Log::Warning("'%s': Invalid video stream", uri.c_str()); + video_stream_info.log = "Invalid video stream"; } else - Log::Warning("'%s': No video stream", uri.c_str()); + video_stream_info.log = "No video stream"; gst_discoverer_stream_info_list_free(streams); } @@ -929,7 +929,8 @@ void MediaPlayer::update() execute_open(); } else { - Log::Warning("MediaPlayer %s Loading cancelled", std::to_string(id_).c_str()); + Log::Warning("'%s' : %s", uri().c_str(), media_.log.c_str()); + Log::Warning("MediaPlayer %s Loading failed.", std::to_string(id_).c_str()); failed_ = true; } } diff --git a/src/MediaPlayer.h b/src/MediaPlayer.h index 0299c64..ba1a389 100644 --- a/src/MediaPlayer.h +++ b/src/MediaPlayer.h @@ -36,40 +36,22 @@ struct MediaInfo { bool valid; GstClockTime dt; GstClockTime end; + std::string log; MediaInfo() { - width = par_width = 640; - height = 480; + width = par_width = 1; + height = 1; bitrate = 0; - framerate_n = 1; - framerate_d = 25; - codec_name = ""; + framerate_n = 0; + framerate_d = 1; + codec_name = "Undefined"; isimage = false; interlaced = false; seekable = false; valid = false; dt = GST_CLOCK_TIME_NONE; end = GST_CLOCK_TIME_NONE; - } - - inline MediaInfo& operator = (const MediaInfo& b) - { - if (this != &b) { - this->dt = b.dt; - this->end = b.end; - this->width = b.width; - this->par_width = b.par_width; - this->height = b.height; - this->bitrate = b.bitrate; - this->framerate_n = b.framerate_n; - this->framerate_d = b.framerate_d; - this->codec_name = b.codec_name; - this->valid = b.valid; - this->isimage = b.isimage; - this->interlaced = b.interlaced; - this->seekable = b.seekable; - } - return *this; + log = ""; } }; @@ -283,6 +265,7 @@ public: static std::list::const_iterator end() { return registered_.cend(); } static MediaInfo UriDiscoverer(const std::string &uri); + std::string log() const { return media_.log; } private: diff --git a/src/MultiFileSource.cpp b/src/MultiFileSource.cpp index f7c0583..d3a928d 100644 --- a/src/MultiFileSource.cpp +++ b/src/MultiFileSource.cpp @@ -20,9 +20,6 @@ #include #include -#include "defines.h" -#include "ImageShader.h" -#include "Resource.h" #include "Decorations.h" #include "Stream.h" #include "Visitor.h" @@ -77,20 +74,6 @@ bool MultiFileSequence::valid() const return !( location.empty() || codec.empty() || width < 1 || height < 1 || max == min); } -MultiFileSequence& MultiFileSequence::operator = (const MultiFileSequence& b) -{ - if (this != &b) { - this->width = b.width; - this->height = b.height; - this->min = b.min; - this->max = b.max; - this->location = b.location; - this->codec = b.codec; - } - return *this; -} - - bool MultiFileSequence::operator != (const MultiFileSequence& b) { return ( location != b.location || codec != b.codec || width != b.width || @@ -104,8 +87,11 @@ MultiFile::MultiFile() : Stream(), src_(nullptr) void MultiFile::open (const MultiFileSequence &sequence, uint framerate ) { - if (sequence.location.empty()) + std::string path = SystemToolkit::path_filename( sequence.location ); + if (!SystemToolkit::file_exists(path) ) { + fail("Invalid path."); return; + } std::ostringstream gstreamer_pipeline; gstreamer_pipeline << "multifilesrc name=src location=\""; diff --git a/src/MultiFileSource.h b/src/MultiFileSource.h index 7aa63e0..777d735 100644 --- a/src/MultiFileSource.h +++ b/src/MultiFileSource.h @@ -17,7 +17,6 @@ struct MultiFileSequence { MultiFileSequence (); MultiFileSequence (const std::list &list_files); bool valid () const; - MultiFileSequence& operator = (const MultiFileSequence& b); bool operator != (const MultiFileSequence& b); }; diff --git a/src/NetworkSource.cpp b/src/NetworkSource.cpp index e0300ab..be4d57a 100644 --- a/src/NetworkSource.cpp +++ b/src/NetworkSource.cpp @@ -123,8 +123,7 @@ void NetworkStream::connect(const std::string &nameconnection) // refuse self referencing if (nameconnection.compare(Connection::manager().info().name) == 0) { - Log::Warning("Cannot create self-referencing Network Source '%s'", nameconnection.c_str()); - failed_ = true; + fail("Cannot create self-referencing Network Source " + nameconnection); return; } @@ -133,8 +132,7 @@ void NetworkStream::connect(const std::string &nameconnection) // Nope, cannot connect to unknown connection if (streamer_index < 0) { - Log::Warning("Cannot connect to %s: please make sure %s is active on this machine.", nameconnection.c_str(), APP_NAME); - failed_ = true; + fail("Cannot connect to " + nameconnection + ". Please make sure vimix is active on this machine"); return; } @@ -159,8 +157,7 @@ void NetworkStream::connect(const std::string &nameconnection) } } if (receiver_ == nullptr) { - Log::Notify("Cannot establish connection with %s. Please check your network.", streamer_.name.c_str()); - failed_ = true; + fail("Cannot establish connection with " + streamer_.name + ". Please check your network."); return; } @@ -191,6 +188,7 @@ void NetworkStream::disconnect() { // receiver should not be active anyway, make sure it is deleted if (receiver_) { + receiver_->AsynchronousBreak(); delete receiver_; receiver_ = nullptr; } @@ -297,8 +295,7 @@ void NetworkStream::update() } } else { - Log::Warning("Connection was rejected by %s.\nMake sure Sharing on local network is enabled and try again.", streamer_.name.c_str()); - failed_=true; + fail("Connection was rejected by " + streamer_.name + ".\nMake sure Sharing on local network is enabled and try again."); } } } diff --git a/src/NetworkSource.h b/src/NetworkSource.h index 8da318b..0ece9d5 100644 --- a/src/NetworkSource.h +++ b/src/NetworkSource.h @@ -5,11 +5,9 @@ #include "Connection.h" #include "StreamSource.h" - class NetworkStream : public Stream { public: - NetworkStream(); void connect(const std::string &nameconnection); diff --git a/src/Stream.cpp b/src/Stream.cpp index 2d0dbcb..2f64994 100644 --- a/src/Stream.cpp +++ b/src/Stream.cpp @@ -23,11 +23,9 @@ // Desktop OpenGL function loader #include -#include "defines.h" #include "Log.h" #include "Resource.h" #include "Visitor.h" -#include "SystemToolkit.h" #include "BaseToolkit.h" #include "GstToolkit.h" @@ -192,8 +190,10 @@ StreamInfo StreamDiscoverer(const std::string &description, guint w, guint h) gst_object_unref (_pipeline); } - else + else { info.message = error->message; + g_clear_error (&error); + } } // at this point, the info should be filled return info; @@ -312,7 +312,8 @@ void Stream::execute_open() void Stream::fail(const std::string &message) { - Log::Warning("Stream %s %s.", std::to_string(id_).c_str(), message.c_str() ); + log_ = message; + Log::Warning("Stream %s %s.", std::to_string(id_).c_str(), log_.c_str() ); failed_ = true; } @@ -878,8 +879,6 @@ GstFlowReturn Stream::callback_new_sample (GstAppSink *sink, gpointer p) return ret; } - - Stream::TimeCounter::TimeCounter(): fps(1.f) { timer = g_timer_new (); diff --git a/src/Stream.h b/src/Stream.h index c416c77..591ad22 100644 --- a/src/Stream.h +++ b/src/Stream.h @@ -143,12 +143,17 @@ public: * NB: perform request on pipeline on first call * */ std::string decoderName(); + /** + * Get logs + * */ + std::string log() const { return log_; } /** * Accept visitors * Used for saving session file * */ void accept(Visitor& v); + protected: // video player description @@ -220,6 +225,7 @@ protected: // gst pipeline control virtual void execute_open(); virtual void fail(const std::string &message); + std::string log_; // gst frame filling bool textureinitialized_; diff --git a/src/StreamSource.cpp b/src/StreamSource.cpp index c48c03f..aca0d35 100644 --- a/src/StreamSource.cpp +++ b/src/StreamSource.cpp @@ -21,8 +21,6 @@ #include #include -#include "defines.h" -#include "ImageShader.h" #include "Resource.h" #include "Decorations.h" #include "Stream.h" diff --git a/src/Streamer.cpp b/src/Streamer.cpp index 65c3424..fb30e17 100644 --- a/src/Streamer.cpp +++ b/src/Streamer.cpp @@ -36,10 +36,8 @@ #include "Settings.h" #include "GstToolkit.h" -#include "defines.h" #include "SystemToolkit.h" #include "Session.h" -#include "FrameBuffer.h" #include "Log.h" #include "Connection.h" #include "NetworkToolkit.h" diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index 12382f4..3b8f83d 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -6311,7 +6311,7 @@ void Navigator::Render() // ignore source if failed (managed in stash below) if (s->failed()){ - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.f, 0.3f, 0.2f, 1.f)); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(IMGUI_COLOR_FAILED, 1.)); ImGui::PushStyleColor(ImGuiCol_Header, ImGui::GetColorU32(ImGuiCol_Button)); ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImGui::GetColorU32(ImGuiCol_ButtonActive)); ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImGui::GetColorU32(ImGuiCol_ButtonHovered)); diff --git a/src/defines.h b/src/defines.h index 579af55..27deead 100644 --- a/src/defines.h +++ b/src/defines.h @@ -89,6 +89,7 @@ #define IMGUI_COLOR_BROADCAST 1.0, 0.9, 0.3 #define IMGUI_NOTIFICATION_DURATION 2.5f #define IMGUI_TOOLTIP_TIMEOUT 80 +#define IMGUI_COLOR_FAILED 1.0, 0.3, 0.2 #define COLOR_BGROUND 0.2f, 0.2f, 0.2f #define COLOR_NAVIGATOR 0.1f, 0.1f, 0.1f