Unified GUI behavior for source creation. cleanup of history of recent

files after loading error.
This commit is contained in:
brunoherbelin
2020-09-20 11:28:09 +02:00
parent 59db2cf57c
commit 519baf7a3b
9 changed files with 139 additions and 96 deletions

View File

@@ -348,9 +348,8 @@ void ImGuiVisitor::visit (CloneSource& s)
{ {
ImGuiToolkit::Icon(9,2); ImGuiToolkit::Icon(9,2);
ImGui::SameLine(0, 10); ImGui::SameLine(0, 10);
ImGui::Text("Clone of %s", s.origin()->name().c_str()); ImGui::Text("Clone");
std::string label = "Select " + s.origin()->name(); if ( ImGui::Button(s.origin()->name().c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0)) )
if ( ImGui::Button(label.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0)) )
Mixer::manager().setCurrentSource(s.origin()); Mixer::manager().setCurrentSource(s.origin());
} }
@@ -358,13 +357,17 @@ void ImGuiVisitor::visit (PatternSource& s)
{ {
ImGuiToolkit::Icon(13,5); ImGuiToolkit::Icon(13,5);
ImGui::SameLine(0, 10); ImGui::SameLine(0, 10);
ImGui::Text("Pattern %s", Pattern::pattern_names[s.pattern()]); ImGui::Text("Pattern");
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
int p = s.pattern(); if (ImGui::BeginCombo("##Pattern", Pattern::pattern_types[s.pattern()->type()].c_str()) )
if ( ImGui::Combo("Pattern", &p, Pattern::pattern_names, IM_ARRAYSIZE(Pattern::pattern_names) ) )
{ {
s.setPattern(p); for (int p = 0; p < Pattern::pattern_types.size(); ++p){
if (ImGui::Selectable( Pattern::pattern_types[p].c_str() )) {
s.setPattern(p);
}
}
ImGui::EndCombo();
} }
} }

View File

@@ -110,7 +110,7 @@ Mixer::Mixer() : session_(nullptr), back_session_(nullptr), current_view_(nullpt
// auto load if Settings ask to // auto load if Settings ask to
if ( Settings::application.recentSessions.load_at_start && if ( Settings::application.recentSessions.load_at_start &&
Settings::application.recentSessions.valid_file && Settings::application.recentSessions.front_is_valid &&
Settings::application.recentSessions.filenames.size() > 0 ) Settings::application.recentSessions.filenames.size() > 0 )
load( Settings::application.recentSessions.filenames.front() ); load( Settings::application.recentSessions.filenames.front() );
else else
@@ -187,8 +187,14 @@ void Mixer::update()
session_->update(dt_); session_->update(dt_);
// delete sources which failed update (one by one) // delete sources which failed update (one by one)
if (session()->failedSource() != nullptr) Source *failure = session()->failedSource();
deleteSource(session()->failedSource()); if (failure != nullptr) {
MediaSource *failedFile = dynamic_cast<MediaSource *>(failure);
if (failedFile != nullptr) {
Settings::application.recentImport.remove( failedFile->path() );
}
deleteSource(failure);
}
// update views // update views
mixing_.update(dt_); mixing_.update(dt_);
@@ -240,8 +246,10 @@ Source * Mixer::createSourceFile(const std::string &path)
renameSource(s, SystemToolkit::base_filename(path)); renameSource(s, SystemToolkit::base_filename(path));
} }
else else {
Settings::application.recentImport.remove(path);
Log::Notify("File %s does not exist.", path.c_str()); Log::Notify("File %s does not exist.", path.c_str());
}
return s; return s;
} }
@@ -264,7 +272,7 @@ Source * Mixer::createSourcePattern(int pattern, glm::ivec2 res)
s->setPattern(pattern); s->setPattern(pattern);
// propose a new name based on pattern name // propose a new name based on pattern name
renameSource(s, Pattern::pattern_names[pattern]); renameSource(s, Pattern::pattern_types[pattern]);
return s; return s;
} }

