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);
ImGui::SameLine(0, 10);
ImGui::Text("Clone of %s", s.origin()->name().c_str());
std::string label = "Select " + s.origin()->name();
if ( ImGui::Button(label.c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0)) )
ImGui::Text("Clone");
if ( ImGui::Button(s.origin()->name().c_str(), ImVec2(IMGUI_RIGHT_ALIGN, 0)) )
Mixer::manager().setCurrentSource(s.origin());
}
@@ -358,13 +357,17 @@ void ImGuiVisitor::visit (PatternSource& s)
{
ImGuiToolkit::Icon(13,5);
ImGui::SameLine(0, 10);
ImGui::Text("Pattern %s", Pattern::pattern_names[s.pattern()]);
ImGui::Text("Pattern");
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
int p = s.pattern();
if ( ImGui::Combo("Pattern", &p, Pattern::pattern_names, IM_ARRAYSIZE(Pattern::pattern_names) ) )
if (ImGui::BeginCombo("##Pattern", Pattern::pattern_types[s.pattern()->type()].c_str()) )
{
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
if ( Settings::application.recentSessions.load_at_start &&
Settings::application.recentSessions.valid_file &&
Settings::application.recentSessions.front_is_valid &&
Settings::application.recentSessions.filenames.size() > 0 )
load( Settings::application.recentSessions.filenames.front() );
else
@@ -187,8 +187,14 @@ void Mixer::update()
session_->update(dt_);
// delete sources which failed update (one by one)
if (session()->failedSource() != nullptr)
deleteSource(session()->failedSource());
Source *failure = session()->failedSource();
if (failure != nullptr) {
MediaSource *failedFile = dynamic_cast<MediaSource *>(failure);
if (failedFile != nullptr) {
Settings::application.recentImport.remove( failedFile->path() );
}
deleteSource(failure);
}
// update views
mixing_.update(dt_);
@@ -240,8 +246,10 @@ Source * Mixer::createSourceFile(const std::string &path)
renameSource(s, SystemToolkit::base_filename(path));
}
else
else {
Settings::application.recentImport.remove(path);
Log::Notify("File %s does not exist.", path.c_str());
}
return s;
}
@@ -264,7 +272,7 @@ Source * Mixer::createSourcePattern(int pattern, glm::ivec2 res)
s->setPattern(pattern);
// propose a new name based on pattern name
renameSource(s, Pattern::pattern_names[pattern]);
renameSource(s, Pattern::pattern_types[pattern]);
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\" "
};
const char* Pattern::pattern_names[25] = { "100% Black",
"100% White",
"Gray bars",
"Gradient",
"Checkers 1x1 px",
"Checkerboard",
"Circles",
"Pinwheel",
"Spokes",
"100% Red",
"100% Green",
"100% Blue",
"Color bars",
"Color Gradient",
"Color grid",
"SMPTE test pattern",
"Television snow",
"Blink",
"Fresnel zone plate",
"Chroma zone plate",
"Moving bar",
"Moving ball",
"Blob",
"Timer",
"Clock"
};
std::vector<std::string> Pattern::pattern_types = { "100% Black",
"100% White",
"Gray bars",
"Gradient",
"Checkers 1x1 px",
"Checkerboard",
"Circles",
"Pinwheel",
"Spokes",
"100% Red",
"100% Green",
"100% Blue",
"Color bars",
"Color Gradient",
"Color grid",
"SMPTE test pattern",
"Television snow",
"Blink",
"Fresnel zone plate",
"Chroma zone plate",
"Moving bar",
"Moving ball",
"Blob",
"Timer",
"Clock"
};
Pattern::Pattern(glm::ivec2 res) : Stream()
{
@@ -99,16 +98,22 @@ Pattern::Pattern(glm::ivec2 res) : Stream()
height_ = res.y;
}
glm::ivec2 Pattern::resolution()
{
return glm::ivec2( width_, height_);
}
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...
switch(pattern)
switch(type_)
{
case 16:
case 17:
case 18:
case 19:
{
std::ostringstream oss;
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)
single_frame_ = pattern < 13;
single_frame_ = type_ < 15;
// (private) open stream
open(gstreamer_pattern);
@@ -149,11 +154,6 @@ PatternSource::PatternSource(glm::ivec2 resolution) : Source()
patternsurface_ = new Surface(renderingshader_);
}
glm::ivec2 PatternSource::resolution()
{
return glm::ivec2( stream_->width(), stream_->height());
}
PatternSource::~PatternSource()
{
// delete media surface & stream
@@ -178,12 +178,10 @@ void PatternSource::replaceRenderingShader()
void PatternSource::setPattern(int id)
{
pattern_ = CLAMP(id, 0, 25);
stream_->open(pattern_);
stream_->open(id);
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
#define PATTERNSOURCE_H
#include "Source.h"
#include <vector>
#include "Stream.h"
#include "Source.h"
class Pattern : public Stream
{
public:
static const char* pattern_names[25];
static std::vector<std::string> pattern_types;
Pattern(glm::ivec2 res);
void open( uint pattern );
glm::ivec2 resolution();
inline uint type() const { return type_; }
private:
void open( std::string description ) override;
uint type_;
};
class PatternSource : public Source
@@ -33,11 +37,9 @@ public:
void accept (Visitor& v) override;
// Pattern specific interface
inline uint pattern() const { return pattern_; }
inline Pattern *pattern() const { return stream_; }
void setPattern(int id);
glm::ivec2 resolution();
protected:
void init() override;
@@ -46,7 +48,6 @@ protected:
Surface *patternsurface_;
Pattern *stream_;
uint pattern_;
};
#endif // PATTERNSOURCE_H

View File

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

View File

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

View File

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

View File

@@ -984,6 +984,9 @@ void UserInterface::RenderPreview()
if ( ImGui::MenuItem( ICON_FA_WINDOW_RESTORE " Show output window") )
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") )
Settings::application.widget.preview = false;
@@ -1559,6 +1562,7 @@ void Navigator::clearButtonSelection()
// clear new source pannel
sprintf(file_browser_path_, " ");
new_source_preview_.setSource();
pattern_type = -1;
}
void Navigator::showPannelSource(int index)
@@ -1799,8 +1803,14 @@ void SourcePreview::Render(float width, bool controlbutton)
{
if(source_) {
// 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();
}
else
{
bool active = source_->active();
@@ -1842,7 +1852,9 @@ void Navigator::RenderNewPannel()
ImGui::SetCursorPosY(width_);
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" };
if (ImGui::Combo("Origin", &Settings::application.source.new_type, origin_names, IM_ARRAYSIZE(origin_names)) )
new_source_preview_.setSource();
@@ -1905,7 +1917,7 @@ void Navigator::RenderNewPannel()
// fill new_source_preview with a new source
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("##Source", "Select input"))
if (ImGui::BeginCombo("##Source", "Select object"))
{
std::string label = "Rendering output";
if (ImGui::Selectable( label.c_str() )) {
@@ -1914,8 +1926,9 @@ void Navigator::RenderNewPannel()
SourceList::iterator 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() )) {
label = std::string("Clone of ") + label;
new_source_preview_.setSource( Mixer::manager().createSourceClone((*iter)->name()),label);
}
}
@@ -1934,31 +1947,45 @@ void Navigator::RenderNewPannel()
bool update_new_source = false;
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::Combo("Aspect 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;
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)
if (ImGui::BeginCombo("##Pattern", "Select generator"))
{
std::string label = Pattern::pattern_names[Settings::application.source.pattern_type];
glm::ivec2 res = GlmToolkit::resolutionFromDescription(Settings::application.source.ratio, Settings::application.source.res);
new_source_preview_.setSource( Mixer::manager().createSourcePattern(Settings::application.source.pattern_type, res), label);
for (int p = 0; p < Pattern::pattern_types.size(); ++p){
if (ImGui::Selectable( Pattern::pattern_types[p].c_str() )) {
pattern_type = p;
update_new_source = true;
}
}
ImGui::EndCombo();
}
// Indication
ImGui::SameLine();
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
else {
@@ -1967,6 +1994,8 @@ void Navigator::RenderNewPannel()
ImGuiToolkit::HelpMarker("Create a source capturing images\nfrom external devices or network.");
}
ImGui::NewLine();
// if a new source was added
if (new_source_preview_.ready()) {
// show preview
@@ -2154,7 +2183,7 @@ void Navigator::RenderMainPannel()
const char *tooltip[2] = {"Clear history", "Clear history"};
if (ImGuiToolkit::IconToggle(12,14,11,14, &reset, tooltip)) {
Settings::application.recentSessions.filenames.clear();
Settings::application.recentSessions.valid_file = false;
Settings::application.recentSessions.front_is_valid = false;
// reload the list next time
selection_session_mode_changed = true;
}

View File

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