GUI: more more more work
error dialog boxes and drawOrders improvements
This commit is contained in:
parent
7f3885d2b1
commit
1cc9b9fe20
|
@ -347,6 +347,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
size_t len;
|
||||
if (slen<16) {
|
||||
logE("too small!");
|
||||
lastError="file is too small";
|
||||
delete[] f;
|
||||
return false;
|
||||
}
|
||||
|
@ -372,6 +373,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
}
|
||||
inflateEnd(&zl);
|
||||
delete[] f;
|
||||
lastError="not a .dmf song";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -385,8 +387,10 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
if (nextErr!=Z_OK && nextErr!=Z_STREAM_END) {
|
||||
if (zl.msg==NULL) {
|
||||
logE("zlib error: unknown error! %d\n",nextErr);
|
||||
lastError="unknown decompression error";
|
||||
} else {
|
||||
logE("zlib inflate: %s\n",zl.msg);
|
||||
lastError=fmt::sprintf("decompression error: %s",zl.msg);
|
||||
}
|
||||
for (InflateBlock* i: blocks) delete i;
|
||||
blocks.clear();
|
||||
|
@ -405,8 +409,10 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
if (nextErr!=Z_OK) {
|
||||
if (zl.msg==NULL) {
|
||||
logE("zlib end error: unknown error! %d\n",nextErr);
|
||||
lastError="unknown decompression finish error";
|
||||
} else {
|
||||
logE("zlib end: %s\n",zl.msg);
|
||||
lastError=fmt::sprintf("decompression finish error: %s",zl.msg);
|
||||
}
|
||||
for (InflateBlock* i: blocks) delete i;
|
||||
blocks.clear();
|
||||
|
@ -421,6 +427,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
}
|
||||
if (finalSize<1) {
|
||||
logE("compressed too small!\n");
|
||||
lastError="file too small";
|
||||
for (InflateBlock* i: blocks) delete i;
|
||||
blocks.clear();
|
||||
delete[] f;
|
||||
|
@ -442,6 +449,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
}
|
||||
if (memcmp(file,DIV_DMF_MAGIC,16)!=0) {
|
||||
logE("not a valid module!\n");
|
||||
lastError="not a .dmf song";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
|
@ -456,11 +464,18 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
|
||||
if (!reader.seek(16,SEEK_SET)) {
|
||||
logE("premature end of file!");
|
||||
lastError="incomplete file";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
ds.version=reader.readC();
|
||||
logI("module version %d (0x%.2x)\n",ds.version,ds.version);
|
||||
if (ds.version>0x18) {
|
||||
logW("this version is not supported by Furnace yet!\n");
|
||||
lastError="this version is not supported by Furnace yet";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
unsigned char sys=0;
|
||||
if (ds.version<0x09) {
|
||||
// V E R S I O N -> 3 <-
|
||||
|
@ -472,6 +487,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
}
|
||||
if (ds.system==DIV_SYSTEM_NULL) {
|
||||
logE("invalid system 0x%.2x!",sys);
|
||||
lastError="system not supported. running old version?";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
|
@ -574,6 +590,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
if (ins->mode) { // FM
|
||||
if (!isFMSystem(ds.system)) {
|
||||
logE("FM instrument in non-FM system. oopsie?\n");
|
||||
lastError="FM instrument in non-FM system";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
|
@ -595,6 +612,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
}
|
||||
if (ins->fm.ops!=2 && ins->fm.ops!=4) {
|
||||
logE("invalid op count %d. did we read it wrong?\n",ins->fm.ops);
|
||||
lastError="file is corrupt or unreadable at operators";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
|
@ -762,6 +780,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
wave->len=(unsigned char)reader.readI();
|
||||
if (wave->len>32) {
|
||||
logE("invalid wave length %d. are we doing something wrong?\n",wave->len);
|
||||
lastError="file is corrupt or unreadable at wavetables";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
|
@ -788,6 +807,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
logD("%d fx rows: %d\n",i,chan.effectRows);
|
||||
if (chan.effectRows>4 || chan.effectRows<1) {
|
||||
logE("invalid effect row count %d. are you sure everything is ok?\n",chan.effectRows);
|
||||
lastError="file is corrupt or unreadable at effect rows";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
|
@ -842,6 +862,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
sample->length=reader.readI();
|
||||
if (sample->length<0) {
|
||||
logE("invalid sample length %d. are we doing something wrong?\n",sample->length);
|
||||
lastError="file is corrupt or unreadable at samples";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
|
@ -897,6 +918,7 @@ bool DivEngine::load(unsigned char* f, size_t slen) {
|
|||
}
|
||||
} catch (EndOfFileException e) {
|
||||
logE("premature end of file!\n");
|
||||
lastError="incomplete file";
|
||||
delete[] file;
|
||||
return false;
|
||||
}
|
||||
|
@ -1373,6 +1395,10 @@ void DivEngine::changeSystem(DivSystem which) {
|
|||
isBusy.unlock();
|
||||
}
|
||||
|
||||
String DivEngine::getLastError() {
|
||||
return lastError;
|
||||
}
|
||||
|
||||
DivInstrument* DivEngine::getIns(int index) {
|
||||
if (index<0 || index>=song.insLen) return &song.nullIns;
|
||||
return song.ins[index];
|
||||
|
|
|
@ -89,6 +89,7 @@ class DivEngine {
|
|||
std::mutex isBusy;
|
||||
String configPath;
|
||||
String configFile;
|
||||
String lastError;
|
||||
|
||||
short vibTable[64];
|
||||
|
||||
|
@ -260,6 +261,9 @@ class DivEngine {
|
|||
// change system
|
||||
void changeSystem(DivSystem which);
|
||||
|
||||
// get last error
|
||||
String getLastError();
|
||||
|
||||
// init dispatch
|
||||
void initDispatch();
|
||||
|
||||
|
|
|
@ -355,9 +355,18 @@ void FurnaceGUI::drawOrders() {
|
|||
char selID[16];
|
||||
if (!ordersOpen) return;
|
||||
if (ImGui::Begin("Orders",&ordersOpen)) {
|
||||
float regionX=ImGui::GetContentRegionAvail().x;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(1.0f*dpiScale,1.0f*dpiScale));
|
||||
ImGui::Columns(2,NULL,false);
|
||||
ImGui::SetColumnWidth(-1,regionX-16.0f*dpiScale);
|
||||
if (ImGui::BeginTable("OrdersTable",1+e->getChannelCount(e->song.system),ImGuiTableFlags_ScrollY)) {
|
||||
ImGui::PushFont(patFont);
|
||||
ImGui::TableSetupScrollFreeze(0,1);
|
||||
ImGui::TableNextRow();
|
||||
float lineHeight=(ImGui::GetTextLineHeight()+4*dpiScale);
|
||||
if (e->isPlaying()) {
|
||||
ImGui::SetScrollY((e->getOrder()+1)*lineHeight-(ImGui::GetContentRegionAvail().y/2));
|
||||
}
|
||||
ImGui::TableNextRow(0,lineHeight);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_ROW_INDEX]);
|
||||
for (int i=0; i<e->getChannelCount(e->song.system); i++) {
|
||||
|
@ -366,8 +375,8 @@ void FurnaceGUI::drawOrders() {
|
|||
}
|
||||
ImGui::PopStyleColor();
|
||||
for (int i=0; i<e->song.ordersLen; i++) {
|
||||
ImGui::TableNextRow();
|
||||
if (e->getOrder()==i) ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,0x40ffffff);
|
||||
ImGui::TableNextRow(0,lineHeight);
|
||||
if (oldOrder1==i) ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0,0x40ffffff);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_ROW_INDEX]);
|
||||
snprintf(selID,16,"%.2x##O_S%.2x",i,i);
|
||||
|
@ -394,11 +403,20 @@ void FurnaceGUI::drawOrders() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopFont();
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
ImGui::Button("N");
|
||||
ImGui::Button("R");
|
||||
ImGui::Button("C");
|
||||
ImGui::Button("U");
|
||||
ImGui::Button("D");
|
||||
ImGui::Button("d");
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
if (ImGui::IsWindowFocused()) curWindow=GUI_WINDOW_ORDERS;
|
||||
oldOrder1=e->getOrder();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
@ -920,7 +938,8 @@ void FurnaceGUI::drawPattern() {
|
|||
ImGui::SetWindowSize(ImVec2(scrW*dpiScale,scrH*dpiScale));
|
||||
char id[32];
|
||||
ImGui::PushFont(patFont);
|
||||
unsigned char ord=e->getOrder();
|
||||
unsigned char ord=e->isPlaying()?oldOrder:e->getOrder();
|
||||
oldOrder=e->getOrder();
|
||||
int chans=e->getChannelCount(e->song.system);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding,ImVec2(0.0f,0.0f));
|
||||
if (ImGui::BeginTable("PatternView",chans+2,ImGuiTableFlags_BordersInnerV|ImGuiTableFlags_ScrollX|ImGuiTableFlags_ScrollY|ImGuiTableFlags_NoPadInnerX)) {
|
||||
|
@ -939,13 +958,13 @@ void FurnaceGUI::drawPattern() {
|
|||
}
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Selectable(extraChannelButtons?" --##ExtraChannelButtons":" ++##ExtraChannelButtons",false,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+2.0f*dpiScale))) {
|
||||
if (ImGui::Selectable(extraChannelButtons?" --##ExtraChannelButtons":" ++##ExtraChannelButtons",false,ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) {
|
||||
extraChannelButtons=!extraChannelButtons;
|
||||
}
|
||||
for (int i=0; i<chans; i++) {
|
||||
ImGui::TableNextColumn();
|
||||
snprintf(chanID,256," %s##_CH%d",e->getChannelName(i),i);
|
||||
if (ImGui::Selectable(chanID,!e->isChannelMuted(i),ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+2.0f*dpiScale))) {
|
||||
if (ImGui::Selectable(chanID,!e->isChannelMuted(i),ImGuiSelectableFlags_NoPadWithHalfSpacing,ImVec2(0.0f,lineHeight+1.0f*dpiScale))) {
|
||||
e->toggleMute(i);
|
||||
}
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
|
||||
|
@ -968,6 +987,7 @@ void FurnaceGUI::drawPattern() {
|
|||
if (e->song.pat[i].effectRows>4) e->song.pat[i].effectRows=4;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::Spacing();
|
||||
}
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
|
@ -1746,6 +1766,7 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
|
|||
int FurnaceGUI::save(String path) {
|
||||
FILE* outFile=fopen(path.c_str(),"wb");
|
||||
if (outFile==NULL) {
|
||||
lastError=strerror(errno);
|
||||
return 1;
|
||||
}
|
||||
SafeWriter* w=e->save();
|
||||
|
@ -1757,6 +1778,7 @@ int FurnaceGUI::save(String path) {
|
|||
ret=deflateInit(&zl,Z_DEFAULT_COMPRESSION);
|
||||
if (ret!=Z_OK) {
|
||||
logE("zlib error!\n");
|
||||
lastError="compression error";
|
||||
fclose(outFile);
|
||||
w->finish();
|
||||
return 2;
|
||||
|
@ -1768,6 +1790,7 @@ int FurnaceGUI::save(String path) {
|
|||
zl.next_out=zbuf;
|
||||
if ((ret=deflate(&zl,Z_NO_FLUSH))==Z_STREAM_ERROR) {
|
||||
logE("zlib stream error!\n");
|
||||
lastError="zlib stream error";
|
||||
deflateEnd(&zl);
|
||||
fclose(outFile);
|
||||
w->finish();
|
||||
|
@ -1777,6 +1800,7 @@ int FurnaceGUI::save(String path) {
|
|||
if (amount>0) {
|
||||
if (fwrite(zbuf,1,amount,outFile)!=amount) {
|
||||
logE("did not write entirely: %s!\n",strerror(errno));
|
||||
lastError=strerror(errno);
|
||||
deflateEnd(&zl);
|
||||
fclose(outFile);
|
||||
w->finish();
|
||||
|
@ -1788,6 +1812,7 @@ int FurnaceGUI::save(String path) {
|
|||
zl.next_out=zbuf;
|
||||
if ((ret=deflate(&zl,Z_FINISH))==Z_STREAM_ERROR) {
|
||||
logE("zlib finish stream error!\n");
|
||||
lastError="zlib finish stream error";
|
||||
deflateEnd(&zl);
|
||||
fclose(outFile);
|
||||
w->finish();
|
||||
|
@ -1796,6 +1821,7 @@ int FurnaceGUI::save(String path) {
|
|||
if (131072-zl.avail_out>0) {
|
||||
if (fwrite(zbuf,1,131072-zl.avail_out,outFile)!=(131072-zl.avail_out)) {
|
||||
logE("did not write entirely: %s!\n",strerror(errno));
|
||||
lastError=strerror(errno);
|
||||
deflateEnd(&zl);
|
||||
fclose(outFile);
|
||||
w->finish();
|
||||
|
@ -1806,6 +1832,7 @@ int FurnaceGUI::save(String path) {
|
|||
#else
|
||||
if (fwrite(w->getFinalBuf(),1,w->size(),outFile)!=w->size()) {
|
||||
logE("did not write entirely: %s!\n",strerror(errno));
|
||||
lastError=strerror(errno);
|
||||
fclose(outFile);
|
||||
w->finish();
|
||||
return 1;
|
||||
|
@ -1822,24 +1849,29 @@ int FurnaceGUI::load(String path) {
|
|||
FILE* f=fopen(path.c_str(),"rb");
|
||||
if (f==NULL) {
|
||||
perror("error");
|
||||
lastError=strerror(errno);
|
||||
return 1;
|
||||
}
|
||||
if (fseek(f,0,SEEK_END)<0) {
|
||||
perror("size error");
|
||||
lastError=fmt::sprintf("on seek: %s",strerror(errno));
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
ssize_t len=ftell(f);
|
||||
if (len==0x7fffffffffffffff) {
|
||||
perror("could not get file length");
|
||||
lastError=fmt::sprintf("on pre tell: %s",strerror(errno));
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
if (len<1) {
|
||||
if (len==0) {
|
||||
printf("that file is empty!\n");
|
||||
lastError="file is empty";
|
||||
} else {
|
||||
perror("tell error");
|
||||
lastError=fmt::sprintf("on tell: %s",strerror(errno));
|
||||
}
|
||||
fclose(f);
|
||||
return 1;
|
||||
|
@ -1847,26 +1879,35 @@ int FurnaceGUI::load(String path) {
|
|||
unsigned char* file=new unsigned char[len];
|
||||
if (fseek(f,0,SEEK_SET)<0) {
|
||||
perror("size error");
|
||||
lastError=fmt::sprintf("on get size: %s",strerror(errno));
|
||||
fclose(f);
|
||||
delete[] file;
|
||||
return 1;
|
||||
}
|
||||
if (fread(file,1,(size_t)len,f)!=(size_t)len) {
|
||||
perror("read error");
|
||||
lastError=fmt::sprintf("on read: %s",strerror(errno));
|
||||
fclose(f);
|
||||
delete[] file;
|
||||
return 1;
|
||||
}
|
||||
fclose(f);
|
||||
if (!e->load(file,(size_t)len)) {
|
||||
lastError=e->getLastError();
|
||||
logE("could not open file!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
lastError="everything OK";
|
||||
updateWindowTitle();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FurnaceGUI::showError(String what) {
|
||||
errorString=what;
|
||||
ImGui::OpenPopup("Error");
|
||||
}
|
||||
|
||||
#define sysChangeOption(x) \
|
||||
if (ImGui::MenuItem(e->getSystemName(x),NULL,e->song.system==x)) { \
|
||||
e->changeSystem(x); \
|
||||
|
@ -2059,11 +2100,15 @@ bool FurnaceGUI::loop() {
|
|||
String copyOfName=fileName;
|
||||
switch (curFileDialog) {
|
||||
case GUI_FILE_OPEN:
|
||||
load(copyOfName);
|
||||
if (load(copyOfName)>0) {
|
||||
showError(fmt::sprintf("Error while loading file! (%s)",lastError));
|
||||
}
|
||||
break;
|
||||
case GUI_FILE_SAVE:
|
||||
printf("saving: %s\n",copyOfName.c_str());
|
||||
save(copyOfName);
|
||||
if (save(copyOfName)>0) {
|
||||
showError(fmt::sprintf("Error while saving file! (%s)",lastError));
|
||||
}
|
||||
break;
|
||||
case GUI_FILE_SAMPLE_OPEN:
|
||||
e->addSampleFromFile(copyOfName.c_str());
|
||||
|
@ -2088,6 +2133,14 @@ bool FurnaceGUI::loop() {
|
|||
|
||||
if (aboutOpen) drawAbout();
|
||||
|
||||
if (ImGui::BeginPopupModal("Error",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("%s",errorString.c_str());
|
||||
if (ImGui::Button("OK")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(sdlRend,uiColors[GUI_COLOR_BACKGROUND].x*255,
|
||||
uiColors[GUI_COLOR_BACKGROUND].y*255,
|
||||
uiColors[GUI_COLOR_BACKGROUND].z*255,
|
||||
|
@ -2207,6 +2260,8 @@ FurnaceGUI::FurnaceGUI():
|
|||
curSample(0),
|
||||
curOctave(3),
|
||||
oldRow(0),
|
||||
oldOrder(0),
|
||||
oldOrder1(0),
|
||||
editStep(1),
|
||||
editControlsOpen(true),
|
||||
ordersOpen(true),
|
||||
|
|
|
@ -68,7 +68,7 @@ class FurnaceGUI {
|
|||
SDL_Window* sdlWin;
|
||||
SDL_Renderer* sdlRend;
|
||||
|
||||
String workingDir, fileName, clipboard;
|
||||
String workingDir, fileName, clipboard, errorString, lastError;
|
||||
|
||||
bool quit, willCommit;
|
||||
|
||||
|
@ -91,7 +91,7 @@ class FurnaceGUI {
|
|||
|
||||
char finalLayoutPath[4096];
|
||||
|
||||
int curIns, curWave, curSample, curOctave, oldRow, editStep;
|
||||
int curIns, curWave, curSample, curOctave, oldRow, oldOrder, oldOrder1, editStep;
|
||||
bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen;
|
||||
bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen;
|
||||
SelectionPoint selStart, selEnd;
|
||||
|
@ -162,6 +162,8 @@ class FurnaceGUI {
|
|||
int save(String path);
|
||||
int load(String path);
|
||||
|
||||
void showError(String what);
|
||||
|
||||
public:
|
||||
const char* noteName(short note, short octave);
|
||||
bool decodeNote(const char* what, short& note, short& octave);
|
||||
|
|
Loading…
Reference in New Issue