View File

@@ -64,33 +64,32 @@ const char* pattern_internal_[25] = { "videotestsrc pattern=black",
"videotestsrc pattern=black ! clockoverlay halignment=center valignment=center font-desc=\"Sans, 72\" " "videotestsrc pattern=black ! clockoverlay halignment=center valignment=center font-desc=\"Sans, 72\" "
}; };
std::vector<std::string> Pattern::pattern_types = { "100% Black",
const char* Pattern::pattern_names[25] = { "100% Black", "100% White",
"100% White", "Gray bars",
"Gray bars", "Gradient",
"Gradient", "Checkers 1x1 px",
"Checkers 1x1 px", "Checkerboard",
"Checkerboard", "Circles",
"Circles", "Pinwheel",
"Pinwheel", "Spokes",
"Spokes", "100% Red",
"100% Red", "100% Green",
"100% Green", "100% Blue",
"100% Blue", "Color bars",
"Color bars", "Color Gradient",
"Color Gradient", "Color grid",
"Color grid", "SMPTE test pattern",
"SMPTE test pattern", "Television snow",
"Television snow", "Blink",
"Blink", "Fresnel zone plate",
"Fresnel zone plate", "Chroma zone plate",
"Chroma zone plate", "Moving bar",
"Moving bar", "Moving ball",
"Moving ball", "Blob",
"Blob", "Timer",
"Timer", "Clock"
"Clock" };
};
Pattern::Pattern(glm::ivec2 res) : Stream() Pattern::Pattern(glm::ivec2 res) : Stream()
{ {
@@ -99,16 +98,22 @@ Pattern::Pattern(glm::ivec2 res) : Stream()
height_ = res.y; height_ = res.y;
} }
glm::ivec2 Pattern::resolution()
{
return glm::ivec2( width_, height_);
}
void Pattern::open( uint pattern ) void Pattern::open( uint pattern )
{ {
std::string gstreamer_pattern = pattern_internal_[pattern]; type_ = CLAMP(pattern, 0, 25);
std::string gstreamer_pattern = pattern_internal_[type_];
// always some special cases... // always some special cases...
switch(pattern) switch(type_)
{ {
case 16: case 18:
case 17: case 19:
{ {
std::ostringstream oss; std::ostringstream oss;
oss << " kx2=" << (int)(aspectRatio() * 10.f) << " ky2=10 kt=4"; oss << " kx2=" << (int)(aspectRatio() * 10.f) << " ky2=10 kt=4";
@@ -121,7 +126,7 @@ void Pattern::open( uint pattern )
} }
// all patterns before index are single frames (not animated) // all patterns before index are single frames (not animated)
single_frame_ = pattern < 13; single_frame_ = type_ < 15;
// (private) open stream // (private) open stream
open(gstreamer_pattern); open(gstreamer_pattern);
@@ -149,11 +154,6 @@ PatternSource::PatternSource(glm::ivec2 resolution) : Source()
patternsurface_ = new Surface(renderingshader_); patternsurface_ = new Surface(renderingshader_);
} }
glm::ivec2 PatternSource::resolution()
{
return glm::ivec2( stream_->width(), stream_->height());
}
PatternSource::~PatternSource() PatternSource::~PatternSource()
{ {
// delete media surface & stream // delete media surface & stream
@@ -178,12 +178,10 @@ void PatternSource::replaceRenderingShader()
void PatternSource::setPattern(int id) void PatternSource::setPattern(int id)
{ {
pattern_ = CLAMP(id, 0, 25); stream_->open(id);
stream_->open(pattern_);
stream_->play(true); stream_->play(true);
Log::Notify("Creating pattern %s", Pattern::pattern_names[pattern_]); Log::Notify("Creating pattern %s", Pattern::pattern_types[id].c_str());
} }

View File

@@ -1,21 +1,25 @@
#ifndef PATTERNSOURCE_H #ifndef PATTERNSOURCE_H
#define PATTERNSOURCE_H #define PATTERNSOURCE_H
#include <vector>
#include "Source.h"
#include "Stream.h" #include "Stream.h"
#include "Source.h"
class Pattern : public Stream class Pattern : public Stream
{ {
public: public:
static const char* pattern_names[25]; static std::vector<std::string> pattern_types;
Pattern(glm::ivec2 res); Pattern(glm::ivec2 res);
void open( uint pattern ); void open( uint pattern );
glm::ivec2 resolution();
inline uint type() const { return type_; }
private: private:
void open( std::string description ) override; void open( std::string description ) override;
uint type_;
}; };
class PatternSource : public Source class PatternSource : public Source
@@ -33,11 +37,9 @@ public:
void accept (Visitor& v) override; void accept (Visitor& v) override;
// Pattern specific interface // Pattern specific interface
inline uint pattern() const { return pattern_; } inline Pattern *pattern() const { return stream_; }
void setPattern(int id); void setPattern(int id);
glm::ivec2 resolution();
protected: protected:
void init() override; void init() override;
@@ -46,7 +48,6 @@ protected:
Surface *patternsurface_; Surface *patternsurface_;
Pattern *stream_; Pattern *stream_;
uint pattern_;
}; };
#endif // PATTERNSOURCE_H #endif // PATTERNSOURCE_H

View File

@@ -384,9 +384,9 @@ void SessionVisitor::visit (CloneSource& s)
void SessionVisitor::visit (PatternSource& s) void SessionVisitor::visit (PatternSource& s)
{ {
xmlCurrent_->SetAttribute("type", "PatternSource"); xmlCurrent_->SetAttribute("type", "PatternSource");
xmlCurrent_->SetAttribute("pattern", s.pattern() ); xmlCurrent_->SetAttribute("pattern", s.pattern()->type() );
XMLElement *resolution = xmlDoc_->NewElement("resolution"); XMLElement *resolution = xmlDoc_->NewElement("resolution");
resolution->InsertEndChild( XMLElementFromGLM(xmlDoc_, s.resolution() ) ); resolution->InsertEndChild( XMLElementFromGLM(xmlDoc_, s.pattern()->resolution() ) );
xmlCurrent_->InsertEndChild(resolution); xmlCurrent_->InsertEndChild(resolution);
} }

View File

@@ -99,7 +99,6 @@ void Settings::Save()
// Source // Source
XMLElement *SourceConfNode = xmlDoc.NewElement( "Source" ); XMLElement *SourceConfNode = xmlDoc.NewElement( "Source" );
SourceConfNode->SetAttribute("new_type", application.source.new_type); SourceConfNode->SetAttribute("new_type", application.source.new_type);
SourceConfNode->SetAttribute("pattern_type", application.source.pattern_type);
SourceConfNode->SetAttribute("ratio", application.source.ratio); SourceConfNode->SetAttribute("ratio", application.source.ratio);
SourceConfNode->SetAttribute("res", application.source.res); SourceConfNode->SetAttribute("res", application.source.res);
pRoot->InsertEndChild(SourceConfNode); pRoot->InsertEndChild(SourceConfNode);
@@ -141,7 +140,7 @@ void Settings::Save()
recentsession->SetAttribute("path", application.recentSessions.path.c_str()); recentsession->SetAttribute("path", application.recentSessions.path.c_str());
recentsession->SetAttribute("autoload", application.recentSessions.load_at_start); recentsession->SetAttribute("autoload", application.recentSessions.load_at_start);
recentsession->SetAttribute("autosave", application.recentSessions.save_on_exit); recentsession->SetAttribute("autosave", application.recentSessions.save_on_exit);
recentsession->SetAttribute("valid", application.recentSessions.valid_file); recentsession->SetAttribute("valid", application.recentSessions.front_is_valid);
for(auto it = application.recentSessions.filenames.begin(); for(auto it = application.recentSessions.filenames.begin();
it != application.recentSessions.filenames.end(); it++) { it != application.recentSessions.filenames.end(); it++) {
XMLElement *fileNode = xmlDoc.NewElement("path"); XMLElement *fileNode = xmlDoc.NewElement("path");
@@ -253,7 +252,6 @@ void Settings::Load()
XMLElement * sourceconfnode = pRoot->FirstChildElement("Source"); XMLElement * sourceconfnode = pRoot->FirstChildElement("Source");
if (sourceconfnode != nullptr) { if (sourceconfnode != nullptr) {
sourceconfnode->QueryIntAttribute("new_type", &application.source.new_type); sourceconfnode->QueryIntAttribute("new_type", &application.source.new_type);
sourceconfnode->QueryIntAttribute("pattern_type", &application.source.pattern_type);
sourceconfnode->QueryIntAttribute("ratio", &application.source.ratio); sourceconfnode->QueryIntAttribute("ratio", &application.source.ratio);
sourceconfnode->QueryIntAttribute("res", &application.source.res); sourceconfnode->QueryIntAttribute("res", &application.source.res);
} }
@@ -344,7 +342,7 @@ void Settings::Load()
} }
pSession->QueryBoolAttribute("autoload", &application.recentSessions.load_at_start); pSession->QueryBoolAttribute("autoload", &application.recentSessions.load_at_start);
pSession->QueryBoolAttribute("autosave", &application.recentSessions.save_on_exit); pSession->QueryBoolAttribute("autosave", &application.recentSessions.save_on_exit);
pSession->QueryBoolAttribute("valid", &application.recentSessions.valid_file); pSession->QueryBoolAttribute("valid", &application.recentSessions.front_is_valid);
} }
// recent session filenames // recent session filenames
XMLElement * pFolder = pElement->FirstChildElement("Folder"); XMLElement * pFolder = pElement->FirstChildElement("Folder");

