Properties pannel of Session

Also added custom thumbnail of session.
This commit is contained in:
Bruno
2021-08-01 00:29:44 +02:00
parent c5f0be2b32
commit d1e833e0a1
7 changed files with 222 additions and 43 deletions

View File

@@ -38,11 +38,13 @@ void captureMixerSession(tinyxml2::XMLDocument *doc, std::string node, std::stri
Session *se = Mixer::manager().session(); Session *se = Mixer::manager().session();
// get the thumbnail (requires one opengl update to render) // get the thumbnail (requires one opengl update to render)
FrameBufferImage *thumbnail = se->thumbnail(); FrameBufferImage *thumbnail = se->renderThumbnail();
if (thumbnail) {
XMLElement *imageelement = SessionVisitor::ImageToXML(thumbnail, doc); XMLElement *imageelement = SessionVisitor::ImageToXML(thumbnail, doc);
if (imageelement) if (imageelement)
sessionNode->InsertEndChild(imageelement); sessionNode->InsertEndChild(imageelement);
delete thumbnail; delete thumbnail;
}
// save all sources using source visitor // save all sources using source visitor
SessionVisitor sv(doc, sessionNode); SessionVisitor sv(doc, sessionNode);

View File

@@ -18,7 +18,7 @@ SessionNote::SessionNote(const std::string &t, bool l, int s): label(std::to_str
{ {
} }
Session::Session() : active_(true), filename_(""), failedSource_(nullptr), fading_target_(0.f) Session::Session() : active_(true), filename_(""), failedSource_(nullptr), fading_target_(0.f), thumbnail_(nullptr)
{ {
config_[View::RENDERING] = new Group; config_[View::RENDERING] = new Group;
config_[View::RENDERING]->scale_ = glm::vec3(0.f); config_[View::RENDERING]->scale_ = glm::vec3(0.f);
@@ -228,6 +228,33 @@ Source *Session::popSource()
return s; return s;
} }
static void replaceThumbnail(Session *s)
{
if (s != nullptr) {
FrameBufferImage *t = s->renderThumbnail();
if (t != nullptr) // avoid recursive infinite loop
s->setThumbnail(t);
}
}
void Session::setThumbnail(FrameBufferImage *t)
{
resetThumbnail();
// replace with given image
if (t != nullptr)
thumbnail_ = t;
// no thumbnail image given: capture from rendering in a parallel thread
else
std::thread( replaceThumbnail, this ).detach();
}
void Session::resetThumbnail()
{
if (thumbnail_ != nullptr)
delete thumbnail_;
thumbnail_ = nullptr;
}
void Session::setResolution(glm::vec3 resolution, bool useAlpha) void Session::setResolution(glm::vec3 resolution, bool useAlpha)
{ {
// setup the render view: if not specified the default config resulution will be used // setup the render view: if not specified the default config resulution will be used

View File

@@ -85,8 +85,13 @@ public:
// get frame result of render // get frame result of render
inline FrameBuffer *frame () const { return render_.frame(); } inline FrameBuffer *frame () const { return render_.frame(); }
// get thumbnail image // get an newly rendered thumbnail
inline FrameBufferImage *thumbnail () { return render_.thumbnail(); } inline FrameBufferImage *renderThumbnail () { return render_.thumbnail(); }
// get / set thumbnail image
inline FrameBufferImage *thumbnail () const { return thumbnail_; }
void setThumbnail(FrameBufferImage *t = nullptr);
void resetThumbnail();
// configure rendering resolution // configure rendering resolution
void setResolution (glm::vec3 resolution, bool useAlpha = false); void setResolution (glm::vec3 resolution, bool useAlpha = false);
@@ -153,7 +158,7 @@ protected:
std::vector<SourceIdList> play_groups_; std::vector<SourceIdList> play_groups_;
float fading_target_; float fading_target_;
std::mutex access_; std::mutex access_;
FrameBufferImage *thumbnail_;
}; };

View File

@@ -54,6 +54,12 @@ SessionInformation SessionCreator::info(const std::string& filename)
} }
const XMLElement *session = doc.FirstChildElement("Session"); const XMLElement *session = doc.FirstChildElement("Session");
if (session != nullptr ) { if (session != nullptr ) {
const XMLElement *thumbnailelement = session->FirstChildElement("Thumbnail");
// if there is a user defined thumbnail, get it
if (thumbnailelement)
ret.thumbnail = XMLToImage(thumbnailelement);
// otherwise get the default saved thumbnail in session
else
ret.thumbnail = XMLToImage(session); ret.thumbnail = XMLToImage(session);
} }
} }
@@ -100,7 +106,8 @@ void SessionCreator::load(const std::string& filename)
// ready to read sources // ready to read sources
sessionFilePath_ = SystemToolkit::path_filename(filename); sessionFilePath_ = SystemToolkit::path_filename(filename);
SessionLoader::load( xmlDoc_.FirstChildElement("Session") ); XMLElement *sessionNode = xmlDoc_.FirstChildElement("Session");
SessionLoader::load( sessionNode );
// create groups // create groups
std::list< SourceList > groups = getMixingGroups(); std::list< SourceList > groups = getMixingGroups();
@@ -116,6 +123,15 @@ void SessionCreator::load(const std::string& filename)
// load playlists // load playlists
loadPlayGroups( xmlDoc_.FirstChildElement("PlayGroups") ); loadPlayGroups( xmlDoc_.FirstChildElement("PlayGroups") );
// thumbnail
const XMLElement *thumbnailelement = sessionNode->FirstChildElement("Thumbnail");
// if there is a user-defined thumbnail, get it
if (thumbnailelement) {
FrameBufferImage *thumbnail = XMLToImage(thumbnailelement);
if (thumbnail != nullptr)
session_->setThumbnail( thumbnail );
}
// all good // all good
session_->setFilename(filename); session_->setFilename(filename);
} }

