mirror of
https://github.com/tildearrow/furnace.git
synced 2024-10-31 18:12:40 +00:00
prepare for new backup system
This commit is contained in:
parent
72b81914b7
commit
79a317723a
4 changed files with 115 additions and 21 deletions
|
@ -21,10 +21,12 @@
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "utfutils.h"
|
#include "utfutils.h"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <shlobj.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FILE* ps_fopen(const char* path, const char* mode) {
|
FILE* ps_fopen(const char* path, const char* mode) {
|
||||||
|
@ -79,3 +81,22 @@ int fileExists(const char* path) {
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dirExists(const char* what) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
WString ws=utf8To16(what);
|
||||||
|
return (PathIsDirectoryW(ws.c_str())!=FALSE);
|
||||||
|
#else
|
||||||
|
struct stat st;
|
||||||
|
if (stat(what,&st)<0) return false;
|
||||||
|
return (st.st_mode&S_IFDIR);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool makeDir(const char* path) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return (SHCreateDirectory(NULL,utf8To16(path).c_str())!=ERROR_SUCCESS);
|
||||||
|
#else
|
||||||
|
return (mkdir(path,0755)==0);
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -26,5 +26,7 @@ bool moveFiles(const char* src, const char* dest);
|
||||||
bool deleteFile(const char* path);
|
bool deleteFile(const char* path);
|
||||||
// returns 1 if file exists, 0 if it doesn't and -1 on error.
|
// returns 1 if file exists, 0 if it doesn't and -1 on error.
|
||||||
int fileExists(const char* path);
|
int fileExists(const char* path);
|
||||||
|
bool dirExists(const char* what);
|
||||||
|
bool makeDir(const char* path);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
112
src/gui/gui.cpp
112
src/gui/gui.cpp
|
@ -50,13 +50,15 @@
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include "../utfutils.h"
|
#include "../utfutils.h"
|
||||||
#define LAYOUT_INI "\\layout.ini"
|
#define LAYOUT_INI "\\layout.ini"
|
||||||
#define BACKUP_FUR "\\backup.fur"
|
#define BACKUPS_DIR "\\backups"
|
||||||
#else
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#define LAYOUT_INI "/layout.ini"
|
#define LAYOUT_INI "/layout.ini"
|
||||||
#define BACKUP_FUR "/backup.fur"
|
#define BACKUPS_DIR "/backups"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IS_MOBILE
|
#ifdef IS_MOBILE
|
||||||
|
@ -1454,15 +1456,8 @@ void FurnaceGUI::keyUp(SDL_Event& ev) {
|
||||||
// nothing for now
|
// nothing for now
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dirExists(String what) {
|
bool dirExists(String s) {
|
||||||
#ifdef _WIN32
|
return dirExists(s.c_str());
|
||||||
WString ws=utf8To16(what.c_str());
|
|
||||||
return (PathIsDirectoryW(ws.c_str())!=FALSE);
|
|
||||||
#else
|
|
||||||
struct stat st;
|
|
||||||
if (stat(what.c_str(),&st)<0) return false;
|
|
||||||
return (st.st_mode&S_IFDIR);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
|
void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
|
||||||
|
@ -2096,7 +2091,7 @@ int FurnaceGUI::load(String path) {
|
||||||
|
|
||||||
void FurnaceGUI::pushRecentFile(String path) {
|
void FurnaceGUI::pushRecentFile(String path) {
|
||||||
if (path.empty()) return;
|
if (path.empty()) return;
|
||||||
if (path==backupPath) return;
|
if (path.find(backupPath)==0) return;
|
||||||
for (int i=0; i<(int)recentFile.size(); i++) {
|
for (int i=0; i<(int)recentFile.size(); i++) {
|
||||||
if (recentFile[i]==path) {
|
if (recentFile[i]==path) {
|
||||||
recentFile.erase(recentFile.begin()+i);
|
recentFile.erase(recentFile.begin()+i);
|
||||||
|
@ -2110,6 +2105,35 @@ void FurnaceGUI::pushRecentFile(String path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FurnaceGUI::delFirstBackup(String name) {
|
||||||
|
std::vector<String> listOfFiles;
|
||||||
|
#ifdef _WIN32
|
||||||
|
// TODO: Windows implementation
|
||||||
|
#else
|
||||||
|
DIR* backDir=opendir(backupPath.c_str());
|
||||||
|
if (backDir==NULL) {
|
||||||
|
logW("could not open backups dir!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
struct dirent* next=readdir(backDir);
|
||||||
|
if (next==NULL) break;
|
||||||
|
if (strstr(next->d_name,name.c_str())!=next->d_name) continue;
|
||||||
|
listOfFiles.push_back(String(next->d_name));
|
||||||
|
}
|
||||||
|
closedir(backDir);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::sort(listOfFiles.begin(),listOfFiles.end(),[](const String& a, const String& b) -> bool {
|
||||||
|
return strcmp(a.c_str(),b.c_str())<0;
|
||||||
|
});
|
||||||
|
|
||||||
|
logV("prior backups of %s:",name);
|
||||||
|
for (String& i: listOfFiles) {
|
||||||
|
logV("- %s",i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int FurnaceGUI::loadStream(String path) {
|
int FurnaceGUI::loadStream(String path) {
|
||||||
if (!path.empty()) {
|
if (!path.empty()) {
|
||||||
logI("loading stream...");
|
logI("loading stream...");
|
||||||
|
@ -3641,7 +3665,7 @@ bool FurnaceGUI::loop() {
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::MenuItem("save",BIND_FOR(GUI_ACTION_SAVE))) {
|
if (ImGui::MenuItem("save",BIND_FOR(GUI_ACTION_SAVE))) {
|
||||||
if (curFileName=="" || curFileName==backupPath || e->song.version>=0xff00) {
|
if (curFileName=="" || (curFileName.find(backupPath)==0) || e->song.version>=0xff00) {
|
||||||
openFileDialog(GUI_FILE_SAVE);
|
openFileDialog(GUI_FILE_SAVE);
|
||||||
} else {
|
} else {
|
||||||
if (save(curFileName,e->song.isDMF?e->song.version:0)>0) {
|
if (save(curFileName,e->song.isDMF?e->song.version:0)>0) {
|
||||||
|
@ -4909,7 +4933,7 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_WARN_QUIT:
|
case GUI_WARN_QUIT:
|
||||||
if (ImGui::Button("Yes")) {
|
if (ImGui::Button("Yes")) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
if (curFileName=="" || curFileName==backupPath || e->song.version>=0xff00) {
|
if (curFileName=="" || curFileName.find(backupPath)==0 || e->song.version>=0xff00) {
|
||||||
openFileDialog(GUI_FILE_SAVE);
|
openFileDialog(GUI_FILE_SAVE);
|
||||||
postWarnAction=GUI_WARN_QUIT;
|
postWarnAction=GUI_WARN_QUIT;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4933,7 +4957,7 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_WARN_NEW:
|
case GUI_WARN_NEW:
|
||||||
if (ImGui::Button("Yes")) {
|
if (ImGui::Button("Yes")) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
if (curFileName=="" || curFileName==backupPath || e->song.version>=0xff00) {
|
if (curFileName=="" || curFileName.find(backupPath)==0 || e->song.version>=0xff00) {
|
||||||
openFileDialog(GUI_FILE_SAVE);
|
openFileDialog(GUI_FILE_SAVE);
|
||||||
postWarnAction=GUI_WARN_NEW;
|
postWarnAction=GUI_WARN_NEW;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4957,7 +4981,7 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_WARN_OPEN:
|
case GUI_WARN_OPEN:
|
||||||
if (ImGui::Button("Yes")) {
|
if (ImGui::Button("Yes")) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
if (curFileName=="" || curFileName==backupPath || e->song.version>=0xff00) {
|
if (curFileName=="" || curFileName.find(backupPath)==0 || e->song.version>=0xff00) {
|
||||||
openFileDialog(GUI_FILE_SAVE);
|
openFileDialog(GUI_FILE_SAVE);
|
||||||
postWarnAction=GUI_WARN_OPEN;
|
postWarnAction=GUI_WARN_OPEN;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4981,7 +5005,7 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_WARN_OPEN_BACKUP:
|
case GUI_WARN_OPEN_BACKUP:
|
||||||
if (ImGui::Button("Yes")) {
|
if (ImGui::Button("Yes")) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
if (curFileName=="" || curFileName==backupPath || e->song.version>=0xff00) {
|
if (curFileName=="" || curFileName.find(backupPath)==0 || e->song.version>=0xff00) {
|
||||||
openFileDialog(GUI_FILE_SAVE);
|
openFileDialog(GUI_FILE_SAVE);
|
||||||
postWarnAction=GUI_WARN_OPEN_BACKUP;
|
postWarnAction=GUI_WARN_OPEN_BACKUP;
|
||||||
} else {
|
} else {
|
||||||
|
@ -5009,7 +5033,7 @@ bool FurnaceGUI::loop() {
|
||||||
case GUI_WARN_OPEN_DROP:
|
case GUI_WARN_OPEN_DROP:
|
||||||
if (ImGui::Button("Yes")) {
|
if (ImGui::Button("Yes")) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
if (curFileName=="" || curFileName==backupPath || e->song.version>=0xff00) {
|
if (curFileName=="" || curFileName.find(backupPath)==0 || e->song.version>=0xff00) {
|
||||||
openFileDialog(GUI_FILE_SAVE);
|
openFileDialog(GUI_FILE_SAVE);
|
||||||
postWarnAction=GUI_WARN_OPEN_DROP;
|
postWarnAction=GUI_WARN_OPEN_DROP;
|
||||||
} else {
|
} else {
|
||||||
|
@ -5421,16 +5445,59 @@ bool FurnaceGUI::loop() {
|
||||||
backupTimer=(backupTimer-ImGui::GetIO().DeltaTime);
|
backupTimer=(backupTimer-ImGui::GetIO().DeltaTime);
|
||||||
if (backupTimer<=0) {
|
if (backupTimer<=0) {
|
||||||
backupTask=std::async(std::launch::async,[this]() -> bool {
|
backupTask=std::async(std::launch::async,[this]() -> bool {
|
||||||
if (backupPath==curFileName) {
|
// TODO: remember how many backups we have made so we don't flood the directory
|
||||||
|
if (curFileName.find(backupPath)==0) {
|
||||||
logD("backup file open. not saving backup.");
|
logD("backup file open. not saving backup.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!dirExists(backupPath.c_str())) {
|
||||||
|
if (!makeDir(backupPath.c_str())) {
|
||||||
|
logW("could not create backup directory!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
logD("saving backup...");
|
logD("saving backup...");
|
||||||
SafeWriter* w=e->saveFur(true);
|
SafeWriter* w=e->saveFur(true);
|
||||||
logV("writing file...");
|
logV("writing file...");
|
||||||
|
|
||||||
if (w!=NULL) {
|
if (w!=NULL) {
|
||||||
FILE* outFile=ps_fopen(backupPath.c_str(),"wb");
|
size_t sepPos=curFileName.rfind(DIR_SEPARATOR);
|
||||||
|
String backupBaseName;
|
||||||
|
String backupFileName;
|
||||||
|
if (sepPos==String::npos) {
|
||||||
|
backupBaseName=curFileName;
|
||||||
|
} else {
|
||||||
|
backupBaseName=curFileName.substr(sepPos+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t dotPos=backupBaseName.rfind('.');
|
||||||
|
if (dotPos!=String::npos) {
|
||||||
|
backupBaseName=backupBaseName.substr(0,dotPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
backupFileName=backupBaseName;
|
||||||
|
|
||||||
|
time_t curTime=time(NULL);
|
||||||
|
struct tm curTM;
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct tm* tempTM=localtime(&curTime);
|
||||||
|
if (tempTM==NULL) {
|
||||||
|
backupFileName+="-unknownTime.fur";
|
||||||
|
} else {
|
||||||
|
curTM=*tempTM;
|
||||||
|
backupFileName+=fmt::sprintf("-%d%.2d%.2d-%.2d%.2d%.2d.fur",curTM.tm_year+1900,curTM.tm_mon+1,curTM.tm_mday,curTM.tm_hour,curTM.tm_min,curTM.tm_sec);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (localtime_r(&curTime,&curTM)==NULL) {
|
||||||
|
backupFileName+="-unknownTime.fur";
|
||||||
|
} else {
|
||||||
|
backupFileName+=fmt::sprintf("-%d%.2d%.2d-%.2d%.2d%.2d.fur",curTM.tm_year+1900,curTM.tm_mon+1,curTM.tm_mday,curTM.tm_hour,curTM.tm_min,curTM.tm_sec);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String finalPath=backupPath+String(DIR_SEPARATOR_STR)+backupFileName;
|
||||||
|
|
||||||
|
FILE* outFile=ps_fopen(finalPath.c_str(),"wb");
|
||||||
if (outFile!=NULL) {
|
if (outFile!=NULL) {
|
||||||
if (fwrite(w->getFinalBuf(),1,w->size(),outFile)!=w->size()) {
|
if (fwrite(w->getFinalBuf(),1,w->size(),outFile)!=w->size()) {
|
||||||
logW("did not write backup entirely: %s!",strerror(errno));
|
logW("did not write backup entirely: %s!",strerror(errno));
|
||||||
|
@ -5441,6 +5508,9 @@ bool FurnaceGUI::loop() {
|
||||||
logW("could not save backup: %s!",strerror(errno));
|
logW("could not save backup: %s!",strerror(errno));
|
||||||
w->finish();
|
w->finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delete previous backup if there are too many
|
||||||
|
delFirstBackup(backupBaseName);
|
||||||
}
|
}
|
||||||
logD("backup saved.");
|
logD("backup saved.");
|
||||||
backupTimer=30.0;
|
backupTimer=30.0;
|
||||||
|
@ -5857,7 +5927,7 @@ bool FurnaceGUI::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(finalLayoutPath,(e->getConfigPath()+String(LAYOUT_INI)).c_str(),4095);
|
strncpy(finalLayoutPath,(e->getConfigPath()+String(LAYOUT_INI)).c_str(),4095);
|
||||||
backupPath=e->getConfigPath()+String(BACKUP_FUR);
|
backupPath=e->getConfigPath()+String(BACKUPS_DIR);
|
||||||
prepareLayout();
|
prepareLayout();
|
||||||
|
|
||||||
ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_DockingEnable;
|
ImGui::GetIO().ConfigFlags|=ImGuiConfigFlags_DockingEnable;
|
||||||
|
|
|
@ -2079,6 +2079,7 @@ class FurnaceGUI {
|
||||||
int loadStream(String path);
|
int loadStream(String path);
|
||||||
void pushRecentFile(String path);
|
void pushRecentFile(String path);
|
||||||
void exportAudio(String path, DivAudioExportModes mode);
|
void exportAudio(String path, DivAudioExportModes mode);
|
||||||
|
void delFirstBackup(String name);
|
||||||
|
|
||||||
bool parseSysEx(unsigned char* data, size_t len);
|
bool parseSysEx(unsigned char* data, size_t len);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue