backup management, part 1
new backup settings backup manager but purging does not work yet
This commit is contained in:
parent
4135123a30
commit
c4c8b6a3f4
|
@ -2370,7 +2370,7 @@ void FurnaceGUI::delFirstBackup(String name) {
|
||||||
return strcmp(a.c_str(),b.c_str())<0;
|
return strcmp(a.c_str(),b.c_str())<0;
|
||||||
});
|
});
|
||||||
|
|
||||||
int totalDelete=((int)listOfFiles.size())-5;
|
int totalDelete=((int)listOfFiles.size())-settings.backupMaxCopies;
|
||||||
for (int i=0; i<totalDelete; i++) {
|
for (int i=0; i<totalDelete; i++) {
|
||||||
String toDelete=backupPath+String(DIR_SEPARATOR_STR)+listOfFiles[i];
|
String toDelete=backupPath+String(DIR_SEPARATOR_STR)+listOfFiles[i];
|
||||||
deleteFile(toDelete.c_str());
|
deleteFile(toDelete.c_str());
|
||||||
|
@ -6395,7 +6395,7 @@ bool FurnaceGUI::loop() {
|
||||||
layoutTimeEnd=SDL_GetPerformanceCounter();
|
layoutTimeEnd=SDL_GetPerformanceCounter();
|
||||||
|
|
||||||
// backup trigger
|
// backup trigger
|
||||||
if (modified) {
|
if (modified && settings.backupEnable) {
|
||||||
if (backupTimer>0) {
|
if (backupTimer>0) {
|
||||||
backupTimer=(backupTimer-ImGui::GetIO().DeltaTime);
|
backupTimer=(backupTimer-ImGui::GetIO().DeltaTime);
|
||||||
if (backupTimer<=0) {
|
if (backupTimer<=0) {
|
||||||
|
@ -6405,14 +6405,14 @@ bool FurnaceGUI::loop() {
|
||||||
logV("curFileName: %s",curFileName);
|
logV("curFileName: %s",curFileName);
|
||||||
if (curFileName.find(backupPath)==0) {
|
if (curFileName.find(backupPath)==0) {
|
||||||
logD("backup file open. not saving backup.");
|
logD("backup file open. not saving backup.");
|
||||||
backupTimer=30.0;
|
backupTimer=settings.backupInterval;
|
||||||
backupLock.unlock();
|
backupLock.unlock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!dirExists(backupPath.c_str())) {
|
if (!dirExists(backupPath.c_str())) {
|
||||||
if (!makeDir(backupPath.c_str())) {
|
if (!makeDir(backupPath.c_str())) {
|
||||||
logW("could not create backup directory!");
|
logW("could not create backup directory!");
|
||||||
backupTimer=30.0;
|
backupTimer=settings.backupInterval;
|
||||||
backupLock.unlock();
|
backupLock.unlock();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -6481,7 +6481,7 @@ bool FurnaceGUI::loop() {
|
||||||
delFirstBackup(backupBaseName);
|
delFirstBackup(backupBaseName);
|
||||||
}
|
}
|
||||||
logD("backup saved.");
|
logD("backup saved.");
|
||||||
backupTimer=30.0;
|
backupTimer=settings.backupInterval;
|
||||||
backupLock.unlock();
|
backupLock.unlock();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -7094,6 +7094,29 @@ bool FurnaceGUI::init() {
|
||||||
cpuCores=SDL_GetCPUCount();
|
cpuCores=SDL_GetCPUCount();
|
||||||
if (cpuCores<1) cpuCores=1;
|
if (cpuCores<1) cpuCores=1;
|
||||||
|
|
||||||
|
time_t thisMakesNoSense=time(NULL);
|
||||||
|
struct tm curTime;
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct tm* tempTM=localtime(&thisMakesNoSense);
|
||||||
|
if (tempTM==NULL) {
|
||||||
|
memset(&curTime,0,sizeof(struct tm));
|
||||||
|
} else {
|
||||||
|
memcpy(&curTime,tempTM,sizeof(struct tm));
|
||||||
|
purgeYear=1900+curTime.tm_year-1;
|
||||||
|
purgeMonth=curTime.tm_mon+1;
|
||||||
|
purgeDay=curTime.tm_mday;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (localtime_r(&thisMakesNoSense,&curTime)==NULL) {
|
||||||
|
memset(&curTime,0,sizeof(struct tm));
|
||||||
|
} else {
|
||||||
|
purgeYear=1900+curTime.tm_year-1;
|
||||||
|
purgeMonth=curTime.tm_mon+1;
|
||||||
|
purgeDay=curTime.tm_mday;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
logI("done!");
|
logI("done!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -7587,7 +7610,9 @@ FurnaceGUI::FurnaceGUI():
|
||||||
aboutScroll(0),
|
aboutScroll(0),
|
||||||
aboutSin(0),
|
aboutSin(0),
|
||||||
aboutHue(0.0f),
|
aboutHue(0.0f),
|
||||||
backupTimer(15.0),
|
backupTimer(0.0),
|
||||||
|
totalBackupSize(0),
|
||||||
|
refreshBackups(true),
|
||||||
learning(-1),
|
learning(-1),
|
||||||
mainFont(NULL),
|
mainFont(NULL),
|
||||||
iconFont(NULL),
|
iconFont(NULL),
|
||||||
|
@ -7632,6 +7657,9 @@ FurnaceGUI::FurnaceGUI():
|
||||||
curPaletteChoice(0),
|
curPaletteChoice(0),
|
||||||
curPaletteType(0),
|
curPaletteType(0),
|
||||||
soloTimeout(0.0f),
|
soloTimeout(0.0f),
|
||||||
|
purgeYear(2021),
|
||||||
|
purgeMonth(4),
|
||||||
|
purgeDay(4),
|
||||||
patExtraButtons(false),
|
patExtraButtons(false),
|
||||||
patChannelNames(false),
|
patChannelNames(false),
|
||||||
patChannelPairs(true),
|
patChannelPairs(true),
|
||||||
|
|
|
@ -1479,6 +1479,16 @@ struct FurnaceGUIPerfMetric {
|
||||||
elapsed(0) {}
|
elapsed(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FurnaceGUIBackupEntry {
|
||||||
|
String name;
|
||||||
|
uint64_t size;
|
||||||
|
struct tm lastEntryTime;
|
||||||
|
FurnaceGUIBackupEntry():
|
||||||
|
size(0) {
|
||||||
|
memset(&lastEntryTime,0,sizeof(struct tm));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
enum FurnaceGUIBlendMode {
|
enum FurnaceGUIBlendMode {
|
||||||
GUI_BLEND_MODE_NONE=0,
|
GUI_BLEND_MODE_NONE=0,
|
||||||
GUI_BLEND_MODE_BLEND,
|
GUI_BLEND_MODE_BLEND,
|
||||||
|
@ -1659,6 +1669,12 @@ class FurnaceGUI {
|
||||||
std::mutex backupLock;
|
std::mutex backupLock;
|
||||||
String backupPath;
|
String backupPath;
|
||||||
|
|
||||||
|
std::vector<FurnaceGUIBackupEntry> backupEntries;
|
||||||
|
std::future<bool> backupEntryTask;
|
||||||
|
std::mutex backupEntryLock;
|
||||||
|
uint64_t totalBackupSize;
|
||||||
|
bool refreshBackups;
|
||||||
|
|
||||||
std::mutex midiLock;
|
std::mutex midiLock;
|
||||||
FixedQueue<TAMidiMessage,4096> midiQueue;
|
FixedQueue<TAMidiMessage,4096> midiQueue;
|
||||||
MIDIMap midiMap;
|
MIDIMap midiMap;
|
||||||
|
@ -1915,6 +1931,9 @@ class FurnaceGUI {
|
||||||
int glAlphaSize;
|
int glAlphaSize;
|
||||||
int glDepthSize;
|
int glDepthSize;
|
||||||
int glDoubleBuffer;
|
int glDoubleBuffer;
|
||||||
|
int backupEnable;
|
||||||
|
int backupInterval;
|
||||||
|
int backupMaxCopies;
|
||||||
unsigned int maxUndoSteps;
|
unsigned int maxUndoSteps;
|
||||||
float vibrationStrength;
|
float vibrationStrength;
|
||||||
int vibrationLength;
|
int vibrationLength;
|
||||||
|
@ -2164,6 +2183,9 @@ class FurnaceGUI {
|
||||||
glAlphaSize(0),
|
glAlphaSize(0),
|
||||||
glDepthSize(24),
|
glDepthSize(24),
|
||||||
glDoubleBuffer(1),
|
glDoubleBuffer(1),
|
||||||
|
backupEnable(1),
|
||||||
|
backupInterval(30),
|
||||||
|
backupMaxCopies(5),
|
||||||
maxUndoSteps(100),
|
maxUndoSteps(100),
|
||||||
vibrationStrength(0.5f),
|
vibrationStrength(0.5f),
|
||||||
vibrationLength(20),
|
vibrationLength(20),
|
||||||
|
@ -2214,6 +2236,8 @@ class FurnaceGUI {
|
||||||
int curPaletteChoice, curPaletteType;
|
int curPaletteChoice, curPaletteType;
|
||||||
float soloTimeout;
|
float soloTimeout;
|
||||||
|
|
||||||
|
int purgeYear, purgeMonth, purgeDay;
|
||||||
|
|
||||||
bool patExtraButtons, patChannelNames, patChannelPairs;
|
bool patExtraButtons, patChannelNames, patChannelPairs;
|
||||||
unsigned char patChannelHints;
|
unsigned char patChannelHints;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,14 @@
|
||||||
#include "scaling.h"
|
#include "scaling.h"
|
||||||
#include <fmt/printf.h>
|
#include <fmt/printf.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_NOTE_KEYS "5:7;6:4;7:3;8:16;10:6;11:8;12:24;13:10;16:11;17:9;18:26;19:28;20:12;21:17;22:1;23:19;24:23;25:5;26:14;27:2;28:21;29:0;30:100;31:13;32:15;34:18;35:20;36:22;38:25;39:27;43:100;46:101;47:29;48:31;53:102;"
|
#define DEFAULT_NOTE_KEYS "5:7;6:4;7:3;8:16;10:6;11:8;12:24;13:10;16:11;17:9;18:26;19:28;20:12;21:17;22:1;23:19;24:23;25:5;26:14;27:2;28:21;29:0;30:100;31:13;32:15;34:18;35:20;36:22;38:25;39:27;43:100;46:101;47:29;48:31;53:102;"
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__APPLE__) || defined(IS_MOBILE)
|
#if defined(_WIN32) || defined(__APPLE__) || defined(IS_MOBILE)
|
||||||
|
@ -4001,6 +4009,323 @@ void FurnaceGUI::drawSettings() {
|
||||||
CONFIG_SECTION("Backup") {
|
CONFIG_SECTION("Backup") {
|
||||||
// SUBSECTION SETTINGS
|
// SUBSECTION SETTINGS
|
||||||
CONFIG_SUBSECTION("Configuration");
|
CONFIG_SUBSECTION("Configuration");
|
||||||
|
|
||||||
|
bool backupEnableB=settings.backupEnable;
|
||||||
|
if (ImGui::Checkbox("Enable backup system",&backupEnableB)) {
|
||||||
|
settings.backupEnable=backupEnableB;
|
||||||
|
settingsChanged=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::InputInt("Interval (in seconds)",&settings.backupInterval)) {
|
||||||
|
if (settings.backupInterval<10) settings.backupInterval=10;
|
||||||
|
if (settings.backupInterval>86400) settings.backupInterval=86400;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::InputInt("Backups per file",&settings.backupMaxCopies)) {
|
||||||
|
if (settings.backupMaxCopies<1) settings.backupMaxCopies=1;
|
||||||
|
if (settings.backupMaxCopies>100) settings.backupMaxCopies=100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SUBSECTION SETTINGS
|
||||||
|
CONFIG_SUBSECTION("Backup Management");
|
||||||
|
bool purgeDateChanged=false;
|
||||||
|
|
||||||
|
ImGui::Text("Delete before (year/month/day):");
|
||||||
|
ImGui::SetNextItemWidth(80.0f*dpiScale);
|
||||||
|
if (ImGui::InputInt("##PYear",&purgeYear,0,0)) purgeDateChanged=true;
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetNextItemWidth(60.0f*dpiScale);
|
||||||
|
if (ImGui::InputInt("##PMonth",&purgeMonth,0,0)) purgeDateChanged=true;
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::SetNextItemWidth(60.0f*dpiScale);
|
||||||
|
if (ImGui::InputInt("##PDay",&purgeDay,0,0)) purgeDateChanged=true;
|
||||||
|
|
||||||
|
if (purgeDateChanged) {
|
||||||
|
// check month/day validity
|
||||||
|
time_t thisMakesNoSense=time(NULL);
|
||||||
|
bool tmFailed=false;
|
||||||
|
struct tm curTime;
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct tm* tempTM=localtime(&thisMakesNoSense);
|
||||||
|
if (tempTM==NULL) {
|
||||||
|
memset(&curTime,0,sizeof(struct tm));
|
||||||
|
tmFailed=true;
|
||||||
|
} else {
|
||||||
|
memcpy(&curTime,tempTM,sizeof(struct tm));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (localtime_r(&thisMakesNoSense,&curTime)==NULL) {
|
||||||
|
memset(&curTime,0,sizeof(struct tm));
|
||||||
|
tmFailed=true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// don't allow dates in the future
|
||||||
|
if (!tmFailed) {
|
||||||
|
int curYear=curTime.tm_year+1900;
|
||||||
|
int curMonth=curTime.tm_mon+1;
|
||||||
|
int curDay=curTime.tm_mday;
|
||||||
|
|
||||||
|
if (purgeYear<1) purgeYear=1;
|
||||||
|
if (purgeYear>curYear) purgeYear=curYear;
|
||||||
|
|
||||||
|
if (purgeYear==curYear) {
|
||||||
|
if (purgeMonth>curMonth) purgeMonth=curMonth;
|
||||||
|
|
||||||
|
if (purgeMonth==curMonth) {
|
||||||
|
if (purgeDay>curDay) purgeDay=curDay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// general checks
|
||||||
|
if (purgeYear<1) purgeYear=1;
|
||||||
|
if (purgeMonth<1) purgeMonth=1;
|
||||||
|
if (purgeMonth>12) purgeMonth=12;
|
||||||
|
if (purgeDay<1) purgeDay=1;
|
||||||
|
|
||||||
|
// 1752 calendar alignment
|
||||||
|
if (purgeYear==1752 && purgeMonth==9) {
|
||||||
|
if (purgeDay>2 && purgeDay<14) purgeDay=2;
|
||||||
|
}
|
||||||
|
if (purgeMonth==2) {
|
||||||
|
// leap year
|
||||||
|
if ((purgeYear&3)==0 && ((purgeYear%100)!=0 || (purgeYear%400)==0)) {
|
||||||
|
if (purgeDay>29) purgeDay=29;
|
||||||
|
} else {
|
||||||
|
if (purgeDay>28) purgeDay=28;
|
||||||
|
}
|
||||||
|
} else if (purgeMonth==1 || purgeMonth==3 || purgeMonth==5 || purgeMonth==7 || purgeMonth==8 || purgeMonth==10 || purgeMonth==12) {
|
||||||
|
if (purgeDay>31) purgeDay=31;
|
||||||
|
} else {
|
||||||
|
if (purgeDay>30) purgeDay=30;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button("Go##PDate");
|
||||||
|
|
||||||
|
ImGui::Button("Delete all");
|
||||||
|
|
||||||
|
backupEntryLock.lock();
|
||||||
|
if (totalBackupSize>=(1ULL<<50ULL)) {
|
||||||
|
ImGui::Text("%luPB used",totalBackupSize>>50);
|
||||||
|
} else if (totalBackupSize>=(1ULL<<40ULL)) {
|
||||||
|
ImGui::Text("%luTB used",totalBackupSize>>40);
|
||||||
|
} else if (totalBackupSize>=(1ULL<<30ULL)) {
|
||||||
|
ImGui::Text("%luGB used",totalBackupSize>>30);
|
||||||
|
} else if (totalBackupSize>=(1ULL<<20ULL)) {
|
||||||
|
ImGui::Text("%luMB used",totalBackupSize>>20);
|
||||||
|
} else if (totalBackupSize>=(1ULL<<10ULL)) {
|
||||||
|
ImGui::Text("%luKB used",totalBackupSize>>10);
|
||||||
|
} else {
|
||||||
|
ImGui::Text("%lu bytes used",totalBackupSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginTable("BackupList",3,ImGuiTableFlags_ScrollY|ImGuiTableFlags_Borders)) {
|
||||||
|
ImGui::TableSetupColumn("Name",ImGuiTableColumnFlags_WidthStretch,0.6f);
|
||||||
|
ImGui::TableSetupColumn("Size",ImGuiTableColumnFlags_WidthStretch,0.15f);
|
||||||
|
ImGui::TableSetupColumn("Latest",ImGuiTableColumnFlags_WidthStretch,0.25f);
|
||||||
|
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
for (FurnaceGUIBackupEntry& i: backupEntries) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(i.name.c_str());
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (i.size>=(1ULL<<50ULL)) {
|
||||||
|
ImGui::Text("%luP",i.size>>50);
|
||||||
|
} else if (i.size>=(1ULL<<40ULL)) {
|
||||||
|
ImGui::Text("%luT",i.size>>40);
|
||||||
|
} else if (i.size>=(1ULL<<30ULL)) {
|
||||||
|
ImGui::Text("%luG",i.size>>30);
|
||||||
|
} else if (i.size>=(1ULL<<20ULL)) {
|
||||||
|
ImGui::Text("%luM",i.size>>20);
|
||||||
|
} else if (i.size>=(1ULL<<10ULL)) {
|
||||||
|
ImGui::Text("%luK",i.size>>10);
|
||||||
|
} else {
|
||||||
|
ImGui::Text("%lu",i.size);
|
||||||
|
}
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%d-%02d-%02d",i.lastEntryTime.tm_year+1900,i.lastEntryTime.tm_mon+1,i.lastEntryTime.tm_mday);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
backupEntryLock.unlock();
|
||||||
|
if (refreshBackups) {
|
||||||
|
refreshBackups=false;
|
||||||
|
backupEntryTask=std::async(std::launch::async,[this]() -> bool {
|
||||||
|
backupEntryLock.lock();
|
||||||
|
backupEntries.clear();
|
||||||
|
backupEntryLock.unlock();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// I will do it later...
|
||||||
|
#else
|
||||||
|
DIR* backDir=opendir(backupPath.c_str());
|
||||||
|
if (backDir==NULL) {
|
||||||
|
logW("could not open backups dir!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
FurnaceGUIBackupEntry nextEntry;
|
||||||
|
struct stat nextStat;
|
||||||
|
struct dirent* next=readdir(backDir);
|
||||||
|
if (next==NULL) break;
|
||||||
|
if (strcmp(next->d_name,".")==0) continue;
|
||||||
|
if (strcmp(next->d_name,"..")==0) continue;
|
||||||
|
size_t len=strlen(next->d_name);
|
||||||
|
if (len<4) continue;
|
||||||
|
|
||||||
|
const char* firstHyphen=NULL;
|
||||||
|
const char* secondHyphen=NULL;
|
||||||
|
bool whichHyphen=false;
|
||||||
|
bool isDateValid=true;
|
||||||
|
// -YYYYMMDD-hhmmss.fur
|
||||||
|
if (strcmp(&next->d_name[len-4],".fur")!=0) continue;
|
||||||
|
// find two hyphens
|
||||||
|
for (const char* i=next->d_name+len; i!=next->d_name; i--) {
|
||||||
|
if ((*i)=='-') {
|
||||||
|
if (whichHyphen) {
|
||||||
|
firstHyphen=i;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
secondHyphen=i;
|
||||||
|
whichHyphen=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (firstHyphen==NULL) continue;
|
||||||
|
if (secondHyphen==NULL) continue;
|
||||||
|
|
||||||
|
// get the time
|
||||||
|
int whichChar=0;
|
||||||
|
for (const char* i=secondHyphen+1; *i; i++) {
|
||||||
|
if ((*i)<'0' || (*i)>'9') {
|
||||||
|
isDateValid=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (whichChar++) {
|
||||||
|
case 0:
|
||||||
|
nextEntry.lastEntryTime.tm_hour=((*i)-'0')*10;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
nextEntry.lastEntryTime.tm_hour+=(*i)-'0';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
nextEntry.lastEntryTime.tm_min=((*i)-'0')*10;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
nextEntry.lastEntryTime.tm_min+=(*i)-'0';
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
nextEntry.lastEntryTime.tm_sec=((*i)-'0')*10;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
nextEntry.lastEntryTime.tm_sec+=(*i)-'0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (whichChar>=6) break;
|
||||||
|
}
|
||||||
|
if (whichChar!=6) continue;
|
||||||
|
if (!isDateValid) continue;
|
||||||
|
if (nextEntry.lastEntryTime.tm_hour>23) continue;
|
||||||
|
if (nextEntry.lastEntryTime.tm_min>59) continue;
|
||||||
|
// intentional
|
||||||
|
if (nextEntry.lastEntryTime.tm_sec>60) continue;
|
||||||
|
|
||||||
|
// get the date
|
||||||
|
String theDate="";
|
||||||
|
for (const char* i=firstHyphen+1; *i; i++) {
|
||||||
|
if ((*i)=='-') break;
|
||||||
|
if ((*i)<'0' || (*i)>'9') {
|
||||||
|
isDateValid=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
theDate+=*i;
|
||||||
|
}
|
||||||
|
if (!isDateValid) continue;
|
||||||
|
if (theDate.size()<5) continue;
|
||||||
|
if (theDate.size()>14) continue;
|
||||||
|
String mmdd=theDate.substr(theDate.size()-4);
|
||||||
|
if (mmdd.size()!=4) continue;
|
||||||
|
nextEntry.lastEntryTime.tm_mon=(mmdd[0]-'0')*10+(mmdd[1]-'0')-1;
|
||||||
|
nextEntry.lastEntryTime.tm_mday=(mmdd[2]-'0')*10+(mmdd[3]-'0');
|
||||||
|
if (nextEntry.lastEntryTime.tm_mon>12) continue;
|
||||||
|
if (nextEntry.lastEntryTime.tm_mday>31) continue;
|
||||||
|
String yyyy=theDate.substr(0,theDate.size()-4);
|
||||||
|
try {
|
||||||
|
nextEntry.lastEntryTime.tm_year=std::stoi(yyyy)-1900;
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String nextPath=backupPath+DIR_SEPARATOR_STR+next->d_name;
|
||||||
|
|
||||||
|
if (stat(nextPath.c_str(),&nextStat)>=0) {
|
||||||
|
nextEntry.size=nextStat.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextEntry.name="";
|
||||||
|
for (const char* i=next->d_name; i!=firstHyphen && (*i); i++) {
|
||||||
|
nextEntry.name+=*i;
|
||||||
|
}
|
||||||
|
|
||||||
|
backupEntryLock.lock();
|
||||||
|
backupEntries.push_back(nextEntry);
|
||||||
|
totalBackupSize+=nextEntry.size;
|
||||||
|
backupEntryLock.unlock();
|
||||||
|
}
|
||||||
|
closedir(backDir);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// sort and merge
|
||||||
|
backupEntryLock.lock();
|
||||||
|
std::sort(backupEntries.begin(),backupEntries.end(),[](const FurnaceGUIBackupEntry& a, const FurnaceGUIBackupEntry& b) -> bool {
|
||||||
|
int sc=strcmp(a.name.c_str(),b.name.c_str());
|
||||||
|
if (sc==0) {
|
||||||
|
if (a.lastEntryTime.tm_year==b.lastEntryTime.tm_year) {
|
||||||
|
if (a.lastEntryTime.tm_mon==b.lastEntryTime.tm_mon) {
|
||||||
|
if (a.lastEntryTime.tm_mday==b.lastEntryTime.tm_mday) {
|
||||||
|
if (a.lastEntryTime.tm_hour==b.lastEntryTime.tm_hour) {
|
||||||
|
if (a.lastEntryTime.tm_min==b.lastEntryTime.tm_min) {
|
||||||
|
return (a.lastEntryTime.tm_sec<b.lastEntryTime.tm_sec);
|
||||||
|
} else {
|
||||||
|
return (a.lastEntryTime.tm_min<b.lastEntryTime.tm_min);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (a.lastEntryTime.tm_hour<b.lastEntryTime.tm_hour);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (a.lastEntryTime.tm_mday<b.lastEntryTime.tm_mday);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (a.lastEntryTime.tm_mon<b.lastEntryTime.tm_mon);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return (a.lastEntryTime.tm_year<b.lastEntryTime.tm_year);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sc<0;
|
||||||
|
});
|
||||||
|
for (size_t i=1; i<backupEntries.size(); i++) {
|
||||||
|
FurnaceGUIBackupEntry& prevEntry=backupEntries[i-1];
|
||||||
|
FurnaceGUIBackupEntry& thisEntry=backupEntries[i];
|
||||||
|
|
||||||
|
if (thisEntry.name==prevEntry.name) {
|
||||||
|
thisEntry.size+=prevEntry.size;
|
||||||
|
backupEntries.erase(backupEntries.begin()+i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backupEntryLock.unlock();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
END_SECTION;
|
END_SECTION;
|
||||||
}
|
}
|
||||||
if (nonLatchNibble) {
|
if (nonLatchNibble) {
|
||||||
|
@ -4203,6 +4528,10 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
|
|
||||||
settings.vibrationStrength=conf.getFloat("vibrationStrength",0.5f);
|
settings.vibrationStrength=conf.getFloat("vibrationStrength",0.5f);
|
||||||
settings.vibrationLength=conf.getInt("vibrationLength",20);
|
settings.vibrationLength=conf.getInt("vibrationLength",20);
|
||||||
|
|
||||||
|
settings.backupEnable=conf.getInt("backupEnable",1);
|
||||||
|
settings.backupInterval=conf.getInt("backupInterval",30);
|
||||||
|
settings.backupMaxCopies=conf.getInt("backupMaxCopies",5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groups&GUI_SETTINGS_AUDIO) {
|
if (groups&GUI_SETTINGS_AUDIO) {
|
||||||
|
@ -4701,6 +5030,9 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
clampSetting(settings.glAlphaSize,0,32);
|
clampSetting(settings.glAlphaSize,0,32);
|
||||||
clampSetting(settings.glDepthSize,0,128);
|
clampSetting(settings.glDepthSize,0,128);
|
||||||
clampSetting(settings.glDoubleBuffer,0,1);
|
clampSetting(settings.glDoubleBuffer,0,1);
|
||||||
|
clampSetting(settings.backupEnable,0,1);
|
||||||
|
clampSetting(settings.backupInterval,10,86400);
|
||||||
|
clampSetting(settings.backupMaxCopies,1,100);
|
||||||
|
|
||||||
if (settings.exportLoops<0.0) settings.exportLoops=0.0;
|
if (settings.exportLoops<0.0) settings.exportLoops=0.0;
|
||||||
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
|
if (settings.exportFadeOut<0.0) settings.exportFadeOut=0.0;
|
||||||
|
@ -4773,6 +5105,10 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) {
|
||||||
|
|
||||||
conf.set("vibrationStrength",settings.vibrationStrength);
|
conf.set("vibrationStrength",settings.vibrationStrength);
|
||||||
conf.set("vibrationLength",settings.vibrationLength);
|
conf.set("vibrationLength",settings.vibrationLength);
|
||||||
|
|
||||||
|
conf.set("backupEnable",settings.backupEnable);
|
||||||
|
conf.set("backupInterval",settings.backupInterval);
|
||||||
|
conf.set("backupMaxCopies",settings.backupMaxCopies);
|
||||||
}
|
}
|
||||||
|
|
||||||
// audio
|
// audio
|
||||||
|
@ -5073,6 +5409,8 @@ void FurnaceGUI::syncSettings() {
|
||||||
if (rend!=NULL) {
|
if (rend!=NULL) {
|
||||||
rend->setSwapInterval(settings.vsync);
|
rend->setSwapInterval(settings.vsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backupTimer=settings.backupInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FurnaceGUI::commitSettings() {
|
void FurnaceGUI::commitSettings() {
|
||||||
|
|
Loading…
Reference in a new issue