GUI: add replace for wave/sample and prepare for

raw sample import
This commit is contained in:
tildearrow 2022-08-13 04:17:32 -05:00
parent 4707eb7002
commit ce2d322e47
8 changed files with 242 additions and 63 deletions

View file

@ -2196,7 +2196,10 @@ void DivEngine::delInstrument(int index) {
} }
int DivEngine::addWave() { int DivEngine::addWave() {
if (song.wave.size()>=256) return -1; if (song.wave.size()>=256) {
lastError="too many wavetables!";
return -1;
}
BUSY_BEGIN; BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
DivWavetable* wave=new DivWavetable; DivWavetable* wave=new DivWavetable;
@ -2208,50 +2211,62 @@ int DivEngine::addWave() {
return waveCount; return waveCount;
} }
bool DivEngine::addWaveFromFile(const char* path, bool addRaw) { int DivEngine::addWavePtr(DivWavetable* which) {
if (song.wave.size()>=256) { if (song.wave.size()>=256) {
lastError="too many wavetables!"; lastError="too many wavetables!";
return false; delete which;
return -1;
} }
BUSY_BEGIN;
saveLock.lock();
int waveCount=(int)song.wave.size();
song.wave.push_back(which);
song.waveLen=waveCount+1;
saveLock.unlock();
BUSY_END;
return song.waveLen;
}
DivWavetable* DivEngine::waveFromFile(const char* path, bool addRaw) {
FILE* f=ps_fopen(path,"rb"); FILE* f=ps_fopen(path,"rb");
if (f==NULL) { if (f==NULL) {
lastError=fmt::sprintf("%s",strerror(errno)); lastError=fmt::sprintf("%s",strerror(errno));
return false; return NULL;
} }
unsigned char* buf; unsigned char* buf;
ssize_t len; ssize_t len;
if (fseek(f,0,SEEK_END)!=0) { if (fseek(f,0,SEEK_END)!=0) {
fclose(f); fclose(f);
lastError=fmt::sprintf("could not seek to end: %s",strerror(errno)); lastError=fmt::sprintf("could not seek to end: %s",strerror(errno));
return false; return NULL;
} }
len=ftell(f); len=ftell(f);
if (len<0) { if (len<0) {
fclose(f); fclose(f);
lastError=fmt::sprintf("could not determine file size: %s",strerror(errno)); lastError=fmt::sprintf("could not determine file size: %s",strerror(errno));
return false; return NULL;
} }
if (len==(SIZE_MAX>>1)) { if (len==(SIZE_MAX>>1)) {
fclose(f); fclose(f);
lastError="file size is invalid!"; lastError="file size is invalid!";
return false; return NULL;
} }
if (len==0) { if (len==0) {
fclose(f); fclose(f);
lastError="file is empty"; lastError="file is empty";
return false; return NULL;
} }
if (fseek(f,0,SEEK_SET)!=0) { if (fseek(f,0,SEEK_SET)!=0) {
fclose(f); fclose(f);
lastError=fmt::sprintf("could not seek to beginning: %s",strerror(errno)); lastError=fmt::sprintf("could not seek to beginning: %s",strerror(errno));
return false; return NULL;
} }
buf=new unsigned char[len]; buf=new unsigned char[len];
if (fread(buf,1,len,f)!=(size_t)len) { if (fread(buf,1,len,f)!=(size_t)len) {
logW("did not read entire wavetable file buffer!"); logW("did not read entire wavetable file buffer!");
delete[] buf; delete[] buf;
lastError=fmt::sprintf("could not read entire file: %s",strerror(errno)); lastError=fmt::sprintf("could not read entire file: %s",strerror(errno));
return false; return NULL;
} }
fclose(f); fclose(f);
@ -2279,7 +2294,7 @@ bool DivEngine::addWaveFromFile(const char* path, bool addRaw) {
lastError="invalid wavetable header/data!"; lastError="invalid wavetable header/data!";
delete wave; delete wave;
delete[] buf; delete[] buf;
return false; return NULL;
} }
} else { } else {
try { try {
@ -2320,7 +2335,7 @@ bool DivEngine::addWaveFromFile(const char* path, bool addRaw) {
} else { } else {
delete wave; delete wave;
delete[] buf; delete[] buf;
return false; return NULL;
} }
} }
} catch (EndOfFileException& e) { } catch (EndOfFileException& e) {
@ -2338,7 +2353,7 @@ bool DivEngine::addWaveFromFile(const char* path, bool addRaw) {
} else { } else {
delete wave; delete wave;
delete[] buf; delete[] buf;
return false; return NULL;
} }
} }
} }
@ -2346,17 +2361,10 @@ bool DivEngine::addWaveFromFile(const char* path, bool addRaw) {
delete wave; delete wave;
delete[] buf; delete[] buf;
lastError="premature end of file"; lastError="premature end of file";
return false; return NULL;
} }
BUSY_BEGIN; return wave;
saveLock.lock();
int waveCount=(int)song.wave.size();
song.wave.push_back(wave);
song.waveLen=waveCount+1;
saveLock.unlock();
BUSY_END;
return true;
} }
void DivEngine::delWave(int index) { void DivEngine::delWave(int index) {
@ -2372,7 +2380,10 @@ void DivEngine::delWave(int index) {
} }
int DivEngine::addSample() { int DivEngine::addSample() {
if (song.sample.size()>=256) return -1; if (song.sample.size()>=256) {
lastError="too many samples!";
return -1;
}
BUSY_BEGIN; BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
DivSample* sample=new DivSample; DivSample* sample=new DivSample;
@ -2388,11 +2399,28 @@ int DivEngine::addSample() {
return sampleCount; return sampleCount;
} }
int DivEngine::addSampleFromFile(const char* path) { int DivEngine::addSamplePtr(DivSample* which) {
if (song.sample.size()>=256) { if (song.sample.size()>=256) {
lastError="too many samples!"; lastError="too many samples!";
delete which;
return -1; return -1;
} }
int sampleCount=(int)song.sample.size();
BUSY_BEGIN;
saveLock.lock();
song.sample.push_back(which);
song.sampleLen=sampleCount+1;
saveLock.unlock();
renderSamples();
BUSY_END;
return sampleCount;
}
DivSample* DivEngine::sampleFromFile(const char* path) {
if (song.sample.size()>=256) {
lastError="too many samples!";
return NULL;
}
BUSY_BEGIN; BUSY_BEGIN;
warnings=""; warnings="";
@ -2425,7 +2453,6 @@ int DivEngine::addSampleFromFile(const char* path) {
if (extS==".dmc") { // read as .dmc if (extS==".dmc") { // read as .dmc
size_t len=0; size_t len=0;
DivSample* sample=new DivSample; DivSample* sample=new DivSample;
int sampleCount=(int)song.sample.size();
sample->name=stripPath; sample->name=stripPath;
FILE* f=ps_fopen(path,"rb"); FILE* f=ps_fopen(path,"rb");
@ -2433,7 +2460,7 @@ int DivEngine::addSampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError=fmt::sprintf("could not open file! (%s)",strerror(errno)); lastError=fmt::sprintf("could not open file! (%s)",strerror(errno));
delete sample; delete sample;
return -1; return NULL;
} }
if (fseek(f,0,SEEK_END)<0) { if (fseek(f,0,SEEK_END)<0) {
@ -2441,7 +2468,7 @@ int DivEngine::addSampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError=fmt::sprintf("could not get file length! (%s)",strerror(errno)); lastError=fmt::sprintf("could not get file length! (%s)",strerror(errno));
delete sample; delete sample;
return -1; return NULL;
} }
len=ftell(f); len=ftell(f);
@ -2451,7 +2478,7 @@ int DivEngine::addSampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError="file is empty!"; lastError="file is empty!";
delete sample; delete sample;
return -1; return NULL;
} }
if (len==(SIZE_MAX>>1)) { if (len==(SIZE_MAX>>1)) {
@ -2459,7 +2486,7 @@ int DivEngine::addSampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError="file is invalid!"; lastError="file is invalid!";
delete sample; delete sample;
return -1; return NULL;
} }
if (fseek(f,0,SEEK_SET)<0) { if (fseek(f,0,SEEK_SET)<0) {
@ -2467,7 +2494,7 @@ int DivEngine::addSampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError=fmt::sprintf("could not seek to beginning of file! (%s)",strerror(errno)); lastError=fmt::sprintf("could not seek to beginning of file! (%s)",strerror(errno));
delete sample; delete sample;
return -1; return NULL;
} }
sample->rate=33144; sample->rate=33144;
@ -2480,22 +2507,16 @@ int DivEngine::addSampleFromFile(const char* path) {
BUSY_END; BUSY_END;
lastError=fmt::sprintf("could not read file! (%s)",strerror(errno)); lastError=fmt::sprintf("could not read file! (%s)",strerror(errno));
delete sample; delete sample;
return -1; return NULL;
} }
saveLock.lock();
song.sample.push_back(sample);
song.sampleLen=sampleCount+1;
saveLock.unlock();
renderSamples();
BUSY_END; BUSY_END;
return sampleCount; return sample;
} }
} }
#ifndef HAVE_SNDFILE #ifndef HAVE_SNDFILE
lastError="Furnace was not compiled with libsndfile!"; lastError="Furnace was not compiled with libsndfile!";
return -1; return NULL;
#else #else
SF_INFO si; SF_INFO si;
SFWrapper sfWrap; SFWrapper sfWrap;
@ -2507,15 +2528,15 @@ int DivEngine::addSampleFromFile(const char* path) {
if (err==SF_ERR_SYSTEM) { if (err==SF_ERR_SYSTEM) {
lastError=fmt::sprintf("could not open file! (%s %s)",sf_error_number(err),strerror(errno)); lastError=fmt::sprintf("could not open file! (%s %s)",sf_error_number(err),strerror(errno));
} else { } else {
lastError=fmt::sprintf("could not open file! (%s)",sf_error_number(err)); lastError=fmt::sprintf("could not open file! (%s)\nif this is raw sample data, you may import it by right-clicking the Load Sample icon and selecting \"import raw\".",sf_error_number(err));
} }
return -1; return NULL;
} }
if (si.frames>16777215) { if (si.frames>16777215) {
lastError="this sample is too big! max sample size is 16777215."; lastError="this sample is too big! max sample size is 16777215.";
sfWrap.doClose(); sfWrap.doClose();
BUSY_END; BUSY_END;
return -1; return NULL;
} }
void* buf=NULL; void* buf=NULL;
sf_count_t sampleLen=sizeof(short); sf_count_t sampleLen=sizeof(short);
@ -2613,13 +2634,8 @@ int DivEngine::addSampleFromFile(const char* path) {
if (sample->centerRate<4000) sample->centerRate=4000; if (sample->centerRate<4000) sample->centerRate=4000;
if (sample->centerRate>64000) sample->centerRate=64000; if (sample->centerRate>64000) sample->centerRate=64000;
sfWrap.doClose(); sfWrap.doClose();
saveLock.lock();
song.sample.push_back(sample);
song.sampleLen=sampleCount+1;
saveLock.unlock();
renderSamples();
BUSY_END; BUSY_END;
return sampleCount; return sample;
#endif #endif
} }

