From f763b3e257920c8fa4647063d5b75251381fd9f9 Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Sun, 10 May 2026 22:46:26 +0200 Subject: [PATCH] Refactoring of Source panel; use collapsing headers for Color correction (image processing on/off), all source specific properties, and transcoding (MediaSource only). This unifies the use of headers in left panel (Session, Playlist, Settings, and now Source). --- src/Navigator.cpp | 195 ++++++++------ src/Settings.cpp | 6 + src/Settings.h | 4 + src/Visitor/ImGuiVisitor.cpp | 510 ++++++++++++++++++++--------------- src/Visitor/ImGuiVisitor.h | 1 + 5 files changed, 430 insertions(+), 286 deletions(-) diff --git a/src/Navigator.cpp b/src/Navigator.cpp index 2d5b8b3..c486deb 100644 --- a/src/Navigator.cpp +++ b/src/Navigator.cpp @@ -53,6 +53,7 @@ #include "Resource.h" #include "ActionManager.h" #include "Mixer.h" +#include "MediaPlayer.h" #include "Source/MediaSource.h" #include "Source/PatternSource.h" #include "Source/DeviceSource.h" @@ -75,6 +76,7 @@ #include "Window/WorkspaceWindow.h" #include "UserInterfaceManager.h" #include "FrameGrabbing.h" +#include "Transcoder.h" #include "Navigator.h" @@ -651,6 +653,112 @@ void Navigator::RenderViewOptions(uint *timeout, const ImVec2 &pos, const ImVec2 } } +bool renderTranscodingPanel(guint64 id, MediaPlayer *mp) +{ + static Transcoder *transcoder = nullptr; + static guint64 transcode_id = 0; + bool ret = false; + + if (mp == nullptr || mp->isImage()) + return ret; + + if (id != transcode_id && transcoder != nullptr) { + // if source changed while transcoding; + // show a disabled transcoding panel + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.f,0.f,0.f,0.f)); + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.f,0.f,0.f,0.f)); + ImGui::CollapsingHeader("Transcoding", ImGuiTreeNodeFlags_Bullet); + ImGui::PopStyleColor(3); + return ret; + } + + // Transcoding panel + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.f,0.f,0.f,0.f)); + Settings::application.pannel_source[2] = ImGui::CollapsingHeader("Transcoding", + Settings::application.pannel_source[2] ? ImGuiTreeNodeFlags_DefaultOpen : 0); + ImGui::PopStyleColor(); + + if (Settings::application.pannel_source[2]) { + + // Transcoding options + ImGuiToolkit::ButtonSwitch( "Backward playback", &Settings::application.transcode_options[0], + "Optimize the video for backward playback by adding more keyframes.", transcoder == nullptr); + ImGuiToolkit::ButtonSwitch( "Animation content", &Settings::application.transcode_options[1], + "Optimize the video encoding for animation content (cartoons, " + "drawings, computer graphics) to preserve more details.", transcoder == nullptr); + ImGuiToolkit::ButtonSwitch( "Constant Quality", &Settings::application.transcode_options[2], + "Use Constant Quality encoding to preserve more visual details " + "(produces larger files).", transcoder == nullptr); + ImGuiToolkit::ButtonSwitch( "Remove audio", &Settings::application.transcode_options[3], + "Remove the audio track from the video during transcoding.", transcoder == nullptr); + + // Start transcoding if not already started for current source + if (transcoder == nullptr) { + if (ImGui::Button(ICON_FA_COG " Re-encode", ImVec2(IMGUI_RIGHT_ALIGN,0))) { + transcode_id = id; + transcoder = new Transcoder(gst_uri_get_location(mp->uri().c_str())); + TranscoderOptions transcode_options(Settings::application.transcode_options[0], + Settings::application.transcode_options[1] ? PsyTuning::ANIMATION : PsyTuning::NONE, + Settings::application.transcode_options[2] ? 19 : -1, + Settings::application.transcode_options[3]); + if (!transcoder->start(transcode_options)) { + Log::Warning("Failed to start transcoding: %s", transcoder->error().c_str()); + delete transcoder; + transcoder = nullptr; + transcode_id = 0; + } + } + ImGui::SameLine(); + ImGuiToolkit::HelpToolTip("Re-encode the source video in MP4 " + "(H.264 video @ 30fps + AAC audio) using the specified options.\n\n " + ICON_FA_FILM " The new file will replace the one in the source " + "once the transcoding is successfully completed.\n\n" + "The current file remains untouched."); + } + + if (transcoder != nullptr) { + if (transcoder->finished()) { + if (transcoder->success()) { + Log::Notify("Transcoding successful : %s", transcoder->outputFilename().c_str()); + // reload source with new file + Source *src = Mixer::manager().findSource(transcode_id); + if (src != nullptr) + static_cast(src)->setPath( transcoder->outputFilename() ); + ret = true; + } + // all done in any case + delete transcoder; + transcoder = nullptr; + transcode_id = 0; + } + else { + float progress = transcoder->progress(); + ImGui::ProgressBar(progress, ImVec2(IMGUI_RIGHT_ALIGN,0), progress < EPSILON ? "working..." : nullptr); + ImGui::SameLine(); + if (ImGui::Button( ICON_FA_TIMES " Cancel", ImVec2(0,0)) || + Mixer::manager().findSource(transcode_id) == nullptr ) { + // cancel transcoding by user or source removed + transcoder->stop(); + } + } + } + } + else { + if (transcoder != nullptr && !transcoder->finished()) { + ImVec2 pos_tmp = ImGui::GetCursorPos(); + ImVec2 space_size = ImGui::CalcTextSize(" Transcoding ", NULL); + space_size.x += ImGui::GetTextLineHeightWithSpacing() * 2.f; + space_size.y = -ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().ItemSpacing.y; + ImGui::SetCursorPos( pos_tmp + space_size ); + ImGui::Text("( %d %% )", (int)(100.0 * transcoder->progress())); + ImGui::SetCursorPos( pos_tmp ); + } + } + + return ret; +} + // Source pannel : *s was checked before void Navigator::RenderSourcePannel(Source *s, const ImVec2 &iconsize, bool reset) { @@ -664,7 +772,9 @@ void Navigator::RenderSourcePannel(Source *s, const ImVec2 &iconsize, bool reset ImGui::SetNextWindowBgAlpha( pannel_alpha_ ); // Transparent background if (ImGui::Begin("##navigatorSource", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) { - // TITLE + /// + /// TITLE + /// ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); ImGui::SetCursorPosY(0.5f * (iconsize.y - ImGui::GetTextLineHeight())); ImGui::Text("Source"); @@ -686,87 +796,22 @@ void Navigator::RenderSourcePannel(Source *s, const ImVec2 &iconsize, bool reset Mixer::manager().renameSource(s, sname); } - // Source pannel + /// + /// Source pannel + /// static ImGuiVisitor v; if (reset) v.reset(); s->accept(v); /// - /// AUDIO PANEL if audio available on source + /// Transcoding panel for media player /// - if (Settings::application.accept_audio && s->audioFlags() & Source::Audio_available) { - ImGuiIO &io = ImGui::GetIO(); - - // test audio and read volume - bool audio_is_on = s->audioFlags() & Source::Audio_enabled; - int vol = audio_is_on ? (int) (s->audioVolumeFactor(Source::VOLUME_BASE) * 100.f) : -1; - std::string label = audio_is_on ? (vol > 50 ? ICON_FA_VOLUME_UP " %d%%" - : ICON_FA_VOLUME_DOWN " %d%%") - : ICON_FA_VOLUME_MUTE " Disabled"; - // VOLUME & on/off slider - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - bool volume_change = ImGui::SliderInt("##VolumeAudio", &vol, -1, 100, label.c_str()); - if (ImGui::IsItemHovered()) { - if (io.MouseWheel != 0.f) { - vol = CLAMP(vol + int(10.f * io.MouseWheel), 0, 100); - volume_change = true; - } else if (!audio_is_on) - ImGuiToolkit::ToolTip("Enabling audio will reload source."); - } - if (volume_change) { - if (vol < 0) - s->setAudioEnabled(false); - else { - s->setAudioEnabled(true); - s->setAudioVolumeFactor(Source::VOLUME_BASE, - CLAMP((float) (vol) *0.01f, 0.f, 1.f)); - } - } - ImGui::SameLine(0, IMGUI_SAME_LINE); - if (ImGuiToolkit::TextButton("Audio")) { - s->setAudioEnabled(false); - } - - // AUDIO MIXING menu - if (audio_is_on) { - ImGui::SameLine(0, 2 * IMGUI_SAME_LINE); - static uint counter_menu_timeout_2 = 0; - if (ImGuiToolkit::IconButton(6, 2) - || ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { - counter_menu_timeout_2 = 0; - ImGui::OpenPopup("MenuMixAudio"); - } - if (ImGui::BeginPopup("MenuMixAudio")) { - ImGui::TextDisabled("Multiply volume with:"); - Source::AudioVolumeMixing flags = s->audioVolumeMix(); - bool mix = flags & Source::Volume_mult_alpha; - if (ImGui::MenuItem("Source alpha", NULL, &mix)) { - if (mix) - s->setAudioVolumeMix(flags | Source::Volume_mult_alpha); - else - s->setAudioVolumeMix(flags & ~Source::Volume_mult_alpha); - } - mix = flags & Source::Volume_mult_opacity; - if (ImGui::MenuItem("Source fading", NULL, &mix)) { - if (mix) - s->setAudioVolumeMix(flags | Source::Volume_mult_opacity); - else - s->setAudioVolumeMix(flags & ~Source::Volume_mult_opacity); - } - mix = flags & Source::Volume_mult_session; - if (ImGui::MenuItem("Output fading", NULL, &mix)) { - if (mix) - s->setAudioVolumeMix(flags | Source::Volume_mult_session); - else - s->setAudioVolumeMix(flags & ~Source::Volume_mult_session); - } - if (ImGui::IsWindowHovered()) - counter_menu_timeout_2 = 0; - else if (++counter_menu_timeout_2 > 10) - ImGui::CloseCurrentPopup(); - ImGui::EndPopup(); - } + if (!s->failed()) { + MediaSource* ms = dynamic_cast(s); + if (ms != nullptr) { + if (renderTranscodingPanel(ms->id(), ms->mediaplayer())) + v.reset(); } } diff --git a/src/Settings.cpp b/src/Settings.cpp index 67a2755..b1e046f 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -153,6 +153,9 @@ void Settings::terminate(uint64_t runtime, const std::string &filename) applicationNode->SetAttribute("accept_connections", application.accept_connections); applicationNode->SetAttribute("pannel_main_mode", application.pannel_main_mode); applicationNode->SetAttribute("pannel_playlist_mode", application.pannel_playlist_mode); + applicationNode->SetAttribute("pannel_source_0", application.pannel_source[0]); + applicationNode->SetAttribute("pannel_source_1", application.pannel_source[1]); + applicationNode->SetAttribute("pannel_source_2", application.pannel_source[2]); applicationNode->SetAttribute("pannel_session_0", application.pannel_session[0]); applicationNode->SetAttribute("pannel_session_1", application.pannel_session[1]); applicationNode->SetAttribute("pannel_session_2", application.pannel_session[2]); @@ -517,6 +520,9 @@ void Settings::init(const std::string &filename) applicationNode->QueryBoolAttribute("pannel_always_visible", &application.pannel_always_visible); applicationNode->QueryIntAttribute("pannel_main_mode", &application.pannel_main_mode); applicationNode->QueryIntAttribute("pannel_playlist_mode", &application.pannel_playlist_mode); + applicationNode->QueryBoolAttribute("pannel_source_0", &application.pannel_source[0]); + applicationNode->QueryBoolAttribute("pannel_source_1", &application.pannel_source[1]); + applicationNode->QueryBoolAttribute("pannel_source_2", &application.pannel_source[2]); applicationNode->QueryBoolAttribute("pannel_session_0", &application.pannel_session[0]); applicationNode->QueryBoolAttribute("pannel_session_1", &application.pannel_session[1]); applicationNode->QueryBoolAttribute("pannel_session_2", &application.pannel_session[2]); diff --git a/src/Settings.h b/src/Settings.h index 5c25acc..fbbcfb9 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -302,6 +302,7 @@ struct Application bool pannel_session[4]; bool pannel_always_visible; bool pannel_settings[6]; + bool pannel_source[3]; // connection settings bool accept_connections; @@ -407,6 +408,9 @@ struct Application pannel_settings[3] = false; pannel_settings[4] = false; pannel_settings[5] = false; + pannel_source[0] = true; + pannel_source[1] = true; + pannel_source[2] = true; transcode_options[0] = true; transcode_options[1] = false; transcode_options[2] = false; diff --git a/src/Visitor/ImGuiVisitor.cpp b/src/Visitor/ImGuiVisitor.cpp index 69ebeaf..832afe8 100644 --- a/src/Visitor/ImGuiVisitor.cpp +++ b/src/Visitor/ImGuiVisitor.cpp @@ -65,7 +65,6 @@ #include "ActionManager.h" #include "Mixer.h" #include "ControlManager.h" -#include "Transcoder.h" #include "Canvas.h" #include "imgui.h" @@ -527,75 +526,72 @@ void ImGuiVisitor::visit (Source& s) Action::manager().store(oss.str()); } - // Filter + // Image processing header and menu bool on = s.imageProcessingEnabled(); ImGui::SetCursorPos( ImVec2( pos.x, pos.y + preview_height)); - if (on) - ImGui::Text(ICON_FA_PALETTE " Color correction"); - else - ImGuiToolkit::Indication("Color correction filter is disabled", ICON_FA_PALETTE " Color correction"); - pos = ImGui::GetCursorPos(); + + // header for Color correction + ImGui::BeginChild("header_color_child", ImVec2(preview_width, ImGui::GetFrameHeightWithSpacing()), + false, ImGuiWindowFlags_NoDecoration); + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.f,0.f,0.f,0.f)); + if (on) { + Settings::application.pannel_source[0] = + ImGui::CollapsingHeader("Color correction",Settings::application.pannel_source[0] ? ImGuiTreeNodeFlags_DefaultOpen : 0); + } + else { + ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.f,0.f,0.f,0.f)); + ImGui::CollapsingHeader("Color correction", ImGuiTreeNodeFlags_Bullet); + ImGui::PopStyleColor(2); + } + ImGui::PopStyleColor(); + ImGui::EndChild(); // menu icon for image processing - ImGui::SameLine(preview_width + 5, 2 * IMGUI_SAME_LINE); static uint counter_menu_timeout = 0; + ImVec2 pos_bot = ImGui::GetCursorPos(); + ImGui::SetCursorPos( ImVec2( pos.x + preview_width + IMGUI_SAME_LINE, pos.y + preview_height + ImGui::GetStyle().ItemSpacing.y)); if (ImGuiToolkit::IconButton(5, 8) || ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { counter_menu_timeout=0; ImGui::OpenPopup( "MenuImageProcessing" ); } + ImGui::SetCursorPos(pos_bot); + + // Active panel for image processing + if (on) { + // Header Color correction is open + if (Settings::application.pannel_source[0]) { + s.processingShader()->accept(*this); + } + } + // context menu for image processing if (ImGui::BeginPopup( "MenuImageProcessing" )) { - if (ImGui::MenuItem("Enable", NULL, &on)) { + if (ImGui::MenuItem("Enabled", NULL, &on)) { oss << ( on ? "Enable Color correction" : "Disable Color correction"); Action::manager().store(oss.str()); s.setImageProcessingEnabled(on); + Settings::application.pannel_source[0] = true; } - - if (s.processingshader_link_.connected()) { - if (ImGui::MenuItem( "Unfollow", NULL, false, on)){ - s.processingshader_link_.disconnect(); - } + if (ImGui::MenuItem("Reset", NULL, false, on )){ + ImageProcessingShader defaultvalues; + s.processingShader()->copy(defaultvalues); + s.processingshader_link_.disconnect(); + oss << "Reset Filter"; + Action::manager().store(oss.str()); } - else { - if (ImGui::MenuItem("Reset", NULL, false, on )){ - ImageProcessingShader defaultvalues; - s.processingShader()->copy(defaultvalues); - s.processingshader_link_.disconnect(); - oss << "Reset Filter"; - Action::manager().store(oss.str()); - } - if (ImGui::MenuItem("Copy", NULL, false, on )){ - std::string clipboard = SessionVisitor::getClipboard(s.processingShader()); - if (!clipboard.empty()) - ImGui::SetClipboardText(clipboard.c_str()); - } - const char *clipboard = ImGui::GetClipboardText(); - const bool can_paste = (clipboard != nullptr && SessionLoader::isClipboard(clipboard)); - if (ImGui::MenuItem("Paste", NULL, false, can_paste)) { - SessionLoader::applyImageProcessing(s, clipboard); - oss << "Change Filter"; - Action::manager().store(oss.str()); - } - // // NON-stable style follow mechanism - // ImGui::Separator(); - // if (ImGui::BeginMenu("Follow", on)) - // { - // for (auto mpit = Mixer::manager().session()->begin(); - // mpit != Mixer::manager().session()->end(); mpit++ ) - // { - // std::string label = (*mpit)->name(); - // if ( (*mpit)->id() != s.id() && - // (*mpit)->imageProcessingEnabled() && - // !(*mpit)->processingshader_link_.connected()) { - // if (ImGui::MenuItem( label.c_str() )){ - // s.processingshader_link_.connect(*mpit); - // s.touch(); - // } - // } - // } - // ImGui::EndMenu(); - // } + if (ImGui::MenuItem("Copy", NULL, false, on )){ + std::string clipboard = SessionVisitor::getClipboard(s.processingShader()); + if (!clipboard.empty()) + ImGui::SetClipboardText(clipboard.c_str()); + } + const char *clipboard = ImGui::GetClipboardText(); + const bool can_paste = (clipboard != nullptr && SessionLoader::isClipboard(clipboard)); + if (ImGui::MenuItem("Paste", NULL, false, can_paste)) { + SessionLoader::applyImageProcessing(s, clipboard); + oss << "Change Filter"; + Action::manager().store(oss.str()); } if (ImGui::IsWindowHovered()) @@ -606,22 +602,6 @@ void ImGuiVisitor::visit (Source& s) ImGui::EndPopup(); } - if (s.imageProcessingEnabled()) { - - // full panel for image processing - ImGui::SetCursorPos( pos ); - ImGui::Spacing(); - - if (s.processingshader_link_.connected()) { - Source *target = s.processingshader_link_.source(); - ImGui::Text("Following"); - if ( target != nullptr && ImGui::Button(target->name().c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) - Mixer::manager().setCurrentSource(target); - } - else - s.processingShader()->accept(*this); - } - } else { @@ -647,15 +627,122 @@ void ImGuiVisitor::visit (Source& s) 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()); + // Header for Source specific settings + ImVec2 pos_top = ImGui::GetCursorPos(); + ImGui::BeginChild("header_source_settings", ImVec2(preview_width, ImGui::GetFrameHeightWithSpacing()), + false, ImGuiWindowFlags_NoDecoration); + ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.f,0.f,0.f,0.f)); + Settings::application.pannel_source[1] = ImGui::TreeNodeBehavior(ImGui::GetID("SourcePanelSpecific"), + (Settings::application.pannel_source[1] ? ImGuiTreeNodeFlags_DefaultOpen : 0) | ImGuiTreeNodeFlags_CollapsingHeader, + s.info().c_str()); + ImGui::PopStyleColor(); + ImGui::EndChild(); + // Source specific icon to the right of Header + ImVec2 pos_bot = ImGui::GetCursorPos(); + ImGui::SetCursorPos( ImVec2( pos_top.x + preview_width + IMGUI_SAME_LINE, pos_top.y + ImGui::GetStyle().ItemSpacing.y)); + if (ImGuiToolkit::IconButton(s.icon().x, s.icon().y) ) { + UserInterface::manager().showSourceEditor(&s); + } + // Source specific tooltip on hover + if (ImGui::IsItemHovered()) { + InfoVisitor info; + info.setExtendedStringMode(); + s.accept(info); + ImGuiToolkit::ToolTip(info.str().c_str()); + } + ImGui::SetCursorPos(pos_bot); + +} + + +void ImGuiVisitor::renderAudioPanel(MediaSource &s) +{ + /// + /// AUDIO PANEL if audio available on source + /// + if (Settings::application.accept_audio && s.audioFlags() & Source::Audio_available) { + ImGuiIO &io = ImGui::GetIO(); + + // test audio and read volume + bool audio_is_on = s.audioFlags() & Source::Audio_enabled; + int vol = audio_is_on ? (int) (s.audioVolumeFactor(Source::VOLUME_BASE) * 100.f) : -1; + std::string label = audio_is_on ? (vol > 50 ? ICON_FA_VOLUME_UP " %d%%" + : ICON_FA_VOLUME_DOWN " %d%%") + : ICON_FA_VOLUME_MUTE " Disabled"; + // VOLUME & on/off slider + ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); + bool volume_change = ImGui::SliderInt("##VolumeAudio", &vol, -1, 100, label.c_str()); + if (ImGui::IsItemHovered()) { + if (io.MouseWheel != 0.f) { + vol = CLAMP(vol + int(10.f * io.MouseWheel), 0, 100); + volume_change = true; + } else if (!audio_is_on) + ImGuiToolkit::ToolTip("When enabling audio, the source will be reloaded."); + } + if (volume_change) { + if (vol < 0) + s.setAudioEnabled(false); + else { + s.setAudioEnabled(true); + s.setAudioVolumeFactor(Source::VOLUME_BASE, + CLAMP((float) (vol) *0.01f, 0.f, 1.f)); + } + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton("Audio")) { + s.setAudioEnabled(false); + } + + // AUDIO MIXING menu + if (audio_is_on) { + ImGui::SameLine(0, 2 * IMGUI_SAME_LINE); + static uint counter_menu_timeout_2 = 0; + if (ImGuiToolkit::IconButton(6, 2) + || ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { + counter_menu_timeout_2 = 0; + ImGui::OpenPopup("MenuMixAudio"); + } + if (ImGui::BeginPopup("MenuMixAudio")) { + ImGui::TextDisabled("Multiply volume with:"); + Source::AudioVolumeMixing flags = s.audioVolumeMix(); + bool mix = flags & Source::Volume_mult_alpha; + if (ImGui::MenuItem("Source alpha", NULL, &mix)) { + if (mix) + s.setAudioVolumeMix(flags | Source::Volume_mult_alpha); + else + s.setAudioVolumeMix(flags & ~Source::Volume_mult_alpha); + } + mix = flags & Source::Volume_mult_opacity; + if (ImGui::MenuItem("Source fading", NULL, &mix)) { + if (mix) + s.setAudioVolumeMix(flags | Source::Volume_mult_opacity); + else + s.setAudioVolumeMix(flags & ~Source::Volume_mult_opacity); + } + mix = flags & Source::Volume_mult_session; + if (ImGui::MenuItem("Output fading", NULL, &mix)) { + if (mix) + s.setAudioVolumeMix(flags | Source::Volume_mult_session); + else + s.setAudioVolumeMix(flags & ~Source::Volume_mult_session); + } + if (ImGui::IsWindowHovered()) + counter_menu_timeout_2 = 0; + else if (++counter_menu_timeout_2 > 10) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + } + } + } void ImGuiVisitor::visit (MediaSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -675,9 +762,13 @@ void ImGuiVisitor::visit (MediaSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } top.x += ImGui::GetFrameHeight(); } ImGui::SetCursorPos(top); @@ -737,103 +828,9 @@ void ImGuiVisitor::visit (MediaSource& s) ImGui::TextDisabled("Hardware decoding disabled"); } - // transcoding panel - static Transcoder *transcoder = nullptr; - static guint64 transcode_id = 0; - static bool _transcoding = false; - bool show_content = _transcoding && (transcode_id == 0 || transcode_id == s.id()); - float w_height = (!show_content) ? - ImGui::GetFrameHeight() : (6.1f * ImGui::GetFrameHeightWithSpacing()); - - ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetColorU32(ImGuiCol_PopupBg)); - ImGui::BeginChild("transcode_child", ImVec2(0, w_height), - true, ImGuiWindowFlags_MenuBar); - if (ImGui::BeginMenuBar()) - { - std::string title = " Transcoding"; - if (show_content) - title.insert(0, ICON_FA_CHEVRON_DOWN " "); - else { - title.insert(0, ICON_FA_CHEVRON_RIGHT " "); - if (transcoder != nullptr) - title += " (" + std::to_string((int)(100.0 * transcoder->progress())) + "%)"; - } + // Audio panel + renderAudioPanel(s); - if ( ImGui::Selectable( title.c_str(), false, - (transcoder != nullptr ? ImGuiSelectableFlags_Disabled : 0)) ) - _transcoding = !_transcoding; - ImGui::EndMenuBar(); - } - - if (_transcoding ) { - - ImGuiToolkit::ButtonSwitch( "Backward playback", &Settings::application.transcode_options[0], - "Optimize the video for backward playback by adding more keyframes.",transcoder == nullptr); - ImGuiToolkit::ButtonSwitch( "Animation content", &Settings::application.transcode_options[1], - "Optimize the video encoding for animation content (cartoons, " - "drawings, computer graphics) to preserve more details." ,transcoder == nullptr ); - ImGuiToolkit::ButtonSwitch( "Constant Quality", &Settings::application.transcode_options[2], - "Use Constant Quality encoding to preserve more visual details " - "(produces larger files).",transcoder == nullptr); - ImGuiToolkit::ButtonSwitch( "Remove audio", &Settings::application.transcode_options[3], - "Remove the audio track from the video during transcoding.",transcoder == nullptr); - - if (transcoder == nullptr) - { - if (ImGui::Button(ICON_FA_COG " Re-encode", ImVec2(IMGUI_RIGHT_ALIGN,0))) { - transcode_id = s.id(); - transcoder = new Transcoder(gst_uri_get_location(mp->uri().c_str())); - TranscoderOptions transcode_options(Settings::application.transcode_options[0], - Settings::application.transcode_options[1] ? PsyTuning::ANIMATION : PsyTuning::NONE, - Settings::application.transcode_options[2] ? 19 : -1, - Settings::application.transcode_options[3]); - if (!transcoder->start(transcode_options)) { - Log::Warning("Failed to start transcoding: %s", transcoder->error().c_str()); - delete transcoder; - transcoder = nullptr; - transcode_id = 0; - } - } - ImGui::SameLine(); - ImGuiToolkit::HelpToolTip("Re-encode the source video in MP4 " - "(H.264 video @ 30fps + AAC audio) using the specified options.\n\n " - ICON_FA_FILM " The new file will replace the one in the source " - "once the transcoding is successfully completed.\n\n" - "The current file remains untouched."); - } - - if (transcoder != nullptr) { - if (transcoder->finished()) { - if (transcoder->success()) { - Log::Notify("Transcoding successful : %s", transcoder->outputFilename().c_str()); - // reload source with new file - Source * s = Mixer::manager().findSource(transcode_id); - if (s != nullptr) { - MediaSource * ms = static_cast(s); - ms->setPath( transcoder->outputFilename() ); - } - info.reset(); - _transcoding = false; - } - // all done in any case - delete transcoder; - transcoder = nullptr; - transcode_id = 0; - } - else { - float progress = transcoder->progress(); - ImGui::ProgressBar(progress, ImVec2(IMGUI_RIGHT_ALIGN,0), progress < EPSILON ? "working..." : nullptr); - ImGui::SameLine(); - if (ImGui::Button( ICON_FA_TIMES " Cancel", ImVec2(0,0)) || - Mixer::manager().findSource(transcode_id) == nullptr ) { - // cancel transcoding by user or source removed - transcoder->stop(); - } - } - } - } - ImGui::EndChild(); - ImGui::PopStyleColor(); } else ImGui::SetCursorPos(botom); @@ -867,6 +864,9 @@ void ImGuiVisitor::visit (MediaSource& s) void ImGuiVisitor::visit (SessionFileSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -937,9 +937,13 @@ void ImGuiVisitor::visit (SessionFileSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } top.x += ImGui::GetFrameHeight(); } @@ -973,6 +977,9 @@ void ImGuiVisitor::visit (SessionFileSource& s) void ImGuiVisitor::visit (SessionGroupSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -1006,9 +1013,13 @@ void ImGuiVisitor::visit (SessionGroupSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } } } else @@ -1019,6 +1030,9 @@ void ImGuiVisitor::visit (SessionGroupSource& s) void ImGuiVisitor::visit (RenderSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -1073,9 +1087,13 @@ void ImGuiVisitor::visit (RenderSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } top.x += ImGui::GetFrameHeight(); } } @@ -1532,6 +1550,9 @@ void ImGuiVisitor::visit (ImageFilter& f) void ImGuiVisitor::visit (CloneSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -1602,9 +1623,13 @@ void ImGuiVisitor::visit (CloneSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } } ImGui::SetCursorPos(botom); @@ -1619,6 +1644,9 @@ void ImGuiVisitor::visit (CloneSource& s) void ImGuiVisitor::visit (ShaderSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -1638,9 +1666,13 @@ void ImGuiVisitor::visit (ShaderSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } top.x += ImGui::GetFrameHeight(); } ImGui::SetCursorPos(top); @@ -1655,6 +1687,9 @@ void ImGuiVisitor::visit (ShaderSource& s) void ImGuiVisitor::visit (PatternSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -1693,9 +1728,13 @@ void ImGuiVisitor::visit (PatternSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } top.x += ImGui::GetFrameHeight(); } ImGui::SetCursorPos(top); @@ -1710,6 +1749,9 @@ void ImGuiVisitor::visit (PatternSource& s) void ImGuiVisitor::visit (DeviceSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -1746,9 +1788,13 @@ void ImGuiVisitor::visit (DeviceSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } top.x += ImGui::GetFrameHeight(); } @@ -1778,6 +1824,9 @@ void ImGuiVisitor::visit (DeviceSource& s) void ImGuiVisitor::visit (ScreenCaptureSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -1814,9 +1863,13 @@ void ImGuiVisitor::visit (ScreenCaptureSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } } ImGui::SetCursorPos(botom); @@ -1832,6 +1885,9 @@ void ImGuiVisitor::visit (ScreenCaptureSource& s) void ImGuiVisitor::visit (NetworkSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -1852,9 +1908,13 @@ void ImGuiVisitor::visit (NetworkSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } } } else @@ -1866,6 +1926,9 @@ void ImGuiVisitor::visit (NetworkSource& s) void ImGuiVisitor::visit (MultiFileSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + static uint64_t id = 0; ImVec2 top = ImGui::GetCursorPos(); @@ -1937,9 +2000,13 @@ void ImGuiVisitor::visit (MultiFileSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } top.x += ImGui::GetFrameHeight(); } @@ -1960,6 +2027,9 @@ void ImGuiVisitor::visit (MultiFileSource& s) void ImGuiVisitor::visit (GenericStreamSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -2011,9 +2081,13 @@ void ImGuiVisitor::visit (GenericStreamSource& s) // icon (>) to open player if ( s.playable() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } } } @@ -2023,6 +2097,9 @@ void ImGuiVisitor::visit (GenericStreamSource& s) void ImGuiVisitor::visit (SrtReceiverSource& s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -2039,9 +2116,13 @@ void ImGuiVisitor::visit (SrtReceiverSource& s) // icon (>) to open player if ( s.stream()->isOpen() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } } else info.reset(); @@ -2056,6 +2137,9 @@ void ImGuiVisitor::visit (SrtReceiverSource& s) void ImGuiVisitor::visit(TextSource &s) { + if ( !Settings::application.pannel_source[1] ) + return; + ImVec2 top = ImGui::GetCursorPos(); top.x = 0.5f * ImGui::GetFrameHeight() + ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; float w = ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; @@ -2323,9 +2407,13 @@ void ImGuiVisitor::visit(TextSource &s) // icon (>) to open player if ( s.stream()->isOpen() ) { ImGui::SetCursorPos(top); - std::string msg = s.playing() ? "Open Player\n(source is playing)" : "Open Player\n(source is paused)"; - if (ImGuiToolkit::IconButton( s.playing() ? ICON_FA_PLAY_CIRCLE : ICON_FA_PAUSE_CIRCLE, msg.c_str())) - UserInterface::manager().showSourceEditor(&s); + if (s.playing()) { + if (ImGuiToolkit::IconButton(ICON_FA_PAUSE_CIRCLE, "Pause") ) + s.play(false); + } else { + if (ImGuiToolkit::IconButton(ICON_FA_PLAY_CIRCLE, "Play") ) + s.play(true); + } } else info.reset(); diff --git a/src/Visitor/ImGuiVisitor.h b/src/Visitor/ImGuiVisitor.h index 8ddacbc..c9475db 100644 --- a/src/Visitor/ImGuiVisitor.h +++ b/src/Visitor/ImGuiVisitor.h @@ -12,6 +12,7 @@ class ImGuiVisitor: public Visitor std::ostringstream oss; void list_parameters_(class ImageFilter &f, std::ostringstream &oss, bool editrange = false); + void renderAudioPanel(class MediaSource &s); public: ImGuiVisitor();