summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2023-02-04 14:48:44 -0800
committeryum <yum.food.vr@gmail.com>2023-02-04 15:26:41 -0800
commitc3db83cdc93509fb242c9f5d62f2a2f3e21d376c (patch)
tree0ad3ebba01dc95e41a41c623b14ba2d7c98954ef
parent92fea304613bacfa014e1fbaf9fddb82e4f33d62 (diff)
GUI: Add debug panelv0.5.0
Add debug panel with options to show installed packages, clear the pip cache, reset venv, and clear OSC configs. * Refactor synchronous command execution + logging pattern inside PythonWrapper
-rw-r--r--GUI/GUI/GUI/Frame.cpp164
-rw-r--r--GUI/GUI/GUI/Frame.h7
-rw-r--r--GUI/GUI/GUI/PythonWrapper.cpp210
-rw-r--r--GUI/GUI/GUI/PythonWrapper.h3
4 files changed, 220 insertions, 164 deletions
diff --git a/GUI/GUI/GUI/Frame.cpp b/GUI/GUI/GUI/Frame.cpp
index e0663c5..75d9e82 100644
--- a/GUI/GUI/GUI/Frame.cpp
+++ b/GUI/GUI/GUI/Frame.cpp
@@ -16,6 +16,7 @@ namespace {
ID_NAVBAR,
ID_NAVBAR_BUTTON_TRANSCRIBE,
ID_NAVBAR_BUTTON_UNITY,
+ ID_NAVBAR_BUTTON_DEBUG,
ID_PY_PANEL,
ID_PY_CONFIG_PANEL,
ID_PY_APP_CONFIG_PANEL_PAIRS,
@@ -57,6 +58,13 @@ namespace {
ID_UNITY_BYTES_PER_CHAR,
ID_UNITY_ROWS,
ID_UNITY_COLS,
+ ID_DEBUG_PANEL,
+ ID_DEBUG_OUT,
+ ID_DEBUG_CONFIG_PANEL,
+ ID_DEBUG_BUTTON_CLEAR_PIP,
+ ID_DEBUG_BUTTON_LIST_PIP,
+ ID_DEBUG_BUTTON_RESET_VENV,
+ ID_DEBUG_BUTTON_CLEAR_OSC,
};
const wxString kMicChoices[] = {
@@ -278,12 +286,14 @@ Frame::Frame()
{
auto* navbar_button_transcribe = new wxButton(navbar, ID_NAVBAR_BUTTON_TRANSCRIBE, "Transcription");
auto* navbar_button_unity = new wxButton(navbar, ID_NAVBAR_BUTTON_UNITY, "Unity");
+ auto* navbar_button_debug = new wxButton(navbar, ID_NAVBAR_BUTTON_DEBUG, "Debug");
auto* sizer = new wxBoxSizer(wxVERTICAL);
navbar->SetSizer(sizer);
sizer->Add(navbar_button_transcribe, /*proportion=*/0, /*flags=*/wxEXPAND);
sizer->Add(navbar_button_unity, /*proportion=*/0, /*flags=*/wxEXPAND);
+ sizer->Add(navbar_button_debug, /*proportion=*/0, /*flags=*/wxEXPAND);
}
auto* transcribe_panel = new wxPanel(main_panel, ID_PY_PANEL);
@@ -706,22 +716,93 @@ Frame::Frame()
}
unity_panel_->Hide();
+ auto* debug_panel = new wxPanel(main_panel, ID_DEBUG_PANEL);
+ debug_panel_ = debug_panel;
+ {
+ const auto debug_out_sz = wxSize(/*x_px=*/480, /*y_px=*/160);
+ auto* debug_out = new wxTextCtrl(debug_panel, ID_DEBUG_OUT,
+ wxEmptyString,
+ wxDefaultPosition,
+ debug_out_sz, wxTE_MULTILINE | wxTE_READONLY);
+ debug_out->SetMinSize(debug_out_sz);
+ debug_out_ = debug_out;
+
+ auto* debug_config_panel = new wxPanel(debug_panel, ID_DEBUG_CONFIG_PANEL);
+ {
+ auto* debug_button_list_pip = new wxButton(debug_config_panel, ID_DEBUG_BUTTON_LIST_PIP, "List pip packages");
+ debug_button_list_pip->SetToolTip(
+ "List the packages (and versions) installed in the "
+ "virtual environment by pip. Also list the contents "
+ "of the pip cache.");
+ debug_button_list_pip->SetWindowStyleFlag(wxBU_EXACTFIT);
+
+ auto* debug_button_clear_pip = new wxButton(debug_config_panel, ID_DEBUG_BUTTON_CLEAR_PIP, "Clear pip cache");
+ // The real explanation: we install a special version of torch
+ // using --extra-index-url, and I'm like 99% sure that pip
+ // doesn't correctly detect that we want this version instead
+ // of the normal version.
+ debug_button_clear_pip->SetToolTip(
+ "TaSTT uses a piece of software called pip to install "
+ "Python dependencies. To enable reusing packages across "
+ "different Python projects, pip installs packages in a "
+ "system-wide cache. Sometimes the contents of this cache "
+ "can get stale (it's complicated) and clearing the cache "
+ "can fix issues.");
+ debug_button_clear_pip->SetWindowStyleFlag(wxBU_EXACTFIT);
+
+ auto* debug_button_reset_venv = new wxButton(debug_config_panel, ID_DEBUG_BUTTON_RESET_VENV, "Reset python virtual environment");
+ debug_button_reset_venv->SetToolTip(
+ "Uninstall all Python packages installed into the virtual "
+ "environment. Do this after clearing pip!");
+ debug_button_reset_venv->SetWindowStyleFlag(wxBU_EXACTFIT);
+
+ auto* debug_button_clear_osc = new wxButton(debug_config_panel, ID_DEBUG_BUTTON_CLEAR_OSC, "Clear OSC configs");
+ debug_button_clear_osc->SetToolTip(
+ "No idea if this actually does anything valuable yet. I "
+ "think making certain animator changes (s.a. turning on "
+ "multi-byte character encoding) require you to reset "
+ "(i.e. delete) your OSC config. This button deletes all "
+ "your OSC configs.");
+ debug_button_clear_osc->SetWindowStyleFlag(wxBU_EXACTFIT);
+
+ auto* sizer = new wxBoxSizer(wxVERTICAL);
+ debug_config_panel->SetSizer(sizer);
+ sizer->Add(debug_button_list_pip, /*proportion=*/0, /*flags=*/wxEXPAND);
+ sizer->Add(debug_button_clear_pip, /*proportion=*/0, /*flags=*/wxEXPAND);
+ sizer->Add(debug_button_reset_venv, /*proportion=*/0, /*flags=*/wxEXPAND);
+ sizer->Add(debug_button_clear_osc, /*proportion=*/0, /*flags=*/wxEXPAND);
+ }
+
+ auto* sizer = new wxBoxSizer(wxHORIZONTAL);
+ debug_panel->SetSizer(sizer);
+ sizer->Add(debug_config_panel, /*proportion=*/0, /*flags=*/wxEXPAND);
+ sizer->Add(debug_out, /*proportion=*/1, /*flags=*/wxEXPAND);
+ }
+ debug_panel_->Hide();
+
auto* sizer = new wxBoxSizer(wxHORIZONTAL);
main_panel->SetSizer(sizer);
sizer->Add(navbar, /*proportion=*/0, /*flags=*/wxEXPAND);
sizer->Add(transcribe_panel, /*proportion=*/1, /*flags=*/wxEXPAND);
sizer->Add(unity_panel, /*proportion=*/1, /*flags=*/wxEXPAND);
+ sizer->Add(debug_panel, /*proportion=*/1, /*flags=*/wxEXPAND);
}
Bind(wxEVT_MENU, &Frame::OnExit, this, wxID_EXIT);
Bind(wxEVT_BUTTON, &Frame::OnNavbarTranscribe, this, ID_NAVBAR_BUTTON_TRANSCRIBE);
Bind(wxEVT_BUTTON, &Frame::OnNavbarUnity, this, ID_NAVBAR_BUTTON_UNITY);
+ Bind(wxEVT_BUTTON, &Frame::OnNavbarDebug, this, ID_NAVBAR_BUTTON_DEBUG);
Bind(wxEVT_BUTTON, &Frame::OnAppStart, this, ID_PY_APP_START_BUTTON);
Bind(wxEVT_BUTTON, &Frame::OnAppStop, this, ID_PY_APP_STOP_BUTTON);
Bind(wxEVT_TIMER, &Frame::OnAppDrain, this, ID_PY_APP_DRAIN);
Bind(wxEVT_BUTTON, &Frame::OnSetupPython, this, ID_PY_SETUP_BUTTON);
Bind(wxEVT_BUTTON, &Frame::OnDumpMics, this, ID_PY_DUMP_MICS_BUTTON);
Bind(wxEVT_BUTTON, &Frame::OnGenerateFX, this, ID_UNITY_BUTTON_GEN_ANIMATOR);
+ Bind(wxEVT_BUTTON, &Frame::OnListPip, this, ID_DEBUG_BUTTON_LIST_PIP);
+ Bind(wxEVT_BUTTON, &Frame::OnClearPip, this, ID_DEBUG_BUTTON_CLEAR_PIP);
+ Bind(wxEVT_BUTTON, &Frame::OnListPip, this, ID_DEBUG_BUTTON_LIST_PIP);
+ Bind(wxEVT_BUTTON, &Frame::OnResetVenv, this, ID_DEBUG_BUTTON_RESET_VENV);
+ Bind(wxEVT_BUTTON, &Frame::OnClearOSC, this, ID_DEBUG_BUTTON_CLEAR_OSC);
Bind(wxEVT_CHOICE, &Frame::OnUnityParamChange, this, ID_UNITY_CHARS_PER_SYNC);
Bind(wxEVT_CHOICE, &Frame::OnUnityParamChange, this, ID_UNITY_BYTES_PER_CHAR);
@@ -746,6 +827,7 @@ void Frame::OnNavbarTranscribe(wxCommandEvent& event)
{
transcribe_panel_->Show();
unity_panel_->Hide();
+ debug_panel_->Hide();
Resize();
}
@@ -753,6 +835,15 @@ void Frame::OnNavbarUnity(wxCommandEvent& event)
{
transcribe_panel_->Hide();
unity_panel_->Show();
+ debug_panel_->Hide();
+ Resize();
+}
+
+void Frame::OnNavbarDebug(wxCommandEvent& event)
+{
+ transcribe_panel_->Hide();
+ unity_panel_->Hide();
+ debug_panel_->Show();
Resize();
}
@@ -899,6 +990,79 @@ void Frame::OnGenerateFX(wxCommandEvent& event)
}
}
+void Frame::OnListPip(wxCommandEvent& event)
+{
+ Log(debug_out_, "Listing pip packages... ");
+ PythonWrapper::InvokeWithArgs({
+ "-m pip",
+ "list",
+ }, "Failed to list pip packages", debug_out_);
+
+ Log(debug_out_, "Listing pip cache... ");
+ PythonWrapper::InvokeWithArgs({
+ "-m pip",
+ "cache",
+ "list",
+ }, "Failed to list pip cache", debug_out_);
+}
+
+void Frame::OnClearPip(wxCommandEvent& event)
+{
+ Log(debug_out_, "Clearing pip cache... ");
+ PythonWrapper::InvokeWithArgs({
+ "-m pip",
+ "cache",
+ "purge",
+ }, "Failed to clear pip cache", debug_out_);
+}
+
+void Frame::OnResetVenv(wxCommandEvent& event)
+{
+ Log(debug_out_, "Resetting virtual environment... ");
+
+ const std::string py_dir = "Resources/Python/Lib/site-packages";
+
+ if (!std::filesystem::is_directory(py_dir)) {
+ Log(debug_out_, "Python package directory not exist at {}, assuming "
+ "already deleted!\n", py_dir);
+ return;
+ }
+
+ std::error_code err;
+ if (std::filesystem::remove_all(py_dir, err)) {
+ Log(debug_out_, "success!\n");
+ }
+ else {
+ wxLogError("Failed to reset virtual environment: %s", err.message());
+ Log(debug_out_, "failed!\n");
+ }
+}
+
+void Frame::OnClearOSC(wxCommandEvent& event)
+{
+ std::filesystem::path osc_path = "C:/Users";
+ osc_path /= wxGetUserName().ToStdString();
+ osc_path /= "AppData/LocalLow/VRChat/vrchat/OSC";
+ osc_path = osc_path.lexically_normal();
+ Log(debug_out_, "OSC configs are stored at {}\n", osc_path.string());
+
+ if (!std::filesystem::is_directory(osc_path)) {
+ Log(debug_out_, "OSC configs do not exist at {}, assuming already "
+ "deleted!\n", osc_path.string());
+ return;
+ }
+
+ Log(debug_out_, "Deleting OSC configs... ");
+ std::error_code err;
+ if (std::filesystem::remove_all(osc_path, err)) {
+ Log(debug_out_, "success!\n");
+ }
+ else {
+ wxLogError("Failed to delete OSC configs: %s", err.message());
+ Log(debug_out_, "failed!\n");
+ }
+}
+
void Frame::OnUnityParamChangeImpl() {
int chars_per_sync_idx = unity_chars_per_sync_->GetSelection();
if (chars_per_sync_idx == wxNOT_FOUND) {
diff --git a/GUI/GUI/GUI/Frame.h b/GUI/GUI/GUI/Frame.h
index 28c8f09..d179728 100644
--- a/GUI/GUI/GUI/Frame.h
+++ b/GUI/GUI/GUI/Frame.h
@@ -20,9 +20,11 @@ private:
wxPanel* main_panel_;
wxPanel* transcribe_panel_;
wxPanel* unity_panel_;
+ wxPanel* debug_panel_;
wxTextCtrl* transcribe_out_;
wxTextCtrl* unity_out_;
+ wxTextCtrl* debug_out_;
wxTextCtrl* unity_animator_generated_dir_;
wxTextCtrl* unity_animator_generated_name_;
@@ -61,6 +63,7 @@ private:
void OnExit(wxCommandEvent& event);
void OnNavbarTranscribe(wxCommandEvent& event);
void OnNavbarUnity(wxCommandEvent& event);
+ void OnNavbarDebug(wxCommandEvent& event);
void OnSetupPython(wxCommandEvent& event);
void OnDumpMics(wxCommandEvent& event);
void OnAppStart(wxCommandEvent& event);
@@ -70,6 +73,10 @@ private:
void OnGenerateFX(wxCommandEvent& event);
void OnUnityParamChangeImpl();
void OnUnityParamChange(wxCommandEvent& event);
+ void OnListPip(wxCommandEvent& event);
+ void OnClearPip(wxCommandEvent& event);
+ void OnResetVenv(wxCommandEvent& event);
+ void OnClearOSC(wxCommandEvent& event);
void LoadAndSetIcons();
void Resize();
diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp
index 60437d2..2bf1a47 100644
--- a/GUI/GUI/GUI/PythonWrapper.cpp
+++ b/GUI/GUI/GUI/PythonWrapper.cpp
@@ -117,6 +117,30 @@ bool PythonWrapper::InvokeWithArgs(std::vector<std::string>&& args,
std::move(args), py_stdout, py_stderr);
}
+bool PythonWrapper::InvokeWithArgs(std::vector<std::string>&& args,
+ const std::string&& err_msg,
+ wxTextCtrl* const out) {
+ std::string py_stdout, py_stderr;
+ if (InvokeWithArgs(std::move(args), &py_stdout, &py_stderr)) {
+ Log(out, "success!\n");
+ Log(out, py_stdout.c_str());
+ if (!py_stdout.empty()) {
+ Log(out, "\n");
+ }
+ Log(out, py_stderr.c_str());
+ if (!py_stderr.empty()) {
+ Log(out, "\n");
+ }
+ return true;
+ }
+ else {
+ wxLogError("%s: %s", err_msg, py_stderr.c_str());
+ Log(out, "failed!\n");
+ return false;
+ }
+}
+
+
std::string PythonWrapper::GetVersion() {
std::string py_stdout, py_stderr;
bool ok = InvokeWithArgs({ "--version" }, &py_stdout, &py_stderr);
@@ -214,28 +238,13 @@ bool PythonWrapper::GenerateAnimator(
{
Log(out, "Generating shader for {}x{} board (pass 0)...", config.rows, config.cols);
-
- std::string py_stdout, py_stderr;
- if (InvokeWithArgs({ generate_shader_path,
+ if (!InvokeWithArgs({ generate_shader_path,
"--bytes_per_char", std::to_string(config.bytes_per_char),
"--rows", std::to_string(config.rows),
"--cols", std::to_string(config.cols),
"--shader_template", shader_template_path,
"--shader_path", shader_path },
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to generate shader: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "Failed to generate shader", out)) {
return false;
}
}
@@ -243,26 +252,13 @@ bool PythonWrapper::GenerateAnimator(
Log(out, "Generating shader for {}x{} board (pass 1)...", config.rows, config.cols);
std::string py_stdout, py_stderr;
- if (InvokeWithArgs({ generate_shader_path,
+ if (!InvokeWithArgs({ generate_shader_path,
"--bytes_per_char", std::to_string(config.bytes_per_char),
"--rows", std::to_string(config.rows),
"--cols", std::to_string(config.cols),
"--shader_template", shader_lighting_template_path,
"--shader_path", shader_lighting_path },
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to generate shader: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "Failed to generate shader", out)) {
return false;
}
}
@@ -328,203 +324,89 @@ bool PythonWrapper::GenerateAnimator(
}
{
Log(out, "Generating guid.map... ");
- std::string py_stdout, py_stderr;
- if (PythonWrapper::InvokeWithArgs({ libunity_path, "guid_map",
+ if (!InvokeWithArgs({ libunity_path, "guid_map",
"--project_root", Quote(config.assets_path),
"--save_to", Quote(guid_map_path), },
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to generate guid.map: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "Failed to generate guid.map", out)) {
return false;
}
}
{
Log(out, "Generating animations... ");
- std::string py_stdout, py_stderr;
- if (InvokeWithArgs({ libtastt_path, "gen_anims",
+ if (!InvokeWithArgs({ libtastt_path, "gen_anims",
"--gen_anim_dir", Quote(tastt_animations_path),
"--guid_map", Quote(guid_map_path),
"--chars_per_sync", std::to_string(config.chars_per_sync),
"--bytes_per_char", std::to_string(config.bytes_per_char),
"--rows", std::to_string(config.rows),
"--cols", std::to_string(config.cols)},
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to generate animations: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "Failed to generate animations", out)) {
return false;
}
}
{
Log(out, "Generating FX layer... ");
- std::string py_stdout, py_stderr;
- if (InvokeWithArgs({ libtastt_path, "gen_fx",
+ if (!InvokeWithArgs({ libtastt_path, "gen_fx",
"--fx_dest", Quote(tastt_fx0_path),
"--gen_anim_dir", Quote(tastt_animations_path),
"--guid_map", Quote(guid_map_path),
"--chars_per_sync", std::to_string(config.chars_per_sync),
"--bytes_per_char", std::to_string(config.bytes_per_char),
"--rows", std::to_string(config.rows),
- "--cols", std::to_string(config.cols)},
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to generate FX layer: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "--cols", std::to_string(config.cols) },
+ "Failed to generate FX layer", out)) {
return false;
}
}
{
Log(out, "Adding enable/disable toggle... ");
- std::string py_stdout, py_stderr;
- if (InvokeWithArgs({ libunity_path, "add_toggle",
+ if (!InvokeWithArgs({ libunity_path, "add_toggle",
"--fx0", Quote(tastt_fx0_path),
"--fx_dest", Quote(tastt_fx1_path),
"--gen_anim_dir", Quote(tastt_animations_path),
"--guid_map", Quote(guid_map_path), },
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to add enable/disable toggle: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "Failed to add enable/disable toggle", out)) {
return false;
}
}
{
Log(out, "Merging with user animator... ");
- std::string py_stdout, py_stderr;
- if (InvokeWithArgs({ libunity_path, "merge",
+ if (!InvokeWithArgs({ libunity_path, "merge",
"--fx0", Quote(config.fx_path),
"--fx1", Quote(tastt_fx1_path),
"--fx_dest", Quote(tastt_fx2_path), },
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to merge animators: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "Failed to merge animators", out)) {
return false;
}
}
{
Log(out, "Setting noop animations... ");
- std::string py_stdout, py_stderr;
- if (InvokeWithArgs({ libunity_path, "set_noop_anim",
+ if (!InvokeWithArgs({ libunity_path, "set_noop_anim",
"--fx0", Quote(tastt_fx2_path),
"--fx_dest", Quote(tastt_animator_path),
"--gen_anim_dir", Quote(tastt_animations_path),
"--guid_map", Quote(guid_map_path), },
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to set noop animations: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "Failed to set noop animations", out)) {
return false;
}
}
{
Log(out, "Generating avatar parameters... ");
- std::string py_stdout, py_stderr;
- if (InvokeWithArgs({ generate_params_path,
+ if (!InvokeWithArgs({ generate_params_path,
"--old_params", Quote(config.params_path),
"--new_params", Quote(tastt_params_path),
"--chars_per_sync", std::to_string(config.chars_per_sync),
"--bytes_per_char", std::to_string(config.bytes_per_char) },
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to generate avatar parameters: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "Failed to generate avatar parameters", out)) {
return false;
}
}
{
Log(out, "Generating avatar menu... ");
- std::string py_stdout, py_stderr;
- // No idea why, but inlining this into `InvokeWithArgs` confuses the compiler.
- std::vector<std::string> args = { generate_menu_path,
+ if (!InvokeWithArgs({ generate_menu_path,
"--old_menu", Quote(config.menu_path),
- "--new_menu", Quote(tastt_menu_path), };
- if (InvokeWithArgs( std::move(args),
- &py_stdout, &py_stderr)) {
- Log(out, "success!\n");
- Log(out, py_stdout.c_str());
- if (!py_stdout.empty()) {
- Log(out, "\n");
- }
- Log(out, py_stderr.c_str());
- if (!py_stderr.empty()) {
- Log(out, "\n");
- }
- }
- else {
- wxLogError("Failed to generate avatar menu: %s", py_stderr.c_str());
- Log(out, "failed!\n");
+ "--new_menu", Quote(tastt_menu_path) },
+ "Failed to generate avatar menu", out)) {
return false;
}
}
diff --git a/GUI/GUI/GUI/PythonWrapper.h b/GUI/GUI/GUI/PythonWrapper.h
index c28a1f1..4ae4583 100644
--- a/GUI/GUI/GUI/PythonWrapper.h
+++ b/GUI/GUI/GUI/PythonWrapper.h
@@ -37,6 +37,9 @@ namespace PythonWrapper
bool InvokeWithArgs(std::vector<std::string>&& args, std::string* py_stdout,
std::string* py_stderr = NULL);
+ bool InvokeWithArgs(std::vector<std::string>&& args,
+ const std::string&& err_msg, wxTextCtrl* out);
+
// Execute python --version.
std::string GetVersion();