mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-05 23:40:02 +01:00
Session loading and saving in thread.
This commit is contained in:
@@ -50,12 +50,6 @@ void ImageShader::reset()
|
||||
{
|
||||
Shader::reset();
|
||||
|
||||
// setup double texturing (TODO : do it only once)
|
||||
program_->use();
|
||||
program_->setUniform("iChannel0", 0);
|
||||
program_->setUniform("iChannel1", 1);
|
||||
program_->enduse();
|
||||
|
||||
// default mask
|
||||
mask = 0;
|
||||
custom_textureindex = mask_presets[0];
|
||||
|
||||
265
Mixer.cpp
265
Mixer.cpp
@@ -22,22 +22,86 @@ using namespace tinyxml2;
|
||||
#include "Mixer.h"
|
||||
|
||||
// static objects for multithreaded session loading
|
||||
static bool sessionLoadPending_ = false;
|
||||
static bool sessionLoadFinished_ = false;
|
||||
static Session *loadedSession;
|
||||
static std::atomic<bool> sessionLoadPending_ = false;
|
||||
static std::atomic<bool> sessionLoadFinished_ = false;
|
||||
static std::string sessionThreadFilename_ = "";
|
||||
|
||||
static void loadSession(const std::string& filename, )
|
||||
static void loadSession(const std::string& filename, Session *session)
|
||||
{
|
||||
sessionLoadPending_ = true;
|
||||
sessionLoadFinished_ = false;
|
||||
sessionThreadFilename_ = "";
|
||||
|
||||
// actual loading of xml file
|
||||
SessionCreator creator( session );
|
||||
|
||||
if (!creator.load(filename)) {
|
||||
// error loading
|
||||
Log::Info("Failed to load Session file %s.", filename.c_str());
|
||||
}
|
||||
else {
|
||||
// loaded ok
|
||||
Log::Info("Session file %s loaded. %d source(s) created.", filename.c_str(), session->numSource());
|
||||
}
|
||||
|
||||
sessionThreadFilename_ = filename;
|
||||
sessionLoadFinished_ = true;
|
||||
sessionLoadPending_ = false;
|
||||
}
|
||||
|
||||
// static objects for multithreaded session saving
|
||||
static std::atomic<bool> sessionSavePending_ = false;
|
||||
static std::atomic<bool> sessionSaveFinished_ = false;
|
||||
|
||||
static void saveSession(const std::string& filename, Session *session)
|
||||
{
|
||||
// reset
|
||||
sessionSavePending_ = true;
|
||||
sessionSaveFinished_ = false;
|
||||
sessionThreadFilename_ = "";
|
||||
|
||||
// creation of XML doc
|
||||
XMLDocument xmlDoc;
|
||||
|
||||
Mixer::Mixer() : session_(nullptr), current_view_(nullptr)
|
||||
XMLElement *version = xmlDoc.NewElement(APP_NAME);
|
||||
version->SetAttribute("major", XML_VERSION_MAJOR);
|
||||
version->SetAttribute("minor", XML_VERSION_MINOR);
|
||||
xmlDoc.InsertEndChild(version);
|
||||
|
||||
// 1. list of sources
|
||||
XMLElement *sessionNode = xmlDoc.NewElement("Session");
|
||||
xmlDoc.InsertEndChild(sessionNode);
|
||||
SourceList::iterator iter;
|
||||
for (iter = session->begin(); iter != session->end(); iter++)
|
||||
{
|
||||
SessionVisitor sv(&xmlDoc, sessionNode);
|
||||
// source visitor
|
||||
(*iter)->accept(sv);
|
||||
}
|
||||
|
||||
// 2. config of views
|
||||
XMLElement *views = xmlDoc.NewElement("Views");
|
||||
xmlDoc.InsertEndChild(views);
|
||||
{
|
||||
XMLElement *mixing = xmlDoc.NewElement( "Mixing" );
|
||||
mixing->InsertEndChild( SessionVisitor::NodeToXML(*session->config(View::MIXING), &xmlDoc));
|
||||
views->InsertEndChild(mixing);
|
||||
|
||||
XMLElement *geometry = xmlDoc.NewElement( "Geometry" );
|
||||
geometry->InsertEndChild( SessionVisitor::NodeToXML(*session->config(View::GEOMETRY), &xmlDoc));
|
||||
views->InsertEndChild(geometry);
|
||||
}
|
||||
|
||||
// save file to disk
|
||||
XMLSaveDoc(&xmlDoc, filename);
|
||||
|
||||
// all ok
|
||||
sessionThreadFilename_ = filename;
|
||||
sessionSaveFinished_ = true;
|
||||
sessionSavePending_ = false;
|
||||
}
|
||||
|
||||
Mixer::Mixer() : session_(nullptr), back_session_(nullptr), current_view_(nullptr)
|
||||
{
|
||||
// this initializes with a new empty session
|
||||
newSession();
|
||||
@@ -49,6 +113,17 @@ Mixer::Mixer() : session_(nullptr), current_view_(nullptr)
|
||||
|
||||
void Mixer::update()
|
||||
{
|
||||
// swap front and back sessions when loading is finished
|
||||
if (sessionLoadFinished_) {
|
||||
swap();
|
||||
sessionFilename_ = sessionThreadFilename_;
|
||||
sessionLoadFinished_ = false;
|
||||
}
|
||||
if (sessionSaveFinished_) {
|
||||
sessionFilename_ = sessionThreadFilename_;
|
||||
sessionSaveFinished_ = false;
|
||||
}
|
||||
|
||||
// compute dt
|
||||
if (update_time_ == GST_CLOCK_TIME_NONE)
|
||||
update_time_ = gst_util_get_timestamp ();
|
||||
@@ -244,119 +319,99 @@ View *Mixer::currentView()
|
||||
return current_view_;
|
||||
}
|
||||
|
||||
|
||||
void Mixer::save(const std::string& filename)
|
||||
void Mixer::save()
|
||||
{
|
||||
XMLDocument xmlDoc;
|
||||
|
||||
XMLElement *version = xmlDoc.NewElement(APP_NAME);
|
||||
version->SetAttribute("major", XML_VERSION_MAJOR);
|
||||
version->SetAttribute("minor", XML_VERSION_MINOR);
|
||||
xmlDoc.InsertEndChild(version);
|
||||
|
||||
// block: list of sources
|
||||
XMLElement *session = xmlDoc.NewElement("Session");
|
||||
xmlDoc.InsertEndChild(session);
|
||||
SourceList::iterator iter;
|
||||
for (iter = session_->begin(); iter != session_->end(); iter++)
|
||||
{
|
||||
SessionVisitor sv(&xmlDoc, session);
|
||||
// source visitor
|
||||
(*iter)->accept(sv);
|
||||
}
|
||||
|
||||
// block: config of views
|
||||
XMLElement *views = xmlDoc.NewElement("Views");
|
||||
xmlDoc.InsertEndChild(views);
|
||||
{
|
||||
XMLElement *mixing = xmlDoc.NewElement( "Mixing" );
|
||||
mixing->InsertEndChild( SessionVisitor::NodeToXML(*mixing_.scene.root(), &xmlDoc));
|
||||
views->InsertEndChild(mixing);
|
||||
|
||||
XMLElement *geometry = xmlDoc.NewElement( "Geometry" );
|
||||
geometry->InsertEndChild( SessionVisitor::NodeToXML(*geometry_.scene.root(), &xmlDoc));
|
||||
views->InsertEndChild(geometry);
|
||||
}
|
||||
|
||||
// save file
|
||||
XMLSaveDoc(&xmlDoc, filename);
|
||||
if (!sessionFilename_.empty())
|
||||
saveas(sessionFilename_);
|
||||
}
|
||||
|
||||
bool Mixer::open(const std::string& filename)
|
||||
void Mixer::saveas(const std::string& filename)
|
||||
{
|
||||
XMLDocument xmlDoc;
|
||||
XMLError eResult = xmlDoc.LoadFile(filename.c_str());
|
||||
if (XMLResultError(eResult))
|
||||
return false;
|
||||
// optional copy of views config
|
||||
session_->config(View::MIXING)->copyTransform( mixing_.scene.root() );
|
||||
session_->config(View::GEOMETRY)->copyTransform( geometry_.scene.root() );
|
||||
|
||||
XMLElement *version = xmlDoc.FirstChildElement(APP_NAME);
|
||||
if (version == nullptr) {
|
||||
Log::Warning("Not a %s session file: %s", APP_NAME, filename.c_str());
|
||||
return false;
|
||||
}
|
||||
int version_major = -1, version_minor = -1;
|
||||
version->QueryIntAttribute("major", &version_major); // TODO incompatible if major is different?
|
||||
version->QueryIntAttribute("minor", &version_minor);
|
||||
if (version_major != XML_VERSION_MAJOR || version_minor != XML_VERSION_MINOR){
|
||||
Log::Warning("%s is in an older versions of session file format. Data might be lost.", filename.c_str());
|
||||
}
|
||||
// launch a thread to save the session
|
||||
std::thread (saveSession, filename, session_).detach();
|
||||
|
||||
// ok, ready to read sources
|
||||
SessionCreator creator( xmlDoc.FirstChildElement("Session") );
|
||||
Session *new_session = creator.session();
|
||||
// XMLDocument xmlDoc;
|
||||
|
||||
// if all good, change to new session
|
||||
if (new_session) {
|
||||
// XMLElement *version = xmlDoc.NewElement(APP_NAME);
|
||||
// version->SetAttribute("major", XML_VERSION_MAJOR);
|
||||
// version->SetAttribute("minor", XML_VERSION_MINOR);
|
||||
// xmlDoc.InsertEndChild(version);
|
||||
|
||||
// validate new session
|
||||
newSession( new_session );
|
||||
// // block: list of sources
|
||||
// XMLElement *session = xmlDoc.NewElement("Session");
|
||||
// xmlDoc.InsertEndChild(session);
|
||||
// SourceList::iterator iter;
|
||||
// for (iter = session_->begin(); iter != session_->end(); iter++)
|
||||
// {
|
||||
// SessionVisitor sv(&xmlDoc, session);
|
||||
// // source visitor
|
||||
// (*iter)->accept(sv);
|
||||
// }
|
||||
|
||||
// insert nodes of sources into views
|
||||
SourceList::iterator source_iter;
|
||||
for (source_iter = new_session->begin(); source_iter != new_session->end(); source_iter++)
|
||||
{
|
||||
mixing_.scene.fg()->attach( (*source_iter)->group(View::MIXING) );
|
||||
geometry_.scene.fg()->attach( (*source_iter)->group(View::GEOMETRY) );
|
||||
}
|
||||
// // block: config of views
|
||||
// XMLElement *views = xmlDoc.NewElement("Views");
|
||||
// xmlDoc.InsertEndChild(views);
|
||||
// {
|
||||
// XMLElement *mixing = xmlDoc.NewElement( "Mixing" );
|
||||
// mixing->InsertEndChild( SessionVisitor::NodeToXML(*mixing_.scene.root(), &xmlDoc));
|
||||
// views->InsertEndChild(mixing);
|
||||
|
||||
}
|
||||
else {
|
||||
Log::Warning("Session file %s not loaded.", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
// XMLElement *geometry = xmlDoc.NewElement( "Geometry" );
|
||||
// geometry->InsertEndChild( SessionVisitor::NodeToXML(*geometry_.scene.root(), &xmlDoc));
|
||||
// views->InsertEndChild(geometry);
|
||||
// }
|
||||
|
||||
// config of view settings (optionnal)
|
||||
XMLElement *views = xmlDoc.FirstChildElement("Views");
|
||||
if (views != nullptr) {
|
||||
// ok, ready to read views
|
||||
SessionCreator::XMLToNode( views->FirstChildElement("Mixing"), *mixing_.scene.root());
|
||||
SessionCreator::XMLToNode( views->FirstChildElement("Geometry"), *geometry_.scene.root());
|
||||
}
|
||||
|
||||
Log::Info("Session file %s loaded. %d source(s) created.", filename.c_str(), session_->numSource());
|
||||
|
||||
return true;
|
||||
// // save file
|
||||
// XMLSaveDoc(&xmlDoc, filename);
|
||||
}
|
||||
|
||||
void Mixer::newSession(Session *newsession)
|
||||
void Mixer::open(const std::string& filename)
|
||||
{
|
||||
// delete session & detatch nodes from views
|
||||
if (back_session_)
|
||||
delete back_session_;
|
||||
|
||||
// create empty session
|
||||
back_session_ = new Session;
|
||||
|
||||
// launch a thread to load the session into back_session
|
||||
std::thread (loadSession, filename, back_session_).detach();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Mixer::swap()
|
||||
{
|
||||
if (!back_session_)
|
||||
return;
|
||||
|
||||
if (session_) {
|
||||
// remove nodes from views
|
||||
// detatch current session's nodes from views
|
||||
for (auto source_iter = session_->begin(); source_iter != session_->end(); source_iter++)
|
||||
{
|
||||
mixing_.scene.fg()->detatch( (*source_iter)->group(View::MIXING) );
|
||||
geometry_.scene.fg()->detatch( (*source_iter)->group(View::GEOMETRY) );
|
||||
}
|
||||
// clear session: delete all sources
|
||||
delete session_;
|
||||
}
|
||||
|
||||
// validate new session
|
||||
if (newsession)
|
||||
session_ = newsession;
|
||||
else
|
||||
session_ = new Session;
|
||||
// swap back and front
|
||||
Session *tmp = session_;
|
||||
session_ = back_session_;
|
||||
back_session_ = tmp;
|
||||
|
||||
// attach new session's nodes to views
|
||||
for (auto source_iter = session_->begin(); source_iter != session_->end(); source_iter++)
|
||||
{
|
||||
mixing_.scene.fg()->attach( (*source_iter)->group(View::MIXING) );
|
||||
geometry_.scene.fg()->attach( (*source_iter)->group(View::GEOMETRY) );
|
||||
}
|
||||
|
||||
// optional copy of views config
|
||||
mixing_.scene.root()->copyTransform( session_->config(View::MIXING) );
|
||||
geometry_.scene.root()->copyTransform( session_->config(View::GEOMETRY) );
|
||||
|
||||
// no current source
|
||||
current_source_ = session_->end();
|
||||
@@ -364,8 +419,24 @@ void Mixer::newSession(Session *newsession)
|
||||
|
||||
// reset timer
|
||||
update_time_ = GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
// default views
|
||||
|
||||
void Mixer::newSession()
|
||||
{
|
||||
// delete previous back session if needed
|
||||
if (back_session_)
|
||||
delete back_session_;
|
||||
|
||||
// create empty session
|
||||
back_session_ = new Session;
|
||||
|
||||
// swap current with empty
|
||||
swap();
|
||||
|
||||
// default view config
|
||||
mixing_.restoreSettings();
|
||||
geometry_.restoreSettings();
|
||||
|
||||
sessionFilename_ = "newsession.vmx";
|
||||
}
|
||||
|
||||
14
Mixer.h
14
Mixer.h
@@ -60,17 +60,21 @@ public:
|
||||
Session *session() { return session_; }
|
||||
|
||||
// load and save session
|
||||
bool open(const std::string& filename);
|
||||
void save(const std::string& filename);
|
||||
void newSession(Session *newsession = nullptr);
|
||||
|
||||
void open(const std::string& filename);
|
||||
void saveas(const std::string& filename);
|
||||
void save();
|
||||
void newSession();
|
||||
|
||||
protected:
|
||||
|
||||
Session *session_;
|
||||
std::string sessionFilename_;
|
||||
Session *back_session_;
|
||||
void swap();
|
||||
|
||||
void insertSource(Source *s);
|
||||
void setCurrentSource(SourceList::iterator it);
|
||||
|
||||
Session *session_;
|
||||
SourceList::iterator current_source_;
|
||||
int current_source_index_;
|
||||
|
||||
|
||||
10
Scene.cpp
10
Scene.cpp
@@ -50,6 +50,16 @@ Node::~Node ()
|
||||
|
||||
}
|
||||
|
||||
void Node::copyTransform(Node *other)
|
||||
{
|
||||
if (!other)
|
||||
return;
|
||||
transform_ = glm::identity<glm::mat4>();
|
||||
scale_ = other->scale_;
|
||||
rotation_ = other->rotation_;
|
||||
translation_ = other->translation_;
|
||||
}
|
||||
|
||||
void Node::update( float )
|
||||
{
|
||||
// update transform matrix from attributes
|
||||
|
||||
4
Scene.h
4
Scene.h
@@ -65,14 +65,14 @@ public:
|
||||
// accept all kind of visitors
|
||||
virtual void accept (Visitor& v);
|
||||
|
||||
void copyTransform(Node *other);
|
||||
|
||||
// public members, to manipulate with care
|
||||
bool visible_;
|
||||
uint refcount_;
|
||||
|
||||
glm::mat4 transform_;
|
||||
glm::vec3 scale_, rotation_, translation_;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
|
||||
Session::Session()
|
||||
{
|
||||
|
||||
config_[View::RENDERING] = new Group;
|
||||
config_[View::GEOMETRY] = new Group;
|
||||
config_[View::MIXING] = new Group;
|
||||
}
|
||||
|
||||
|
||||
Session::~Session()
|
||||
{
|
||||
// delete all sources
|
||||
|
||||
@@ -32,9 +32,14 @@ public:
|
||||
// result of render
|
||||
inline FrameBuffer *frame() const { return render_.frameBuffer(); }
|
||||
|
||||
// configuration for group nodes of views
|
||||
inline Group *config(View::Mode m) const { return config_.at(m); }
|
||||
|
||||
protected:
|
||||
RenderView render_;
|
||||
SourceList sources_;
|
||||
|
||||
std::map<View::Mode, Group*> config_;
|
||||
};
|
||||
|
||||
#endif // SESSION_H
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "SessionCreator.h"
|
||||
|
||||
#include "Log.h"
|
||||
#include "defines.h"
|
||||
#include "Scene.h"
|
||||
#include "Primitives.h"
|
||||
#include "Mesh.h"
|
||||
@@ -14,12 +15,48 @@
|
||||
using namespace tinyxml2;
|
||||
|
||||
|
||||
SessionCreator::SessionCreator(tinyxml2::XMLElement *sessionNode): Visitor()
|
||||
SessionCreator::SessionCreator(Session *session): Visitor(), session_(session)
|
||||
{
|
||||
session_ = nullptr;
|
||||
xmlDoc_ = new XMLDocument;
|
||||
|
||||
}
|
||||
|
||||
bool SessionCreator::load(const std::string& filename)
|
||||
{
|
||||
XMLError eResult = xmlDoc_->LoadFile(filename.c_str());
|
||||
if ( XMLResultError(eResult))
|
||||
return false;
|
||||
|
||||
XMLElement *version = xmlDoc_->FirstChildElement(APP_NAME);
|
||||
if (version == nullptr) {
|
||||
Log::Warning("%s is not a %s session file.", filename.c_str(), APP_NAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
int version_major = -1, version_minor = -1;
|
||||
version->QueryIntAttribute("major", &version_major); // TODO incompatible if major is different?
|
||||
version->QueryIntAttribute("minor", &version_minor);
|
||||
if (version_major != XML_VERSION_MAJOR || version_minor != XML_VERSION_MINOR){
|
||||
Log::Warning("%s is in a different versions of session file. Loading might fail.", filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// ok, ready to read sources
|
||||
loadSession( xmlDoc_->FirstChildElement("Session") );
|
||||
// excellent, session was created: load optionnal config
|
||||
if (session_){
|
||||
loadConfig( xmlDoc_->FirstChildElement("Views") );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SessionCreator::loadSession(XMLElement *sessionNode)
|
||||
{
|
||||
if (sessionNode != nullptr) {
|
||||
session_ = new Session;
|
||||
// create a session if not provided
|
||||
if (!session_)
|
||||
session_ = new Session;
|
||||
|
||||
int counter = 0;
|
||||
XMLElement* sourceNode = sessionNode->FirstChildElement("Source");
|
||||
@@ -34,16 +71,23 @@ SessionCreator::SessionCreator(tinyxml2::XMLElement *sessionNode): Visitor()
|
||||
new_media_source->accept(*this);
|
||||
session_->addSource(new_media_source);
|
||||
}
|
||||
// TODO : else other types of source
|
||||
// TODO : create other types of source
|
||||
|
||||
}
|
||||
Log::Info("Created %d Sources", counter);
|
||||
|
||||
}
|
||||
else
|
||||
Log::Warning("Session seems empty.");
|
||||
}
|
||||
|
||||
void SessionCreator::loadConfig(XMLElement *viewsNode)
|
||||
{
|
||||
if (viewsNode != nullptr) {
|
||||
// ok, ready to read views
|
||||
SessionCreator::XMLToNode( viewsNode->FirstChildElement("Mixing"), *session_->config(View::MIXING));
|
||||
SessionCreator::XMLToNode( viewsNode->FirstChildElement("Geometry"), *session_->config(View::GEOMETRY));
|
||||
}
|
||||
}
|
||||
|
||||
void SessionCreator::XMLToNode(tinyxml2::XMLElement *xml, Node &n)
|
||||
{
|
||||
|
||||
@@ -8,12 +8,17 @@ class Session;
|
||||
|
||||
class SessionCreator : public Visitor {
|
||||
|
||||
tinyxml2::XMLDocument *xmlDoc_;
|
||||
tinyxml2::XMLElement *xmlCurrent_;
|
||||
Session *session_;
|
||||
|
||||
public:
|
||||
SessionCreator(tinyxml2::XMLElement *root);
|
||||
void loadSession(tinyxml2::XMLElement *sessionNode);
|
||||
void loadConfig(tinyxml2::XMLElement *viewsNode);
|
||||
|
||||
public:
|
||||
SessionCreator(Session *session = nullptr);
|
||||
|
||||
bool load(const std::string& filename);
|
||||
inline Session *session() const { return session_; }
|
||||
|
||||
// Elements of Scene
|
||||
|
||||
16
Shader.cpp
16
Shader.cpp
@@ -50,26 +50,30 @@ bool ShadingProgram::initialized()
|
||||
|
||||
void ShadingProgram::compile()
|
||||
{
|
||||
const char* vcode = vertex_code_.c_str();
|
||||
const char* vcode = vertex_code_.c_str();
|
||||
vertex_id_ = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_id_, 1, &vcode, NULL);
|
||||
glCompileShader(vertex_id_);
|
||||
|
||||
const char* fcode = fragment_code_.c_str();
|
||||
const char* fcode = fragment_code_.c_str();
|
||||
fragment_id_ = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_id_, 1, &fcode, NULL);
|
||||
glCompileShader(fragment_id_);
|
||||
|
||||
checkCompileErr();
|
||||
checkCompileErr();
|
||||
}
|
||||
|
||||
void ShadingProgram::link()
|
||||
{
|
||||
id_ = glCreateProgram();
|
||||
id_ = glCreateProgram();
|
||||
glAttachShader(id_, vertex_id_);
|
||||
glAttachShader(id_, fragment_id_);
|
||||
glLinkProgram(id_);
|
||||
checkLinkingErr();
|
||||
glLinkProgram(id_);
|
||||
checkLinkingErr();
|
||||
glUseProgram(id_);
|
||||
glUniform1i(glGetUniformLocation(id_, "iChannel0"), 0);
|
||||
glUniform1i(glGetUniformLocation(id_, "iChannel1"), 1);
|
||||
glUseProgram(0);
|
||||
glDeleteShader(vertex_id_);
|
||||
glDeleteShader(fragment_id_);
|
||||
}
|
||||
|
||||
@@ -57,12 +57,14 @@ void ShowAbout(bool* p_open);
|
||||
|
||||
// static objects for multithreaded file dialog
|
||||
static bool FileDialogPending_ = false;
|
||||
static bool FileDialogFinished_ = false;
|
||||
static bool FileDialogLoadFinished_ = false;
|
||||
static bool FileDialogSaveFinished_ = false;
|
||||
static std::string FileDialogFilename_ = "";
|
||||
|
||||
static void FileDialogOpen(std::string path)
|
||||
{
|
||||
FileDialogPending_ = true;
|
||||
FileDialogLoadFinished_ = false;
|
||||
|
||||
char const * lTheOpenFileName;
|
||||
char const * lFilterPatterns[2] = { "*.vmx" };
|
||||
@@ -78,7 +80,29 @@ static void FileDialogOpen(std::string path)
|
||||
FileDialogFilename_ = std::string( lTheOpenFileName );
|
||||
}
|
||||
|
||||
FileDialogFinished_ = true;
|
||||
FileDialogLoadFinished_ = true;
|
||||
}
|
||||
|
||||
static void FileDialogSave(std::string path)
|
||||
{
|
||||
FileDialogPending_ = true;
|
||||
FileDialogSaveFinished_ = false;
|
||||
|
||||
char const * save_file_name;
|
||||
char const * save_pattern[2] = { "*.vmx" };
|
||||
|
||||
save_file_name = tinyfd_saveFileDialog( "Save a session file", path.c_str(), 1, save_pattern, "vimix session");
|
||||
|
||||
if (!save_file_name)
|
||||
{
|
||||
FileDialogFilename_ = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
FileDialogFilename_ = std::string( save_file_name );
|
||||
}
|
||||
|
||||
FileDialogSaveFinished_ = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -314,11 +338,16 @@ void UserInterface::NewFrame()
|
||||
navigator.Render();
|
||||
|
||||
// handle FileDialog
|
||||
if (FileDialogFinished_) {
|
||||
FileDialogFinished_ = false;
|
||||
if (FileDialogLoadFinished_) {
|
||||
FileDialogLoadFinished_ = false;
|
||||
FileDialogPending_ = false;
|
||||
Mixer::manager().open(FileDialogFilename_);
|
||||
}
|
||||
if (FileDialogSaveFinished_) {
|
||||
FileDialogSaveFinished_ = false;
|
||||
FileDialogPending_ = false;
|
||||
Mixer::manager().saveas(FileDialogFilename_);
|
||||
}
|
||||
}
|
||||
|
||||
void UserInterface::Render()
|
||||
@@ -389,9 +418,13 @@ void UserInterface::showMenuFile()
|
||||
navigator.hidePannel();
|
||||
}
|
||||
if (ImGui::MenuItem( ICON_FA_FILE_DOWNLOAD " Save", "Ctrl+S", false, !FileDialogPending_)) {
|
||||
// UserInterface::manager().OpenFileMedia();
|
||||
Mixer::manager().save();
|
||||
navigator.hidePannel();
|
||||
}
|
||||
if (ImGui::MenuItem( ICON_FA_FOLDER_OPEN " Save as", NULL, false, !FileDialogPending_)) {
|
||||
std::thread (FileDialogSave, "./").detach();
|
||||
navigator.hidePannel();
|
||||
}
|
||||
// TODO : Save As...
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem( ICON_FA_POWER_OFF " Quit", "Ctrl+Q")) {
|
||||
|
||||
Reference in New Issue
Block a user