Recent session files, saved in Settings and restored on start.

This commit is contained in:
brunoherbelin
2020-05-09 19:20:15 +02:00
parent 069009fc06
commit 7634e62054
7 changed files with 176 additions and 98 deletions

View File

@@ -106,6 +106,12 @@ Mixer::Mixer() : session_(nullptr), back_session_(nullptr), current_view_(nullpt
// this initializes with a new empty session // this initializes with a new empty session
newSession(); newSession();
// auto load if Settings ask to
if ( Settings::application.recentSessions.automatic ) {
if ( Settings::application.recentSessions.filenames.size() > 0 )
open( Settings::application.recentSessions.filenames.back() );
}
// this initializes with the current view // this initializes with the current view
setCurrentView( (View::Mode) Settings::application.current_view ); setCurrentView( (View::Mode) Settings::application.current_view );
} }
@@ -115,13 +121,17 @@ void Mixer::update()
{ {
// swap front and back sessions when loading is finished // swap front and back sessions when loading is finished
if (sessionLoadFinished_) { if (sessionLoadFinished_) {
// finished loading, swap front and back sessions
swap(); swap();
// done
sessionFilename_ = sessionThreadFilename_; sessionFilename_ = sessionThreadFilename_;
sessionLoadFinished_ = false; sessionLoadFinished_ = false;
Settings::application.recentSessions.push(sessionFilename_);
} }
if (sessionSaveFinished_) { if (sessionSaveFinished_) {
sessionFilename_ = sessionThreadFilename_; sessionFilename_ = sessionThreadFilename_;
sessionSaveFinished_ = false; sessionSaveFinished_ = false;
Settings::application.recentSessions.push(sessionFilename_);
} }
// compute dt // compute dt
@@ -176,13 +186,7 @@ void Mixer::insertSource(Source *s)
} }
void Mixer::deleteSource(Source *s) void Mixer::deleteSource(Source *s)
{ {
// SessionVisitor visit; // in case..
// geometry_.scene.accept(visit);
// visit.doc()->SaveFile("./geombefore.xml");
// SessionVisitor visitm;
// mixing_.scene.accept(visitm);
// visitm.doc()->SaveFile("./mixbefore.xml");
unsetCurrentSource(); unsetCurrentSource();
// remove source Nodes from views // remove source Nodes from views
@@ -191,13 +195,6 @@ void Mixer::deleteSource(Source *s)
// delete source // delete source
session_->deleteSource(s); session_->deleteSource(s);
// SessionVisitor visit2;
// geometry_.scene.accept(visit2);
// visit2.doc()->SaveFile("./geomafter.xml");
// SessionVisitor visit2m;
// mixing_.scene.accept(visit2m);
// visit2m.doc()->SaveFile("./mixmafter.xml");
} }
void Mixer::renameSource(Source *s, const std::string &newname) void Mixer::renameSource(Source *s, const std::string &newname)
@@ -334,39 +331,6 @@ void Mixer::saveas(const std::string& filename)
// launch a thread to save the session // launch a thread to save the session
std::thread (saveSession, filename, session_).detach(); std::thread (saveSession, filename, session_).detach();
// 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);
} }
void Mixer::open(const std::string& filename) void Mixer::open(const std::string& filename)
@@ -419,6 +383,10 @@ void Mixer::swap()
// reset timer // reset timer
update_time_ = GST_CLOCK_TIME_NONE; update_time_ = GST_CLOCK_TIME_NONE;
// delete back
delete back_session_;
back_session_ = nullptr;
} }

View File

@@ -68,10 +68,12 @@ public:
protected: protected:
Session *session_; Session *session_;
std::string sessionFilename_;
Session *back_session_; Session *back_session_;
void swap(); void swap();
// void validateFilename(const std::string& filename);
std::string sessionFilename_;
void insertSource(Source *s); void insertSource(Source *s);
void setCurrentSource(SourceList::iterator it); void setCurrentSource(SourceList::iterator it);

View File

@@ -1,3 +1,4 @@
#include <algorithm>
#include <iostream> #include <iostream>
using namespace std; using namespace std;
@@ -61,7 +62,7 @@ void Settings::Save()
applicationNode->SetAttribute("toolbox", application.toolbox); applicationNode->SetAttribute("toolbox", application.toolbox);
pRoot->InsertEndChild(applicationNode); pRoot->InsertEndChild(applicationNode);
// block: views // bloc views
{ {
XMLElement *viewsNode = xmlDoc.NewElement( "Views" ); XMLElement *viewsNode = xmlDoc.NewElement( "Views" );
viewsNode->SetAttribute("current", application.current_view); viewsNode->SetAttribute("current", application.current_view);
@@ -88,6 +89,37 @@ void Settings::Save()
pRoot->InsertEndChild(viewsNode); pRoot->InsertEndChild(viewsNode);
} }
// bloc history
{
XMLElement *recent = xmlDoc.NewElement( "Recent" );
XMLElement *recentsession = xmlDoc.NewElement( "Session" );
recentsession->SetAttribute("auto", application.recentSessions.automatic);
for(auto it = application.recentSessions.filenames.begin();
it != application.recentSessions.filenames.end(); it++) {
XMLElement *fileNode = xmlDoc.NewElement("path");
XMLText *text = xmlDoc.NewText( (*it).c_str() );
fileNode->InsertEndChild( text );
recentsession->InsertEndChild(fileNode);
};
recent->InsertEndChild(recentsession);
XMLElement *recentmedia = xmlDoc.NewElement( "Media" );
for(auto it = application.recentMedia.filenames.begin();
it != application.recentMedia.filenames.end(); it++) {
XMLElement *fileNode = xmlDoc.NewElement("uri");
XMLText *text = xmlDoc.NewText( (*it).c_str() );
fileNode->InsertEndChild( text );
recentmedia->InsertEndChild(fileNode);
}
recent->InsertEndChild(recentmedia);
pRoot->InsertEndChild(recent);
}
// First save : create filename
if (settingsFilename.empty()) if (settingsFilename.empty())
settingsFilename = SystemToolkit::settings_prepend_path(APP_SETTINGS); settingsFilename = SystemToolkit::settings_prepend_path(APP_SETTINGS);
@@ -116,32 +148,9 @@ void Settings::Load()
// different root name // different root name
return; return;
// block: windows XMLElement * pElement = pRoot->FirstChildElement("Application");
{ if (pElement == nullptr) return;
application.windows.clear(); // trash existing list pElement->QueryFloatAttribute("scale", &application.scale);
XMLElement * pElement = pRoot->FirstChildElement("Windows");
if (pElement == nullptr) return;
XMLElement* windowNode = pElement->FirstChildElement("Window");
for( ; windowNode ; windowNode=windowNode->NextSiblingElement())
{
const char *pName = windowNode->Attribute("name");
Settings::WindowConfig w(pName);
windowNode->QueryIntAttribute("x", &w.x); // If this fails, original value is left as-is
windowNode->QueryIntAttribute("y", &w.y);
windowNode->QueryIntAttribute("w", &w.w);
windowNode->QueryIntAttribute("h", &w.h);
windowNode->QueryBoolAttribute("f", &w.fullscreen);
application.windows.push_back(w);
}
}
XMLElement * pElement = pRoot->FirstChildElement("Application");
if (pElement == nullptr) return;
pElement->QueryFloatAttribute("scale", &application.scale);
pElement->QueryIntAttribute("accent_color", &application.accent_color); pElement->QueryIntAttribute("accent_color", &application.accent_color);
pElement->QueryBoolAttribute("preview", &application.preview); pElement->QueryBoolAttribute("preview", &application.preview);
pElement->QueryBoolAttribute("media_player", &application.media_player); pElement->QueryBoolAttribute("media_player", &application.media_player);
@@ -151,32 +160,90 @@ void Settings::Load()
pElement->QueryBoolAttribute("toolbox", &application.toolbox); pElement->QueryBoolAttribute("toolbox", &application.toolbox);
pElement->QueryIntAttribute("stats_corner", &application.stats_corner); pElement->QueryIntAttribute("stats_corner", &application.stats_corner);
// block: views // bloc windows
{
application.windows.clear(); // trash existing list
XMLElement * pElement = pRoot->FirstChildElement("Windows");
if (pElement)
{
XMLElement* windowNode = pElement->FirstChildElement("Window");
for( ; windowNode ; windowNode=windowNode->NextSiblingElement())
{
const char *pName = windowNode->Attribute("name");
Settings::WindowConfig w(pName);
windowNode->QueryIntAttribute("x", &w.x); // If this fails, original value is left as-is
windowNode->QueryIntAttribute("y", &w.y);
windowNode->QueryIntAttribute("w", &w.w);
windowNode->QueryIntAttribute("h", &w.h);
windowNode->QueryBoolAttribute("f", &w.fullscreen);
application.windows.push_back(w);
}
}
}
// bloc views
{ {
application.views.clear(); // trash existing list application.views.clear(); // trash existing list
XMLElement * pElement = pRoot->FirstChildElement("Views"); XMLElement * pElement = pRoot->FirstChildElement("Views");
if (pElement == nullptr) return; if (pElement)
pElement->QueryIntAttribute("current", &application.current_view);
XMLElement* viewNode = pElement->FirstChildElement("View");
for( ; viewNode ; viewNode=viewNode->NextSiblingElement())
{ {
int id = 0; pElement->QueryIntAttribute("current", &application.current_view);
viewNode->QueryIntAttribute("id", &id);
application.views[id].name = viewNode->Attribute("name");
XMLElement* scaleNode = viewNode->FirstChildElement("default_scale"); XMLElement* viewNode = pElement->FirstChildElement("View");
tinyxml2::XMLElementToGLM( scaleNode->FirstChildElement("vec3"), for( ; viewNode ; viewNode=viewNode->NextSiblingElement())
application.views[id].default_scale); {
int id = 0;
viewNode->QueryIntAttribute("id", &id);
application.views[id].name = viewNode->Attribute("name");
XMLElement* translationNode = viewNode->FirstChildElement("default_translation"); XMLElement* scaleNode = viewNode->FirstChildElement("default_scale");
tinyxml2::XMLElementToGLM( translationNode->FirstChildElement("vec3"), tinyxml2::XMLElementToGLM( scaleNode->FirstChildElement("vec3"),
application.views[id].default_translation); application.views[id].default_scale);
XMLElement* translationNode = viewNode->FirstChildElement("default_translation");
tinyxml2::XMLElementToGLM( translationNode->FirstChildElement("vec3"),
application.views[id].default_translation);
}
}
}
// bloc history of recent
{
XMLElement * pElement = pRoot->FirstChildElement("Recent");
if (pElement)
{
// recent session filenames
XMLElement * pSession = pElement->FirstChildElement("Session");
if (pSession)
{
pSession->QueryBoolAttribute("auto", &application.recentSessions.automatic);
application.recentSessions.filenames.clear();
XMLElement* path = pSession->FirstChildElement("path");
for( ; path ; path = path->NextSiblingElement())
{
application.recentSessions.push( std::string (path->GetText()) );
}
}
// recent media uri
XMLElement * pMedia = pElement->FirstChildElement("Media");
if (pMedia)
{
application.recentMedia.filenames.clear();
XMLElement* path = pMedia->FirstChildElement("path");
for( ; path ; path = path->NextSiblingElement())
{
application.recentMedia.push( std::string (path->GetText()) );
}
}
} }
} }
} }

