mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 10:19:59 +01:00
Unified GUI behavior for source creation. cleanup of history of recent
files after loading error.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
18
Mixer.cpp
18
Mixer.cpp
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
19
Settings.h
19
Settings.h
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user