diff options
| author | yum <yum.food.vr@gmail.com> | 2022-12-17 17:51:12 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2022-12-17 17:51:12 -0800 |
| commit | ee8213d1d2c2008d2d996929500c9e87dac325a3 (patch) | |
| tree | f5fb3da0fea10a30229c3642c4312fd457ac293a | |
| parent | 4d836989720523cd0363927e3e066f56b9dc445c (diff) | |
Finish python virtual env
GUI can now download all TaSTT dependencies and install them into a
virtual environment.
* Add buttons to check embedded python version & install dependencies
* Add class to wrap interacting with embedded Python
* Put all TaSTT python scripts into a folder
| -rw-r--r-- | GUI/GUI/GUI/Frame.cpp | 116 | ||||
| -rw-r--r-- | GUI/GUI/GUI/Frame.h | 11 | ||||
| -rw-r--r-- | GUI/GUI/GUI/GUI.vcxproj | 2 | ||||
| -rw-r--r-- | GUI/GUI/GUI/GUI.vcxproj.filters | 14 | ||||
| -rw-r--r-- | GUI/GUI/GUI/PythonWrapper.cpp | 54 | ||||
| -rw-r--r-- | GUI/GUI/GUI/PythonWrapper.h | 28 | ||||
| -rw-r--r-- | GUI/package.ps1 | 1 | ||||
| -rw-r--r-- | Python/python310._pth | 5 | ||||
| -rw-r--r-- | Scripts/emotes.py (renamed from emotes.py) | 0 | ||||
| -rw-r--r-- | Scripts/generate_fonts.py (renamed from generate_fonts.py) | 0 | ||||
| -rw-r--r-- | Scripts/generate_params.py (renamed from generate_params.py) | 0 | ||||
| -rw-r--r-- | Scripts/generate_utils.py (renamed from generate_utils.py) | 0 | ||||
| -rw-r--r-- | Scripts/libtastt.py (renamed from libtastt.py) | 0 | ||||
| -rw-r--r-- | Scripts/libunity.py (renamed from libunity.py) | 0 | ||||
| -rw-r--r-- | Scripts/obfuscate.py (renamed from obfuscate.py) | 0 | ||||
| -rw-r--r-- | Scripts/osc_ctrl.py (renamed from osc_ctrl.py) | 0 | ||||
| -rw-r--r-- | Scripts/steamvr.py (renamed from steamvr.py) | 0 | ||||
| -rw-r--r-- | Scripts/string_matcher.py (renamed from string_matcher.py) | 0 | ||||
| -rw-r--r-- | Scripts/transcribe.py (renamed from transcribe.py) | 0 |
19 files changed, 212 insertions, 19 deletions
diff --git a/GUI/GUI/GUI/Frame.cpp b/GUI/GUI/GUI/Frame.cpp index 841bfb9..74683ca 100644 --- a/GUI/GUI/GUI/Frame.cpp +++ b/GUI/GUI/GUI/Frame.cpp @@ -1,23 +1,44 @@ #include "Frame.h"
+#include "PythonWrapper.h"
#include <filesystem>
+#include <string>
+#include <vector>
+
+namespace {
+ enum FrameIds {
+ ID_PY_PANEL,
+ ID_PY_VERSION_BUTTON,
+ ID_PY_SETUP_BUTTON,
+ ID_PY_OUT,
+ };
+};
Frame::Frame()
- : wxFrame(nullptr, wxID_ANY, "TaSTT")
+ : wxFrame(nullptr, wxID_ANY, "TaSTT"),
+ py_panel_(this, ID_PY_PANEL),
+ py_panel_sizer_(wxVERTICAL),
+ py_version_button_(&py_panel_, ID_PY_VERSION_BUTTON, "Check embedded Python version"),
+ py_setup_button_(&py_panel_, ID_PY_SETUP_BUTTON, "Set up Python virtual environment"),
+ py_out_(&py_panel_, ID_PY_OUT, wxEmptyString, wxDefaultPosition,
+ wxSize(/*x_px=*/480, /*y_px=*/160), wxTE_MULTILINE)
{
- Bind(wxEVT_MENU, &Frame::OnExit, this, wxID_EXIT);
+ Bind(wxEVT_MENU, &Frame::OnExit, this, wxID_EXIT);
+ Bind(wxEVT_BUTTON, &Frame::OnGetPythonVersion, this, ID_PY_VERSION_BUTTON);
+ Bind(wxEVT_BUTTON, &Frame::OnSetupPython, this, ID_PY_SETUP_BUTTON);
- // wx needs this to be able to load PNGs.
- wxImage::AddHandler(&png_handler_);
+ // wx needs this to be able to load PNGs.
+ wxImage::AddHandler(&png_handler_);
+ const std::string icon_path = "Resources/logo.png";
+ LoadAndSetIcon(icon_path);
- const std::string logo_path = "Resources/logo.png";
- if (!std::filesystem::exists(logo_path)) {
- wxLogFatalError("Logo is missing from %s", logo_path.c_str());
- }
- wxBitmap icon_img("Resources/logo.png", wxBITMAP_TYPE_PNG);
- wxIcon icon;
- icon.CopyFromBitmap(icon_img);
- SetIcon(icon);
+ wxSize py_out_size(/*x=*/80, /*y=*/20);
+ py_out_.SetSize(py_out_size);
+
+ py_panel_.SetSizer(&py_panel_sizer_);
+ py_panel_sizer_.Add(&py_version_button_);
+ py_panel_sizer_.Add(&py_setup_button_);
+ py_panel_sizer_.Add(&py_out_);
}
void Frame::OnExit(wxCommandEvent& event)
@@ -25,3 +46,74 @@ void Frame::OnExit(wxCommandEvent& event) Close(true);
}
+void Frame::OnGetPythonVersion(wxCommandEvent& event)
+{
+ PythonWrapper py;
+ std::string py_version = py.GetVersion();
+ py_out_.AppendText(py_version + "\n");
+}
+
+void Frame::OnSetupPython(wxCommandEvent& event)
+{
+ PythonWrapper py;
+
+ py_out_.AppendText("Setting up Python virtual environment\n");
+ py_out_.AppendText("This could take several minutes, please be patient!\n");
+ py_out_.AppendText("This will download ~5GB of dependencies.\n");
+ py_out_.AppendText("Dependencies are installed in the executable folder, "
+ "so deleting the folder is all that's needed to undo this.");
+
+ {
+ std::string py_out;
+ std::ostringstream py_out_oss;
+ py_out_oss << "Installing pip" << std::endl;
+ py_out_.AppendText(py_out_oss.str());
+ if (!py.InstallPip(&py_out)) {
+ std::ostringstream py_out_oss;
+ py_out_oss << "Failed to install pip: " << py_out;
+ py_out_.AppendText(py_out_oss.str());
+ }
+ }
+
+ const std::vector<std::string> pip_deps{
+ "pillow",
+ "pydub",
+ "pyaudio",
+ "playsound==1.2.2",
+ "torch --extra-index-url https://download.pytorch.org/whl/cu116",
+ "git+https://github.com/openai/whisper.git",
+ "openvr",
+ "editdistance",
+ "pydub",
+ "python-osc",
+ };
+
+ for (const auto& pip_dep : pip_deps) {
+ {
+ std::ostringstream py_out_oss;
+ py_out_oss << "Installing " << pip_dep << std::endl;
+ py_out_.AppendText(py_out_oss.str());
+ }
+ std::string py_out;
+ bool res = py.InvokeWithArgs({ "-m", "pip", "install", pip_dep }, &py_out);
+ if (!res) {
+ std::ostringstream py_out_oss;
+ py_out_oss << "Failed to install " << pip_dep << ": " << py_out << std::endl;
+ py_out_.AppendText(py_out_oss.str());
+ return;
+ }
+ }
+
+ py_out_.AppendText("Python virtual environment successfully set up!\n");
+}
+
+void Frame::LoadAndSetIcon(const std::string& icon_path) {
+ if (!std::filesystem::exists(icon_path)) {
+ wxLogFatalError("Logo is missing from %s", icon_path.c_str());
+ }
+ wxBitmap icon_img(icon_path, wxBITMAP_TYPE_PNG);
+ wxIcon icon;
+ icon.CopyFromBitmap(icon_img);
+ SetIcon(icon);
+}
+
diff --git a/GUI/GUI/GUI/Frame.h b/GUI/GUI/GUI/Frame.h index 4dcfd4a..62e9169 100644 --- a/GUI/GUI/GUI/Frame.h +++ b/GUI/GUI/GUI/Frame.h @@ -13,8 +13,15 @@ public: private:
wxPNGHandler png_handler_;
+ wxPanel py_panel_;
+ wxBoxSizer py_panel_sizer_;
+ wxButton py_version_button_;
+ wxButton py_setup_button_;
+ wxTextCtrl py_out_;
- void OnHello(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
- void OnAbout(wxCommandEvent& event);
+ void OnGetPythonVersion(wxCommandEvent& event);
+ void OnSetupPython(wxCommandEvent& event);
+
+ void LoadAndSetIcon(const std::string& icon_path);
};
diff --git a/GUI/GUI/GUI/GUI.vcxproj b/GUI/GUI/GUI/GUI.vcxproj index 79bb220..223f47e 100644 --- a/GUI/GUI/GUI/GUI.vcxproj +++ b/GUI/GUI/GUI/GUI.vcxproj @@ -138,10 +138,12 @@ <ClCompile Include="App.cpp" />
<ClCompile Include="Frame.cpp" />
<ClCompile Include="main.cpp" />
+ <ClCompile Include="PythonWrapper.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="App.h" />
<ClInclude Include="Frame.h" />
+ <ClInclude Include="PythonWrapper.h" />
<ClInclude Include="ScopeGuard.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/GUI/GUI/GUI/GUI.vcxproj.filters b/GUI/GUI/GUI/GUI.vcxproj.filters index c332693..74e4659 100644 --- a/GUI/GUI/GUI/GUI.vcxproj.filters +++ b/GUI/GUI/GUI/GUI.vcxproj.filters @@ -24,16 +24,22 @@ <ClCompile Include="Frame.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="PythonWrapper.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="ScopeGuard.h">
- <Filter>Source Files</Filter>
+ <ClInclude Include="PythonWrapper.h">
+ <Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="App.h">
- <Filter>Source Files</Filter>
+ <Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Frame.h">
- <Filter>Source Files</Filter>
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ScopeGuard.h">
+ <Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp new file mode 100644 index 0000000..27d12fd --- /dev/null +++ b/GUI/GUI/GUI/PythonWrapper.cpp @@ -0,0 +1,54 @@ +#include "PythonWrapper.h" + +#include <stdio.h> + +#include <sstream> + +bool PythonWrapper::InvokeWithArgs(std::vector<std::string>&& args, std::string* out) { + std::ostringstream cmd_oss; + cmd_oss << "Resources/Python/python.exe"; + for (const auto& arg : args) { + cmd_oss << " " << arg; + } + + wxArrayString cmd_output_ary; + long result = wxExecute(cmd_oss.str(), cmd_output_ary); + std::ostringstream cmd_out_oss; + for (const auto& line : cmd_output_ary) { + if (!cmd_out_oss.str().empty()) { + cmd_out_oss << std::endl; + } + cmd_out_oss << line; + } + if (result == -1) { + std::ostringstream err_oss; + err_oss << "Error while executing python command \"" << cmd_oss.str() << "\": Failed to launch process"; + *out = err_oss.str(); + return false; + } else if (result) { + std::ostringstream err_oss; + err_oss << "Error while executing python command \"" << cmd_oss.str() << "\": Process returned " << result << ": " << cmd_out_oss.str(); + *out = err_oss.str(); + return false; + } + + *out = cmd_out_oss.str(); + return true; +} + + +std::string PythonWrapper::GetVersion() { + std::string result; + bool ok = InvokeWithArgs({ "--version" }, &result); + if (!ok) { + wxLogFatalError("Failed to get python version: %s", result.c_str()); + } + return result; +} + +bool PythonWrapper::InstallPip(std::string* out) { + std::string result; + + std::string pip_path = "Resources/Python/get-pip.py"; + return InvokeWithArgs({ pip_path }, out); +} diff --git a/GUI/GUI/GUI/PythonWrapper.h b/GUI/GUI/GUI/PythonWrapper.h new file mode 100644 index 0000000..607507d --- /dev/null +++ b/GUI/GUI/GUI/PythonWrapper.h @@ -0,0 +1,28 @@ +#pragma once + +#include <wx/wxprec.h> + +#ifndef WX_PRECOMP +#include <wx/wx.h> +#endif + +#include <string> +#include <vector> + +/* + * This class wraps interactions with the embedded Python interpreter. +*/ +class PythonWrapper +{ +public: + // Invoke the interpreter with arguments. + // On error, sets `out` to an error message and returns false. + bool InvokeWithArgs(std::vector<std::string>&& args, std::string* out); + + // Execute python --version. + std::string GetVersion(); + + // Execute get-pip.py. + bool InstallPip(std::string* out); +}; + diff --git a/GUI/package.ps1 b/GUI/package.ps1 index 4b25f3f..0c2cec0 100644 --- a/GUI/package.ps1 +++ b/GUI/package.ps1 @@ -8,5 +8,6 @@ mkdir $install_dir > $null mkdir $install_dir/Resources > $null
cp ../Images/logo.png TaSTT/Resources
cp -Recurse ../Python TaSTT/Resources/Python
+cp -Recurse ../Scripts TaSTT/Resources/Scripts
cp GUI/x64/Release/GUI.exe TaSTT/TaSTT.exe
diff --git a/Python/python310._pth b/Python/python310._pth index 2676d09..91fe233 100644 --- a/Python/python310._pth +++ b/Python/python310._pth @@ -4,7 +4,10 @@ python310.zip # Uncomment to run site.main() automatically import site +# TaSTT Python scripts +../Scripts + Lib Lib/site-packages -Scripts Dependencies/future-0.18.2 + diff --git a/emotes.py b/Scripts/emotes.py index b922fdf..b922fdf 100644 --- a/emotes.py +++ b/Scripts/emotes.py diff --git a/generate_fonts.py b/Scripts/generate_fonts.py index ef5bfc5..ef5bfc5 100644 --- a/generate_fonts.py +++ b/Scripts/generate_fonts.py diff --git a/generate_params.py b/Scripts/generate_params.py index 323502c..323502c 100644 --- a/generate_params.py +++ b/Scripts/generate_params.py diff --git a/generate_utils.py b/Scripts/generate_utils.py index e8fcc8b..e8fcc8b 100644 --- a/generate_utils.py +++ b/Scripts/generate_utils.py diff --git a/libtastt.py b/Scripts/libtastt.py index bee535f..bee535f 100644 --- a/libtastt.py +++ b/Scripts/libtastt.py diff --git a/libunity.py b/Scripts/libunity.py index f9e9e28..f9e9e28 100644 --- a/libunity.py +++ b/Scripts/libunity.py diff --git a/obfuscate.py b/Scripts/obfuscate.py index 8d01e10..8d01e10 100644 --- a/obfuscate.py +++ b/Scripts/obfuscate.py diff --git a/osc_ctrl.py b/Scripts/osc_ctrl.py index 34d1a36..34d1a36 100644 --- a/osc_ctrl.py +++ b/Scripts/osc_ctrl.py diff --git a/steamvr.py b/Scripts/steamvr.py index ed4150c..ed4150c 100644 --- a/steamvr.py +++ b/Scripts/steamvr.py diff --git a/string_matcher.py b/Scripts/string_matcher.py index 461f180..461f180 100644 --- a/string_matcher.py +++ b/Scripts/string_matcher.py diff --git a/transcribe.py b/Scripts/transcribe.py index 62e6add..62e6add 100644 --- a/transcribe.py +++ b/Scripts/transcribe.py |
