fix: Normalize line endings in TranslationUI.cpp
Convert Windows CRLF to Unix LF line endings for consistency across platforms and version control. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
14ed043bf5
commit
089acbfff1
@ -1,250 +1,250 @@
|
||||
#include <glad/glad.h> // MUST be FIRST! Provides OpenGL functions
|
||||
#define GLFW_INCLUDE_NONE // Tell GLFW not to include OpenGL headers (GLAD does it)
|
||||
#include "TranslationUI.h"
|
||||
#include <imgui.h>
|
||||
#include <imgui_impl_glfw.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
namespace secondvoice {
|
||||
|
||||
TranslationUI::TranslationUI(int width, int height)
|
||||
: width_(width)
|
||||
, height_(height) {
|
||||
}
|
||||
|
||||
TranslationUI::~TranslationUI() {
|
||||
if (window_) {
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
glfwDestroyWindow(window_);
|
||||
glfwTerminate();
|
||||
}
|
||||
}
|
||||
|
||||
bool TranslationUI::initialize() {
|
||||
// Initialize GLFW
|
||||
std::cout << "[UI] Initializing GLFW..." << std::endl;
|
||||
glfwSetErrorCallback([](int error, const char* description) {
|
||||
std::cerr << "[GLFW Error " << error << "] " << description << std::endl;
|
||||
});
|
||||
|
||||
if (!glfwInit()) {
|
||||
std::cerr << "[UI] Failed to initialize GLFW" << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::cout << "[UI] GLFW initialized successfully" << std::endl;
|
||||
|
||||
// FORCE high-performance GPU (NVIDIA/AMD dedicated)
|
||||
std::cout << "[UI] Requesting high-performance GPU..." << std::endl;
|
||||
|
||||
// OpenGL 3.3 - core profile
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
// Create window
|
||||
std::cout << "[UI] Creating GLFW window (" << width_ << "x" << height_ << ")..." << std::endl;
|
||||
window_ = glfwCreateWindow(width_, height_, "SecondVoice - Live Translation", nullptr, nullptr);
|
||||
if (!window_) {
|
||||
std::cerr << "[UI] Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return false;
|
||||
}
|
||||
std::cout << "[UI] GLFW window created successfully" << std::endl;
|
||||
|
||||
glfwMakeContextCurrent(window_);
|
||||
glfwSwapInterval(1); // Enable vsync
|
||||
|
||||
// Initialize GLAD - MUST happen after glfwMakeContextCurrent!
|
||||
std::cout << "[UI] Initializing GLAD OpenGL loader..." << std::endl;
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
std::cerr << "[UI] Failed to initialize GLAD!" << std::endl;
|
||||
glfwDestroyWindow(window_);
|
||||
glfwTerminate();
|
||||
return false;
|
||||
}
|
||||
std::cout << "[UI] GLAD initialized successfully" << std::endl;
|
||||
|
||||
// Query OpenGL context to see which GPU we got
|
||||
const GLubyte* vendor = glGetString(GL_VENDOR);
|
||||
const GLubyte* renderer = glGetString(GL_RENDERER);
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
|
||||
std::cout << "[UI] ========================================" << std::endl;
|
||||
std::cout << "[UI] OpenGL Context Info:" << std::endl;
|
||||
std::cout << "[UI] Vendor: " << (vendor ? (const char*)vendor : "Unknown") << std::endl;
|
||||
std::cout << "[UI] Renderer: " << (renderer ? (const char*)renderer : "Unknown") << std::endl;
|
||||
std::cout << "[UI] Version: " << (version ? (const char*)version : "Unknown") << std::endl;
|
||||
std::cout << "[UI] ========================================" << std::endl;
|
||||
|
||||
// Initialize ImGui
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(window_, true);
|
||||
|
||||
// TEST: Compile a simple shader to see REAL error messages
|
||||
std::cout << "[UI] Testing shader compilation..." << std::endl;
|
||||
const char* vertexShaderSource = R"(
|
||||
#version 130
|
||||
in vec2 Position;
|
||||
in vec2 UV;
|
||||
in vec4 Color;
|
||||
varying vec2 Frag_UV;
|
||||
varying vec4 Frag_Color;
|
||||
void main() {
|
||||
Frag_UV = UV;
|
||||
Frag_Color = Color;
|
||||
gl_Position = vec4(Position, 0, 1);
|
||||
}
|
||||
)";
|
||||
|
||||
GLuint testShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(testShader, 1, &vertexShaderSource, NULL);
|
||||
glCompileShader(testShader);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(testShader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
char infoLog[1024];
|
||||
glGetShaderInfoLog(testShader, 1024, NULL, infoLog);
|
||||
std::cerr << "[UI] ==================== SHADER COMPILATION ERROR ====================" << std::endl;
|
||||
std::cerr << infoLog << std::endl;
|
||||
std::cerr << "[UI] ====================================================================" << std::endl;
|
||||
} else {
|
||||
std::cout << "[UI] Test shader compiled successfully!" << std::endl;
|
||||
}
|
||||
glDeleteShader(testShader);
|
||||
|
||||
// DEBUG: Check if GLAD loaded glCreateShader
|
||||
std::cout << "[UI] DEBUG: glCreateShader function pointer = " << (void*)glCreateShader << std::endl;
|
||||
if (glCreateShader == nullptr) {
|
||||
std::cerr << "[UI] ERROR: glCreateShader is NULL!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let ImGui auto-detect the GLSL version
|
||||
ImGui_ImplOpenGL3_Init(nullptr);
|
||||
|
||||
// CRITICAL: Release the OpenGL context from this thread
|
||||
// The UI rendering will happen in a separate thread which will call makeContextCurrent()
|
||||
std::cout << "[UI] Releasing OpenGL context from initialization thread" << std::endl;
|
||||
glfwMakeContextCurrent(nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TranslationUI::makeContextCurrent() {
|
||||
if (window_) {
|
||||
std::cout << "[UI] Making OpenGL context current in thread: " << std::this_thread::get_id() << std::endl;
|
||||
glfwMakeContextCurrent(window_);
|
||||
}
|
||||
}
|
||||
|
||||
void TranslationUI::render() {
|
||||
glfwPollEvents();
|
||||
|
||||
// Start ImGui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Main window (full viewport)
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||
ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize);
|
||||
ImGui::Begin("SecondVoice", nullptr,
|
||||
ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
renderTranslations();
|
||||
renderControls();
|
||||
renderStatus();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
int display_w, display_h;
|
||||
glfwGetFramebufferSize(window_, &display_w, &display_h);
|
||||
glViewport(0, 0, display_w, display_h);
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
glfwSwapBuffers(window_);
|
||||
}
|
||||
|
||||
bool TranslationUI::shouldClose() const {
|
||||
return glfwWindowShouldClose(window_);
|
||||
}
|
||||
|
||||
void TranslationUI::addTranslation(const std::string& chinese, const std::string& french) {
|
||||
messages_.push_back({chinese, french});
|
||||
}
|
||||
|
||||
void TranslationUI::renderTranslations() {
|
||||
ImGui::Text("SecondVoice - Live Translation");
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::BeginChild("Translations", ImVec2(0, -120), true);
|
||||
|
||||
for (const auto& msg : messages_) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.8f, 1.0f, 1.0f));
|
||||
ImGui::TextWrapped("中文: %s", msg.chinese.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 1.0f, 0.5f, 1.0f));
|
||||
ImGui::TextWrapped("FR: %s", msg.french.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
if (auto_scroll_ && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void TranslationUI::renderControls() {
|
||||
ImGui::Spacing();
|
||||
|
||||
// Center the stop button
|
||||
float button_width = 200.0f;
|
||||
float window_width = ImGui::GetWindowWidth();
|
||||
ImGui::SetCursorPosX((window_width - button_width) * 0.5f);
|
||||
|
||||
if (ImGui::Button("STOP RECORDING", ImVec2(button_width, 40))) {
|
||||
stop_requested_ = true;
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
void TranslationUI::renderStatus() {
|
||||
ImGui::Separator();
|
||||
|
||||
// Format duration as MM:SS
|
||||
int minutes = recording_duration_ / 60;
|
||||
int seconds = recording_duration_ % 60;
|
||||
ImGui::Text("Recording... Duration: %02d:%02d", minutes, seconds);
|
||||
|
||||
if (!processing_status_.empty()) {
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(" | Status: %s", processing_status_.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace secondvoice
|
||||
#include <glad/glad.h> // MUST be FIRST! Provides OpenGL functions
|
||||
#define GLFW_INCLUDE_NONE // Tell GLFW not to include OpenGL headers (GLAD does it)
|
||||
#include "TranslationUI.h"
|
||||
#include <imgui.h>
|
||||
#include <imgui_impl_glfw.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
namespace secondvoice {
|
||||
|
||||
TranslationUI::TranslationUI(int width, int height)
|
||||
: width_(width)
|
||||
, height_(height) {
|
||||
}
|
||||
|
||||
TranslationUI::~TranslationUI() {
|
||||
if (window_) {
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
glfwDestroyWindow(window_);
|
||||
glfwTerminate();
|
||||
}
|
||||
}
|
||||
|
||||
bool TranslationUI::initialize() {
|
||||
// Initialize GLFW
|
||||
std::cout << "[UI] Initializing GLFW..." << std::endl;
|
||||
glfwSetErrorCallback([](int error, const char* description) {
|
||||
std::cerr << "[GLFW Error " << error << "] " << description << std::endl;
|
||||
});
|
||||
|
||||
if (!glfwInit()) {
|
||||
std::cerr << "[UI] Failed to initialize GLFW" << std::endl;
|
||||
return false;
|
||||
}
|
||||
std::cout << "[UI] GLFW initialized successfully" << std::endl;
|
||||
|
||||
// FORCE high-performance GPU (NVIDIA/AMD dedicated)
|
||||
std::cout << "[UI] Requesting high-performance GPU..." << std::endl;
|
||||
|
||||
// OpenGL 3.3 - core profile
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
// Create window
|
||||
std::cout << "[UI] Creating GLFW window (" << width_ << "x" << height_ << ")..." << std::endl;
|
||||
window_ = glfwCreateWindow(width_, height_, "SecondVoice - Live Translation", nullptr, nullptr);
|
||||
if (!window_) {
|
||||
std::cerr << "[UI] Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return false;
|
||||
}
|
||||
std::cout << "[UI] GLFW window created successfully" << std::endl;
|
||||
|
||||
glfwMakeContextCurrent(window_);
|
||||
glfwSwapInterval(1); // Enable vsync
|
||||
|
||||
// Initialize GLAD - MUST happen after glfwMakeContextCurrent!
|
||||
std::cout << "[UI] Initializing GLAD OpenGL loader..." << std::endl;
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
std::cerr << "[UI] Failed to initialize GLAD!" << std::endl;
|
||||
glfwDestroyWindow(window_);
|
||||
glfwTerminate();
|
||||
return false;
|
||||
}
|
||||
std::cout << "[UI] GLAD initialized successfully" << std::endl;
|
||||
|
||||
// Query OpenGL context to see which GPU we got
|
||||
const GLubyte* vendor = glGetString(GL_VENDOR);
|
||||
const GLubyte* renderer = glGetString(GL_RENDERER);
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
|
||||
std::cout << "[UI] ========================================" << std::endl;
|
||||
std::cout << "[UI] OpenGL Context Info:" << std::endl;
|
||||
std::cout << "[UI] Vendor: " << (vendor ? (const char*)vendor : "Unknown") << std::endl;
|
||||
std::cout << "[UI] Renderer: " << (renderer ? (const char*)renderer : "Unknown") << std::endl;
|
||||
std::cout << "[UI] Version: " << (version ? (const char*)version : "Unknown") << std::endl;
|
||||
std::cout << "[UI] ========================================" << std::endl;
|
||||
|
||||
// Initialize ImGui
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(window_, true);
|
||||
|
||||
// TEST: Compile a simple shader to see REAL error messages
|
||||
std::cout << "[UI] Testing shader compilation..." << std::endl;
|
||||
const char* vertexShaderSource = R"(
|
||||
#version 130
|
||||
in vec2 Position;
|
||||
in vec2 UV;
|
||||
in vec4 Color;
|
||||
varying vec2 Frag_UV;
|
||||
varying vec4 Frag_Color;
|
||||
void main() {
|
||||
Frag_UV = UV;
|
||||
Frag_Color = Color;
|
||||
gl_Position = vec4(Position, 0, 1);
|
||||
}
|
||||
)";
|
||||
|
||||
GLuint testShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(testShader, 1, &vertexShaderSource, NULL);
|
||||
glCompileShader(testShader);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(testShader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
char infoLog[1024];
|
||||
glGetShaderInfoLog(testShader, 1024, NULL, infoLog);
|
||||
std::cerr << "[UI] ==================== SHADER COMPILATION ERROR ====================" << std::endl;
|
||||
std::cerr << infoLog << std::endl;
|
||||
std::cerr << "[UI] ====================================================================" << std::endl;
|
||||
} else {
|
||||
std::cout << "[UI] Test shader compiled successfully!" << std::endl;
|
||||
}
|
||||
glDeleteShader(testShader);
|
||||
|
||||
// DEBUG: Check if GLAD loaded glCreateShader
|
||||
std::cout << "[UI] DEBUG: glCreateShader function pointer = " << (void*)glCreateShader << std::endl;
|
||||
if (glCreateShader == nullptr) {
|
||||
std::cerr << "[UI] ERROR: glCreateShader is NULL!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let ImGui auto-detect the GLSL version
|
||||
ImGui_ImplOpenGL3_Init(nullptr);
|
||||
|
||||
// CRITICAL: Release the OpenGL context from this thread
|
||||
// The UI rendering will happen in a separate thread which will call makeContextCurrent()
|
||||
std::cout << "[UI] Releasing OpenGL context from initialization thread" << std::endl;
|
||||
glfwMakeContextCurrent(nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TranslationUI::makeContextCurrent() {
|
||||
if (window_) {
|
||||
std::cout << "[UI] Making OpenGL context current in thread: " << std::this_thread::get_id() << std::endl;
|
||||
glfwMakeContextCurrent(window_);
|
||||
}
|
||||
}
|
||||
|
||||
void TranslationUI::render() {
|
||||
glfwPollEvents();
|
||||
|
||||
// Start ImGui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Main window (full viewport)
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||
ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize);
|
||||
ImGui::Begin("SecondVoice", nullptr,
|
||||
ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoResize |
|
||||
ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
renderTranslations();
|
||||
renderControls();
|
||||
renderStatus();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
int display_w, display_h;
|
||||
glfwGetFramebufferSize(window_, &display_w, &display_h);
|
||||
glViewport(0, 0, display_w, display_h);
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
glfwSwapBuffers(window_);
|
||||
}
|
||||
|
||||
bool TranslationUI::shouldClose() const {
|
||||
return glfwWindowShouldClose(window_);
|
||||
}
|
||||
|
||||
void TranslationUI::addTranslation(const std::string& chinese, const std::string& french) {
|
||||
messages_.push_back({chinese, french});
|
||||
}
|
||||
|
||||
void TranslationUI::renderTranslations() {
|
||||
ImGui::Text("SecondVoice - Live Translation");
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::BeginChild("Translations", ImVec2(0, -120), true);
|
||||
|
||||
for (const auto& msg : messages_) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.8f, 1.0f, 1.0f));
|
||||
ImGui::TextWrapped("中文: %s", msg.chinese.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 1.0f, 0.5f, 1.0f));
|
||||
ImGui::TextWrapped("FR: %s", msg.french.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
if (auto_scroll_ && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void TranslationUI::renderControls() {
|
||||
ImGui::Spacing();
|
||||
|
||||
// Center the stop button
|
||||
float button_width = 200.0f;
|
||||
float window_width = ImGui::GetWindowWidth();
|
||||
ImGui::SetCursorPosX((window_width - button_width) * 0.5f);
|
||||
|
||||
if (ImGui::Button("STOP RECORDING", ImVec2(button_width, 40))) {
|
||||
stop_requested_ = true;
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
void TranslationUI::renderStatus() {
|
||||
ImGui::Separator();
|
||||
|
||||
// Format duration as MM:SS
|
||||
int minutes = recording_duration_ / 60;
|
||||
int seconds = recording_duration_ % 60;
|
||||
ImGui::Text("Recording... Duration: %02d:%02d", minutes, seconds);
|
||||
|
||||
if (!processing_status_.empty()) {
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(" | Status: %s", processing_status_.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace secondvoice
|
||||
|
||||
Loading…
Reference in New Issue
Block a user