diff --git a/FrameGrabber.cpp b/FrameGrabber.cpp index a3b34d4..4ba12e7 100644 --- a/FrameGrabber.cpp +++ b/FrameGrabber.cpp @@ -79,12 +79,9 @@ void FrameGrabbing::verify(FrameGrabber **rec) *rec = nullptr; } -FrameGrabber *FrameGrabbing::front() +bool FrameGrabbing::busy() const { - if (grabbers_.empty()) - return nullptr; - - return grabbers_.front(); + return !grabbers_.empty(); } struct fgId: public std::unary_function diff --git a/FrameGrabber.h b/FrameGrabber.h index 2dce0e6..78d9648 100644 --- a/FrameGrabber.h +++ b/FrameGrabber.h @@ -119,7 +119,7 @@ public: void add(FrameGrabber *rec); void chain(FrameGrabber *rec, FrameGrabber *new_rec); void verify(FrameGrabber **rec); - FrameGrabber *front(); + bool busy() const; FrameGrabber *get(uint64_t id); void stopAll(); void clearAll(); diff --git a/Mixer.cpp b/Mixer.cpp index 03962a7..04ea692 100644 --- a/Mixer.cpp +++ b/Mixer.cpp @@ -66,13 +66,13 @@ const std::chrono::milliseconds timeout_ = std::chrono::milliseconds(4); // static multithreaded session saving static void saveSession(const std::string& filename, Session *session, bool with_version) { + // lock access while saving + session->lock(); + // capture a snapshot of current version if requested if (with_version) Action::manager().snapshot( SystemToolkit::date_time_string()); - // lock access while saving - session->lock(); - // save file to disk if ( SessionVisitor::saveSession(filename, session) ) { // all ok diff --git a/Session.cpp b/Session.cpp index e5ec272..4e623eb 100644 --- a/Session.cpp +++ b/Session.cpp @@ -602,6 +602,14 @@ void Session::unlock() access_.unlock(); } +bool Session::locked() +{ + bool l = access_.try_lock(); + if (l) + access_.unlock(); + return !l; +} + void Session::validate (SourceList &sources) { // verify that all sources given are valid in the sesion diff --git a/Session.h b/Session.h index 2b55018..8db68ff 100644 --- a/Session.h +++ b/Session.h @@ -151,6 +151,7 @@ public: // lock and unlock access (e.g. while saving) void lock (); void unlock (); + bool locked (); protected: bool active_; diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index c252969..53594f4 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -141,6 +141,7 @@ UserInterface::UserInterface() currentTextEdit.clear(); screenshot_step = 0; pending_save_on_exit = false; + close_and_exit = false; sessionopendialog = nullptr; sessionimportdialog = nullptr; @@ -152,6 +153,9 @@ bool UserInterface::Init() if (Rendering::manager().mainWindow().window()== nullptr) return false; + pending_save_on_exit = false; + close_and_exit = false; + // Setup Dear ImGui context IMGUI_CHECKVERSION(); ImGui::CreateContext(); @@ -683,18 +687,27 @@ bool UserInterface::TryClose() // force close if trying to close again although it is already pending for save if (pending_save_on_exit) { - Rendering::manager().close(); + close_and_exit = true; return true; } - // general case: determine if a pending save of session is required + // determine if a pending save of session is required pending_save_on_exit = ( Settings::application.recentSessions.save_on_exit && !Mixer::manager().session()->empty() && Mixer::manager().session()->filename().empty() ); // if no pending save of session is needed, close if (!pending_save_on_exit) - Rendering::manager().close(); + { + // stop all recordings + FrameGrabbing::manager().stopAll(); + + // save on exit + if (Settings::application.recentSessions.save_on_exit) + Mixer::manager().save(false); + + close_and_exit = true; + } // say we can close if no pending save of session is needed return !pending_save_on_exit; @@ -745,7 +758,8 @@ void UserInterface::NewFrame() // overlay to ensure file dialog is modal if (DialogToolkit::FileDialog::busy()){ - ImGui::OpenPopup("Busy"); + if (!ImGui::IsPopupOpen("Busy")) + ImGui::OpenPopup("Busy"); if (ImGui::BeginPopupModal("Busy", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::Text("Close file dialog box to resume."); @@ -754,27 +768,49 @@ void UserInterface::NewFrame() } // popup to inform to save before close - if (pending_save_on_exit && !ImGui::IsPopupOpen(MENU_SAVE_ON_EXIT)) - ImGui::OpenPopup(MENU_SAVE_ON_EXIT); - if (ImGui::BeginPopupModal(MENU_SAVE_ON_EXIT, NULL, ImGuiWindowFlags_AlwaysAutoResize)) - { - ImGui::Spacing(); - ImGuiToolkit::PushFont(ImGuiToolkit::FONT_ITALIC); - ImGui::Text("Looks like you started some work"); - ImGui::Text("but didn't save the session."); - ImGui::PopFont(); - ImGui::Spacing(); - if (ImGui::Button(MENU_SAVEAS_FILE, ImVec2(ImGui::GetWindowContentRegionWidth(), 0))) { - pending_save_on_exit = false; - saveOrSaveAs(); - ImGui::CloseCurrentPopup(); + if (pending_save_on_exit) { + if (!ImGui::IsPopupOpen(MENU_SAVE_ON_EXIT)) + ImGui::OpenPopup(MENU_SAVE_ON_EXIT); + if (ImGui::BeginPopupModal(MENU_SAVE_ON_EXIT, NULL, ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::Spacing(); + ImGuiToolkit::PushFont(ImGuiToolkit::FONT_ITALIC); + ImGui::Text("Looks like you started some work"); + ImGui::Text("but didn't save the session."); + ImGui::PopFont(); + ImGui::Spacing(); + if (ImGui::Button(MENU_SAVEAS_FILE, ImVec2(ImGui::GetWindowContentRegionWidth(), 0))) { + pending_save_on_exit = false; + saveOrSaveAs(); + ImGui::CloseCurrentPopup(); + } + if (ImGui::Button(MENU_QUIT, ImVec2(ImGui::GetWindowContentRegionWidth(), 0))) { + pending_save_on_exit = false; + close_and_exit = true; + ImGui::CloseCurrentPopup(); + } + ImGui::Spacing(); + ImGui::EndPopup(); } - if (ImGui::Button(MENU_QUIT, ImVec2(ImGui::GetWindowContentRegionWidth(), 0))) { - ImGui::CloseCurrentPopup(); + } + + // Asked to close_and_exit + if (close_and_exit){ + if (!ImGui::IsPopupOpen("Closing")) + ImGui::OpenPopup("Closing"); + if (ImGui::BeginPopupModal("Closing", NULL, ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::Text("Please wait..."); + if (FrameGrabbing::manager().busy()) + ImGui::Text(" - Stop recordings."); + if (Settings::application.recentSessions.save_on_exit) + ImGui::Text(" - Save session."); + ImGui::EndPopup(); + } + // exit only after everything is closed + if (!FrameGrabbing::manager().busy() && !Mixer::manager().session()->locked()) { Rendering::manager().close(); } - ImGui::Spacing(); - ImGui::EndPopup(); } // navigator bar first @@ -856,10 +892,6 @@ void UserInterface::Terminate() // restore windows position for saving WorkspaceWindow::restoreWorkspace(true); - // save on exit - if (Settings::application.recentSessions.save_on_exit) - Mixer::manager().save(false); - // Cleanup ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); diff --git a/UserInterfaceManager.h b/UserInterfaceManager.h index 128d5c9..d482737 100644 --- a/UserInterfaceManager.h +++ b/UserInterfaceManager.h @@ -405,6 +405,7 @@ protected: int target_view_navigator; unsigned int screenshot_step; bool pending_save_on_exit; + bool close_and_exit; // Dialogs DialogToolkit::OpenSessionDialog *sessionopendialog;