View File

@@ -51,12 +51,26 @@ bool SessionVisitor::saveSession(const std::string& filename, Session *session)
// source visitor // source visitor
(*iter)->accept(sv); (*iter)->accept(sv);
// get the thumbnail // save the thumbnail
FrameBufferImage *thumbnail = session->thumbnail(); FrameBufferImage *thumbnail = session->thumbnail();
if (thumbnail != nullptr && thumbnail->width > 0 && thumbnail->height > 0) {
XMLElement *thumbnailelement = xmlDoc.NewElement("Thumbnail");
XMLElement *imageelement = SessionVisitor::ImageToXML(thumbnail, &xmlDoc);
if (imageelement) {
sessionNode->InsertEndChild(thumbnailelement);
thumbnailelement->InsertEndChild(imageelement);
}
}
// if no thumbnail is set by user, capture thumbnail now
else {
thumbnail = session->renderThumbnail();
if (thumbnail) {
XMLElement *imageelement = SessionVisitor::ImageToXML(thumbnail, &xmlDoc); XMLElement *imageelement = SessionVisitor::ImageToXML(thumbnail, &xmlDoc);
if (imageelement) if (imageelement)
sessionNode->InsertEndChild(imageelement); sessionNode->InsertEndChild(imageelement);
delete thumbnail; delete thumbnail;
}
}
// 2. config of views // 2. config of views
saveConfig( &xmlDoc, session ); saveConfig( &xmlDoc, session );

View File

@@ -767,7 +767,10 @@ void UserInterface::Render()
} }
// verify the video recorder is valid // verify the video recorder is valid
FrameGrabbing::manager().verify(&video_recorder_); FrameGrabbing::manager().verify(&video_recorder_);
if (video_recorder_ && video_recorder_->duration() > Settings::application.record.timeout ){ if (video_recorder_ // if there is an ongoing recorder
&& Settings::application.record.timeout < RECORD_MAX_TIMEOUT // and if the timeout is valid
&& video_recorder_->duration() > Settings::application.record.timeout ) // and the timeout is reached
{
video_recorder_->stop(); video_recorder_->stop();
video_recorder_ = nullptr; video_recorder_ = nullptr;
} }
@@ -1078,27 +1081,33 @@ void UserInterface::RenderPreview()
Settings::application.widget.preview = false; Settings::application.widget.preview = false;
if (ImGui::BeginMenu(IMGUI_TITLE_PREVIEW)) if (ImGui::BeginMenu(IMGUI_TITLE_PREVIEW))
{ {
glm::ivec2 p = FrameBuffer::getParametersFromResolution(output->resolution()); // glm::ivec2 p = FrameBuffer::getParametersFromResolution(output->resolution());
std::ostringstream info; // std::ostringstream info;
info << "Resolution " << output->width() << "x" << output->height(); // info << "Resolution " << output->width() << "x" << output->height();
if (p.x > -1) // if (p.x > -1)
info << " " << FrameBuffer::aspect_ratio_name[p.x] ; // info << " " << FrameBuffer::aspect_ratio_name[p.x] ;
ImGui::MenuItem(info.str().c_str(), nullptr, false, false); // ImGui::MenuItem(info.str().c_str(), nullptr, false, false);
// cannot change resolution when recording // // cannot change resolution when recording
if (video_recorder_ == nullptr && p.y > -1) { // if (video_recorder_ == nullptr && p.y > -1) {
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); // ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::Combo("Height", &p.y, FrameBuffer::resolution_name, IM_ARRAYSIZE(FrameBuffer::resolution_name) ) ) // if (ImGui::Combo("Height", &p.y, FrameBuffer::resolution_name, IM_ARRAYSIZE(FrameBuffer::resolution_name) ) )
{ // {
glm::vec3 res = FrameBuffer::getResolutionFromParameters(p.x, p.y); // glm::vec3 res = FrameBuffer::getResolutionFromParameters(p.x, p.y);
Mixer::manager().session()->setResolution(res); // Mixer::manager().session()->setResolution(res);
} // }
} // }
if ( ImGui::MenuItem( ICON_FA_PLUS " Insert Rendering Source") ) if ( ImGui::MenuItem( ICON_FA_PLUS " Insert Rendering Source") )
Mixer::manager().addSource( Mixer::manager().createSourceRender() ); Mixer::manager().addSource( Mixer::manager().createSourceRender() );
if ( ImGui::MenuItem( ICON_FA_WINDOW_RESTORE " Show output window") ) if ( ImGui::MenuItem( ICON_FA_WINDOW_RESTORE " Show output window") )
Rendering::manager().outputWindow().show(); Rendering::manager().outputWindow().show();
bool isfullscreen = Rendering::manager().outputWindow().isFullscreen();
if ( ImGui::MenuItem( ICON_FA_EXPAND_ALT " Fullscreen output window", nullptr, &isfullscreen) ) {
Rendering::manager().outputWindow().show();
Rendering::manager().outputWindow().toggleFullscreen();
}
ImGui::Separator(); ImGui::Separator();
bool pinned = Settings::application.widget.preview_view == Settings::application.current_view; bool pinned = Settings::application.widget.preview_view == Settings::application.current_view;
@@ -4105,7 +4114,7 @@ void Navigator::RenderMainPannelVimix()
_file_info = info.description; _file_info = info.description;
if (info.thumbnail) { if (info.thumbnail) {
// set image content to thumbnail display // set image content to thumbnail display
_file_thumbnail.set( info.thumbnail ); _file_thumbnail.fill( info.thumbnail );
delete info.thumbnail; delete info.thumbnail;
} else } else
_file_thumbnail.reset(); _file_thumbnail.reset();
@@ -4148,7 +4157,7 @@ void Navigator::RenderMainPannelVimix()
// Right side of the list: helper and options // Right side of the list: helper and options
ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y)); ImGui::SetCursorPos( ImVec2( pannel_width_ IMGUI_RIGHT_ALIGN, pos_top.y));
if ( ImGuiToolkit::IconButton( ICON_FA_FILE )) { if ( ImGuiToolkit::IconButton( ICON_FA_FILE " +" )) {
Mixer::manager().close(Settings::application.smooth_transition ); Mixer::manager().close(Settings::application.smooth_transition );
hidePannel(); hidePannel();
} }
@@ -4174,13 +4183,112 @@ void Navigator::RenderMainPannelVimix()
// Status // Status
// //
ImGui::Spacing(); ImGui::Spacing();
ImGui::Text("Status"); ImGui::Text("Current");
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("##SelectHistory", &Settings::application.pannel_history_mode, ICON_FA_STAR " Snapshots\0" ICON_FA_HISTORY " Undo history\0");
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::Combo("##SelectHistory", &Settings::application.pannel_history_mode,
ICON_FA_STAR " Snapshots\0" ICON_FA_HISTORY " Undo history\0" ICON_FA_FILE_ALT " Properties\0");
if (Settings::application.pannel_history_mode > 1) {
std::string sessionfilename = Mixer::manager().session()->filename();
// Information and resolution
FrameBuffer *output = Mixer::manager().session()->frame();
if (output)
{
// fill information buffer
ImGuiTextBuffer info;
if (!sessionfilename.empty())
info.appendf("%s\n", SystemToolkit::filename(sessionfilename).c_str());
else
info.append("<unsaved>\n");
info.appendf("Sources: %d\n", Mixer::manager().session()->numSource());
glm::ivec2 p = FrameBuffer::getParametersFromResolution(output->resolution());
if (p.x > -1)
info.appendf("Ratio: %s\n", FrameBuffer::aspect_ratio_name[p.x]);
info.appendf("Resolution: %dx%d", output->width(), output->height());
// Show info text bloc (multi line, dark background)
ImGuiToolkit::PushFont( ImGuiToolkit::FONT_MONO );
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f));
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
ImGui::InputTextMultiline("##Info", (char *)info.c_str(), info.size(), ImVec2(IMGUI_RIGHT_ALIGN, 4*ImGui::GetTextLineHeightWithSpacing()), ImGuiInputTextFlags_ReadOnly);
ImGui::PopStyleColor(1);
ImGui::PopFont();
// change resolution (height only)
if (p.y > -1) {
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
// cannot change resolution when recording
if ( UserInterface::manager().isRecording() ) {
// show static info (same size than combo)
static char dummy_str[512];
sprintf(dummy_str, "%s", FrameBuffer::resolution_name[p.y]);
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f));
ImGui::InputText("Height", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly);
ImGui::PopStyleColor(1);
}
else {
// combo box to select height
if (ImGui::Combo("Height", &p.y, FrameBuffer::resolution_name, IM_ARRAYSIZE(FrameBuffer::resolution_name) ) )
{
glm::vec3 res = FrameBuffer::getResolutionFromParameters(p.x, p.y);
Mixer::manager().session()->setResolution(res);
}
}
}
}
// the session file exists
if (!sessionfilename.empty())
{
// Thumbnail
static Thumbnail _file_thumbnail;
static FrameBufferImage *thumbnail = nullptr;
if ( ImGui::Button( ICON_FA_TAGS " Capture thumbnail", ImVec2(IMGUI_RIGHT_ALIGN, 0)) ) {
Mixer::manager().session()->setThumbnail();
thumbnail = nullptr;
}
pos_bot = ImGui::GetCursorPos();
if (ImGui::IsItemHovered()){
// thumbnail changed
if (thumbnail != Mixer::manager().session()->thumbnail()) {
_file_thumbnail.reset();
thumbnail = Mixer::manager().session()->thumbnail();
if (thumbnail != nullptr)
_file_thumbnail.fill( thumbnail );
}
if (_file_thumbnail.filled()) {
ImGui::BeginTooltip();
_file_thumbnail.Render(230);
ImGui::EndTooltip();
}
}
if (Mixer::manager().session()->thumbnail()) {
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.7);
ImGui::SameLine();
if (ImGuiToolkit::IconButton(ICON_FA_BACKSPACE, "Remove captured thumbnail")) {
Mixer::manager().session()->resetThumbnail();
_file_thumbnail.reset();
thumbnail = nullptr;
}
ImGui::PopStyleVar();
}
ImGui::SetCursorPos( pos_bot );
// Folder
std::string path = SystemToolkit::path_filename(sessionfilename);
std::string label = BaseToolkit::trunc_string(path, 23);
label = BaseToolkit::transliterate(label);
ImGuiToolkit::ButtonOpenUrl( label.c_str(), path.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0) );
}
}
// //
// UNDO History // UNDO History
if (Settings::application.pannel_history_mode > 0) { else if (Settings::application.pannel_history_mode > 0) {
static uint _over = 0; static uint _over = 0;
static uint64_t _displayed_over = 0; static uint64_t _displayed_over = 0;
@@ -4220,7 +4328,7 @@ void Navigator::RenderMainPannelVimix()
FrameBufferImage *im = Action::manager().thumbnail(_over); FrameBufferImage *im = Action::manager().thumbnail(_over);
if (im) { if (im) {
// set image content to thumbnail display // set image content to thumbnail display
_undo_thumbnail.set( im ); _undo_thumbnail.fill( im );
delete im; delete im;
} }
else else
@@ -4329,7 +4437,7 @@ void Navigator::RenderMainPannelVimix()
FrameBufferImage *im = Action::manager().thumbnail(_over); FrameBufferImage *im = Action::manager().thumbnail(_over);
if (im) { if (im) {
// set image content to thumbnail display // set image content to thumbnail display
_snap_thumbnail.set( im ); _snap_thumbnail.fill( im );
delete im; delete im;
} }
else else
@@ -4742,12 +4850,17 @@ Thumbnail::~Thumbnail()
glDeleteTextures(1, &texture_); glDeleteTextures(1, &texture_);
} }
bool Thumbnail::filled()
{
return aspect_ratio_ > 0.f;
}
void Thumbnail::reset() void Thumbnail::reset()
{ {
aspect_ratio_ = -1.f; aspect_ratio_ = -1.f;
} }
void Thumbnail::set(const FrameBufferImage *image) void Thumbnail::fill(const FrameBufferImage *image)
{ {
if (!texture_) { if (!texture_) {
glGenTextures(1, &texture_); glGenTextures(1, &texture_);
@@ -4764,7 +4877,7 @@ void Thumbnail::set(const FrameBufferImage *image)
void Thumbnail::Render(float width) void Thumbnail::Render(float width)
{ {
if (aspect_ratio_>0.f) if (filled())
ImGui::Image((void*)(intptr_t)texture_, ImVec2(width, width/aspect_ratio_), ImVec2(0,0), ImVec2(0.5f*aspect_ratio_, 1.f)); ImGui::Image((void*)(intptr_t)texture_, ImVec2(width, width/aspect_ratio_), ImVec2(0,0), ImVec2(0.5f*aspect_ratio_, 1.f));
} }

View File

@@ -45,7 +45,8 @@ public:
~Thumbnail(); ~Thumbnail();
void reset(); void reset();
void set (const FrameBufferImage *image); void fill (const FrameBufferImage *image);
bool filled();
void Render(float width); void Render(float width);
}; };
@@ -218,6 +219,7 @@ public:
void fillShaderEditor(const std::string &text); void fillShaderEditor(const std::string &text);
void StartScreenshot(); void StartScreenshot();
inline bool isRecording() const { return video_recorder_ != nullptr; }
protected: protected: