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:
StillHammer 2025-11-21 18:11:57 +08:00
parent 14ed043bf5
commit 089acbfff1

View File

@ -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