diff --git a/extprocess/CMakeLists.txt b/extprocess/CMakeLists.txt index f82655f..d47a9d6 100644 --- a/extprocess/CMakeLists.txt +++ b/extprocess/CMakeLists.txt @@ -46,7 +46,7 @@ endif() install(TARGETS ${EPROCESS_BINARY_NAME} RUNTIME DESTINATION ${bin_INSTALL_PATH_NSIS} COMPONENT "${CMAKE_PROJECT_NAME}") if(WIN32) - target_link_libraries(${EPROCESS_BINARY_NAME} PRIVATE wxWidgets::wxWidgets exiv2lib OpenSSL::Crypto) + target_link_libraries(${EPROCESS_BINARY_NAME} PRIVATE wxWidgets::wxWidgets OpenSSL::Crypto) else(WIN32) - target_link_libraries(${EPROCESS_BINARY_NAME} PRIVATE wx::base wx::core exiv2lib OpenSSL::Crypto) + target_link_libraries(${EPROCESS_BINARY_NAME} PRIVATE wx::base OpenSSL::Crypto) endif(WIN32) \ No newline at end of file diff --git a/extprocess/src/ApplicationLogic.cpp b/extprocess/src/ApplicationLogic.cpp index 3685775..75cb701 100644 --- a/extprocess/src/ApplicationLogic.cpp +++ b/extprocess/src/ApplicationLogic.cpp @@ -26,7 +26,6 @@ ApplicationLogic::ApplicationLogic(const std::string& libName, std::shared_ptrtempPath = std::filesystem::temp_directory_path().string(); #endif - std::cout << "Using tmp path: " << this->tempPath << std::endl; } ApplicationLogic::~ApplicationLogic() { @@ -141,7 +140,7 @@ void ApplicationLogic::processMessage(QM::QueueItem& item) { std::cout << "[EXTPROCESS] Processing item: " << this->currentItem->id << std::endl; if (this->currentItem->need_sha256 == true) { - this->sendStatus(QM::QueueStatus::HASHING, QM::QueueEvents::ITEM_MODEL_HASH_START); + this->sendStatus(QueueStatus::HASHING, QueueEvents::ITEM_MODEL_HASH_START); this->currentItem->hash_fullsize = std::filesystem::file_size(this->currentItem->params.model_path.c_str()); this->currentItem->generated_sha256 = sd_gui_utils::sha256_file_openssl( @@ -149,22 +148,22 @@ void ApplicationLogic::processMessage(QM::QueueItem& item) { (void*)this, ApplicationLogic::HandleHashCallback); - this->sendStatus(QM::QueueStatus::HASHING, QM::QueueEvents::ITEM_MODEL_HASH_DONE, "", EPROCESS_SLEEP_TIME); + this->sendStatus(QueueStatus::HASHING, QueueEvents::ITEM_MODEL_HASH_DONE, "", EPROCESS_SLEEP_TIME); } - this->sendStatus(QM::QueueStatus::MODEL_LOADING, QM::QueueEvents::ITEM_MODEL_LOAD_START, "", EPROCESS_SLEEP_TIME); + this->sendStatus(QueueStatus::MODEL_LOADING, QueueEvents::ITEM_MODEL_LOAD_START, "", EPROCESS_SLEEP_TIME); // on mode convert always return true, because no model loading if (this->loadSdModel() == false) { - if (this->currentItem->mode == QM::GenerationMode::TXT2IMG || this->currentItem->mode == QM::GenerationMode::IMG2IMG) { + if (this->currentItem->mode == SDMode::TXT2IMG || this->currentItem->mode == SDMode::IMG2IMG) { std::cerr << "[EXTPROCESS] Failed to load model: " << this->currentItem->params.model_path << std::endl; this->currentItem->status_message = _("Failed to load model: ") + this->currentItem->params.model_path; } - if (this->currentItem->mode == QM::GenerationMode::UPSCALE) { + if (this->currentItem->mode == SDMode::UPSCALE) { std::cerr << "[EXTPROCESS] Failed to load model: " << this->currentItem->params.esrgan_path << std::endl; this->currentItem->status_message = _("Failed to load model: ") + this->currentItem->params.esrgan_path; } - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_MODEL_FAILED); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_MODEL_FAILED); this->currentItem = nullptr; this->lastItem = nullptr; return; @@ -174,43 +173,43 @@ void ApplicationLogic::processMessage(QM::QueueItem& item) { this->currentItem->step = 0; this->currentItem->steps = 1; - this->sendStatus(QM::QueueStatus::RUNNING, QM::QueueEvents::ITEM_MODEL_LOADED, "", EPROCESS_SLEEP_TIME); + this->sendStatus(QueueStatus::RUNNING, QueueEvents::ITEM_MODEL_LOADED, "", EPROCESS_SLEEP_TIME); // handle the convert differently - if (this->currentItem->mode == QM::GenerationMode::CONVERT) { - this->sendStatus(QM::QueueStatus::RUNNING, QM::QueueEvents::ITEM_GENERATION_STARTED, "", EPROCESS_SLEEP_TIME); + if (this->currentItem->mode == SDMode::CONVERT) { + this->sendStatus(QueueStatus::RUNNING, QueueEvents::ITEM_GENERATION_STARTED, "", EPROCESS_SLEEP_TIME); bool status = this->convertFuncPtr(this->currentItem->params.model_path.c_str(), this->currentItem->params.vae_path.c_str(), this->currentItem->params.output_path.c_str(), this->currentItem->params.wtype); if (status == false) { - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED); this->currentItem = nullptr; this->lastItem = nullptr; return; } - this->sendStatus(QM::QueueStatus::DONE, QM::QueueEvents::ITEM_FINISHED, "", EPROCESS_SLEEP_TIME); + this->sendStatus(QueueStatus::DONE, QueueEvents::ITEM_FINISHED, "", EPROCESS_SLEEP_TIME); this->currentItem = nullptr; this->lastItem = nullptr; return; } - std::cout << "[EXTPROCESS] Starting item: " << this->currentItem->id << " type: " << QM::GenerationMode_str.at(this->currentItem->mode) << std::endl; + std::cout << "[EXTPROCESS] Starting item: " << this->currentItem->id << " type: " << GenerationMode_str.at(this->currentItem->mode) << std::endl; switch (this->currentItem->mode) { - case QM::GenerationMode::TXT2IMG: { + case SDMode::TXT2IMG: { std::cout << "[EXTPROCESS] Running txt2img" << std::endl; Txt2Img(); } break; - case QM::GenerationMode::IMG2IMG: { + case SDMode::IMG2IMG: { std::cout << "[EXTPROCESS] Running img2img" << std::endl; Img2img(); } break; - case QM::GenerationMode::UPSCALE: { + case SDMode::UPSCALE: { std::cout << "[EXTPROCESS] Running upscale" << std::endl; Upscale(); } break; default: { std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME)); - this->currentItem->status_message = wxString::Format(_("Unknown mode: %s"), QM::GenerationMode_str.at(this->currentItem->mode).c_str()); - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED); + this->currentItem->status_message = wxString::Format(_("Unknown mode: %s"), GenerationMode_str.at(this->currentItem->mode).c_str()); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED); std::cerr << this->currentItem->status_message << std::endl; this->lastItem = nullptr; this->currentItem = nullptr; @@ -224,7 +223,7 @@ void ApplicationLogic::processMessage(QM::QueueItem& item) { void ApplicationLogic::Txt2Img() { try { std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME * 2)); - this->sendStatus(QM::QueueStatus::RUNNING, QM::QueueEvents::ITEM_GENERATION_STARTED); + this->sendStatus(QueueStatus::RUNNING, QueueEvents::ITEM_GENERATION_STARTED); sd_image_t* control_image = NULL; sd_image_t* results; @@ -272,7 +271,7 @@ void ApplicationLogic::Txt2Img() { if (results == NULL) { std::cout << "[EXTPROCESS] txt2img failed" << std::endl; - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED); return; } @@ -290,12 +289,12 @@ void ApplicationLogic::Txt2Img() { auto finished_at = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME * 2)); this->currentItem->finished_at = finished_at; - this->sendStatus(QM::QueueStatus::DONE, QM::QueueEvents::ITEM_FINISHED); + this->sendStatus(QueueStatus::DONE, QueueEvents::ITEM_FINISHED); delete results; } catch (const std::exception& e) { std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME)); - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED); std::cerr << "Error calling txt2img: " << e.what() << std::endl; } } @@ -305,7 +304,7 @@ void ApplicationLogic::Img2img() { std::cout << "running img2img" << std::endl; try { std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME * 2)); - this->sendStatus(QM::QueueStatus::RUNNING, QM::QueueEvents::ITEM_GENERATION_STARTED); + this->sendStatus(QueueStatus::RUNNING, QueueEvents::ITEM_GENERATION_STARTED); std::cout << " sent status" << std::endl; unsigned char* input_image_buffer = NULL; @@ -329,13 +328,13 @@ void ApplicationLogic::Img2img() { } else { std::cerr << "Initial image not found: " << this->currentItem->initial_image << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME)); - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED, "Initial image not found:" + this->currentItem->initial_image); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED, "Initial image not found:" + this->currentItem->initial_image); return; } } else { std::cerr << "Missing input image" << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME)); - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED, "Missing input image"); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED, "Missing input image"); return; } if (this->currentItem->mask_image.length() > 0 && std::filesystem::exists(this->currentItem->mask_image)) { @@ -396,7 +395,7 @@ void ApplicationLogic::Img2img() { delete control_image; if (results == NULL) { - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED); return; } for (int i = 0; i < this->currentItem->params.batch_count; i++) { @@ -413,12 +412,12 @@ void ApplicationLogic::Img2img() { auto finished_at = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME * 2)); this->currentItem->finished_at = finished_at; - this->sendStatus(QM::QueueStatus::DONE, QM::QueueEvents::ITEM_FINISHED); + this->sendStatus(QueueStatus::DONE, QueueEvents::ITEM_FINISHED); delete results; } catch (const std::exception& e) { - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED); std::cerr << "Error calling img2img: " << e.what() << std::endl; } } @@ -433,18 +432,18 @@ void ApplicationLogic::Upscale() { if (input_image_buffer == NULL) { std::cerr << "Failed to load image: " << this->currentItem->initial_image << std::endl; this->currentItem->status_message = _("Failed to load image: ") + this->currentItem->initial_image; - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED); return; } sd_image_t control_image = sd_image_t{(uint32_t)w, (uint32_t)h, 3, input_image_buffer}; std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME)); - this->sendStatus(QM::QueueStatus::RUNNING, QM::QueueEvents::ITEM_GENERATION_STARTED); + this->sendStatus(QueueStatus::RUNNING, QueueEvents::ITEM_GENERATION_STARTED); results = this->upscalerFuncPtr(this->upscale_ctx, control_image, this->currentItem->upscale_factor); if (results.data == NULL) { - this->sendStatus(QM::QueueStatus::FAILED, QM::QueueEvents::ITEM_FAILED); + this->sendStatus(QueueStatus::FAILED, QueueEvents::ITEM_FAILED); stbi_image_free(input_image_buffer); return; } @@ -458,7 +457,7 @@ void ApplicationLogic::Upscale() { auto finished_at = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME * 2)); this->currentItem->finished_at = finished_at; - this->sendStatus(QM::QueueStatus::DONE, QM::QueueEvents::ITEM_FINISHED); + this->sendStatus(QueueStatus::DONE, QueueEvents::ITEM_FINISHED); stbi_image_free(input_image_buffer); } @@ -490,7 +489,7 @@ std::string ApplicationLogic::handleSdImage(sd_image_t& image) { bool ApplicationLogic::loadSdModel() { // on covert, there is no model loading into ctx, but need to clean up memory - if (this->currentItem->mode == QM::GenerationMode::CONVERT) { + if (this->currentItem->mode == SDMode::CONVERT) { // remove already loaded models if (this->sd_ctx != nullptr && this->currentItem->keep_checkpoint_in_memory == false) { std::cout << "Freeing up previous sd model" << std::endl; @@ -506,7 +505,7 @@ bool ApplicationLogic::loadSdModel() { } // hnalde upscaler model - if (this->currentItem->mode == QM::GenerationMode::UPSCALE) { + if (this->currentItem->mode == SDMode::UPSCALE) { std::cout << "Loading upscale model: " << this->currentItem->params.esrgan_path << std::endl; // free up the sd model if (this->sd_ctx != nullptr && this->currentItem->keep_checkpoint_in_memory == false) { @@ -516,7 +515,7 @@ bool ApplicationLogic::loadSdModel() { } // check if we need reload the model - if (this->lastItem != nullptr && this->lastItem->mode == QM::GenerationMode::UPSCALE) { + if (this->lastItem != nullptr && this->lastItem->mode == SDMode::UPSCALE) { std::cout << "Previous model is upscale" << std::endl; if (this->lastItem->params.esrgan_path != this->currentItem->params.esrgan_path) { std::cout << "upscaler model changed" << std::endl; @@ -535,7 +534,7 @@ bool ApplicationLogic::loadSdModel() { this->upscale_ctx = this->newUpscalerCtxPtr(this->currentItem->params.esrgan_path.c_str(), this->currentItem->params.n_threads, this->currentItem->params.wtype); return this->upscale_ctx != NULL; } - if (this->currentItem->mode == QM::GenerationMode::TXT2IMG || this->currentItem->mode == QM::GenerationMode::IMG2IMG) { + if (this->currentItem->mode == SDMode::TXT2IMG || this->currentItem->mode == SDMode::IMG2IMG) { if (this->currentItem->params.model_path == "") { std::cout << "Loading sd model: " << this->currentItem->params.diffusion_model_path << std::endl; } else { @@ -654,11 +653,11 @@ bool ApplicationLogic::loadSdModel() { bool vae_decode_only = true; switch (this->currentItem->mode) { - case QM::GenerationMode::IMG2IMG: - // case QM::GenerationMode::IMG2VID: + case SDMode::IMG2IMG: + // case SDMode::IMG2VID: vae_decode_only = false; break; - case QM::GenerationMode::TXT2IMG: + case SDMode::TXT2IMG: vae_decode_only = true; break; default: diff --git a/extprocess/src/ApplicationLogic.h b/extprocess/src/ApplicationLogic.h index 6494ec5..1d35a2b 100644 --- a/extprocess/src/ApplicationLogic.h +++ b/extprocess/src/ApplicationLogic.h @@ -21,7 +21,7 @@ class ApplicationLogic { if (item != nullptr) { item->hash_progress_size = readed; item->generated_sha256 = hash; - instance->sendStatus(QM::QueueStatus::HASHING, QM::QueueEvents::ITEM_MODEL_HASH_UPDATE); + instance->sendStatus(QueueStatus::HASHING, QueueEvents::ITEM_MODEL_HASH_UPDATE); } } @@ -48,7 +48,7 @@ class ApplicationLogic { } // instance->currentItem->stats.time_per_step[step] = time; - instance->currentItem->stats.time_per_step.emplace_back(QM::QueueStatsStepItem(step, steps, time)); + instance->currentItem->stats.time_per_step.emplace_back(QueueStatsStepItem(step, steps, time)); instance->currentItem->stats.time_total += time; if (instance->currentItem->step > 0) { @@ -56,7 +56,7 @@ class ApplicationLogic { } instance->currentItem->updated_at = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - instance->sendStatus(QM::QueueEvents::ITEM_UPDATED); + instance->sendStatus(QueueEvents::ITEM_UPDATED); } bool loadLibrary(); @@ -112,7 +112,7 @@ class ApplicationLogic { * status_message field. If a sleep time is provided, the function will * sleep for that amount of time before sending the message. */ - inline void sendStatus(QM::QueueStatus status, QM::QueueEvents event, const std::string& reason = "", unsigned int sleep = 0) { + inline void sendStatus(QueueStatus status, QueueEvents event, const std::string& reason = "", unsigned int sleep = 0) { if (this->currentItem == nullptr) { return; } @@ -135,7 +135,7 @@ class ApplicationLogic { std::string jsonString = j.dump(); this->sharedMemoryManager->write(jsonString.c_str(), jsonString.length()); } - inline void sendStatus(QM::QueueEvents event, const std::string& reason = "", unsigned int sleep = 0) { + inline void sendStatus(QueueEvents event, const std::string& reason = "", unsigned int sleep = 0) { if (this->currentItem == nullptr) { return; } diff --git a/extprocess/src/main.cpp b/extprocess/src/main.cpp index 048d363..f4cfb43 100644 --- a/extprocess/src/main.cpp +++ b/extprocess/src/main.cpp @@ -1,15 +1,20 @@ int main(int argc, char* argv[]) { - if (argc != 2) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " [shared_memory_path]" << std::endl; return 1; } + std::string shared_memory_path = SHARED_MEMORY_PATH; + + if (argv[2]) { + shared_memory_path = argv[2]; + } std::shared_ptr sharedMemory = nullptr; std::cout << "[EXTPROCESS] starting with shared memory size: " << SHARED_MEMORY_SIZE << std::endl; try { - sharedMemory = std::make_shared(SHARED_MEMORY_PATH, SHARED_MEMORY_SIZE, false); + sharedMemory = std::make_shared(shared_memory_path.c_str(), SHARED_MEMORY_SIZE, false); } catch (const std::exception& e) { std::cerr << "[EXTPROCESS] Failed to create SharedMemoryManager: " << e.what() << std::endl; return 1; diff --git a/extprocess/src/pch.h b/extprocess/src/pch.h index 3aa5417..19ef969 100644 --- a/extprocess/src/pch.h +++ b/extprocess/src/pch.h @@ -24,6 +24,9 @@ #include #include #include +#include "helpers/sd.hpp" +#include "helpers/QueueItem.h" +#include "network/RemoteQueueJobItem.h" #include "network/packets.h" #include "helpers/sd.hpp" #include "helpers/sslUtils.hpp" diff --git a/graphics/window.fbp b/graphics/window.fbp index 8fe4882..2f71c44 100644 --- a/graphics/window.fbp +++ b/graphics/window.fbp @@ -13280,6 +13280,72 @@ onGenerate + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + "local" + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 1 + wxID_ANY + + 0 + + + 0 + + 1 + m_server + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnServerSelect + + @@ -13411,11 +13477,11 @@ sizer2010 wxVERTICAL none - + 5 wxALL|wxEXPAND 1 - + 1 1 1 @@ -17615,6 +17681,657 @@ + + + Servers + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_serversPanel + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL + + + bSizer103 + wxVERTICAL + none + + 5 + wxEXPAND + 1 + + + bSizer105 + wxVERTICAL + none + + 5 + wxEXPAND + 0 + + + bSizer106 + wxHORIZONTAL + none + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Delete + + 0 + + 0 + + + 0 + + 1 + m_deleteServer + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnDeleteServer + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Enable + + 0 + + 0 + + + 0 + + 1 + m_serverEnable + 1 + + + protected + 1 + + + + Resizable + 1 + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + 0 + + + + OnServerEnableToggle + + + + + + 5 + wxALL|wxEXPAND + 1 + + + + 1 + 0 + 1 + + + 0 + wxID_ANY + + + m_serverList + protected + + + wxDV_HORIZ_RULES|wxDV_ROW_LINES|wxDV_SINGLE|wxDV_VERT_RULES + ; ; forward_declare + + + + + OnServerListEditingDone + OnServerListEditingStarted + OnServerListStartEditing + OnServerListItemValueChanged + OnServerListSelectionChanged + + wxALIGN_LEFT + + wxDATAVIEW_COL_RESIZABLE + Host + wxDATAVIEW_CELL_INERT + m_dataViewListColumn36 + protected + Text + -1 + + + wxALIGN_LEFT + + wxDATAVIEW_COL_RESIZABLE + Port + wxDATAVIEW_CELL_INERT + m_dataViewListColumn37 + protected + Text + -1 + + + wxALIGN_LEFT + wxELLIPSIZE_MIDDLE + wxDATAVIEW_COL_RESIZABLE + Auth key + wxDATAVIEW_CELL_INERT + m_dataViewListColumn38 + protected + Text + 200 + + + wxALIGN_LEFT + + wxDATAVIEW_COL_RESIZABLE + Status + wxDATAVIEW_CELL_INERT + m_dataViewListColumn39 + protected + Text + -1 + + + + + + + 5 + wxEXPAND + 0 + + + bSizer104 + wxHORIZONTAL + none + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Host: + 0 + + 0 + + + 0 + + 1 + m_staticText70 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + 180,-1 + 1 + m_AddServerHost + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + 5 + wxALL|wxALIGN_CENTER_VERTICAL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Port: + 0 + + 0 + + + 0 + + 1 + m_staticText71 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 5 + + 0 + + 1 + m_AddServerPort + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NUMERIC + wxGenericValidator + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Add server + + 0 + + 0 + + + 0 + + 1 + m_button18 + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnAddServer + + + + + + + diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 9143150..2a34fa7 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -26,12 +26,15 @@ set(bin_INSTALL_PATH_NSIS "bin") if (WIN32) set(bin_INSTALL_PATH_NSIS ".") endif() - +# to generate Dockerfile for the server +configure_file(platforms/Docker/Dockerfile.in ${PROJECT_BINARY_DIR}/Dockerfile) +configure_file(server-config-example.json ${PROJECT_BINARY_DIR}/server-config-example.json @ONLY) install(TARGETS ${SERVER_BINARY_NAME} RUNTIME DESTINATION ${bin_INSTALL_PATH_NSIS} COMPONENT "${CMAKE_PROJECT_NAME}Server") +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Dockerfile DESTINATION share/stablediffusiongui COMPONENT "${CMAKE_PROJECT_NAME}Server") if(WIN32) target_link_libraries(${SERVER_BINARY_NAME} PRIVATE wxWidgets::wxWidgets OpenSSL::Crypto) else(WIN32) - target_link_libraries(${SERVER_BINARY_NAME} PRIVATE wx::base wx::core OpenSSL::Crypto) + target_link_libraries(${SERVER_BINARY_NAME} PRIVATE wx::base OpenSSL::Crypto) endif(WIN32) \ No newline at end of file diff --git a/server/platforms/Docker/Dockerfile.in b/server/platforms/Docker/Dockerfile.in new file mode 100644 index 0000000..807b858 --- /dev/null +++ b/server/platforms/Docker/Dockerfile.in @@ -0,0 +1,73 @@ +FROM ubuntu:24.04 + +ARG BACKEND=avx + +# Build argumentumok (default értékek) +ARG BACKEND=avx +RUN apt-get update && apt-get install -y --no-install-recommends \ + libmagic1 \ + libstdc++6 \ + openssl \ + bash \ + libgomp1 + +COPY *.so /usr/lib/ + +RUN mkdir /app +RUN mkdir /app/models +RUN mkdir /app/models/checkpoints +RUN mkdir /app/models/loras +RUN mkdir /app/models/vae +RUN mkdir /app/models/embeddings +RUN mkdir /app/models/taesd +RUN mkdir /app/models/controlnet +RUN mkdir /app/models/esrgan + +RUN if [ "$BACKEND" = "cuda" ]; then \ + echo "CUDA support enabled"; \ + apt update; apt install -y --no-install-recommends libcudart12 libcublas12; \ + fi + + +RUN if [ "$BACKEND" = "vulkan" ]; then \ + echo "Vulkan support enabled"; \ + apt install -y --no-install-recommends libvulkan1; \ + fi + +# AVX/AVX2/AVX512 beállítások, ha szükséges +RUN if [ "$BACKEND" = "avx" ]; then \ + echo "AVX support enabled"; \ + fi + +RUN if [ "$BACKEND" = "avx2" ]; then \ + echo "AVX2 support enabled"; \ + fi + +RUN if [ "$BACKEND" = "avx512" ]; then \ + echo "AVX512 support enabled"; \ + fi + + +COPY server/@SERVER_BINARY_NAME@ /app/@SERVER_BINARY_NAME@ +COPY server-config-example.json /app/config.json +COPY extprocess/@PROJECT_BINARY_NAME@_diffuser /app/@PROJECT_BINARY_NAME@_diffuser + + +RUN apt-get clean && rm -rf /var/lib/apt/lists/* + +RUN sed -i "s/\"backend\": \".*\"/\"backend\": \"$BACKEND\"/" /app/config.json +# Fájl engedélyek beállítása +RUN chmod +x /app/@SERVER_BINARY_NAME@ + +# Munkakönyvtár beállítása +WORKDIR /app + +# Indítási parancs +CMD ["/app/@SERVER_BINARY_NAME@", "/app/config.json"] + + +#docker build --build-arg BACKEND=cuda -t myimage-cuda . +#docker build --build-arg BACKEND=vulkan -t myimage-vulkan . +#docker build --build-arg BACKEND=avx -t myimage-avx . +#docker build --build-arg BACKEND=avx2 -t myimage-avx2 . +#docker build --build-arg BACKEND=avx512 -t myimage-avx512 . \ No newline at end of file diff --git a/server/server-config-example.json b/server/server-config-example.json index b01d581..8d5bea3 100644 --- a/server/server-config-example.json +++ b/server/server-config-example.json @@ -2,5 +2,14 @@ "port": 8191, "host": "127.0.0.1", "logfile": "/var/log/stable-diffusion-server.log", - "backend": "avx" + "backend": "avx", + "model_path": "/app/models/checkpoints", + "lora_path": "/app/models/loras", + "vae_path": "/app/models/vae", + "embedding_path": "/app/models/embeddings", + "taesd_path": "/app/models/taesd", + "controlnet_path": "/app/models/controlnet", + "esrgan_path": "/app/models/esrgan", + "max_clients": 10, + "unauthorized_timeout": 4 } \ No newline at end of file diff --git a/server/src/EventQueue.h b/server/src/EventQueue.h new file mode 100644 index 0000000..2efdc59 --- /dev/null +++ b/server/src/EventQueue.h @@ -0,0 +1,37 @@ +#ifndef __SERVER_EVENT_QUEUE__ +#define __SERVER_EVENT_QUEUE__ +#include +#include +#include +#include + +class EventQueue { +public: + using EventHandler = std::function; + + void Push(EventHandler handler) { + std::lock_guard lock(mutex_); + events_.emplace(handler); + cond_var_.notify_one(); + } + + EventHandler Pop() { + std::unique_lock lock(mutex_); + cond_var_.wait(lock, [this] { return !events_.empty(); }); + auto event = events_.front(); + events_.pop(); + return event; + } + + bool IsEmpty() { + std::lock_guard lock(mutex_); + return events_.empty(); + } + +private: + std::queue events_; + std::mutex mutex_; + std::condition_variable cond_var_; +}; + +#endif // __SERVER_EVENT_QUEUE__ \ No newline at end of file diff --git a/server/src/ServerConfig.h b/server/src/ServerConfig.h index 8783903..590a380 100644 --- a/server/src/ServerConfig.h +++ b/server/src/ServerConfig.h @@ -40,6 +40,7 @@ struct ServerConfig { std::string logfile; backend_type backend = backend_type::AVX; std::string authkey; + std::string shared_memory_path = ""; std::string server_name = ""; // optional server name to display in the gui unsigned int unauthorized_timeout = 4; // disconnect clients after this many seconds if not authenticated std::string exprocess_binary_path; // force to use this exprocess binary @@ -50,6 +51,7 @@ struct ServerConfig { std::string taesd_path; std::string controlnet_path; std::string esrgan_path; + std::string server_id; }; inline void to_json(nlohmann ::json& nlohmann_json_j, const ServerConfig& nlohmann_json_t) { @@ -61,6 +63,10 @@ inline void to_json(nlohmann ::json& nlohmann_json_j, const ServerConfig& nlohma nlohmann_json_j["backend"] = backend_type_to_str.at(nlohmann_json_t.backend); nlohmann_json_j["authkey"] = nlohmann_json_t.authkey; nlohmann_json_j["unauthorized_timeout"] = nlohmann_json_t.unauthorized_timeout; + nlohmann_json_j["server_id"] = nlohmann_json_t.server_id; + if (nlohmann_json_t.shared_memory_path.empty() == false) { + nlohmann_json_j["shared_memory_path"] = nlohmann_json_t.shared_memory_path; + } if (nlohmann_json_t.server_name.empty() == false) { nlohmann_json_j["server_name"] = nlohmann_json_t.server_name; } @@ -96,13 +102,16 @@ inline void from_json(const nlohmann ::json& nlohmann_json_j, ServerConfig& nloh nlohmann_json_t.max_clients = nlohmann_json_j.value("max_clients", nlohmann_json_default_obj.max_clients); nlohmann_json_t.max_request_size = nlohmann_json_j.value("max_request_size", nlohmann_json_default_obj.max_request_size); nlohmann_json_t.logfile = nlohmann_json_j.value("logfile", nlohmann_json_default_obj.logfile); + nlohmann_json_t.server_id = nlohmann_json_j.value("server_id", nlohmann_json_default_obj.server_id); std::string backend = nlohmann_json_j.value("backend", "avx"); if (backend_str_to_type.find(backend) == backend_str_to_type.end()) { backend = "avx"; } - nlohmann_json_t.backend = backend_str_to_type.at(backend); - nlohmann_json_t.authkey = nlohmann_json_j.value("authkey", nlohmann_json_default_obj.authkey); + + nlohmann_json_t.shared_memory_path = nlohmann_json_j.value("shared_memory_path", nlohmann_json_default_obj.shared_memory_path); + nlohmann_json_t.backend = backend_str_to_type.at(backend); + nlohmann_json_t.authkey = nlohmann_json_j.value("authkey", nlohmann_json_default_obj.authkey); if (nlohmann_json_j.contains("server_name") && !nlohmann_json_j["server_name"].is_null()) { nlohmann_json_t.server_name = nlohmann_json_j.value("server_name", nlohmann_json_default_obj.server_name); } diff --git a/server/src/SocketApp.cpp b/server/src/SocketApp.cpp index 478a11d..6c876d1 100644 --- a/server/src/SocketApp.cpp +++ b/server/src/SocketApp.cpp @@ -160,153 +160,4 @@ void SocketApp::DisconnectClient(int idx) { this->m_clientInfo.erase(idx); } } -}#include "SocketApp.h" -#include "TerminalApp.h" -SocketApp::SocketApp(const char* listenAddr, uint16_t port, TerminalApp* parent) - : m_socketOpt({sockets::TX_BUFFER_SIZE, sockets::RX_BUFFER_SIZE, listenAddr}), m_server(*this, &m_socketOpt), parent(parent) { - sockets::SocketRet ret = m_server.start(port); - if (ret.m_success) { - this->parent->sendLogEvent("Server started on " + std::string(listenAddr) + ":" + std::to_string(port)); - } else { - this->parent->sendLogEvent("Error: " + ret.m_msg, wxLOG_Error); - this->needToRun = false; - } -} - -SocketApp::~SocketApp() { - { - std::lock_guard guard(m_mutex); - this->m_clientInfo.clear(); - } -} - -void SocketApp::sendMsg(int idx, const char* data, size_t len) { - std::lock_guard guard(m_mutex); - if (idx == 0) { - auto ret = m_server.sendBcast(data, len); - if (!ret.m_success) { - this->parent->sendLogEvent("Broadcast send Error: " + ret.m_msg, wxLOG_Error); - } - } else if (this->m_clientInfo.contains(idx)) { - auto ret = m_server.sendClientMessage(idx, data, len); - if (!ret.m_success) { - this->parent->sendLogEvent("Send Error: " + ret.m_msg, wxLOG_Error); - } - } else { - this->parent->sendLogEvent("Client " + std::to_string(idx) + " doesn't exist", wxLOG_Warning); - } -} - -void SocketApp::onReceiveClientData(const sockets::ClientHandle& client, const char* data, size_t size) { - if (this->expected_size == 0 && size >= sizeof(size_t)) { - memcpy(&this->expected_size, data, sizeof(this->expected_size)); - - size -= sizeof(this->expected_size); - data += sizeof(this->expected_size); - - if (size > 0) { - this->buffer.insert(this->buffer.end(), data, data + size); - } - this->parent->sendLogEvent("Received packet expected size: " + std::to_string(this->expected_size), wxLOG_Debug); - } else if (this->expected_size > 0) { - this->buffer.insert(this->buffer.end(), data, data + size); - } - - if (this->buffer.size() == this->expected_size && this->expected_size > 0) { - auto packet = sd_gui_utils::networks::Packet::DeSerialize(this->buffer.data(), this->buffer.size()); - packet.source_idx = client; - - this->parseMsg(packet); - - this->buffer.clear(); - this->expected_size = 0; - } } - -void SocketApp::onClientConnect(const sockets::ClientHandle& client) { - std::string ipAddr; - uint16_t port; - bool connected; - if (m_server.getClientInfo(client, ipAddr, port, connected)) { - this->parent->sendLogEvent("Client " + std::to_string(client) + " connected from " + ipAddr + ":" + std::to_string(port)); - { - std::lock_guard guard(m_mutex); - this->m_clientInfo[client] = {ipAddr, port, client, wxGetLocalTime()}; - } - sd_gui_utils::networks::Packet auth_required_packet; - auth_required_packet.type = sd_gui_utils::networks::PacketType::REQUEST; - auth_required_packet.param = sd_gui_utils::networks::PacketParam::AUTH; - this->sendMsg(client, auth_required_packet); - } -} - -void SocketApp::onClientDisconnect(const sockets::ClientHandle& client, const sockets::SocketRet& ret) { - this->parent->sendLogEvent("Client " + std::to_string(client) + " disconnected: " + ret.m_msg); - { - std::lock_guard guard(m_mutex); - m_clientInfo.erase(client); - } -} - -void SocketApp::OnTimer() { - std::lock_guard guard(m_mutex); - - auto it = this->m_clientInfo.begin(); - while (it != this->m_clientInfo.end()) { - if ((wxGetLocalTime() - it->second.connected_at) > this->parent->configData->unauthorized_timeout && it->second.apikey.empty()) { - this->parent->sendLogEvent(wxString::Format("Unauthorized client %d disconnected due to inactivity %s:%d", it->second.idx, it->second.host, it->second.port), wxLOG_Warning); - this->m_server.deleteClient(it->second.idx); - it = this->m_clientInfo.erase(it); - } else { - ++it; - } - } -} - -void SocketApp::parseMsg(sd_gui_utils::networks::Packet& packet) { - // parse from cbor to struct Packet - try { - if (packet.version != SD_GUI_VERSION) { - auto errorPacket = sd_gui_utils::networks::Packet(sd_gui_utils::networks::PacketType::RESPONSE, sd_gui_utils::networks::PacketParam::ERROR); - errorPacket.SetData("Version Mismatch, server: " + std::string(SD_GUI_VERSION) + ", client: " + packet.version); - this->sendMsg(packet.source_idx, errorPacket); - this->parent->sendLogEvent(wxString::Format("Version Mismatch, server: %s, client: %s", SD_GUI_VERSION, packet.version), wxLOG_Error); - this->DisconnectClient(packet.source_idx); - return; - } - if (packet.type == sd_gui_utils::networks::PacketType::REQUEST) { - this->parent->ProcessReceivedSocketPackages(packet); - } - // handle the response to the auth request - if (packet.type == sd_gui_utils::networks::PacketType::RESPONSE) { - if (packet.param == sd_gui_utils::networks::PacketParam::AUTH) { - { - std::lock_guard guard(m_mutex); - std::string packetData = packet.GetData(); - this->parent->sendLogEvent("Got auth key: " + packetData + " our key: " + this->parent->configData->authkey, wxLOG_Debug); - - if (this->parent->configData->authkey.compare(packetData) == 0) { - this->m_clientInfo[packet.source_idx].apikey = packetData; - this->parent->sendLogEvent("Client authenticated: " + std::to_string(packet.source_idx), wxLOG_Info); - } else { - auto errorPacket = sd_gui_utils::networks::Packet(sd_gui_utils::networks::PacketType::RESPONSE, sd_gui_utils::networks::PacketParam::ERROR); - errorPacket.SetData("Authentication Failed"); - this->sendMsg(packet.source_idx, errorPacket); - this->parent->sendLogEvent("Authentication Failed, ip: " + this->m_clientInfo[packet.source_idx].host + " port: " + std::to_string(this->m_clientInfo[packet.source_idx].port) + " key: " + this->m_clientInfo[packet.source_idx].apikey + "", wxLOG_Error); - } - } - } - } - } catch (nlohmann::json::exception& e) { - this->parent->sendLogEvent(wxString::Format("Json Parse Error: %s", e.what()), wxLOG_Error); - } -} - -void SocketApp::DisconnectClient(int idx) { - std::lock_guard guard(m_mutex); - if (this->m_clientInfo.contains(idx)) { - if (this->m_server.deleteClient(idx)) { - this->m_clientInfo.erase(idx); - } - } -} \ No newline at end of file diff --git a/server/src/SocketApp.h b/server/src/SocketApp.h index 7b216bd..61aaf97 100644 --- a/server/src/SocketApp.h +++ b/server/src/SocketApp.h @@ -1,14 +1,19 @@ #ifndef _SERVER_SOCKETAPP_H #define _SERVER_SOCKETAPP_H +#include #include #include #include +#include "ver.hpp" + +#include "libs/json.hpp" + #include "network/packets.h" #include "sockets-cpp/TcpServer.h" -#include "libs/json.hpp" + inline auto LogPrinter = [](const std::string& strLogMsg) { std::cout << strLogMsg << std::endl; }; @@ -30,8 +35,8 @@ class SocketApp { void sendMsg(int idx, const sd_gui_utils::networks::Packet& packet); void DisconnectClient(int idx); void parseMsg(sd_gui_utils::networks::Packet& packet); - inline bool isRunning() { return this->needToRun == true; } - inline void stop() { this->needToRun = false; } + inline bool isRunning() { return this->needToRun.load() == true; } + inline void stop() { this->needToRun.store(false); } void OnTimer(); private: @@ -48,7 +53,7 @@ class SocketApp { int m_clientIdx = 0; std::map m_clientInfo; std::mutex m_mutex; - std::atomic needToRun = true; + std::atomic needToRun{true}; TerminalApp* parent = nullptr; std::vector buffer; size_t expected_size = 0; diff --git a/server/src/TerminalApp.cpp b/server/src/TerminalApp.cpp index 13281d3..1a07102 100644 --- a/server/src/TerminalApp.cpp +++ b/server/src/TerminalApp.cpp @@ -37,8 +37,7 @@ bool TerminalApp::OnInit() { } // set a random identifier to the server if not set in the config if (this->configData->authkey.empty()) { - this->configData->authkey = std::to_string(std::rand()); - this->configData->authkey = sd_gui_utils::sha256_string_openssl(this->configData->authkey); + this->configData->authkey = sd_gui_utils::sha256_string_openssl(std::to_string(std::rand()) + this->configData->host + std::to_string(this->configData->port)); wxLogInfo("Generated authkey: %s", this->configData->authkey); // save into the config file try { @@ -56,6 +55,29 @@ bool TerminalApp::OnInit() { return false; } } + if (this->configData->server_id.empty()) { + this->configData->server_id = std::to_string(std::rand()); + this->configData->server_id = sd_gui_utils::sha256_string_openssl(this->configData->authkey + this->configData->host + this->configData->model_path); + wxLogInfo("Generated server_id: %s", this->configData->server_id); + // save into the config file + try { + nlohmann::json saveJsonData = *this->configData.get(); + wxFile file; + if (file.Open(config.GetAbsolutePath(), wxFile::write)) { + file.Write(saveJsonData.dump(4)); + file.Close(); + } else { + wxLogError("Failed to open config file: %s", config.GetAbsolutePath()); + } + + } catch (const nlohmann::json::parse_error& e) { + wxLogError("Error parsing config file: %s", e.what()); + return false; + } + } + if (configData->shared_memory_path.empty()) { + configData->shared_memory_path = SHARED_MEMORY_PATH; + } if (configData->logfile.empty() == false) { configData->logfile = wxFileName(configData->logfile).GetAbsolutePath(); wxLogInfo("Logging to file: %s", configData->logfile); @@ -70,28 +92,14 @@ bool TerminalApp::OnInit() { this->oldLogger = wxLog::GetActiveTarget(); wxLog::SetActiveTarget(this->logger); } - this->sharedMemoryManager = std::make_shared(SHARED_MEMORY_PATH, SHARED_MEMORY_SIZE, true); - wxLogDebug(wxString::Format("Shared memory initialized: %s size: %d", SHARED_MEMORY_PATH, SHARED_MEMORY_SIZE)); - // init events - Bind(wxEVT_THREAD_LOG, [](wxCommandEvent& evt) { - switch (evt.GetInt()) { - case wxLOG_Info: - wxLogInfo(evt.GetString()); - break; - case wxLOG_Warning: - wxLogWarning(evt.GetString()); - break; - case wxLOG_Error: - wxLogError(evt.GetString()); - break; - case wxLOG_Debug: - wxLogDebug(evt.GetString()); - break; - default: - wxLogInfo(evt.GetString()); - break; - } - }); + + if (this->configData->model_path.empty()) { + wxLogError("`model_path` config key is missing"); + return false; + } + + this->sharedMemoryManager = std::make_shared(configData->shared_memory_path, SHARED_MEMORY_SIZE, true); + wxLogDebug(wxString::Format("Shared memory initialized: %s size: %d", configData->shared_memory_path, SHARED_MEMORY_SIZE)); Bind(wxEVT_TIMER, [this](wxTimerEvent& evt) { if (this->socket != nullptr) { @@ -102,7 +110,7 @@ bool TerminalApp::OnInit() { this->timer.SetOwner(this, wxID_ANY); this->timer.Start(1000); - this->eventHandlerReady = true; + this->eventHandlerReady.store(true); // find the external process if not in the config if (this->configData->exprocess_binary_path.empty() == false) { this->extprocessCommand = wxFileName(this->configData->exprocess_binary_path).GetAbsolutePath(); @@ -112,9 +120,11 @@ bool TerminalApp::OnInit() { f.SetName(EPROCESS_BINARY_NAME); if (f.Exists() == false) { + wxLogWarning("External process not found: %s", f.GetFullPath().utf8_string()); f.AppendDir("extprocess"); } if (f.Exists() == false) { + wxLogWarning("External process not found: %s", f.GetFullPath().utf8_string()); f.AppendDir("Debug"); } @@ -133,18 +143,19 @@ bool TerminalApp::OnInit() { // get the library #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) - wxString dllFullPath = currentPath + wxFileName::GetPathSeparator() + wxString::FromUTF8Unchecked(dllName.c_str()); - this->extProcessParam = dllFullPath.utf8_string() + ".dll"; + wxString dllFullPath = currentPath + wxFileName::GetPathSeparator() + wxString::FromUTF8Unchecked(dllName.c_str()); + this->extProcessParams.Add(dllFullPath.utf8_string() + ".dll"); if (std::filesystem::exists(this->extProcessParam.utf8_string()) == false) { this->sendLogEvent("Shared lib not found: " + this->extProcessParam, wxLOG_Error); return false; } #else - this->extProcessParam = "lib" + dllName + ".so"; + this->extProcessParams.Add("lib" + dllName + ".so"); + #endif - wxLogInfo("Using lib: %s", this->extProcessParam.utf8_string()); - this->sharedLibrary = std::make_shared(this->extProcessParam.utf8_string()); + wxLogInfo("Using lib: %s", this->extProcessParams.begin()->c_str()); + this->sharedLibrary = std::make_shared(this->extProcessParams.begin()->ToStdString()); try { this->sharedLibrary->load(); } catch (std::exception& e) { @@ -157,19 +168,22 @@ bool TerminalApp::OnInit() { std::cerr << "Failed to load model files" << std::endl; return false; } + + this->extProcessParams.Add(this->configData->shared_memory_path); + this->extProcessNeedToRun.store(true); return true; // return wxAppConsole::OnInit(); // Call the base class implementation } int TerminalApp::OnExit() { - wxLogInfo("OnExit started"); + wxLogInfo("Exiting..."); if (this->socket != nullptr) { this->socket->stop(); } if (this->subprocess != nullptr) { - this->extProcessNeedToRun = false; + this->extProcessNeedToRun.store(false); } for (auto& thread : this->threads) { @@ -186,10 +200,12 @@ int TerminalApp::OnExit() { wxLogError(e.what()); } } - + if (this->logThread.joinable()) { + this->logThread.join(); + } wxLog::SetActiveTarget(this->oldLogger); - wxLogDebug("Attempting to stop logger."); + wxLogDebug("Stopping logger... bye!"); delete this->logger; fclose(this->logfile); @@ -197,13 +213,26 @@ int TerminalApp::OnExit() { } int TerminalApp::OnRun() { - wxEventLoop loop; - wxEventLoopBase::SetActive(&loop); + + this->logThread = std::thread(&TerminalApp::ProcessLogQueue, this); + + std::thread tr3(&TerminalApp::ProcessOutputThread, this); + this->threads.emplace_back(std::move(tr3)); std::thread tr([this]() { - while (!this->eventHandlerReady) { + while (this->eventHandlerReady.load() == false) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); } + while (this->extProcessNeedToRun.load() == true && this->extprocessIsRunning.load() == false) { + this->sendLogEvent("Waiting for external process to start", wxLOG_Info); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + if (this->extProcessNeedToRun.load() == false && this->extprocessIsRunning.load() == false) { + this->sendLogEvent("External process not running, exiting...", wxLOG_Error); + this->ExitMainLoop(); + return; + } this->sendLogEvent("Starting socket server", wxLOG_Info); try { this->socket = new SocketApp(this->configData->host.c_str(), this->configData->port, this); @@ -211,13 +240,16 @@ int TerminalApp::OnRun() { this->sendLogEvent(e.what(), wxLOG_Error); } - while (this->socket->isRunning()) { + while (this->socket->isRunning() && this->eventHandlerReady.load() && this->extprocessIsRunning.load()) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } delete this->socket; this->socket = nullptr; + // stop the external process too + this->extProcessNeedToRun.store(false); this->sendLogEvent("Socket server stopped", wxLOG_Info); + this->ExitMainLoop(); }); this->threads.emplace_back(std::move(tr)); @@ -228,34 +260,75 @@ int TerminalApp::OnRun() { return wxAppConsole::OnRun(); } +void TerminalApp::ProcessOutputThread() { + this->sendLogEvent("Starting process output monitoring thread", wxLOG_Debug); + while (this->extProcessNeedToRun.load() == true) { + if (this->subprocess != nullptr && subprocess_alive(this->subprocess) != 0) { + static char stddata[1024] = {0}; + static char stderrdata[1024] = {0}; + + unsigned int size = sizeof(stderrdata); + unsigned int stdout_read_size = 0; + unsigned int stderr_read_size = 0; + + stdout_read_size = subprocess_read_stdout(this->subprocess, stddata, size); + stderr_read_size = subprocess_read_stderr(this->subprocess, stderrdata, size); + + if (stdout_read_size > 0 && std::string(stddata).find("(null)") == std::string::npos) { + this->sendLogEvent(stddata, wxLOG_Info); + } + if (stderr_read_size > 0 && std::string(stderrdata).find("(null)") == std::string::npos) { + this->sendLogEvent(stddata, wxLOG_Error); + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME)); + } +} + void TerminalApp::ExternalProcessRunner() { if (this->subprocess != nullptr) { this->sendLogEvent("Subprocess already running", wxLOG_Error); return; } - this->sendLogEvent(wxString::Format("Starting subprocess: %s %s", this->extprocessCommand.utf8_string().c_str(), this->extProcessParam.utf8_string().c_str()), wxLOG_Info); - const char* command_line[] = {this->extprocessCommand.c_str(), this->extProcessParam.c_str(), nullptr}; - this->subprocess = new subprocess_s(); - int result = subprocess_create(command_line, subprocess_option_no_window | subprocess_option_combined_stdout_stderr | subprocess_option_enable_async | subprocess_option_search_user_path | subprocess_option_inherit_environment, this->subprocess); - if (this->subprocess == nullptr) { + + const char* command_line[this->extProcessParams.size() + 1]; + + command_line[0] = this->extprocessCommand.c_str(); + wxString params = this->extprocessCommand; + int counter = 1; + for (auto const& p : this->extProcessParams) { + params.Append(" "); + params.Append(p); + command_line[counter] = p.c_str(); + counter++; + } + + command_line[counter] = nullptr; + + this->sendLogEvent(wxString::Format("Starting subprocess: %s", params), wxLOG_Info); + this->subprocess = new subprocess_s(); + int result = subprocess_create(command_line, subprocess_option_no_window | subprocess_option_combined_stdout_stderr | subprocess_option_enable_async | subprocess_option_search_user_path | subprocess_option_inherit_environment, this->subprocess); + if (this->subprocess == nullptr || result != 0) { this->sendLogEvent("Failed to create subprocess", wxLOG_Error); - this->extprocessIsRunning = false; + this->extprocessIsRunning.store(false); + this->extProcessNeedToRun.store(false); return; } + this->extprocessIsRunning.store(true); this->sendLogEvent(wxString::Format("Subprocess created: %d", result), wxLOG_Info); - while (this->extProcessNeedToRun == true) { + while (this->extProcessNeedToRun.load() == true) { if (subprocess_alive(this->subprocess) == 0) { this->sendLogEvent("Subprocess stopped", wxLOG_Error); - this->extprocessIsRunning = false; + this->extprocessIsRunning.store(false); // restart int result = subprocess_create(command_line, subprocess_option_no_window | subprocess_option_combined_stdout_stderr | subprocess_option_enable_async | subprocess_option_search_user_path | subprocess_option_inherit_environment, this->subprocess); if (this->subprocess == nullptr) { this->sendLogEvent("Failed to create subprocess", wxLOG_Error); - this->extprocessIsRunning = false; + this->extprocessIsRunning.store(false); return; } - this->extprocessIsRunning = true; + this->extprocessIsRunning.store(false); this->sendLogEvent(wxString::Format("Subprocess created: %d", result), wxLOG_Info); } // handle shared memory @@ -272,7 +345,7 @@ void TerminalApp::ExternalProcessRunner() { } std::this_thread::sleep_for(std::chrono::milliseconds(100)); } - this->extprocessIsRunning = false; + this->extprocessIsRunning.store(false); subprocess_terminate(this->subprocess); } @@ -301,7 +374,9 @@ void TerminalApp::ProcessReceivedSocketPackages(const sd_gui_utils::networks::Pa if (packet.param == sd_gui_utils::networks::PacketParam::MODEL_LIST) { auto response = sd_gui_utils::networks::Packet(sd_gui_utils::networks::PacketType::RESPONSE, sd_gui_utils::networks::PacketParam::MODEL_LIST); std::vector list; - for (const auto model : this->modelFiles) { + for (auto model : this->modelFiles) { + // change the model's path + model.second.path = this->configData->server_id + ":" + model.second.path; list.emplace_back(model.second); } response.SetData(list); @@ -336,21 +411,35 @@ bool TerminalApp::LoadModelFiles() { wxLogInfo("Loaded %d checkpoints %s", checkpoint_count, wxFileName::GetHumanReadableSize(used_checkpoint_sizes)); // load loras - wxArrayString lora_files; - wxDir::GetAllFiles(this->configData->lora_path, &lora_files); - int lora_count = 0; - wxULongLong used_lora_sizes = 0; - for (const auto& file : lora_files) { - wxFileName filename(file); - if (std::find(LORA_FILE_EXTENSIONS.begin(), LORA_FILE_EXTENSIONS.end(), filename.GetExt()) != LORA_FILE_EXTENSIONS.end()) { - sd_gui_utils::networks::RemoteModelInfo modelInfo = sd_gui_utils::networks::RemoteModelInfo(filename, sd_gui_utils::DirTypes::LORA, this->configData->lora_path); - this->modelFiles[filename.GetAbsolutePath().utf8_string()] = modelInfo; - used_sizes += modelInfo.size; - used_lora_sizes += modelInfo.size; - lora_count++; + if (this->configData->lora_path.empty() == false && wxDirExists(this->configData->lora_path)) { + wxArrayString lora_files; + wxDir::GetAllFiles(this->configData->lora_path, &lora_files); + int lora_count = 0; + wxULongLong used_lora_sizes = 0; + for (const auto& file : lora_files) { + wxFileName filename(file); + if (std::find(LORA_FILE_EXTENSIONS.begin(), LORA_FILE_EXTENSIONS.end(), filename.GetExt()) != LORA_FILE_EXTENSIONS.end()) { + sd_gui_utils::networks::RemoteModelInfo modelInfo = sd_gui_utils::networks::RemoteModelInfo(filename, sd_gui_utils::DirTypes::LORA, this->configData->lora_path); + this->modelFiles[filename.GetAbsolutePath().utf8_string()] = modelInfo; + used_sizes += modelInfo.size; + used_lora_sizes += modelInfo.size; + lora_count++; + } } + wxLogInfo("Loaded %d loras %s", lora_count, wxFileName::GetHumanReadableSize(used_lora_sizes)); + wxLogInfo("Total size: %s", wxFileName::GetHumanReadableSize((wxULongLong)used_sizes)); + } else { + wxLogWarning("Lora path does not exist or missing from config: %s", this->configData->lora_path); } - wxLogInfo("Loaded %d loras %s", lora_count, wxFileName::GetHumanReadableSize(used_lora_sizes)); - wxLogInfo("Total size: %s", wxFileName::GetHumanReadableSize((wxULongLong)used_sizes)); return true; +} + +void TerminalApp::ProcessLogQueue() { + while (!this->eventHanlderExit.load()) { + while (!this->eventQueue.IsEmpty()) { + auto event = this->eventQueue.Pop(); + event(); + } + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } } \ No newline at end of file diff --git a/server/src/TerminalApp.h b/server/src/TerminalApp.h index 99627c3..bfbb3c7 100644 --- a/server/src/TerminalApp.h +++ b/server/src/TerminalApp.h @@ -2,19 +2,15 @@ #define _SERVER_TERMINALAPP_H #include "libs/SharedLibrary.h" -#include "wx/wxprec.h" - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif #include -#include #include #include #include #include #include +#include + #include #include "libs/json.hpp" #include "network/RemoteModelInfo.h" @@ -24,9 +20,9 @@ #include "helpers/sslUtils.hpp" #include "libs/ExternalProcess.h" -wxDECLARE_APP(TerminalApp); +#include "EventQueue.h" -wxDEFINE_EVENT(wxEVT_THREAD_LOG, wxCommandEvent); +wxDECLARE_APP(TerminalApp); class TerminalApp : public wxAppConsole { public: @@ -35,25 +31,40 @@ class TerminalApp : public wxAppConsole { virtual int OnExit() override; virtual bool IsGUI() const override { return false; } void ProcessReceivedSocketPackages(const sd_gui_utils::networks::Packet& packet); - inline void sendLogEvent(const wxString& strLogMsg, const wxLogLevel level = wxLOG_Info) { - if (!this->eventHandlerReady) { - std::cerr << "Event handler not ready. Dropping log: " << strLogMsg << std::endl; - return; - } - wxCommandEvent evt(wxEVT_THREAD_LOG); - evt.SetString(strLogMsg); - evt.SetInt((int)level); - wxTheApp->AddPendingEvent(evt); + inline void sendLogEvent(const wxString& message, const wxLogLevel level = wxLOG_Info) { + eventQueue.Push([message, level]() { + switch (level) { + case wxLOG_Info: + wxLogInfo(message); + break; + case wxLOG_Warning: + wxLogWarning(message); + break; + case wxLOG_Error: + wxLogError(message); + break; + case wxLOG_Debug: + wxLogDebug(message); + break; + default: + wxLogMessage(message); + break; + } + }); } std::shared_ptr configData = nullptr; - private: void ExternalProcessRunner(); + void ProcessOutputThread(); + void ProcessLogQueue(); // process the messages from the shm bool ProcessEventHandler(std::string message); bool LoadModelFiles(); + std::thread logThread; + std::atomic eventHanlderExit{false}; + EventQueue eventQueue; std::vector threads; bool m_shouldExit = false; std::shared_ptr sharedMemoryManager = nullptr; @@ -62,12 +73,12 @@ class TerminalApp : public wxAppConsole { std::FILE* logfile = nullptr; wxLogStderr* logger = nullptr; wxLog* oldLogger = nullptr; - std::atomic eventHandlerReady = false; struct subprocess_s* subprocess = nullptr; wxString extprocessCommand = ""; - wxString extProcessParam = ""; - std::atomic extprocessIsRunning = false; - std::atomic extProcessNeedToRun = true; + wxArrayString extProcessParams; + std::atomic eventHandlerReady{false}; + std::atomic extProcessNeedToRun{false}; + std::atomic extprocessIsRunning{false}; wxTimer timer; std::unordered_map modelFiles; }; diff --git a/src/MainApp.h b/src/MainApp.h index 04328c2..cc2e059 100644 --- a/src/MainApp.h +++ b/src/MainApp.h @@ -169,9 +169,6 @@ class MainApp : public wxApp { delete this->config; this->config = nullptr; } - if (this->cfg != nullptr) { - delete this->cfg; - } this->config = new wxConfig(PROJECT_NAME, SD_GUI_AUTHOR, wxEmptyString, wxEmptyString, wxCONFIG_USE_LOCAL_FILE); this->cfg = new sd_gui_utils::config(this->config); wxConfigBase::Set(this->config); diff --git a/src/helpers/QueueItem.h b/src/helpers/QueueItem.h new file mode 100644 index 0000000..8991926 --- /dev/null +++ b/src/helpers/QueueItem.h @@ -0,0 +1,96 @@ +#ifndef __HELPERS_QUEUE_ITEM_ +#define __HELPERS_QUEUE_ITEM_ +/** +@file QueueItem.h +@brief A status of a QueueItem +*/ +enum QueueStatus { + PENDING, // deletable + RUNNING, // non deletable + PAUSED, // deletable + FAILED, // deletable + MODEL_LOADING, // non deletable + DONE, // deletable + HASHING, // non deletable + HASHING_DONE // non deletable +}; + +inline const std::unordered_map GenerationMode_str = { + {SDMode::TXT2IMG, "txt2img"}, + {SDMode::IMG2IMG, "img2img"}, + {SDMode::CONVERT, "convert"}, + {SDMode::UPSCALE, "upscale"}, + {SDMode::IMG2VID, "img2vid"}}; + +inline const std::unordered_map GenerationMode_str_inv = { + {"txt2img", SDMode::TXT2IMG}, + {"img2img", SDMode::IMG2IMG}, + {"convert", SDMode::CONVERT}, + {"upscale", SDMode::UPSCALE}, + {"img2vid", SDMode::IMG2VID}}; + +inline const char* QueueStatus_str[] = { + _("pending"), + _("running"), + _("paused"), + _("failed"), + _("model loading..."), + _("finished"), + _("model hashing...")}; + +inline const std::unordered_map QueueStatus_GUI_str = { + {QueueStatus::PENDING, "pending"}, + {QueueStatus::RUNNING, "running"}, + {QueueStatus::PAUSED, "paused"}, + {QueueStatus::FAILED, "failed"}, + {QueueStatus::MODEL_LOADING, "model loading..."}, + {QueueStatus::DONE, "finished"}, + {QueueStatus::HASHING, "model hashing..."}}; + +/// @brief Event commands to inter thread communication +enum class QueueEvents : unsigned int { + ITEM_DELETED = 1, + ITEM_ADDED = 2, + ITEM_STATUS_CHANGED = 4, + ITEM_UPDATED = 8, + ITEM_START = 16, + ITEM_FINISHED = 32, + ITEM_MODEL_LOAD_START = 64, + ITEM_MODEL_LOADED = 128, + ITEM_MODEL_FAILED = 256, + ITEM_GENERATION_STARTED = 512, + ITEM_FAILED = 1024, + ITEM_MODEL_HASH_START = 2048, + ITEM_MODEL_HASH_UPDATE = 4096, + ITEM_MODEL_HASH_DONE = 8192 +}; + +inline const std::unordered_map QueueEvents_str = { + {QueueEvents::ITEM_DELETED, "ITEM_DELETED"}, + {QueueEvents::ITEM_ADDED, "ITEM_ADDED"}, + {QueueEvents::ITEM_STATUS_CHANGED, "ITEM_STATUS_CHANGED"}, + {QueueEvents::ITEM_UPDATED, "ITEM_UPDATED"}, + {QueueEvents::ITEM_START, "ITEM_START"}, + {QueueEvents::ITEM_FINISHED, "ITEM_FINISHED"}, + {QueueEvents::ITEM_MODEL_LOAD_START, "ITEM_MODEL_LOAD_START"}, + {QueueEvents::ITEM_MODEL_LOADED, "ITEM_MODEL_LOADED"}, + {QueueEvents::ITEM_MODEL_FAILED, "ITEM_MODEL_FAILED"}, + {QueueEvents::ITEM_GENERATION_STARTED, "ITEM_GENERATION_STARTED"}, + {QueueEvents::ITEM_FAILED, "ITEM_FAILED"}, + {QueueEvents::ITEM_MODEL_HASH_START, "ITEM_MODEL_HASH_START"}, + {QueueEvents::ITEM_MODEL_HASH_UPDATE, "ITEM_MODEL_HASH_UPDATE"}, + {QueueEvents::ITEM_MODEL_HASH_DONE, "ITEM_MODEL_HASH_DONE"}}; + +struct QueueStatsStepItem { + int step; + int steps; + float time; +}; +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(QueueStatsStepItem, step, steps, time) +struct QueueItemStats { + float time_min = 0.f, time_max = 0.f, time_avg = 0.f, time_total = 0.f; + std::vector time_per_step = {}; +}; +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(QueueItemStats, time_min, time_max, time_avg, time_total, time_per_step) + +#endif // __HELPERS_QUEUE_ITEM \ No newline at end of file diff --git a/src/helpers/TreeListManager.h b/src/helpers/TreeListManager.h index 5638f29..63cda91 100644 --- a/src/helpers/TreeListManager.h +++ b/src/helpers/TreeListManager.h @@ -50,27 +50,29 @@ class TreeListManager { if (!treeList) { throw std::invalid_argument("treeList cannot be null"); } - auto comparator = new wxTreeListModelItemComparator(); - this->treeListCtrl = treeList; - this->treeListCtrl->SetItemComparator(comparator); + auto comparator = new wxTreeListModelItemComparator(); + treeListCtrl = treeList; + treeListCtrl->SetItemComparator(comparator); } + void AppendColumn(const wxString& title, int width = wxCOL_WIDTH_AUTOSIZE, wxAlignment align = wxALIGN_LEFT, int flags = wxCOL_RESIZABLE) { + int id = treeListCtrl->AppendColumn(title, width, align, flags); + ColumnInfo info{title, width, align, flags, id}; + columns.push_back(info); + } - void AddItem(const sd_gui_utils::ModelFileInfo* item, bool select = false, sd_gui_utils::sdServer* server = nullptr) { + void AddItem(const sd_gui_utils::ModelFileInfo* item, bool select = false) { wxTreeListItem parentItem = GetOrCreateParent(item->folderGroupName); wxString name = wxString::FromUTF8Unchecked(item->name); if (!item->folderGroupName.empty()) { name.Replace(item->folderGroupName, ""); name.Replace(wxFileName::GetPathSeparator(), ""); } - if (sd_gui_utils::HasTag(item->tags, sd_gui_utils::ModelInfoTag::Favorite)) { // name.Prepend(wxUniChar(0x2B50)); // Unicode star: ⭐ --> this is not working on windows name = wxString::Format("%s %s", _("[F] "), name); } - wxTreeListItem newItem = treeListCtrl->AppendItem(parentItem, name); - this->dataMap[newItem] = new ModelFileInfoData(item); treeListCtrl->SetItemText(newItem, 1, wxString(item->size_f)); treeListCtrl->SetItemText(newItem, 2, wxString(ConvertTypeToString(item->model_type))); treeListCtrl->SetItemText(newItem, 3, wxString(item->sha256).substr(0, 10)); @@ -80,241 +82,199 @@ class TreeListManager { } } - void DeleteByServerId(const sd_gui_utils::sdServer* server) { - for (auto it = dataMap.begin(); it != dataMap.end();) { - if (it->second != nullptr && it->second->GetFileInfo() != nullptr && it->second->GetFileInfo()->server_id == server->server_id) { - this->treeListCtrl->DeleteItem(it->first); - it = dataMap.erase(it); - } else { - it++; - } + template + void AddItem(const wxString& title, const wxVector& item, const wxString& groupName = wxEmptyString, T* data = nullptr) { + wxTreeListItem parentItem = GetOrCreateParent(groupName); + wxTreeListItem newItem = treeListCtrl->AppendItem(parentItem, title); + if (data) { + treeListCtrl->SetItemData(newItem, new DataContainer(data)); } - } - - void TraverseAndDelete(const wxTreeListItem& parentItem, std::function condition) { - wxTreeListItem child = treeListCtrl->GetFirstChild(parentItem); - while (child.IsOk()) { - wxTreeListItem nextSibling = treeListCtrl->GetNextSibling(child); - // Bejárás: gyerekek rekurzív ellenőrzése - TraverseAndDelete(child, condition); - - // Feltétel ellenőrzése és törlés - void* data = treeListCtrl->GetItemData(child); - if (data && condition(data)) { - auto it = std::find_if(parentMap.begin(), parentMap.end(), - [&](const auto& pair) { return pair.second == child; }); - if (it != parentMap.end()) { - parentMap.erase(it); - } - treeListCtrl->DeleteItem(child); - } - - child = nextSibling; + if (item.size() != this->columns.size()) { + throw std::invalid_argument("item.size() != this->columns.size()"); } - - // Szülő törlése, ha nincs gyerek - if (treeListCtrl->GetFirstChild(parentItem).IsOk() == false && parentItem != treeListCtrl->GetRootItem()) { - auto it = std::find_if(parentMap.begin(), parentMap.end(), - [&](const auto& pair) { return pair.second == parentItem; }); - if (it != parentMap.end()) { - parentMap.erase(it); - } - treeListCtrl->DeleteItem(parentItem); + for (size_t i = 0; i < item.size(); i++) { + treeListCtrl->SetItemText(newItem, item[i].pos, item[i].title); } + } - template - void AddItem(const wxString& title, const wxVector& item, const wxString& groupName = wxEmptyString, T* data = nullptr) { - wxTreeListItem parentItem = GetOrCreateParent(groupName); - wxTreeListItem newItem = treeListCtrl->AppendItem(parentItem, title); - if (data) { - treeListCtrl->SetItemData(newItem, new DataContainer(data)); - } - - if (item.size() != this->columns.size()) { - throw std::invalid_argument("item.size() != this->columns.size()"); - } - for (size_t i = 0; i < item.size(); i++) { - treeListCtrl->SetItemText(newItem, item[i].pos, item[i].title); - } + void RemoveItem(const std::string& path) { + wxTreeListItem root = treeListCtrl->GetRootItem(); + wxTreeListItem item = FindItemByPath(root, path); + if (item.IsOk()) { + treeListCtrl->DeleteItem(item); } + } - void RemoveItem(const std::string& path) { - wxTreeListItem root = treeListCtrl->GetRootItem(); - wxTreeListItem item = FindItemByPath(root, path); - if (item.IsOk()) { - treeListCtrl->DeleteItem(item); - } + void SelectItemByModelPath(const std::string& path) { + if (path.empty()) { + return; } - - void SelectItemByModelPath(const std::string& path) { - if (path.empty()) { - return; - } - wxTreeListItem root = treeListCtrl->GetRootItem(); - wxTreeListItem item = FindItemByPath(root, path); - if (item.IsOk()) { - treeListCtrl->Select(item); - } + wxTreeListItem root = treeListCtrl->GetRootItem(); + wxTreeListItem item = FindItemByPath(root, path); + if (item.IsOk()) { + treeListCtrl->Select(item); } + } - void UpdateItem(const sd_gui_utils::ModelFileInfo* updatedItem) { - wxTreeListItem root = treeListCtrl->GetRootItem(); - wxTreeListItem item = FindItemByPath(root, updatedItem->path); - if (item.IsOk()) { - treeListCtrl->SetItemText(item, 0, wxString(updatedItem->name)); - treeListCtrl->SetItemText(item, 1, wxString(updatedItem->size_f)); - treeListCtrl->SetItemText(item, 2, wxString(ConvertTypeToString(updatedItem->model_type))); - treeListCtrl->SetItemText(item, 3, wxString(updatedItem->sha256)); - } + void UpdateItem(const sd_gui_utils::ModelFileInfo* updatedItem) { + wxTreeListItem root = treeListCtrl->GetRootItem(); + wxTreeListItem item = FindItemByPath(root, updatedItem->path); + if (item.IsOk()) { + treeListCtrl->SetItemText(item, 0, wxString(updatedItem->name)); + treeListCtrl->SetItemText(item, 1, wxString(updatedItem->size_f)); + treeListCtrl->SetItemText(item, 2, wxString(ConvertTypeToString(updatedItem->model_type))); + treeListCtrl->SetItemText(item, 3, wxString(updatedItem->sha256)); } - void ChangeText(const std::string& path, const wxString& text, unsigned int col) { - wxTreeListItem root = treeListCtrl->GetRootItem(); - wxTreeListItem item = FindItemByPath(root, path); - if (item.IsOk()) { - treeListCtrl->SetItemText(item, col, wxString::FromUTF8(text)); - } - } - void ChangeText(wxTreeListItem item, const wxString& text, unsigned int col = 0) { - if (item.IsOk()) { - treeListCtrl->SetItemText(item, col, text); - } + } + void ChangeText(const std::string& path, const wxString& text, unsigned int col) { + wxTreeListItem root = treeListCtrl->GetRootItem(); + wxTreeListItem item = FindItemByPath(root, path); + if (item.IsOk()) { + treeListCtrl->SetItemText(item, col, wxString::FromUTF8(text)); } + } - sd_gui_utils::ModelFileInfo* FindItem(const std::string& path) { - wxTreeListItem root = treeListCtrl->GetRootItem(); - wxTreeListItem item = FindItemByPath(root, path); - if (item.IsOk()) { - ModelFileInfoData* data = static_cast(treeListCtrl->GetItemData(item)); - return data ? data->GetFileInfo() : nullptr; - } - return nullptr; + void ChangeText(wxTreeListItem item, const wxString& text, unsigned int col) { + if (item.IsOk()) { + treeListCtrl->SetItemText(item, col, wxString::FromUTF8(text)); } + } - sd_gui_utils::ModelFileInfo* FindItem(const wxTreeListItem& item) { + sd_gui_utils::ModelFileInfo* FindItem(const std::string& path) { + wxTreeListItem root = treeListCtrl->GetRootItem(); + wxTreeListItem item = FindItemByPath(root, path); + if (item.IsOk()) { ModelFileInfoData* data = static_cast(treeListCtrl->GetItemData(item)); - if (data == NULL) { - return nullptr; - } - auto mdl = data->GetFileInfo(); - return mdl; + return data ? data->GetFileInfo() : nullptr; } + return nullptr; + } - wxTreeListItem GetOrCreateParent(const wxString& folderGroupName) { - return GetOrCreateParent(folderGroupName.utf8_string()); - } + sd_gui_utils::ModelFileInfo* FindItem(const wxTreeListItem& item) { + ModelFileInfoData* data = static_cast(treeListCtrl->GetItemData(item)); + return data ? data->GetFileInfo() : nullptr; + } - const wxString findParentPath(const wxTreeListItem& item, sd_gui_utils::config* config) { - auto selected = item; - auto selectedName = this->treeListCtrl->GetItemText(item); - wxString basePath = selectedName, groupFolderName = selectedName; + wxTreeListItem GetOrCreateParent(const wxString& folderGroupName) { + return GetOrCreateParent(folderGroupName.utf8_string()); + } - while (selected.IsOk()) { - auto parent = this->treeListCtrl->GetItemParent(selected); - wxString parentName = this->treeListCtrl->GetItemText(parent); - if (parent.IsOk() == false || parentName.empty()) { - break; - } - auto parentPath = config->getPathByDirType(parentName); - if (parentPath.empty() == false) { - basePath.Prepend(parentPath + wxFileName::GetPathSeparators()); - } else { - parentName.Append(wxFileName::GetPathSeparators()); - basePath.Prepend(parentName); - } - groupFolderName.Prepend(parentName + wxFileName::GetPathSeparators()); - selected = parent; + const wxString findParentPath(const wxTreeListItem& item, sd_gui_utils::config* config) { + auto selected = item; + auto selectedName = this->treeListCtrl->GetItemText(item); + wxString basePath = selectedName, groupFolderName = selectedName; + + while (selected.IsOk()) { + auto parent = this->treeListCtrl->GetItemParent(selected); + wxString parentName = this->treeListCtrl->GetItemText(parent); + if (parent.IsOk() == false || parentName.empty()) { + break; } - if (basePath == selectedName) { - basePath = config->getPathByDirType(selectedName); - if (basePath.empty() == true) { - return wxEmptyString; - } + auto parentPath = config->getPathByDirType(parentName); + if (parentPath.empty() == false) { + basePath.Prepend(parentPath + wxFileName::GetPathSeparators()); + } else { + parentName.Append(wxFileName::GetPathSeparators()); + basePath.Prepend(parentName); } - return basePath; + groupFolderName.Prepend(parentName + wxFileName::GetPathSeparators()); + selected = parent; } - - void CleanAll() { - treeListCtrl->DeleteAllItems(); - parentMap.clear(); + if (basePath == selectedName) { + basePath = config->getPathByDirType(selectedName); + if (basePath.empty() == true) { + return wxEmptyString; + } } + return basePath; + } - private: - wxTreeListCtrl* treeListCtrl = nullptr; - wxVector columns; - std::map parentMap; - std::map dataMap; + void DeleteByServerId(const std::string& serverId) { - /** - * Retrieves or creates the parent wxTreeListItem for a given folder group name. - * - * This function takes a folder group name, which may consist of multiple segments - * separated by separator character, and ensures that each segment has a corresponding wxTreeListItem - * in the tree. If the specified folder group name is empty, it returns the root item. - * For each segment, it checks if a corresponding item already exists; if not, it creates - * a new item and inserts it into the tree. The function returns the wxTreeListItem of - * the last segment in the folder group name. - * - * @param folderGroupName A string representing the hierarchical folder group name, - * where segments are separated by separator character. - * @return The wxTreeListItem corresponding to the last segment of the folder group name. - */ - wxTreeListItem GetOrCreateParent(const std::string& folderGroupName) { - if (folderGroupName.empty()) { - return treeListCtrl->GetRootItem(); - } - std::vector groups; - SplitFolderGroupName(wxString::FromUTF8Unchecked(folderGroupName), groups); + } - wxTreeListItem parent = treeListCtrl->GetRootItem(); - std::string fullPath; - for (const auto& group : groups) { - if (!fullPath.empty()) { - fullPath += wxFileName::GetPathSeparator(); - } - fullPath += group; + void CleanAll() { + treeListCtrl->DeleteAllItems(); + parentMap.clear(); + } - if (parentMap.find(fullPath) == parentMap.end()) { - wxTreeListItem newParent = treeListCtrl->AppendItem(parent, wxString(group)); - parentMap[fullPath] = newParent; - parent = newParent; - } else { - parent = parentMap[fullPath]; - } - } - return parent; +private: + wxTreeListCtrl* treeListCtrl; + wxVector columns; + std::map parentMap; + + /** + * Retrieves or creates the parent wxTreeListItem for a given folder group name. + * + * This function takes a folder group name, which may consist of multiple segments + * separated by separator character, and ensures that each segment has a corresponding wxTreeListItem + * in the tree. If the specified folder group name is empty, it returns the root item. + * For each segment, it checks if a corresponding item already exists; if not, it creates + * a new item and inserts it into the tree. The function returns the wxTreeListItem of + * the last segment in the folder group name. + * + * @param folderGroupName A string representing the hierarchical folder group name, + * where segments are separated by separator character. + * @return The wxTreeListItem corresponding to the last segment of the folder group name. + */ + wxTreeListItem GetOrCreateParent(const std::string& folderGroupName) { + if (folderGroupName.empty()) { + return treeListCtrl->GetRootItem(); } + // std::cout << "folderGroupName: " << folderGroupName << std::endl; + std::vector groups; + SplitFolderGroupName(wxString::FromUTF8Unchecked(folderGroupName), groups); + + wxTreeListItem parent = treeListCtrl->GetRootItem(); + std::string fullPath; + for (const auto& group : groups) { + if (!fullPath.empty()) { + fullPath += wxFileName::GetPathSeparator(); + } + fullPath += group; - wxTreeListItem FindItemByPath(const wxTreeListItem& parent, const std::string& path) { - wxTreeListItem item = treeListCtrl->GetFirstChild(parent); - while (item.IsOk()) { - ModelFileInfoData* data = static_cast(treeListCtrl->GetItemData(item)); - if (data) { - sd_gui_utils::ModelFileInfo* fileInfo = data->GetFileInfo(); - if (fileInfo && fileInfo->path == path) { - return item; - } - } - wxTreeListItem childResult = FindItemByPath(item, path); - if (childResult.IsOk()) { - return childResult; - } - item = treeListCtrl->GetNextSibling(item); + if (parentMap.find(fullPath) == parentMap.end()) { + wxTreeListItem newParent = treeListCtrl->AppendItem(parent, wxString(group)); + parentMap[fullPath] = newParent; + parent = newParent; + } else { + parent = parentMap[fullPath]; } - return wxTreeListItem(); } + return parent; + } - void SplitFolderGroupName(const wxString& folderGroupName, std::vector& groups) { - wxStringTokenizer tokenizer(folderGroupName, wxFileName::GetPathSeparator()); - while (tokenizer.HasMoreTokens()) { - wxString token = tokenizer.GetNextToken(); - groups.push_back(std::string(token.mb_str())); + wxTreeListItem FindItemByPath(const wxTreeListItem& parent, const std::string& path) { + wxTreeListItem item = treeListCtrl->GetFirstChild(parent); + while (item.IsOk()) { + ModelFileInfoData* data = static_cast(treeListCtrl->GetItemData(item)); + if (data) { + sd_gui_utils::ModelFileInfo* fileInfo = data->GetFileInfo(); + if (fileInfo && fileInfo->path == path) { + return item; + } + } + wxTreeListItem childResult = FindItemByPath(item, path); + if (childResult.IsOk()) { + return childResult; } + item = treeListCtrl->GetNextSibling(item); } + return wxTreeListItem(); + } - std::string ConvertTypeToString(sd_gui_utils::DirTypes type) { - return sd_gui_utils::dirtypes_str.contains(type) ? sd_gui_utils::dirtypes_str.at(type) : "Unknown"; + void SplitFolderGroupName(const wxString& folderGroupName, std::vector& groups) { + wxStringTokenizer tokenizer(folderGroupName, wxFileName::GetPathSeparator()); + while (tokenizer.HasMoreTokens()) { + wxString token = tokenizer.GetNextToken(); + groups.push_back(std::string(token.mb_str())); } - }; + } + + std::string ConvertTypeToString(sd_gui_utils::DirTypes type) { + return sd_gui_utils::dirtypes_str.contains(type) ? sd_gui_utils::dirtypes_str.at(type) : "Unknown"; + } +}; -#endif // TREE_LIST_MANAGER_H +#endif // TREE_LIST_MANAGER_H \ No newline at end of file diff --git a/src/helpers/sd.hpp b/src/helpers/sd.hpp index b481ad5..e800a71 100644 --- a/src/helpers/sd.hpp +++ b/src/helpers/sd.hpp @@ -216,11 +216,14 @@ typedef sd_image_t (*UpscalerFunction)(upscaler_ctx_t*, // pointer inline const char* modes_str[] = {"txt2img", "img2img", "convert", "upscale"}; -enum SDMode { TXT2IMG, - IMG2IMG, - CONVERT, - UPSCALE, - MODE_COUNT }; +enum SDMode { + TXT2IMG, + IMG2IMG, + CONVERT, + UPSCALE, + IMG2VID, + MODE_COUNT +}; struct SDParams { int n_threads = -1; diff --git a/src/libs/TcpClient.h b/src/libs/TcpClient.h index 71bd0d8..cc9f56f 100644 --- a/src/libs/TcpClient.h +++ b/src/libs/TcpClient.h @@ -53,4 +53,4 @@ namespace sd_gui_utils::networks { } }; } -#endif; // _LIBS_TCPCLIENT_H_ \ No newline at end of file +#endif // _LIBS_TCPCLIENT_H_ \ No newline at end of file diff --git a/src/network/RemoteQueueJobItem.h b/src/network/RemoteQueueJobItem.h new file mode 100644 index 0000000..7700d75 --- /dev/null +++ b/src/network/RemoteQueueJobItem.h @@ -0,0 +1,32 @@ +#ifndef _NETWORK_REMOTE_QUEUE_JOB_ITEM_H_ +#define _NETWORK_REMOTE_QUEUE_JOB_ITEM_H_ + +namespace sd_gui_utils::networks { + struct RemoteQueueItem { + int id = 0, created_at = 0, updated_at = 0, finished_at = 0, started_at = 0; + SDParams params = SDParams(); + QueueStatus status = QueueStatus::PENDING; + QueueEvents event = QueueEvents::ITEM_ADDED; + QueueItemStats stats = QueueItemStats(); + int step = 0, steps = 0; + size_t hash_fullsize = 0, hash_progress_size = 0; + float time = 0; + std::string model = ""; + SDMode mode = SDMode::TXT2IMG; + std::string status_message = ""; + uint32_t upscale_factor = 4; + std::string sha256 = ""; + std::string app_version = SD_GUI_VERSION; + std::string git_version = GIT_HASH; + std::string original_prompt = ""; + std::string original_negative_prompt = ""; + bool keep_checkpoint_in_memory = false; + bool keep_upscaler_in_memory = false; + bool need_sha256 = false; + std::string generated_sha256 = ""; + int update_index = -1; + std::string server = ""; + }; +} + +#endif // _NETWORK_REMOTE_QUEUE_JOB_ITEM_H_ \ No newline at end of file diff --git a/src/network/packets.h b/src/network/packets.h index e3c5ec7..8799cd0 100644 --- a/src/network/packets.h +++ b/src/network/packets.h @@ -1,6 +1,5 @@ #ifndef _NETWORK_PACKETS_H_ #define _NETWORK_PACKETS_H_ - namespace sd_gui_utils { static std::string toHex(const char* data, size_t size) { @@ -30,7 +29,7 @@ namespace sd_gui_utils { ERROR = 0, AUTH = 1, MODEL_LIST = 2, - KEEPALIVE = 3 + KEEPALIVE = 3 }; NLOHMANN_JSON_SERIALIZE_ENUM(PacketParam, {{PacketParam::ERROR, 0}, {PacketParam::AUTH, 1}, {PacketParam::MODEL_LIST, 2}}) @@ -47,9 +46,10 @@ namespace sd_gui_utils { : type(PacketType::REQUEST), param(PacketParam::ERROR) {} sd_gui_utils::networks::PacketType type; sd_gui_utils::networks::PacketParam param; - std::string version = std::string(SD_GUI_VERSION); - int source_idx = -1; - int target_idx = -1; + std::string version = std::string(SD_GUI_VERSION); + int source_idx = -1; + int target_idx = -1; + std::string server_id = ""; inline size_t GetSize() { return this->data_size; } template @@ -93,14 +93,12 @@ namespace sd_gui_utils { std::vector binary_data(data, data + size); auto json_data = nlohmann::json::from_ubjson(binary_data); - // Ellenőrizzük, hogy valóban megfelelő adat érkezett if (json_data.is_null()) { throw std::runtime_error("Received empty MessagePack data."); } return json_data.get(); } catch (const std::exception& e) { - // Debugging kiírás hexadecimálisan std::string received_data(data, data + size); throw std::runtime_error( "Failed to convert MessagePack to Packet: " + std::string(e.what()) + "\nRaw data size: " + std::to_string(size) + "\nRaw data: " + sd_gui_utils::toHex(data, size)); @@ -113,6 +111,7 @@ namespace sd_gui_utils { nlohmann_json_j["version"] = nlohmann_json_t.version; nlohmann_json_j["data_size"] = nlohmann_json_t.data_size; nlohmann_json_j["data"] = nlohmann_json_t.data; + nlohmann_json_j["server_id"] = nlohmann_json_t.server_id; } friend void from_json(const nlohmann ::json& nlohmann_json_j, Packet& nlohmann_json_t) { const Packet nlohmann_json_default_obj{}; @@ -121,6 +120,7 @@ namespace sd_gui_utils { nlohmann_json_t.version = nlohmann_json_j.value("version", nlohmann_json_default_obj.version); nlohmann_json_t.data_size = nlohmann_json_j.value("data_size", nlohmann_json_default_obj.data_size); nlohmann_json_t.data = nlohmann_json_j.value("data", nlohmann_json_default_obj.data); + nlohmann_json_t.server_id = nlohmann_json_j.value("server_id", nlohmann_json_default_obj.server_id); } }; } // namespace networks diff --git a/src/network/sdServer.h b/src/network/sdServer.h index a0a03f3..634a8eb 100644 --- a/src/network/sdServer.h +++ b/src/network/sdServer.h @@ -9,12 +9,13 @@ namespace sd_gui_utils { struct sdServer : public wxClientData { std::string name; // name is get from the over tcp std::string host; - bool authkey = false; // auth key is set in the secret - int port = 0; - std::atomic connected = false; // we check if the server is connected and not needed to store it into config - std::atomic enabled = {false}; - int server_id = -1; - std::atomic needToRun = {false}; + bool authkey = false; // auth key is set in the secret + int port = 0; + std::atomic connected{false}; + std::atomic enabled{false}; + std::atomic needToRun{false}; + std::string server_id = ""; + int internal_id = -1; std::string disconnect_reason; std::shared_ptr client = nullptr; bool IsOk() const { return !host.empty() && port > 0; } @@ -31,41 +32,44 @@ namespace sd_gui_utils { /// @brief Get the status of the server /// @return "connected" if enabled and connected, "disconnected" if enabled but not connected, "disabled" if not enabled wxString GetStatus() const { - return this->enabled ? this->connected ? "connected" : "disconnected" : "disabled"; + return this->enabled.load() == true ? this->connected.load() == true ? "connected" : "disconnected" : "disabled"; }; sdServer& operator=(const sdServer&) = default; sdServer(const std::string& host, int port) : host(host), port(port) {} // copy constructor sdServer(const sdServer& other) { - this->name = other.name; - this->host = other.host; - this->authkey = other.authkey; - this->port = other.port; - this->connected = other.connected.load(); - this->server_id = other.server_id; - this->enabled = other.enabled.load(); + this->name = other.name; + this->host = other.host; + this->authkey = other.authkey; + this->port = other.port; + this->connected.store(other.connected); + this->server_id = other.server_id; + this->internal_id = other.internal_id; + this->enabled.store(other.enabled.load()); }; sdServer() {} }; inline void to_json(nlohmann ::json& nlohmann_json_j, const sdServer& nlohmann_json_t) { - nlohmann_json_j["name"] = nlohmann_json_t.name; - nlohmann_json_j["host"] = nlohmann_json_t.host; - nlohmann_json_j["authkey"] = nlohmann_json_t.authkey; - nlohmann_json_j["port"] = nlohmann_json_t.port; - nlohmann_json_j["connected"] = nlohmann_json_t.connected.load(); - nlohmann_json_j["server_id"] = nlohmann_json_t.server_id; - nlohmann_json_j["enabled"] = nlohmann_json_t.enabled.load(); + nlohmann_json_j["name"] = nlohmann_json_t.name; + nlohmann_json_j["host"] = nlohmann_json_t.host; + nlohmann_json_j["authkey"] = nlohmann_json_t.authkey; + nlohmann_json_j["port"] = nlohmann_json_t.port; + nlohmann_json_j["connected"] = nlohmann_json_t.connected.load(); + nlohmann_json_j["server_id"] = nlohmann_json_t.server_id; + nlohmann_json_j["internal_id"] = nlohmann_json_t.internal_id; + nlohmann_json_j["enabled"] = nlohmann_json_t.enabled.load(); } inline void from_json(const nlohmann ::json& nlohmann_json_j, sdServer& nlohmann_json_t) { const sdServer nlohmann_json_default_obj{}; - nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); - nlohmann_json_t.host = nlohmann_json_j.value("host", nlohmann_json_default_obj.host); - nlohmann_json_t.authkey = nlohmann_json_j.value("authkey", nlohmann_json_default_obj.authkey); - nlohmann_json_t.port = nlohmann_json_j.value("port", nlohmann_json_default_obj.port); - nlohmann_json_t.connected = nlohmann_json_j.value("connected", false); - nlohmann_json_t.server_id = nlohmann_json_j.value("server_id", nlohmann_json_default_obj.server_id); - nlohmann_json_t.enabled = nlohmann_json_j.value("enabled", false); + nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name); + nlohmann_json_t.host = nlohmann_json_j.value("host", nlohmann_json_default_obj.host); + nlohmann_json_t.authkey = nlohmann_json_j.value("authkey", nlohmann_json_default_obj.authkey); + nlohmann_json_t.port = nlohmann_json_j.value("port", nlohmann_json_default_obj.port); + nlohmann_json_t.connected.store(nlohmann_json_j.value("connected", nlohmann_json_default_obj.connected.load())); + nlohmann_json_t.server_id = nlohmann_json_j.value("server_id", nlohmann_json_default_obj.server_id); + nlohmann_json_t.internal_id = nlohmann_json_j.value("internal_id", nlohmann_json_default_obj.internal_id); + nlohmann_json_t.enabled.store(nlohmann_json_j.value("enabled", nlohmann_json_default_obj.enabled.load())); } } // namespace sd_gui_utils #endif // _NETWORK_SD_SERVER_H_ \ No newline at end of file diff --git a/src/pch.h b/src/pch.h index d68846b..f5402a1 100644 --- a/src/pch.h +++ b/src/pch.h @@ -44,9 +44,12 @@ #include "ver.hpp" #include "helpers/DirTypes.h" +#include "helpers/sd.hpp" #include "sockets-cpp/TcpClient.h" #include "libs/json.hpp" +#include "helpers/QueueItem.h" #include "network/RemoteModelInfo.h" +#include "network/RemoteQueueJobItem.h" #include "network/packets.h" #include "libs/TcpClient.h" @@ -56,7 +59,7 @@ #include "helpers/cpuinfo_x86.hpp" #include "helpers/vcardinfo.hpp" #include "helpers/civitai.hpp" -#include "helpers/sd.hpp" + #include "libs/SharedMemoryManager.h" #include "libs/subprocess.h" diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp index a348beb..95941bb 100644 --- a/src/ui/MainWindow.cpp +++ b/src/ui/MainWindow.cpp @@ -241,7 +241,7 @@ mainUI::mainUI( wxWindow* parent, wxWindowID id, const wxString& title, const wx wxBoxSizer* bSizer79; bSizer79 = new wxBoxSizer( wxVERTICAL ); - m_joblist = new wxDataViewListCtrl( m_panel14, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_MULTIPLE|wxDV_ROW_LINES|wxDV_VERT_RULES ); + m_joblist = new wxDataViewListCtrl( m_panel14, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_HORIZ_RULES|wxDV_MULTIPLE|wxDV_ROW_LINES|wxDV_VERT_RULES ); m_joblist->SetExtraStyle( wxWS_EX_VALIDATE_RECURSIVELY ); m_dataViewListColumn32 = m_joblist->AppendTextColumn( _("Id"), wxDATAVIEW_CELL_INERT, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_HIDDEN|wxDATAVIEW_COL_RESIZABLE|wxDATAVIEW_COL_SORTABLE ); @@ -253,8 +253,7 @@ mainUI::mainUI( wxWindow* parent, wxWindowID id, const wxString& title, const wx m_dataViewListColumn32111111 = m_joblist->AppendProgressColumn( _("Progress"), wxDATAVIEW_CELL_INERT, 80, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); m_dataViewListColumn321111111 = m_joblist->AppendTextColumn( _("Speed"), wxDATAVIEW_CELL_INERT, 110, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); m_dataViewListColumn3211111111 = m_joblist->AppendTextColumn( _("Status"), wxDATAVIEW_CELL_ACTIVATABLE, 150, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); - m_dataViewListColumn32111111111 = m_joblist->AppendTextColumn( wxEmptyString, wxDATAVIEW_CELL_ACTIVATABLE, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_HIDDEN|wxDATAVIEW_COL_RESIZABLE ); - m_dataViewListColumn41 = m_joblist->AppendTextColumn( _("Server"), wxDATAVIEW_CELL_INERT, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); + m_dataViewListColumn32111111111 = m_joblist->AppendTextColumn( wxEmptyString, wxDATAVIEW_CELL_ACTIVATABLE, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); bSizer79->Add( m_joblist, 1, wxEXPAND, 5 ); @@ -1528,7 +1527,7 @@ mainUI::mainUI( wxWindow* parent, wxWindowID id, const wxString& title, const wx m_queue->SetBitmap( play_png_to_wx_bitmap() ); m_queue->Enable( false ); - bSizer1121->Add( m_queue, 0, wxALL, 5 ); + bSizer1121->Add( m_queue, 0, wxALL|wxEXPAND, 5 ); wxString m_serverChoices[] = { _("local") }; int m_serverNChoices = sizeof( m_serverChoices ) / sizeof( wxString ); @@ -1536,7 +1535,7 @@ mainUI::mainUI( wxWindow* parent, wxWindowID id, const wxString& title, const wx m_server->SetSelection( 0 ); m_server->Hide(); - fgSizer2->Add( m_server, 0, wxALL|wxEXPAND, 5 ); + bSizer1121->Add( m_server, 0, wxALL|wxEXPAND, 5 ); m_rightMainPanel->SetSizer( bSizer1121 ); @@ -2301,56 +2300,74 @@ Settings::Settings( wxWindow* parent, wxWindowID id, const wxString& title, cons m_panel18->Layout(); bSizer89->Fit( m_panel18 ); m_notebook1696->AddPage( m_panel18, _("CivitAi"), false ); - m_panel181 = new wxPanel( m_notebook1696, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - wxBoxSizer* bSizer891; - bSizer891 = new wxBoxSizer( wxVERTICAL ); - - m_serverList = new wxDataViewListCtrl( m_panel181, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_HORIZ_RULES|wxDV_MULTIPLE|wxDV_ROW_LINES|wxDV_SINGLE|wxDV_VERT_RULES ); - m_dataViewListColumn36 = m_serverList->AppendTextColumn( _("Host"), wxDATAVIEW_CELL_EDITABLE, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); - m_dataViewListColumn37 = m_serverList->AppendTextColumn( _("Port"), wxDATAVIEW_CELL_EDITABLE, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); - m_dataViewListColumn38 = m_serverList->AppendTextColumn( _("Auth key"), wxDATAVIEW_CELL_EDITABLE, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); + m_serversPanel = new wxPanel( m_notebook1696, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + wxBoxSizer* bSizer103; + bSizer103 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer105; + bSizer105 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer106; + bSizer106 = new wxBoxSizer( wxHORIZONTAL ); + + m_deleteServer = new wxButton( m_serversPanel, wxID_ANY, _("Delete"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer106->Add( m_deleteServer, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + + m_serverEnable = new wxToggleButton( m_serversPanel, wxID_ANY, _("Enable"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer106->Add( m_serverEnable, 0, wxALL, 5 ); + + + bSizer105->Add( bSizer106, 0, wxEXPAND, 5 ); + + m_serverList = new wxDataViewListCtrl( m_serversPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxDV_HORIZ_RULES|wxDV_ROW_LINES|wxDV_SINGLE|wxDV_VERT_RULES ); + m_dataViewListColumn36 = m_serverList->AppendTextColumn( _("Host"), wxDATAVIEW_CELL_INERT, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); + m_dataViewListColumn37 = m_serverList->AppendTextColumn( _("Port"), wxDATAVIEW_CELL_INERT, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); + m_dataViewListColumn38 = m_serverList->AppendTextColumn( _("Auth key"), wxDATAVIEW_CELL_INERT, 200, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); m_dataViewListColumn38->GetRenderer()->EnableEllipsize( wxELLIPSIZE_MIDDLE ); m_dataViewListColumn39 = m_serverList->AppendTextColumn( _("Status"), wxDATAVIEW_CELL_INERT, -1, static_cast(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); - bSizer891->Add( m_serverList, 1, wxALL|wxEXPAND, 5 ); - - wxBoxSizer* bSizer110; - bSizer110 = new wxBoxSizer( wxHORIZONTAL ); + bSizer105->Add( m_serverList, 1, wxALL|wxEXPAND, 5 ); - m_serverEnable = new wxToggleButton( m_panel181, wxID_ANY, _("Enable"), wxDefaultPosition, wxDefaultSize, 0 ); - m_serverEnable->Enable( false ); - bSizer110->Add( m_serverEnable, 0, wxALL, 5 ); + bSizer103->Add( bSizer105, 1, wxEXPAND, 5 ); - m_addServer = new wxButton( m_panel181, wxID_ANY, _("Add server"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer110->Add( m_addServer, 0, wxALL, 5 ); + wxBoxSizer* bSizer104; + bSizer104 = new wxBoxSizer( wxHORIZONTAL ); - m_staticText68 = new wxStaticText( m_panel181, wxID_ANY, _("Host/IP:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText68->Wrap( -1 ); - bSizer110->Add( m_staticText68, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + m_staticText70 = new wxStaticText( m_serversPanel, wxID_ANY, _("Host:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText70->Wrap( -1 ); + bSizer104->Add( m_staticText70, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_AddServerHost = new wxTextCtrl( m_panel181, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 160,-1 ), 0 ); - bSizer110->Add( m_AddServerHost, 0, wxALL, 5 ); + m_AddServerHost = new wxTextCtrl( m_serversPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + m_AddServerHost->SetMinSize( wxSize( 180,-1 ) ); - m_staticText69 = new wxStaticText( m_panel181, wxID_ANY, _("Port:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText69->Wrap( -1 ); - bSizer110->Add( m_staticText69, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); + bSizer104->Add( m_AddServerHost, 0, wxALL, 5 ); - m_AddServerPort = new wxTextCtrl( m_panel181, wxID_ANY, _("8191"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer110->Add( m_AddServerPort, 0, wxALL, 5 ); + m_staticText71 = new wxStaticText( m_serversPanel, wxID_ANY, _("Port:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText71->Wrap( -1 ); + bSizer104->Add( m_staticText71, 0, wxALL|wxALIGN_CENTER_VERTICAL, 5 ); - m_deleteServer = new wxButton( m_panel181, wxID_ANY, _("Delete"), wxDefaultPosition, wxDefaultSize, 0 ); - m_deleteServer->Enable( false ); + m_AddServerPort = new wxTextCtrl( m_serversPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + #ifdef __WXGTK__ + if ( !m_AddServerPort->HasFlag( wxTE_MULTILINE ) ) + { + m_AddServerPort->SetMaxLength( 5 ); + } + #else + m_AddServerPort->SetMaxLength( 5 ); + #endif + bSizer104->Add( m_AddServerPort, 0, wxALL, 5 ); - bSizer110->Add( m_deleteServer, 0, wxALL, 5 ); + m_button18 = new wxButton( m_serversPanel, wxID_ANY, _("Add server"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer104->Add( m_button18, 0, wxALL, 5 ); - bSizer891->Add( bSizer110, 0, 0, 5 ); + bSizer103->Add( bSizer104, 0, wxEXPAND, 5 ); - m_panel181->SetSizer( bSizer891 ); - m_panel181->Layout(); - bSizer891->Fit( m_panel181 ); - m_notebook1696->AddPage( m_panel181, _("Servers"), false ); + m_serversPanel->SetSizer( bSizer103 ); + m_serversPanel->Layout(); + bSizer103->Fit( m_serversPanel ); + m_notebook1696->AddPage( m_serversPanel, _("Servers"), false ); sizer2010->Add( m_notebook1696, 1, wxALL|wxEXPAND, 5 ); @@ -2399,14 +2416,14 @@ Settings::Settings( wxWindow* parent, wxWindowID id, const wxString& title, cons m_output_filename_format->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( Settings::OnOutputFilenameText ), NULL, this ); m_show_notifications->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( Settings::onShowNotificationCheck ), NULL, this ); m_bpButton15->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnCivitaiHelpButton ), NULL, this ); + m_deleteServer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnDeleteServer ), NULL, this ); + m_serverEnable->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( Settings::OnServerEnableToggle ), NULL, this ); m_serverList->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, wxDataViewEventHandler( Settings::OnServerListEditingDone ), NULL, this ); m_serverList->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, wxDataViewEventHandler( Settings::OnServerListEditingStarted ), NULL, this ); m_serverList->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, wxDataViewEventHandler( Settings::OnServerListStartEditing ), NULL, this ); m_serverList->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEventHandler( Settings::OnServerListItemValueChanged ), NULL, this ); m_serverList->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( Settings::OnServerListSelectionChanged ), NULL, this ); - m_serverEnable->Connect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( Settings::OnServerEnableToggle ), NULL, this ); - m_addServer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnAddServer ), NULL, this ); - m_deleteServer->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnDeleteServer ), NULL, this ); + m_button18->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnAddServer ), NULL, this ); m_save->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::onSave ), NULL, this ); } @@ -2445,14 +2462,14 @@ Settings::~Settings() m_output_filename_format->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( Settings::OnOutputFilenameText ), NULL, this ); m_show_notifications->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( Settings::onShowNotificationCheck ), NULL, this ); m_bpButton15->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnCivitaiHelpButton ), NULL, this ); + m_deleteServer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnDeleteServer ), NULL, this ); + m_serverEnable->Disconnect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( Settings::OnServerEnableToggle ), NULL, this ); m_serverList->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, wxDataViewEventHandler( Settings::OnServerListEditingDone ), NULL, this ); m_serverList->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, wxDataViewEventHandler( Settings::OnServerListEditingStarted ), NULL, this ); m_serverList->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING, wxDataViewEventHandler( Settings::OnServerListStartEditing ), NULL, this ); m_serverList->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED, wxDataViewEventHandler( Settings::OnServerListItemValueChanged ), NULL, this ); m_serverList->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( Settings::OnServerListSelectionChanged ), NULL, this ); - m_serverEnable->Disconnect( wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler( Settings::OnServerEnableToggle ), NULL, this ); - m_addServer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnAddServer ), NULL, this ); - m_deleteServer->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnDeleteServer ), NULL, this ); + m_button18->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::OnAddServer ), NULL, this ); m_save->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( Settings::onSave ), NULL, this ); } diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h index 494a775..32d5145 100644 --- a/src/ui/MainWindow.h +++ b/src/ui/MainWindow.h @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -91,7 +92,6 @@ class mainUI : public wxFrame wxDataViewColumn* m_dataViewListColumn321111111; wxDataViewColumn* m_dataViewListColumn3211111111; wxDataViewColumn* m_dataViewListColumn32111111111; - wxDataViewColumn* m_dataViewListColumn41; wxScrolledWindow* m_scrolledWindow41; wxStaticBitmap* m_bitmap6; wxStaticText* m_staticText64; @@ -455,19 +455,19 @@ class Settings : public wxFrame wxStaticText* m_staticText42; wxTextCtrl* m_civitai_api_key; wxBitmapButton* m_bpButton15; - wxPanel* m_panel181; + wxPanel* m_serversPanel; + wxButton* m_deleteServer; + wxToggleButton* m_serverEnable; wxDataViewListCtrl* m_serverList; wxDataViewColumn* m_dataViewListColumn36; wxDataViewColumn* m_dataViewListColumn37; wxDataViewColumn* m_dataViewListColumn38; wxDataViewColumn* m_dataViewListColumn39; - wxToggleButton* m_serverEnable; - wxButton* m_addServer; - wxStaticText* m_staticText68; + wxStaticText* m_staticText70; wxTextCtrl* m_AddServerHost; - wxStaticText* m_staticText69; + wxStaticText* m_staticText71; wxTextCtrl* m_AddServerPort; - wxButton* m_deleteServer; + wxButton* m_button18; wxButton* m_save; // Virtual event handlers, override them in your derived class @@ -479,14 +479,14 @@ class Settings : public wxFrame virtual void OnOutputFilenameText( wxCommandEvent& event ) { event.Skip(); } virtual void onShowNotificationCheck( wxCommandEvent& event ) { event.Skip(); } virtual void OnCivitaiHelpButton( wxCommandEvent& event ) { event.Skip(); } + virtual void OnDeleteServer( wxCommandEvent& event ) { event.Skip(); } + virtual void OnServerEnableToggle( wxCommandEvent& event ) { event.Skip(); } virtual void OnServerListEditingDone( wxDataViewEvent& event ) { event.Skip(); } virtual void OnServerListEditingStarted( wxDataViewEvent& event ) { event.Skip(); } virtual void OnServerListStartEditing( wxDataViewEvent& event ) { event.Skip(); } virtual void OnServerListItemValueChanged( wxDataViewEvent& event ) { event.Skip(); } virtual void OnServerListSelectionChanged( wxDataViewEvent& event ) { event.Skip(); } - virtual void OnServerEnableToggle( wxCommandEvent& event ) { event.Skip(); } virtual void OnAddServer( wxCommandEvent& event ) { event.Skip(); } - virtual void OnDeleteServer( wxCommandEvent& event ) { event.Skip(); } virtual void onSave( wxCommandEvent& event ) { event.Skip(); } diff --git a/src/ui/MainWindowDesktopWidget.cpp b/src/ui/MainWindowDesktopWidget.cpp index 79b7248..69c38c7 100644 --- a/src/ui/MainWindowDesktopWidget.cpp +++ b/src/ui/MainWindowDesktopWidget.cpp @@ -46,7 +46,7 @@ void MainWindowDesktopWidget::OnThreadMessage(wxThreadEvent& e) { sd_gui_utils::ThreadEvents threadEvent = (sd_gui_utils::ThreadEvents)std::stoi(token); if (threadEvent == sd_gui_utils::ThreadEvents::QUEUE) { - QM::QueueEvents event = (QM::QueueEvents)std::stoi(content); + QueueEvents event = (QueueEvents)std::stoi(content); std::shared_ptr item = e.GetPayload>(); @@ -54,7 +54,7 @@ void MainWindowDesktopWidget::OnThreadMessage(wxThreadEvent& e) { size_t stepsDone = 0; // item->stats.time_per_step.size(); wxString steps = wxEmptyString; - if (event == QM::QueueEvents::ITEM_MODEL_HASH_START || event == QM::QueueEvents::ITEM_MODEL_HASH_UPDATE) { + if (event == QueueEvents::ITEM_MODEL_HASH_START || event == QueueEvents::ITEM_MODEL_HASH_UPDATE) { stepsSum = item->hash_fullsize; stepsDone = item->hash_progress_size; @@ -68,7 +68,7 @@ void MainWindowDesktopWidget::OnThreadMessage(wxThreadEvent& e) { wxFileName::GetHumanReadableSize((wxULongLong)stepsDone), wxFileName::GetHumanReadableSize((wxULongLong)stepsSum)); } - if (event == QM::QueueEvents::ITEM_MODEL_HASH_DONE || event == QM::QueueEvents::ITEM_UPDATED || event == QM::QueueEvents::ITEM_FINISHED) { + if (event == QueueEvents::ITEM_MODEL_HASH_DONE || event == QueueEvents::ITEM_UPDATED || event == QueueEvents::ITEM_FINISHED) { stepsSum = (size_t)(item->params.sample_steps * item->params.batch_count); stepsDone = item->stats.time_per_step.size(); @@ -87,7 +87,7 @@ void MainWindowDesktopWidget::OnThreadMessage(wxThreadEvent& e) { this->m_currentStatus->SetLabel(wxString::Format(_("Current job: %s %s %s"), modes_str[item->mode], - wxGetTranslation(QM::QueueStatus_GUI_str.at(item->status)), + wxGetTranslation(QueueStatus_GUI_str.at(item->status)), steps)); } } diff --git a/src/ui/MainWindowSettings.cpp b/src/ui/MainWindowSettings.cpp index a289665..2fe2b41 100644 --- a/src/ui/MainWindowSettings.cpp +++ b/src/ui/MainWindowSettings.cpp @@ -124,7 +124,7 @@ void MainWindowSettings::onSave(wxCommandEvent& event) { this->config->SetPath(wxString::Format("Server%zu", i)); this->config->Write("Host", wxString::FromUTF8Unchecked(this->cfg->servers[i]->host)); this->config->Write("Port", this->cfg->servers[i]->port); - this->config->Write("Id", this->cfg->servers[i]->server_id); + this->config->Write("InternalId", this->cfg->servers[i]->internal_id); this->config->Write("Enabled", this->cfg->servers[i]->enabled.load()); this->config->SetPath(".."); } @@ -246,10 +246,10 @@ void MainWindowSettings::AddRemoteServerToList(sd_gui_utils::sdServer* server) { values.push_back(wxGetTranslation((server->GetStatus()))); // get last row auto row = this->m_serverList->GetItemCount(); - if (server->server_id == -1) { - server->server_id = row; + if (server->internal_id == -1) { + server->internal_id = row; } - this->m_serverList->InsertItem(row, values, row); + this->m_serverList->InsertItem(row, values, server->internal_id); values.clear(); this->checkboxUpdate = false; } @@ -262,10 +262,10 @@ void MainWindowSettings::OnDeleteServer(wxCommandEvent& event) { } for (const auto item : selections) { - auto server_id = static_cast(this->m_serverList->GetItemData(item)); - auto row = this->m_serverList->ItemToRow(item); + auto internal_id = static_cast(this->m_serverList->GetItemData(item)); + auto row = this->m_serverList->ItemToRow(item); this->m_serverList->DeleteItem(row); - this->cfg->RemoveTcpServer(server_id); + this->cfg->RemoveTcpServer(internal_id); } } @@ -307,12 +307,12 @@ void MainWindowSettings::OnServerListEditingDone(wxDataViewEvent& event) { if (value.empty()) { return; } - auto col = event.GetColumn(); - auto item = event.GetItem(); - auto row = this->m_serverList->ItemToRow(item); - auto server_id = static_cast(this->m_serverList->GetItemData(item)); + auto col = event.GetColumn(); + auto item = event.GetItem(); + auto row = this->m_serverList->ItemToRow(item); + int internal_id = static_cast(this->m_serverList->GetItemData(item)); - auto srv = this->cfg->GetTcpServer(server_id); + auto srv = this->cfg->GetTcpServer(internal_id); if (srv == nullptr) { return; } @@ -321,7 +321,7 @@ void MainWindowSettings::OnServerListEditingDone(wxDataViewEvent& event) { wxMessageDialog(this, _("Server already exists")).ShowModal(); this->m_serverList->SetValue(wxString::FromUTF8Unchecked(srv->host), row, col); } - this->cfg->ServerChangeHost(server_id, value.utf8_string()); + this->cfg->ServerChangeHost(internal_id, value.utf8_string()); } if (col == ServerListColumns::SERVER_LIST_COLUMN_AUTH_KEY) { @@ -351,15 +351,15 @@ void MainWindowSettings::OnServerListEditingDone(wxDataViewEvent& event) { if (col == ServerListColumns::SERVER_LIST_COLUMN_PORT) { auto oldPort = srv->port; if (value.ToInt(&srv->port) == false) { - this->cfg->ServerChangePort(server_id, oldPort); + this->cfg->ServerChangePort(internal_id, oldPort); this->m_serverList->SetValue(wxString::Format(wxT("%d"), srv->port), row, col); } if (srv->port < 1 || srv->port > 65535) { - this->cfg->ServerChangePort(server_id, oldPort); + this->cfg->ServerChangePort(internal_id, oldPort); this->m_serverList->SetValue(wxString::Format(wxT("%d"), srv->port), row, col); } for (const auto& server : this->cfg->servers) { - if (server->host == value.utf8_string() && server->port == srv->port && server->server_id != server_id) { + if (server->host == value.utf8_string() && server->port == srv->port && server->internal_id != internal_id) { wxMessageDialog(this, _("Server already exists")).ShowModal(); this->m_serverList->SetValue(wxString::FromUTF8Unchecked(srv->host), row, col); return; @@ -377,10 +377,10 @@ void MainWindowSettings::OnServerListSelectionChanged(wxDataViewEvent& event) { if (this->m_serverList->GetSelectedItemsCount() == 1) { this->m_serverEnable->Enable(); - auto item = event.GetItem(); - auto server_id = static_cast(this->m_serverList->GetItemData(item)); + auto item = event.GetItem(); + auto internal_id = static_cast(this->m_serverList->GetItemData(item)); for (auto& srv : this->cfg->ListRemoteServers()) { - if (srv->server_id == server_id) { + if (srv->internal_id == internal_id) { this->m_serverEnable->SetValue(srv->enabled); this->m_serverEnable->SetLabel(srv->enabled ? _("Disable") : _("Enable")); break; @@ -394,15 +394,15 @@ void MainWindowSettings::OnServerEnableToggle(wxCommandEvent& event) { auto item = this->m_serverList->GetSelection(); auto row = this->m_serverList->ItemToRow(item); if (item.IsOk()) { - auto server_id = static_cast(this->m_serverList->GetItemData(item)); + auto internal_id = static_cast(this->m_serverList->GetItemData(item)); for (auto& srv : this->cfg->servers) { - if (srv->server_id == server_id) { + if (srv->internal_id == internal_id) { if ((srv->authkey == false || srv->host.empty() || srv->port == 0) && this->m_serverEnable->GetValue() == true) { this->m_serverEnable->SetValue(srv->enabled); wxMessageDialog(this, _("Please fill all required fields before enabling the server")).ShowModal(); return; } - this->cfg->ServerEnable(server_id, this->m_serverEnable->GetValue()); + this->cfg->ServerEnable(internal_id, this->m_serverEnable->GetValue()); ChangeRemoteServer(srv->GetStatus(), ServerListColumns::SERVER_LIST_COLUMN_STATUS, row); this->m_serverEnable->SetLabel(srv->enabled ? _("Disable") : _("Enable")); break; diff --git a/src/ui/MainWindowUI.cpp b/src/ui/MainWindowUI.cpp index 53f9f91..672cd75 100644 --- a/src/ui/MainWindowUI.cpp +++ b/src/ui/MainWindowUI.cpp @@ -128,8 +128,9 @@ MainWindowUI::MainWindowUI(wxWindow* parent, const std::string dllName, const st break; } - if (tries > 5) { + if (tries > 5 || server->needToRun == false) { server->needToRun = false; + break; } tries++; std::this_thread::sleep_for(std::chrono::seconds(5 * tries)); @@ -190,7 +191,7 @@ MainWindowUI::MainWindowUI(wxWindow* parent, const std::string dllName, const st this->extProcessParam = dllName + ".so"; #endif - this->extProcessRunning = false; + this->extProcessRunning.store(false); // start process from the thread @@ -207,7 +208,7 @@ MainWindowUI::MainWindowUI(wxWindow* parent, const std::string dllName, const st this->Destroy(); return; } - this->extProcessNeedToRun = true; + this->extProcessNeedToRun.store(true); this->processCheckThread = std::make_shared(&MainWindowUI::ProcessCheckThread, this); this->processHandleOutput = std::make_shared(&MainWindowUI::ProcessOutputThread, this); } @@ -313,7 +314,7 @@ void MainWindowUI::OnCivitAitButton(wxCommandEvent& event) { void MainWindowUI::OnStopBackgroundProcess(wxCommandEvent& event) { if (this->subprocess != nullptr && // we have subprocess subprocess_alive(this->subprocess) != 0 && // is running - this->extProcessNeedToRun && // need to run, eg. not in stopping state + this->extProcessNeedToRun.load() && // need to run, eg. not in stopping state this->qmanager->GetCurrentItem() == nullptr) { this->m_stop_background_process->Disable(); subprocess_terminate(this->subprocess); @@ -611,10 +612,10 @@ void MainWindowUI::OnJobListItemKeyDown(wxKeyEvent& event) { int id = store->GetItemData(item); auto qitem = this->qmanager->GetItemPtr(id); - if (qitem->status == QM::QueueStatus::RUNNING || - qitem->status == QM::QueueStatus::MODEL_LOADING || - qitem->status == QM::QueueStatus::HASHING || - qitem->status == QM::QueueStatus::HASHING_DONE) { + if (qitem->status == QueueStatus::RUNNING || + qitem->status == QueueStatus::MODEL_LOADING || + qitem->status == QueueStatus::HASHING || + qitem->status == QueueStatus::HASHING_DONE) { continue; } if (this->qmanager->DeleteJob(id) && row != wxNOT_FOUND) { @@ -651,8 +652,51 @@ void MainWindowUI::onContextMenu(wxDataViewEvent& event) { return; } wxMenu* menu = new wxMenu(); + if (this->m_joblist->GetSelectedItemsCount() > 1) { + wxDataViewItemArray selections; + this->m_joblist->GetSelections(selections); + wxDataViewListStore* store = this->m_joblist->GetStore(); + std::vector items_to_del; + std::vector rows_to_del; + for (const auto item : selections) { + int id = store->GetItemData(item); + auto qitem = this->qmanager->GetItemPtr(id); + if (qitem == nullptr) { + continue; + } + if (qitem->status == QueueStatus::RUNNING || + qitem->status == QueueStatus::MODEL_LOADING || + qitem->status == QueueStatus::HASHING || + qitem->status == QueueStatus::HASHING_DONE) { + continue; + } + rows_to_del.emplace_back(item); + items_to_del.emplace_back(qitem->id); + } + if (rows_to_del.size() != items_to_del.size()) { + this->writeLog(_("Error: rows_to_del.size() != items_to_del.size()")); + items_to_del.clear(); + rows_to_del.clear(); + } + if (items_to_del.size() > 0) { + menu->Append(99, wxString::Format(_("Delete %d items"), (int)rows_to_del.size())); + // menu->Enable(99, false); + menu->Bind(wxEVT_COMMAND_MENU_SELECTED, [this, rows_to_del, items_to_del](wxCommandEvent& event) { + // unselect all before delete + this->m_joblist->SetSelections(wxDataViewItemArray()); + for (int i = 0; i < items_to_del.size(); i++) { + this->qmanager->DeleteJob(items_to_del[i]); + auto row = this->m_joblist->ItemToRow(rows_to_del[i]); + if (row != wxNOT_FOUND) { + this->m_joblist->DeleteItem(row); + } + } + this->m_static_number_of_jobs->SetLabel(wxString::Format(_("Number of jobs: %d"), this->m_joblist->GetItemCount())); + }); + } - auto item = event.GetItem(); + } else { + auto item = event.GetItem(); wxDataViewListStore* store = this->m_joblist->GetStore(); @@ -663,10 +707,10 @@ void MainWindowUI::onContextMenu(wxDataViewEvent& event) { return; } - if (qitem->mode != QM::GenerationMode::CONVERT) { + if (qitem->mode != SDMode::CONVERT) { menu->Append(1, _("Requeue")); - if (qitem->mode == QM::GenerationMode::IMG2IMG || - qitem->mode == QM::GenerationMode::UPSCALE) { + if (qitem->mode == SDMode::IMG2IMG || + qitem->mode == SDMode::UPSCALE) { if (!std::filesystem::exists(qitem->initial_image)) { menu->Enable(1, false); } @@ -679,8 +723,8 @@ void MainWindowUI::onContextMenu(wxDataViewEvent& event) { menu->Enable(1, false); } - if (qitem->mode != QM::GenerationMode::UPSCALE && - qitem->mode != QM::GenerationMode::CONVERT) { + if (qitem->mode != SDMode::UPSCALE && + qitem->mode != SDMode::CONVERT) { menu->Append(2, _("Load parameters")); menu->Append(3, _("Copy prompts to text2img")); menu->Append(4, _("Copy prompts to img2img")); @@ -691,31 +735,31 @@ void MainWindowUI::onContextMenu(wxDataViewEvent& event) { menu->Append(7, _("Send the last image to the img2img tab")); } } - if (qitem->mode == QM::GenerationMode::UPSCALE) { + if (qitem->mode == SDMode::UPSCALE) { if (qitem->images.size() > 0) { menu->Append(6, wxString::Format(_("Upscale again"))); } } - if (qitem->status == QM::QueueStatus::PAUSED || - qitem->status == QM::QueueStatus::PENDING) { + if (qitem->status == QueueStatus::PAUSED || + qitem->status == QueueStatus::PENDING) { menu->AppendSeparator(); - menu->Append(8, qitem->status == QM::QueueStatus::PENDING ? _("Pause") : _("Resume")); + menu->Append(8, qitem->status == QueueStatus::PENDING ? _("Pause") : _("Resume")); } menu->AppendSeparator(); menu->Append(99, _("Delete")); menu->Enable(99, false); - if (qitem->status == QM::QueueStatus::RUNNING || - qitem->status == QM::QueueStatus::HASHING) { + if (qitem->status == QueueStatus::RUNNING || + qitem->status == QueueStatus::HASHING) { menu->Enable(1, false); } - if (qitem->status == QM::QueueStatus::PENDING || - qitem->status == QM::QueueStatus::PAUSED || - qitem->status == QM::QueueStatus::FAILED || - qitem->status == QM::QueueStatus::DONE) { + if (qitem->status == QueueStatus::PENDING || + qitem->status == QueueStatus::PAUSED || + qitem->status == QueueStatus::FAILED || + qitem->status == QueueStatus::DONE) { menu->Enable(99, true); } menu->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainWindowUI::OnPopupClick, this); @@ -834,12 +878,12 @@ void MainWindowUI::OnDataModelTreeContextMenu(wxTreeListEvent& event) { // do not delete the model if it is used in a job for (const auto& qitem : this->qmanager->getList()) { if (qitem.second->params.model_path == modelInfo->path && - (qitem.second->status == QM::QueueStatus::MODEL_LOADING || - qitem.second->status == QM::QueueStatus::HASHING || - qitem.second->status == QM::QueueStatus::HASHING_DONE || - qitem.second->status == QM::QueueStatus::PAUSED || - qitem.second->status == QM::QueueStatus::PENDING || - qitem.second->status == QM::QueueStatus::RUNNING)) { + (qitem.second->status == QueueStatus::MODEL_LOADING || + qitem.second->status == QueueStatus::HASHING || + qitem.second->status == QueueStatus::HASHING_DONE || + qitem.second->status == QueueStatus::PAUSED || + qitem.second->status == QueueStatus::PENDING || + qitem.second->status == QueueStatus::RUNNING)) { menu->Enable(310, false); break; } @@ -971,17 +1015,17 @@ void MainWindowUI::onGenerate(wxCommandEvent& event) { this->CheckQueueButton(); - auto type = QM::GenerationMode::TXT2IMG; + auto type = SDMode::TXT2IMG; int pageId = this->m_notebook1302->GetSelection(); switch (pageId) { case 1: - type = QM::GenerationMode::TXT2IMG; + type = SDMode::TXT2IMG; break; case 2: - type = QM::GenerationMode::IMG2IMG; + type = SDMode::IMG2IMG; break; case 3: - type = QM::GenerationMode::UPSCALE; + type = SDMode::UPSCALE; break; default: return; @@ -999,7 +1043,7 @@ void MainWindowUI::onGenerate(wxCommandEvent& event) { auto sClientData = dynamic_cast(this->m_scheduler->GetClientObject(this->m_scheduler->GetSelection())); auto smClientData = dynamic_cast(this->m_sampler->GetClientObject(this->m_sampler->GetSelection())); - if (type == QM::GenerationMode::UPSCALE) { + if (type == SDMode::UPSCALE) { auto esrganModel = static_cast(this->m_upscaler_model->GetClientData(this->m_upscaler_model->GetSelection())); if (esrganModel == nullptr) { wxLogError(_("No upscaler model found!")); @@ -1084,7 +1128,7 @@ void MainWindowUI::onGenerate(wxCommandEvent& event) { item->model = this->m_model->GetStringSelection().utf8_string(); - if (type == QM::GenerationMode::TXT2IMG || type == QM::GenerationMode::IMG2IMG) { + if (type == SDMode::TXT2IMG || type == SDMode::IMG2IMG) { if (diffusionModel.empty() == false) { item->model = wxFileName(item->params.diffusion_model_path).GetFullName(); } @@ -1146,7 +1190,7 @@ void MainWindowUI::onGenerate(wxCommandEvent& event) { item->params.clip_on_cpu = this->clipOnCpu->GetValue(); item->params.diffusion_flash_attn = this->diffusionFlashAttn->GetValue(); - if (type == QM::GenerationMode::TXT2IMG) { + if (type == SDMode::TXT2IMG) { item->params.prompt = this->m_prompt->GetValue().utf8_string(); item->params.negative_prompt = this->m_neg_prompt->GetValue().utf8_string(); @@ -1183,7 +1227,7 @@ void MainWindowUI::onGenerate(wxCommandEvent& event) { } } - if (type == QM::GenerationMode::IMG2IMG) { + if (type == SDMode::IMG2IMG) { item->params.prompt = this->m_prompt2->GetValue().utf8_string(); item->params.negative_prompt = this->m_neg_prompt2->GetValue().utf8_string(); wxImage originalImage = this->inpaintHelper->GetOriginalImage(); @@ -1239,15 +1283,15 @@ void MainWindowUI::onGenerate(wxCommandEvent& event) { item->params.clip_skip = this->m_clip_skip->GetValue(); item->params.sample_steps = this->m_steps->GetValue(); - if (type == QM::GenerationMode::TXT2IMG) { + if (type == SDMode::TXT2IMG) { item->params.control_strength = this->m_controlnetStrength->GetValue(); } - if (type == QM::GenerationMode::IMG2IMG) { + if (type == SDMode::IMG2IMG) { item->params.strength = this->m_strength->GetValue(); } - if (this->m_controlnetModels->GetCurrentSelection() > 0 && type == QM::GenerationMode::TXT2IMG) { + if (this->m_controlnetModels->GetCurrentSelection() > 0 && type == SDMode::TXT2IMG) { if (diffusionModel.empty() == false) { this->writeLog(wxString::Format(_("Skipping controlnet with diffusion model: %s"), diffusionModel.c_str())); } else { @@ -1275,7 +1319,7 @@ void MainWindowUI::onGenerate(wxCommandEvent& event) { item->mode = type; - if (type == QM::GenerationMode::IMG2IMG) { + if (type == SDMode::IMG2IMG) { if (this->m_img2imgOpen->GetPath().empty() == false && wxFileName(this->m_img2imgOpen->GetPath()).Exists() && item->initial_image.empty()) { item->initial_image = this->m_img2imgOpen->GetPath().utf8_string(); // if (this->mapp->cfg->save_all_image) { @@ -1299,7 +1343,7 @@ void MainWindowUI::onGenerate(wxCommandEvent& event) { this->mapp->config->Write("/last_neg_prompt", this->m_neg_prompt->GetValue()); this->mapp->config->Write("/last_model", this->m_model->GetStringSelection()); this->mapp->config->Write("/last_diffusion_model", this->m_filePickerDiffusionModel->GetPath()); - this->mapp->config->Write("/last_generation_mode", wxString::FromUTF8Unchecked(QM::GenerationMode_str.at(type))); + this->mapp->config->Write("/last_generation_mode", wxString::FromUTF8Unchecked(GenerationMode_str.at(type))); this->mapp->config->Flush(true); } @@ -1676,10 +1720,10 @@ void MainWindowUI::onSavePreset(wxCommandEvent& event) { preset.name = preset_name.utf8_string(); preset.type = this->m_type->GetStringSelection().utf8_string(); if (this->m_notebook1302->GetSelection() == (int)sd_gui_utils::GuiMainPanels::PANEL_TEXT2IMG) { - preset.mode = modes_str[QM::GenerationMode::TXT2IMG]; + preset.mode = modes_str[SDMode::TXT2IMG]; } if (this->m_notebook1302->GetSelection() == (int)sd_gui_utils::GuiMainPanels::PANEL_IMG2IMG) { - preset.mode = modes_str[QM::GenerationMode::IMG2IMG]; + preset.mode = modes_str[SDMode::IMG2IMG]; } nlohmann::json j(preset); @@ -1759,7 +1803,7 @@ void MainWindowUI::ChangeGuiFromQueueItem(QM::QueueItem item) { this->m_cfg->SetValue(item.params.cfg_scale); this->m_batch_count->SetValue(item.params.batch_count); - if (item.mode == QM::GenerationMode::TXT2IMG) { + if (item.mode == SDMode::TXT2IMG) { auto currentSkipLayers = sd_gui_utils::splitStr2int(this->m_skipLayers->GetValue().utf8_string(), ','); if (currentSkipLayers.size() != item.params.skip_layers.size()) { wxString newSkipLayers; @@ -1790,7 +1834,7 @@ void MainWindowUI::ChangeGuiFromQueueItem(QM::QueueItem item) { this->slgScale->SetValue(item.params.slg_scale); } } - if (item.mode == QM::GenerationMode::IMG2IMG) { + if (item.mode == SDMode::IMG2IMG) { for (const auto& img : item.images) { if (wxFileExists(wxString::FromUTF8Unchecked(img.pathname)) == false) { continue; @@ -1926,7 +1970,16 @@ void MainWindowUI::UpdateModelInfoDetailsFromModelList(sd_gui_utils::ModelFileIn } data.push_back(wxVariant(_("File name"))); - data.push_back(wxVariant(wxString::Format("%s", modelinfo->path))); + + if (modelinfo->server_id > -1) { + wxFileName fname(modelinfo->path); + data.push_back(wxVariant(wxString::Format("%s", fname.GetName()))); + } else { + wxString p = wxString::Format("%s", modelinfo->path).SubString(65,modelinfo->path.length()); + wxFileName fname(p); + data.push_back(wxVariant(wxString::Format("%s", fname.GetName()))); + } + this->m_model_details->AppendItem(data); data.clear(); @@ -2120,7 +2173,7 @@ void MainWindowUI::OnQueueItemManagerItemAdded(std::shared_ptr it data.push_back(wxVariant(modes_str[item->mode])); data.push_back(wxVariant(item->model)); - if (item->mode == QM::GenerationMode::UPSCALE || item->mode == QM::GenerationMode::CONVERT) { + if (item->mode == SDMode::UPSCALE || item->mode == SDMode::CONVERT) { data.push_back(wxVariant("--")); // sample method data.push_back(wxVariant("--")); // seed } else { @@ -2128,15 +2181,15 @@ void MainWindowUI::OnQueueItemManagerItemAdded(std::shared_ptr it data.push_back(wxVariant(std::to_string(item->params.seed))); } - data.push_back(item->status == QM::QueueStatus::DONE ? 100 : 1); // progressbar + data.push_back(item->status == QueueStatus::DONE ? 100 : 1); // progressbar // calculate the item average speed frrom item->stats in step / seconds or seconds / step wxString speed = wxString::Format(item->stats.time_avg > 1.0f ? "%.2fs/it %d/%d" : "%.2fit/s %d/%d", item->stats.time_avg > 1.0f || item->stats.time_avg == 0 ? item->stats.time_avg : (1.0f / item->stats.time_avg), item->step, item->steps); - data.push_back(wxString(speed)); // speed - data.push_back(wxVariant(wxGetTranslation(QM::QueueStatus_GUI_str.at(item->status)))); // status + data.push_back(wxString(speed)); // speed + data.push_back(wxVariant(wxGetTranslation(QueueStatus_GUI_str.at(item->status)))); // status data.push_back(wxVariant(item->status_message)); - if (item->server > -1) { + if (item->server.empty() == false) { auto srv = this->mapp->cfg->GetTcpServer(item->server); if (srv != nullptr) { data.push_back(wxVariant(srv->GetName())); @@ -2197,34 +2250,29 @@ MainWindowUI::~MainWindowUI() { if (this->widget != nullptr) { this->widget->Destroy(); } - this->extProcessNeedToRun = false; - - if (this->processCheckThread != nullptr && this->processCheckThread->joinable()) { - this->processCheckThread->join(); - } + this->extProcessNeedToRun.store(false); if (this->disableExternalProcessHandling == false && this->subprocess != nullptr && subprocess_alive(this->subprocess) != 0) { - std::cout << "Terminating processs" << std::endl; + if (this->processCheckThread != nullptr && this->processCheckThread->joinable()) { + this->processCheckThread->join(); + } int result = 0; result = subprocess_terminate(subprocess); if (0 != result) { std::cerr << "Can not terminate extprocess" << std::endl; } - - std::cout << "Join processs" << std::endl; result = subprocess_join(subprocess, NULL); if (0 != result) { std::cerr << "Can not join extprocess" << std::endl; } - - std::cout << "Destroy processs" << std::endl; result = subprocess_destroy(subprocess); if (0 != result) { std::cerr << "Can not destroy extprocess" << std::endl; } - } - if (this->processHandleOutput != nullptr && this->processHandleOutput->joinable()) { - this->processHandleOutput->join(); + + if (this->processHandleOutput != nullptr && this->processHandleOutput->joinable()) { + this->processHandleOutput->join(); + } } for (auto it = this->tcpClients.begin(); it != this->tcpClients.end(); it++) { @@ -2479,38 +2527,29 @@ void MainWindowUI::OnModelListPopUpClick(wxCommandEvent& evt) { void MainWindowUI::OnPopupClick(wxCommandEvent& evt) { auto tu = evt.GetId(); - if (tu == 99) { - this->m_joblist->GetSelections(sel); - for (auto& item : sel) { - int id = store->GetItemData(item); - std::shared_ptr qitem = this->qmanager->GetItemPtr(id); - if (this->qmanager->DeleteJob(qitem->id)) { - store->DeleteItem(this->m_joblist->ItemToRow(item)); - this->m_static_number_of_jobs->SetLabel(wxString::Format(_("Number of jobs: %d"), this->m_joblist->GetItemCount())); - } - } - return; - } // 100 for queueitem list table if (tu < 100) { wxDataViewListStore* store = this->m_joblist->GetStore(); - auto currentItem = this->m_joblist->GetCurrentItem(); auto currentRow = this->m_joblist->GetSelectedRow(); if (currentRow == wxNOT_FOUND) { return; } + auto currentItem = this->m_joblist->RowToItem(currentRow); + if (currentItem.IsOk() == false) { + return; + } int id = store->GetItemData(currentItem); std::shared_ptr qitem = this->qmanager->GetItemPtr(id); - /* - 1 Copy and queue - 2 copy to text2img - 3 copy prompts to text2image - 4 copy prompts to img2img - 5 Details - 99 delete - */ + /* + 1 Copy and queue + 2 copy to text2img + 3 copy prompts to text2image + 4 copy prompts to img2img + 5 Details + 99 delete + */ switch (tu) { case 1: @@ -2544,15 +2583,15 @@ void MainWindowUI::OnPopupClick(wxCommandEvent& evt) { this->onUpscaleImageOpen(wxString::FromUTF8Unchecked(qitem->images.back().pathname)); this->m_notebook1302->SetSelection(+sd_gui_utils::GuiMainPanels::PANEL_UPSCALER); // switch to the upscaler } break; - case 7: { + case 7: { this->onimg2ImgImageOpen(wxString::FromUTF8Unchecked(qitem->images.back().pathname), true); } break; case 8: { - if (qitem->status == QM::QueueStatus::PAUSED) { + if (qitem->status == QueueStatus::PAUSED) { this->qmanager->UnPauseItem(qitem); return; } - if (qitem->status == QM::QueueStatus::PENDING) { + if (qitem->status == QueueStatus::PENDING) { this->qmanager->PauseItem(qitem); return; } @@ -2589,7 +2628,7 @@ void MainWindowUI::loadTaesdList() { wxString MainWindowUI::paramsToImageComment(const QM::QueueItem& myItem) { // TODO: copy original image's exif... - if (myItem.mode == QM::GenerationMode::UPSCALE) { + if (myItem.mode == SDMode::UPSCALE) { return ""; } if (myItem.params.model_path.empty() && myItem.params.diffusion_model_path.empty()) { @@ -2699,7 +2738,7 @@ std::string MainWindowUI::paramsToImageCommentJson(QM::QueueItem myItem, sd_gui_ } template -inline void MainWindowUI::SendThreadEvent(wxEvtHandler* eventHandler, QM::QueueEvents eventType, const T& payload, std::string text) { +inline void MainWindowUI::SendThreadEvent(wxEvtHandler* eventHandler, QueueEvents eventType, const T& payload, std::string text) { wxThreadEvent* e = new wxThreadEvent(); e->SetString(wxString::Format("%d:%d:%s", (int)sd_gui_utils::ThreadEvents::QUEUE, (int)eventType, text)); e->SetPayload(payload); @@ -3246,8 +3285,8 @@ void MainWindowUI::StartGeneration(std::shared_ptr myJob) { if (subprocess_alive(this->subprocess) == 0) { wxMessageDialog errorDialog(NULL, wxT("An error occurred while starting the generation process."), wxT("Error"), wxOK | wxICON_ERROR); myJob->status_message = _("Error accessing to the background process. Please try again."); - // this->qmanager->SendEventToMainWindow(QM::QueueEvents::ITEM_FAILED, myJob); - this->qmanager->SetStatus(QM::QueueStatus::FAILED, myJob); + // this->qmanager->SendEventToMainWindow(QueueEvents::ITEM_FAILED, myJob); + this->qmanager->SetStatus(QueueStatus::FAILED, myJob); errorDialog.ShowModal(); return; } @@ -3255,12 +3294,12 @@ void MainWindowUI::StartGeneration(std::shared_ptr myJob) { try { myJob->updated_at = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); - this->qmanager->SetStatus(QM::QueueStatus::PENDING, myJob); + this->qmanager->SetStatus(QueueStatus::PENDING, myJob); nlohmann::json j = *myJob; std::string msg = j.dump(); this->sharedMemory->write(msg.data(), msg.size()); - // this->qmanager->SendEventToMainWindow(QM::QueueEvents::ITEM_GENERATION_STARTED, myJob); + // this->qmanager->SendEventToMainWindow(QueueEvents::ITEM_GENERATION_STARTED, myJob); } catch (const std::exception& e) { std::cerr << __FILE__ << ":" << __LINE__ << e.what() << std::endl; @@ -3341,7 +3380,7 @@ void MainWindowUI::OnQueueItemManagerItemStatusChanged(std::shared_ptrGetItemData(currentItem); std::shared_ptr qitem = this->qmanager->GetItemPtr(id); if (qitem->id == item->id) { - store->SetValueByRow(wxVariant(wxGetTranslation(QM::QueueStatus_GUI_str.at(item->status))), i, (int)queueJobRows::STATUS); + store->SetValueByRow(wxVariant(wxGetTranslation(QueueStatus_GUI_str.at(item->status))), i, (int)queueJobRows::STATUS); store->RowValueChanged(i, (int)queueJobRows::STATUS); store->SetValueByRow(wxVariant(item->status_message), i, (int)queueJobRows::STATUS_MESSAGE); @@ -3373,11 +3412,11 @@ void MainWindowUI::OnThreadMessage(wxThreadEvent& e) { if (threadEvent == sd_gui_utils::ThreadEvents::QUEUE) { // only numbers here... - QM::QueueEvents event = (QM::QueueEvents)std::stoi(content); + QueueEvents event = (QueueEvents)std::stoi(content); std::shared_ptr item = e.GetPayload>(); - if (QM::QueueEvents::ITEM_ADDED != event) { + if (QueueEvents::ITEM_ADDED != event) { this->qmanager->UpdateItem(*item); } @@ -3385,44 +3424,44 @@ void MainWindowUI::OnThreadMessage(wxThreadEvent& e) { wxString message; switch (event) { - case QM::QueueEvents::ITEM_MODEL_HASH_START: { + case QueueEvents::ITEM_MODEL_HASH_START: { } break; - case QM::QueueEvents::ITEM_MODEL_HASH_UPDATE: { + case QueueEvents::ITEM_MODEL_HASH_UPDATE: { MainWindowUI::SendThreadEvent(sd_gui_utils::ThreadEvents::HASHING_PROGRESS, item); // this will call the STANDALONE_HASHING_PROGRESS event too this->UpdateCurrentProgress(item, event); } break; - case QM::QueueEvents::ITEM_MODEL_HASH_DONE: { + case QueueEvents::ITEM_MODEL_HASH_DONE: { MainWindowUI::SendThreadEvent(sd_gui_utils::ThreadEvents::HASHING_DONE, item); // this will call the STANDALONE_HASHING_DONE event too this->UpdateCurrentProgress(item, event); } break; // new item added - case QM::QueueEvents::ITEM_ADDED: { + case QueueEvents::ITEM_ADDED: { this->UpdateJobInfoDetailsFromJobQueueList(item); this->OnQueueItemManagerItemAdded(item); } break; // item status changed - case QM::QueueEvents::ITEM_STATUS_CHANGED: { + case QueueEvents::ITEM_STATUS_CHANGED: { this->UpdateJobInfoDetailsFromJobQueueList(item); this->OnQueueItemManagerItemStatusChanged(item); this->UpdateCurrentProgress(item, event); } break; // item updated... -> set the progress bar in the queue - case QM::QueueEvents::ITEM_UPDATED: { + case QueueEvents::ITEM_UPDATED: { this->OnQueueItemManagerItemUpdated(item); this->UpdateCurrentProgress(item, event); } break; // this is just the item start, if no mode // loaded, then will trigger model load // event - case QM::QueueEvents::ITEM_START: { + case QueueEvents::ITEM_START: { this->UpdateJobInfoDetailsFromJobQueueList(item); this->StartGeneration(item); message = wxString::Format(_("%s is just stared to generate %d images\nModel: %s"), modes_str[item->mode], item->params.batch_count, item->model); - if (item->mode == QM::GenerationMode::UPSCALE) { + if (item->mode == SDMode::UPSCALE) { title = _("Upscaling started"); message = wxString::Format(_("Upscaling the image is started: %s\nModel: %s"), item->initial_image, item->model); - } else if (item->mode == QM::GenerationMode::CONVERT) { + } else if (item->mode == SDMode::CONVERT) { title = _("Conversion started"); message = wxString::Format(_("Conversion the model is started: %s\nModel: %s"), item->initial_image, item->model); } else { @@ -3438,18 +3477,18 @@ void MainWindowUI::OnThreadMessage(wxThreadEvent& e) { // update global status info this->UpdateCurrentProgress(item, event); } break; - case QM::QueueEvents::ITEM_FINISHED: { + case QueueEvents::ITEM_FINISHED: { // update again - this->SendThreadEvent(this->GetEventHandler(), QM::QueueEvents::ITEM_UPDATED, item); + this->SendThreadEvent(this->GetEventHandler(), QueueEvents::ITEM_UPDATED, item); this->m_stop_background_process->Enable(); this->jobsCountSinceSegfault++; this->stepsCountSinceSegfault += item->steps; this->UpdateJobInfoDetailsFromJobQueueList(item); message = wxString::Format(_("%s is just finished to generate %d images\nModel: %s"), modes_str[item->mode], item->params.batch_count, item->model); - if (item->mode == QM::GenerationMode::UPSCALE) { + if (item->mode == SDMode::UPSCALE) { title = _("Upscaling done"); message = wxString::Format(_("Upscaling the image is done: \n%s\nModel: %s"), item->initial_image, item->model); - } else if (item->mode == QM::GenerationMode::CONVERT) { + } else if (item->mode == SDMode::CONVERT) { title = _("Conversion done"); message = wxString::Format(_("Conversion the model is done: \n%s\nModel: %s"), item->model, item->params.output_path); if (wxFileExists(item->params.output_path)) { @@ -3469,7 +3508,7 @@ void MainWindowUI::OnThreadMessage(wxThreadEvent& e) { this->ShowNotification(title, message); this->writeLog(message); { - if (this->jobsCountSinceSegfault > 0) { + if (this->jobsCountSinceSegfault.load() > 0) { wxString msg; if (this->jobsCountSinceSegfault.load() > 1) { msg = _("%d jobs and %d steps without a segfault"); @@ -3486,37 +3525,37 @@ void MainWindowUI::OnThreadMessage(wxThreadEvent& e) { // update global status info this->UpdateCurrentProgress(item, event); } break; - case QM::QueueEvents::ITEM_MODEL_LOADED: { // MODEL_LOAD_DONE + case QueueEvents::ITEM_MODEL_LOADED: { // MODEL_LOAD_DONE this->UpdateJobInfoDetailsFromJobQueueList(item); this->writeLog(wxString::Format(_("Model loaded: %s\n"), item->model)); this->UpdateCurrentProgress(item, event); } break; - case QM::QueueEvents::ITEM_MODEL_LOAD_START: { // MODEL_LOAD_START + case QueueEvents::ITEM_MODEL_LOAD_START: { // MODEL_LOAD_START this->writeLog(wxString::Format(_("Model load started: %s\n"), item->model)); this->UpdateCurrentProgress(item, event); } break; - case QM::QueueEvents::ITEM_MODEL_FAILED: { // MODEL_LOAD_ERROR + case QueueEvents::ITEM_MODEL_FAILED: { // MODEL_LOAD_ERROR this->writeLog(wxString::Format(_("Model load failed: %s\n"), item->model)); title = _("Model load failed"); message = wxString::Format(_("The '%s' just failed to load... for more details please see the logs!"), item->model); this->ShowNotification(title, message); this->UpdateCurrentProgress(item, event); } break; - case QM::QueueEvents::ITEM_GENERATION_STARTED: // GENERATION_START - if (item->mode == QM::GenerationMode::IMG2IMG || - item->mode == QM::GenerationMode::TXT2IMG) { + case QueueEvents::ITEM_GENERATION_STARTED: // GENERATION_START + if (item->mode == SDMode::IMG2IMG || + item->mode == SDMode::TXT2IMG) { this->writeLog(wxString::Format( _("Diffusion started. Seed: %" PRId64 " Batch: %d %dx%dpx Cfg: %.1f Steps: %d"), item->params.seed, item->params.batch_count, item->params.width, item->params.height, item->params.cfg_scale, item->params.sample_steps)); } - if (item->mode == QM::GenerationMode::UPSCALE) { + if (item->mode == SDMode::UPSCALE) { this->writeLog(wxString::Format(_("Upscale start, factor: %d image: %s\n"), item->upscale_factor, item->initial_image)); } this->UpdateCurrentProgress(item, event); break; - case QM::QueueEvents::ITEM_FAILED: // GENERATION_ERROR + case QueueEvents::ITEM_FAILED: // GENERATION_ERROR this->writeLog(wxString::Format(_("Generation error: %s\n"), item->status_message)); this->UpdateJobInfoDetailsFromJobQueueList(item); this->UpdateCurrentProgress(item, event); @@ -3534,6 +3573,7 @@ void MainWindowUI::OnThreadMessage(wxThreadEvent& e) { sd_gui_utils::sdServer* server = e.GetPayload(); this->writeLog(wxString::Format(_("Server disconnected: %s %s"), server->GetName(), server->disconnect_reason)); // this->treeListManager->DeleteByServerId(server); + this->treeListManager->DeleteByServerId(server->server_id); this->ModelManager->UnloadModelsByServer(server); return; } @@ -3884,7 +3924,7 @@ void MainWindowUI::UpdateJobInfoDetailsFromJobQueueList(std::shared_ptrserver > -1) { + if (item->server.empty() == false) { auto srv = this->mapp->cfg->GetTcpServer(item->server); data.push_back(wxVariant(wxString::Format("%s", srv == nullptr ? _("deleted server") : srv->GetName()))); } else { @@ -3910,7 +3950,7 @@ void MainWindowUI::UpdateJobInfoDetailsFromJobQueueList(std::shared_ptrm_joblist_item_details->AppendItem(data); data.clear(); - if (item->mode == QM::GenerationMode::CONVERT) { + if (item->mode == SDMode::CONVERT) { data.push_back(wxVariant(_("Model"))); data.push_back(wxVariant(wxString(item->params.output_path))); this->m_joblist_item_details->AppendItem(data); @@ -3922,7 +3962,7 @@ void MainWindowUI::UpdateJobInfoDetailsFromJobQueueList(std::shared_ptrm_joblist_item_details->AppendItem(data); data.clear(); - if (item->mode == QM::GenerationMode::UPSCALE) { + if (item->mode == SDMode::UPSCALE) { data.push_back(wxVariant(_("Factor"))); data.push_back( wxVariant(wxString::Format("%" PRId32, item->upscale_factor))); @@ -3930,14 +3970,14 @@ void MainWindowUI::UpdateJobInfoDetailsFromJobQueueList(std::shared_ptrmode == QM::GenerationMode::IMG2IMG || - item->mode == QM::GenerationMode::TXT2IMG || - item->mode == QM::GenerationMode::CONVERT) { + if (item->mode == SDMode::IMG2IMG || + item->mode == SDMode::TXT2IMG || + item->mode == SDMode::CONVERT) { data.push_back(wxVariant(_("Type"))); data.push_back(wxVariant(wxString::Format("%s", sd_gui_utils::sd_type_gui_names[item->params.wtype]))); this->m_joblist_item_details->AppendItem(data); data.clear(); - if (item->mode != QM::GenerationMode::CONVERT) { + if (item->mode != SDMode::CONVERT) { data.push_back(wxVariant(_("Scheduler"))); data.push_back(wxVariant(sd_gui_utils::sd_scheduler_gui_names[item->params.schedule])); this->m_joblist_item_details->AppendItem(data); @@ -3945,7 +3985,7 @@ void MainWindowUI::UpdateJobInfoDetailsFromJobQueueList(std::shared_ptrmode == QM::GenerationMode::IMG2IMG) { + if (item->mode == SDMode::IMG2IMG) { data.push_back(wxVariant(_("Init image"))); data.push_back(wxVariant(wxString::FromUTF8Unchecked(item->initial_image.data(), item->initial_image.size()))); this->m_joblist_item_details->AppendItem(data); @@ -3964,8 +4004,8 @@ void MainWindowUI::UpdateJobInfoDetailsFromJobQueueList(std::shared_ptrmode == QM::GenerationMode::TXT2IMG || - item->mode == QM::GenerationMode::IMG2IMG) { + if (item->mode == SDMode::TXT2IMG || + item->mode == SDMode::IMG2IMG) { data.push_back(wxVariant(_("Prompt"))); data.push_back(wxVariant(wxString::FromUTF8Unchecked(item->params.prompt))); this->m_joblist_item_details->AppendItem(data); @@ -4072,7 +4112,7 @@ void MainWindowUI::UpdateJobInfoDetailsFromJobQueueList(std::shared_ptrmode == QM::GenerationMode::TXT2IMG) { + if (item->mode == SDMode::TXT2IMG) { data.push_back(wxVariant(_("Width"))); data.push_back(wxVariant(wxString::Format("%dpx", item->params.width))); this->m_joblist_item_details->AppendItem(data); @@ -4269,7 +4309,7 @@ std::shared_ptr MainWindowUI::handleSdImages(std::shared_ptrSetLoadFlags(rawImage->GetLoadFlags() & ~wxImage::Load_Verbose); if (!rawImage->LoadFile(wxString::FromUTF8Unchecked(rimage))) { itemPtr->status_message = _("Invalid image from diffusion: ") + rimage; - MainWindowUI::SendThreadEvent(eventHandler, QM::QueueEvents::ITEM_FAILED, itemPtr); + MainWindowUI::SendThreadEvent(eventHandler, QueueEvents::ITEM_FAILED, itemPtr); delete rawImage; return itemPtr; } @@ -4278,7 +4318,7 @@ std::shared_ptr MainWindowUI::handleSdImages(std::shared_ptrSetOption(wxIMAGE_OPTION_PNG_COMPRESSION_LEVEL, 0); if (!rawImage->SaveFile(fullName, imgHandler)) { itemPtr->status_message = wxString::Format(_("Failed to save image into %s"), fullName).utf8_string(); - MainWindowUI::SendThreadEvent(eventHandler, QM::QueueEvents::ITEM_FAILED, itemPtr); + MainWindowUI::SendThreadEvent(eventHandler, QueueEvents::ITEM_FAILED, itemPtr); delete rawImage; return itemPtr; } @@ -4639,7 +4679,7 @@ void MainWindowUI::PrepareModelConvert(sd_gui_utils::ModelFileInfo* modelInfo) { std::shared_ptr item = std::make_shared(); item->model = modelInfo->name; - item->mode = QM::GenerationMode::CONVERT; + item->mode = SDMode::CONVERT; item->params.mode = SDMode::CONVERT; item->params.n_threads = this->mapp->cfg->n_threads; item->params.output_path = modelOut.GetAbsolutePath().utf8_string(); @@ -4710,12 +4750,12 @@ bool MainWindowUI::ProcessEventHandler(std::string message) { std::cerr << "[GUI] Could not find item " << item.id << std::endl; return false; } - if (itemPtr->event == QM::QueueEvents::ITEM_FAILED) { - std::cerr << "[GUI] Item " << item.id << " QM::QueueEvents::ITEM_FAILED" << std::endl; + if (itemPtr->event == QueueEvents::ITEM_FAILED) { + std::cerr << "[GUI] Item " << item.id << " QueueEvents::ITEM_FAILED" << std::endl; // return true; } - if (itemPtr->status == QM::QueueStatus::FAILED) { - std::cerr << "[GUI] Item " << item.id << " QM::QueueStatus::FAILED, skipping" << std::endl; + if (itemPtr->status == QueueStatus::FAILED) { + std::cerr << "[GUI] Item " << item.id << " QueueStatus::FAILED, skipping" << std::endl; return true; } // mutex lock @@ -4723,7 +4763,7 @@ bool MainWindowUI::ProcessEventHandler(std::string message) { if (itemPtr->update_index != item.update_index || itemPtr->event != item.event) { if (BUILD_TYPE == "Debug") { - std::cout << "[GUI] Item " << item.id << " was updated, event: " << QM::QueueEvents_str.at(item.event) << std::endl; + std::cout << "[GUI] Item " << item.id << " was updated, event: " << QueueEvents_str.at(item.event) << std::endl; } *itemPtr = item; @@ -4731,7 +4771,7 @@ bool MainWindowUI::ProcessEventHandler(std::string message) { if (!itemPtr->rawImages.empty()) { this->handleSdImages(itemPtr, this->GetEventHandler()); } - if (itemPtr->event == QM::QueueEvents::ITEM_FAILED) { + if (itemPtr->event == QueueEvents::ITEM_FAILED) { if (this->extprocessLastError.empty() == false) { itemPtr->status_message = this->extprocessLastError; this->extprocessLastError = ""; @@ -4818,7 +4858,7 @@ void MainWindowUI::ProcessOutputThread() { } void MainWindowUI::ProcessCheckThread() { - while (this->extProcessNeedToRun == true) { + while (this->extProcessNeedToRun.load()) { if (subprocess_alive(this->subprocess) != 0) { std::unique_ptr buffer(new char[SHARED_MEMORY_SIZE]); @@ -4831,7 +4871,7 @@ void MainWindowUI::ProcessCheckThread() { } } - if (this->extProcessNeedToRun == false) { + if (this->extProcessNeedToRun.load() == false) { std::string exitMsg = "exit"; this->sharedMemory->write(exitMsg.c_str(), exitMsg.size()); { @@ -4844,7 +4884,7 @@ void MainWindowUI::ProcessCheckThread() { return; } float sleepTime = EPROCESS_SLEEP_TIME; - if (this->qmanager->GetCurrentItem() != nullptr && this->qmanager->GetCurrentItem()->status == QM::QueueStatus::RUNNING) { + if (this->qmanager->GetCurrentItem() != nullptr && this->qmanager->GetCurrentItem()->status == QueueStatus::RUNNING) { if (this->qmanager->GetCurrentItem()->stats.time_min > 0) { sleepTime = this->qmanager->GetCurrentItem()->stats.time_min; } else { @@ -4852,7 +4892,7 @@ void MainWindowUI::ProcessCheckThread() { } } { // it will be updated again, when a job is finished - if (this->jobsCountSinceSegfault == 0) { + if (this->jobsCountSinceSegfault.load() == 0) { { wxThreadEvent* event = new wxThreadEvent(); event->SetString(_("Process is ready")); @@ -4895,9 +4935,9 @@ void MainWindowUI::ProcessCheckThread() { this->m_stop_background_process->Disable(); } } - this->jobsCountSinceSegfault = 0; - this->stepsCountSinceSegfault = 0; - if (BUILD_TYPE == "Debug") { + this->jobsCountSinceSegfault.store(0); + this->stepsCountSinceSegfault.store(0); + if (std::string(BUILD_TYPE) == "Debug") { std::cout << "[GUI] restart sleep time: " << (EPROCESS_SLEEP_TIME * 10) << std::endl; } std::this_thread::sleep_for(std::chrono::milliseconds(EPROCESS_SLEEP_TIME * 10)); @@ -4953,14 +4993,14 @@ void MainWindowUI::writeLog(const wxString& msg, bool writeIntoGui, bool debug) void MainWindowUI::writeLog(const std::string& message) { this->writeLog(wxString::FromUTF8Unchecked(message)); } -void MainWindowUI::UpdateCurrentProgress(std::shared_ptr item, const QM::QueueEvents& event) { - this->m_currentStatus->SetLabel(wxString::Format(_("Current job: %s %s"), modes_str[item->mode], wxGetTranslation(QM::QueueStatus_GUI_str.at(item->status)))); +void MainWindowUI::UpdateCurrentProgress(std::shared_ptr item, const QueueEvents& event) { + this->m_currentStatus->SetLabel(wxString::Format(_("Current job: %s %s"), modes_str[item->mode], wxGetTranslation(QueueStatus_GUI_str.at(item->status)))); - if (event == QM::QueueEvents::ITEM_STATUS_CHANGED) { + if (event == QueueEvents::ITEM_STATUS_CHANGED) { return; } - if (event == QM::QueueEvents::ITEM_MODEL_HASH_UPDATE || event == QM::QueueEvents::ITEM_MODEL_HASH_START) { + if (event == QueueEvents::ITEM_MODEL_HASH_UPDATE || event == QueueEvents::ITEM_MODEL_HASH_START) { auto current = item->hash_progress_size; auto total = item->hash_fullsize; if (current > total) { @@ -4971,9 +5011,9 @@ void MainWindowUI::UpdateCurrentProgress(std::shared_ptr item, co return; } - if (event == QM::QueueEvents::ITEM_UPDATED || - event == QM::QueueEvents::ITEM_START || - event == QM::QueueEvents::ITEM_FINISHED) { + if (event == QueueEvents::ITEM_UPDATED || + event == QueueEvents::ITEM_START || + event == QueueEvents::ITEM_FINISHED) { unsigned int stepsSum = item->params.sample_steps * item->params.batch_count; unsigned int stepsDone = item->stats.time_per_step.size(); diff --git a/src/ui/MainWindowUI.h b/src/ui/MainWindowUI.h index 90e1e44..8098172 100644 --- a/src/ui/MainWindowUI.h +++ b/src/ui/MainWindowUI.h @@ -177,7 +177,7 @@ class MainWindowUI : public mainUI { std::vector voids; struct subprocess_s* subprocess = nullptr; - std::atomic extProcessNeedToRun = true; + std::atomic extProcessNeedToRun{true}; wxString extprocessCommand; wxString extProcessParam; wxString extprocessLastError; @@ -217,7 +217,7 @@ class MainWindowUI : public mainUI { void ProcessOutputThread(); void ProcessStdOutEvent(const char* bytes, size_t n); void ProcessStdErrEvent(const char* bytes, size_t n); - void UpdateCurrentProgress(std::shared_ptr item, const QM::QueueEvents& event); + void UpdateCurrentProgress(std::shared_ptr item, const QueueEvents& event); void SetSchedulerByType(schedule_t schedule); void SetSamplerByType(sample_method_t sampler); void SetTypeByType(sd_type_t type); @@ -287,9 +287,9 @@ class MainWindowUI : public mainUI { } inline void EnableModelSelect() { this->m_model->Enable(); } - std::shared_ptr processCheckThread = nullptr; - std::shared_ptr processHandleOutput = nullptr; - std::atomic_bool extProcessRunning = false; + std::shared_ptr processCheckThread = nullptr; + std::shared_ptr processHandleOutput = nullptr; + std::atomic extProcessRunning{false}; std::shared_ptr sharedMemory = nullptr; static void ModelHashingCallback(size_t readed_size, std::string sha256, void* custom_pointer); @@ -323,7 +323,7 @@ class MainWindowUI : public mainUI { void OnQueueItemManagerItemStatusChanged(std::shared_ptr item); template - static void SendThreadEvent(wxEvtHandler* eventHandler, QM::QueueEvents eventType, const T& payload, std::string text = ""); + static void SendThreadEvent(wxEvtHandler* eventHandler, QueueEvents eventType, const T& payload, std::string text = ""); template static void SendThreadEvent(wxEvtHandler* eventHandler, sd_gui_utils::ThreadEvents eventType, const T& payload, std::string text = ""); @@ -344,10 +344,10 @@ class MainWindowUI : public mainUI { inline static wxString formatFileName(const QM::QueueItem& item, const wxString& format = "[mode]_[jobid]_[seed]_[width]x[height]_[batch]") { wxDateTime localTime = wxDateTime::Now(); - auto day = localTime.Format(wxT("%d")); - auto month = localTime.Format(wxT("%m")); - auto year = localTime.Format(wxT("%Y")); - auto hours = localTime.Format(wxT("%H")); + auto day = localTime.Format(wxT("%d")); + auto month = localTime.Format(wxT("%m")); + auto year = localTime.Format(wxT("%Y")); + auto hours = localTime.Format(wxT("%H")); auto minutes = localTime.Format(wxT("%M")); auto seconds = localTime.Format(wxT("%S")); diff --git a/src/ui/ModelInfo.cpp b/src/ui/ModelInfo.cpp index da95904..cfbbe74 100644 --- a/src/ui/ModelInfo.cpp +++ b/src/ui/ModelInfo.cpp @@ -94,7 +94,7 @@ sd_gui_utils::ModelFileInfo* ModelInfo::Manager::addRemoteModel(const sd_gui_uti sd_gui_utils::ModelFileInfo* _z = new sd_gui_utils::ModelFileInfo(data.get()); _z->folderGroupName = this->GetFolderName(wxString::FromUTF8Unchecked(info.path), info.model_type, info.root_path, server); _z->meta_file = meta_file.utf8_string(); - _z->server_id = server->server_id; + _z->server_id = server->internal_id; if (_z->sha256.empty()) { auto localVer = this->findInfoByName(info.name); if (localVer != nullptr && localVer->sha256.empty() == false) { @@ -118,7 +118,7 @@ sd_gui_utils::ModelFileInfo* ModelInfo::Manager::addRemoteModel(const sd_gui_uti if (localVer != nullptr && localVer->sha256.empty() == false) { meta->sha256 = localVer->sha256; } - meta->server_id = server->server_id; + meta->server_id = server->internal_id; this->WriteIntoMeta(meta); diff --git a/src/ui/ModelInfo.h b/src/ui/ModelInfo.h index ce70d71..6d9b049 100644 --- a/src/ui/ModelInfo.h +++ b/src/ui/ModelInfo.h @@ -57,7 +57,7 @@ namespace ModelInfo { inline void UnloadModelsByServer(sd_gui_utils::sdServer* server) { std::lock_guard lock(this->mutex); for (auto it = this->ModelInfos.begin(); it != this->ModelInfos.end();) { - if (it->second->server_id == server->server_id) { + if (it->second->server_id == server->internal_id) { this->ModelCount[it->second->model_type]--; delete it->second; it = this->ModelInfos.erase(it); diff --git a/src/ui/QueueManager.cpp b/src/ui/QueueManager.cpp index 4eab5dc..c1cad13 100644 --- a/src/ui/QueueManager.cpp +++ b/src/ui/QueueManager.cpp @@ -33,20 +33,18 @@ int QM::QueueManager::AddItem(const QM::QueueItem& _item, bool fromFile) { this->QueueList[item->id] = item; - if (fromFile == false) { + if (fromFile == false && item->server.empty()) { this->SaveJobToFile(*item); } - this->SendEventToMainWindow(QM::QueueEvents::ITEM_ADDED, item); + this->SendEventToMainWindow(QueueEvents::ITEM_ADDED, item); - if (this->isRunning == false && item->status == QM::QueueStatus::PENDING) { + if (this->isRunning == false && item->status == QueueStatus::PENDING) { this->currentItem = item; - this->SendEventToMainWindow(QM::QueueEvents::ITEM_START, item); + this->SendEventToMainWindow(QueueEvents::ITEM_START, item); this->isRunning = true; } - if (BUILD_TYPE == "Debug" && fromFile == true) { - std::cout << "Item added from file: " << item->id << std::endl; - } + return item->id; } void QM::QueueManager::UpdateItem(const QM::QueueItem& item) { @@ -99,17 +97,17 @@ std::shared_ptr QM::QueueManager::Duplicate(std::shared_ptrupdated_at = 0; newitem->started_at = 0; newitem->finished_at = 0; - newitem->status = QM::QueueStatus::PENDING; + newitem->status = QueueStatus::PENDING; newitem->status_message = ""; - newitem->stats = QM::QueueItemStats(); + newitem->stats = QueueItemStats(); newitem->steps = 0; newitem->step = 0; newitem->time = 0; // remove old images whitch are generated by the original job - if (newitem->mode == QM::GenerationMode::TXT2IMG || - newitem->mode == QM::GenerationMode::IMG2IMG || - newitem->mode == QM::GenerationMode::UPSCALE) { + if (newitem->mode == SDMode::TXT2IMG || + newitem->mode == SDMode::IMG2IMG || + newitem->mode == SDMode::UPSCALE) { newitem->images.erase( std::remove_if(newitem->images.begin(), newitem->images.end(), [](QM::QueueItemImage img) { @@ -134,7 +132,7 @@ std::shared_ptr QM::QueueManager::Duplicate(std::shared_ptrstatus = QM::QueueStatus::PAUSED; + newitem->status = QueueStatus::PAUSED; this->AddItem(newitem); return newitem; } @@ -149,41 +147,41 @@ std::shared_ptr QM::QueueManager::Duplicate(int id) { return nullptr; } -void QM::QueueManager::SetStatus(QM::QueueStatus status, std::shared_ptr item) { +void QM::QueueManager::SetStatus(QueueStatus status, std::shared_ptr item) { if (this->QueueList.find(item->id) != this->QueueList.end()) { - if (item->finished_at == 0 && status == QM::QueueStatus::DONE) { + if (item->finished_at == 0 && status == QueueStatus::DONE) { item->finished_at = this->GetCurrentUnixTimestamp(); } else { item->updated_at = this->GetCurrentUnixTimestamp(); } this->QueueList[item->id]->status = status; this->SaveJobToFile(*this->QueueList[item->id]); - this->SendEventToMainWindow(QM::QueueEvents::ITEM_STATUS_CHANGED, this->QueueList[item->id]); + this->SendEventToMainWindow(QueueEvents::ITEM_STATUS_CHANGED, this->QueueList[item->id]); } } void QM::QueueManager::PauseAll() { for (auto q : this->QueueList) { - if (q.second->status == QM::QueueStatus::PENDING) { - this->SetStatus(QM::PAUSED, q.second); + if (q.second->status == QueueStatus::PENDING) { + this->SetStatus(QueueStatus::PAUSED, q.second); } } } void QM::QueueManager::RestartQueue() { for (auto q : this->QueueList) { - if (q.second->status == QM::QueueStatus::PAUSED) { - this->SetStatus(QM::PENDING, q.second); + if (q.second->status == QueueStatus::PAUSED) { + this->SetStatus(QueueStatus::PENDING, q.second); } } if (!this->isRunning) { for (auto job : this->QueueList) { - if (job.second->status == QM::QueueStatus::PENDING) { + if (job.second->status == QueueStatus::PENDING) { if (this->isRunning == false) { this->isRunning = true; this->currentItem = job.second; - this->SendEventToMainWindow(QM::QueueEvents::ITEM_START, job.second); + this->SendEventToMainWindow(QueueEvents::ITEM_START, job.second); } break; } @@ -192,24 +190,24 @@ void QM::QueueManager::RestartQueue() { } void QM::QueueManager::UnPauseItem(std::shared_ptr item) { - if (item->status == QM::QueueStatus::PAUSED) { - this->SetStatus(QM::QueueStatus::PENDING, item); + if (item->status == QueueStatus::PAUSED) { + this->SetStatus(QueueStatus::PENDING, item); // check if queue is active if (!this->isRunning) { this->currentItem = this->QueueList[item->id]; - this->SendEventToMainWindow(QM::QueueEvents::ITEM_START, this->QueueList[item->id]); + this->SendEventToMainWindow(QueueEvents::ITEM_START, this->QueueList[item->id]); this->isRunning = true; } } } void QM::QueueManager::PauseItem(std::shared_ptr item) { - if (item->status == QM::QueueStatus::PENDING) { - this->SetStatus(QM::QueueStatus::PAUSED, item); + if (item->status == QueueStatus::PENDING) { + this->SetStatus(QueueStatus::PAUSED, item); } } -void QM::QueueManager::SendEventToMainWindow(QM::QueueEvents eventType, std::shared_ptr item) { +void QM::QueueManager::SendEventToMainWindow(QueueEvents eventType, std::shared_ptr item) { // TODO: e->SetInt instead of SetString wxThreadEvent* e = new wxThreadEvent(); e->SetString(wxString::Format("%d:%d", (int)sd_gui_utils::ThreadEvents::QUEUE, (int)eventType)); @@ -233,25 +231,25 @@ void QM::QueueManager::OnThreadMessage(wxThreadEvent& e) { // only handle the QUEUE messages, what this class generate if (threadEvent == sd_gui_utils::ThreadEvents::QUEUE) { - QM::QueueEvents event = (QM::QueueEvents)wxAtoi(content); + QueueEvents event = (QueueEvents)wxAtoi(content); auto payload = e.GetPayload>(); - if (event == QM::QueueEvents::ITEM_START) { - this->SetStatus(QM::QueueStatus::RUNNING, payload); + if (event == QueueEvents::ITEM_START) { + this->SetStatus(QueueStatus::RUNNING, payload); this->isRunning = true; this->currentItem = payload; return; } - if (event == QM::QueueEvents::ITEM_FINISHED) { - this->SetStatus(QM::QueueStatus::DONE, payload); + if (event == QueueEvents::ITEM_FINISHED) { + this->SetStatus(QueueStatus::DONE, payload); this->isRunning = false; this->currentItem = nullptr; // jump to the next item in queue // find waiting jobs for (auto job : this->QueueList) { - if (job.second->status == QM::QueueStatus::PENDING) { + if (job.second->status == QueueStatus::PENDING) { if (this->isRunning == false) { this->currentItem = job.second; - this->SendEventToMainWindow(QM::QueueEvents::ITEM_START, job.second); + this->SendEventToMainWindow(QueueEvents::ITEM_START, job.second); this->isRunning = true; } break; @@ -259,52 +257,52 @@ void QM::QueueManager::OnThreadMessage(wxThreadEvent& e) { } return; } - if (event == QM::QueueEvents::ITEM_MODEL_LOAD_START) { + if (event == QueueEvents::ITEM_MODEL_LOAD_START) { auto payload = e.GetPayload>(); - this->SetStatus(QM::QueueStatus::MODEL_LOADING, payload); + this->SetStatus(QueueStatus::MODEL_LOADING, payload); } - if (event == QM::QueueEvents::ITEM_MODEL_FAILED) { + if (event == QueueEvents::ITEM_MODEL_FAILED) { auto payload = e.GetPayload>(); - this->SetStatus(QM::QueueStatus::FAILED, payload); + this->SetStatus(QueueStatus::FAILED, payload); this->isRunning = false; // jump to the next for (auto job : this->QueueList) { - if (job.second->status == QM::QueueStatus::PENDING) { + if (job.second->status == QueueStatus::PENDING) { if (this->isRunning == false) { this->currentItem = job.second; - this->SendEventToMainWindow(QM::QueueEvents::ITEM_START, job.second); + this->SendEventToMainWindow(QueueEvents::ITEM_START, job.second); this->isRunning = true; } break; } } } - if (event == QM::QueueEvents::ITEM_FAILED) { + if (event == QueueEvents::ITEM_FAILED) { auto payload = e.GetPayload>(); - this->SetStatus(QM::QueueStatus::FAILED, payload); + this->SetStatus(QueueStatus::FAILED, payload); this->isRunning = false; // jump to the next for (auto job : this->QueueList) { - if (job.second->status == QM::QueueStatus::PENDING) { + if (job.second->status == QueueStatus::PENDING) { if (this->isRunning == false) { this->currentItem = job.second; - this->SendEventToMainWindow(QM::QueueEvents::ITEM_START, job.second); + this->SendEventToMainWindow(QueueEvents::ITEM_START, job.second); this->isRunning = true; } break; } } } - if (event == QM::QueueEvents::ITEM_GENERATION_STARTED) { + if (event == QueueEvents::ITEM_GENERATION_STARTED) { auto payload = e.GetPayload>(); - this->SetStatus(QM::QueueStatus::RUNNING, payload); + this->SetStatus(QueueStatus::RUNNING, payload); this->isRunning = true; } } if (threadEvent == sd_gui_utils::ThreadEvents::HASHING_PROGRESS) { auto payload = e.GetPayload>(); - this->SetStatus(QM::QueueStatus::HASHING, payload); + this->SetStatus(QueueStatus::HASHING, payload); } } @@ -394,11 +392,11 @@ void QM::QueueManager::LoadJobListFromDir() { try { nlohmann::json data = nlohmann::json::parse(f); std::shared_ptr item = std::make_shared(data.get()); - if (item->status == QM::QueueStatus::RUNNING || - item->status == QM::QueueStatus::MODEL_LOADING || - item->status == QM::QueueStatus::HASHING || - item->status == QM::QueueStatus::HASHING_DONE) { - item->status = QM::QueueStatus::PAUSED; + if (item->status == QueueStatus::RUNNING || + item->status == QueueStatus::MODEL_LOADING || + item->status == QueueStatus::HASHING || + item->status == QueueStatus::HASHING_DONE) { + item->status = QueueStatus::PAUSED; } this->AddItem(item, true); diff --git a/src/ui/QueueManager.h b/src/ui/QueueManager.h index e91c1bb..c34c56b 100644 --- a/src/ui/QueueManager.h +++ b/src/ui/QueueManager.h @@ -2,91 +2,6 @@ #define __SD_GUI_QUEUE_MANAGER namespace QM { - enum QueueStatus { - PENDING, // deletable - RUNNING, // non deletable - PAUSED, // deletable - FAILED, // deletable - MODEL_LOADING, // non deletable - DONE, // deletable - HASHING, // non deletable - HASHING_DONE // non deletable - }; - - enum GenerationMode { - TXT2IMG, - IMG2IMG, - CONVERT, - UPSCALE, - IMG2VID - }; - - inline const std::unordered_map GenerationMode_str = { - {QM::GenerationMode::TXT2IMG, "txt2img"}, - {QM::GenerationMode::IMG2IMG, "img2img"}, - {QM::GenerationMode::CONVERT, "convert"}, - {QM::GenerationMode::UPSCALE, "upscale"}, - {QM::GenerationMode::IMG2VID, "img2vid"}}; - - inline const std::unordered_map GenerationMode_str_inv = { - {"txt2img", QM::GenerationMode::TXT2IMG}, - {"img2img", QM::GenerationMode::IMG2IMG}, - {"convert", QM::GenerationMode::CONVERT}, - {"upscale", QM::GenerationMode::UPSCALE}, - {"img2vid", QM::GenerationMode::IMG2VID}}; - - inline const char* QueueStatus_str[] = { - _("pending"), - _("running"), - _("paused"), - _("failed"), - _("model loading..."), - _("finished"), - _("model hashing...")}; - - inline const std::unordered_map QueueStatus_GUI_str = { - {QM::QueueStatus::PENDING, "pending"}, - {QM::QueueStatus::RUNNING, "running"}, - {QM::QueueStatus::PAUSED, "paused"}, - {QM::QueueStatus::FAILED, "failed"}, - {QM::QueueStatus::MODEL_LOADING, "model loading..."}, - {QM::QueueStatus::DONE, "finished"}, - {QM::QueueStatus::HASHING, "model hashing..."}}; - - /// @brief Event commands to inter thread communication - enum class QueueEvents : unsigned int { - ITEM_DELETED = 1 << 0, - ITEM_ADDED = 1 << 1, - ITEM_STATUS_CHANGED = 1 << 2, - ITEM_UPDATED = 1 << 3, - ITEM_START = 1 << 4, - ITEM_FINISHED = 1 << 5, - ITEM_MODEL_LOAD_START = 1 << 6, - ITEM_MODEL_LOADED = 1 << 7, - ITEM_MODEL_FAILED = 1 << 8, - ITEM_GENERATION_STARTED = 1 << 9, - ITEM_FAILED = 1 << 10, - ITEM_MODEL_HASH_START = 1 << 11, - ITEM_MODEL_HASH_UPDATE = 1 << 12, - ITEM_MODEL_HASH_DONE = 1 << 13 - }; - - inline const std::unordered_map QueueEvents_str = { - {QM::QueueEvents::ITEM_DELETED, "ITEM_DELETED"}, - {QM::QueueEvents::ITEM_ADDED, "ITEM_ADDED"}, - {QM::QueueEvents::ITEM_STATUS_CHANGED, "ITEM_STATUS_CHANGED"}, - {QM::QueueEvents::ITEM_UPDATED, "ITEM_UPDATED"}, - {QM::QueueEvents::ITEM_START, "ITEM_START"}, - {QM::QueueEvents::ITEM_FINISHED, "ITEM_FINISHED"}, - {QM::QueueEvents::ITEM_MODEL_LOAD_START, "ITEM_MODEL_LOAD_START"}, - {QM::QueueEvents::ITEM_MODEL_LOADED, "ITEM_MODEL_LOADED"}, - {QM::QueueEvents::ITEM_MODEL_FAILED, "ITEM_MODEL_FAILED"}, - {QM::QueueEvents::ITEM_GENERATION_STARTED, "ITEM_GENERATION_STARTED"}, - {QM::QueueEvents::ITEM_FAILED, "ITEM_FAILED"}, - {QM::QueueEvents::ITEM_MODEL_HASH_START, "ITEM_MODEL_HASH_START"}, - {QM::QueueEvents::ITEM_MODEL_HASH_UPDATE, "ITEM_MODEL_HASH_UPDATE"}, - {QM::QueueEvents::ITEM_MODEL_HASH_DONE, "ITEM_MODEL_HASH_DONE"}}; - enum class QueueItemImageType : unsigned int { /// @brief The image is generated by diffusion GENERATED = 1 << 0, @@ -169,50 +84,15 @@ namespace QM { item = nullptr; } } - struct QueueStatsStepItem { - int step; - int steps; - float time; - }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(QueueStatsStepItem, step, steps, time) - struct QueueItemStats { - float time_min = 0.f, time_max = 0.f, time_avg = 0.f, time_total = 0.f; - std::vector time_per_step = {}; - }; - NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(QueueItemStats, time_min, time_max, time_avg, time_total, time_per_step) - struct QueueItem { - int id = 0, created_at = 0, updated_at = 0, finished_at = 0, started_at = 0; - SDParams params = SDParams(); - QM::QueueStatus status = QM::QueueStatus::PENDING; - QM::QueueEvents event = QM::QueueEvents::ITEM_ADDED; - QM::QueueItemStats stats = QM::QueueItemStats(); + struct QueueItem : public sd_gui_utils::networks::RemoteQueueItem { std::vector images = {}; - int step = 0, steps = 0; - size_t hash_fullsize = 0, hash_progress_size = 0; - float time = 0; - std::string model = ""; - QM::GenerationMode mode = QM::GenerationMode::TXT2IMG; - std::string initial_image = ""; - std::string mask_image = ""; - std::string status_message = ""; - uint32_t upscale_factor = 4; - std::string sha256 = ""; - std::vector rawImages = {}; - std::string app_version = SD_GUI_VERSION; - std::string git_version = GIT_HASH; - std::string original_prompt = ""; - std::string original_negative_prompt = ""; - std::string original_negative_prompt = ""; - bool keep_checkpoint_in_memory = false; - bool keep_upscaler_in_memory = false; - bool need_sha256 = false; - std::string generated_sha256 = ""; - int update_index = -1; - int server = -1; + std::vector rawImages = {}; + std::string initial_image = ""; + std::string mask_image = ""; inline wxString GetActualSpeed() { wxString speed = ""; - if (this->status == QM::QueueStatus::MODEL_LOADING || this->mode == QM::GenerationMode::CONVERT) { + if (this->status == QueueStatus::MODEL_LOADING || this->mode == SDMode::CONVERT) { int progress = (this->step / this->steps) * 100; speed = wxString::Format(this->time > 1.0f ? "%.2fs/it" : "%.2fit/s", this->time > 1.0f || this->time == 0 ? this->time : (1.0f / this->time)); } else { @@ -232,40 +112,10 @@ namespace QM { } return static_cast(current_progress); } - QueueItem(const QueueItem& other) - : id(other.id), - created_at(other.created_at), - updated_at(other.updated_at), - finished_at(other.finished_at), - started_at(other.started_at), - params(other.params), - status(other.status), - event(other.event), - stats(other.stats), - images(other.images), - step(other.step), - steps(other.steps), - hash_fullsize(other.hash_fullsize), - hash_progress_size(other.hash_progress_size), - time(other.time), - model(other.model), - mode(other.mode), - initial_image(other.initial_image), - mask_image(other.mask_image), - status_message(other.status_message), - upscale_factor(other.upscale_factor), - sha256(other.sha256), - rawImages(other.rawImages), - app_version(other.app_version), - git_version(other.git_version), - original_prompt(other.original_prompt), - original_negative_prompt(other.original_negative_prompt), - keep_checkpoint_in_memory(other.keep_checkpoint_in_memory), - keep_upscaler_in_memory(other.keep_upscaler_in_memory), - need_sha256(other.need_sha256), - generated_sha256(other.generated_sha256), - update_index(other.update_index), - server(other.server) {} + QueueItem(const sd_gui_utils::networks::RemoteQueueItem& item) + : sd_gui_utils::networks::RemoteQueueItem(item) {} + QueueItem(const QueueItem& item) + : sd_gui_utils::networks::RemoteQueueItem(item), images(item.images), rawImages(item.rawImages), initial_image(item.initial_image), mask_image(item.mask_image) {} QueueItem() = default; }; @@ -302,8 +152,7 @@ namespace QM { keep_upscaler_in_memory, need_sha256, generated_sha256, - update_index, - server) + update_index) class QueueManager { public: @@ -330,12 +179,12 @@ namespace QM { std::shared_ptr Duplicate(std::shared_ptr item); std::shared_ptr Duplicate(int id); // @brief Update the item too then update the status. This will store the list of the generated images too - void SetStatus(QM::QueueStatus status, std::shared_ptr); + void SetStatus(QueueStatus status, std::shared_ptr); void PauseAll(); void RestartQueue(); void UnPauseItem(std::shared_ptr item); void PauseItem(std::shared_ptr item); - void SendEventToMainWindow(QM::QueueEvents eventType, std::shared_ptr item = nullptr); + void SendEventToMainWindow(QueueEvents eventType, std::shared_ptr item = nullptr); void OnThreadMessage(wxThreadEvent& e); void SaveJobToFile(int id); void SaveJobToFile(const QM::QueueItem& item); @@ -349,7 +198,7 @@ namespace QM { std::lock_guard lock(queueMutex); if (this->QueueList.find(item->id) != this->QueueList.end()) { item->status_message = reason; - this->SendEventToMainWindow(QM::QueueEvents::ITEM_FAILED, this->QueueList[item->id]); + this->SendEventToMainWindow(QueueEvents::ITEM_FAILED, this->QueueList[item->id]); } } inline void resetRunning(const std::string& reason) { @@ -364,7 +213,7 @@ namespace QM { if (reason.empty() == false) { this->currentItem->status_message = reason; } - this->SendEventToMainWindow(QM::QueueEvents::ITEM_FAILED, this->QueueList[this->currentItem->id]); + this->SendEventToMainWindow(QueueEvents::ITEM_FAILED, this->QueueList[this->currentItem->id]); } } inline void resetRunning(const wxString& reason) { @@ -379,7 +228,7 @@ namespace QM { if (reason.empty() == false) { this->currentItem->status_message = reason.utf8_string(); } - this->SendEventToMainWindow(QM::QueueEvents::ITEM_FAILED, this->QueueList[this->currentItem->id]); + this->SendEventToMainWindow(QueueEvents::ITEM_FAILED, this->QueueList[this->currentItem->id]); } } inline std::shared_ptr GetCurrentItem() { return this->currentItem; } diff --git a/src/ui/utils.hpp b/src/ui/utils.hpp index 170af80..dae6751 100644 --- a/src/ui/utils.hpp +++ b/src/ui/utils.hpp @@ -256,7 +256,6 @@ namespace sd_gui_utils { class config { private: wxConfigBase* configBase = nullptr; - // mutex to protect concurrent access to tcp client config std::mutex mutex; public: @@ -294,13 +293,13 @@ namespace sd_gui_utils { int mainSashPose = 320; bool favorite_models_only = false; - inline void ServerEnable(int server_id, bool enable) { - std::cout << "ServerEnable " << server_id << " " << enable << std::endl; + inline void ServerEnable(int internal_id, bool enable) { + std::cout << "ServerEnable " << internal_id << " " << enable << std::endl; std::lock_guard lock(this->mutex); for (auto it = this->servers.begin(); it != this->servers.end(); ++it) { - if ((*it)->server_id == server_id) { + if ((*it)->internal_id == internal_id) { (*it)->enabled = enable; - std::cout << "ServerEnable done " << server_id << " " << enable << std::endl; + std::cout << "ServerEnable done " << internal_id << " " << enable << std::endl; return; } } @@ -311,7 +310,19 @@ namespace sd_gui_utils { this->servers.push_back(new sd_gui_utils::sdServer(server)); std::cout << "AddTcpServer done" << std::endl; } - inline sd_gui_utils::sdServer* GetTcpServer(int server_id) { + inline sd_gui_utils::sdServer* GetTcpServer(int internal_id) { + std::cout << "GetTcpServer id: " << internal_id << std::endl; + std::lock_guard lock(this->mutex); + for (auto it = this->servers.begin(); it != this->servers.end(); ++it) { + if ((*it)->internal_id == internal_id) { + std::cout << "GetTcpServer done" << std::endl; + return *it; + } + } + std::cout << "GetTcpServer done nullptr" << std::endl; + return nullptr; + } + inline sd_gui_utils::sdServer* GetTcpServer(std::string server_id) { std::cout << "GetTcpServer id: " << server_id << std::endl; std::lock_guard lock(this->mutex); for (auto it = this->servers.begin(); it != this->servers.end(); ++it) { @@ -329,11 +340,11 @@ namespace sd_gui_utils { this->servers.push_back(server); std::cout << "AddTcpServer done" << std::endl; } - inline void RemoveTcpServer(int server_id) { + inline void RemoveTcpServer(int internal_id) { std::cout << "RemoveTcpServer" << std::endl; std::lock_guard lock(this->mutex); for (auto it = this->servers.begin(); it != this->servers.end(); ++it) { - if ((*it)->server_id == server_id) { + if ((*it)->internal_id == internal_id) { delete *it; this->servers.erase(it); std::cout << "RemoveTcpServer done" << std::endl; @@ -354,11 +365,11 @@ namespace sd_gui_utils { return false; } - inline void ServerChangePort(int server_id, int port) { + inline void ServerChangePort(int internal_id, int port) { std::cout << "ServerChangePort" << std::endl; std::lock_guard lock(this->mutex); for (auto it = this->servers.begin(); it != this->servers.end(); ++it) { - if ((*it)->server_id == server_id) { + if ((*it)->internal_id == internal_id) { (*it)->port = port; break; } @@ -366,22 +377,22 @@ namespace sd_gui_utils { std::cout << "ServerChangePort done" << std::endl; } - inline void ServerChangeHost(int server_id, const std::string& host) { + inline void ServerChangeHost(int internal_id, const std::string& host) { std::cout << "ServerChangeHost" << std::endl; std::lock_guard lock(this->mutex); for (auto it = this->servers.begin(); it != this->servers.end(); ++it) { - if ((*it)->server_id == server_id) { + if ((*it)->internal_id == internal_id) { (*it)->host = host; break; } } std::cout << "ServerChangeHost done" << std::endl; } - inline void ServerChangeName(int server_id, const std::string& name) { + inline void ServerChangeName(int internal_id, const std::string& name) { std::cout << "ServerChangeName" << std::endl; std::lock_guard lock(this->mutex); for (auto it = this->servers.begin(); it != this->servers.end(); ++it) { - if ((*it)->server_id == server_id) { + if ((*it)->internal_id == internal_id) { (*it)->name = name; break; } @@ -534,7 +545,7 @@ namespace sd_gui_utils { config->Read("Host", &host); config->Read("Port", &port, 8191); bool enabled = config->ReadBool("Enabled", false); - int id = config->Read("Id", -1); + wxString id = config->Read("Id", wxEmptyString); sd_gui_utils::sdServer* server = new sd_gui_utils::sdServer(host.utf8_string(), port); server->enabled = enabled; server->server_id = id; @@ -643,7 +654,7 @@ namespace sd_gui_utils { this->configBase->Write("Host", wxString::FromUTF8Unchecked(servers[i]->host)); this->configBase->Write("Port", servers[i]->port); this->configBase->Write("Enabled", servers[i]->enabled.load()); - this->configBase->Write("Id", servers[i]->server_id); + this->configBase->Write("Id", wxString::FromUTF8Unchecked(servers[i]->server_id)); this->configBase->SetPath(".."); } this->configBase->SetPath(oldPath); @@ -836,7 +847,7 @@ namespace sd_gui_utils { {schedule_t::AYS, "Ays"}, {schedule_t::GITS, "Gits"}}; - /* JSONize SD Params*/ + enum class ThreadEvents { QUEUE, HASHING_PROGRESS,