diff --git a/Mixer.cpp b/Mixer.cpp index 7fcbc44..f9902a5 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -22,13 +22,13 @@ using namespace tinyxml2; #include "Mixer.h" // static objects for multithreaded session loading -static std::atomic sessionLoadPending_ = false; -static std::atomic sessionLoadFinished_ = false; +static std::atomic sessionThreadActive_ = false; static std::string sessionThreadFilename_ = ""; +static std::atomic sessionLoadFinished_ = false; static void loadSession(const std::string& filename, Session *session) { - sessionLoadPending_ = true; + sessionThreadActive_ = true; sessionLoadFinished_ = false; sessionThreadFilename_ = ""; @@ -41,22 +41,20 @@ static void loadSession(const std::string& filename, Session *session) } else { // loaded ok - Log::Info("Session file %s loaded. %d source(s) created.", filename.c_str(), session->numSource()); + Log::Info("Session %s loaded. %d source(s) created.", filename.c_str(), session->numSource()); } sessionThreadFilename_ = filename; sessionLoadFinished_ = true; - sessionLoadPending_ = false; + sessionThreadActive_ = false; } // static objects for multithreaded session saving -static std::atomic sessionSavePending_ = false; static std::atomic sessionSaveFinished_ = false; - static void saveSession(const std::string& filename, Session *session) { // reset - sessionSavePending_ = true; + sessionThreadActive_ = true; sessionSaveFinished_ = false; sessionThreadFilename_ = ""; @@ -95,10 +93,13 @@ static void saveSession(const std::string& filename, Session *session) // save file to disk XMLSaveDoc(&xmlDoc, filename); + // loaded ok + Log::Info("Session %s saved.", filename.c_str()); + // all ok sessionThreadFilename_ = filename; sessionSaveFinished_ = true; - sessionSavePending_ = false; + sessionThreadActive_ = false; } Mixer::Mixer() : session_(nullptr), back_session_(nullptr), current_view_(nullptr) @@ -318,12 +319,18 @@ View *Mixer::currentView() void Mixer::save() { + if (sessionThreadActive_) + return; + if (!sessionFilename_.empty()) saveas(sessionFilename_); } void Mixer::saveas(const std::string& filename) { + if (sessionThreadActive_) + return; + // optional copy of views config session_->config(View::MIXING)->copyTransform( mixing_.scene.root() ); session_->config(View::GEOMETRY)->copyTransform( geometry_.scene.root() ); @@ -335,6 +342,9 @@ void Mixer::saveas(const std::string& filename) void Mixer::open(const std::string& filename) { + if (sessionThreadActive_) + return; + if (back_session_) delete back_session_; diff --git a/Settings.cpp b/Settings.cpp index 0a420f1..98c16ae 100644 --- a/Settings.cpp +++ b/Settings.cpp @@ -14,6 +14,7 @@ using namespace tinyxml2; Settings::Application Settings::application; static string settingsFilename = ""; + void Settings::Save() { XMLDocument xmlDoc; @@ -94,6 +95,7 @@ void Settings::Save() XMLElement *recent = xmlDoc.NewElement( "Recent" ); XMLElement *recentsession = xmlDoc.NewElement( "Session" ); + recentsession->SetAttribute("path", application.recentSessions.path.c_str()); recentsession->SetAttribute("auto", application.recentSessions.automatic); for(auto it = application.recentSessions.filenames.begin(); it != application.recentSessions.filenames.end(); it++) { @@ -221,6 +223,11 @@ void Settings::Load() XMLElement * pSession = pElement->FirstChildElement("Session"); if (pSession) { + const char *path_ = pSession->Attribute("path"); + if (path_) + application.recentSessions.path = std::string(path_); + else + application.recentSessions.path = SystemToolkit::home_path(); pSession->QueryBoolAttribute("auto", &application.recentSessions.automatic); application.recentSessions.filenames.clear(); XMLElement* path = pSession->FirstChildElement("path"); diff --git a/Settings.h b/Settings.h index b13a185..320eeff 100644 --- a/Settings.h +++ b/Settings.h @@ -36,6 +36,7 @@ struct ViewConfig struct History { + std::string path; std::list filenames; bool automatic; diff --git a/SystemToolkit.cpp b/SystemToolkit.cpp index 63d455b..b43e10f 100644 --- a/SystemToolkit.cpp +++ b/SystemToolkit.cpp @@ -58,7 +58,7 @@ string SystemToolkit::date_time_string() std::string SystemToolkit::base_filename(const std::string& uri) { - std::string basefilename = uri.substr(uri.find_last_of("/\\") + 1); + std::string basefilename = uri.substr(uri.find_last_of(PATH_SEP) + 1); const size_t period_idx = basefilename.rfind('.'); if (std::string::npos != period_idx) { @@ -67,7 +67,15 @@ std::string SystemToolkit::base_filename(const std::string& uri) return basefilename; } -string SystemToolkit::settings_path() +std::string SystemToolkit::path_filename(const std::string& uri) +{ + std::string path = uri.substr(0, uri.find_last_of(PATH_SEP) + 1); + + return path; +} + + +std::string SystemToolkit::home_path() { // 1. find home char *mHomePath; @@ -80,7 +88,13 @@ string SystemToolkit::settings_path() // try the $HOME environment variable mHomePath = getenv("HOME"); } - string home(mHomePath); + + return string(mHomePath) + PATH_SEP; +} + +string SystemToolkit::settings_path() +{ + string home(home_path()); // 2. try to access user settings folder string settingspath = home + PATH_SETTINGS; diff --git a/SystemToolkit.h b/SystemToolkit.h index 7f3c97f..69db709 100644 --- a/SystemToolkit.h +++ b/SystemToolkit.h @@ -15,6 +15,9 @@ namespace SystemToolkit // get fixed length string (17 chars) YYYYMMDDHHmmssiii std::string date_time_string(); + // get the OS dependent home path + std::string home_path(); + // get the OS dependent path where to store settings std::string settings_path(); @@ -24,6 +27,9 @@ namespace SystemToolkit // extract the base file name from a full URI (e.g. file:://home/me/toto.mpg -> toto) std::string base_filename(const std::string& uri); + // extract the path of a file from a full URI (e.g. file:://home/me/toto.mpg -> file:://home/me/) + std::string path_filename(const std::string& uri); + // true of file exists bool file_exists(const std::string& path); diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index 326c408..887a354 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -57,9 +57,9 @@ void ShowAboutOpengl(bool* p_open); void ShowAbout(bool* p_open); // static objects for multithreaded file dialog -static bool FileDialogPending_ = false; -static bool FileDialogLoadFinished_ = false; -static bool FileDialogSaveFinished_ = false; +static std::atomic FileDialogPending_ = false; +static std::atomic FileDialogLoadFinished_ = false; +static std::atomic FileDialogSaveFinished_ = false; static std::string FileDialogFilename_ = ""; static void FileDialogOpen(std::string path) @@ -67,19 +67,15 @@ static void FileDialogOpen(std::string path) FileDialogPending_ = true; FileDialogLoadFinished_ = false; - char const * lTheOpenFileName; - char const * lFilterPatterns[2] = { "*.vmx" }; + char const * open_file_name; + char const * open_pattern[1] = { "*.vmx" }; - lTheOpenFileName = tinyfd_openFileDialog( "Open a session file", path.c_str(), 1, lFilterPatterns, nullptr, 0); + open_file_name = tinyfd_openFileDialog( "Open a session file", path.c_str(), 1, open_pattern, nullptr, 0); - if (!lTheOpenFileName) - { + if (!open_file_name) FileDialogFilename_ = ""; - } else - { - FileDialogFilename_ = std::string( lTheOpenFileName ); - } + FileDialogFilename_ = std::string( open_file_name ); FileDialogLoadFinished_ = true; } @@ -90,14 +86,12 @@ static void FileDialogSave(std::string path) FileDialogSaveFinished_ = false; char const * save_file_name; - char const * save_pattern[2] = { "*.vmx" }; + char const * save_pattern[1] = { "*.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 ); @@ -191,7 +185,7 @@ void UserInterface::handleKeyboard() } else if (ImGui::IsKeyPressed( GLFW_KEY_O )) { // Open session - std::thread (FileDialogOpen, "./").detach(); + std::thread (FileDialogOpen, Settings::application.recentSessions.path).detach(); navigator.hidePannel(); } else if (ImGui::IsKeyPressed( GLFW_KEY_S )) { @@ -341,20 +335,36 @@ void UserInterface::NewFrame() handleKeyboard(); handleMouse(); - // navigator bar first - navigator.Render(); - // handle FileDialog if (FileDialogLoadFinished_) { FileDialogLoadFinished_ = false; FileDialogPending_ = false; - Mixer::manager().open(FileDialogFilename_); + if (!FileDialogFilename_.empty()) { + Mixer::manager().open(FileDialogFilename_); + Settings::application.recentSessions.path = SystemToolkit::path_filename(FileDialogFilename_); + } } if (FileDialogSaveFinished_) { FileDialogSaveFinished_ = false; FileDialogPending_ = false; - Mixer::manager().saveas(FileDialogFilename_); + if (!FileDialogFilename_.empty()) { + Mixer::manager().saveas(FileDialogFilename_); + Settings::application.recentSessions.path = SystemToolkit::path_filename(FileDialogFilename_); + } } + + // overlay when disabled + if (FileDialogPending_){ + ImGui::OpenPopup("Busy"); + if (ImGui::BeginPopupModal("Busy", NULL, ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::Text("Close dialog to resume..."); + ImGui::EndPopup(); + } + } + + // navigator bar first + navigator.Render(); } void UserInterface::Render() @@ -415,20 +425,20 @@ void UserInterface::Terminate() void UserInterface::showMenuFile() { - if (ImGui::MenuItem( ICON_FA_FILE " New", "Ctrl+W", false, !FileDialogPending_)) { + if (ImGui::MenuItem( ICON_FA_FILE " New", "Ctrl+W")) { Mixer::manager().newSession(); navigator.hidePannel(); } - if (ImGui::MenuItem( ICON_FA_FILE_UPLOAD " Open", "Ctrl+O", false, !FileDialogPending_)) { + if (ImGui::MenuItem( ICON_FA_FILE_UPLOAD " Open", "Ctrl+O")) { // launch file dialog to open a session file - std::thread (FileDialogOpen, "./").detach(); + std::thread (FileDialogOpen, Settings::application.recentSessions.path).detach(); navigator.hidePannel(); } - if (ImGui::MenuItem( ICON_FA_FILE_DOWNLOAD " Save", "Ctrl+S", false, !FileDialogPending_)) { + if (ImGui::MenuItem( ICON_FA_FILE_DOWNLOAD " Save", "Ctrl+S")) { Mixer::manager().save(); navigator.hidePannel(); } - if (ImGui::MenuItem( ICON_FA_FOLDER_OPEN " Save as", NULL, false, !FileDialogPending_)) { + if (ImGui::MenuItem( ICON_FA_FOLDER_OPEN " Save as")) { std::thread (FileDialogSave, "./").detach(); navigator.hidePannel(); } @@ -1049,7 +1059,8 @@ void Navigator::RenderMainPannel() { 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() )) { + int right = MIN( 40, filename.size()); + if (ImGui::Selectable( filename.substr( filename.size() - right ).c_str() )) { Mixer::manager().open( filename ); recentselected = true; }