View file

@ -706,8 +706,11 @@ class DivEngine {
// add wavetable // add wavetable
int addWave(); int addWave();
// add wavetable from file // add wavetable from pointer
bool addWaveFromFile(const char* path, bool loadRaw=true); int addWavePtr(DivWavetable* which);
// get wavetable from file
DivWavetable* waveFromFile(const char* path, bool loadRaw=true);
// delete wavetable // delete wavetable
void delWave(int index); void delWave(int index);
@ -715,8 +718,14 @@ class DivEngine {
// add sample // add sample
int addSample(); int addSample();
// add sample from file // add sample from pointer
int addSampleFromFile(const char* path); int addSamplePtr(DivSample* which);
// get sample from file
DivSample* sampleFromFile(const char* path);
// get raw sample
DivSample* sampleFromFileRaw(const char* path, DivSampleDepth depth, int channels, bool bigEndian);
// delete sample // delete sample
void delSample(int index); void delSample(int index);

View file

@ -420,6 +420,12 @@ void FurnaceGUI::drawWaveList() {
if (ImGui::Button(ICON_FA_FOLDER_OPEN "##WaveLoad")) { if (ImGui::Button(ICON_FA_FOLDER_OPEN "##WaveLoad")) {
doAction(GUI_ACTION_WAVE_LIST_OPEN); doAction(GUI_ACTION_WAVE_LIST_OPEN);
} }
if (ImGui::BeginPopupContextItem("WaveOpenOpt")) {
if (ImGui::MenuItem("replace...")) {
doAction((curWave>=0 && curWave<(int)e->song.wave.size())?GUI_ACTION_WAVE_LIST_OPEN_REPLACE:GUI_ACTION_WAVE_LIST_OPEN);
}
ImGui::EndPopup();
}
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button(ICON_FA_FLOPPY_O "##WaveSave")) { if (ImGui::Button(ICON_FA_FLOPPY_O "##WaveSave")) {
doAction(GUI_ACTION_WAVE_LIST_SAVE); doAction(GUI_ACTION_WAVE_LIST_SAVE);
@ -470,6 +476,19 @@ void FurnaceGUI::drawSampleList() {
if (ImGui::Button(ICON_FA_FOLDER_OPEN "##SampleLoad")) { if (ImGui::Button(ICON_FA_FOLDER_OPEN "##SampleLoad")) {
doAction(GUI_ACTION_SAMPLE_LIST_OPEN); doAction(GUI_ACTION_SAMPLE_LIST_OPEN);
} }
if (ImGui::BeginPopupContextItem("SampleOpenOpt")) {
if (ImGui::MenuItem("replace...")) {
doAction((curSample>=0 && curSample<(int)e->song.sample.size())?GUI_ACTION_SAMPLE_LIST_OPEN_REPLACE:GUI_ACTION_SAMPLE_LIST_OPEN);
}
ImGui::Separator();
if (ImGui::MenuItem("import raw...")) {
doAction(GUI_ACTION_SAMPLE_LIST_OPEN_RAW);
}
if (ImGui::MenuItem("import raw (replace)...")) {
doAction((curSample>=0 && curSample<(int)e->song.sample.size())?GUI_ACTION_SAMPLE_LIST_OPEN_REPLACE_RAW:GUI_ACTION_SAMPLE_LIST_OPEN_RAW);
}
ImGui::EndPopup();
}
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button(ICON_FA_FLOPPY_O "##SampleSave")) { if (ImGui::Button(ICON_FA_FLOPPY_O "##SampleSave")) {
doAction(GUI_ACTION_SAMPLE_LIST_SAVE); doAction(GUI_ACTION_SAMPLE_LIST_SAVE);

View file

@ -648,6 +648,9 @@ void FurnaceGUI::doAction(int what) {
case GUI_ACTION_WAVE_LIST_OPEN: case GUI_ACTION_WAVE_LIST_OPEN:
openFileDialog(GUI_FILE_WAVE_OPEN); openFileDialog(GUI_FILE_WAVE_OPEN);
break; break;
case GUI_ACTION_WAVE_LIST_OPEN_REPLACE:
openFileDialog(GUI_FILE_WAVE_OPEN_REPLACE);
break;
case GUI_ACTION_WAVE_LIST_SAVE: case GUI_ACTION_WAVE_LIST_SAVE:
if (curWave>=0 && curWave<(int)e->song.wave.size()) openFileDialog(GUI_FILE_WAVE_SAVE); if (curWave>=0 && curWave<(int)e->song.wave.size()) openFileDialog(GUI_FILE_WAVE_SAVE);
break; break;
@ -728,6 +731,15 @@ void FurnaceGUI::doAction(int what) {
case GUI_ACTION_SAMPLE_LIST_OPEN: case GUI_ACTION_SAMPLE_LIST_OPEN:
openFileDialog(GUI_FILE_SAMPLE_OPEN); openFileDialog(GUI_FILE_SAMPLE_OPEN);
break; break;
case GUI_ACTION_SAMPLE_LIST_OPEN_REPLACE:
openFileDialog(GUI_FILE_SAMPLE_OPEN_REPLACE);
break;
case GUI_ACTION_SAMPLE_LIST_OPEN_RAW:
openFileDialog(GUI_FILE_SAMPLE_OPEN_RAW);
break;
case GUI_ACTION_SAMPLE_LIST_OPEN_REPLACE_RAW:
openFileDialog(GUI_FILE_SAMPLE_OPEN_REPLACE_RAW);
break;
case GUI_ACTION_SAMPLE_LIST_SAVE: case GUI_ACTION_SAMPLE_LIST_SAVE:
if (curSample>=0 && curSample<(int)e->song.sample.size()) openFileDialog(GUI_FILE_SAMPLE_SAVE); if (curSample>=0 && curSample<(int)e->song.sample.size()) openFileDialog(GUI_FILE_SAMPLE_SAVE);
break; break;

View file

@ -1320,6 +1320,7 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
); );
break; break;
case GUI_FILE_WAVE_OPEN: case GUI_FILE_WAVE_OPEN:
case GUI_FILE_WAVE_OPEN_REPLACE:
if (!dirExists(workingDirWave)) workingDirWave=getHomeDir(); if (!dirExists(workingDirWave)) workingDirWave=getHomeDir();
hasOpened=fileDialog->openLoad( hasOpened=fileDialog->openLoad(
"Load Wavetable", "Load Wavetable",
@ -1341,6 +1342,7 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
); );
break; break;
case GUI_FILE_SAMPLE_OPEN: case GUI_FILE_SAMPLE_OPEN:
case GUI_FILE_SAMPLE_OPEN_REPLACE:
if (!dirExists(workingDirSample)) workingDirSample=getHomeDir(); if (!dirExists(workingDirSample)) workingDirSample=getHomeDir();
hasOpened=fileDialog->openLoad( hasOpened=fileDialog->openLoad(
"Load Sample", "Load Sample",
@ -1351,6 +1353,17 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) {
dpiScale dpiScale
); );
break; break;
case GUI_FILE_SAMPLE_OPEN_RAW:
case GUI_FILE_SAMPLE_OPEN_REPLACE_RAW:
if (!dirExists(workingDirSample)) workingDirSample=getHomeDir();
hasOpened=fileDialog->openLoad(
"Load Raw Sample",
{"all files", ".*"},
".*",
workingDirSample,
dpiScale
);
break;
case GUI_FILE_SAMPLE_SAVE: case GUI_FILE_SAMPLE_SAVE:
if (!dirExists(workingDirSample)) workingDirSample=getHomeDir(); if (!dirExists(workingDirSample)) workingDirSample=getHomeDir();
hasOpened=fileDialog->openSave( hasOpened=fileDialog->openSave(
@ -2630,6 +2643,8 @@ bool FurnaceGUI::loop() {
case SDL_DROPFILE: case SDL_DROPFILE:
if (ev.drop.file!=NULL) { if (ev.drop.file!=NULL) {
std::vector<DivInstrument*> instruments=e->instrumentFromFile(ev.drop.file); std::vector<DivInstrument*> instruments=e->instrumentFromFile(ev.drop.file);
DivWavetable* droppedWave=NULL;
DivSample* droppedSample=NULL;;
if (!instruments.empty()) { if (!instruments.empty()) {
if (!e->getWarnings().empty()) { if (!e->getWarnings().empty()) {
showWarning(e->getWarnings(),GUI_WARN_GENERIC); showWarning(e->getWarnings(),GUI_WARN_GENERIC);
@ -2639,10 +2654,12 @@ bool FurnaceGUI::loop() {
} }
nextWindow=GUI_WINDOW_INS_LIST; nextWindow=GUI_WINDOW_INS_LIST;
MARK_MODIFIED; MARK_MODIFIED;
} else if (e->addWaveFromFile(ev.drop.file,false)) { } else if ((droppedWave=e->waveFromFile(ev.drop.file,false))!=NULL) {
e->addWavePtr(droppedWave);
nextWindow=GUI_WINDOW_WAVE_LIST; nextWindow=GUI_WINDOW_WAVE_LIST;
MARK_MODIFIED; MARK_MODIFIED;
} else if (e->addSampleFromFile(ev.drop.file)!=-1) { } else if ((droppedSample=e->sampleFromFile(ev.drop.file))!=NULL) {
e->addSamplePtr(droppedSample);
nextWindow=GUI_WINDOW_SAMPLE_LIST; nextWindow=GUI_WINDOW_SAMPLE_LIST;
MARK_MODIFIED; MARK_MODIFIED;
} else if (modified) { } else if (modified) {
@ -3269,10 +3286,14 @@ bool FurnaceGUI::loop() {
workingDirIns=fileDialog->getPath()+DIR_SEPARATOR_STR; workingDirIns=fileDialog->getPath()+DIR_SEPARATOR_STR;
break; break;
case GUI_FILE_WAVE_OPEN: case GUI_FILE_WAVE_OPEN:
case GUI_FILE_WAVE_OPEN_REPLACE:
case GUI_FILE_WAVE_SAVE: case GUI_FILE_WAVE_SAVE:
workingDirWave=fileDialog->getPath()+DIR_SEPARATOR_STR; workingDirWave=fileDialog->getPath()+DIR_SEPARATOR_STR;
break; break;
case GUI_FILE_SAMPLE_OPEN: case GUI_FILE_SAMPLE_OPEN:
case GUI_FILE_SAMPLE_OPEN_RAW:
case GUI_FILE_SAMPLE_OPEN_REPLACE:
case GUI_FILE_SAMPLE_OPEN_REPLACE_RAW:
case GUI_FILE_SAMPLE_SAVE: case GUI_FILE_SAMPLE_SAVE:
workingDirSample=fileDialog->getPath()+DIR_SEPARATOR_STR; workingDirSample=fileDialog->getPath()+DIR_SEPARATOR_STR;
break; break;
@ -3438,13 +3459,45 @@ bool FurnaceGUI::loop() {
e->song.wave[curWave]->save(copyOfName.c_str()); e->song.wave[curWave]->save(copyOfName.c_str());
} }
break; break;
case GUI_FILE_SAMPLE_OPEN: case GUI_FILE_SAMPLE_OPEN: {
if (e->addSampleFromFile(copyOfName.c_str())==-1) { DivSample* s=e->sampleFromFile(copyOfName.c_str());
if (s==NULL) {
showError(e->getLastError()); showError(e->getLastError());
} else { } else {
MARK_MODIFIED; if (e->addSamplePtr(s)==-1) {
showError(e->getLastError());
} else {
MARK_MODIFIED;
}
} }
break; break;
}
case GUI_FILE_SAMPLE_OPEN_REPLACE: {
DivSample* s=e->sampleFromFile(copyOfName.c_str());
if (s==NULL) {
showError(e->getLastError());
} else {
if (curSample>=0 && curSample<(int)e->song.sample.size()) {
e->lockEngine([this,s]() {
// if it crashes here please tell me...
DivSample* oldSample=e->song.sample[curSample];
e->song.sample[curSample]=s;
delete oldSample;
e->renderSamples();
MARK_MODIFIED;
});
} else {
showError("...but you haven't selected a sample!");
delete s;
}
}
break;
}
case GUI_FILE_SAMPLE_OPEN_RAW:
case GUI_FILE_SAMPLE_OPEN_REPLACE_RAW:
pendingRawSample=copyOfName;
displayPendingRawSample=true;
break;
case GUI_FILE_SAMPLE_SAVE: case GUI_FILE_SAMPLE_SAVE:
if (curSample>=0 && curSample<(int)e->song.sample.size()) { if (curSample>=0 && curSample<(int)e->song.sample.size()) {
e->song.sample[curSample]->save(copyOfName.c_str()); e->song.sample[curSample]->save(copyOfName.c_str());
@ -3508,13 +3561,36 @@ bool FurnaceGUI::loop() {
} }
break; break;
} }
case GUI_FILE_WAVE_OPEN: case GUI_FILE_WAVE_OPEN: {
if (!e->addWaveFromFile(copyOfName.c_str())) { DivWavetable* wave=e->waveFromFile(copyOfName.c_str());
if (wave==NULL) {
showError("cannot load wavetable! ("+e->getLastError()+")"); showError("cannot load wavetable! ("+e->getLastError()+")");
} else { } else {
MARK_MODIFIED; if (e->addWavePtr(wave)==-1) {
showError("cannot load wavetable! ("+e->getLastError()+")");
} else {
MARK_MODIFIED;
}
} }
break; break;
}
case GUI_FILE_WAVE_OPEN_REPLACE: {
DivWavetable* wave=e->waveFromFile(copyOfName.c_str());
if (wave==NULL) {
showError("cannot load wavetable! ("+e->getLastError()+")");
} else {
if (curWave>=0 && curWave<(int)e->song.wave.size()) {
e->lockEngine([this,wave]() {
*e->song.wave[curWave]=*wave;
MARK_MODIFIED;
});
} else {
showError("...but you haven't selected a wavetable!");
}
delete wave;
}
break;
}
case GUI_FILE_EXPORT_VGM: { case GUI_FILE_EXPORT_VGM: {
SafeWriter* w=e->saveVGM(willExport,vgmExportLoop,vgmExportVersion,vgmExportPatternHints); SafeWriter* w=e->saveVGM(willExport,vgmExportLoop,vgmExportVersion,vgmExportPatternHints);
if (w!=NULL) { if (w!=NULL) {
@ -3641,6 +3717,11 @@ bool FurnaceGUI::loop() {
ImGui::OpenPopup("Select Instrument"); ImGui::OpenPopup("Select Instrument");
} }
if (displayPendingRawSample) {
displayPendingRawSample=false;
ImGui::OpenPopup("Import Raw Sample");
}
if (displayExporting) { if (displayExporting) {
displayExporting=false; displayExporting=false;
ImGui::OpenPopup("Rendering..."); ImGui::OpenPopup("Rendering...");
@ -4071,6 +4152,34 @@ bool FurnaceGUI::loop() {
ImGui::EndPopup(); ImGui::EndPopup();
} }
bool doRespond=false;
if (ImGui::BeginPopupModal("Import Raw Sample",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("Work In Progress - sorry");
if (ImGui::Button("Oh... really?")) {
ImGui::CloseCurrentPopup();
}
ImGui::SameLine();
if (ImGui::Button("Why are you so hostile? I'm just trying to import a raw sample.")) {
doRespond=true;
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (doRespond) {
doRespond=false;
ImGui::OpenPopup("Fatal Alert");
}
if (ImGui::BeginPopupModal("Fatal Alert",NULL,ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::Text("Well, I'd rather you didn't. So, good night.");
if (ImGui::Button("Fine")) {
abort();
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
layoutTimeEnd=SDL_GetPerformanceCounter(); layoutTimeEnd=SDL_GetPerformanceCounter();
// backup trigger // backup trigger
@ -4521,6 +4630,7 @@ FurnaceGUI::FurnaceGUI():
noteInputPoly(true), noteInputPoly(true),
displayPendingIns(false), displayPendingIns(false),
pendingInsSingle(false), pendingInsSingle(false),
displayPendingRawSample(false),
vgmExportVersion(0x171), vgmExportVersion(0x171),
drawHalt(10), drawHalt(10),
macroPointSize(16), macroPointSize(16),

View file

@ -259,8 +259,12 @@ enum FurnaceGUIFileDialogs {
GUI_FILE_INS_OPEN_REPLACE, GUI_FILE_INS_OPEN_REPLACE,
GUI_FILE_INS_SAVE, GUI_FILE_INS_SAVE,
GUI_FILE_WAVE_OPEN, GUI_FILE_WAVE_OPEN,
GUI_FILE_WAVE_OPEN_REPLACE,
GUI_FILE_WAVE_SAVE, GUI_FILE_WAVE_SAVE,
GUI_FILE_SAMPLE_OPEN, GUI_FILE_SAMPLE_OPEN,
GUI_FILE_SAMPLE_OPEN_RAW,
GUI_FILE_SAMPLE_OPEN_REPLACE,
GUI_FILE_SAMPLE_OPEN_REPLACE_RAW,
GUI_FILE_SAMPLE_SAVE, GUI_FILE_SAMPLE_SAVE,
GUI_FILE_EXPORT_AUDIO_ONE, GUI_FILE_EXPORT_AUDIO_ONE,
GUI_FILE_EXPORT_AUDIO_PER_SYS, GUI_FILE_EXPORT_AUDIO_PER_SYS,
@ -451,6 +455,7 @@ enum FurnaceGUIActions {
GUI_ACTION_WAVE_LIST_ADD, GUI_ACTION_WAVE_LIST_ADD,
GUI_ACTION_WAVE_LIST_DUPLICATE, GUI_ACTION_WAVE_LIST_DUPLICATE,
GUI_ACTION_WAVE_LIST_OPEN, GUI_ACTION_WAVE_LIST_OPEN,
GUI_ACTION_WAVE_LIST_OPEN_REPLACE,
GUI_ACTION_WAVE_LIST_SAVE, GUI_ACTION_WAVE_LIST_SAVE,
GUI_ACTION_WAVE_LIST_MOVE_UP, GUI_ACTION_WAVE_LIST_MOVE_UP,
GUI_ACTION_WAVE_LIST_MOVE_DOWN, GUI_ACTION_WAVE_LIST_MOVE_DOWN,
@ -464,6 +469,9 @@ enum FurnaceGUIActions {
GUI_ACTION_SAMPLE_LIST_ADD, GUI_ACTION_SAMPLE_LIST_ADD,
GUI_ACTION_SAMPLE_LIST_DUPLICATE, GUI_ACTION_SAMPLE_LIST_DUPLICATE,
GUI_ACTION_SAMPLE_LIST_OPEN, GUI_ACTION_SAMPLE_LIST_OPEN,
GUI_ACTION_SAMPLE_LIST_OPEN_REPLACE,
GUI_ACTION_SAMPLE_LIST_OPEN_RAW,
GUI_ACTION_SAMPLE_LIST_OPEN_REPLACE_RAW,
GUI_ACTION_SAMPLE_LIST_SAVE, GUI_ACTION_SAMPLE_LIST_SAVE,
GUI_ACTION_SAMPLE_LIST_MOVE_UP, GUI_ACTION_SAMPLE_LIST_MOVE_UP,
GUI_ACTION_SAMPLE_LIST_MOVE_DOWN, GUI_ACTION_SAMPLE_LIST_MOVE_DOWN,
@ -958,13 +966,15 @@ class FurnaceGUI {
bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, vgmExportPatternHints; bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, vgmExportPatternHints;
bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu; bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu;
bool displayNew, fullScreen, preserveChanPos, wantScrollList, noteInputPoly; bool displayNew, fullScreen, preserveChanPos, wantScrollList, noteInputPoly;
bool displayPendingIns, pendingInsSingle; bool displayPendingIns, pendingInsSingle, displayPendingRawSample;
bool willExport[32]; bool willExport[32];
int vgmExportVersion; int vgmExportVersion;
int drawHalt; int drawHalt;
int macroPointSize; int macroPointSize;
int waveEditStyle; int waveEditStyle;
String pendingRawSample;
ImGuiWindowFlags globalWinFlags; ImGuiWindowFlags globalWinFlags;
FurnaceGUIFileDialogs curFileDialog; FurnaceGUIFileDialogs curFileDialog;

View file

@ -581,6 +581,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={
D("WAVE_LIST_ADD", "Add", SDLK_INSERT), D("WAVE_LIST_ADD", "Add", SDLK_INSERT),
D("WAVE_LIST_DUPLICATE", "Duplicate", FURKMOD_CMD|SDLK_d), D("WAVE_LIST_DUPLICATE", "Duplicate", FURKMOD_CMD|SDLK_d),
D("WAVE_LIST_OPEN", "Open", 0), D("WAVE_LIST_OPEN", "Open", 0),
D("WAVE_LIST_OPEN_REPLACE", "Open (replace current)", 0),
D("WAVE_LIST_SAVE", "Save", 0), D("WAVE_LIST_SAVE", "Save", 0),
D("WAVE_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP), D("WAVE_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP),
D("WAVE_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN), D("WAVE_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN),
@ -594,6 +595,9 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={
D("SAMPLE_LIST_ADD", "Add", SDLK_INSERT), D("SAMPLE_LIST_ADD", "Add", SDLK_INSERT),
D("SAMPLE_LIST_DUPLICATE", "Duplicate", FURKMOD_CMD|SDLK_d), D("SAMPLE_LIST_DUPLICATE", "Duplicate", FURKMOD_CMD|SDLK_d),
D("SAMPLE_LIST_OPEN", "Open", 0), D("SAMPLE_LIST_OPEN", "Open", 0),
D("SAMPLE_LIST_OPEN_REPLACE", "Open (replace current)", 0),
D("SAMPLE_LIST_OPEN_RAW", "Import raw data", 0),
D("SAMPLE_LIST_OPEN_REPLACE_RAW", "Import raw data (replace current)", 0),
D("SAMPLE_LIST_SAVE", "Save", 0), D("SAMPLE_LIST_SAVE", "Save", 0),
D("SAMPLE_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP), D("SAMPLE_LIST_MOVE_UP", "Move up", FURKMOD_SHIFT|SDLK_UP),
D("SAMPLE_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN), D("SAMPLE_LIST_MOVE_DOWN", "Move down", FURKMOD_SHIFT|SDLK_DOWN),

View file

@ -131,9 +131,8 @@ void FurnaceGUI::drawWaveEdit() {
if (curWave>=(int)e->song.wave.size()) curWave=e->song.wave.size()-1; if (curWave>=(int)e->song.wave.size()) curWave=e->song.wave.size()-1;
} }
ImGui::SameLine(); ImGui::SameLine();
// TODO: load replace
if (ImGui::Button(ICON_FA_FOLDER_OPEN "##WELoad")) { if (ImGui::Button(ICON_FA_FOLDER_OPEN "##WELoad")) {
doAction(GUI_ACTION_WAVE_LIST_OPEN); doAction(GUI_ACTION_WAVE_LIST_OPEN_REPLACE);
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button(ICON_FA_FLOPPY_O "##WESave")) { if (ImGui::Button(ICON_FA_FLOPPY_O "##WESave")) {