From fa1f619fcaaf7d40670d11f492cd0156a85bcf03 Mon Sep 17 00:00:00 2001 From: yum Date: Thu, 23 Feb 2023 15:28:18 -0800 Subject: Wire up browser source Browser source can be started and stopped via the UI. It still serves a hello world json blob. Observing occasional crashes when stopping the C++ transcription engine. --- GUI/GUI/GUI/BrowserSource.cpp | 12 +++++++--- GUI/GUI/GUI/BrowserSource.h | 12 ++++++++-- GUI/GUI/GUI/Config.cpp | 2 +- GUI/GUI/GUI/Frame.cpp | 51 +++++++++++++++++++++++++++++++++---------- GUI/GUI/GUI/Frame.h | 4 +++- GUI/GUI/GUI/WhisperCPP.cpp | 15 ++++--------- 6 files changed, 67 insertions(+), 29 deletions(-) (limited to 'GUI') diff --git a/GUI/GUI/GUI/BrowserSource.cpp b/GUI/GUI/GUI/BrowserSource.cpp index 030b982..0b4ad31 100644 --- a/GUI/GUI/GUI/BrowserSource.cpp +++ b/GUI/GUI/GUI/BrowserSource.cpp @@ -1,15 +1,21 @@ #include "BrowserSource.h" #include "Logging.h" +#include "ScopeGuard.h" #include "oatpp/network/Server.hpp" +using ::Logging::Log; + BrowserSource::BrowserSource(uint16_t port, wxTextCtrl *out) : port_(port), out_(out) {} void BrowserSource::Run(volatile bool* run) { - AppComponent components; + oatpp::base::Environment::init(); + ScopeGuard oatpp_env_cleanup([]() { oatpp::base::Environment::destroy(); }); + + AppComponent components(port_); OATPP_COMPONENT(std::shared_ptr, router); router->addController(std::make_shared()); @@ -20,8 +26,8 @@ void BrowserSource::Run(volatile bool* run) oatpp::network::Server server(connectionProvider, connectionHandler); - OATPP_LOGI("BrowserSource", "Server running on port %s", - connectionProvider->getProperty("port").getData()); + Log(out_, "Server running on port {}\n", + static_cast(connectionProvider->getProperty("port").getData())); server.run(std::function([run]() { return *run == true; })); } diff --git a/GUI/GUI/GUI/BrowserSource.h b/GUI/GUI/GUI/BrowserSource.h index 5b75c21..37d45a7 100644 --- a/GUI/GUI/GUI/BrowserSource.h +++ b/GUI/GUI/GUI/BrowserSource.h @@ -52,9 +52,14 @@ public: class AppComponent { public: - // TODO(yum) parameterize port + AppComponent(uint16_t port) : port_(port) {} + + // TODO(yum) make port configurable. oatpp examples show how to use a port + // that's available at boot time. Plumbing this with port_ or port causes + // oatpp to use a different port every time, which I think is caused by port_ + // being uninitialized. OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionProvider)([] { - return oatpp::network::tcp::server::ConnectionProvider::createShared({ "0.0.0.0", 8000, oatpp::network::Address::IP_4 }); + return oatpp::network::tcp::server::ConnectionProvider::createShared({ "0.0.0.0", 9517, oatpp::network::Address::IP_4 }); }()); OATPP_CREATE_COMPONENT(std::shared_ptr, httpRouter)([] { @@ -69,6 +74,9 @@ public: OATPP_CREATE_COMPONENT(std::shared_ptr, apiObjectMapper)([] { return oatpp::parser::json::mapping::ObjectMapper::createShared(); }()); + +private: + const uint16_t port_; }; class BrowserSource diff --git a/GUI/GUI/GUI/Config.cpp b/GUI/GUI/GUI/Config.cpp index bcc7375..3e09a2e 100644 --- a/GUI/GUI/GUI/Config.cpp +++ b/GUI/GUI/GUI/Config.cpp @@ -92,7 +92,7 @@ AppConfig::AppConfig() whisper_model("ggml-base.en.bin"), whisper_mic(0), - browser_src_port(9010), + browser_src_port(9517), whisper_enable_builtin(false), whisper_enable_custom(true), whisper_enable_browser_src(false) diff --git a/GUI/GUI/GUI/Frame.cpp b/GUI/GUI/GUI/Frame.cpp index ce3d832..ec7de2e 100644 --- a/GUI/GUI/GUI/Frame.cpp +++ b/GUI/GUI/GUI/Frame.cpp @@ -952,10 +952,12 @@ Frame::Frame() "but are far more accurate."); whisper_window_duration_ = whisper_window_duration; + // TODO(yum) make this mutable once we figure out how to + // get oatpp to accept a runtime src port. auto* whisper_browser_src_port = new wxTextCtrl( whisper_config_panel_pairs, ID_WHISPER_BROWSER_SRC_PORT, std::to_string(app_c_.browser_src_port), wxDefaultPosition, - wxDefaultSize, /*style=*/0); + wxDefaultSize, wxTE_READONLY); whisper_browser_src_port->SetToolTip( "This is the port that the browser source is hosted " "on. If you aren't using TaSTT to stream, you can " @@ -1200,7 +1202,7 @@ Frame::Frame() sizer->Add(whisper_panel, /*proportion=*/1, /*flags=*/wxEXPAND); } - Bind(wxEVT_MENU, &Frame::OnExit, this, wxID_EXIT); + Bind(wxEVT_CLOSE_WINDOW, &Frame::OnExit, this, wxID_EXIT); Bind(wxEVT_BUTTON, &Frame::OnNavbarTranscribe, this, ID_NAVBAR_BUTTON_TRANSCRIBE); Bind(wxEVT_BUTTON, &Frame::OnNavbarUnity, this, ID_NAVBAR_BUTTON_UNITY); @@ -1350,10 +1352,10 @@ void Frame::PopulateDynamicInputFields() } } -void Frame::OnExit(wxCommandEvent& event) +void Frame::OnExit(wxCloseEvent& event) { - OnAppStop(event); - Close(true); + OnAppStop(); + OnWhisperStop(); } void Frame::OnNavbarTranscribe(wxCommandEvent& event) @@ -1887,7 +1889,7 @@ void Frame::OnAppStart(wxCommandEvent& event) { py_app_ = p; } -void Frame::OnAppStop(wxCommandEvent& event) { +void Frame::OnAppStop() { if (py_app_) { const long pid = py_app_->GetPid(); @@ -1927,6 +1929,10 @@ void Frame::OnAppStop(wxCommandEvent& event) { } } +void Frame::OnAppStop(wxCommandEvent& event) { + OnAppStop(); +} + void Frame::OnWhisperStart(wxCommandEvent& event) { Log(whisper_out_, "Launching transcription engine\n"); @@ -1956,7 +1962,6 @@ void Frame::OnWhisperStart(wxCommandEvent& event) { } const bool enable_local_beep = whisper_enable_local_beep_->GetValue(); const bool use_cpu = whisper_use_cpu_->GetValue(); - const bool use_builtin = whisper_enable_builtin_->GetValue(); std::string rows_str = whisper_rows_->GetValue().ToStdString(); std::string cols_str = whisper_cols_->GetValue().ToStdString(); std::string chars_per_sync_str = @@ -1965,13 +1970,16 @@ void Frame::OnWhisperStart(wxCommandEvent& event) { kBytesPerChar[bytes_per_char_idx].ToStdString(); std::string window_duration_str = whisper_window_duration_->GetValue().ToStdString(); - int rows, cols, chars_per_sync, bytes_per_char, window_duration; + std::string browser_src_port_str = + whisper_browser_src_port_->GetValue().ToStdString(); + int rows, cols, chars_per_sync, bytes_per_char, window_duration, browser_src_port; try { rows = std::stoi(rows_str); cols = std::stoi(cols_str); chars_per_sync = std::stoi(chars_per_sync_str); bytes_per_char = std::stoi(bytes_per_char_str); window_duration = std::stoi(window_duration_str); + browser_src_port = std::stoi(browser_src_port_str); } catch (const std::invalid_argument&) { Log(whisper_out_, "Could not parse rows \"{}\", cols \"{}\", chars " @@ -2003,6 +2011,14 @@ void Frame::OnWhisperStart(wxCommandEvent& event) { return; } + const int min_port = 1024; + const int max_port = 65535; + if (browser_src_port < min_port || browser_src_port > max_port) { + Log(whisper_out_, "Browser source port not on [{},{}]\n", + min_port, max_port); + return; + } + app_c_.whisper_mic = which_mic; app_c_.language = kLangChoices[which_lang].ToStdString(); app_c_.whisper_model = kWhisperModelChoices[which_model].ToStdString(); @@ -2014,15 +2030,28 @@ void Frame::OnWhisperStart(wxCommandEvent& event) { app_c_.window_duration = std::to_string(window_duration); app_c_.enable_local_beep = enable_local_beep; app_c_.use_cpu = use_cpu; - app_c_.use_builtin = use_builtin; + app_c_.browser_src_port = browser_src_port; + app_c_.whisper_enable_browser_src = whisper_enable_browser_src_->GetValue(); + app_c_.whisper_enable_builtin = whisper_enable_builtin_->GetValue(); + app_c_.whisper_enable_custom = whisper_enable_custom_->GetValue(); app_c_.Serialize(AppConfig::kConfigPath); whisper_->Start(app_c_); - Log(whisper_out_, "Control flow exit start button\n"); + if (whisper_enable_browser_src_->GetValue()) { + Log(whisper_out_, "Frame launching browser src\n"); + whisper_->StartBrowserSource(app_c_); + } } -void Frame::OnWhisperStop(wxCommandEvent& event) { +void Frame::OnWhisperStop() { whisper_->Stop(); + if (whisper_enable_browser_src_->GetValue()) { + whisper_->StopBrowserSource(); + } +} + +void Frame::OnWhisperStop(wxCommandEvent& event) { + OnWhisperStop(); } void Frame::OnAppDrain(wxTimerEvent& event) { diff --git a/GUI/GUI/GUI/Frame.h b/GUI/GUI/GUI/Frame.h index d40ba24..7da65a3 100644 --- a/GUI/GUI/GUI/Frame.h +++ b/GUI/GUI/GUI/Frame.h @@ -93,7 +93,7 @@ private: // Populate dynamically-generated input fields, such as microphone lists. void PopulateDynamicInputFields(); - void OnExit(wxCommandEvent& event); + void OnExit(wxCloseEvent& event); void OnNavbarTranscribe(wxCommandEvent& event); void OnNavbarUnity(wxCommandEvent& event); void OnNavbarDebug(wxCommandEvent& event); @@ -101,8 +101,10 @@ private: void OnSetupPython(wxCommandEvent& event); void OnDumpMics(wxCommandEvent& event); void OnAppStart(wxCommandEvent& event); + void OnAppStop(); void OnAppStop(wxCommandEvent& event); void OnWhisperStart(wxCommandEvent& event); + void OnWhisperStop(); void OnWhisperStop(wxCommandEvent& event); void OnAppDrain(wxTimerEvent& event); void OnGenerateFX(wxCommandEvent& event); diff --git a/GUI/GUI/GUI/WhisperCPP.cpp b/GUI/GUI/GUI/WhisperCPP.cpp index 3007834..b610941 100644 --- a/GUI/GUI/GUI/WhisperCPP.cpp +++ b/GUI/GUI/GUI/WhisperCPP.cpp @@ -240,7 +240,6 @@ void WhisperCPP::Start(const AppConfig& c) { } transcription_thd_ = std::async(std::launch::async, [&]() -> void { - Log(out_, "Transcription thread top\n"); run_transcription_ = true; Whisper::iAudioCapture* mic_stream; @@ -361,12 +360,6 @@ void WhisperCPP::Start(const AppConfig& c) { Log(app->out_, "Exit transcription loop\n"); return S_FALSE; } - // Sleeping here prevents the GUI from hanging. - // For some reason, printing is also required to prevent hanging. - static int i = 0; - if (++i % 20 == 0) { - Log(app->out_, "Spin {}\n", i); - } return S_OK; }; callbacks.pv = this; @@ -394,20 +387,20 @@ void WhisperCPP::Stop() { void WhisperCPP::StartBrowserSource(const AppConfig& c) { if (!browser_src_thd_.valid()) { - Log(out_, "Transcription engine already running\n"); + Log(out_, "Browser source already running\n"); return; } browser_src_thd_ = std::async(std::launch::async, [&]() -> void { -#if 0 + run_browser_src_ = true; BrowserSource src(c.browser_src_port, out_); src.Run(&run_browser_src_); -#endif + Log(out_, "Browser source thread exit\n"); }); } void WhisperCPP::StopBrowserSource() { - Log(out_, "Stopping browser source engine...\n"); + Log(out_, "Stopping browser source...\n"); run_browser_src_ = false; browser_src_thd_.wait(); Log(out_, "Done!\n"); -- cgit v1.2.3