diff options
Diffstat (limited to 'GUI')
| -rw-r--r-- | GUI/GUI/GUI/Config.cpp | 2 | ||||
| -rw-r--r-- | GUI/GUI/GUI/Frame.cpp | 1 | ||||
| -rw-r--r-- | GUI/GUI/GUI/Logging.cpp | 56 | ||||
| -rw-r--r-- | GUI/GUI/GUI/Logging.h | 53 | ||||
| -rw-r--r-- | GUI/GUI/GUI/PythonWrapper.cpp | 117 | ||||
| -rw-r--r-- | GUI/GUI/GUI/PythonWrapper.h | 2 | ||||
| -rw-r--r-- | GUI/GUI/GUI/WhisperCPP.cpp | 159 | ||||
| -rw-r--r-- | GUI/GUI/GUI/WhisperCPP.h | 22 | ||||
| -rw-r--r-- | GUI/Libraries/.gitignore | 2 | ||||
| -rw-r--r-- | GUI/Libraries/fetch.ps1 | 31 | ||||
| -rw-r--r-- | GUI/README.md | 2 |
11 files changed, 251 insertions, 196 deletions
diff --git a/GUI/GUI/GUI/Config.cpp b/GUI/GUI/GUI/Config.cpp index 50f0dca..a877d4a 100644 --- a/GUI/GUI/GUI/Config.cpp +++ b/GUI/GUI/GUI/Config.cpp @@ -78,7 +78,7 @@ AppConfig::AppConfig() use_cpu(false),
use_builtin(false),
- chars_per_sync(20),
+ chars_per_sync(8),
bytes_per_char(1),
rows(4),
cols(48),
diff --git a/GUI/GUI/GUI/Frame.cpp b/GUI/GUI/GUI/Frame.cpp index 5332490..0bac3aa 100644 --- a/GUI/GUI/GUI/Frame.cpp +++ b/GUI/GUI/GUI/Frame.cpp @@ -1991,6 +1991,7 @@ void Frame::OnWhisperStop(wxCommandEvent& event) { void Frame::OnAppDrain(wxTimerEvent& event) {
DrainAsyncOutput(py_app_, transcribe_out_);
DrainAsyncOutput(env_proc_, transcribe_out_);
+ Logging::kThreadLogger.Drain();
}
void Frame::LoadAndSetIcons() {
diff --git a/GUI/GUI/GUI/Logging.cpp b/GUI/GUI/GUI/Logging.cpp index 78594b4..f799e31 100644 --- a/GUI/GUI/GUI/Logging.cpp +++ b/GUI/GUI/GUI/Logging.cpp @@ -1,8 +1,48 @@ #include "Logging.h"
+#include <wx/wxprec.h>
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+#include <wx/process.h>
+#include <wx/txtstrm.h>
+
+#include <fstream>
#include <regex>
#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_);
+ std::ofstream log_ofs("Resources/log.txt", std::ios_base::app);
+ for (const auto& [frame, messages] : messages_) {
+ for (const auto& message : messages) {
+ frame->AppendText(message);
+ log_ofs << message;
+ }
+ }
+ log_ofs.close();
+ messages_.clear();
+}
+
std::string Logging::HidePII(const std::string&& str,
const std::string& replacement) {
try {
@@ -16,3 +56,19 @@ std::string Logging::HidePII(const std::string&& str, 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());
+ }
+
+ while (proc->IsErrorAvailable()) {
+ wxTextInputStream iss(*(proc->GetErrorStream()));
+ Log(frame, " {}\n", iss.ReadLine());
+ }
+}
diff --git a/GUI/GUI/GUI/Logging.h b/GUI/GUI/GUI/Logging.h index 99462c0..c85a376 100644 --- a/GUI/GUI/GUI/Logging.h +++ b/GUI/GUI/GUI/Logging.h @@ -16,30 +16,23 @@ #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 = "*****");
-#if 0
- class Log {
+ class ThreadLogger {
public:
- static Log& Get() {
- static Log l;
- return l;
- }
-
- bool Write(const std::string& text);
+ ThreadLogger();
+ void Append(wxTextCtrl* frame, const std::string&& message);
+ void Drain();
private:
- Log() {}
-
- bool Open(const std::string& path);
-
- int fd_;
+ std::mutex mu_;
+ std::unordered_map<wxTextCtrl*, std::list<std::string>> messages_;
};
-#endif
- // 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 = "*****");
+ extern ThreadLogger kThreadLogger;
// Provides a simple Python format()-like interface to wxTextCtrl.
// Ex: Log(my_textctrl_, "{}\n", "Hello, world!");
@@ -47,28 +40,10 @@ namespace Logging { 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));
- frame->AppendText(masked);
- // Limit log to 10 MB to avoid runaway memory usage.
- const int max_frame_len_bytes = 10 * 1000 * 1000;
- if (frame->GetLastPosition() > max_frame_len_bytes) {
- frame->Remove(0, frame->GetLastPosition() - max_frame_len_bytes);
- }
- }
-
- inline void DrainAsyncOutput(wxProcess* proc, wxTextCtrl* frame) {
- if (!proc) {
- return;
- }
- while (proc->IsInputAvailable()) {
- wxTextInputStream iss(*(proc->GetInputStream()));
- Log(frame, " {}\n", iss.ReadLine());
- }
-
- while (proc->IsErrorAvailable()) {
- wxTextInputStream iss(*(proc->GetErrorStream()));
- Log(frame, " {}\n", iss.ReadLine());
- }
+ kThreadLogger.Append(frame, std::move(masked));
}
+
+ void DrainAsyncOutput(wxProcess* proc, wxTextCtrl* frame);
}
diff --git a/GUI/GUI/GUI/PythonWrapper.cpp b/GUI/GUI/GUI/PythonWrapper.cpp index bcb7b1d..c90520d 100644 --- a/GUI/GUI/GUI/PythonWrapper.cpp +++ b/GUI/GUI/GUI/PythonWrapper.cpp @@ -1,10 +1,12 @@ #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> @@ -60,58 +62,95 @@ bool PythonWrapper::InvokeCommandWithArgs( cmd_oss << " " << arg; } - wxString path; - if (!wxGetEnv("PATH", &path)) { - *py_stderr = "Failed to get PATH"; - return false; - } - if (!wxSetEnv("PATH", path + ";Resources/PortableGit/bin")) { - *py_stderr = "Failed to append to PATH"; + HANDLE stdout_read{}; + HANDLE stdout_write{}; + SECURITY_ATTRIBUTES sec_attr{}; + sec_attr.nLength = sizeof(sec_attr); + sec_attr.bInheritHandle = TRUE; + if (!CreatePipe(&stdout_read, &stdout_write, &sec_attr, 0)) { + if (py_stderr) { + std::ostringstream err_oss; + err_oss << "Error while executing python command \"" << cmd_oss.str() + << "\": Failed to create stdout pipe" << std::endl; + *py_stderr = err_oss.str(); + } return false; } + ScopeGuard stdout_cleanup([&]() { + CloseHandle(stdout_read); + CloseHandle(stdout_write); + }); - wxArrayString cmd_stdout; - wxArrayString cmd_stderr; - long result = wxExecute(cmd_oss.str(), cmd_stdout, cmd_stderr, /*flags=*/0); - std::ostringstream cmd_stdout_oss; - for (const auto& line : cmd_stdout) { - if (!cmd_stdout_oss.str().empty()) { - cmd_stdout_oss << std::endl; - } - cmd_stdout_oss << line; - } - std::ostringstream cmd_stderr_oss; - for (const auto& line : cmd_stderr) { - if (!cmd_stderr_oss.str().empty()) { - cmd_stderr_oss << std::endl; - } - cmd_stderr_oss << line; - } - if (result == -1) { - std::ostringstream err_oss; - err_oss << "Error while executing python command \"" << cmd_oss.str() << "\": Failed to launch process" << std::endl; - err_oss << cmd_stdout_oss.str() << std::endl; - err_oss << cmd_stderr_oss.str() << std::endl; + HANDLE stderr_read{}; + HANDLE stderr_write{}; + if (!CreatePipe(&stderr_read, &stderr_write, &sec_attr, 0)) { if (py_stderr) { + std::ostringstream err_oss; + err_oss << "Error while executing python command \"" << cmd_oss.str() + << "\": Failed to create stderr pipe" << std::endl; *py_stderr = err_oss.str(); } return false; - } else if (result) { + } + ScopeGuard stderr_cleanup([&]() { + CloseHandle(stderr_read); + CloseHandle(stderr_write); + }); + + STARTUPINFOA si{}; + si.cb = sizeof(si); + si.hStdOutput = stdout_write; + si.hStdError = stderr_write; + PROCESS_INFORMATION pi{}; + std::string path = "Resources/PortableGit/bin"; + std::string env = "PATH=" + path; + //std::string env; + + //std::string tmp_cmd = "Get-ChildItem"; + + std::string cmd_str = cmd_oss.str(); + if (!CreateProcessA(NULL, // application name + cmd_str.data(), + //tmp_cmd.data(), + NULL, // process attributes + NULL, // thread attributes + FALSE, // whether to inherit parent's handles + 0, // creation flags + env.data(), + NULL, // current directory (use parent's) + &si, + &pi)) { if (py_stderr) { std::ostringstream err_oss; - err_oss << "Error while executing python command \"" << cmd_oss.str() << - "\"" << std::endl << - "Process returned " << result << ": " << std::endl << - cmd_stdout_oss.str() << std::endl << - cmd_stderr_oss.str() << std::endl; + err_oss << "Error while executing python command \"" << cmd_oss.str() + << "\": Failed to launch process" << std::endl; *py_stderr = err_oss.str(); } return false; } + ScopeGuard pi_cleanup([&] { + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + }); + + std::ostringstream stdout_oss, stderr_oss; + std::vector<char> buf(4096, 0); + DWORD bytes_read = 0; + while (ReadFile(si.hStdOutput, buf.data(), buf.size(), &bytes_read, NULL) && bytes_read > 0) { + stdout_oss << std::string(buf.data(), bytes_read); + } + bytes_read = 0; + while (ReadFile(si.hStdError, buf.data(), buf.size(), &bytes_read, NULL) && bytes_read > 0) { + stderr_oss << std::string(buf.data(), bytes_read); + } + + WaitForSingleObject(pi.hProcess, INFINITE); + + // TODO(yum) retrieve exit code - *py_stdout = cmd_stdout_oss.str(); + *py_stdout = stdout_oss.str(); if (py_stderr) { - *py_stderr = cmd_stderr_oss.str(); + *py_stderr = stderr_oss.str(); } return true; } @@ -165,7 +204,7 @@ std::string PythonWrapper::DumpMics() { return py_stdout; } -bool PythonWrapper::InstallPip(std::string* out) { +bool PythonWrapper::InstallPip(std::string* out, std::string* err) { std::string result; std::filesystem::path pip_flag = "Resources/Python/.pip_installed"; @@ -174,7 +213,7 @@ bool PythonWrapper::InstallPip(std::string* out) { } std::string pip_path = "Resources/Python/get-pip.py"; - if (!InvokeWithArgs({ pip_path }, out)) { + if (!InvokeWithArgs({ pip_path }, out, err)) { return false; } diff --git a/GUI/GUI/GUI/PythonWrapper.h b/GUI/GUI/GUI/PythonWrapper.h index 05de538..3433b0f 100644 --- a/GUI/GUI/GUI/PythonWrapper.h +++ b/GUI/GUI/GUI/PythonWrapper.h @@ -47,7 +47,7 @@ namespace PythonWrapper std::string DumpMics(); // Execute get-pip.py. - bool InstallPip(std::string* out); + bool InstallPip(std::string* out, std::string* err = nullptr); // TODO(yum) both StartApp and GenerateAnimator should be // parameterized with config files instead of these ever-growing lists of diff --git a/GUI/GUI/GUI/WhisperCPP.cpp b/GUI/GUI/GUI/WhisperCPP.cpp index 809415e..362bad0 100644 --- a/GUI/GUI/GUI/WhisperCPP.cpp +++ b/GUI/GUI/GUI/WhisperCPP.cpp @@ -14,6 +14,7 @@ #include <codecvt>
#include <cwchar>
#include <fstream>
+#include <future>
#include <locale>
#include <string>
#include <vector>
@@ -60,9 +61,11 @@ namespace { };
WhisperCPP::WhisperCPP(wxTextCtrl* out)
- : out_(out), f_(nullptr), did_init_(false), proc_(nullptr), run_(false)
+ : out_(out), f_(nullptr), did_init_(false), proc_(), run_(false)
{
- Log(out_, "Setting concurrency to 2: {}\n", wxThread::SetConcurrency(2));
+ auto p = std::promise<void>();
+ proc_ = p.get_future();
+ p.set_value();
}
WhisperCPP::~WhisperCPP() {
@@ -135,32 +138,26 @@ bool WhisperCPP::OpenMic(const int idx, Whisper::iAudioCapture*& stream) { return true;
}
-bool WhisperCPP::InstallDependencies(wxProcess*& proc) {
+bool WhisperCPP::InstallDependencies() {
std::filesystem::path flag_file = "Resources/.whisper_deps_installed";
flag_file = flag_file.lexically_normal();
if (std::filesystem::exists(flag_file)) {
- proc = nullptr;
return true;
}
- auto cb = [&](wxProcess* proc, int ret) -> void {
- Log(out_, "Dependency installation exited with code {}\n", ret);
- if (ret == 0) {
- Log(out_, "Dependency installation finished\n");
- }
- DrainAsyncOutput(proc, out_);
- return;
- };
-
- proc = PythonWrapper::InvokeAsyncWithArgs({
+ std::string py_stdout, py_stderr;
+ bool ret = PythonWrapper::InvokeWithArgs({
"-u", // Unbuffered output
"-m pip",
"install",
"-r Resources/Scripts/whisper_requirements.txt",
- }, std::move(cb));
- if (!proc) {
- Log(out_, "Failed to launch installation thread!\n");
+ }, &py_stdout, &py_stderr);
+
+ Log(out_, py_stdout);
+ Log(out_, py_stderr);
+ if (!ret) {
+ Log(out_, "Failed to install dependencies!\n");
return false;
}
@@ -172,30 +169,25 @@ bool WhisperCPP::InstallDependencies(wxProcess*& proc) { }
bool WhisperCPP::DownloadModel(const std::string& model_name,
- const std::filesystem::path& fs_path, wxProcess*& proc) {
- auto cb = [&](wxProcess* proc, int ret) -> void {
- Log(out_, "Model download completed with code {}\n", ret);
- if (ret == 0) {
- Log(out_, "Model download finished\n");
- }
- DrainAsyncOutput(proc, out_);
- return;
- };
-
+ const std::filesystem::path& fs_path) {
std::ostringstream url_oss;
url_oss << "https://huggingface.co/datasets/ggerganov/whisper.cpp/resolve/main/";
url_oss << model_name;
Log(out_, "Model will be saved to {}\n", fs_path.lexically_normal().string());
- proc = PythonWrapper::InvokeAsyncWithArgs({
+ std::string py_stdout, py_stderr;
+ bool ret = PythonWrapper::InvokeWithArgs({
"-u", // Unbuffered output
"-m wget",
url_oss.str(),
"-o", fs_path.string(),
- }, std::move(cb));
- if (!proc) {
- Log(out_, "Failed to launch download thread!\n");
+ }, &py_stdout, &py_stderr);
+ Log(out_, py_stdout);
+ Log(out_, py_stderr);
+ if (!ret) {
+ Log(out_, "Failed to download model!\n");
return false;
}
+
return true;
}
@@ -229,29 +221,13 @@ bool WhisperCPP::CreateContext(Whisper::iModel* model, Whisper::iContext*& conte return true;
}
-WhisperCPP::AppThread::AppThread(
- const std::function<void(AppThread* thd)>&& cb,
- WhisperCPP* app)
- : wxThread(wxTHREAD_DETACHED), cb_(cb), app_(app)
-{}
-WhisperCPP::AppThread::~AppThread()
-{
- Log(app_->out_, "Destroy transcription thread\n");
- app_->proc_ = nullptr;
-}
-
-void* WhisperCPP::AppThread::Entry() {
- cb_(this);
- return nullptr;
-}
-
void WhisperCPP::Start(const AppConfig& c) {
- if (proc_) {
+ if (!proc_.valid()) {
Log(out_, "Transcription engine already running\n");
return;
}
- proc_ = new AppThread([&](AppThread* thd) {
+ proc_ = std::async(std::launch::async, [&]() -> void {
Log(out_, "Transcription thread top\n");
run_ = true;
@@ -261,28 +237,17 @@ void WhisperCPP::Start(const AppConfig& c) { }
ScopeGuard mic_stream_cleanup([mic_stream]() { mic_stream->Release(); });
- {
- std::string output;
- Log(out_, "Installing pip\n");
- if (!PythonWrapper::InstallPip(&output)) {
- Log(out_, "Failed to install pip: {}\n", output);
- }
+ std::string pip_out, pip_err;
+ Log(out_, "Installing pip\n");
+ if (!PythonWrapper::InstallPip(&pip_out, &pip_err)) {
+ Log(out_, "Failed to install pip: {}\n", pip_err);
+ return;
}
-
- {
- Log(out_, "Installing Python dependencies\n");
- wxProcess* proc = nullptr;
- if (!InstallDependencies(proc)) {
- return;
- }
- while (proc && proc->Exists(proc->GetPid())) {
- if (!run_ || thd->TestDestroy()) {
- proc->Kill(proc->GetPid(), wxSIGKILL);
- return;
- }
- wxThread::Sleep(100);
- }
+ Log(out_, "Installing Python dependencies\n");
+ if (!InstallDependencies()) {
+ return;
}
+#if 1
std::filesystem::path model_path = "Resources/Models";
model_path /= c.whisper_model;
@@ -291,19 +256,9 @@ void WhisperCPP::Start(const AppConfig& c) { }
else {
Log(out_, "Downloading model {}\n", c.whisper_model);
- wxProcess* proc = nullptr;
- model_path = model_path.lexically_normal();
- if (!DownloadModel(c.whisper_model, model_path, proc)) {
+ if (!DownloadModel(c.whisper_model, model_path)) {
return;
}
- while (proc->Exists(proc->GetPid())) {
- if (!run_ || thd->TestDestroy()) {
- proc->Kill(proc->GetPid(), wxSIGKILL);
- std::filesystem::remove(model_path);
- return;
- }
- wxThread::Sleep(100);
- }
}
Whisper::iModel* model;
@@ -349,22 +304,25 @@ void WhisperCPP::Start(const AppConfig& c) { bool is_metadata = false;
for (int j = 0; j < seg.countTokens; j++) {
const sToken& tok = tokens[seg.firstToken + j];
- if (tok.text[0] == '[') {
- continue;
- }
- if (tok.text[0] == ' ' && (
- tok.text[1] == '[' ||
- tok.text[1] == '(')) {
- if (tok.text[strlen(tok.text) - 1] == ']') {
+ std::string_view tok_str(tok.text);
+ if (tok_str.starts_with("[") ||
+ tok_str.starts_with(" [") ||
+ tok_str.starts_with(" (")) {
+ if (tok_str.ends_with("]") ||
+ tok_str.ends_with(")")) {
continue;
}
is_metadata = true;
continue;
}
- if (is_metadata && (
- tok.text[strlen(tok.text) - 1] == ']' ||
- tok.text[strlen(tok.text) - 1] == ')')) {
- is_metadata = false;
+ if (is_metadata) {
+ if (tok_str.ends_with("]") ||
+ tok_str.ends_with(")")) {
+ is_metadata = false;
+ }
+ continue;
+ }
+ if (tok_str.ends_with("BLANK_AUDIO")) {
continue;
}
Log(out, "{}", tok.text);
@@ -379,9 +337,10 @@ void WhisperCPP::Start(const AppConfig& c) { wparams.new_segment_callback_user_data = out_;
sCaptureCallbacks callbacks{};
+
callbacks.shouldCancel = [](void* pv) noexcept -> HRESULT __stdcall {
WhisperCPP* app = static_cast<WhisperCPP*>(pv);
- if (app->proc_->TestDestroy() || !app->run_) {
+ if (!app->run_) {
Log(app->out_, "Exit transcription loop\n");
return S_FALSE;
}
@@ -391,7 +350,6 @@ void WhisperCPP::Start(const AppConfig& c) { if (++i % 20 == 0) {
Log(app->out_, "Spin {}\n", i);
}
- wxThread::Sleep(10);
return S_OK;
};
callbacks.pv = this;
@@ -402,11 +360,18 @@ void WhisperCPP::Start(const AppConfig& c) { Log(out_, "Capture failed: {}\n", hresultToString(err));
return;
}
+#else
+ while (run_) {
+ static int i = 0;
+ if (++i % 100 == 0) {
+ Log(out_, "Spin {}\n", i);
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+#endif
Log(out_, "Exit transcription engine\n");
- }, this);
-
- proc_->Run();
+ });
Log(out_, "Success!\n");
return;
@@ -415,6 +380,8 @@ void WhisperCPP::Start(const AppConfig& c) { void WhisperCPP::Stop() {
Log(out_, "Stopping transcription engine...\n");
run_ = false;
+ proc_.wait();
+ Log(out_, "Done!\n");
}
bool WhisperCPP::GetMicsImpl(std::vector<sCaptureDevice>& mics) {
diff --git a/GUI/GUI/GUI/WhisperCPP.h b/GUI/GUI/GUI/WhisperCPP.h index 20b0106..ed934be 100644 --- a/GUI/GUI/GUI/WhisperCPP.h +++ b/GUI/GUI/GUI/WhisperCPP.h @@ -2,8 +2,6 @@ #include <wx/filepicker.h>
#include <wx/wxprec.h>
-#include <wx/process.h>
-#include <wx/thread.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
@@ -19,6 +17,7 @@ #include <filesystem>
#include <functional>
+#include <future>
#include <string>
#include <vector>
@@ -30,9 +29,9 @@ public: bool Init();
bool GetMics(std::vector<std::string>& mics);
bool OpenMic(const int idx, Whisper::iAudioCapture*& stream);
- bool InstallDependencies(wxProcess*& proc);
+ bool InstallDependencies();
bool DownloadModel(const std::string& model_name,
- const std::filesystem::path& fs_path, wxProcess*& proc);
+ const std::filesystem::path& fs_path);
bool LoadModel(const std::string& path, Whisper::iModel*& model);
bool CreateContext(Whisper::iModel* model, Whisper::iContext*& context);
@@ -42,22 +41,9 @@ public: private:
bool GetMicsImpl(std::vector<Whisper::sCaptureDevice>& mics);
- class AppThread : public wxThread {
- public:
- AppThread(const std::function<void(AppThread* thd)>&& cb, WhisperCPP* app);
-
- virtual ~AppThread();
-
- virtual void* Entry() wxOVERRIDE;
-
- private:
- const std::function<void(AppThread* thd)> cb_;
- WhisperCPP* app_;
- };
-
wxTextCtrl* out_;
Whisper::iMediaFoundation* f_;
bool did_init_;
- AppThread* volatile proc_;
+ std::future<void> proc_;
volatile bool run_;
};
diff --git a/GUI/Libraries/.gitignore b/GUI/Libraries/.gitignore index 0e14a69..26be5d9 100644 --- a/GUI/Libraries/.gitignore +++ b/GUI/Libraries/.gitignore @@ -2,4 +2,4 @@ wx rapidyaml whisper - +oatpp diff --git a/GUI/Libraries/fetch.ps1 b/GUI/Libraries/fetch.ps1 index f13bad5..218d48b 100644 --- a/GUI/Libraries/fetch.ps1 +++ b/GUI/Libraries/fetch.ps1 @@ -12,6 +12,15 @@ $WHISPER_1_7_0_URL = "https://github.com/Const-me/Whisper/releases/download/1.7. $WHISPER_URL = $WHISPER_1_7_0_URL $WHISPER_FILE = $(Split-Path -Path $WHISPER_URL -Leaf) +$OATPP_1_3_0_URL = "https://github.com/oatpp/oatpp/archive/refs/tags/1.3.0.zip" +$OATPP_URL = $OATPP_1_3_0_URL +$OATPP_FILE = $(Split-Path -Path $OATPP_URL -Leaf) +$OATPP_VER = $OATPP_FILE -replace '\.[a-z\.]*$' +$OATPP_DIR = "oatpp-$OATPP_VER" + +$NPROC = $(Get-CimInstance Win32_Processor).NumberOfCores +echo "nproc: $NPROC" + pushd $PSScriptRoot # WX @@ -61,6 +70,28 @@ if (-Not (Test-Path whisper)) { popd > $null } +if ((Test-Path oatpp) -And ($overwrite)) { + rm -Recurse oatpp +} + +if (-Not (Test-Path oatpp)) { + mkdir oatpp + pushd oatpp > $null + Invoke-WebRequest $OATPP_URL -OutFile $OATPP_FILE + Expand-Archive $OATPP_FILE -DestinationPath . + if (Test-Path ../../GUI/GUI/oatpp/) { + rm -Recurse ../../GUI/GUI/oatpp/ + } + mkdir ../../GUI/GUI/oatpp/ + pushd $OATPP_DIR > $null + mkdir build + pushd build > $null + cmake.exe .. -DCMAKE_BUILD_TYPE=Release -DOATPP_BUILD_TESTS=OFF + cmake.exe --build . -j $NPROC --config Release + popd > $null + popd > $null +} + popd > $null # rapidyaml popd > $null # $PSScriptRoot diff --git a/GUI/README.md b/GUI/README.md index d2fa999..ea28124 100644 --- a/GUI/README.md +++ b/GUI/README.md @@ -1,6 +1,6 @@ ## Build instructions -0. Install build dependencies: git, python3, Visual Studio 2022 +0. Install build dependencies: cmake, git, python3, Visual Studio 2022 1. Open Powershell. 2. Make sure you've downloaded submodules: ``` |