View File

@@ -6,6 +6,7 @@
#include <string> #include <string>
#include <map> #include <map>
#include <vector> #include <vector>
#include <list>
#include <glm/glm.hpp> #include <glm/glm.hpp>
namespace Settings { namespace Settings {
@@ -33,6 +34,22 @@ struct ViewConfig
}; };
struct History
{
std::list<std::string> filenames;
bool automatic;
History() {
automatic = false;
}
void push(std::string filename) {
filenames.remove(filename);
filenames.push_front(filename);
if (filenames.size() > MAX_RECENT_HISTORY)
filenames.pop_back();
}
};
struct Application struct Application
{ {
// Verification // Verification
@@ -54,9 +71,13 @@ struct Application
std::map<int, ViewConfig> views; std::map<int, ViewConfig> views;
// multiple windows handling // multiple windows handling
// TODO: maybe keep map of multiple windows, widn id=0 for main window // TODO: manage other windows
std::vector<WindowConfig> windows; std::vector<WindowConfig> windows;
// recent files histories
History recentSessions;
History recentMedia;
Application() : name(APP_NAME){ Application() : name(APP_NAME){
scale = 1.f; scale = 1.f;
accent_color = 0; accent_color = 0;

View File

@@ -2,6 +2,7 @@
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include <thread> #include <thread>
#include <algorithm>
// ImGui // ImGui
#include "imgui.h" #include "imgui.h"
@@ -100,6 +101,10 @@ static void FileDialogSave(std::string path)
else else
{ {
FileDialogFilename_ = std::string( save_file_name ); FileDialogFilename_ = std::string( save_file_name );
// check extension
std::string extension = FileDialogFilename_.substr(FileDialogFilename_.find_last_of(".") + 1);
if (extension != "vmx")
FileDialogFilename_ += ".vmx";
} }
FileDialogSaveFinished_ = true; FileDialogSaveFinished_ = true;
@@ -186,14 +191,16 @@ void UserInterface::handleKeyboard()
} }
else if (ImGui::IsKeyPressed( GLFW_KEY_O )) { else if (ImGui::IsKeyPressed( GLFW_KEY_O )) {
// Open session // Open session
std::thread (FileDialogOpen, "./").detach();
navigator.hidePannel();
} }
else if (ImGui::IsKeyPressed( GLFW_KEY_S )) { else if (ImGui::IsKeyPressed( GLFW_KEY_S )) {
// Save Session // Save Session
std::cerr <<" Save File " << std::endl; Mixer::manager().save();
} }
else if (ImGui::IsKeyPressed( GLFW_KEY_W )) { else if (ImGui::IsKeyPressed( GLFW_KEY_W )) {
// New Session // New Session
std::cerr <<" Close File " << std::endl; Mixer::manager().newSession();
} }
else if (ImGui::IsKeyPressed( GLFW_KEY_L )) { else if (ImGui::IsKeyPressed( GLFW_KEY_L )) {
// Logs // Logs
@@ -1035,10 +1042,23 @@ void Navigator::RenderMainPannel()
ImGui::EndMenu(); ImGui::EndMenu();
} }
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
static int recent_session = 0; // combo box with list of recent session files from Settings
if ( ImGui::Combo("Recent", &recent_session, "Select\0") ) { static bool recentselected = false;
recentselected = false;
if (ImGui::BeginCombo("Recent", "Select"))
{
std::for_each(Settings::application.recentSessions.filenames.begin(),
Settings::application.recentSessions.filenames.end(), [](std::string& filename) {
if (ImGui::Selectable( filename.substr( filename.size() - 40 ).c_str() )) {
Mixer::manager().open( filename );
recentselected = true;
}
});
ImGui::EndCombo();
} }
if (recentselected)
hidePannel();
ImGuiToolkit::ButtonSwitch( "Load most recent on start", &Settings::application.recentSessions.automatic);
ImGui::Text(" "); ImGui::Text(" ");
ImGui::Text("Windows"); ImGui::Text("Windows");

View File

@@ -79,7 +79,6 @@ class UserInterface
// } FileDialogStatus; // } FileDialogStatus;
// FileDialogStatus filestatus_; // FileDialogStatus filestatus_;
// std::string filename_; // std::string filename_;
// std::thread filethread_;
// void startOpenFileDialog(); // void startOpenFileDialog();
// Private Constructor // Private Constructor

View File

@@ -8,6 +8,7 @@
#define APP_VERSION_MINOR 1 #define APP_VERSION_MINOR 1
#define XML_VERSION_MAJOR 0 #define XML_VERSION_MAJOR 0
#define XML_VERSION_MINOR 1 #define XML_VERSION_MINOR 1
#define MAX_RECENT_HISTORY 10
#define MINI(a, b) (((a) < (b)) ? (a) : (b)) #define MINI(a, b) (((a) < (b)) ? (a) : (b))
#define MAXI(a, b) (((a) > (b)) ? (a) : (b)) #define MAXI(a, b) (((a) > (b)) ? (a) : (b))