From 05da08d6da728e9149dc08511f9b446c19d1e107 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 8 Apr 2025 04:59:00 -0500 Subject: [PATCH] GUI: threaded command stream export, part 1 no progress bar yet --- src/gui/csPlayer.cpp | 12 +---- src/gui/gui.cpp | 110 ++++++++++++++++++++++++++++++++++++------- src/gui/gui.h | 7 ++- 3 files changed, 99 insertions(+), 30 deletions(-) diff --git a/src/gui/csPlayer.cpp b/src/gui/csPlayer.cpp index 051f73620..82127561a 100644 --- a/src/gui/csPlayer.cpp +++ b/src/gui/csPlayer.cpp @@ -207,17 +207,7 @@ void FurnaceGUI::drawCSPlayer() { ImGui::SameLine(); if (ImGui::Button(_("Burn Current Song"))) { e->killStream(); - SafeWriter* w=e->saveCommand(NULL,csExportDisablePass); - if (w!=NULL) { - if (!e->playStream(w->getFinalBuf(),w->size())) { - showError(e->getLastError()); - w->finish(); - delete w; - } else { - w->disown(); - delete w; - } - } + exportCmdStream(true,""); } if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) { ImGui::OpenPopup("CSOptions"); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 60e0b4424..a88f8c5d9 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2648,6 +2648,18 @@ void FurnaceGUI::exportAudio(String path, DivAudioExportModes mode) { displayExporting=true; } +void FurnaceGUI::exportCmdStream(bool target, String path) { + csExportPath=path; + csExportTarget=target; + csExportDone=false; + csExportThread=new std::thread([this]() { + SafeWriter* w=e->saveCommand(&csProgress,csExportDisablePass); + csExportResult=w; + csExportDone=true; + }); + displayExportingCS=true; +} + void FurnaceGUI::editStr(String* which) { editString=which; displayEditString=true; @@ -5694,24 +5706,7 @@ bool FurnaceGUI::loop() { break; } case GUI_FILE_EXPORT_CMDSTREAM: { - SafeWriter* w=e->saveCommand(NULL,csExportDisablePass); - if (w!=NULL) { - FILE* f=ps_fopen(copyOfName.c_str(),"wb"); - if (f!=NULL) { - fwrite(w->getFinalBuf(),1,w->size(),f); - fclose(f); - pushRecentSys(copyOfName.c_str()); - } else { - showError(_("could not open file!")); - } - w->finish(); - delete w; - if (!e->getWarnings().empty()) { - showWarning(e->getWarnings(),GUI_WARN_GENERIC); - } - } else { - showError(fmt::sprintf(_("could not write command stream! (%s)"),e->getLastError())); - } + exportCmdStream(false,copyOfName); break; } case GUI_FILE_LOAD_MAIN_FONT: @@ -5847,6 +5842,11 @@ bool FurnaceGUI::loop() { ImGui::OpenPopup(_("ROM Export Progress")); } + if (displayExportingCS) { + displayExportingCS=false; + ImGui::OpenPopup(_("CmdStream Export Progress")); + } + if (displayNew) { newSongQuery=""; newSongFirstFrame=true; @@ -6045,6 +6045,74 @@ bool FurnaceGUI::loop() { ImGui::EndPopup(); } + centerNextWindow(_("CmdStream Export Progress"),canvasW,canvasH); + ImGui::SetNextWindowSizeConstraints(romExportMinSize,romExportMaxSize); + if (ImGui::BeginPopupModal(_("CmdStream Export Progress"),NULL)) { + if (csExportThread==NULL) { + ImGui::TextWrapped("%s",_("it appears your Furnace has too many bugs in it. any song you can export?")); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (ImGui::Button(_("Talk With Devs"),ImVec2(ImGui::GetContentRegionAvail().x/3.0f,0.0f))) { + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button(_("Ask on Bug Report"),ImVec2(ImGui::GetContentRegionAvail().x/3.0f,0.0f))) { + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button(_("View Issues"),ImVec2(ImGui::GetContentRegionAvail().x/3.0f,0.0f))) { + ImGui::CloseCurrentPopup(); + } + } else { + WAKE_UP; + ImGui::Text("Exporting..."); + + // check whether we're done + if (csExportDone) { + csExportThread->join(); + delete csExportThread; + csExportThread=NULL; + + if (csExportTarget) { // command stream player + if (csExportResult!=NULL) { + if (!e->playStream(csExportResult->getFinalBuf(),csExportResult->size())) { + showError(e->getLastError()); + csExportResult->finish(); + delete csExportResult; + } else { + csExportResult->disown(); + delete csExportResult; + } + } else { + showError(_("oh no! it broke!")); + } + csExportResult=NULL; + } else { // command stream export + if (csExportResult!=NULL) { + FILE* f=ps_fopen(csExportPath.c_str(),"wb"); + if (f!=NULL) { + fwrite(csExportResult->getFinalBuf(),1,csExportResult->size(),f); + fclose(f); + pushRecentSys(csExportPath.c_str()); + } else { + showError(_("could not open file!")); + } + csExportResult->finish(); + delete csExportResult; + if (!e->getWarnings().empty()) { + showWarning(e->getWarnings(),GUI_WARN_GENERIC); + } + } else { + showError(fmt::sprintf(_("could not write command stream! (%s)"),e->getLastError())); + } + csExportResult=NULL; + } + + ImGui::CloseCurrentPopup(); + } + } + ImGui::EndPopup(); + } + drawTutorial(); ImVec2 newSongMinSize=mobileUI?ImVec2(canvasW-(portrait?0:(60.0*dpiScale)),canvasH-60.0*dpiScale):ImVec2(400.0f*dpiScale,200.0f*dpiScale); @@ -8382,6 +8450,7 @@ FurnaceGUI::FurnaceGUI(): displayPendingSamples(false), replacePendingSample(false), displayExportingROM(false), + displayExportingCS(false), changeCoarse(false), mobileEdit(false), killGraphics(false), @@ -8875,6 +8944,11 @@ FurnaceGUI::FurnaceGUI(): introStopped(false), curTutorial(-1), curTutorialStep(0), + csDisAsmAddr(0), + csExportThread(NULL), + csExportResult(NULL), + csExportTarget(false), + csExportDone(false), dmfExportVersion(0), curExportType(GUI_EXPORT_NONE), csExportDisablePass(0), diff --git a/src/gui/gui.h b/src/gui/gui.h index a41ba0b80..0157be9b9 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1676,7 +1676,7 @@ class FurnaceGUI { bool wantScrollListIns, wantScrollListWave, wantScrollListSample; bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString; bool displayPendingSamples, replacePendingSample; - bool displayExportingROM; + bool displayExportingROM, displayExportingCS; bool changeCoarse; bool mobileEdit; bool killGraphics; @@ -2756,6 +2756,10 @@ class FurnaceGUI { ImGuiListClipper csClipper; unsigned int csDisAsmAddr; std::vector csDisAsm; + std::thread* csExportThread; + SafeWriter* csExportResult; + bool csExportTarget, csExportDone; + String csExportPath; // export options DivAudioExportOptions audioExportOptions; @@ -3053,6 +3057,7 @@ class FurnaceGUI { void pushRecentFile(String path); void pushRecentSys(const char* path); void exportAudio(String path, DivAudioExportModes mode); + void exportCmdStream(bool target, String path); void delFirstBackup(String name); bool parseSysEx(unsigned char* data, size_t len);