diff options
Diffstat (limited to 'GUI')
39 files changed, 0 insertions, 6160 deletions
diff --git a/GUI/.gitignore b/GUI/.gitignore deleted file mode 100644 index 727e4ae..0000000 --- a/GUI/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ignore generated package files -TaSTT -TaSTT.zip - -# ignore net-fetched dependencies -PortableGit* -Python* -python-* -UwwwuPP -Profanity -curl - -# Frequently created during development -freeze.txt diff --git a/GUI/GUI/.gitignore b/GUI/GUI/.gitignore deleted file mode 100644 index 7082b1d..0000000 --- a/GUI/GUI/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Don't check in build artifacts -x64 -x86 -# Ignore visual studio cruft -.vs diff --git a/GUI/GUI/GUI.sln b/GUI/GUI/GUI.sln deleted file mode 100644 index 5ef5534..0000000 --- a/GUI/GUI/GUI.sln +++ /dev/null @@ -1,31 +0,0 @@ -
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.4.33122.133
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GUI", "GUI\GUI.vcxproj", "{E17AD8B1-0565-459B-B8D0-2024CC6C5CD4}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x64 = Debug|x64
- Debug|x86 = Debug|x86
- Release|x64 = Release|x64
- Release|x86 = Release|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {E17AD8B1-0565-459B-B8D0-2024CC6C5CD4}.Debug|x64.ActiveCfg = Debug|x64
- {E17AD8B1-0565-459B-B8D0-2024CC6C5CD4}.Debug|x64.Build.0 = Debug|x64
- {E17AD8B1-0565-459B-B8D0-2024CC6C5CD4}.Debug|x86.ActiveCfg = Debug|Win32
- {E17AD8B1-0565-459B-B8D0-2024CC6C5CD4}.Debug|x86.Build.0 = Debug|Win32
- {E17AD8B1-0565-459B-B8D0-2024CC6C5CD4}.Release|x64.ActiveCfg = Release|x64
- {E17AD8B1-0565-459B-B8D0-2024CC6C5CD4}.Release|x64.Build.0 = Release|x64
- {E17AD8B1-0565-459B-B8D0-2024CC6C5CD4}.Release|x86.ActiveCfg = Release|Win32
- {E17AD8B1-0565-459B-B8D0-2024CC6C5CD4}.Release|x86.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {FA0FE5DA-8B30-47E0-9715-792C7CA1D5F8}
- EndGlobalSection
-EndGlobal
diff --git a/GUI/GUI/GUI/.gitignore b/GUI/GUI/GUI/.gitignore deleted file mode 100644 index 75f9933..0000000 --- a/GUI/GUI/GUI/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Don't check in build artifacts -x64 -x86 -# No .rc generated files -GUI.APS -# No fetched files -ryml.h -whisper/ -oatpp/ diff --git a/GUI/GUI/GUI/App.cpp b/GUI/GUI/GUI/App.cpp deleted file mode 100644 index 94a01a4..0000000 --- a/GUI/GUI/GUI/App.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "App.h"
-#include "Frame.h"
-
-bool MyApp::OnInit()
-{
- Frame* frame = new Frame();
-
- frame->Show(true);
-
- return true;
-}
diff --git a/GUI/GUI/GUI/App.h b/GUI/GUI/GUI/App.h deleted file mode 100644 index fe6eeec..0000000 --- a/GUI/GUI/GUI/App.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once
-
-#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-class MyApp : public wxApp
-{
-public:
- virtual bool OnInit();
-};
diff --git a/GUI/GUI/GUI/BrowserSource.cpp b/GUI/GUI/GUI/BrowserSource.cpp deleted file mode 100644 index fce1bee..0000000 --- a/GUI/GUI/GUI/BrowserSource.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "BrowserSource.h"
-#include "Logging.h"
-#include "ScopeGuard.h"
-#include "WebCommon.h"
-#include "WebServer.h"
-
-using ::Logging::Log;
-
-BrowserSource::BrowserSource(uint16_t port, wxTextCtrl *out, Transcript *transcript)
- : port_(port), out_(out), transcript_(transcript)
-{}
-
-void BrowserSource::Run(volatile bool* run)
-{
- WebServer::WebServer ws(out_, port_);
-
- ws.RegisterPathHandler("GET", "/",
- [&](int& status_code, std::string& payload,
- WebServer::ContentType& type) -> void {
- auto html_path = std::filesystem::path("Resources/BrowserSource/index.html");
-
- std::ifstream html_ifs(html_path);
- std::vector<char> resp(4096 * 16, 0);
- html_ifs.read(resp.data(), resp.size());
-
- std::string html(resp.data());
- resp.clear();
-
- size_t pos = 0;
- std::string key = "%PORT%";
- std::string value = std::to_string(port_);
- while ((pos = html.find("%PORT%", pos)) != std::string::npos) {
- html.replace(pos, key.size(), value);
- pos += value.size();
- }
-
- status_code = 200;
- payload = html;
- type = WebServer::HTML;
- });
-
- ws.RegisterPathHandler("GET", "/api/transcript",
- [&](int& status_code, std::string& payload,
- WebServer::ContentType& type) -> void {
- status_code = 200;
-
- std::ostringstream transcript_oss;
- std::vector<std::string> transcript = transcript_->Get();
- // Hack: escape transcription to work inside JSON blob.
- for (auto& segment : transcript) {
- size_t pos;
- while ((pos = segment.find('"')) != std::string::npos) {
- segment[pos] = '\'';
- }
- transcript_oss << segment;
- }
-
- std::ostringstream preview_oss;
- std::vector<std::string> preview = transcript_->GetPreview();
- // Hack: escape transcription to work inside JSON blob.
- for (auto& segment : preview) {
- size_t pos;
- while ((pos = segment.find('"')) != std::string::npos) {
- segment[pos] = '\'';
- }
- preview_oss << segment;
- }
-
- bool is_final = transcript_->IsFinalized();
-
- std::ostringstream resp_oss;
- resp_oss << "{";
- resp_oss << "\"transcript\":\"" << transcript_oss.str() << "\",";
- resp_oss << "\"preview\":\"" << preview_oss.str() << "\",";
- resp_oss << "\"is_final\":" << std::to_string(is_final ? 1 : 0) << "";
- resp_oss << "}";
- payload = resp_oss.str();
- type = WebServer::JSON;
-
- //Log(out_, "Serving transcript to port {}: {}\n", port_, transcript_oss.str());
- });
-
- if (!ws.Run(run)) {
- Log(out_, "Failed to launch browser source!\n");
- }
- return;
-}
diff --git a/GUI/GUI/GUI/BrowserSource.h b/GUI/GUI/GUI/BrowserSource.h deleted file mode 100644 index fe732ba..0000000 --- a/GUI/GUI/GUI/BrowserSource.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once
-
-#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#include "Transcript.h"
-
-#include <stdint.h>
-
-#include <filesystem>
-#include <fstream>
-
-class BrowserSource
-{
-public:
- BrowserSource(uint16_t port, wxTextCtrl *out, Transcript *transcript);
-
- void Run(volatile bool* run);
-
-private:
- const uint16_t port_;
- wxTextCtrl* const out_;
- Transcript* const transcript_;
-};
-
diff --git a/GUI/GUI/GUI/Config.cpp b/GUI/GUI/GUI/Config.cpp deleted file mode 100644 index 948b1af..0000000 --- a/GUI/GUI/GUI/Config.cpp +++ /dev/null @@ -1,230 +0,0 @@ -#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#include "Config.h"
-#include "ConfigMarshal.h"
-#include "Logging.h"
-
-#include <fstream>
-#include <memory>
-#include <string>
-
-using ::Logging::Log;
-
-bool Config::Serialize(const std::filesystem::path& path,
- const ConfigMarshal& cm) {
- // If there's an old config, delete it.
- struct stat tmpstat;
- if (stat(path.string().c_str(), &tmpstat) == 0) {
- if (::_unlink(path.string().c_str())) {
- Log(out_, "Failed to delete old config at {}: {}\n",
- path.string().c_str(), strerror(errno));
- return false;
- }
- }
-
- // Write the config to a tmp file. If we crash in the middle of this, it
- // doesn't matter, since the next process will just overwrite it.
- std::filesystem::path tmp_path = path;
-
- if (stat(tmp_path.string().c_str(), &tmpstat) == 0) {
- if (::_unlink(tmp_path.string().c_str())) {
- Log(out_, "Failed to delete old tmp config at {}: {}\n",
- tmp_path.string().c_str(), strerror(errno));
- return false;
- }
- }
-
- if (!cm.Save(tmp_path)) {
- Log(out_, "Failed to save config to {}\n", tmp_path.string());
- return false;
- }
-
- // File renames within the same filesystem are atomic, so there's no risk
- // of leaving a corrupt file on disk.
- if (rename(tmp_path.string().c_str(), path.string().c_str()) != 0) {
- Log(out_, "Failed to save config to {}: {}\n", path.string().c_str(),
- strerror(errno));
- return false;
- }
-
- return true;
-}
-
-bool Config::Deserialize(const std::filesystem::path& path,
- ConfigMarshal& cm) {
- return cm.Load(path);
-}
-
-AppConfig::AppConfig(wxTextCtrl* out)
- : Config(out),
-
- microphone("index"),
- language("english"),
- language_target("Do not translate"),
- model("small.en"),
- model_translation("nllb-200-distilled-600M"),
- button("left joystick"),
- prio("normal"),
- compute_type("float16"),
-
- enable_local_beep(true),
- enable_orig_lang(true),
- enable_browser_src(false),
- browser_src_port(8097),
- commit_fuzz_threshold(4),
- use_cpu(false),
- use_flash_attention(false),
- use_builtin(true),
- enable_uwu_filter(false),
- remove_trailing_period(false),
- enable_uppercase_filter(false),
- enable_lowercase_filter(false),
- enable_profanity_filter(false),
- enable_debug_mode(false),
- reset_on_toggle(true),
- enable_previews(true),
- enable_lock_at_spawn(true),
- gpu_idx(0),
- min_silence_duration_ms(250),
- max_speech_duration_s(10),
- reset_after_silence_s(15),
- transcription_loop_delay_ms(100),
- keybind("ctrl+x"),
-
- chars_per_sync(10),
- bytes_per_char(1),
- rows(4),
- cols(40),
- texture_sz(512),
-
- assets_path(),
- fx_path(),
- params_path(),
- menu_path(),
- unity_generated_dir("TaSTT_Generated"),
- clear_osc(true),
- enable_phonemes(false)
-{}
-
-bool AppConfig::Serialize(const std::filesystem::path& path) {
- ConfigMarshal cm(out_);
-
- cm.Set("microphone", microphone);
- cm.Set("language", language);
- cm.Set("language_target", language_target);
- cm.Set("model", model);
- cm.Set("model_translation", model_translation);
- cm.Set("button", button);
- cm.Set("prio", prio);
- cm.Set("compute_type", compute_type);
-
- cm.Set("enable_local_beep", enable_local_beep);
- cm.Set("enable_orig_lang", enable_orig_lang);
- cm.Set("enable_browser_src", enable_browser_src);
- cm.Set("browser_src_port", browser_src_port);
- cm.Set("commit_fuzz_threshold", commit_fuzz_threshold);
- cm.Set("use_cpu", use_cpu);
- cm.Set("use_flash_attention", use_flash_attention);
- cm.Set("use_builtin", use_builtin);
- cm.Set("enable_uwu_filter", enable_uwu_filter);
- cm.Set("remove_trailing_period", remove_trailing_period);
- cm.Set("enable_uppercase_filter", enable_uppercase_filter);
- cm.Set("enable_lowercase_filter", enable_lowercase_filter);
- cm.Set("enable_profanity_filter", enable_profanity_filter);
- cm.Set("enable_debug_mode", enable_debug_mode);
- cm.Set("reset_on_toggle", reset_on_toggle);
- cm.Set("enable_previews", enable_previews);
- cm.Set("enable_lock_at_spawn", enable_lock_at_spawn);
- cm.Set("gpu_idx", gpu_idx);
- cm.Set("min_silence_duration_ms", min_silence_duration_ms);
- cm.Set("max_speech_duration_s", max_speech_duration_s);
- cm.Set("reset_after_silence_s", reset_after_silence_s);
- cm.Set("transcription_loop_delay_ms", transcription_loop_delay_ms);
- cm.Set("keybind", keybind);
-
- cm.Set("chars_per_sync", chars_per_sync);
- cm.Set("bytes_per_char", bytes_per_char);
- cm.Set("rows", rows);
- cm.Set("cols", cols);
- cm.Set("texture_sz", texture_sz);
-
- cm.Set("assets_path", assets_path);
- cm.Set("fx_path", fx_path);
- cm.Set("params_path", params_path);
- cm.Set("menu_path", menu_path);
- cm.Set("unity_generated_dir", unity_generated_dir);
- cm.Set("clear_osc", clear_osc);
- cm.Set("enable_phonemes", enable_phonemes);
-
- return Config::Serialize(path, cm);
-}
-
-bool AppConfig::Deserialize(const std::filesystem::path& path) {
- std::error_code err;
- if (!std::filesystem::exists(path, err)) {
- *this = AppConfig(out_);
- return true;
- }
-
- ConfigMarshal cm(out_);
- if (!Config::Deserialize(path, cm)) {
- Log(out_, "Deserialization failed at {}\n", path.string());
- return false;
- }
-
- AppConfig c(out_);
- cm.Get("microphone", c.microphone);
- cm.Get("language", c.language);
- cm.Get("language_target", c.language_target);
- cm.Get("model", c.model);
- cm.Get("model_translation", c.model_translation);
- cm.Get("button", c.button);
- cm.Get("prio", c.prio);
- cm.Get("compute_type", c.compute_type);
-
- cm.Get("enable_local_beep", c.enable_local_beep);
- cm.Get("enable_orig_lang", c.enable_orig_lang);
- cm.Get("enable_browser_src", c.enable_browser_src);
- cm.Get("browser_src_port", c.browser_src_port);
- cm.Get("commit_fuzz_threshold", c.commit_fuzz_threshold);
- cm.Get("use_cpu", c.use_cpu);
- cm.Get("use_flash_attention", c.use_flash_attention);
- cm.Get("use_builtin", c.use_builtin);
- cm.Get("enable_uwu_filter", c.enable_uwu_filter);
- cm.Get("remove_trailing_period", c.remove_trailing_period);
- cm.Get("enable_uppercase_filter", c.enable_uppercase_filter);
- cm.Get("enable_lowercase_filter", c.enable_lowercase_filter);
- cm.Get("enable_profanity_filter", c.enable_profanity_filter);
- cm.Get("enable_debug_mode", c.enable_debug_mode);
- cm.Get("reset_on_toggle", c.reset_on_toggle);
- cm.Get("enable_previews", c.enable_previews);
- cm.Get("enable_lock_at_spawn", c.enable_lock_at_spawn);
- cm.Get("gpu_idx", c.gpu_idx);
- cm.Get("min_silence_duration_ms", c.min_silence_duration_ms);
- cm.Get("max_speech_duration_s", c.max_speech_duration_s);
- cm.Get("reset_after_silence_s", c.reset_after_silence_s);
- cm.Get("transcription_loop_delay_ms", c.transcription_loop_delay_ms);
- cm.Get("keybind", c.keybind);
-
- cm.Get("chars_per_sync", c.chars_per_sync);
- cm.Get("bytes_per_char", c.bytes_per_char);
- cm.Get("rows", c.rows);
- cm.Get("cols", c.cols);
- cm.Get("texture_sz", c.texture_sz);
-
- cm.Get("assets_path", c.assets_path);
- cm.Get("fx_path", c.fx_path);
- cm.Get("params_path", c.params_path);
- cm.Get("menu_path", c.menu_path);
- cm.Get("unity_generated_dir", c.unity_generated_dir);
- cm.Get("clear_osc", c.clear_osc);
- cm.Get("enable_phonemes", c.enable_phonemes);
-
- *this = std::move(c);
- return true;
-}
-
diff --git a/GUI/GUI/GUI/Config.h b/GUI/GUI/GUI/Config.h deleted file mode 100644 index 48b49a2..0000000 --- a/GUI/GUI/GUI/Config.h +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once
-
-#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#include "ConfigMarshal.h"
-
-#include <filesystem>
-
-// Represents a disk-backed configuration. Knows how to save to disk
-// (Serialize) and restore from disk (Deserialize).
-class Config {
-public:
- Config(wxTextCtrl* out) : out_(out) {}
-
- virtual ~Config() {}
-
- virtual bool Serialize(const std::filesystem::path& path) = 0;
-
- virtual bool Deserialize(const std::filesystem::path& path) = 0;
-
-protected:
- virtual bool Serialize(const std::filesystem::path& path,
- const ConfigMarshal& cm);
-
- virtual bool Deserialize(const std::filesystem::path& path,
- ConfigMarshal& cm);
-
- wxTextCtrl* out_;
-};
-
-// Represents the configurable fields for the GUI. Used by both the
-// Transcription panel and the Unity panel.
-class AppConfig : public Config {
-public:
- virtual ~AppConfig() {}
-
- AppConfig(wxTextCtrl* out);
-
- bool Serialize(const std::filesystem::path& path) override;
-
- bool Deserialize(const std::filesystem::path& path) override;
-
- // The default path at which configs are serialized.
- static constexpr char kConfigPath[] = "Resources/app_config.yml";
-
- // Transcription-specific settings.
- std::string microphone;
- std::string language;
- std::string language_target;
- std::string model;
- std::string model_translation;
- std::string button;
- std::string prio;
- std::string compute_type;
-
- bool enable_local_beep;
- bool enable_orig_lang;
- bool enable_browser_src;
- int browser_src_port;
- int commit_fuzz_threshold;
- bool use_cpu;
- bool use_flash_attention;
- bool use_builtin;
- bool enable_uwu_filter;
- bool remove_trailing_period;
- bool enable_uppercase_filter;
- bool enable_lowercase_filter;
- bool enable_profanity_filter;
- bool enable_debug_mode;
- bool reset_on_toggle;
- bool enable_previews;
- bool enable_lock_at_spawn;
- int gpu_idx;
- int min_silence_duration_ms;
- int max_speech_duration_s;
- int reset_after_silence_s;
- int transcription_loop_delay_ms;
- std::string keybind;
-
- // Unity and transcription shared settings.
- int chars_per_sync;
- int bytes_per_char;
- int rows;
- int cols;
- int texture_sz;
-
- // Unity-specific settings.
- std::string assets_path;
- std::string fx_path;
- std::string params_path;
- std::string menu_path;
- std::string unity_generated_dir;
- bool clear_osc;
- bool enable_phonemes;
-};
-
diff --git a/GUI/GUI/GUI/ConfigMarshal.h b/GUI/GUI/GUI/ConfigMarshal.h deleted file mode 100644 index 0f40ed4..0000000 --- a/GUI/GUI/GUI/ConfigMarshal.h +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once
-
-#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#include "Logging.h"
-
-#include <filesystem>
-#include <fstream>
-#include <map>
-#include <sstream>
-#include <string>
-#include <type_traits>
-
-class ConfigMarshal
-{
-public:
- ConfigMarshal(wxTextCtrl* const out)
- : out_(out)
- {}
-
- bool Save(const std::filesystem::path& path) const {
- std::ostringstream oss;
- for (const auto& [k, v] : kv_str_) {
- oss << k << ": " << v << std::endl;
- }
- for (const auto& [k, v] : kv_int_) {
- oss << k << ": " << std::to_string(v) << std::endl;
- }
- for (const auto& [k, v] : kv_float_) {
- oss << k << ": " << std::to_string(v) << std::endl;
- }
-
- std::ofstream ofs(path.string());
- ofs << oss.str();
- ofs.close();
-
- return true;
- }
-
- bool Load(const std::filesystem::path& path) {
- std::ifstream ifs(path.string());
- std::string line;
- while (std::getline(ifs, line)) {
- int n_words = 0;
-
- std::string delim = ": ";
- size_t delim_pos = line.find(delim, 0);
- if (delim_pos == std::string::npos) {
- Logging::Log(out_, "Invalid config file: line {} has no delimiter\n", line);
- return false;
- }
- std::string key = line.substr(0, delim_pos);
- std::string val = line.substr(delim_pos + delim.length());
-
- try {
- size_t pos;
- int val_i = std::stoi(val, &pos);
- if (pos == val.length()) {
- // The entire value is an int -> interpret as an int. Corollary: users
- // can't store ints as strings!
- kv_int_[key] = val_i;
- continue;
- }
- }
- catch (const std::invalid_argument&) {}
- catch (const std::out_of_range&) {}
-
- try {
- size_t pos;
- float val_f = std::stof(val, &pos);
- if (pos == val.length()) {
- // The entire value is a float -> interpret as a float. Corollary: users
- // can't store floats as strings!
- kv_float_[key] = val_f;
- continue;
- }
- }
- catch (const std::invalid_argument&) {}
- catch (const std::out_of_range&) {}
-
- kv_str_[key] = val;
- }
- return true;
- }
-
- template <typename T>
- bool Set(const std::string& key, const T& value) {
- if constexpr (std::is_same_v<T, std::string>) {
- kv_str_[key] = value;
- return true;
- }
- if constexpr (std::is_same_v<T, int> || std::is_same_v<T, bool>) {
- kv_int_[key] = static_cast<int>(value);
- return true;
- }
- if constexpr (std::is_same_v<T, float>) {
- kv_float_[key] = value;
- return true;
- }
- Logging::Log(out_, "ConfigMarshal unsupported type: {}\n", typeid(T).name());
- return false;
- }
-
- template <typename T>
- bool Get(const std::string& key, T& value) const {
- if constexpr (std::is_same_v<T, std::string>) {
- auto iter = kv_str_.find(key);
- if (iter == kv_str_.end()) {
- // Edge case: string may be represented entirely as an int, so
- // it was parsed out as an int.
- auto iter = kv_int_.find(key);
- if (iter == kv_int_.end()) {
- Logging::Log(out_, "Config contains no field named `{}`\n", key);
- return false;
- }
- value = std::to_string(iter->second);
- return true;
- }
- value = iter->second;
- return true;
- }
- if constexpr (std::is_same_v<T, float>) {
- auto iter = kv_float_.find(key);
- if (iter == kv_float_.end()) {
- Logging::Log(out_, "Config contains no field named `{}`\n", key);
- return false;
- }
- value = iter->second;
- return true;
- }
- if constexpr (std::is_same_v<T, int> || std::is_same_v<T, bool>) {
- auto iter = kv_int_.find(key);
- if (iter == kv_int_.end()) {
- Logging::Log(out_, "Config contains no field named `{}`\n", key);
- return false;
- }
- if constexpr (std::is_same_v<T, bool>) {
- if (iter->second < 0 || iter->second > 1) {
- Logging::Log(out_, "Config field {} is out of boolean range: {}\n", key, iter->second);
- return false;
- }
- }
- value = static_cast<T>(iter->second);
- return true;
- }
- Logging::Log(out_, "ConfigMarshal unsupported type: {}\n", typeid(T).name());
- return false;
- }
-
-
-private:
- wxTextCtrl* out_;
-
- std::map<std::string, std::string> kv_str_;
- std::map<std::string, int> kv_int_;
- std::map<std::string, float> kv_float_;
-};
diff --git a/GUI/GUI/GUI/Frame.cpp b/GUI/GUI/GUI/Frame.cpp deleted file mode 100644 index 697e18a..0000000 --- a/GUI/GUI/GUI/Frame.cpp +++ /dev/null @@ -1,2757 +0,0 @@ -#include "BrowserSource.h"
-#include "Frame.h"
-#include "Logging.h"
-#include "PythonWrapper.h"
-#include "ScopeGuard.h"
-#include "Util.h"
-
-#include <filesystem>
-#include <fstream>
-#include <numeric>
-#include <regex>
-#include <sstream>
-#include <string>
-#include <vector>
-#include <wx/filepicker.h>
-#include <wx/txtstrm.h>
-
-// Does `lhs_type lhs = rhs`, where rhs returns `std::optional<lhs_type>`.
-// If the optional doesn't return a value, this returns.
-// TODO(yum) do this without creating a named temporary.
-// Example:
-// ASSIGN_OR_RETURN(int, foo, 1)
-#define ASSIGN_OR_RETURN_VOID(lhs_type, lhs, rhs) \
- std::optional<lhs_type> lhs ## _tmp = rhs; \
- if (!lhs ## _tmp.has_value()) return; \
- lhs_type lhs = std::move(lhs ## _tmp).value()
-
-#define ASSIGN_OR_RETURN_BOOL(lhs_type, lhs, rhs) \
- std::optional<lhs_type> lhs ## _tmp = rhs; \
- if (!lhs ## _tmp.has_value()) return false; \
- lhs_type lhs = std::move(lhs ## _tmp).value()
-
-using ::Logging::DrainAsyncOutput;
-using ::Logging::Log;
-
-namespace {
- enum FrameIds {
- ID_MAIN_PANEL,
- 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,
- ID_PY_DUMP_MICS_BUTTON,
- ID_PY_APP_DRAIN,
- ID_PY_APP_START_BUTTON,
- ID_PY_APP_STOP_BUTTON,
- ID_TRANSCRIBE_OUT,
- ID_PY_APP_MIC,
- ID_PY_APP_MIC_PANEL,
- ID_PY_APP_LANG,
- ID_PY_APP_TRANSLATE_TARGET,
- ID_PY_APP_LANG_PANEL,
- ID_PY_APP_MODEL,
- ID_PY_APP_MODEL_TRANSLATION,
- ID_PY_APP_CHARS_PER_SYNC,
- ID_PY_APP_BYTES_PER_CHAR,
- ID_PY_APP_BUTTON,
- ID_PY_APP_PRIO,
- ID_PY_APP_COMPUTE_TYPE,
- ID_PY_APP_MODEL_PANEL,
- ID_PY_APP_ENABLE_LOCAL_BEEP,
- ID_PY_APP_ENABLE_ORIG_LANG,
- ID_PY_APP_ENABLE_BROWSER_SRC,
- ID_PY_APP_USE_CPU,
- ID_PY_APP_USE_BUILTIN,
- ID_PY_APP_ENABLE_UWU_FILTER,
- ID_PY_APP_REMOVE_TRAILING_PERIOD,
- ID_PY_APP_ENABLE_UPPERCASE_FILTER,
- ID_PY_APP_ENABLE_LOWERCASE_FILTER,
- ID_PY_APP_ENABLE_PROFANITY_FILTER,
- ID_PY_APP_ENABLE_DEBUG_MODE,
- ID_PY_APP_RESET_ON_TOGGLE,
- ID_PY_APP_ENABLE_PREVIEWS,
- ID_PY_APP_ENABLE_LOCK_AT_SPAWN,
- ID_PY_APP_ROWS,
- ID_PY_APP_COLS,
- ID_PY_APP_GPU_IDX,
- ID_PY_APP_MIN_SILENCE_DURATION_MS,
- ID_PY_APP_MAX_SPEECH_DURATION_S,
- ID_PY_APP_RESET_AFTER_SILENCE_S,
- ID_PY_APP_TRANSCRIPTION_LOOP_DELAY_MS,
- ID_PY_APP_KEYBIND,
- ID_PY_APP_BROWSER_SRC_PORT,
- ID_PY_APP_COMMIT_FUZZ_THRESHOLD,
- ID_UNITY_PANEL,
- ID_UNITY_CONFIG_PANEL,
- ID_UNITY_OUT,
- ID_UNITY_ASSETS_FILE_PICKER,
- ID_UNITY_ANIMATOR_FILE_PICKER,
- ID_UNITY_PARAMETERS_FILE_PICKER,
- ID_UNITY_MENU_FILE_PICKER,
- ID_UNITY_CONFIG_PANEL_PAIRS,
- ID_UNITY_ANIMATOR_GENERATED_DIR,
- ID_UNITY_ANIMATOR_GENERATED_NAME,
- ID_UNITY_PARAMETERS_GENERATED_NAME,
- ID_UNITY_MENU_GENERATED_NAME,
- ID_UNITY_BUTTON_GEN_ANIMATOR,
- ID_UNITY_BUTTON_AUTO_REFRESH,
- ID_UNITY_BUTTON_AUTO_REFRESH_STOP,
- ID_UNITY_CHARS_PER_SYNC,
- ID_UNITY_BYTES_PER_CHAR,
- ID_UNITY_ROWS,
- ID_UNITY_COLS,
- ID_UNITY_TEXTURE_SZ,
- ID_UNITY_CLEAR_OSC,
- ID_UNITY_ENABLE_PHONEMES,
- 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,
- ID_DEBUG_BUTTON_BACKUP_VENV,
- ID_DEBUG_BUTTON_RESTORE_VENV,
- ID_DEBUG_BUTTON_SETUP_VENV,
- };
-
- const wxString kMicChoices[] = {
- "index",
- "beyond",
- "focusrite",
- "motu",
- // ok now this is epic
- "0",
- "1",
- "2",
- "3",
- "4",
- "5",
- "6",
- "7",
- "8",
- "9",
- "10",
- "11",
- "12",
- "13",
- "14",
- "15",
- "16",
- "17",
- "18",
- "19",
- };
- const size_t kNumMicChoices = sizeof(kMicChoices) / sizeof(kMicChoices[0]);
- constexpr int kMicDefault = 0; // index
-
- // lifted from whisper/tokenizer.py
- const wxString kLangChoices[] = {
- "english",
- "afrikaans",
- "albanian",
- "amharic",
- "arabic",
- "armenian",
- "assamese",
- "azerbaijani",
- "bashkir",
- "basque",
- "belarusian",
- "bengali",
- "bosnian",
- "breton",
- "bulgarian",
- "catalan",
- "chinese",
- "croatian",
- "czech",
- "danish",
- "dutch",
- "estonian",
- "faroese",
- "finnish",
- "french",
- "galician",
- "georgian",
- "german",
- "greek",
- "gujarati",
- "haitian creole",
- "hausa",
- "hawaiian",
- "hebrew",
- "hindi",
- "hungarian",
- "icelandic",
- "indonesian",
- "italian",
- "japanese",
- "javanese",
- "kannada",
- "kazakh",
- "khmer",
- "korean",
- "lao",
- "latin",
- "latvian",
- "lingala",
- "lithuanian",
- "luxembourgish",
- "macedonian",
- "malagasy",
- "malay",
- "malayalam",
- "maltese",
- "maori",
- "marathi",
- "mongolian",
- "myanmar",
- "nepali",
- "norwegian",
- "nynorsk",
- "occitan",
- "pashto",
- "persian",
- "polish",
- "portuguese",
- "punjabi",
- "romanian",
- "russian",
- "sanskrit",
- "serbian",
- "shona",
- "sindhi",
- "sinhala",
- "slovak",
- "slovenian",
- "somali",
- "spanish",
- "sundanese"
- "swahili",
- "swedish",
- "tagalog",
- "tajik",
- "tamil",
- "tatar",
- "telugu",
- "thai",
- "tibetan",
- "turkish",
- "turkmen",
- "ukrainian",
- "urdu",
- "uzbek",
- "vietnamese",
- "welsh",
- "yiddish",
- "yoruba",
- };
- const size_t kNumLangChoices = sizeof(kLangChoices) / sizeof(kLangChoices[0]);
- constexpr int kLangDefault = 0; // english
-
- const wxString kLangTargetChoices[] = {
- "Do not translate",
- "Acehnese(Arabic script) | ace_Arab",
- "Acehnese(Latin script) | ace_Latn",
- "Afrikaans | afr_Latn",
- "Akan | aka_Latn",
- "Amharic | amh_Ethi",
- "Armenian | hye_Armn",
- "Assamese | asm_Beng",
- "Asturian | ast_Latn",
- "Awadhi | awa_Deva",
- "Ayacucho Quechua | quy_Latn",
- "Balinese | ban_Latn",
- "Bambara | bam_Latn",
- "Banjar(Arabic script) | bjn_Arab",
- "Banjar(Latin script) | bjn_Latn",
- "Bashkir | bak_Cyrl",
- "Basque | eus_Latn",
- "Belarusian | bel_Cyrl",
- "Bemba | bem_Latn",
- "Bengali | ben_Beng",
- "Bhojpuri | bho_Deva",
- "Bosnian | bos_Latn",
- "Buginese | bug_Latn",
- "Bulgarian | bul_Cyrl",
- "Burmese | mya_Mymr",
- "Catalan | cat_Latn",
- "Cebuano | ceb_Latn",
- "Central Atlas Tamazight | tzm_Tfng",
- "Central Aymara | ayr_Latn",
- "Central Kanuri(Arabic script) | knc_Arab",
- "Central Kanuri(Latin script) | knc_Latn",
- "Central Kurdish | ckb_Arab",
- "Chhattisgarhi | hne_Deva",
- "Chinese(Simplified) | zho_Hans",
- "Chinese(Traditional) | zho_Hant",
- "Chokwe | cjk_Latn",
- "Crimean Tatar | crh_Latn",
- "Croatian | hrv_Latn",
- "Czech | ces_Latn",
- "Danish | dan_Latn",
- "Dari | prs_Arab",
- "Dutch | nld_Latn",
- "Dyula | dyu_Latn",
- "Dzongkha | dzo_Tibt",
- "Eastern Panjabi | pan_Guru",
- "Eastern Yiddish | ydd_Hebr",
- "Egyptian Arabic | arz_Arab",
- "English | eng_Latn",
- "Esperanto | epo_Latn",
- "Estonian | est_Latn",
- "Ewe | ewe_Latn",
- "Faroese | fao_Latn",
- "Fijian | fij_Latn",
- "Finnish | fin_Latn",
- "Fon | fon_Latn",
- "French | fra_Latn",
- "Friulian | fur_Latn",
- "Galician | glg_Latn",
- "Ganda | lug_Latn",
- "Georgian | kat_Geor",
- "German | deu_Latn",
- "Greek | ell_Grek",
- "Guarani | grn_Latn",
- "Gujarati | guj_Gujr",
- "Haitian Creole | hat_Latn",
- "Halh Mongolian | khk_Cyrl",
- "Hausa | hau_Latn",
- "Hebrew | heb_Hebr",
- "Hindi | hin_Deva",
- "Hungarian | hun_Latn",
- "Icelandic | isl_Latn",
- "Igbo | ibo_Latn",
- "Ilocano | ilo_Latn",
- "Indonesian | ind_Latn",
- "Irish | gle_Latn",
- "Italian | ita_Latn",
- "Japanese | jpn_Jpan",
- "Javanese | jav_Latn",
- "Jingpho | kac_Latn",
- "Kabiyè | kbp_Latn",
- "Kabuverdianu | kea_Latn",
- "Kabyle | kab_Latn",
- "Kamba | kam_Latn",
- "Kannada | kan_Knda",
- "Kashmiri(Arabic script) | kas_Arab",
- "Kashmiri(Devanagari script) | kas_Deva",
- "Kazakh | kaz_Cyrl",
- "Khmer | khm_Khmr",
- "Kikongo | kon_Latn",
- "Kikuyu | kik_Latn",
- "Kimbundu | kmb_Latn",
- "Kinyarwanda | kin_Latn",
- "Korean | kor_Hang",
- "Kyrgyz | kir_Cyrl",
- "Lao | lao_Laoo",
- "Latgalian | ltg_Latn",
- "Ligurian | lij_Latn",
- "Limburgish | lim_Latn",
- "Lingala | lin_Latn",
- "Lithuanian | lit_Latn",
- "Lombard | lmo_Latn",
- "Luba - Kasai | lua_Latn",
- "Luo | luo_Latn",
- "Luxembourgish | ltz_Latn",
- "Macedonian | mkd_Cyrl",
- "Magahi | mag_Deva",
- "Maithili | mai_Deva",
- "Malayalam | mal_Mlym",
- "Maltese | mlt_Latn",
- "Maori | mri_Latn",
- "Marathi | mar_Deva",
- "Meitei(Bengali script) | mni_Beng",
- "Mesopotamian Arabic | acm_Arab",
- "Minangkabau(Arabic script) | min_Arab",
- "Minangkabau(Latin script) | min_Latn",
- "Mizo | lus_Latn",
- "Modern Standard Arabic | arb_Arab",
- "Modern Standard Arabic(Romanized) | arb_Latn",
- "Moroccan Arabic | ary_Arab",
- "Mossi | mos_Latn",
- "Najdi Arabic | ars_Arab",
- "Nepali | npi_Deva",
- "Nigerian Fulfulde | fuv_Latn",
- "North Azerbaijani | azj_Latn",
- "North Levantine Arabic | apc_Arab",
- "Northern Kurdish | kmr_Latn",
- "Northern Sotho | nso_Latn",
- "Northern Uzbek | uzn_Latn",
- "Norwegian Bokmål | nob_Latn",
- "Norwegian Nynorsk | nno_Latn",
- "Nuer | nus_Latn",
- "Nyanja | nya_Latn",
- "Occitan | oci_Latn",
- "Odia | ory_Orya",
- "Pangasinan | pag_Latn",
- "Papiamento | pap_Latn",
- "Plateau Malagasy | plt_Latn",
- "Polish | pol_Latn",
- "Portuguese | por_Latn",
- "Romanian | ron_Latn",
- "Rundi | run_Latn",
- "Russian | rus_Cyrl",
- "Samoan | smo_Latn",
- "Sango | sag_Latn",
- "Sanskrit | san_Deva",
- "Santali | sat_Olck",
- "Sardinian | srd_Latn",
- "Scottish Gaelic | gla_Latn",
- "Serbian | srp_Cyrl",
- "Shan | shn_Mymr",
- "Shona | sna_Latn",
- "Sicilian | scn_Latn",
- "Silesian | szl_Latn",
- "Sindhi | snd_Arab",
- "Sinhala | sin_Sinh",
- "Slovak | slk_Latn",
- "Slovenian | slv_Latn",
- "Somali | som_Latn",
- "South Azerbaijani | azb_Arab",
- "South Levantine Arabic | ajp_Arab",
- "Southern Pashto | pbt_Arab",
- "Southern Sotho | sot_Latn",
- "Southwestern Dinka | dik_Latn",
- "Spanish | spa_Latn",
- "Standard Latvian | lvs_Latn",
- "Standard Malay | zsm_Latn",
- "Standard Tibetan | bod_Tibt",
- "Sundanese | sun_Latn",
- "Swahili | swh_Latn",
- "Swati | ssw_Latn",
- "Swedish | swe_Latn",
- "Ta'izzi - Adeni Arabic | acq_Arab",
- "Tagalog | tgl_Latn",
- "Tajik | tgk_Cyrl",
- "Tamasheq(Latin script) | taq_Latn",
- "Tamasheq(Tifinagh script) | taq_Tfng",
- "Tamil | tam_Taml",
- "Tatar | tat_Cyrl",
- "Telugu | tel_Telu",
- "Thai | tha_Thai",
- "Tigrinya | tir_Ethi",
- "Tok Pisin | tpi_Latn",
- "Tosk Albanian | als_Latn",
- "Tsonga | tso_Latn",
- "Tswana | tsn_Latn",
- "Tumbuka | tum_Latn",
- "Tunisian Arabic | aeb_Arab",
- "Turkish | tur_Latn",
- "Turkmen | tuk_Latn",
- "Twi | twi_Latn",
- "Ukrainian | ukr_Cyrl",
- "Umbundu | umb_Latn",
- "Urdu | urd_Arab",
- "Uyghur | uig_Arab",
- "Venetian | vec_Latn",
- "Vietnamese | vie_Latn",
- "Waray | war_Latn",
- "Welsh | cym_Latn",
- "West Central Oromo | gaz_Latn",
- "Western Persian | pes_Arab",
- "Wolof | wol_Latn",
- "Xhosa | xho_Latn",
- "Yoruba | yor_Latn",
- "Yue Chinese | yue_Hant",
- "Zulu | zul_Latn",
- };
- const size_t kNumLangTargetChoices = sizeof(kLangTargetChoices) / sizeof(kLangTargetChoices[0]);
- constexpr int kLangTargetDefault = 0; // do not translate
-
- // lifted from whisper/__init__.py
- const wxString kModelChoices[] = {
- "tiny.en",
- "tiny",
- "base.en",
- "base",
- "distil-small.en",
- "small.en",
- "small",
- "distil-medium.en",
- "medium.en",
- "medium",
- "large-v1",
- "distil-large-v2",
- "large-v2",
- "distil-large-v3",
- "large-v3",
- "large-v3-turbo",
- };
- const size_t kNumModelChoices = sizeof(kModelChoices) / sizeof(kModelChoices[0]);
- constexpr int kModelDefault = 2; // base.en
-
- const wxString kModelTranslationChoices[] = {
- "nllb-200-distilled-600M",
- "nllb-200-distilled-1.3B",
- };
- const size_t kNumModelTranslationChoices = sizeof(kModelTranslationChoices) / sizeof(kModelTranslationChoices[0]);
- constexpr int kModelTranslationDefault = 2; // base.en
-
- const wxString kCharsPerSync[] = {
- "1",
- "2",
- "3",
- "4",
- "5",
- "6",
- "7",
- "8",
- "9",
- "10",
- "11",
- "12",
- "13",
- "14",
- "15",
- "16",
- "17",
- "18",
- "19",
- "20",
- "21",
- "22",
- "23",
- "24",
- };
- const size_t kNumCharsPerSync = sizeof(kCharsPerSync) / sizeof(kCharsPerSync[0]);
- // 20 chars per sync is a good balance between parameter space and speed:
- // 20 * 8 + 25 = 185 bits, leaving 71 bits for other systems.
- constexpr int kCharsDefault = kNumCharsPerSync - 5;
-
- const wxString kBytesPerChar[] = {
- "1",
- "2",
- };
- const size_t kNumBytesPerChar = sizeof(kBytesPerChar) / sizeof(kBytesPerChar[0]);
- // Sorry international users. Optimize for English speakers, by default.
- constexpr int kBytesDefault = 0;
-
- const wxString kButton[] = {
- "left thumbstick",
- "left a",
- "left b",
- "right thumbstick",
- "right a",
- "right b",
- };
- const size_t kNumButtons = sizeof(kButton) / sizeof(kButton[0]);
- constexpr int kButtonDefault = 0;
-
- const wxString kPrio[] = {
- "idle",
- "below normal",
- "normal",
- "above normal",
- "high",
- "realtime",
- };
- const size_t kNumPrios = sizeof(kPrio) / sizeof(kPrio[0]);
- constexpr int kPrioDefault = 0;
-
- const wxString kComputeType[] = {
- "int8",
- "int8_float32",
- "int8_float16",
- "int8_bfloat16",
- "int16",
- "float16",
- "bfloat16",
- "float32",
- };
- const size_t kNumComputeTypes = sizeof(kComputeType) / sizeof(kComputeType[0]);
- constexpr int kComputeTypeDefault = 4;
-
- const wxString kDecodeMethods[] = {
- "greedy",
- "beam",
- };
- const size_t kNumDecodeMethods = sizeof(kDecodeMethods) / sizeof(kDecodeMethods[0]);
- constexpr int kDecodeMethodDefault = 0;
-
- // Given the string value of a dropdown menu's entry, find its index. If no
- // entry matches, return `default_index`.
- int GetDropdownChoiceIndex(const wxString menu[],
- const size_t num_menu_entries, const std::string& entry,
- const int default_index) {
- for (int i = 0; i < num_menu_entries; i++) {
- if (entry == menu[i]) {
- return i;
- }
- }
- return default_index;
- }
-
- std::optional<int> stoiInRange(wxTextCtrl* out, const std::string& int_s, const std::string int_name, int min, int max) {
- int res;
- try {
- res = std::stoi(int_s);
- }
- catch (const std::invalid_argument&) {
- Log(out, "Could not parse {} \"{}\" as an integer: invalid\n",
- int_name, int_s);
- return {};
- }
- catch (const std::out_of_range&) {
- Log(out, "Could not parse {} \"{}\" as an integer: out of "
- "range\n", int_name, int_s);
- return {};
- }
- if (res < min || res > max) {
- Log(out, "Int argument {} is out of the allowed range [{},{}]\n",
- int_name, min, max);
- return {};
- }
- return res;
- }
-
-} // namespace
-
-Frame::Frame()
- : wxFrame(nullptr, wxID_ANY, "TaSTT"),
- run_py_app_(false),
- py_app_drain_(this, ID_PY_APP_DRAIN)
-{
- app_c_ = std::make_unique<AppConfig>(nullptr);
-
- // Initialize futures so that valid() returns true. We use this as a proxy
- // to tell whether they're still executing.
- {
- auto p = std::promise<bool>();
- py_app_ = p.get_future();
- p.set_value(true);
- }
- {
- auto p = std::promise<bool>();
- obs_app_ = p.get_future();
- p.set_value(true);
- }
- {
- auto p = std::promise<bool>();
- unity_app_ = p.get_future();
- p.set_value(true);
- }
- {
- auto p = std::promise<bool>();
- unity_auto_refresh_ = p.get_future();
- p.set_value(true);
- }
- {
- auto p = std::promise<bool>();
- dump_mics_ = p.get_future();
- p.set_value(true);
- }
- {
- auto p = std::promise<bool>();
- env_proc_ = p.get_future();
- p.set_value(true);
- }
- {
- auto p = std::promise<void>();
- reset_venv_proc_ = p.get_future();
- p.set_value();
- }
-
- auto* main_panel = new wxPanel(this, ID_MAIN_PANEL);
- main_panel_ = main_panel;
- {
- auto* navbar = new wxPanel(main_panel, ID_NAVBAR);
- {
- 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);
- transcribe_panel_ = transcribe_panel;
- {
- const auto transcribe_out_sz = wxSize(/*x_px=*/480, /*y_px=*/160);
- auto* transcribe_out = new wxTextCtrl(transcribe_panel,
- ID_TRANSCRIBE_OUT, wxEmptyString, wxDefaultPosition,
- transcribe_out_sz, wxTE_MULTILINE | wxTE_READONLY);
- transcribe_out->SetMinSize(transcribe_out_sz);
- transcribe_out_ = transcribe_out;
-
- Log(transcribe_out_, "{}\n", PythonWrapper::GetVersion());
-
- auto* py_config_panel = new wxPanel(transcribe_panel,
- ID_PY_CONFIG_PANEL);
- {
- auto* py_dump_mics_button = new wxButton(py_config_panel,
- ID_PY_DUMP_MICS_BUTTON, "List input devices");
- py_dump_mics_button->SetToolTip(
- "List the microphones (and input devices) attached to "
- "your computer. To use a microphone, enter the number "
- "to its left in the 'Microphone' dropdown.");
- auto* py_app_config_panel_pairs = new wxPanel(py_config_panel,
- ID_PY_APP_CONFIG_PANEL_PAIRS);
- {
- auto* py_app_mic = new wxChoice(py_app_config_panel_pairs,
- ID_PY_APP_MIC, wxDefaultPosition,
- wxDefaultSize, kNumMicChoices, kMicChoices);
- py_app_mic->SetToolTip(
- "Select which microphone to listen to when "
- "transcribing. To get list microphones and get their "
- "numbers, click 'List input devices'.");
- py_app_mic_ = py_app_mic;
-
- auto* py_app_lang = new wxChoice(py_app_config_panel_pairs,
- ID_PY_APP_LANG, wxDefaultPosition, wxDefaultSize,
- kNumLangChoices, kLangChoices);
- py_app_lang->SetToolTip("Select which language you will "
- "speak in.");
- py_app_lang_ = py_app_lang;
-
- auto* py_app_translate_target = new wxChoice(py_app_config_panel_pairs,
- ID_PY_APP_TRANSLATE_TARGET, wxDefaultPosition, wxDefaultSize,
- kNumLangTargetChoices, kLangTargetChoices);
- py_app_translate_target->SetToolTip("Select which "
- "language to translate to. This is the language "
- "that will appear in game. "
- "If using a language with non-ASCII characters (i.e. "
- "not English), make sure you have 'bytes per char' "
- "set to 2.");
- py_app_translate_target_ = py_app_translate_target;
-
- auto* py_app_model = new wxChoice(
- py_app_config_panel_pairs, ID_PY_APP_MODEL,
- wxDefaultPosition, wxDefaultSize, kNumModelChoices,
- kModelChoices);
- py_app_model->SetToolTip("Select which version of "
- "the transcription model to use. 'base' is a good "
- "choice for most users. 'small' is slightly more "
- "accurate, slower, and uses more VRAM. The *.en "
- "models are fine-tuned English language models, and "
- "don't work for other languages.");
- py_app_model_ = py_app_model;
-
- auto* py_app_model_translation = new wxChoice(
- py_app_config_panel_pairs, ID_PY_APP_MODEL_TRANSLATION,
- wxDefaultPosition, wxDefaultSize, kNumModelTranslationChoices,
- kModelTranslationChoices);
- py_app_model_translation->SetToolTip("Select which "
- "version of the translation model to use. 600M params "
- "uses 4.1 GB of memory, while 1.3B uses ~7GB of "
- "memory. If 'Translate to' is set to 'Do not "
- "translate', this does nothing.");
- py_app_model_translation_ = py_app_model_translation;
-
- auto* py_app_chars_per_sync = new wxChoice(
- py_app_config_panel_pairs, ID_PY_APP_CHARS_PER_SYNC,
- wxDefaultPosition, wxDefaultSize, kNumCharsPerSync,
- kCharsPerSync);
- py_app_chars_per_sync->SetToolTip(
- "VRChat syncs avatar parameters roughly 5 times per "
- "second. We use this to send text to the box. By "
- "sending more characters per sync, the box will be "
- "faster, but you'll use more avatar parameters.");
- py_app_chars_per_sync_ = py_app_chars_per_sync;
-
- auto* py_app_bytes_per_char = new wxChoice(
- py_app_config_panel_pairs, ID_PY_APP_BYTES_PER_CHAR,
- wxDefaultPosition, wxDefaultSize, kNumBytesPerChar,
- kBytesPerChar);
- py_app_bytes_per_char->SetToolTip(
- "If you speak a language that uses non-ASCII "
- "characters (i.e. not English), set this to 2.");
- py_app_bytes_per_char_ = py_app_bytes_per_char;
-
- auto* py_app_button = new wxChoice(py_app_config_panel_pairs,
- ID_PY_APP_BUTTON, wxDefaultPosition,
- wxDefaultSize, kNumButtons, kButton);
- py_app_button->SetToolTip(
- "You will use this button in game to start and stop "
- "transcription. Set it to a button you're not using "
- "for anything else!");
- py_app_button_ = py_app_button;
-
- auto* py_app_prio = new wxChoice(py_app_config_panel_pairs,
- ID_PY_APP_PRIO, wxDefaultPosition,
- wxDefaultSize, kNumPrios, kPrio);
- py_app_prio->SetToolTip(
- "The priority level at which the transcription process runs.");
- py_app_prio_ = py_app_prio;
-
- auto* py_app_compute_type = new wxChoice(py_app_config_panel_pairs,
- ID_PY_APP_COMPUTE_TYPE, wxDefaultPosition,
- wxDefaultSize, kNumComputeTypes, kComputeType);
- py_app_compute_type->SetToolTip(
- "The compute type to use for GPU inference. Ignored "
- "if CPU mode is enabled.");
- py_app_compute_type_ = py_app_compute_type;
-
- auto* py_app_rows = new wxTextCtrl(py_app_config_panel_pairs,
- ID_PY_APP_ROWS, std::to_string(app_c_->rows),
- wxDefaultPosition, wxDefaultSize, /*style=*/0);
- py_app_rows->SetToolTip(
- "The number of rows on the text box.");
- py_app_rows_ = py_app_rows;
-
- auto* py_app_cols = new wxTextCtrl(py_app_config_panel_pairs,
- ID_PY_APP_COLS, std::to_string(app_c_->cols),
- wxDefaultPosition, wxDefaultSize, /*style=*/0);
- py_app_cols->SetToolTip(
- "The number of columns on the text box.");
- py_app_cols_ = py_app_cols;
-
- auto* py_app_gpu_idx = new wxTextCtrl(
- py_app_config_panel_pairs, ID_PY_APP_GPU_IDX,
- std::to_string(app_c_->gpu_idx), wxDefaultPosition,
- wxDefaultSize, /*style=*/0);
- py_app_gpu_idx->SetToolTip(
- "The index of the GPU to use. 0 is usually your CPU's "
- "onboard GPU (if you have one), 1 is usually your "
- "discrete GPU.");
- py_app_gpu_idx_ = py_app_gpu_idx;
-
- auto* py_app_min_silence_duration_ms = new wxTextCtrl(
- py_app_config_panel_pairs, ID_PY_APP_MIN_SILENCE_DURATION_MS,
- std::to_string(app_c_->min_silence_duration_ms), wxDefaultPosition,
- wxDefaultSize, /*style=*/0);
- py_app_min_silence_duration_ms->SetToolTip(
- "The minimum duration, in milliseconds, of a silence "
- "used to segment speech.");
- py_app_min_silence_duration_ms_ = py_app_min_silence_duration_ms;
-
- auto* py_app_max_speech_duration_s = new wxTextCtrl(
- py_app_config_panel_pairs, ID_PY_APP_MAX_SPEECH_DURATION_S,
- std::to_string(app_c_->max_speech_duration_s), wxDefaultPosition,
- wxDefaultSize, /*style=*/0);
- py_app_max_speech_duration_s->SetToolTip(
- "The maximum duration, in seconds, of any segment of "
- "speech. Continuous speech longer than this is split "
- "at the last pause lasting longer than 100 "
- "milliseconds.");
- py_app_max_speech_duration_s_ = py_app_max_speech_duration_s;
-
- auto* py_app_reset_after_silence_s = new wxTextCtrl(
- py_app_config_panel_pairs, ID_PY_APP_RESET_AFTER_SILENCE_S,
- std::to_string(app_c_->reset_after_silence_s), wxDefaultPosition,
- wxDefaultSize, /*style=*/0);
- py_app_reset_after_silence_s->SetToolTip(
- "If you pause for at least this long between "
- "sentences, the transcript before the pause will be "
- "removed. To disable this feature, set it to -1.");
- py_app_reset_after_silence_s_ = py_app_reset_after_silence_s;
-
- auto* py_app_transcription_loop_delay_ms = new wxTextCtrl(
- py_app_config_panel_pairs, ID_PY_APP_TRANSCRIPTION_LOOP_DELAY_MS,
- std::to_string(app_c_->transcription_loop_delay_ms), wxDefaultPosition,
- wxDefaultSize, /*style=*/0);
- py_app_transcription_loop_delay_ms->SetToolTip(
- "The amount of time, in milliseconds, that the "
- "application will sleep between every subsequent "
- "transcription.");
- py_app_transcription_loop_delay_ms_ = py_app_transcription_loop_delay_ms;
-
- auto* py_app_keybind = new wxTextCtrl(
- py_app_config_panel_pairs, ID_PY_APP_KEYBIND,
- app_c_->keybind, wxDefaultPosition,
- wxDefaultSize, /*style=*/0);
- py_app_keybind->SetToolTip(
- "The keybind to use to toggle the STT when in desktop "
- "mode. To dismiss the STT, double press the keybind "
- "quickly.");
- py_app_keybind_ = py_app_keybind;
-
- auto* py_app_browser_src_port = new wxTextCtrl(
- py_app_config_panel_pairs, ID_PY_APP_BROWSER_SRC_PORT,
- std::to_string(app_c_->browser_src_port), wxDefaultPosition,
- wxDefaultSize, /*style=*/0);
- py_app_browser_src_port->SetToolTip(
- "The port to send the transcript to when `Enable "
- "browser source` is enabled. To preview, go to "
- "localhost:$PORT in your browser, where $PORT is the "
- "value you configure here.");
- py_app_browser_src_port_ = py_app_browser_src_port;
-
- auto* sizer = new wxFlexGridSizer(/*cols=*/2);
- py_app_config_panel_pairs->SetSizer(sizer);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Microphone:"));
- sizer->Add(py_app_mic, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Spoken language:"));
- sizer->Add(py_app_lang, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Transcription model:"));
- sizer->Add(py_app_model, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Translate to:"));
- sizer->Add(py_app_translate_target, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Translation model:"));
- sizer->Add(py_app_model_translation, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Characters per sync:"));
- sizer->Add(py_app_chars_per_sync, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Bytes per character:"));
- sizer->Add(py_app_bytes_per_char, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Button:"));
- sizer->Add(py_app_button, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Process priority:"));
- sizer->Add(py_app_prio, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"GPU compute type:"));
- sizer->Add(py_app_compute_type, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Desktop keybind:"));
- sizer->Add(py_app_keybind, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Text box rows:"));
- sizer->Add(py_app_rows, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Text box columns:"));
- sizer->Add(py_app_cols, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"GPU index:"));
- sizer->Add(py_app_gpu_idx, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Minimum silence duration (ms):"));
- sizer->Add(py_app_min_silence_duration_ms, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Maximum speech duration (s):"));
- sizer->Add(py_app_max_speech_duration_s, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Reset after silence (s):"));
- sizer->Add(py_app_reset_after_silence_s, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Transcription loop delay (ms):"));
- sizer->Add(py_app_transcription_loop_delay_ms, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(py_app_config_panel_pairs,
- wxID_ANY, /*label=*/"Browser source port:"));
- sizer->Add(py_app_browser_src_port, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- }
-
- auto* py_app_enable_browser_src = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_BROWSER_SRC, "Enable browser source");
- py_app_enable_browser_src->SetValue(app_c_->enable_browser_src);
- py_app_enable_browser_src->SetToolTip(
- "Stream transcript to a browser source. To preview, go to "
- "localhost:8097, or whatever port you configured.");
- py_app_enable_browser_src_ = py_app_enable_browser_src;
-
- auto* py_app_enable_local_beep = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_LOCAL_BEEP, "Enable local beep");
- py_app_enable_local_beep->SetValue(app_c_->enable_local_beep);
- py_app_enable_local_beep->SetToolTip(
- "By default, TaSTT will play a sound (audible only to "
- "you) when it begins transcription and when it stops. "
- "Uncheck this to disable that behavior."
- );
- py_app_enable_local_beep_ = py_app_enable_local_beep;
-
- auto* py_app_enable_orig_lang = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_ORIG_LANG, "Translation shows original language");
- py_app_enable_orig_lang->SetValue(app_c_->enable_orig_lang);
- py_app_enable_orig_lang->SetToolTip(
- "When translation is enabled, this checkbox determines whether "
- "the original language is shown in parentheses after the "
- "translated text - c'est comme ça. ( like this)."
- );
- py_app_enable_orig_lang_ = py_app_enable_orig_lang;
-
- auto* py_app_use_cpu = new wxCheckBox(py_config_panel,
- ID_PY_APP_USE_CPU, "Use CPU");
- py_app_use_cpu->SetValue(app_c_->use_cpu);
- py_app_use_cpu->SetToolTip(
- "If checked, the transcription engine will run on your "
- "CPU instead of your GPU. This is typically much slower "
- "and should only be used if you aren't able to use your "
- "GPU."
- );
- py_app_use_cpu_ = py_app_use_cpu;
-
- auto* py_app_use_builtin = new wxCheckBox(py_config_panel,
- ID_PY_APP_USE_BUILTIN, "Use built-in chatbox");
- py_app_use_builtin->SetValue(app_c_->use_builtin);
- py_app_use_builtin->SetToolTip(
- "If checked, text will be sent to the built-in text box "
- "instead of one attached to the current avatar."
- );
- py_app_use_builtin_ = py_app_use_builtin;
-
- auto* py_app_enable_uwu_filter = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_UWU_FILTER, "Enable uwu filter :3");
- py_app_enable_uwu_filter->SetValue(app_c_->enable_uwu_filter);
- py_app_enable_uwu_filter->SetToolTip(
- "If checked, transcribed text will be passed through an "
- "uwu filter."
- );
- py_app_enable_uwu_filter_ = py_app_enable_uwu_filter;
-
- auto* py_app_remove_trailing_period = new wxCheckBox(py_config_panel,
- ID_PY_APP_REMOVE_TRAILING_PERIOD, "Remove trailing period");
- py_app_remove_trailing_period->SetValue(app_c_->remove_trailing_period);
- py_app_remove_trailing_period->SetToolTip(
- "If checked, transcriptions will never end with a period."
- );
- py_app_remove_trailing_period_ = py_app_remove_trailing_period;
-
- auto* py_app_enable_uppercase_filter = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_UPPERCASE_FILTER, "Enable uppercase filter");
- py_app_enable_uppercase_filter->SetValue(app_c_->enable_uppercase_filter);
- py_app_enable_uppercase_filter->SetToolTip(
- "If checked, transcribed text will be converted to UPPERCASE."
- );
- py_app_enable_uppercase_filter_ = py_app_enable_uppercase_filter;
-
- auto* py_app_enable_lowercase_filter = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_LOWERCASE_FILTER, "Enable lowercase filter");
- py_app_enable_lowercase_filter->SetValue(app_c_->enable_lowercase_filter);
- py_app_enable_lowercase_filter->SetToolTip(
- "If checked, transcribed text will be converted to lowercase."
- );
- py_app_enable_lowercase_filter_ = py_app_enable_lowercase_filter;
-
- auto* py_app_enable_profanity_filter = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_PROFANITY_FILTER, "Enable profanity filter");
- py_app_enable_profanity_filter->SetValue(app_c_->enable_profanity_filter);
- py_app_enable_profanity_filter->SetToolTip(
- "If checked, profane words in your transcript will have "
- "their vowels replaced with asterisks. Currently only "
- "English is supported."
- );
- py_app_enable_profanity_filter_ = py_app_enable_profanity_filter;
-
- auto* py_app_enable_debug_mode = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_DEBUG_MODE, "Enable debug mode");
- py_app_enable_debug_mode->SetValue(app_c_->enable_debug_mode);
- py_app_enable_debug_mode->SetToolTip(
- "If checked, the transcription engine will print out "
- "additional information. Use this if you're debugging a "
- "technical issue."
- );
- py_app_enable_debug_mode_ = py_app_enable_debug_mode;
-
- auto* py_app_reset_on_toggle = new wxCheckBox(py_config_panel,
- ID_PY_APP_RESET_ON_TOGGLE, "Reset transcript on toggle");
- py_app_reset_on_toggle->SetValue(app_c_->reset_on_toggle);
- py_app_reset_on_toggle->SetToolTip(
- "If checked, the transcript will be reset (cleared) every "
- "time that transcription is toggled on. Only affects "
- "keyboard controls, not the VR controls."
- );
- py_app_reset_on_toggle_ = py_app_reset_on_toggle;
-
- auto* py_app_enable_previews = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_PREVIEWS, "Enable previews");
- py_app_enable_previews->SetValue(app_c_->enable_previews);
- py_app_enable_previews->SetToolTip(
- "If checked, audio that has not yet stabilized will also "
- "be transcribed and shown. Turn this off if you're on a "
- "resource-constrained system or if transcription is "
- "running slowly."
- );
- py_app_enable_previews_ = py_app_enable_previews;
-
- auto* py_app_enable_lock_at_spawn = new wxCheckBox(py_config_panel,
- ID_PY_APP_ENABLE_LOCK_AT_SPAWN, "Lock chatbox at spawn");
- py_app_enable_lock_at_spawn->SetValue(app_c_->enable_lock_at_spawn);
- py_app_enable_lock_at_spawn->SetToolTip(
- "If checked, the custom chatbox will be locked in world "
- "space when spawned. This minimizes the visual "
- "disruption for other players.");
- py_app_enable_lock_at_spawn_ = py_app_enable_lock_at_spawn;
-
- // Hack: Add newlines before and after the button text to make
- // the buttons bigger, and easier to click from inside VR.
- auto* py_app_start_button = new wxButton(py_config_panel,
- ID_PY_APP_START_BUTTON, "\nBegin transcribing\n\n");
- auto* py_app_stop_button = new wxButton(py_config_panel,
- ID_PY_APP_STOP_BUTTON, "\nStop transcribing\n\n");
-
- auto* sizer = new wxBoxSizer(wxVERTICAL);
- py_config_panel->SetSizer(sizer);
- sizer->Add(py_dump_mics_button, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_config_panel_pairs, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_reset_on_toggle, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_previews, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_lock_at_spawn, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_browser_src, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_local_beep, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_orig_lang, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_use_cpu, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_use_builtin, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_uwu_filter, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_remove_trailing_period, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_uppercase_filter, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_lowercase_filter, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_profanity_filter, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_enable_debug_mode, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_start_button, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(py_app_stop_button, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- }
-
- auto* sizer = new wxBoxSizer(wxHORIZONTAL);
- transcribe_panel->SetSizer(sizer);
- sizer->Add(py_config_panel, /*proportion=*/0, /*flags=*/wxEXPAND);
- sizer->Add(transcribe_out, /*proportion=*/1, /*flags=*/wxEXPAND);
- }
-
- auto* unity_panel = new wxPanel(main_panel, ID_UNITY_PANEL);
- unity_panel_ = unity_panel;
- {
- const auto unity_out_sz = wxSize(/*x_px=*/480, /*y_px=*/160);
- auto* unity_out = new wxTextCtrl(unity_panel, ID_UNITY_OUT,
- wxEmptyString,
- wxDefaultPosition,
- unity_out_sz, wxTE_MULTILINE | wxTE_READONLY);
- unity_out->SetMinSize(unity_out_sz);
- unity_out_ = unity_out;
-
- auto* unity_config_panel = new wxPanel(unity_panel,
- ID_UNITY_CONFIG_PANEL);
- {
- auto* unity_config_panel_pairs = new wxPanel(unity_config_panel,
- ID_UNITY_CONFIG_PANEL_PAIRS);
- {
- auto* unity_assets_file_picker = new wxDirPickerCtrl(
- unity_config_panel_pairs,
- ID_UNITY_ASSETS_FILE_PICKER,
- /*path=*/app_c_->assets_path,
- /*message=*/"Unity Assets folder"
- );
- unity_assets_file_picker->SetToolTip(
- "The path to the Assets folder for your avatar's "
- "Unity project. Example:\n"
- "C:\\Users\\yum\\unity\\kumadan\\Assets");
- unity_assets_file_picker_ = unity_assets_file_picker;
-
- auto* unity_animator_file_picker = new wxFilePickerCtrl(
- unity_config_panel_pairs,
- ID_UNITY_ANIMATOR_FILE_PICKER,
- /*path=*/app_c_->fx_path,
- /*message=*/"FX controller path",
- /*wildcard=*/wxFileSelectorDefaultWildcardStr,
- /*pos=*/wxDefaultPosition,
- /*size=*/wxDefaultSize
- );
- unity_animator_file_picker->SetToolTip(
- "The path to your avatar's FX layer. You can find "
- "this in your avatar descriptor. Example:\n"
- "C:\\Users\\yum\\unity\\kumadan\\Assets\\kumadan_fx.controller");
- unity_animator_file_picker_ = unity_animator_file_picker;
-
- auto* unity_parameters_file_picker = new wxFilePickerCtrl(
- unity_config_panel_pairs,
- ID_UNITY_PARAMETERS_FILE_PICKER,
- /*path=*/app_c_->params_path,
- /*message=*/"Avatar parameters path",
- /*wildcard=*/wxFileSelectorDefaultWildcardStr,
- /*pos=*/wxDefaultPosition,
- /*size=*/wxDefaultSize
- );
- unity_parameters_file_picker->SetToolTip(
- "The path to your avatar's parameters. You can find "
- "this in your avatar descriptor. Example:\n"
- "C:\\Users\\yum\\unity\\kumadan\\Assets\\kumadan_parameters.asset");
- unity_parameters_file_picker_ =
- unity_parameters_file_picker;
-
- auto* unity_menu_file_picker = new wxFilePickerCtrl(
- unity_config_panel_pairs,
- ID_UNITY_MENU_FILE_PICKER,
- /*path=*/app_c_->menu_path,
- /*message=*/"Avatar menu path",
- /*wildcard=*/wxFileSelectorDefaultWildcardStr,
- /*pos=*/wxDefaultPosition,
- /*size=*/wxDefaultSize
- );
- unity_menu_file_picker->SetToolTip(
- "The path to your avatar's menu. You can find "
- "this in your avatar descriptor. Example:\n"
- "C:\\Users\\yum\\unity\\kumadan\\Assets\\kumadan_menu.asset");
- unity_menu_file_picker_ = unity_menu_file_picker;
-
- auto* unity_animator_generated_dir = new wxTextCtrl(
- unity_config_panel_pairs,
- ID_UNITY_ANIMATOR_GENERATED_DIR,
- wxEmptyString, wxDefaultPosition, wxDefaultSize,
- /*style=*/0);
- unity_animator_generated_dir->AppendText("TaSTT_Generated");
- unity_animator_generated_dir->SetToolTip(
- "TaSTT will create a bunch of files "
- "(animations, shaders, etc.) to drive the text box. "
- "It places them in this folder, which it creates "
- "under your Unity project's Assets folder. Any data "
- "inside this folder may be overwritten!");
- unity_animator_generated_dir_ =
- unity_animator_generated_dir;
-
- auto* unity_animator_generated_name = new wxTextCtrl(
- unity_config_panel_pairs,
- ID_UNITY_ANIMATOR_GENERATED_NAME,
- wxEmptyString, wxDefaultPosition, wxDefaultSize,
- wxTE_READONLY);
- unity_animator_generated_name->AppendText("TaSTT.controller");
- unity_animator_generated_name->SetToolTip(
- "The name of the FX layer that TaSTT generates. "
- "It will be placed inside the generated assets "
- "folder. Put this on your avatar descriptor when "
- "you're done!");
- unity_animator_generated_name_ = unity_animator_generated_name;
-
- auto* unity_parameters_generated_name = new wxTextCtrl(
- unity_config_panel_pairs,
- ID_UNITY_PARAMETERS_GENERATED_NAME,
- wxEmptyString, wxDefaultPosition, wxDefaultSize,
- wxTE_READONLY);
- unity_parameters_generated_name->AppendText(
- "TaSTT_Parameters.asset");
- unity_parameters_generated_name->SetToolTip(
- "The name of the parameters file that TaSTT generates. "
- "It will be placed inside the generated assets "
- "folder. Put this on your avatar descriptor when "
- "you're done!");
- unity_parameters_generated_name_ =
- unity_parameters_generated_name;
-
- auto* unity_menu_generated_name = new wxTextCtrl(
- unity_config_panel_pairs,
- ID_UNITY_MENU_GENERATED_NAME,
- wxEmptyString, wxDefaultPosition, wxDefaultSize,
- wxTE_READONLY);
- unity_menu_generated_name->AppendText("TaSTT_Menu.asset");
- unity_menu_generated_name->SetToolTip(
- "The name of the menu file that TaSTT generates. "
- "It will be placed inside the generated assets "
- "folder. Put this on your avatar descriptor when "
- "you're done!");
- unity_menu_generated_name_ = unity_menu_generated_name;
-
- auto* unity_chars_per_sync = new wxChoice(
- unity_config_panel_pairs,
- ID_UNITY_CHARS_PER_SYNC, wxDefaultPosition,
- wxDefaultSize, kNumCharsPerSync, kCharsPerSync);
- unity_chars_per_sync->SetToolTip(
- "VRChat syncs avatar parameters roughly 5 times per "
- "second. We use this to send text to the box. By "
- "sending more characters per sync, the box will be "
- "faster, but you'll use more avatar parameters.");
- unity_chars_per_sync_ = unity_chars_per_sync;
-
- auto* unity_bytes_per_char = new wxChoice(
- unity_config_panel_pairs,
- ID_UNITY_BYTES_PER_CHAR, wxDefaultPosition,
- wxDefaultSize, kNumBytesPerChar, kBytesPerChar);
- unity_bytes_per_char->SetToolTip(
- "If you speak a language that uses non-ASCII "
- "characters (i.e. not English), set this to 2.");
- unity_bytes_per_char_ = unity_bytes_per_char;
-
- auto* unity_rows = new wxTextCtrl(unity_config_panel_pairs,
- ID_UNITY_ROWS, std::to_string(app_c_->rows),
- wxDefaultPosition, wxDefaultSize, /*style=*/0);
- unity_rows->SetToolTip(
- "The number of rows on the text box.");
- unity_rows_ = unity_rows;
-
- auto* unity_cols = new wxTextCtrl(unity_config_panel_pairs,
- ID_UNITY_COLS, std::to_string(app_c_->cols),
- wxDefaultPosition, wxDefaultSize, /*style=*/0);
- unity_cols->SetToolTip(
- "The number of columns on the text box.");
- unity_cols_ = unity_cols;
-
- auto* unity_texture_sz = new wxTextCtrl(unity_config_panel_pairs,
- ID_UNITY_TEXTURE_SZ, std::to_string(app_c_->texture_sz),
- wxDefaultPosition, wxDefaultSize, /*style=*/0);
- unity_texture_sz->SetToolTip(
- "The size of the textures holding text glyphs.");
- unity_texture_sz_ = unity_texture_sz;
-
- auto* sizer = new wxFlexGridSizer(/*cols=*/2);
- unity_config_panel_pairs->SetSizer(sizer);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Unity Assets folder:"));
- sizer->Add(unity_assets_file_picker);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"FX controller:"));
- sizer->Add(unity_animator_file_picker);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Avatar parameters:"));
- sizer->Add(unity_parameters_file_picker);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Avatar menu:"));
- sizer->Add(unity_menu_file_picker);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Generated assets folder:"));
- sizer->Add(unity_animator_generated_dir);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Generated FX controller:"));
- sizer->Add(unity_animator_generated_name);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Generated parameters:"));
- sizer->Add(unity_parameters_generated_name);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Generated menu:"));
- sizer->Add(unity_menu_generated_name);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Characters per sync:"));
- sizer->Add(unity_chars_per_sync, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Bytes per character:"));
- sizer->Add(unity_bytes_per_char, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Text box rows:"));
- sizer->Add(unity_rows, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Text box columns:"));
- sizer->Add(unity_cols, /*proportion=*/0,
- /*flags=*/wxEXPAND);
-
- sizer->Add(new wxStaticText(unity_config_panel_pairs,
- wxID_ANY, /*label=*/"Texture size:"));
- sizer->Add(unity_texture_sz, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- }
-
- auto* clear_osc = new wxCheckBox(unity_config_panel,
- ID_UNITY_CLEAR_OSC, "Clear OSC configs");
- clear_osc->SetValue(app_c_->clear_osc);
- clear_osc->SetToolTip(
- "If checked, VRChat's OSC configs will be cleared. "
- "VRC SDK has a bug where parameters added to an "
- "existing avatar are not added to the avatar's OSC "
- "config. By clearing configs, VRC SDK is forced to "
- "regenerate them. The regenerated config will include "
- "the STT parameters. Check this if you are updating "
- "an existing avatar.");
- unity_clear_osc_ = clear_osc;
-
- auto* enable_phonemes = new wxCheckBox(unity_config_panel,
- ID_UNITY_ENABLE_PHONEMES, "Enable phonemes");
- enable_phonemes->SetValue(app_c_->enable_phonemes);
- enable_phonemes->SetToolTip(
- "If checked, the chatbox will be created with 5 audio "
- "sources for each English vowel sound: a, e, i, o, and u. "
- "Whenever a page of data is sent into the game, any "
- "vowels will have the corresponding audio source enabled. "
- "This uses 6 parameter bits.");
- unity_enable_phonemes_ = enable_phonemes;
-
- auto* unity_button_gen_fx = new wxButton(unity_config_panel,
- ID_UNITY_BUTTON_GEN_ANIMATOR, "Generate avatar assets");
- unity_button_gen_fx->SetWindowStyleFlag(wxBU_EXACTFIT);
-
- auto* unity_button_auto_refresh = new wxButton(unity_config_panel,
- ID_UNITY_BUTTON_AUTO_REFRESH, "Begin auto generating assets on change");
- unity_button_auto_refresh->SetWindowStyleFlag(wxBU_EXACTFIT);
- unity_button_auto_refresh->SetToolTip(
- "When the configured FX controller, parameters, or menu "
- "change (as determined by its hash changing), "
- "automatically regenerate TaSTT assets."
- );
-
- auto* unity_button_auto_refresh_stop = new wxButton(unity_config_panel,
- ID_UNITY_BUTTON_AUTO_REFRESH_STOP,
- "Stop auto generating assets on change");
- unity_button_auto_refresh_stop->SetWindowStyleFlag(wxBU_EXACTFIT);
- unity_button_auto_refresh_stop->SetToolTip(
- "Stop auto-generating TaSTT assets on change.");
-
- auto* sizer = new wxBoxSizer(wxVERTICAL);
- unity_config_panel->SetSizer(sizer);
- sizer->Add(unity_config_panel_pairs);
- sizer->Add(clear_osc);
- sizer->Add(enable_phonemes);
- sizer->Add(unity_button_gen_fx, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(unity_button_auto_refresh, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(unity_button_auto_refresh_stop, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- }
-
- auto* sizer = new wxBoxSizer(wxHORIZONTAL);
- unity_panel->SetSizer(sizer);
- sizer->Add(unity_config_panel, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(unity_out, /*proportion=*/1, /*flags=*/wxEXPAND);
- }
- 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* debug_button_backup_venv = new wxButton(
- debug_config_panel, ID_DEBUG_BUTTON_BACKUP_VENV,
- "Back up virtual env");
- debug_button_backup_venv->SetToolTip(
- "Back up the virtual environment to "
- "~/Downloads/TaSTT_venv");
- debug_button_backup_venv->SetWindowStyleFlag(wxBU_EXACTFIT);
-
- auto* debug_button_restore_venv = new wxButton(
- debug_config_panel, ID_DEBUG_BUTTON_RESTORE_VENV,
- "Restore virtual env");
- debug_button_restore_venv->SetToolTip(
- "Restore the virtual environment from "
- "~/Downloads/TaSTT_venv");
- debug_button_restore_venv->SetWindowStyleFlag(wxBU_EXACTFIT);
-
- auto* debug_button_setup_venv = new wxButton(
- debug_config_panel, ID_DEBUG_BUTTON_SETUP_VENV,
- "Set up virtual env");
- debug_button_setup_venv->SetToolTip(
- "Reinstall packages to the virtual environment");
- debug_button_setup_venv->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);
- sizer->Add(debug_button_backup_venv, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(debug_button_restore_venv, /*proportion=*/0,
- /*flags=*/wxEXPAND);
- sizer->Add(debug_button_setup_venv, /*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);
- }
-
- // Now that transcribe_out_ has been created, we can deserialize.
- app_c_ = std::make_unique<AppConfig>(transcribe_out_);
- app_c_->Deserialize(AppConfig::kConfigPath);
-
- Bind(wxEVT_CLOSE_WINDOW, &Frame::OnExit, this);
- 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::OnDumpMics, this, ID_PY_DUMP_MICS_BUTTON);
- Bind(wxEVT_BUTTON, &Frame::OnGenerateFX, this,
- ID_UNITY_BUTTON_GEN_ANIMATOR);
- Bind(wxEVT_BUTTON, &Frame::OnUnityAutoRefresh, this,
- ID_UNITY_BUTTON_AUTO_REFRESH);
- Bind(wxEVT_BUTTON, &Frame::OnUnityAutoRefreshStop, this,
- ID_UNITY_BUTTON_AUTO_REFRESH_STOP);
- 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_BUTTON, &Frame::OnBackupVenv, this, ID_DEBUG_BUTTON_BACKUP_VENV);
- Bind(wxEVT_BUTTON, &Frame::OnRestoreVenv, this,
- ID_DEBUG_BUTTON_RESTORE_VENV);
- Bind(wxEVT_BUTTON, &Frame::OnSetupVenv, this,
- ID_DEBUG_BUTTON_SETUP_VENV);
- Bind(wxEVT_CHOICE, &Frame::OnUnityParamChange, this,
- ID_UNITY_CHARS_PER_SYNC);
- Bind(wxEVT_CHOICE, &Frame::OnUnityParamChange, this,
- ID_UNITY_BYTES_PER_CHAR);
- Bind(wxEVT_CHECKBOX, &Frame::OnUnityParamChange, this,
- ID_UNITY_ENABLE_PHONEMES);
-
- // wx needs this to be able to load PNGs.
- wxImage::AddHandler(&png_handler_);
- LoadAndSetIcons();
-
- // Make tooltips show up for longer.
- wxToolTip::SetAutoPop(/*milliseconds=*/ 10 * 1000);
-
- // Initialize input fields using AppConfig.
- ApplyConfigToInputFields();
-
- Resize();
- OnUnityParamChangeImpl();
-
- // Every 100 milliseconds we drain output from the Python app.
- py_app_drain_.Start(/*milliseconds=*/100);
-}
-
-void Frame::ApplyConfigToInputFields()
-{
- // Transcription panel
- auto* py_app_mic = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_MIC));
- int mic_idx = GetDropdownChoiceIndex(kMicChoices,
- kNumMicChoices, app_c_->microphone, kMicDefault);
- py_app_mic->SetSelection(mic_idx);
-
- auto* py_app_lang = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_LANG));
- int lang_idx = GetDropdownChoiceIndex(kLangChoices,
- kNumLangChoices, app_c_->language, kLangDefault);
- py_app_lang->SetSelection(lang_idx);
-
- auto* py_app_translate_target = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_TRANSLATE_TARGET));
- int translate_target_idx = GetDropdownChoiceIndex(kLangTargetChoices,
- kNumLangTargetChoices, app_c_->language_target, kLangTargetDefault);
- py_app_translate_target->SetSelection(translate_target_idx);
-
- auto* py_app_model = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_MODEL));
- int model_idx = GetDropdownChoiceIndex(kModelChoices,
- kNumModelChoices, app_c_->model, kModelDefault);
- py_app_model->SetSelection(model_idx);
-
- auto* py_app_model_translation = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_MODEL_TRANSLATION));
- int model_translation_idx = GetDropdownChoiceIndex(kModelTranslationChoices,
- kNumModelTranslationChoices, app_c_->model_translation, kModelTranslationDefault);
- py_app_model_translation->SetSelection(model_translation_idx);
-
- auto* py_app_chars_per_sync = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_CHARS_PER_SYNC));
- int chars_idx = GetDropdownChoiceIndex(kCharsPerSync,
- kNumCharsPerSync, std::to_string(app_c_->chars_per_sync),
- kCharsDefault);
- py_app_chars_per_sync->SetSelection(chars_idx);
-
- auto* py_app_bytes_per_char = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_BYTES_PER_CHAR));
- int bytes_idx = GetDropdownChoiceIndex(kBytesPerChar,
- kNumBytesPerChar, std::to_string(app_c_->bytes_per_char),
- kBytesDefault);
- py_app_bytes_per_char->SetSelection(bytes_idx);
-
- auto* py_app_button = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_BUTTON));
- int button_idx = GetDropdownChoiceIndex(kButton,
- kNumButtons, app_c_->button, kButtonDefault);
- py_app_button->SetSelection(button_idx);
-
- auto* py_app_prio = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_PRIO));
- int prio_idx = GetDropdownChoiceIndex(kPrio,
- kNumPrios, app_c_->prio, kPrioDefault);
- py_app_prio->SetSelection(prio_idx);
-
- auto* py_app_compute_type = static_cast<wxChoice*>(FindWindowById(ID_PY_APP_COMPUTE_TYPE));
- int compute_type_idx = GetDropdownChoiceIndex(kComputeType,
- kNumComputeTypes, app_c_->compute_type, kComputeTypeDefault);
- py_app_compute_type->SetSelection(compute_type_idx);
-
- auto* py_app_desktop_keybind = static_cast<wxTextCtrl*>(FindWindowById(ID_PY_APP_KEYBIND));
- py_app_desktop_keybind->Clear();
- py_app_desktop_keybind->AppendText(app_c_->keybind);
-
- auto* py_app_desktop_browser_src_port = static_cast<wxTextCtrl*>(FindWindowById(ID_PY_APP_BROWSER_SRC_PORT));
- py_app_desktop_browser_src_port->Clear();
- py_app_desktop_browser_src_port->AppendText(std::to_string(app_c_->browser_src_port));
-
- auto* py_app_rows = static_cast<wxTextCtrl*>(FindWindowById(ID_PY_APP_ROWS));
- py_app_rows->Clear();
- py_app_rows->AppendText(std::to_string(app_c_->rows));
-
- auto* py_app_cols = static_cast<wxTextCtrl*>(FindWindowById(ID_PY_APP_COLS));
- py_app_cols->Clear();
- py_app_cols->AppendText(std::to_string(app_c_->cols));
-
- auto* py_app_gpu_idx = static_cast<wxTextCtrl*>(FindWindowById(ID_PY_APP_GPU_IDX));
- py_app_gpu_idx->Clear();
- py_app_gpu_idx->AppendText(std::to_string(app_c_->gpu_idx));
-
- auto* py_app_min_silence_duration_ms = static_cast<wxTextCtrl*>(FindWindowById(ID_PY_APP_MIN_SILENCE_DURATION_MS));
- py_app_min_silence_duration_ms->Clear();
- py_app_min_silence_duration_ms->AppendText(std::to_string(app_c_->min_silence_duration_ms));
-
- auto* py_app_max_speech_duration_s = static_cast<wxTextCtrl*>(FindWindowById(ID_PY_APP_MAX_SPEECH_DURATION_S));
- py_app_max_speech_duration_s->Clear();
- py_app_max_speech_duration_s->AppendText(std::to_string(app_c_->max_speech_duration_s));
-
- auto* py_app_reset_after_silence_s = static_cast<wxTextCtrl*>(FindWindowById(ID_PY_APP_RESET_AFTER_SILENCE_S));
- py_app_reset_after_silence_s->Clear();
- py_app_reset_after_silence_s->AppendText(std::to_string(app_c_->reset_after_silence_s));
-
- auto* py_app_transcription_loop_delay_ms = static_cast<wxTextCtrl*>(FindWindowById(ID_PY_APP_TRANSCRIPTION_LOOP_DELAY_MS));
- py_app_transcription_loop_delay_ms->Clear();
- py_app_transcription_loop_delay_ms->AppendText(std::to_string(app_c_->transcription_loop_delay_ms));
-
- auto* py_app_enable_local_beep = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_LOCAL_BEEP));
- py_app_enable_local_beep->SetValue(app_c_->enable_local_beep);
-
- auto* py_app_enable_orig_lang = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_ORIG_LANG));
- py_app_enable_orig_lang->SetValue(app_c_->enable_orig_lang);
-
- auto* py_app_enable_browser_src = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_BROWSER_SRC));
- py_app_enable_browser_src->SetValue(app_c_->enable_browser_src);
-
- auto* py_app_use_cpu = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_USE_CPU));
- py_app_use_cpu->SetValue(app_c_->use_cpu);
-
- auto* py_app_use_builtin = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_USE_BUILTIN));
- py_app_use_builtin->SetValue(app_c_->use_builtin);
-
- auto* py_app_enable_uwu_filter = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_UWU_FILTER));
- py_app_enable_uwu_filter->SetValue(app_c_->enable_uwu_filter);
-
- auto* py_app_remove_trailing_period = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_REMOVE_TRAILING_PERIOD));
- py_app_remove_trailing_period->SetValue(app_c_->remove_trailing_period);
-
- auto* py_app_enable_uppercase_filter = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_UPPERCASE_FILTER));
- py_app_enable_uppercase_filter->SetValue(app_c_->enable_uppercase_filter);
-
- auto* py_app_enable_lowercase_filter = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_LOWERCASE_FILTER));
- py_app_enable_lowercase_filter->SetValue(app_c_->enable_lowercase_filter);
-
- auto* py_app_enable_profanity_filter = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_PROFANITY_FILTER));
- py_app_enable_profanity_filter->SetValue(app_c_->enable_profanity_filter);
-
- auto* py_app_enable_debug_mode = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_DEBUG_MODE));
- py_app_enable_debug_mode->SetValue(app_c_->enable_debug_mode);
-
- auto* py_app_reset_on_toggle = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_RESET_ON_TOGGLE));
- py_app_reset_on_toggle->SetValue(app_c_->reset_on_toggle);
-
- auto* py_app_enable_previews = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_PREVIEWS));
- py_app_enable_previews->SetValue(app_c_->enable_previews);
-
- auto* py_app_enable_lock_at_spawn = static_cast<wxCheckBox*>(FindWindowById(ID_PY_APP_ENABLE_LOCK_AT_SPAWN));
- py_app_enable_lock_at_spawn->SetValue(app_c_->enable_lock_at_spawn);
-
- // Unity panel
- auto* unity_assets_path = static_cast<wxDirPickerCtrl*>(FindWindowById(ID_UNITY_ASSETS_FILE_PICKER));
- unity_assets_path->SetPath(app_c_->assets_path);
-
- auto* unity_animator_path = static_cast<wxFilePickerCtrl*>(FindWindowById(ID_UNITY_ANIMATOR_FILE_PICKER));
- unity_animator_path->SetPath(app_c_->fx_path);
-
- auto* unity_params_path = static_cast<wxFilePickerCtrl*>(FindWindowById(ID_UNITY_PARAMETERS_FILE_PICKER));
- unity_params_path->SetPath(app_c_->params_path);
-
- auto* unity_menu_path = static_cast<wxFilePickerCtrl*>(FindWindowById(ID_UNITY_MENU_FILE_PICKER));
- unity_menu_path->SetPath(app_c_->menu_path);
-
- auto* unity_generated_dir = static_cast<wxTextCtrl*>(FindWindowById(ID_UNITY_ANIMATOR_GENERATED_DIR));
- unity_generated_dir->Clear();
- unity_generated_dir->AppendText(app_c_->unity_generated_dir);
-
- auto* unity_chars_per_sync = static_cast<wxChoice*>(FindWindowById(ID_UNITY_CHARS_PER_SYNC));
- unity_chars_per_sync->SetSelection(chars_idx);
-
- auto* unity_bytes_per_char = static_cast<wxChoice*>(FindWindowById(ID_UNITY_BYTES_PER_CHAR));
- unity_bytes_per_char->SetSelection(bytes_idx);
-
- auto* unity_rows = static_cast<wxTextCtrl*>(FindWindowById(ID_UNITY_ROWS));
- unity_rows->Clear();
- unity_rows->AppendText(std::to_string(app_c_->rows));
-
- auto* unity_cols = static_cast<wxTextCtrl*>(FindWindowById(ID_UNITY_COLS));
- unity_cols->Clear();
- unity_cols->AppendText(std::to_string(app_c_->cols));
-
- auto* unity_texture_sz = static_cast<wxTextCtrl*>(FindWindowById(ID_UNITY_TEXTURE_SZ));
- unity_texture_sz->Clear();
- unity_texture_sz->AppendText(std::to_string(app_c_->texture_sz));
-
- auto* unity_clear_osc = static_cast<wxCheckBox*>(FindWindowById(ID_UNITY_CLEAR_OSC));
- unity_clear_osc->SetValue(app_c_->clear_osc);
-
- auto* unity_enable_phonemes = static_cast<wxCheckBox*>(FindWindowById(ID_UNITY_ENABLE_PHONEMES));
- unity_enable_phonemes->SetValue(app_c_->enable_phonemes);
-}
-
-void Frame::OnExit(wxCloseEvent& event)
-{
- OnAppStop();
- OnUnityAutoRefreshStop();
- event.Skip();
-}
-
-void Frame::OnNavbarTranscribe(wxCommandEvent& event)
-{
- transcribe_panel_->Hide();
- unity_panel_->Hide();
- debug_panel_->Hide();
-
- // Initialize input fields using AppConfig.
- ApplyConfigToInputFields();
-
- transcribe_panel_->Show();
- Resize();
-}
-
-void Frame::OnNavbarUnity(wxCommandEvent& event)
-{
- transcribe_panel_->Hide();
- unity_panel_->Hide();
- debug_panel_->Hide();
-
- // Initialize input fields using AppConfig.
- ApplyConfigToInputFields();
-
- unity_panel_->Show();
- Resize();
-}
-
-void Frame::OnNavbarDebug(wxCommandEvent& event)
-{
- transcribe_panel_->Hide();
- unity_panel_->Hide();
- debug_panel_->Hide();
-
- // Initialize input fields using AppConfig.
- ApplyConfigToInputFields();
-
- debug_panel_->Show();
- Resize();
-}
-
-bool FindDirectoryByPrefix(wxTextCtrl* out, const std::string& prefix, std::filesystem::path& path) {
- std::error_code ec;
- // Find directory starting with "cudnn"
- for (const auto& entry :
- std::filesystem::directory_iterator(".", ec)) {
- if (ec) {
- Log(out, "Failed to iterate cwd: {}\n",
- ec.message());
- return false;
- }
-
- if (entry.is_directory(ec) &&
- !ec &&
- entry.path().filename().string().starts_with(prefix)) {
- path = entry.path();
- return true;
- }
- }
- return false;
-}
-
-void Frame::EnsureVirtualEnv(bool block, bool force)
-{
- auto status = env_proc_.wait_for(std::chrono::seconds(0));
- if (status != std::future_status::ready) {
- Log(transcribe_out_, "Virtual environment setup already running\n");
- return;
- }
-
- static const std::filesystem::path venv_flag = std::filesystem::current_path() / ".venv_is_set_up";
- if (!force && std::filesystem::exists(venv_flag)) {
- std::ifstream venv_flag_ifs(venv_flag);
- std::string venv_flag_ts_str;
- std::getline(venv_flag_ifs, venv_flag_ts_str);
-
- int64_t venv_flag_ts;
- bool is_valid = false;
- try {
- venv_flag_ts = std::stol(venv_flag_ts_str);
- is_valid = true;
- }
- catch (const std::invalid_argument&) {
- Log(transcribe_out_, "Could not venv flag timestamp \"{}\" as long "
- "- will re-setup venv");
- }
- catch (const std::out_of_range&) {
- Log(transcribe_out_, "Could not venv flag timestamp \"{}\" as long "
- "- will re-setup venv");
- }
- return;
- }
-
- env_proc_ = std::move(std::async(std::launch::async, [&]() {
- Log(transcribe_out_, "Setting up Python virtual environment\n");
- Log(transcribe_out_, "This could take several minutes, please be "
- "patient!\n");
- Log(transcribe_out_, "This will download ~1GB of dependencies.\n");
-
- {
- Log(transcribe_out_, " Installing pip\n");
- auto out_cb = [&](const std::string& out, const std::string& err) {
- Log(transcribe_out_, "{}", out);
- Log(transcribe_out_, "{}", err);
- };
- if (!PythonWrapper::InstallPip(std::move(out_cb))) {
- Log(transcribe_out_, "Failed to install pip!\n");
- return false;
- }
- }
-
- Log(transcribe_out_, " Installing python dependencies\n");
- auto out_cb = [&](const std::string& out, const std::string& err) {
- Log(transcribe_out_, "{}", out);
- Log(transcribe_out_, "{}", err);
- };
- if (!PythonWrapper::InvokeWithArgs(*app_c_,
- {
- "-u", // Unbuffered output
- "-m pip",
- "install",
- "-r Resources/Scripts/requirements_frozen.txt",
- }, out_cb)) {
- Log(transcribe_out_, "Failed to launch environment setup thread!\n");
- return false;
- }
-
- Log(transcribe_out_, " Fetching CuDNN\n");
- if (!PythonWrapper::InvokeWithArgs(*app_c_,
- {
- "-m wget",
- "https://developer.download.nvidia.com/compute/cudnn/redist/cudnn/windows-x86_64/cudnn-windows-x86_64-9.5.1.17_cuda12-archive.zip"
- }, out_cb)) {
- }
- Log(transcribe_out_, " Unzipping CuDNN\n");
- if (!PythonWrapper::InvokeWithArgs(*app_c_,
- {
- "-m zipfile -e",
- "cudnn-windows-x86_64-9.5.1.17_cuda12-archive.zip",
- "."
- }, out_cb)) {
- }
- Log(transcribe_out_, " Installing CuDNN\n");
- {
- std::filesystem::path cudnn_dir;
- if (!FindDirectoryByPrefix(transcribe_out_, "cudnn", cudnn_dir)) {
- Log(transcribe_out_, "Failed to find unzipped cudnn "
- "directory\n");
- return false;
- }
- std::error_code ec;
- const std::filesystem::path dest_dir = "Resources/Scripts";
- for (const auto& entry :
- std::filesystem::recursive_directory_iterator(cudnn_dir, ec)) {
- if (ec) {
- Log(transcribe_out_, "Failed to iterate cudnn dir: {}\n",
- ec.message());
- return false;
- }
- if (!entry.is_regular_file(ec)) {
- continue;
- }
- if (ec) {
- Log(transcribe_out_, "Skipping unrecognized file type "
- "{}: {}\n", entry.path().string(), ec.message());
- continue;
- }
- if (entry.path().extension() != ".dll") {
- continue;
- }
- std::filesystem::path dest =
- dest_dir / entry.path().filename();
- // Remove destination
- std::filesystem::remove(dest, ec);
- if (ec) {
- Log(transcribe_out_, "Failed to delete old CuDNN .dll: {}\n",
- ec.message());
- return false;
- }
- // Rename file
- std::filesystem::rename(entry.path(), dest, ec);
- if (ec) {
- Log(transcribe_out_, "Failed to move CuDNN .dll: {}\n",
- ec.message());
- }
- }
- // Delete cudnn dir
- std::filesystem::remove_all(cudnn_dir, ec);
- if (ec) {
- Log(transcribe_out_, "Failed to remove old CuDNN dir: {}\n",
- ec.message());
- }
- }
-
- Log(transcribe_out_, "Successfully set up virtual environment!\n");
-
- std::ofstream venv_flag_ofs(venv_flag);
- auto now = std::chrono::system_clock::now();
- const int64_t seconds_since_epoch = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
- venv_flag_ofs << std::to_string(seconds_since_epoch);
-
- return true;
- }));
-
- if (block) {
- // Spinning prevents the GUI from hanging.
- while (true) {
- auto status = env_proc_.wait_for(std::chrono::milliseconds(1));
- if (status == std::future_status::ready) {
- break;
- }
- }
- }
-}
-
-void Frame::OnDumpMics(wxCommandEvent& event)
-{
- auto status = dump_mics_.wait_for(std::chrono::seconds(0));
- if (status != std::future_status::ready) {
- Log(transcribe_out_, "Mic dump already running\n");
- return;
- }
- dump_mics_ = std::move(std::async(std::launch::async, [&]() {
- EnsureVirtualEnv(/*block=*/true);
- Log(transcribe_out_, "Getting mics...\n");
- Log(transcribe_out_, "{}\n", PythonWrapper::DumpMics());
- return true;
- }));
-}
-
-bool GetUserPath(wxTextCtrl* out,
- const std::string& raw, std::filesystem::path& clean,
- const std::string& err_prefix = "", bool must_exist = true) {
- clean = raw;
- if (must_exist && !std::filesystem::exists(clean)) {
- std::ostringstream oss;
- oss << err_prefix << ": User-provided path does not exist at "
- << clean << std::endl;
- Log(out, oss.str().c_str());
- return false;
- }
- return true;
-}
-
-void Frame::OnGenerateFX(wxCommandEvent& event)
-{
- auto status = unity_app_.wait_for(std::chrono::seconds(0));
- if (status != std::future_status::ready) {
- Log(unity_out_, "Unity process already running\n");
- return;
- }
-
- unity_app_ = std::move(std::async(std::launch::async, [&]() {
- Log(unity_out_, "Generating animator\n");
-
- EnsureVirtualEnv(/*block=*/true);
-
- std::filesystem::path unity_assets_path;
- if (!GetUserPath(unity_out_,
- unity_assets_file_picker_->GetPath().ToStdString(),
- unity_assets_path,
- "Cannot generate FX layer: Failed to validate assets directory")) {
- return false;
- }
- std::filesystem::path unity_animator_path;
- if (!GetUserPath(unity_out_,
- unity_animator_file_picker_->GetPath().ToStdString(),
- unity_animator_path,
- "Cannot generate FX layer: Failed to validate animator directory")) {
- return false;
- }
- std::filesystem::path unity_parameters_path;
- if (!GetUserPath(unity_out_,
- unity_parameters_file_picker_->GetPath().ToStdString(),
- unity_parameters_path,
- "Cannot generate FX layer: Failed to validate parameters directory")) {
- return false;
- }
- std::filesystem::path unity_menu_path;
- if (!GetUserPath(unity_out_, unity_menu_file_picker_->GetPath().ToStdString(),
- unity_menu_path,
- "Cannot generate FX layer: Failed to validate menu directory")) {
- return false;
- }
-
- std::string unity_animator_generated_dir =
- unity_animator_generated_dir_->GetLineText(0).ToStdString();
- std::string unity_animator_generated_name =
- unity_animator_generated_name_->GetLineText(0).ToStdString();
- std::string unity_parameters_generated_name =
- unity_parameters_generated_name_->GetLineText(0).ToStdString();
- std::string unity_menu_generated_name =
- unity_menu_generated_name_->GetLineText(0).ToStdString();
-
- int chars_per_sync_idx = unity_chars_per_sync_->GetSelection();
- if (chars_per_sync_idx == wxNOT_FOUND) {
- chars_per_sync_idx = kCharsDefault;
- }
- int bytes_per_char_idx = unity_bytes_per_char_->GetSelection();
- if (bytes_per_char_idx == wxNOT_FOUND) {
- bytes_per_char_idx = kBytesDefault;
- }
-
- ASSIGN_OR_RETURN_BOOL(int, rows, stoiInRange(transcribe_out_, unity_rows_->GetValue().ToStdString(), "rows", 1, 10));
- ASSIGN_OR_RETURN_BOOL(int, cols, stoiInRange(transcribe_out_, unity_cols_->GetValue().ToStdString(), "cols", 1, 120));
- ASSIGN_OR_RETURN_BOOL(int, texture_sz, stoiInRange(transcribe_out_, unity_texture_sz_->GetValue().ToStdString(), "texture_sz", 128, 8192));
- ASSIGN_OR_RETURN_BOOL(int, chars_per_sync, stoiInRange(transcribe_out_, kCharsPerSync[chars_per_sync_idx].ToStdString(), "chars_per_sync", 1, 24));
- ASSIGN_OR_RETURN_BOOL(int, bytes_per_char, stoiInRange(transcribe_out_, kBytesPerChar[bytes_per_char_idx].ToStdString(), "bytes_per_char", 1, 2));
-
- app_c_->assets_path = unity_assets_path.string();
- app_c_->fx_path = unity_animator_path.string();
- app_c_->params_path = unity_parameters_path.string();
- app_c_->menu_path = unity_menu_path.string();
- app_c_->unity_generated_dir = unity_animator_generated_dir;
- app_c_->bytes_per_char = bytes_per_char;
- app_c_->chars_per_sync = chars_per_sync;
- app_c_->rows = rows;
- app_c_->cols = cols;
- app_c_->texture_sz = texture_sz;
- app_c_->clear_osc = unity_clear_osc_->GetValue();
- app_c_->enable_phonemes = unity_enable_phonemes_->GetValue();
- app_c_->Serialize(AppConfig::kConfigPath);
-
- std::string out;
- if (!PythonWrapper::GenerateAnimator(
- *app_c_,
- std::string(AppConfig::kConfigPath),
- unity_animator_generated_dir,
- unity_animator_generated_name,
- unity_parameters_generated_name,
- unity_menu_generated_name,
- unity_out_)) {
- Log(unity_out_, "Failed to generate animator:\n%s\n", out.c_str());
- }
- return true;
- }));
-}
-
-// Return a non-cryptographic hash of the file at `path`.
-std::string hash_non_crypto(const std::string& path) {
- std::ifstream file_ifs(path, std::ios::binary);
- if (!file_ifs) {
- std::cerr << "Could not open the file: " << path << '\n';
- return 0;
- }
-
- // Read all bytes from the file into a vector
- std::vector<uint8_t> data((std::istreambuf_iterator<char>(file_ifs)),
- std::istreambuf_iterator<char>());
-
- // Compute the hash as a sum of all bytes
- uint32_t hash = std::accumulate(data.begin(), data.end(), 0);
-
- std::stringstream ss;
- ss << std::hex << hash;
- return ss.str();
-}
-
-void Frame::OnUnityAutoRefresh(wxCommandEvent& event)
-{
- auto status = unity_auto_refresh_.wait_for(std::chrono::seconds(0));
- if (status != std::future_status::ready) {
- Log(unity_out_, "Auto refresh thread already running\n");
- return;
- }
-
- run_unity_auto_refresh_ = true;
-
- unity_auto_refresh_ = std::move(std::async(std::launch::async, [&]() {
- std::string fx_hash_prev;
- std::string params_hash_prev;
- std::string menu_hash_prev;
- while (run_unity_auto_refresh_) {
- std::this_thread::sleep_for(std::chrono::seconds(3));
-
- std::filesystem::path unity_animator_path;
- if (!GetUserPath(unity_out_,
- unity_animator_file_picker_->GetPath().ToStdString(),
- unity_animator_path,
- "Cannot auto-refresh FX layer: Failed to validate animator directory")) {
- return false;
- }
- std::filesystem::path unity_parameters_path;
- if (!GetUserPath(unity_out_,
- unity_parameters_file_picker_->GetPath().ToStdString(),
- unity_parameters_path,
- "Cannot auto-refresh FX layer: Failed to validate parameters directory")) {
- return false;
- }
- std::filesystem::path unity_menu_path;
- if (!GetUserPath(unity_out_, unity_menu_file_picker_->GetPath().ToStdString(),
- unity_menu_path,
- "Cannot auto-refresh FX layer: Failed to validate menu directory")) {
- return false;
- }
-
- if (fx_hash_prev.empty() || params_hash_prev.empty() || menu_hash_prev.empty()) {
- Log(unity_out_, "Generating initial hash of animator, parameters and menu\n");
- fx_hash_prev = hash_non_crypto(unity_animator_path.string());
- params_hash_prev = hash_non_crypto(unity_parameters_path.string());
- menu_hash_prev = hash_non_crypto(unity_menu_path.string());
- continue;
- }
-
- const std::string fx_hash = hash_non_crypto(unity_animator_path.string());
- const std::string params_hash = hash_non_crypto(unity_parameters_path.string());
- const std::string menu_hash = hash_non_crypto(unity_menu_path.string());
-
- if (fx_hash.empty() || params_hash.empty() || menu_hash.empty()) {
- Log(unity_out_, "Failed to hash animator ({}, {}), parameters ({}, {}), or menu ({}, {})\n",
- unity_animator_path.string(), fx_hash,
- unity_parameters_path.string(), params_hash,
- unity_menu_path.string(), menu_hash);
- continue;
- }
-
- if (fx_hash != fx_hash_prev ||
- params_hash != params_hash_prev ||
- menu_hash != menu_hash_prev) {
- Log(unity_out_, "Detected change in animator ({}), params ({}), or menu ({}), regenerating unity assets\n",
- fx_hash != fx_hash_prev ? "CHANGED" : "NO_CHANGE",
- params_hash != params_hash_prev ? "CHANGED" : "NO_CHANGE",
- menu_hash != menu_hash_prev ? "CHANGED" : "NO_CHANGE");
- OnGenerateFX(event);
- fx_hash_prev = fx_hash;
- params_hash_prev = params_hash;
- menu_hash_prev = menu_hash;
- }
- }
- Log(unity_out_, "Stopping unity asset auto-generation\n");
- return true;
- }));
-}
-
-void Frame::OnUnityAutoRefreshStop() {
- run_unity_auto_refresh_ = false;
- auto status = unity_auto_refresh_.wait_for(std::chrono::seconds(0));
- if (status == std::future_status::ready) {
- Log(transcribe_out_, "Auto-refresh thread already stopped.\n");
- }
- else {
- unity_auto_refresh_.wait();
- Log(transcribe_out_, "Stopped transcription engine\n");
- }
-}
-
-void Frame::OnUnityAutoRefreshStop(wxCommandEvent& event) {
- OnUnityAutoRefreshStop();
-}
-
-void Frame::OnListPip(wxCommandEvent& event)
-{
- Log(debug_out_, "Listing pip packages... ");
- PythonWrapper::InvokeWithArgs(*app_c_, {
- "-m pip",
- "list",
- }, "Failed to list pip packages", debug_out_);
-
- Log(debug_out_, "Listing pip cache... ");
- PythonWrapper::InvokeWithArgs(*app_c_, {
- "-m pip",
- "cache",
- "list",
- }, "Failed to list pip cache", debug_out_);
-}
-
-void Frame::OnClearPip(wxCommandEvent& event)
-{
- Log(debug_out_, "Clearing pip cache... ");
- PythonWrapper::InvokeWithArgs(*app_c_, {
- "-m pip",
- "cache",
- "purge",
- }, "Failed to clear pip cache", debug_out_);
-}
-
-void Frame::OnResetVenv(wxCommandEvent& event)
-{
- auto status = reset_venv_proc_.wait_for(std::chrono::seconds(0));
- if (status != std::future_status::ready) {
- Log(debug_out_, "Virtual environment reset already running\n");
- return;
- }
-
- /*
- Equivalent shell:
- python -m pip freeze > venv_pkgs.txt
- python -m pip uninstall -r venv_pkgs.txt
- rm venv_pkgs.txt
- */
-
- reset_venv_proc_ = std::move(std::async(std::launch::async, [&]() {
- Log(debug_out_, "Resetting virtual environment...\n");
-
- {
- std::stringstream pkg_list_ss;
- auto out_cb = [&](const std::string& out, const std::string& err) {
- Log(debug_out_, "{}", out);
- Log(debug_out_, "{}", err);
- pkg_list_ss << out;
- };
- auto in_cb = [&](std::string& in) {};
- Log(debug_out_, "Freezing packages...\n");
- if (!PythonWrapper::InvokeWithArgs(*app_c_, { "-m pip freeze" }, out_cb, in_cb)) {
- Log(debug_out_, "failed!\n");
- return;
- }
-
- std::stringstream pkg_list_ss2;
- std::string pkg_line;
- while (std::getline(pkg_list_ss, pkg_line)) {
- if (pkg_line.find("future") != std::string::npos) {
- continue;
- }
- pkg_list_ss2 << pkg_line << std::endl;
- }
-
- std::ofstream pkgs_ofs("venv_pkgs.txt");
- pkgs_ofs << pkg_list_ss2.str();
- pkgs_ofs.close();
- }
-
- // For now, leave venv_pkgs.txt on disk for better debuggability.
- //ScopeGuard venv_pkgs_cleanup([]() { std::filesystem::remove("venv_pkgs.txt"); });
-
- {
- auto out_cb = [&](const std::string& out, const std::string& err) {
- Log(debug_out_, "{}", out);
- Log(debug_out_, "{}", err);
- };
- auto in_cb = [&](std::string& in) {};
- Log(debug_out_, "Uninstalling packages...\n");
- if (!PythonWrapper::InvokeWithArgs(*app_c_, { "-m pip uninstall -y -r venv_pkgs.txt" }, out_cb, in_cb)) {
- Log(debug_out_, "failed!\n");
- return;
- }
- }
-
- Log(debug_out_, "Virtual environment reset done!\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::OnBackupVenv(wxCommandEvent& event)
-{
- std::filesystem::path venv_path = "C:/Users";
- venv_path /= wxGetUserName().ToStdString();
- venv_path /= "Downloads/TaSTT_venv";
- venv_path = venv_path.lexically_normal();
- Log(debug_out_, "Backing up virtual environment to {}\n",
- venv_path.string());
-
- if (std::filesystem::is_directory(venv_path)) {
- Log(debug_out_, "Old backup found, removing... ");
- std::error_code err;
- if (!std::filesystem::remove_all(venv_path, err)) {
- wxLogError("Failed to remove old virtual environment backup: %s",
- err.message());
- Log(debug_out_, "failed!\n");
- return;
- }
- Log(debug_out_, "success!\n");
- }
-
- Log(debug_out_, "Copying venv... ");
- auto opts = std::filesystem::copy_options();
- opts |= std::filesystem::copy_options::overwrite_existing;
- opts |= std::filesystem::copy_options::recursive;
- std::error_code error;
- std::filesystem::copy("Resources/Python", venv_path, opts, error);
- if (error.value()) {
- wxLogError("Failed to back up virtual environment: %s (%d)",
- error.message(), error.value());
- Log(debug_out_, "failed!\n");
- return;
- }
- Log(debug_out_, "success!\n");
-}
-
-void Frame::OnRestoreVenv(wxCommandEvent& event)
-{
- std::filesystem::path venv_path = "C:/Users";
- venv_path /= wxGetUserName().ToStdString();
- venv_path /= "Downloads/TaSTT_venv";
- venv_path = venv_path.lexically_normal();
- Log(debug_out_, "Restoring virtual environment from {}\n",
- venv_path.string());
-
- if (!std::filesystem::is_directory(venv_path)) {
- wxLogError("Virtual environment backup does not exist at %s",
- venv_path.string());
- Log(debug_out_, "Failed!\n");
- }
-
- if (std::filesystem::is_directory("Resources/Python")) {
- Log(debug_out_, "Removing active virtual environment... ");
- std::error_code err;
- if (!std::filesystem::remove_all("Resources/Python", err)) {
- wxLogError("Failed to remove active virtual environment: %s",
- err.message());
- Log(debug_out_, "failed!\n");
- return;
- }
- Log(debug_out_, "success!\n");
- }
-
- Log(debug_out_, "Copying venv... ");
- auto opts = std::filesystem::copy_options();
- opts |= std::filesystem::copy_options::overwrite_existing;
- opts |= std::filesystem::copy_options::recursive;
- std::error_code error;
- std::filesystem::copy(venv_path, "Resources/Python", opts, error);
- if (error.value()) {
- wxLogError("Failed to copy venv: %s (%d)", error.message(),
- error.value());
- Log(debug_out_, "failed!\n");
- return;
- }
- Log(debug_out_, "success!\n");
-
- Log(debug_out_, "Setting up virtual env to ensure consistency. Most "
- "packages should not be re-acquired. Output is printed to the "
- "transcription panel.\n");
- EnsureVirtualEnv(/*block=*/false);
-}
-
-void Frame::OnSetupVenv(wxCommandEvent& event)
-{
- Log(debug_out_, "Setting up virtual environment. Output is printed to the "
- "transcription panel.\n");
- EnsureVirtualEnv(/*block=*/false, /*force=*/true);
-}
-
-void Frame::OnUnityParamChangeImpl() {
- int chars_per_sync_idx = unity_chars_per_sync_->GetSelection();
- if (chars_per_sync_idx == wxNOT_FOUND) {
- chars_per_sync_idx = kCharsDefault;
- }
- ASSIGN_OR_RETURN_VOID(int, chars_per_sync, stoiInRange(transcribe_out_, kCharsPerSync[chars_per_sync_idx].ToStdString(), "chars_per_sync", 1, 24));
- int bytes_per_char_idx = unity_bytes_per_char_->GetSelection();
- if (bytes_per_char_idx == wxNOT_FOUND) {
- bytes_per_char_idx = kBytesDefault;
- }
- ASSIGN_OR_RETURN_VOID(int, bytes_per_char, stoiInRange(transcribe_out_, kBytesPerChar[bytes_per_char_idx].ToStdString(), "bytes_per_char", 1, 2));
-
- // Used to select which region is being updated.
- int select_bits = 8;
- // Used to update the active region.
- int layer_bits = (chars_per_sync * bytes_per_char) * 8;
- // Used to control the size of the board.
- int scale_bits = 8;
- // These are all the misc bits we use:
- // 1. dummy (we should get rid of this one)
- // 2. show
- // 3. disable
- // 4. lock
- // 5. clear
- int misc_bits = 5;
-
- int phoneme_bits = 0;
- if (unity_enable_phonemes_->GetValue()) {
- phoneme_bits = 6;
- }
-
- int total_bits = select_bits + layer_bits + scale_bits + misc_bits + phoneme_bits;
-
- Log(unity_out_, "This configuration will use {} bits of avatar parameter space:\n", total_bits);
- Log(unity_out_, " {} bits coming from ({} characters per sync) * ({} bytes per character)\n", layer_bits, chars_per_sync, bytes_per_char);
- Log(unity_out_, " {} bits coming from fixed overheads\n", select_bits + scale_bits + misc_bits);
- if (phoneme_bits > 0) {
- Log(unity_out_, " {} bits coming from phonemes\n", phoneme_bits);
- }
-}
-
-void Frame::OnUnityParamChange(wxCommandEvent& event) {
- OnUnityParamChangeImpl();
-}
-
-void Frame::OnAppStart(wxCommandEvent& event) {
- auto status = py_app_.wait_for(std::chrono::seconds(0));
- if (status != std::future_status::ready) {
- Log(transcribe_out_, "Transcription engine already running\n");
- return;
- }
-
- status = obs_app_.wait_for(std::chrono::seconds(0));
- if (status != std::future_status::ready) {
- Log(transcribe_out_, "Transcription engine (OBS server) already running\n");
- return;
- }
-
- Log(transcribe_out_, "Launching transcription engine\n");
-
- int which_mic = py_app_mic_->GetSelection();
- if (which_mic == wxNOT_FOUND) {
- which_mic = kMicDefault;
- }
- int which_lang = py_app_lang_->GetSelection();
- if (which_lang == wxNOT_FOUND) {
- which_lang = kLangDefault;
- }
- int which_translate_target = py_app_translate_target_->GetSelection();
- if (which_translate_target == wxNOT_FOUND) {
- which_translate_target = kLangDefault;
- }
- int which_model = py_app_model_->GetSelection();
- if (which_model == wxNOT_FOUND) {
- which_model = kModelDefault;
- }
- int which_model_translation = py_app_model_translation_->GetSelection();
- if (which_model_translation == wxNOT_FOUND) {
- which_model_translation = kModelTranslationDefault;
- }
- int chars_per_sync_idx = py_app_chars_per_sync_->GetSelection();
- if (chars_per_sync_idx == wxNOT_FOUND) {
- chars_per_sync_idx = kCharsDefault;
- }
- int bytes_per_char_idx = py_app_bytes_per_char_->GetSelection();
- if (bytes_per_char_idx == wxNOT_FOUND) {
- bytes_per_char_idx = kBytesDefault;
- }
- int button_idx = py_app_button_->GetSelection();
- if (button_idx == wxNOT_FOUND) {
- button_idx = kButtonDefault;
- }
- int prio_idx = py_app_prio_->GetSelection();
- if (prio_idx == wxNOT_FOUND) {
- prio_idx = kPrioDefault;
- }
- int compute_type_idx = py_app_compute_type_->GetSelection();
- if (compute_type_idx == wxNOT_FOUND) {
- compute_type_idx = kComputeTypeDefault;
- }
-
- const bool enable_local_beep = py_app_enable_local_beep_->GetValue();
- const bool enable_orig_lang = py_app_enable_orig_lang_->GetValue();
- const bool enable_browser_src = py_app_enable_browser_src_->GetValue();
- const bool use_cpu = py_app_use_cpu_->GetValue();
- const bool use_builtin = py_app_use_builtin_->GetValue();
- const bool enable_uwu_filter = py_app_enable_uwu_filter_->GetValue();
- const bool remove_trailing_period = py_app_remove_trailing_period_->GetValue();
- const bool enable_uppercase_filter = py_app_enable_uppercase_filter_->GetValue();
- const bool enable_lowercase_filter = py_app_enable_lowercase_filter_->GetValue();
- const bool enable_profanity_filter = py_app_enable_profanity_filter_->GetValue();
- const bool enable_debug_mode = py_app_enable_debug_mode_->GetValue();
- const bool reset_on_toggle = py_app_reset_on_toggle_->GetValue();
- const bool enable_previews = py_app_enable_previews_->GetValue();
- const bool enable_lock_at_spawn = py_app_enable_lock_at_spawn_->GetValue();
-
- ASSIGN_OR_RETURN_VOID(int, rows, stoiInRange(transcribe_out_, py_app_rows_->GetValue().ToStdString(), "rows", 1, 10));
- ASSIGN_OR_RETURN_VOID(int, cols, stoiInRange(transcribe_out_, py_app_cols_->GetValue().ToStdString(), "cols", 1, 120));
- ASSIGN_OR_RETURN_VOID(int, chars_per_sync, stoiInRange(transcribe_out_, kCharsPerSync[chars_per_sync_idx].ToStdString(), "chars_per_sync", 1, 24));
- ASSIGN_OR_RETURN_VOID(int, bytes_per_char, stoiInRange(transcribe_out_, kBytesPerChar[bytes_per_char_idx].ToStdString(), "bytes_per_char", 1, 2));
- ASSIGN_OR_RETURN_VOID(int, gpu_idx, stoiInRange(transcribe_out_, py_app_gpu_idx_->GetValue().ToStdString(), "gpu_idx", 0, 10));
- ASSIGN_OR_RETURN_VOID(int, min_silence_duration_ms, stoiInRange(transcribe_out_, py_app_min_silence_duration_ms_->GetValue().ToStdString(), "min_silence_duration_ms", 50, 5000));
- ASSIGN_OR_RETURN_VOID(int, max_speech_duration_s, stoiInRange(transcribe_out_, py_app_max_speech_duration_s_->GetValue().ToStdString(), "max_speech_duration_s", 1, 30));
- ASSIGN_OR_RETURN_VOID(int, reset_after_silence_s, stoiInRange(transcribe_out_, py_app_reset_after_silence_s_->GetValue().ToStdString(), "reset_after_silence_s", -1, 30));
- ASSIGN_OR_RETURN_VOID(int, transcription_loop_delay_ms, stoiInRange(transcribe_out_, py_app_transcription_loop_delay_ms_->GetValue().ToStdString(), "transcription_loop_delay_ms", 0, 10000));
- ASSIGN_OR_RETURN_VOID(int, browser_src_port, stoiInRange(transcribe_out_, py_app_browser_src_port_->GetValue().ToStdString(), "browser_src_port", 1024, 65535));
-
- std::string keybind = py_app_keybind_->GetValue().ToStdString();
-
- app_c_->microphone = kMicChoices[which_mic].ToStdString();
- app_c_->language = kLangChoices[which_lang].ToStdString();
- app_c_->language_target = kLangTargetChoices[which_translate_target].ToStdString();
- app_c_->model = kModelChoices[which_model].ToStdString();
- app_c_->model_translation = kModelTranslationChoices[which_model_translation].ToStdString();
- app_c_->chars_per_sync = chars_per_sync;
- app_c_->bytes_per_char = bytes_per_char;
- app_c_->button = kButton[button_idx].ToStdString();
- app_c_->prio = kPrio[prio_idx].ToStdString();
- app_c_->compute_type = kComputeType[compute_type_idx].ToStdString();
- app_c_->rows = rows;
- app_c_->cols = cols;
- app_c_->enable_local_beep = enable_local_beep;
- app_c_->enable_orig_lang = enable_orig_lang;
- app_c_->enable_browser_src = enable_browser_src;
- app_c_->browser_src_port = browser_src_port;
- app_c_->use_cpu = use_cpu;
- app_c_->use_builtin = use_builtin;
- app_c_->enable_uwu_filter = enable_uwu_filter;
- app_c_->remove_trailing_period = remove_trailing_period;
- app_c_->enable_uppercase_filter = enable_uppercase_filter;
- app_c_->enable_lowercase_filter = enable_lowercase_filter;
- app_c_->enable_profanity_filter = enable_profanity_filter;
- app_c_->enable_debug_mode = enable_debug_mode;
- app_c_->reset_on_toggle = reset_on_toggle;
- app_c_->enable_previews = enable_previews;
- app_c_->enable_lock_at_spawn = enable_lock_at_spawn;
- app_c_->gpu_idx = gpu_idx;
- app_c_->min_silence_duration_ms = min_silence_duration_ms;
- app_c_->max_speech_duration_s = max_speech_duration_s;
- app_c_->reset_after_silence_s = reset_after_silence_s;
- app_c_->transcription_loop_delay_ms = transcription_loop_delay_ms;
- app_c_->keybind = keybind;
- app_c_->Serialize(AppConfig::kConfigPath);
-
- auto out_cb = [&](const std::string& out, const std::string& err) {
- Log(transcribe_out_, "{}", out);
- Log(transcribe_out_, "{}", err);
-
- std::istringstream out_iss(out);
- std::string out_line;
- while (std::getline(out_iss, out_line)) {
- if (out_line.starts_with("Finalized: 1")) {
- transcript_.SetFinalized(true);
- }
- else if (out_line.starts_with("Finalized: 0")) {
- transcript_.SetFinalized(false);
- }
-
- std::regex pattern("^Transcript: ");
- if (std::regex_search(out_line, pattern)) {
- std::string filtered_transcript = std::regex_replace(out_line, pattern, "");
- filtered_transcript.erase(std::remove_if(filtered_transcript.begin(), filtered_transcript.end(), [](char c) {
- return c == '\n' || c == '\r';
- }), filtered_transcript.end());
- //Log(transcribe_out_, "Got transcription line! Transcript: \"{}\"", filtered_transcript);
- transcript_.Set(std::move(filtered_transcript));
- }
-
- pattern = std::regex("^Preview: ");
- if (std::regex_search(out_line, pattern)) {
- std::string filtered_transcript = std::regex_replace(out_line, pattern, "");
- filtered_transcript.erase(std::remove_if(filtered_transcript.begin(), filtered_transcript.end(), [](char c) {
- return c == '\n' || c == '\r';
- }), filtered_transcript.end());
- //Log(transcribe_out_, "Got transcription line! Transcript: \"{}\"", filtered_transcript);
- transcript_.SetPreview(std::move(filtered_transcript));
- }
- }
- };
- auto in_cb = [&](std::string& in) {
- if (!run_py_app_) {
- std::ostringstream oss;
- oss << "exit" << std::endl;
- in = oss.str();
- }
- };
- auto run_cb = [&]() {
- return run_py_app_;
- };
- run_py_app_ = true;
- auto prestart_cb = [this]() -> void {
- EnsureVirtualEnv(/*block=*/true);
- };
-
-#if 0
- obs_app_ = std::async(std::launch::async,
- [this, enable_browser_src, browser_src_port]() -> bool {
- if (enable_browser_src) {
- BrowserSource browser_src(browser_src_port, transcribe_out_, &transcript_);
- browser_src.Run(&run_py_app_);
- }
- return true;
- });
-#endif
- const std::string config_path(AppConfig::kConfigPath);
- py_app_ = std::move(PythonWrapper::StartApp(*app_c_,
- config_path, transcribe_out_,
- std::move(out_cb), std::move(in_cb), std::move(run_cb),
- std::move(prestart_cb)));
- Log(transcribe_out_, "py app valid: {}\n", py_app_.valid());
-}
-
-void Frame::OnAppStop() {
- run_py_app_ = false;
- auto status = py_app_.wait_for(std::chrono::seconds(0));
- if (status == std::future_status::ready) {
- Log(transcribe_out_, "Transcription engine already stopped\n");
- }
- else {
- py_app_.wait();
- Log(transcribe_out_, "Stopped transcription engine\n");
- }
- status = obs_app_.wait_for(std::chrono::seconds(0));
- if (status == std::future_status::ready) {
- Log(transcribe_out_, "Browser source already stopped\n");
- }
- else {
- obs_app_.wait();
- Log(transcribe_out_, "Stopped browser source\n");
- }
- transcript_.Clear();
-}
-
-void Frame::OnAppStop(wxCommandEvent& event) {
- OnAppStop();
-}
-
-void Frame::OnAppDrain(wxTimerEvent& event) {
- Logging::kThreadLogger.Drain();
-}
-
-void Frame::LoadAndSetIcons() {
- const char* icons[] = {
- "Resources/Images/logo.png",
- "Resources/Images/logo_16x16.png",
- "Resources/Images/logo_32x32.png",
- };
- wxIconBundle icon_bundle;
- for (const auto& icon_path : icons) {
- if (!std::filesystem::exists(icon_path)) {
- wxLogFatalError("Logo is missing from %s", icon_path);
- }
- icon_bundle.AddIcon(icon_path, wxBITMAP_TYPE_PNG);
- }
- SetIcons(icon_bundle);
-}
-
-void Frame::Resize()
-{
- auto frame_sz = GetBestSize();
- auto panel_sz = main_panel_->GetBestSize();
-
- //auto ideal_sz = panel_sz;
- //ideal_sz.x += frame_sz.x;
- //ideal_sz.y += frame_sz.y;
-
- this->SetSize(panel_sz);
-}
-
diff --git a/GUI/GUI/GUI/Frame.h b/GUI/GUI/GUI/Frame.h deleted file mode 100644 index 7e5c7c7..0000000 --- a/GUI/GUI/GUI/Frame.h +++ /dev/null @@ -1,134 +0,0 @@ -#pragma once
-
-#include <wx/filepicker.h>
-#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#include "Config.h"
-#include "Transcript.h"
-
-#include <future>
-#include <memory>
-
-class Frame : public wxFrame
-{
-public:
- Frame();
-
-private:
- wxPNGHandler png_handler_;
-
- 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_;
- wxTextCtrl* unity_parameters_generated_name_;
- wxTextCtrl* unity_menu_generated_name_;
-
- wxTextCtrl* py_app_rows_;
- wxTextCtrl* py_app_cols_;
- wxTextCtrl* py_app_gpu_idx_;
- wxTextCtrl* py_app_min_silence_duration_ms_;
- wxTextCtrl* py_app_max_speech_duration_s_;
- wxTextCtrl* py_app_reset_after_silence_s_;
- wxTextCtrl* py_app_transcription_loop_delay_ms_;
- wxTextCtrl* py_app_keybind_;
- wxTextCtrl* py_app_browser_src_port_;
- wxTextCtrl* py_app_commit_fuzz_threshold_;
- wxTextCtrl* unity_rows_;
- wxTextCtrl* unity_cols_;
- wxTextCtrl* unity_texture_sz_;
-
- wxDirPickerCtrl* unity_assets_file_picker_;
- wxFilePickerCtrl* unity_animator_file_picker_;
- wxFilePickerCtrl* unity_parameters_file_picker_;
- wxFilePickerCtrl* unity_menu_file_picker_;
-
- wxChoice* py_app_mic_;
- wxChoice* py_app_lang_;
- wxChoice* py_app_translate_target_;
- wxChoice* py_app_model_;
- wxChoice* py_app_model_translation_;
- // TODO(yum) figure out how to deduplicate these objects
- wxChoice* py_app_chars_per_sync_;
- wxChoice* py_app_bytes_per_char_;
- wxChoice* py_app_button_;
- wxChoice* py_app_prio_;
- wxChoice* py_app_compute_type_;
- wxChoice* unity_chars_per_sync_;
- wxChoice* unity_bytes_per_char_;
-
- wxCheckBox* py_app_enable_local_beep_;
- wxCheckBox* py_app_enable_orig_lang_;
- wxCheckBox* py_app_enable_browser_src_;
- wxCheckBox* py_app_use_cpu_;
- wxCheckBox* py_app_use_builtin_;
- wxCheckBox* py_app_enable_uwu_filter_;
- wxCheckBox* py_app_remove_trailing_period_;
- wxCheckBox* py_app_enable_uppercase_filter_;
- wxCheckBox* py_app_enable_lowercase_filter_;
- wxCheckBox* py_app_enable_profanity_filter_;
- wxCheckBox* py_app_enable_debug_mode_;
- wxCheckBox* py_app_reset_on_toggle_;
- wxCheckBox* py_app_enable_previews_;
- wxCheckBox* py_app_enable_lock_at_spawn_;
- wxCheckBox* unity_clear_osc_;
- wxCheckBox* unity_enable_phonemes_;
-
- std::future<bool> py_app_;
- std::future<bool> obs_app_;
- Transcript transcript_;
- bool run_py_app_;
- bool run_unity_auto_refresh_;
- std::future<bool> unity_app_;
- std::future<bool> unity_auto_refresh_;
- std::future<bool> dump_mics_;
- std::future<bool> env_proc_;
- std::future<void> reset_venv_proc_;
-
- wxTimer py_app_drain_;
-
- std::unique_ptr<AppConfig> app_c_;
-
- // Initialize GUI input fields using `app_c_`.
- void ApplyConfigToInputFields();
- // Ensure that virtual env is set up.
- void EnsureVirtualEnv(bool block, bool force = false);
-
- void OnExit(wxCloseEvent& event);
- void OnNavbarTranscribe(wxCommandEvent& event);
- void OnNavbarUnity(wxCommandEvent& event);
- void OnNavbarDebug(wxCommandEvent& event);
- void OnDumpMics(wxCommandEvent& event);
- void OnAppStart(wxCommandEvent& event);
- void OnAppStop();
- void OnAppStop(wxCommandEvent& event);
- void OnAppDrain(wxTimerEvent& event);
- void OnGenerateFX(wxCommandEvent& event);
- void OnUnityAutoRefresh(wxCommandEvent& event);
- void OnUnityAutoRefreshStop();
- void OnUnityAutoRefreshStop(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 OnBackupVenv(wxCommandEvent& event);
- void OnRestoreVenv(wxCommandEvent& event);
- void OnSetupVenv(wxCommandEvent& event);
-
- void LoadAndSetIcons();
- void Resize();
-};
-
diff --git a/GUI/GUI/GUI/GUI.rc b/GUI/GUI/GUI/GUI.rc Binary files differdeleted file mode 100644 index 01c922a..0000000 --- a/GUI/GUI/GUI/GUI.rc +++ /dev/null diff --git a/GUI/GUI/GUI/GUI.vcxproj b/GUI/GUI/GUI/GUI.vcxproj deleted file mode 100644 index e5874c4..0000000 --- a/GUI/GUI/GUI/GUI.vcxproj +++ /dev/null @@ -1,196 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <VCProjectVersion>16.0</VCProjectVersion>
- <Keyword>Win32Proj</Keyword>
- <ProjectGuid>{e17ad8b1-0565-459b-b8d0-2024cc6c5cd4}</ProjectGuid>
- <RootNamespace>GUI</RootNamespace>
- <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v143</PlatformToolset>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v143</PlatformToolset>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v143</PlatformToolset>
- <CharacterSet>Unicode</CharacterSet>
- <EnableASAN>false</EnableASAN>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v143</PlatformToolset>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="Shared">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\Libraries\wx\wxwidgets.props" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\Libraries\wx\wxwidgets.props" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\Libraries\wx\wxwidgets.props" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\Libraries\wx\wxwidgets.props" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(ProjectDir)/whisper;$(ProjectDir)/oatpp</LibraryPath>
- <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)</IncludePath>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(ProjectDir)/whisper;$(ProjectDir)/oatpp</LibraryPath>
- <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)</IncludePath>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <ConformanceMode>true</ConformanceMode>
- <LanguageStandard>stdcpp20</LanguageStandard>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <ConformanceMode>true</ConformanceMode>
- <LanguageStandard>stdcpp20</LanguageStandard>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;winspool.lib;shell32.lib;shlwapi.lib;ole32.lib;oleaut32.lib;uuid.lib;advapi32.lib;version.lib;comctl32.lib;rpcrt4.lib;ws2_32.lib;wininet.lib;winmm.lib;Whisper.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <ConformanceMode>true</ConformanceMode>
- <LanguageStandard>stdcpp20</LanguageStandard>
- <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;winspool.lib;shell32.lib;shlwapi.lib;ole32.lib;oleaut32.lib;uuid.lib;advapi32.lib;version.lib;comctl32.lib;rpcrt4.lib;ws2_32.lib;wininet.lib;winmm.lib;Whisper.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <SDLCheck>true</SDLCheck>
- <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <ConformanceMode>true</ConformanceMode>
- <LanguageStandard>stdcpp20</LanguageStandard>
- <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
- </ClCompile>
- <Link>
- <SubSystem>Windows</SubSystem>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;winspool.lib;shell32.lib;shlwapi.lib;ole32.lib;oleaut32.lib;uuid.lib;advapi32.lib;version.lib;comctl32.lib;rpcrt4.lib;ws2_32.lib;wininet.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="App.cpp" />
- <ClCompile Include="BrowserSource.cpp" />
- <ClCompile Include="Config.cpp" />
- <ClCompile Include="Frame.cpp" />
- <ClCompile Include="HTTPMapper.cpp" />
- <ClCompile Include="HTTPParser.cpp" />
- <ClCompile Include="Logging.cpp" />
- <ClCompile Include="main.cpp" />
- <ClCompile Include="PythonWrapper.cpp" />
- <ClCompile Include="Transcript.cpp" />
- <ClCompile Include="WebServer.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="App.h" />
- <ClInclude Include="BrowserSource.h" />
- <ClInclude Include="Config.h" />
- <ClInclude Include="ConfigMarshal.h" />
- <ClInclude Include="Frame.h" />
- <ClInclude Include="HTTPMapper.h" />
- <ClInclude Include="HTTPParser.h" />
- <ClInclude Include="Logging.h" />
- <ClInclude Include="PythonWrapper.h" />
- <ClInclude Include="resource.h" />
- <ClInclude Include="ScopeGuard.h" />
- <ClInclude Include="Transcript.h" />
- <ClInclude Include="Util.h" />
- <ClInclude Include="WebCommon.h" />
- <ClInclude Include="WebServer.h" />
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="GUI.rc" />
- </ItemGroup>
- <ItemGroup>
- <Image Include="..\..\..\Images\logo.png" />
- <Image Include="..\..\..\Images\logo_16x16.png" />
- <Image Include="..\..\..\Images\logo_32x32.png" />
- <Image Include="icon1.ico" />
- <Image Include="Resources\logo.png" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project>
\ No newline at end of file diff --git a/GUI/GUI/GUI/GUI.vcxproj.filters b/GUI/GUI/GUI/GUI.vcxproj.filters deleted file mode 100644 index 10069e8..0000000 --- a/GUI/GUI/GUI/GUI.vcxproj.filters +++ /dev/null @@ -1,124 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
- <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
- </Filter>
- <Filter Include="WebServer">
- <UniqueIdentifier>{a0953f26-cbc5-43b7-86c6-2d4b1030b13f}</UniqueIdentifier>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="main.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="App.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="Frame.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="PythonWrapper.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="Logging.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="Config.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="BrowserSource.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="Transcript.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="WebServer.cpp">
- <Filter>WebServer</Filter>
- </ClCompile>
- <ClCompile Include="HTTPMapper.cpp">
- <Filter>WebServer</Filter>
- </ClCompile>
- <ClCompile Include="HTTPParser.cpp">
- <Filter>WebServer</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="PythonWrapper.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="App.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="Frame.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="ScopeGuard.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="resource.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="Logging.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="Config.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="Util.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="BrowserSource.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="Transcript.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="WebCommon.h">
- <Filter>WebServer</Filter>
- </ClInclude>
- <ClInclude Include="WebServer.h">
- <Filter>WebServer</Filter>
- </ClInclude>
- <ClInclude Include="HTTPMapper.h">
- <Filter>WebServer</Filter>
- </ClInclude>
- <ClInclude Include="HTTPParser.h">
- <Filter>WebServer</Filter>
- </ClInclude>
- <ClInclude Include="ConfigMarshal.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ResourceCompile Include="GUI.rc">
- <Filter>Resource Files</Filter>
- </ResourceCompile>
- </ItemGroup>
- <ItemGroup>
- <Image Include="..\..\..\Images\logo.png">
- <Filter>Resource Files</Filter>
- </Image>
- <Image Include="icon1.ico">
- <Filter>Resource Files</Filter>
- </Image>
- <Image Include="..\..\..\Images\logo_16x16.png">
- <Filter>Resource Files</Filter>
- </Image>
- <Image Include="..\..\..\Images\logo_32x32.png">
- <Filter>Resource Files</Filter>
- </Image>
- <Image Include="Resources\logo.png">
- <Filter>Resource Files</Filter>
- </Image>
- </ItemGroup>
-</Project>
\ No newline at end of file diff --git a/GUI/GUI/GUI/GUI.vcxproj.user b/GUI/GUI/GUI/GUI.vcxproj.user deleted file mode 100644 index 052eb16..0000000 --- a/GUI/GUI/GUI/GUI.vcxproj.user +++ /dev/null @@ -1,13 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <LocalDebuggerCommand>TaSTT.exe</LocalDebuggerCommand>
- <LocalDebuggerWorkingDirectory>$(ProjectDir)/../../TaSTT/</LocalDebuggerWorkingDirectory>
- <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <LocalDebuggerCommand>TaSTT.exe</LocalDebuggerCommand>
- <LocalDebuggerWorkingDirectory>$(ProjectDir)/../../TaSTT/</LocalDebuggerWorkingDirectory>
- <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
- </PropertyGroup>
-</Project>
\ No newline at end of file diff --git a/GUI/GUI/GUI/HTTPMapper.cpp b/GUI/GUI/GUI/HTTPMapper.cpp deleted file mode 100644 index c9884ae..0000000 --- a/GUI/GUI/GUI/HTTPMapper.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "HTTPMapper.h"
-
-#include <sstream>
-#include <map>
-
-namespace {
- // Source: RFC 2616 section 6.1.1
- const std::map<int, std::string> kStatusCodeToString{
- {100, "Continue" },
- {101, "Switching Protocols"},
- {200, "OK"},
- {201, "Created"},
- {202, "Accepted"},
- {203, "Non-Authoritative Information"},
- {204, "No Content"},
- {205, "Reset Content"},
- {206, "Partial Content"},
- {300, "Multiple Choices"},
- {301, "Moved Permanently"},
- {302, "Found"},
- {303, "See Other"},
- {304, "Not Modified"},
- {305, "Use Proxy"},
- {307, "Temporary Redirect"},
- {400, "Bad Request"},
- {401, "Unauthorized"},
- {402, "Payment Required"},
- {403, "Forbidden"},
- {404, "Not Found"},
- {405, "Method Not Allowed"},
- {406, "Not Acceptable"},
- };
-}
-
-namespace WebServer {
- std::string HTTPMapper::Map(const int status_code,
- const std::string& payload, const ContentType type) {
- switch (type) {
- case HTML:
- return HTTPMapperHTML().Map(status_code, payload);
- case JSON:
- return HTTPMapperJSON().Map(status_code, payload);
- }
- }
-
- std::string HTTPMapperHTML::Map(const int status_code,
- const std::string& payload) {
- std::ostringstream oss;
- // This might throw and crash the app, but that's ok, just don't use an unsupported code.
- oss << "HTTP/1.1 " << status_code << " " << kStatusCodeToString.at(status_code) << "\r\n";
- oss << "Content-Type: text/html\r\n";
- oss << "Content-Length: " << std::to_string(payload.size()) << "\r\n";
- oss << "\r\n";
- oss << payload;
- return oss.str();
- }
-
- std::string HTTPMapperJSON::Map(const int status_code,
- const std::string& payload) {
- std::ostringstream oss;
- // This might throw and crash the app, but that's ok, just don't use an unsupported code.
- oss << "HTTP/1.1 " << status_code << " " << kStatusCodeToString.at(status_code) << "\r\n";
- oss << "Content-Type: application/json\r\n";
- oss << "Content-Length: " << std::to_string(payload.size()) << "\r\n";
- oss << "\r\n";
- oss << payload;
- return oss.str();
- }
-}
\ No newline at end of file diff --git a/GUI/GUI/GUI/HTTPMapper.h b/GUI/GUI/GUI/HTTPMapper.h deleted file mode 100644 index 4086fe9..0000000 --- a/GUI/GUI/GUI/HTTPMapper.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once
-
-#include "WebCommon.h"
-
-#include <string>
-
-namespace WebServer {
-
- class HTTPMapper {
- public:
- HTTPMapper() {}
- virtual ~HTTPMapper() {}
-
- std::string Map(int status_code,
- const std::string& payload, ContentType type);
- };
-
- class HTTPMapperHTML : public HTTPMapper {
- public:
- HTTPMapperHTML() {}
- virtual ~HTTPMapperHTML() {}
-
- std::string Map(int status_code,
- const std::string& payload);
- };
-
- class HTTPMapperJSON : public HTTPMapper {
- public:
- HTTPMapperJSON() {}
- virtual ~HTTPMapperJSON() {}
-
- std::string Map(int status_code,
- const std::string& payload);
- };
-}
diff --git a/GUI/GUI/GUI/HTTPParser.cpp b/GUI/GUI/GUI/HTTPParser.cpp deleted file mode 100644 index 3e15afa..0000000 --- a/GUI/GUI/GUI/HTTPParser.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include "HTTPParser.h"
-#include "ScopeGuard.h"
-
-#include <sstream>
-
-namespace WebServer {
- HTTPParser::HTTPParser() {}
-
- namespace {
- constexpr const char kLineDelim[] = "\r\n";
- constexpr const char kHeadersDelim[] = "\r\n\r\n";
- constexpr const char kRfcSP[] = " ";
- constexpr const char kRfcHT[] = "\t";
- constexpr const char kRfcLWS[] = " \t\r\n";
- };
-
- bool HTTPParser::Parse(const std::string& raw_http, std::string& err) {
- std::ostringstream err_oss;
- ScopeGuard err_oss_flush([&]() { err += err_oss.str(); });
-
- ParserState state = PARSER_STATE_START_LINE;
- size_t pos = 0;
- while (pos < raw_http.length()) {
- size_t end;
- switch (state) {
- case PARSER_STATE_START_LINE:
- end = raw_http.find(kLineDelim, pos);
- break;
- case PARSER_STATE_HEADERS:
- end = raw_http.find(kHeadersDelim, pos);
- break;
- case PARSER_STATE_PAYLOAD:
- end = raw_http.length();
- break;
- }
- ScopeGuard advance_pos([&]() { pos = end + 1; });
- if (end == std::string::npos) {
- err_oss << "Failed to parse HTTP in state " << state << ": No delimiter!" << std::endl;
- return false;
- }
- std::string_view segment(raw_http.data() + pos, end - pos);
- if (!ParseSegment(segment, state, err)) {
- return false;
- }
- }
- return true;
- }
-
- const std::string& HTTPParser::GetMethod() const {
- return method_;
- }
-
- const std::string& HTTPParser::GetPath() const {
- return path_;
- }
-
- bool HTTPParser::GetHeader(const std::string& header, std::string& value) const {
- auto iter = headers_.find(header);
- if (iter == headers_.end()) {
- return false;
- }
- value = iter->second;
- return true;
- }
-
- const std::map<std::string, std::string>& HTTPParser::GetHeaders() const {
- return headers_;
- }
-
- const std::string& HTTPParser::GetPayload() const {
- return payload_;
- }
-
- bool HTTPParser::ParseSegment(
- const std::string_view segment,
- ParserState& state,
- std::string& err) {
- std::ostringstream err_oss;
- ScopeGuard err_oss_flush([&]() { err += err_oss.str(); });
- switch (state) {
- case PARSER_STATE_START_LINE:
- return ParseStartLine(segment, state, err);
- case PARSER_STATE_HEADERS:
- return ParseHeaders(segment, state, err);
- case PARSER_STATE_PAYLOAD:
- return ParsePayload(segment, state, err);
- }
- }
-
- enum StartLineParserState {
- START_LINE_PARSER_STATE_METHOD,
- START_LINE_PARSER_STATE_PATH,
- START_LINE_PARSER_STATE_VERSION,
- START_LINE_PARSER_STATE_END,
- };
- // Source: RFC 2616 section 5.1.1.
- bool HTTPParser::ParseStartLine(
- const std::string_view segment,
- ParserState& state,
- std::string& err) {
- std::ostringstream err_oss;
- ScopeGuard err_oss_flush([&]() { err += err_oss.str(); });
-
- // Request-Line = Method SP Request-URI SP HTTP-Version CRLF
- // SP == space.
- // Thus we expect to see exactly three space-delimited chunks.
- StartLineParserState cur_state = START_LINE_PARSER_STATE_METHOD;
- size_t pos = 0;
- while (pos < segment.length()) {
- size_t end = segment.find(' ', pos);
- if (end == std::string::npos) {
- end = segment.length();
- }
- ScopeGuard advance_pos([&]() { pos = end + 1; });
-
- std::string_view cur_segment(segment.data() + pos, end - pos);
- switch (cur_state) {
- case START_LINE_PARSER_STATE_METHOD:
- method_ = cur_segment;
- cur_state = START_LINE_PARSER_STATE_PATH;
- continue;
- case START_LINE_PARSER_STATE_PATH:
- path_ = cur_segment;
- cur_state = START_LINE_PARSER_STATE_VERSION;
- continue;
- case START_LINE_PARSER_STATE_VERSION:
- // TODO(yum) check this
- cur_state = START_LINE_PARSER_STATE_END;
- continue;
- case START_LINE_PARSER_STATE_END:
- err_oss << "Invalid start line: has too many parts: " << segment << std::endl;
- return false;
- }
- }
- if (cur_state != START_LINE_PARSER_STATE_END) {
- err_oss << "Invalid start line: missing parts: " << segment << std::endl;
- return false;
- }
-
- state = PARSER_STATE_HEADERS;
- return true;
- }
-
- // Source: RFC 2616 section 4.2.
- bool HTTPParser::ParseHeaders(
- const std::string_view segment,
- ParserState& state,
- std::string& err) {
- std::ostringstream err_oss;
- ScopeGuard err_oss_flush([&]() { err += err_oss.str(); });
-
- // From the RFC:
- // message-header = field-name ":" [ field-value ]
- // field-name = token
- // field-value = *(field-content | LWS)
- // field-content = <the OCTETs making up the field - value
- // and consisting of either * TEXT or combinations
- // of token, separators, and quoted-string>
- // Takewaways:
- // * field-name is guaranteed to not be preceded by whitespace
- // * field-name is guaranteed to be followed by ":"
- // * field-value may be preceded by LWS
- // * multi-line field-values are guaranteed to start with either ' '
- // or '\t'
- size_t pos = 0;
- std::string key, value;
- while (pos < segment.length()) {
- // Divide into lines.
- size_t end = segment.find(kLineDelim, pos);
- if (end == std::string::npos) {
- end = segment.length();
- }
- ScopeGuard advance_pos([&]() { pos = end + 1; });
-
- std::string_view line = segment.substr(pos, end - pos);
- if (line.empty()) {
- continue;
- }
-
- // Lengthen the current line to cover multi-line header.
- while (end + 1 < segment.length() &&
- (segment[end + 1] == ' ' || segment[end + 1] == '\t')) {
- end = segment.find("\r\n", end + 1);
- }
-
- size_t sep = line.find(':');
- if (sep == std::string::npos) {
- err_oss << "Invalid header: No ':' delimiter: " << segment << std::endl;
- return false;
- }
-
- std::string_view key = line.substr(0, sep);
- size_t key_start = key.find_first_not_of(kRfcLWS);
- size_t key_end = key.find_last_not_of(kRfcLWS);
- key = key.substr(key_start, (key_end - key_start) + 1);
- // Value may contain interspersed LWS (linear whitespace).
- // Could scrub it out, but not necessary for our purposes.
- std::string_view value = line.substr(sep + 1);
- size_t value_start = value.find_first_not_of(kRfcLWS);
- size_t value_end = value.find_last_not_of(kRfcLWS);
- value = value.substr(value_start, (value_end - value_start) + 1);
-
- headers_[std::string(key)] = value;
- }
-
- state = PARSER_STATE_PAYLOAD;
- return true;
- }
-
- bool HTTPParser::ParsePayload(
- const std::string_view segment,
- ParserState& state,
- std::string& err) {
- payload_ = segment;
- return true;
- }
-}
diff --git a/GUI/GUI/GUI/HTTPParser.h b/GUI/GUI/GUI/HTTPParser.h deleted file mode 100644 index 7fcfe0e..0000000 --- a/GUI/GUI/GUI/HTTPParser.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once
-
-#include <string>
-#include <map>
-
-namespace WebServer {
-
- // A simple HTTP/1.1 message parser based on RFC 2616.
- class HTTPParser
- {
- public:
- HTTPParser();
-
- bool Parse(const std::string& raw_http, std::string& err);
-
- const std::string& GetMethod() const;
- const std::string& GetPath() const;
- bool GetHeader(const std::string& header, std::string& value) const;
- const std::map<std::string, std::string>& GetHeaders() const;
- const std::string& GetPayload() const;
-
- private:
- enum ParserState {
- PARSER_STATE_START_LINE,
- PARSER_STATE_HEADERS,
- PARSER_STATE_PAYLOAD,
- };
-
- bool ParseSegment(
- const std::string_view segment,
- ParserState& state,
- std::string& err);
- bool ParseStartLine(
- const std::string_view segment,
- ParserState& state,
- std::string& err);
- bool ParseHeaders(
- const std::string_view segment,
- ParserState& state,
- std::string& err);
- bool ParsePayload(
- const std::string_view segment,
- ParserState& state,
- std::string& err);
-
- std::string method_;
- std::string path_;
- std::map<std::string, std::string> headers_;
- std::string payload_;
- };
-}
diff --git a/GUI/GUI/GUI/Logging.cpp b/GUI/GUI/GUI/Logging.cpp deleted file mode 100644 index 6983a40..0000000 --- a/GUI/GUI/GUI/Logging.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "Logging.h"
-
-#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#include <wx/process.h>
-#include <wx/tokenzr.h>
-#include <wx/txtstrm.h>
-
-#include <filesystem>
-#include <fstream>
-#include <regex>
-#include <sstream>
-#include <string>
-
-Logging::ThreadLogger Logging::kThreadLogger = Logging::ThreadLogger();
-
-Logging::ThreadLogger::ThreadLogger() {}
-
-void Logging::ThreadLogger::Append(wxTextCtrl* frame, const std::string&& message)
-{
- std::scoped_lock l(mu_);
- auto entry = messages_.find(frame);
- if (entry == messages_.end()) {
- messages_[frame] = { std::move(message) };
- }
- else {
- messages_[frame].push_back(message);
- }
-}
-
-void Logging::ThreadLogger::Drain()
-{
- std::scoped_lock l(mu_);
- const std::filesystem::path log_path("Resources/log.txt");
- std::ofstream log_ofs(log_path, std::ios_base::app);
- for (const auto& [frame, messages] : messages_) {
- for (const auto& message : messages) {
- if (frame) {
- frame->AppendText(message);
- }
- else {
- wxLogError("%s", message);
- }
- log_ofs << message;
- }
-
- // Constrain wxTextCtrl's to a few hundred lines to keep memory usage /
- // general snappiness in check.
- if (frame) {
- constexpr int kHalfMaxChars = 50 * 1000;
- int nchars;
- while ((nchars = frame->GetLastPosition()) > kHalfMaxChars) {
- wxString allText = frame->GetValue();
- wxArrayString lines = wxStringTokenize(allText, "\n");
- // Keep only the last kHalfMaxLines lines.
- size_t nlines = lines.GetCount();
- size_t linesToRemove = nlines / 2;
-
- // Remove lines from the beginning
- lines.RemoveAt(0, linesToRemove);
-
- // Join the lines back into a single string
- wxString newText = wxJoin(lines, '\n');
-
- // Update the text in the wxTextCtrl
- frame->Clear();
- frame->AppendText(newText);
- }
- }
- }
- log_ofs.close();
- messages_.clear();
-
- // Drop first 50% of lines in file if larger than 1 MB.
- if (std::filesystem::file_size(log_path) > 1024 * 1024) {
- std::vector<std::string> lines;
- std::ifstream log_ifs(log_path);
- std::string line;
- while (std::getline(log_ifs, line)) {
- lines.push_back(std::move(line));
- }
- log_ofs = std::ofstream(log_path);
- for (int i = lines.size() / 2; i < lines.size(); i++) {
- log_ofs << lines[i];
- }
- }
-}
-
-std::string Logging::HidePII(const std::string&& str,
- const std::string& replacement) {
- try {
- std::regex c_users("([A-Za-z]:\\\\+[Uu]sers\\\\+)[a-zA-Z0-9_ ]+");
- std::string real_replacement = "$1" + replacement;
- return std::regex_replace(str, c_users, real_replacement);
- }
- catch (const std::exception& e) {
- wxLogFatalError(e.what());
- }
- wxLogFatalError("Unhandled regex error (HidePII)");
- return ""; // Compiler thinks we can get here (we can't) and prints a warning.
-}
-
-void Logging::DrainAsyncOutput(wxProcess* proc, wxTextCtrl* frame) {
- if (!proc) {
- return;
- }
-
- while (proc->IsInputAvailable()) {
- wxTextInputStream iss(*(proc->GetInputStream()));
- Log(frame, " {}\n", iss.ReadLine().ToStdString());
- }
-
- while (proc->IsErrorAvailable()) {
- wxTextInputStream iss(*(proc->GetErrorStream()));
- Log(frame, " {}\n", iss.ReadLine().ToStdString());
- }
-}
diff --git a/GUI/GUI/GUI/Logging.h b/GUI/GUI/GUI/Logging.h deleted file mode 100644 index 193617a..0000000 --- a/GUI/GUI/GUI/Logging.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once
-
-#pragma once
-
-#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#include <wx/process.h>
-#include <wx/txtstrm.h>
-
-#include <format>
-#include <string>
-#include <string_view>
-
-namespace Logging {
- // Remove personally identifying information (PII) from str.
- //
- // For example, this translates "C:/Users/foo/Desktop" to "C:/Users/*****/Desktop".
- std::string HidePII(const std::string&& str, const std::string& replacement = "*****");
-
- class ThreadLogger {
- public:
- ThreadLogger();
-
- void Append(wxTextCtrl* frame, const std::string&& message);
- void Drain();
- private:
- std::mutex mu_;
- std::unordered_map<wxTextCtrl*, std::list<std::string>> messages_;
- };
-
- extern ThreadLogger kThreadLogger;
-
- // Provides a simple Python format()-like interface to wxTextCtrl.
- // Ex: Log(my_textctrl_, "{}\n", "Hello, world!");
- template<typename... Args>
- void Log(wxTextCtrl* frame, std::string_view format, Args&&... args) {
- const std::string raw = std::vformat(format, std::make_format_args(args...));
- const std::string masked = HidePII(std::move(raw));
- const std::string decoded = wxString::FromUTF8(masked).ToStdString();
-
- kThreadLogger.Append(frame, std::move(decoded));
- }
-
- void DrainAsyncOutput(wxProcess* proc, wxTextCtrl* frame);
-}
-
diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp deleted file mode 100644 index 765a283..0000000 --- a/GUI/GUI/GUI/PythonWrapper.cpp +++ /dev/null @@ -1,894 +0,0 @@ -// Import rand_s() WIN32 API. -#define _CRT_RAND_S -// Silence security warnings caused by importing stdlib.h before wx. -#define _CRT_SECURE_NO_WARNINGS - -#include <stdlib.h> - -#include "Logging.h" -#include "PythonWrapper.h" -#include "ScopeGuard.h" -#include "Util.h" -#include "Config.h" - -#include <stdio.h> -#include <Windows.h> - -#include <filesystem> -#include <fstream> -#include <sstream> - -using ::Logging::Log; - -namespace { - constexpr const char kEmotesPickle[] = "Resources/Fonts/Bitmaps/emotes.map"; -} // namespace - -class PythonProcess : public wxProcess { -public: - PythonProcess(std::function<void(wxProcess* proc, int ret)>&& exit_callback) : exit_cb_(exit_callback) { - Redirect(); - } - - virtual void OnTerminate(int pid, int status) wxOVERRIDE { - exit_cb_(this, status); - } - -private: - const std::function<void(wxProcess* proc, int ret)> exit_cb_; -}; - -wxProcess* PythonWrapper::InvokeAsyncWithArgs(std::vector<std::string>&& args, - std::function<void(wxProcess* proc, int ret)>&& exit_callback) { - std::ostringstream cmd_oss; - cmd_oss << "Resources/Python/python.exe"; - for (const auto& arg : args) { - cmd_oss << " " << arg; - } - - auto *p = new PythonProcess(std::move(exit_callback)); - int pid = wxExecute(cmd_oss.str(), wxEXEC_ASYNC, p); - - if (!pid) { - delete p; - p = nullptr; - } - - return p; -} - -std::string GetWin32ErrMsg() { - DWORD error = GetLastError(); - LPSTR err_msg = nullptr; - FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&err_msg, - 0, - NULL - ); - ScopeGuard err_msg_cleanup([&]() { LocalFree(err_msg); }); - return std::to_string(error) + ": " + err_msg; -} - - -std::string DrainWin32Pipe(const HANDLE pipe) { - DWORD bytes_avail; - std::ostringstream oss; - if (PeekNamedPipe( - pipe, - nullptr, // buffer to read into - 0, // buffer size - nullptr, // bytes read - &bytes_avail, - nullptr // bytes left in this message - )) { - DWORD cur_bytes_read = 0; - DWORD sum_bytes_read = 0; - std::vector<char> buf(4096, 0); - while (sum_bytes_read < bytes_avail && - ReadFile(pipe, buf.data(), buf.size() - 1, &cur_bytes_read, NULL) && - cur_bytes_read > 0) { - oss << std::string(buf.data(), cur_bytes_read); - sum_bytes_read += cur_bytes_read; - } - } - return oss.str(); -} - -bool PythonWrapper::InvokeCommandWithArgs( - const AppConfig& app_c, - const std::string& cmd, - std::vector<std::string>&& args, - const std::function<void(const std::string& out, const std::string& err)>&& out_cb, - const std::function<void(std::string& in)>&& in_cb, - const std::function<bool()>&& run_cb) { - std::ostringstream cmd_oss; - cmd_oss << cmd; - for (const auto& arg : args) { - cmd_oss << " " << arg; - } - - HANDLE stdout_read{}; - HANDLE stdout_write{}; - SECURITY_ATTRIBUTES stdout_sec_attr{}; - stdout_sec_attr.nLength = sizeof(stdout_sec_attr); - stdout_sec_attr.bInheritHandle = TRUE; - if (!CreatePipe(&stdout_read, &stdout_write, &stdout_sec_attr, 0)) { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" << cmd_oss.str() - << "\": Failed to create stdout pipe: " << GetWin32ErrMsg() << std::endl; - out_cb("", err_oss.str()); - return false; - } - ScopeGuard stdout_cleanup([&]() { - if (stdout_read) { - CloseHandle(stdout_read); - } - if (stdout_write) { - CloseHandle(stdout_write); - } - }); - SetHandleInformation(stdout_read, HANDLE_FLAG_INHERIT, 0); - - HANDLE stderr_read{}; - HANDLE stderr_write{}; - SECURITY_ATTRIBUTES stderr_sec_attr{}; - stderr_sec_attr.nLength = sizeof(stderr_sec_attr); - stderr_sec_attr.bInheritHandle = TRUE; - - if (!CreatePipe(&stderr_read, &stderr_write, &stderr_sec_attr, 0)) { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" << cmd_oss.str() - << "\": Failed to create stderr pipe: " << GetWin32ErrMsg() << std::endl; - out_cb("", err_oss.str()); - return false; - } - ScopeGuard stderr_cleanup([&]() { - if (stderr_read) { - CloseHandle(stderr_read); - } - if (stderr_write) { - CloseHandle(stderr_write); - } - }); - SetHandleInformation(stderr_read, HANDLE_FLAG_INHERIT, 0); - - HANDLE stdin_read{}; - HANDLE stdin_write{}; - SECURITY_ATTRIBUTES stdin_sec_attr{}; - stdin_sec_attr.nLength = sizeof(stdin_sec_attr); - stdin_sec_attr.bInheritHandle = TRUE; - - if (!CreatePipe(&stdin_read, &stdin_write, &stdin_sec_attr, 0)) { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" << cmd_oss.str() - << "\": Failed to create stdin pipe: " << GetWin32ErrMsg() << std::endl; - out_cb("", err_oss.str()); - return false; - } - ScopeGuard stdin_cleanup([&]() { - if (stdin_read) { - CloseHandle(stdin_read); - } - if (stdin_write) { - CloseHandle(stdin_write); - } - }); - SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0); - - STARTUPINFOA si{}; - si.cb = sizeof(si); - si.hStdOutput = stdout_write; - si.hStdError = stderr_write; - si.hStdInput = stdin_read; - si.dwFlags |= STARTF_USESTDHANDLES; - si.dwFlags |= STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - PROCESS_INFORMATION pi{}; - std::string env; - - { - std::vector<char> buf(4096 * 8, 0); - DWORD len = GetEnvironmentVariableA("PATH", buf.data(), buf.size() - 1); - if (len > 0) { - env = std::string("PATH=") + buf.data(); - } - else { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" << cmd_oss.str() - << "\": Failed to get PATH env variable: " << GetWin32ErrMsg() << std::endl; - out_cb("", err_oss.str()); - return false; - } - - // Add git to PATH - std::filesystem::path git_path = - (std::filesystem::current_path() / - "Resources/PortableGit/bin").lexically_normal(); - if (env.find(git_path.string()) == std::string::npos) { - env += ";" + git_path.string(); - - // Add updated PATH to current process's environment - if (!SetEnvironmentVariableA("PATH", env.c_str())) { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" - << cmd_oss.str() - << "\": Failed to add git to PATH: " << GetWin32ErrMsg() - << std::endl; - out_cb("", err_oss.str()); - return false; - } - } - - // Add python scripts to PATH - std::filesystem::path py_bin = (std::filesystem::current_path() / - "Resources/Python/Scripts").lexically_normal(); - if (env.find(py_bin.string()) == std::string::npos) { - env += ";" + py_bin.string(); - - // Add updated PATH to current process's environment - if (!SetEnvironmentVariableA("PATH", env.c_str())) { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" - << cmd_oss.str() - << "\": Failed to add python scripts to PATH: " - << GetWin32ErrMsg() << std::endl; - out_cb("", err_oss.str()); - return false; - } - } - - // Add scripts to PATH - std::filesystem::path dll_bin = (std::filesystem::current_path() / - "Resources/Scripts").lexically_normal(); - if (env.find(dll_bin.string()) == std::string::npos) { - env += ";" + dll_bin.string(); - - // Add updated PATH to current process's environment - if (!SetEnvironmentVariableA("PATH", env.c_str())) { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" - << cmd_oss.str() - << "\": Failed to add python scripts to PATH: " - << GetWin32ErrMsg() << std::endl; - out_cb("", err_oss.str()); - return false; - } - } - } - - std::string cmd_str = cmd_oss.str(); - if (!CreateProcessA(NULL, // application name - cmd_str.data(), - NULL, // process attributes - NULL, // thread attributes - TRUE, // whether to inherit parent's handles - 0, // creation flags - //env.data(), - nullptr, // environment variables - std::filesystem::current_path().string().c_str(), // current directory - &si, - &pi)) { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" << cmd_oss.str() - << "\": Failed to launch process: " << GetWin32ErrMsg(); - out_cb("", err_oss.str()); - return false; - } - ScopeGuard pi_cleanup([&] { - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - }); - - std::map<std::string, int> prio_stoi = { - {"above normal", ABOVE_NORMAL_PRIORITY_CLASS}, - {"below normal", BELOW_NORMAL_PRIORITY_CLASS}, - {"normal", NORMAL_PRIORITY_CLASS}, - {"idle", IDLE_PRIORITY_CLASS}, - {"high", HIGH_PRIORITY_CLASS}, - {"realtime", REALTIME_PRIORITY_CLASS}, - }; - if (!SetPriorityClass(pi.hProcess, prio_stoi[app_c.prio])) { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" << cmd_oss.str() - << "\": Failed to reduce priority class: " << GetWin32ErrMsg(); - out_cb("", err_oss.str()); - return false; - } - - // While the process is running, drain output and send input every 10 ms. - DWORD timeout_ms = 10; - DWORD ret = WAIT_TIMEOUT; - while (run_cb() && ret == WAIT_TIMEOUT) { - DWORD ret = WaitForSingleObject(pi.hProcess, timeout_ms); - if (ret != WAIT_TIMEOUT) { - break; - } - std::ostringstream stdout_oss, stderr_oss; - stdout_oss << DrainWin32Pipe(stdout_read); - stderr_oss << DrainWin32Pipe(stderr_read); - out_cb(stdout_oss.str(), stderr_oss.str()); - - std::string input; - in_cb(input); - if (input.size()) { - DWORD cur_bytes_write = 0; - DWORD sum_bytes_write = 0; - std::vector<char> buf(4096, 0); - while (sum_bytes_write < input.size() && - WriteFile(stdin_write, input.data() + sum_bytes_write, - input.size() - sum_bytes_write, &cur_bytes_write, NULL)) { - sum_bytes_write += cur_bytes_write; - } - } - } - if (!run_cb()) { - DWORD timeout_ms = 1000 * 10; - DWORD ret = WaitForSingleObject(pi.hProcess, timeout_ms); - - if (ret == WAIT_TIMEOUT) { - std::ostringstream stderr_oss; - stderr_oss << "Timed out waiting for graceful exit, killing process"; - out_cb("", stderr_oss.str()); - - TerminateProcess(pi.hProcess, 0); - } - } - - std::ostringstream stdout_oss, stderr_oss; - DWORD exit_code; - if (!GetExitCodeProcess(pi.hProcess, &exit_code)) { - stderr_oss << "Failed to get exit code: " << GetWin32ErrMsg(); - } - if (exit_code != 0) { - stderr_oss << "Command exited with code " << exit_code << ": " - << GetWin32ErrMsg(); - } - - // Close write ends of pipes. If we don't do this, the last read will block forever. - CloseHandle(stdout_write); - stdout_write = 0; - CloseHandle(stderr_write); - stderr_write = 0; - - stdout_oss << DrainWin32Pipe(stdout_read); - stderr_oss << DrainWin32Pipe(stderr_read); - out_cb(stdout_oss.str(), stderr_oss.str()); - - return exit_code == 0; -} - -bool PythonWrapper::InvokeCommandWithArgs( - const AppConfig& app_c, - const std::string& cmd, - std::vector<std::string>&& args, - std::string* py_stdout, std::string* py_stderr) { - - std::ostringstream out_oss, err_oss; - auto out_cb = [&](const std::string& out, const std::string& err) { - out_oss << out; - err_oss << err; - }; - bool ret = InvokeCommandWithArgs(app_c, cmd, std::move(args), std::move(out_cb)); - if (py_stderr) { - *py_stderr = err_oss.str(); - } - *py_stdout = out_oss.str(); - return ret; -} - -bool PythonWrapper::InvokeWithArgs( - const AppConfig& app_c, - std::vector<std::string>&& args, - std::string* py_stdout, std::string* py_stderr) { - return InvokeCommandWithArgs(app_c, "Resources/Python/python.exe", - std::move(args), py_stdout, py_stderr); -} - -bool PythonWrapper::InvokeWithArgs( - const AppConfig& app_c, - std::vector<std::string>&& args, - const std::string&& err_msg, - wxTextCtrl* const out) { - std::string py_stdout, py_stderr; - if (InvokeWithArgs(app_c, 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 { - Log(out, "failed!\n"); - Log(out, "Error: {}: {}\n", err_msg, py_stderr); - return false; - } -} - -bool PythonWrapper::InvokeWithArgs( - const AppConfig& app_c, - std::vector<std::string>&& args, - const std::function<void(const std::string& out, const std::string& err)>&& out_cb, - const std::function<void(std::string& in)>&& in_cb, - const std::function<bool()>&& run_cb) { - return InvokeCommandWithArgs(app_c, - "Resources/Python/python.exe", - std::move(args), std::move(out_cb), std::move(in_cb), std::move(run_cb)); -} - - -std::string PythonWrapper::GetVersion() { - std::string py_stdout, py_stderr; - bool ok = InvokeWithArgs(AppConfig(nullptr), { "--version" }, &py_stdout, &py_stderr); - if (!ok) { - wxLogError("Failed to get python version: %s", py_stderr.c_str()); - } - return py_stdout; -} - -std::string PythonWrapper::DumpMics() { - std::string py_stdout, py_stderr; - const std::string dump_mics_path = "Resources/Scripts/dump_mic_devices.py"; - bool ok = InvokeWithArgs(AppConfig(nullptr), { dump_mics_path }, &py_stdout, &py_stderr); - if (!ok) { - wxLogError("Failed to dump mic devices: %s", py_stderr.c_str()); - } - return py_stdout; -} - -bool PythonWrapper::InstallPip(std::string* out, std::string* err) { - std::ostringstream out_oss, err_oss; - auto out_cb = [&](const std::string& out, const std::string& err) { - out_oss << out; - err_oss << err; - }; - bool ret = InstallPip(std::move(out_cb)); - *out = out_oss.str(); - if (err) { - *err = err_oss.str(); - } - return ret; -} - -bool PythonWrapper::InstallPip( - const std::function<void(const std::string& out, const std::string& err)>&& out_cb, - const std::function<void(std::string& in)>&& in_cb, - const std::function<bool()>&& run_cb) { - std::filesystem::path pip_flag = "Resources/Python/.pip_installed"; - if (std::filesystem::exists(pip_flag)) { - out_cb("Pip flag exists, already installed\n", ""); - return true; - } - - std::string pip_path = "Resources/Python/get-pip.py"; - if (!InvokeWithArgs(AppConfig(nullptr), { pip_path }, std::move(out_cb), std::move(in_cb), - std::move(run_cb))) { - return false; - } - - // Create the flag file so subsstd::chrono::milliseconds(100));equent calls don't reinstall. - std::ofstream flag_ofs(pip_path); - flag_ofs.close(); - - return true; -} - -std::future<bool> PythonWrapper::StartApp( - const AppConfig& app_c, - const std::string& config_path, - wxTextCtrl *out, - const std::function<void(const std::string& out, const std::string& err)>&& out_cb, - const std::function<void(std::string& in)>&& in_cb, - const std::function<bool()>&& run_cb, - const std::function<void()>&& prestart_cb) { - - return std::move(std::async(std::launch::async, - []( - const AppConfig app_c, - const std::string config_path, - wxTextCtrl *out, - const std::function<void(const std::string& out, const std::string& err)>&& out_cb, - const std::function<void(std::string& in)>&& in_cb, - const std::function<bool()>&& run_cb, - const std::function<void()>&& prestart_cb) -> bool { - prestart_cb(); - - Log(out, "DEBUG::{}:: config_path: {}\n", __func__, config_path); - - return InvokeWithArgs( - app_c, - { - "-u", // Unbuffered output - "Resources/Scripts/transcribe_v2.py", - "--config", config_path, - }, - std::move(out_cb), - std::move(in_cb), - std::move(run_cb)); - }, app_c, config_path, out, std::move(out_cb), std::move(in_cb), - std::move(run_cb), std::move(prestart_cb))); -} - -bool PythonWrapper::GenerateAnimator( - const AppConfig& config, - const std::string& config_path, - const std::string& unity_animator_generated_dir, - const std::string& unity_animator_generated_name, - const std::string& unity_parameters_generated_name, - const std::string& unity_menu_generated_name, - wxTextCtrl* out) { - // Python script locations - std::string remove_audio_srcs_path = "Resources/Scripts/remove_audio_sources.py"; - std::string set_texture_sz_path = "Resources/Scripts/set_texture_sz.py"; - std::string libunity_path = "Resources/Scripts/libunity.py"; - std::string libtastt_path = "Resources/Scripts/libtastt.py"; - std::string generate_emotes_path = "Resources/Scripts/emotes_v2.py"; - std::string generate_params_path = "Resources/Scripts/generate_params.py"; - std::string generate_menu_path = "Resources/Scripts/generate_menu.py"; - std::string generate_shader_path = "Resources/Scripts/generate_shader.py"; - std::string shader_template_path = "Resources/Shaders/TaSTT_template.shader"; - std::string shader_lighting_template_path = "Resources/Shaders/STT_generated_template.cginc"; - std::string shader_path = "Resources/Shaders/TaSTT.shader"; - std::string shader_lighting_path = "Resources/Shaders/STT_generated.cginc"; - - // Generated directory locations - std::filesystem::path tastt_generated_dir_path = - std::filesystem::path(config.assets_path) / unity_animator_generated_dir; - std::filesystem::path guid_map_path = - tastt_generated_dir_path / "guid.map"; - std::filesystem::path tastt_animations_path = - tastt_generated_dir_path / "Animations"; - std::filesystem::path tastt_assets_path = - tastt_generated_dir_path / "UnityAssets"; - std::filesystem::path tastt_sounds_path = - tastt_generated_dir_path / "Sounds"; - std::filesystem::path tastt_shaders_path = - tastt_generated_dir_path / "Shaders"; - std::filesystem::path tastt_fonts_path = - tastt_generated_dir_path / "Fonts"; - std::filesystem::path tastt_params_path = - tastt_generated_dir_path / unity_parameters_generated_name; - std::filesystem::path tastt_menu_path = - tastt_generated_dir_path / unity_menu_generated_name; - // These are intermediate animators. We apply several transformations before - // arriving at the final animator. - std::filesystem::path tastt_fx0_path = - tastt_generated_dir_path / "FX0.controller"; - std::filesystem::path tastt_fx1_path = - tastt_generated_dir_path / "FX1.controller"; - // This is the final animator. - std::filesystem::path tastt_animator_path = - tastt_generated_dir_path / unity_animator_generated_name; - - const int texture_rows = (config.bytes_per_char == 1 ? 8 : 64); - const int texture_cols = (config.bytes_per_char == 1 ? 16 : 128); - { - Log(out, "Generating shader for {}x{} board (pass 0)...", config.rows, config.cols); - if (!InvokeWithArgs(AppConfig(nullptr), { generate_shader_path, - "--bytes_per_char", std::to_string(config.bytes_per_char), - "--board_rows", std::to_string(config.rows), - "--board_cols", std::to_string(config.cols), - "--texture_rows", std::to_string(texture_rows), - "--texture_cols", std::to_string(texture_cols), - "--shader_template", shader_template_path, - "--shader_path", shader_path }, - "Failed to generate shader", out)) { - return false; - } - } - { - Log(out, "Generating shader for {}x{} board (pass 1)...", config.rows, config.cols); - - std::string py_stdout, py_stderr; - if (!InvokeWithArgs(AppConfig(nullptr), { generate_shader_path, - "--bytes_per_char", std::to_string(config.bytes_per_char), - "--board_rows", std::to_string(config.rows), - "--board_cols", std::to_string(config.cols), - "--texture_rows", std::to_string(texture_rows), - "--texture_cols", std::to_string(texture_cols), - "--shader_template", shader_lighting_template_path, - "--shader_path", shader_lighting_path }, - "Failed to generate shader", out)) { - return false; - } - } -#if 0 - { - Log(out, "Generating emotes... "); - - std::string py_stdout, py_stderr; - if (InvokeWithArgs(AppConfig(nullptr), { generate_emotes_path, - "Resources/Fonts/Emotes/", - /*board_aspect_ratio=*/ std::to_string(6), - /*texture_aspect_ratio=*/ std::to_string(2), - "Resources/Fonts/Bitmaps/emotes.png", - kEmotesPickle - }, - &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 { - Log(out, "failed!\n"); - Log(out, "stdout: {}\n", py_stdout.c_str()); - Log(out, "stderr: {}\n", py_stderr.c_str()); - return false; - } - } -#endif - { - Log(out, "Creating {}\n", tastt_generated_dir_path.string()); - std::filesystem::create_directories(tastt_generated_dir_path); - } - { - Log(out, "Copying canned animations... "); - auto opts = std::filesystem::copy_options(); - opts |= std::filesystem::copy_options::overwrite_existing; - opts |= std::filesystem::copy_options::recursive; - std::error_code error; - std::filesystem::copy("Resources/Animations", tastt_animations_path, opts, error); - if (error.value()) { - Log(out, "failed!\n"); - Log(out, "Error: {} ({})\n", error.message(), error.value()); - return false; - } - Log(out, "success!\n"); - } - { - Log(out, "Copying canned assets... "); - auto opts = std::filesystem::copy_options(); - opts |= std::filesystem::copy_options::overwrite_existing; - opts |= std::filesystem::copy_options::recursive; - std::error_code error; - std::filesystem::copy("Resources/UnityAssets", tastt_assets_path, opts, error); - if (error.value()) { - Log(out, "failed!\n"); - Log(out, "Error: {} ({})\n", error.message(), error.value()); - return false; - } - Log(out, "success!\n"); - } - if (!config.enable_phonemes) { - std::string prefab_path = (std::filesystem::path(tastt_assets_path) / "World Constraint.prefab").string(); - Log(out, "Remove audio sources from prefab at {}\n", prefab_path); - Log(out, "Removing audio sources from prefab... "); - if (!InvokeWithArgs(AppConfig(nullptr), { remove_audio_srcs_path, - "--prefab", Quote(prefab_path) - }, - "Failed to remove audio sources", out)) { - return false; - } - Log(out, "succes!\n"); - } - { - Log(out, "Copying canned sounds... "); - auto opts = std::filesystem::copy_options(); - opts |= std::filesystem::copy_options::overwrite_existing; - opts |= std::filesystem::copy_options::recursive; - std::error_code error; - std::filesystem::copy("Resources/Sounds", tastt_sounds_path, opts, error); - if (error.value()) { - Log(out, "failed!\n"); - Log(out, "Error: {} ({})\n", error.message(), error.value()); - return false; - } - Log(out, "success!\n"); - } - { - Log(out, "Copying canned shaders... "); - auto opts = std::filesystem::copy_options(); - opts |= std::filesystem::copy_options::overwrite_existing; - opts |= std::filesystem::copy_options::recursive; - std::error_code error; - std::filesystem::copy("Resources/Shaders", tastt_shaders_path, opts, error); - if (error.value()) { - Log(out, "failed!\n"); - Log(out, "Error: {} ({})\n", error.message(), error.value()); - return false; - } - Log(out, "success!\n"); - } - { - Log(out, "Deleting shader templates... "); - try { - if (std::filesystem::exists(tastt_shaders_path) && std::filesystem::is_directory(tastt_shaders_path)) { - for (const auto& entry : std::filesystem::directory_iterator(tastt_shaders_path)) { - if (entry.is_regular_file()) { - if (entry.path().stem().string().ends_with("_template")) { - std::filesystem::remove(entry.path()); - } - } - } - } - } - catch (const std::exception& e) { - Log(out, "failed!\n"); - Log(out, "Error: {}\n", e.what()); - } - Log(out, "success!\n"); - } - { - Log(out, "Copying canned fonts... "); - auto opts = std::filesystem::copy_options(); - opts |= std::filesystem::copy_options::overwrite_existing; - opts |= std::filesystem::copy_options::recursive; - std::error_code error; - std::filesystem::copy("Resources/Fonts", tastt_fonts_path, opts, error); - if (error.value()) { - Log(out, "failed!\n"); - Log(out, "Error: {} ({})\n", error.message(), error.value()); - return false; - } - Log(out, "success!\n"); - } - if (config.bytes_per_char == 1) { - Log(out, "Applying texture memory optimization for English speakers... "); - std::error_code err; - for (int i = 0; i < 8; i++) { - std::filesystem::remove(tastt_fonts_path / ("Bitmaps/font-" + std::to_string(i) + ".png"), err); - if (err.value()) { - Log(out, "failed!\n"); - Log(out, "Error removing unicode texture: {} ({})\n", err.message(), err.value()); - return false; - } - std::filesystem::remove(tastt_fonts_path / ("Bitmaps/font-" + std::to_string(i) + ".png.meta"), err); - if (err.value()) { - Log(out, "failed!\n"); - Log(out, "Error removing unicode texture: {} ({})\n", err.message(), err.value()); - return false; - } - } - std::filesystem::remove(tastt_fonts_path / "Bitmaps/emotes.png", err); - if (err.value()) { - Log(out, "failed!\n"); - Log(out, "Error removing emotes texture: {} ({})\n", err.message(), err.value()); - return false; - } - - Log(out, "success!\n"); - } - else { - std::error_code err; - std::filesystem::remove(tastt_fonts_path / ("Bitmaps/font-ascii.png"), err); - if (err.value()) { - Log(out, "failed!\n"); - Log(out, "Error removing unicode texture: {} ({})\n", err.message(), err.value()); - return false; - } - std::filesystem::remove(tastt_fonts_path / ("Bitmaps/font-ascii.png.meta"), err); - if (err.value()) { - Log(out, "failed!\n"); - Log(out, "Error removing unicode texture: {} ({})\n", err.message(), err.value()); - return false; - } - } - { - Log(out, "Setting texture sizes... "); - std::filesystem::path fonts_dir = tastt_fonts_path / "Bitmaps"; - for (const auto& entry : std::filesystem::recursive_directory_iterator(fonts_dir)) { - Log(out, "Entry get {}\n", entry.path().string()); - Log(out, "Setting size to {}\n", config.texture_sz); - if (entry.is_regular_file() && entry.path().extension() == ".meta") { - if (!InvokeWithArgs(AppConfig(nullptr), { set_texture_sz_path, - "--meta", Quote(entry.path().string()), - "--size", std::to_string(config.texture_sz)}, - "Failed to set texture size", out)) { - return false; - } - } - } - Log(out, "succes!\n"); - } - { - Log(out, "Generating guid.map... "); - if (!InvokeWithArgs(AppConfig(nullptr), { libunity_path, "guid_map", - "--project_root", Quote(config.assets_path), - "--save_to", Quote(guid_map_path), }, - "Failed to generate guid.map", out)) { - return false; - } - } - { - Log(out, "Generating animations... "); - if (!InvokeWithArgs(AppConfig(nullptr), { libtastt_path, "gen_anims", - "--gen_anim_dir", Quote(tastt_animations_path), - "--guid_map", Quote(guid_map_path), - "--config", Quote(config_path) }, - "Failed to generate animations", out)) { - return false; - } - } - { - Log(out, "Generating FX layer... "); - if (!InvokeWithArgs(AppConfig(nullptr), { libtastt_path, "gen_fx", - "--fx_dest", Quote(tastt_fx0_path), - "--gen_anim_dir", Quote(tastt_animations_path), - "--guid_map", Quote(guid_map_path), - "--config", Quote(config_path) }, - "Failed to generate FX layer", out)) { - return false; - } - } - { - Log(out, "Merging with user animator... "); - if (!InvokeWithArgs(AppConfig(nullptr), { libunity_path, "merge", - "--fx0", Quote(config.fx_path), - "--fx1", Quote(tastt_fx0_path), - "--fx_dest", Quote(tastt_fx1_path), }, - "Failed to merge animators", out)) { - return false; - } - } - { - Log(out, "Setting noop animations... "); - if (!InvokeWithArgs(AppConfig(nullptr), { libunity_path, "set_noop_anim", - "--fx0", Quote(tastt_fx1_path), - "--fx_dest", Quote(tastt_animator_path), - "--gen_anim_dir", Quote(tastt_animations_path), - "--guid_map", Quote(guid_map_path), }, - "Failed to set noop animations", out)) { - return false; - } - } - { - Log(out, "Generating avatar parameters... "); - if (!InvokeWithArgs(AppConfig(nullptr), { generate_params_path, - "--old_params", Quote(config.params_path), - "--new_params", Quote(tastt_params_path), - "--config", Quote(config_path) }, - "Failed to generate avatar parameters", out)) { - return false; - } - } - { - Log(out, "Generating avatar menu... "); - if (!InvokeWithArgs(AppConfig(nullptr), { generate_menu_path, - "--old_menu", Quote(config.menu_path), - "--new_menu", Quote(tastt_menu_path) }, - "Failed to generate avatar menu", out)) { - return false; - } - } - if (config.clear_osc) { - 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(out, "OSC configs are stored at {}\n", osc_path.string()); - Log(out, "Clearing OSC configs... "); - - if (std::filesystem::is_directory(osc_path)) { - std::error_code err; - if (std::filesystem::remove_all(osc_path, err)) { - Log(out, "success!\n"); - } - else { - Log(out, "failed!\n"); - Log(out, "Error: {} ({})\n", err.message(), err.value()); - } - } - else { - Log(out, "OSC configs do not exist at {}, assuming already " - "cleared!\n", osc_path.string()); - } - } - - Log(out, "Done!\n"); - return true; -} - diff --git a/GUI/GUI/GUI/PythonWrapper.h b/GUI/GUI/GUI/PythonWrapper.h deleted file mode 100644 index b5fe518..0000000 --- a/GUI/GUI/GUI/PythonWrapper.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include <wx/wxprec.h> - -#ifndef WX_PRECOMP -#include <wx/wx.h> -#endif - -#include <wx/process.h> - -#include "Config.h" - -#include <filesystem> -#include <future> -#include <string> -#include <vector> - -/* - * This class wraps interactions with the embedded Python interpreter. -*/ -namespace PythonWrapper -{ - // Invoke the interpreter asynchronously with the given arguments. - // When the process exits, `exit_callback` runs. - // The caller is responsible for deleting wxProcess. - wxProcess* InvokeAsyncWithArgs(std::vector<std::string>&& args, - std::function<void(wxProcess* proc, int ret)>&& exit_callback); - - // Invoke a command on the shell with arguments. - // On error, sets `out` to an error message and returns false. - bool InvokeCommandWithArgs( - const AppConfig& app_c, - const std::string& cmd, - std::vector<std::string>&& args, - std::string* py_stdout, - std::string* py_stderr = NULL); - - // Invoke a command on the shell with arguments. - // On error, sets `out` to an error message and returns false. - bool InvokeCommandWithArgs( - const AppConfig& app_c, - const std::string& cmd, - std::vector<std::string>&& args, - const std::function<void(const std::string& out, const std::string& err)>&& out_cb, - const std::function<void(std::string& in)>&& in_cb = [](std::string&) {}, - const std::function<bool()>&& run_cb = []() { return true; }); - - // Invoke the interpreter with arguments. - // On error, sets `out` to an error message and returns false. - bool InvokeWithArgs( - const AppConfig& app_c, - std::vector<std::string>&& args, std::string* py_stdout, - std::string* py_stderr = NULL); - - bool InvokeWithArgs( - const AppConfig& app_c, - std::vector<std::string>&& args, - const std::string&& err_msg, wxTextCtrl* out); - - bool InvokeWithArgs( - const AppConfig& app_c, - std::vector<std::string>&& args, - const std::function<void(const std::string& out, const std::string& err)>&& out_cb, - const std::function<void(std::string& in)>&& in_cb = [](std::string&) {}, - const std::function<bool()>&& run_cb = []() { return true; }); - - // Execute python --version. - std::string GetVersion(); - - // Executes dump_mic_devices.py. - std::string DumpMics(); - - // Execute get-pip.py. - bool InstallPip( - const std::function<void(const std::string& out, const std::string& err)>&& out_cb, - const std::function<void(std::string& in)>&& in_cb = [](std::string&) {}, - const std::function<bool()>&& run_cb = []() { return true; }); - bool InstallPip(std::string* out, std::string* err = nullptr); - - std::future<bool> StartApp( - const AppConfig& app_c, - const std::string& config_path, - wxTextCtrl *out, - const std::function<void(const std::string& out, const std::string& err)>&& out_cb, - const std::function<void(std::string& in)>&& in_cb = [](std::string&) {}, - const std::function<bool()>&& run_cb = []() { return true; }, - const std::function<void()>&& prestart_cb = []() {}); - - bool GenerateAnimator( - const AppConfig& config, - const std::string& config_path, - const std::string& unity_animator_generated_dir, - const std::string& unity_animator_generated_name, - const std::string& unity_parameters_generated_name, - const std::string& unity_menu_generated_name, - wxTextCtrl* out); -}; - diff --git a/GUI/GUI/GUI/Resources/logo.ico b/GUI/GUI/GUI/Resources/logo.ico Binary files differdeleted file mode 100644 index aca1b5a..0000000 --- a/GUI/GUI/GUI/Resources/logo.ico +++ /dev/null diff --git a/GUI/GUI/GUI/ScopeGuard.h b/GUI/GUI/GUI/ScopeGuard.h deleted file mode 100644 index 601061c..0000000 --- a/GUI/GUI/GUI/ScopeGuard.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once
-
-#include <functional>
-#include <utility>
-
-class ScopeGuard {
-public:
- ScopeGuard(std::function<void()>&& cb) : cb_(std::move(cb)), active_(true) {}
- ~ScopeGuard() {
- Invoke();
- }
-
- ScopeGuard() = delete;
- ScopeGuard(ScopeGuard&) = delete;
- ScopeGuard(const ScopeGuard&) = delete;
- ScopeGuard(ScopeGuard&&) = delete;
- ScopeGuard& operator=(ScopeGuard&) = delete;
- ScopeGuard& operator=(const ScopeGuard&) = delete;
-
- void Cancel() { active_ = false; }
-
- void Invoke() {
- if (active_) {
- cb_();
- active_ = false;
- }
- }
-
-private:
- const std::function<void()> cb_;
- bool active_;
-};
diff --git a/GUI/GUI/GUI/Transcript.cpp b/GUI/GUI/GUI/Transcript.cpp deleted file mode 100644 index 11bab31..0000000 --- a/GUI/GUI/GUI/Transcript.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "Transcript.h"
-
-void Transcript::Append(std::string&& segment) {
- std::scoped_lock l(mu_);
- segments_.push_back(std::move(segment));
-}
-
-void Transcript::Set(std::string&& segment) {
- std::scoped_lock l(mu_);
- segments_.clear();
- segments_.push_back(std::move(segment));
-}
-
-void Transcript::SetPreview(std::string&& segment) {
- std::scoped_lock l(mu_);
- previews_.clear();
- previews_.push_back(std::move(segment));
-}
-
-void Transcript::Clear() {
- std::scoped_lock l(mu_);
- segments_.clear();
- previews_.clear();
-}
-
-std::vector<std::string> Transcript::Get() {
- std::scoped_lock l(mu_);
- return segments_;
-}
-
-std::vector<std::string> Transcript::GetPreview() {
- std::scoped_lock l(mu_);
- return previews_;
-}
-
-void Transcript::SetFinalized(bool is_finalized) {
- // Accessing anything smaller than a word is always atomic.
- is_finalized_ = is_finalized;
-}
-
-bool Transcript::IsFinalized() {
- // Accessing anything smaller than a word is always atomic.
- return is_finalized_;
-}
diff --git a/GUI/GUI/GUI/Transcript.h b/GUI/GUI/GUI/Transcript.h deleted file mode 100644 index 1c18afe..0000000 --- a/GUI/GUI/GUI/Transcript.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once
-
-#include <mutex>
-#include <string>
-#include <vector>
-
-// Simple thread-safe class to share transcription data between layers.
-class Transcript {
-public:
- Transcript() = default;
-
- void Append(std::string&& segment);
- void Set(std::string&& segment);
- void SetPreview(std::string&& segment);
- void Clear();
-
- // Indicate whether the transcript is "finalized", i.e. the transcription
- // engine has committed the entirety of the transcript and will no longer
- // change it.
- void SetFinalized(bool is_finalized);
-
- std::vector<std::string> Get();
- std::vector<std::string> GetPreview();
- bool IsFinalized();
-
-private:
- std::mutex mu_;
- std::vector<std::string> segments_;
- std::vector<std::string> previews_;
- bool is_finalized_{ false };
-};
diff --git a/GUI/GUI/GUI/Util.h b/GUI/GUI/GUI/Util.h deleted file mode 100644 index 594972e..0000000 --- a/GUI/GUI/GUI/Util.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once
-
-#include <filesystem>
-#include <string>
-
-// Wrap the filesystem path in quotes, escaping intermediate quotes with \\.
-inline std::string Quote(const std::filesystem::path& p) {
- std::ostringstream oss;
- oss << std::quoted(p.string());
- return oss.str();
-}
-
-inline std::string Unquote(const std::string& s) {
- std::istringstream iss(s);
-
- std::string result;
- iss >> quoted(result);
-
- return result;
-}
diff --git a/GUI/GUI/GUI/WebCommon.h b/GUI/GUI/GUI/WebCommon.h deleted file mode 100644 index 6e18bb2..0000000 --- a/GUI/GUI/GUI/WebCommon.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once
-
-namespace WebServer {
- enum ContentType {
- HTML,
- JSON,
- };
-};
diff --git a/GUI/GUI/GUI/WebServer.cpp b/GUI/GUI/GUI/WebServer.cpp deleted file mode 100644 index 2b589c6..0000000 --- a/GUI/GUI/GUI/WebServer.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#include "HTTPMapper.h"
-#include "HTTPParser.h"
-#include "ScopeGuard.h"
-#include "WebServer.h"
-
-#include <stdint.h>
-#include <WinSock2.h>
-#include <ws2tcpip.h>
-
-using ::Logging::Log;
-
-namespace WebServer {
- WebServer::WebServer(wxTextCtrl* out, uint16_t port)
- : out_(out), port_(port)
- {
- default_handler_ =
- [](int& status_code, std::string& payload,
- ContentType& type) -> void {
- status_code = 404;
- payload = "404: No route to URI";
- type = HTML;
- };
- }
-
- bool WebServer::RegisterPathHandler(const std::string& method,
- const std::string& path, handler_t&& handler) {
- dispatch_key_t key = GetDispatchKey(method, path);
- if (dispatch_map_.contains(key)) {
- Log(out_, "Failed to register path handler at {} {}: "
- "Handler already exists!\n", method, path);
- return false;
- }
-
- dispatch_map_[key] = std::move(handler);
- return true;
- }
-
- void WebServer::RegisterDefaultHandler(handler_t&& handler) {
- default_handler_ = std::move(handler);
- }
-
- bool WebServer::Run(volatile bool* run) {
- WSADATA wsaData;
- int result = WSAStartup(/*version=*/MAKEWORD(2, 2), &wsaData);
- if (result) {
- Log(out_, "Failed to start winsock: {}\n", result);
- return false;
- }
- ScopeGuard wsa_cleanup([]() { WSACleanup(); });
-
- SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (sock == INVALID_SOCKET) {
- Log(out_, "Failed to create socket: {}\n", WSAGetLastError());
- return false;
- }
- ScopeGuard sock_cleanup([sock]() { closesocket(sock); });
-
- sockaddr_in saddr;
- saddr.sin_family = AF_INET;
- saddr.sin_addr.s_addr = INADDR_ANY;
- saddr.sin_port = htons(port_);
- if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) == SOCKET_ERROR) {
- Log(out_, "Failed to bind to port {}: {}\n", port_, WSAGetLastError());
- return false;
- }
-
- int optval = 1;
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(optval)) == SOCKET_ERROR) {
- Log(out_, "Failed to setsockopt(SO_REUSEADDR): {}", WSAGetLastError());
- return 1;
- }
-
- u_long enable_nonblock = 1;
- if (ioctlsocket(sock, FIONBIO, &enable_nonblock) == SOCKET_ERROR) {
- Log(out_, "Failed to enable non-blocking socket: {}\n", WSAGetLastError());
- return false;
- }
-
- if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
- Log(out_, "Failed to listen on port {}: {}\n", port_, WSAGetLastError());
- return false;
- }
-
- Log(out_, "Server running on port {}\n", port_);
-
- sockaddr_in peer_addr;
- int accept_cnt = 0;
- while (*run) {
- int peer_addr_sz = sizeof(peer_addr);
- SOCKET csock = accept(sock, (sockaddr*)&peer_addr, &peer_addr_sz);
- if (csock == INVALID_SOCKET) {
- int err = WSAGetLastError();
- if (err == WSAEWOULDBLOCK) {
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- continue;
- }
- Log(out_, "Accept failed: {}\n", WSAGetLastError());
- return false;
- }
-
- // Periodically cull dead connections to prevent runaway memory usage.
- ++accept_cnt;
- if (accept_cnt % 10 == 0) {
- std::vector<std::future<void>> alive_conn;
- for (int i = 0; i < connections_.size(); i++) {
- if (connections_[i].valid()) {
- continue;
- }
- alive_conn.push_back(std::move(connections_[i]));
- }
- //Log(out_, "Culled {} dead connections\n", connections_.size() - alive_conn.size());
- connections_ = std::move(alive_conn);
- accept_cnt = 0; // Prevent overflow
- }
-
- wxTextCtrl* out = out_;
- const auto& dispatch_map = dispatch_map_;
- const auto& default_handler = default_handler_;
- connections_.push_back(std::async(std::launch::async,
- [csock, peer_addr, out, run, dispatch_map, default_handler]() -> void {
- ScopeGuard csock_cleanup([csock]() { closesocket(csock); });
- char peer_ip_str[INET_ADDRSTRLEN]{};
- inet_ntop(AF_INET, &peer_addr.sin_addr, peer_ip_str, sizeof(peer_ip_str));
- //Log(out, "Connection get: peer: {}:{}\n", peer_ip_str, ntohs(peer_addr.sin_port));
-
- std::string buf(4096 * 16, 0);
- int cur_bytes_read = 0;
- int sum_bytes_read = 0;
-
- // Drain socket until we see a valid HTTP message.
- while (*run) {
- cur_bytes_read = recv(csock, buf.data() + sum_bytes_read,
- buf.size() - (1 + sum_bytes_read), /*flags=*/0);
- if (cur_bytes_read == SOCKET_ERROR) {
- if (WSAGetLastError() == WSAEWOULDBLOCK) {
- // Client may try to keep the connection open,
- // so see if there's a complete request in the
- // buffer. If so, terminate the recv loop.
- HTTPParser p;
- std::string err;
- if (p.Parse(buf, err)) {
- // In general we should verify that we got a
- // full message, but since we only need to
- // support GET, this is unnecessary.
- cur_bytes_read = 0;
- break;
- }
- std::this_thread::sleep_for(std::chrono::milliseconds(10));
- continue;
- }
- break;
- }
- sum_bytes_read += cur_bytes_read;
- if (cur_bytes_read == 0) {
- break;
- }
- }
- if (cur_bytes_read == SOCKET_ERROR) {
- Log(out, "Failed to read client socket: {}\n", WSAGetLastError());
- return;
- }
- // Edge case: Server was stopped in the middle of serving a request.
- if (!*run) {
- return;
- }
- buf.resize(sum_bytes_read);
-
- // Parse HTTP. Expect this to succeed, since we only exit the loop once the
- // request parses.
- // TODO(yum) this repeats work! The loop already parsed the request.
- HTTPParser p;
- std::string err;
- if (!p.Parse(buf, err)) {
- Log(out, "Failed to parse client request: {}\n", err);
- Log(out, "Offending request:\n{}\n", buf);
- return;
- }
-
- // Find the dispatch handler for the requested method and path.
- dispatch_key_t dispatch_key = GetDispatchKey(p.GetMethod(), p.GetPath());
- auto iter = dispatch_map.find(dispatch_key);
- handler_t handler;
- if (iter == dispatch_map.end()) {
- handler = default_handler;
- } else {
- handler = iter->second;
- }
-
- // Generate a response.
- int status_code;
- std::string payload;
- ContentType type;
- handler(status_code, payload, type);
- std::string response = HTTPMapper().Map(status_code, payload, type);
-
- // Send the response.
- if (send(csock, response.data(), response.size(), /*flags=*/0) == SOCKET_ERROR) {
- Log(out, "Failed to send response to client: {}\n", WSAGetLastError());
- return;
- }
-
- // Implicitly close the connection by exiting scope. We
- // completely ignore keep-alive requests for now. Browsers
- // should handle this well, there are many reasons why
- // keep-alive requests may be ignored, such as transient
- // network failures.
- }));
- }
- return true;
- }
-}
diff --git a/GUI/GUI/GUI/WebServer.h b/GUI/GUI/GUI/WebServer.h deleted file mode 100644 index e476ba9..0000000 --- a/GUI/GUI/GUI/WebServer.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once
-
-#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-#include <stdint.h>
-
-#include <functional>
-#include <future>
-#include <map>
-#include <mutex>
-#include <string>
-#include <vector>
-
-#include "Logging.h"
-#include "WebCommon.h"
-
-namespace WebServer {
- class WebServer {
- public:
- WebServer(wxTextCtrl *out, std::uint16_t port);
-
- typedef std::function<void(
- int& status_code,
- std::string& payload,
- ContentType& type)> handler_t;
-
- bool RegisterPathHandler(const std::string& method,
- const std::string& path, handler_t&& handler);
- void RegisterDefaultHandler(handler_t&& handler);
-
- bool Run(volatile bool* run);
-
- private:
- // Dispatch requests by mapping from (method, path) to handler.
- // Dispatch key is (method, path) in that order.
- typedef std::tuple<std::string, std::string> dispatch_key_t;
- static inline dispatch_key_t GetDispatchKey(const std::string& method, const std::string& path)
- {
- return dispatch_key_t(method, path);
- }
-
- typedef std::map<dispatch_key_t, handler_t> dispatch_map_t;
- dispatch_map_t dispatch_map_;
- handler_t default_handler_;
-
- wxTextCtrl* const out_;
- const uint16_t port_;
-
- std::vector<std::future<void>> connections_;
- };
-}
-
diff --git a/GUI/GUI/GUI/main.cpp b/GUI/GUI/GUI/main.cpp deleted file mode 100644 index d9303f5..0000000 --- a/GUI/GUI/GUI/main.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "App.h"
-
-#include <wx/wxprec.h>
-
-#ifndef WX_PRECOMP
-#include <wx/wx.h>
-#endif
-
-wxIMPLEMENT_APP(MyApp);
-
diff --git a/GUI/GUI/GUI/resource.h b/GUI/GUI/GUI/resource.h deleted file mode 100644 index f10e004..0000000 --- a/GUI/GUI/GUI/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by GUI.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 106 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/GUI/Libraries/.gitignore b/GUI/Libraries/.gitignore deleted file mode 100644 index 26be5d9..0000000 --- a/GUI/Libraries/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Don't check in anything we fetch -wx -rapidyaml -whisper -oatpp diff --git a/GUI/Libraries/fetch.ps1 b/GUI/Libraries/fetch.ps1 deleted file mode 100644 index f558d3f..0000000 --- a/GUI/Libraries/fetch.ps1 +++ /dev/null @@ -1,31 +0,0 @@ -param( - [switch]$overwrite = $False, - [string]$release = "Release" -) - -echo "Overwrite: $overwrite" -echo "Release: $release" - -Set-PSDebug -trace 0 - -$WX_3_2_1_URL = "https://github.com/wxWidgets/wxWidgets/releases/download/v3.2.1/wxWidgets-3.2.1.zip" -$WX_URL = $WX_3_2_1_URL -$WX_FILE = $(Split-Path -Path $WX_URL -Leaf) - -pushd $PSScriptRoot - -# WX -if ((Test-Path wx) -And ($overwrite)) { - rm -Recurse wx -} - -if (-Not (Test-Path wx)) { - mkdir wx - pushd wx > $null - Invoke-WebRequest $WX_URL -OutFile $WX_FILE - Expand-Archive $WX_FILE -DestinationPath . - popd > $null -} - -popd > $null # $PSScriptRoot - diff --git a/GUI/README.md b/GUI/README.md deleted file mode 100644 index 39d3292..0000000 --- a/GUI/README.md +++ /dev/null @@ -1,93 +0,0 @@ -## Build instructions - -0. Install build dependencies: cmake, git, python3, Visual Studio Community - 2022 - 0.0. When installing Visual Studio, make sure `Desktop development with C++` - is selected. - 0.1. Make sure Windows is using Python 3.10.9. From Powershell, the command - `python.exe --version` should show that it's using 3.10.9. Direct link: - https://www.python.org/ftp/python/3.10.9/python-3.10.9-amd64.exe -1. Open Powershell. -2. Make sure you've downloaded submodules: -``` -$ git submodule init -$ git submodule update -``` -3. Execute Libraries/fetch.ps1. This will take 2-3 minutes. - 3.0. If you can't run the script, run `Set-ExecutionPolicyPolicy - Unrestricted` in an admin instance of powershell. Heed the warning, - this is a security risk! Never run code from someone you don't trust - unless you've carefully audited it. -4. Open `Libraries/wx/build/msw/wx_vc17.sln` with Visual Studio 2022. -5. Select every project in the Solution Explorer except for `_custom_build`. -6. Right click, select Properties, go to C/C++, Code Generation, and set - Runtime Library to Multi-threaded (/MT). Make sure this applies to the - configuration x64/Release. Click Apply. -7. Build x64/Release. - 1. The build configuration is in the top. By default it's probably Debug/x64. - 2. To build: ctrl+shift+B - 3. If you saw an error in 7.1, rerun Libraries/fetch.ps1. -8. Open GUI/GUI.sln with Visual Studio 2022. -9. Build x64/Release. -10. Run package.ps1 from powershell. - 10.0. If you're not creating a redistributable release, use this command - instead (it's way faster): `package.ps1 -skip_zip`. - 10.1. When PortableGit creates a window, wait for it to complete, then press - then press enter in Powershell. - 10.2. The first time you run this it'll take a long time since it has to - fetch a few large packages. Subsequent invocations will be much faster - since it won't reacquire anything already downloaded. On my connection, - it took 90 minutes to finish downloading, mostly because Google Drive - downloads are slower than dirt. - -## High level design - -* The GUI is written using wxWidgets. -* Python executes core business logic. With libraries like faster\_whisper - available, this provides a nice balance between flexibility and performance. -* To skirt licensing complexity, we distribute an embedded python - that's hacked up to allow installing packages via pip. We use this - to install packages at runtime (like a net installer), so we don't - actually distribute all our transitive dependencies. This also keeps - the initial package size small. - -## C++ Style - -Follow the Google C++ style guide. This is not absolutely strict but -it will be used to settle arguments. - -https://google.github.io/styleguide/cppguide.html - -This should get you 80% of the way there: - -* When in doubt, use K&R style -* 2 space indents -* Class members `look_like_this_` -* Functions and methods `LookLikeThis()` -* Local variables `look_like_this` -* Global constexprs `kLookLikeThis` - -Consistent style reduces cognitive burden. Follow it for the benefit of -your peers. - -## How the embedded python environment works - -I'm distributing an embeddable version of python from the official -python website. It's modified so that packages are installed under -Python/Lib/site-packages, instead of the usual filesystem paths. - -To bootstrap pip & fetch the dependencies needed: - -``` -cd TaSTT -./Resources/Python/python.exe Resources/Python/get-pip.py -./Resources/Python/python.exe -m pip install $YOUR\_PACKAGE\_HERE -``` - -The `future` package imports extra modules, and the embedded python -search path needs to be told where that is. For that reason, we also -redistribute the `future` package in source format. - -This is logically what the GUI does internally when it creates the -python environment. - diff --git a/GUI/package.ps1 b/GUI/package.ps1 deleted file mode 100644 index 697f1a2..0000000 --- a/GUI/package.ps1 +++ /dev/null @@ -1,150 +0,0 @@ -param(
- [switch]$skip_zip = $false,
- [string]$release = "Release",
- [string]$install_pip = $true
-)
-
-echo "Skip zip: $skip_zip"
-echo "Release: $release"
-echo "Install pip: $install_pip"
-
-$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
-
-$install_dir = "TaSTT"
-
-if (Test-Path $install_dir) {
- rm -Recurse -Force $install_dir
-}
-
-$py_dir = "Python"
-
-if (Test-Path $py_dir) {
- rm -Recurse $py_dir
-}
-if (-Not (Test-Path $py_dir)) {
- echo "Fetching python"
-
- $PYTHON_3_10_9_URL = "https://www.python.org/ftp/python/3.10.9/python-3.10.9-embed-amd64.zip"
- $PYTHON_URL = $PYTHON_3_10_9_URL
- $PYTHON_FILE = $(Split-Path -Path $PYTHON_URL -Leaf)
-
- if (-Not (Test-Path $PYTHON_FILE)) {
- Invoke-WebRequest $PYTHON_URL -OutFile $PYTHON_FILE
- }
-
- mkdir Python
- Expand-Archive $PYTHON_FILE -DestinationPath Python
-
- echo "../Scripts" >> Python/python310._pth
- echo "import site" >> Python/python310._pth
-}
-
-$pip_path = "$py_dir/get-pip.py"
-
-if (Test-Path $pip_path) {
- rm -Force $pip_path
-}
-
-if (-Not (Test-Path $pip_path)) {
- echo "Fetching pip"
-
- $PIP_URL = "https://bootstrap.pypa.io/get-pip.py"
- $PIP_FILE = $(Split-Path -Path $PIP_URL -Leaf)
-
- if (-Not (Test-Path $PIP_FILE)) {
- Invoke-WebRequest $PIP_URL -OutFile $PIP_FILE
- }
-
- mv $PIP_FILE $pip_path
-}
-
-if ($install_pip) {
- ./Python/python.exe Python/get-pip.py
-
- echo "Installing future"
- echo "Assuming host has python 3.10.9 installed" # TODO test for this
- python -m pip install future==0.18.2 --target Python/Lib/site-packages
-}
-
-$git_dir = "PortableGit"
-
-if (-Not (Test-Path $git_dir)) {
- echo "Fetching PortableGit"
-
- # When it's time to update this, get the latest version from here:
- # https://git-scm.com/download/win
- $GIT_2_39_0_URL = "https://github.com/git-for-windows/git/releases/download/v2.39.0.windows.2/PortableGit-2.39.0.2-64-bit.7z.exe"
- $GIT_URL = $GIT_2_39_0_URL
- $GIT_FILE = $(Split-Path -Path $GIT_URL -Leaf)
-
- if (-Not (Test-Path $GIT_FILE)) {
- Invoke-WebRequest $GIT_URL -OutFile $GIT_FILE
- }
- & "./$GIT_FILE"
-
- Read-Host -Prompt "Press enter once PortableGit is installed at $pwd\PortableGit"
-}
-
-if (-Not (Test-Path UwwwuPP)) {
- git clone https://github.com/yum-food/UwwwuPP
- pushd UwwwuPP > $null
- git submodule update --init --recursive
-
- mkdir build
- pushd build > $null
-
- cmake.exe ..
- cmake.exe --build .
-
- popd > $null
- popd > $null
-}
-
-if (-Not (Test-Path Profanity)) {
- mkdir Profanity
- pushd Profanity > $null
-
- $repo = "List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words"
- git clone https://github.com/LDNOOBW/$repo
-
- mkdir Profanity
- cp $repo/LICENSE Profanity/
- cp $repo/en Profanity/
-
- echo "Source: https://github.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words" > Profanity/AUTHOR
-
- popd > $null
-}
-
-if (-Not (Test-Path "silero-vad")) {
- git clone "https://github.com/snakers4/silero-vad"
-}
-
-mkdir $install_dir > $null
-mkdir $install_dir/Resources > $null
-cp -Recurse ../Animations TaSTT/Resources/Animations
-mkdir TaSTT/Resources/Fonts
-cp -Recurse ../Fonts/Bitmaps TaSTT/Resources/Fonts/Bitmaps
-cp -Recurse ../Fonts/Emotes TaSTT/Resources/Fonts/Emotes
-cp -Recurse Python TaSTT/Resources/Python
-cp -Recurse PortableGit TaSTT/Resources/PortableGit
-cp -Recurse ../Scripts TaSTT/Resources/Scripts
-mkdir TaSTT/Resources/Images
-cp ../Images/logo*.png TaSTT/Resources/Images/
-cp -Recurse ../Shaders TaSTT/Resources/Shaders
-cp -Recurse ../Sounds TaSTT/Resources/Sounds
-cp -Recurse ../UnityAssets TaSTT/Resources/UnityAssets
-cp -Recurse ../BrowserSource TaSTT/Resources/BrowserSource
-cp GUI/x64/$release/GUI.exe TaSTT/TaSTT.exe
-mkdir TaSTT/Resources/Models
-cp "silero-vad/files/silero_vad.onnx" TaSTT/Resources/Models/
-cp "silero-vad/LICENSE" TaSTT/Resources/Models/silero_vad.onnx.LICENSE
-mkdir TaSTT/Resources/Uwu
-cp UwwwuPP/build/Src/Debug/Uwwwu.exe TaSTT/Resources/Uwu/
-cp UwwwuPP/LICENSE TaSTT/Resources/Uwu/
-cp -r Profanity/Profanity TaSTT/Resources/Profanity
-
-if (-Not $skip_zip) {
- Compress-Archive -Path "$install_dir" -DestinationPath "$install_dir.zip" -Force
-}
-
|