View File

@@ -77,26 +77,33 @@ struct History
{ {
std::string path; std::string path;
std::list<std::string> filenames; std::list<std::string> filenames;
bool valid_file; bool front_is_valid;
bool load_at_start; bool load_at_start;
bool save_on_exit; bool save_on_exit;
History() { History() {
path = IMGUI_LABEL_RECENT_FILES; path = IMGUI_LABEL_RECENT_FILES;
valid_file = false; front_is_valid = false;
load_at_start = false; load_at_start = false;
save_on_exit = false; save_on_exit = false;
} }
void push(std::string filename) { void push(const std::string &filename) {
if (filename.empty()) { if (filename.empty()) {
valid_file = false; front_is_valid = false;
return; return;
} }
filenames.remove(filename); filenames.remove(filename);
filenames.push_front(filename); filenames.push_front(filename);
if (filenames.size() > MAX_RECENT_HISTORY) if (filenames.size() > MAX_RECENT_HISTORY)
filenames.pop_back(); filenames.pop_back();
valid_file = true; front_is_valid = true;
}
void remove(const std::string &filename) {
if (filename.empty())
return;
if (filenames.front() == filename)
front_is_valid = false;
filenames.remove(filename);
} }
}; };
@@ -139,13 +146,11 @@ struct RenderConfig
struct SourceConfig struct SourceConfig
{ {
int new_type; int new_type;
int pattern_type;
int ratio; int ratio;
int res; int res;
SourceConfig() { SourceConfig() {
new_type = 0; new_type = 0;
pattern_type = 0;
ratio = 3; ratio = 3;
res = 1; res = 1;
} }

View File

@@ -984,6 +984,9 @@ void UserInterface::RenderPreview()
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();
if ( ImGui::MenuItem( ICON_FA_SHARE_SQUARE " Create Source") )
Mixer::manager().addSource( Mixer::manager().createSourceRender() );
if ( ImGui::MenuItem( ICON_FA_TIMES " Close") ) if ( ImGui::MenuItem( ICON_FA_TIMES " Close") )
Settings::application.widget.preview = false; Settings::application.widget.preview = false;
@@ -1559,6 +1562,7 @@ void Navigator::clearButtonSelection()
// clear new source pannel // clear new source pannel
sprintf(file_browser_path_, " "); sprintf(file_browser_path_, " ");
new_source_preview_.setSource(); new_source_preview_.setSource();
pattern_type = -1;
} }
void Navigator::showPannelSource(int index) void Navigator::showPannelSource(int index)
@@ -1799,8 +1803,14 @@ void SourcePreview::Render(float width, bool controlbutton)
{ {
if(source_) { if(source_) {
// cancel if failed // cancel if failed
if (source_->failed()) if (source_->failed()) {
// remove from list of recent import files if relevant
MediaSource *failedFile = dynamic_cast<MediaSource *>(source_);
if (failedFile != nullptr) {
Settings::application.recentImport.remove( failedFile->path() );
}
setSource(); setSource();
}
else else
{ {
bool active = source_->active(); bool active = source_->active();
@@ -1842,7 +1852,9 @@ void Navigator::RenderNewPannel()
ImGui::SetCursorPosY(width_); ImGui::SetCursorPosY(width_);
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
static const char* origin_names[3] = { ICON_FA_FILE " File", ICON_FA_SITEMAP " Internal", ICON_FA_COG " Generated" }; static const char* origin_names[3] = { ICON_FA_FILE " File",
ICON_FA_SITEMAP " Internal",
ICON_FA_COG " Generated" };
// TODO IMPLEMENT EXTERNAL SOURCES static const char* origin_names[3] = { ICON_FA_FILE " File", ICON_FA_SITEMAP " Internal", ICON_FA_PLUG " External" }; // TODO IMPLEMENT EXTERNAL SOURCES static const char* origin_names[3] = { ICON_FA_FILE " File", ICON_FA_SITEMAP " Internal", ICON_FA_PLUG " External" };
if (ImGui::Combo("Origin", &Settings::application.source.new_type, origin_names, IM_ARRAYSIZE(origin_names)) ) if (ImGui::Combo("Origin", &Settings::application.source.new_type, origin_names, IM_ARRAYSIZE(origin_names)) )
new_source_preview_.setSource(); new_source_preview_.setSource();
@@ -1905,7 +1917,7 @@ void Navigator::RenderNewPannel()
// fill new_source_preview with a new source // fill new_source_preview with a new source
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("##Source", "Select input")) if (ImGui::BeginCombo("##Source", "Select object"))
{ {
std::string label = "Rendering output"; std::string label = "Rendering output";
if (ImGui::Selectable( label.c_str() )) { if (ImGui::Selectable( label.c_str() )) {
@@ -1914,8 +1926,9 @@ void Navigator::RenderNewPannel()
SourceList::iterator iter; SourceList::iterator iter;
for (iter = Mixer::manager().session()->begin(); iter != Mixer::manager().session()->end(); iter++) for (iter = Mixer::manager().session()->begin(); iter != Mixer::manager().session()->end(); iter++)
{ {
label = std::string("Clone of ") + (*iter)->name(); label = std::string("Source ") + (*iter)->name();
if (ImGui::Selectable( label.c_str() )) { if (ImGui::Selectable( label.c_str() )) {
label = std::string("Clone of ") + label;
new_source_preview_.setSource( Mixer::manager().createSourceClone((*iter)->name()),label); new_source_preview_.setSource( Mixer::manager().createSourceClone((*iter)->name()),label);
} }
} }
@@ -1934,31 +1947,45 @@ void Navigator::RenderNewPannel()
bool update_new_source = false; bool update_new_source = false;
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::Combo("Aspect Ratio", &Settings::application.source.ratio, if (ImGui::BeginCombo("##Pattern", "Select generator"))
GlmToolkit::aspect_ratio_names, IM_ARRAYSIZE(GlmToolkit::aspect_ratio_names) ) )
update_new_source = true;
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::Combo("Height", &Settings::application.source.res,
GlmToolkit::height_names, IM_ARRAYSIZE(GlmToolkit::height_names) ) )
update_new_source = true;
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::Combo("Pattern", &Settings::application.source.pattern_type,
Pattern::pattern_names, IM_ARRAYSIZE(Pattern::pattern_names) ) )
update_new_source = true;
if (update_new_source)
{ {
std::string label = Pattern::pattern_names[Settings::application.source.pattern_type]; for (int p = 0; p < Pattern::pattern_types.size(); ++p){
glm::ivec2 res = GlmToolkit::resolutionFromDescription(Settings::application.source.ratio, Settings::application.source.res); if (ImGui::Selectable( Pattern::pattern_types[p].c_str() )) {
new_source_preview_.setSource( Mixer::manager().createSourcePattern(Settings::application.source.pattern_type, res), label); pattern_type = p;
update_new_source = true;
}
}
ImGui::EndCombo();
} }
// Indication // Indication
ImGui::SameLine(); ImGui::SameLine();
ImGuiToolkit::HelpMarker("Create a source generated algorithmically."); ImGuiToolkit::HelpMarker("Create a source generated algorithmically.");
// resolution (if pattern selected
if (pattern_type > 0) {
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::Combo("Ratio", &Settings::application.source.ratio,
GlmToolkit::aspect_ratio_names, IM_ARRAYSIZE(GlmToolkit::aspect_ratio_names) ) )
update_new_source = true;
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::Combo("Height", &Settings::application.source.res,
GlmToolkit::height_names, IM_ARRAYSIZE(GlmToolkit::height_names) ) )
update_new_source = true;
}
// create preview
if (update_new_source)
{
std::ostringstream oss;
oss << Pattern::pattern_types[pattern_type];
glm::ivec2 res = GlmToolkit::resolutionFromDescription(Settings::application.source.ratio, Settings::application.source.res);
oss << " (" << res.x << " x " << res.y << " px)";
new_source_preview_.setSource( Mixer::manager().createSourcePattern(pattern_type, res), oss.str());
}
} }
// Hardware // Hardware
else { else {
@@ -1967,6 +1994,8 @@ void Navigator::RenderNewPannel()
ImGuiToolkit::HelpMarker("Create a source capturing images\nfrom external devices or network."); ImGuiToolkit::HelpMarker("Create a source capturing images\nfrom external devices or network.");
} }
ImGui::NewLine();
// if a new source was added // if a new source was added
if (new_source_preview_.ready()) { if (new_source_preview_.ready()) {
// show preview // show preview
@@ -2154,7 +2183,7 @@ void Navigator::RenderMainPannel()
const char *tooltip[2] = {"Clear history", "Clear history"}; const char *tooltip[2] = {"Clear history", "Clear history"};
if (ImGuiToolkit::IconToggle(12,14,11,14, &reset, tooltip)) { if (ImGuiToolkit::IconToggle(12,14,11,14, &reset, tooltip)) {
Settings::application.recentSessions.filenames.clear(); Settings::application.recentSessions.filenames.clear();
Settings::application.recentSessions.valid_file = false; Settings::application.recentSessions.front_is_valid = false;
// reload the list next time // reload the list next time
selection_session_mode_changed = true; selection_session_mode_changed = true;
} }

View File

@@ -41,6 +41,7 @@ class Navigator
// behavior pannel // behavior pannel
bool pannel_visible_; bool pannel_visible_;
bool selected_button[NAV_COUNT]; bool selected_button[NAV_COUNT];
int pattern_type;
void clearButtonSelection(); void clearButtonSelection();
void applyButtonSelection(int index); void applyButtonSelection(int index);