diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..fdb0302
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/neko-player.iml b/.idea/neko-player.iml
new file mode 100644
index 0000000..bc2cd87
--- /dev/null
+++ b/.idea/neko-player.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..552d15a
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RendererBackend.cpp b/RendererBackend.cpp
new file mode 100644
index 0000000..9ab9e41
--- /dev/null
+++ b/RendererBackend.cpp
@@ -0,0 +1,273 @@
+#include "RendererBackend.h"
+#include "assets.h"
+#include
+#include "IconsForkAwesome.h"
+#include "config.h"
+#include
+#include
+#include "theme.h"
+#include "imgui_stdlib.h"
+#include "imgui_impl_sdl2.h"
+#include "imgui_impl_opengl3.h"
+#include "base85.h"
+#include
+#include "translation.h"
+using std::vector;
+
+struct FontData {
+ const char* data;
+ const ImWchar *ranges;
+};
+
+ImFont *add_font(vector data_vec, int size = 13) {
+ ImFont* font = nullptr;
+ ImGuiIO& io = ImGui::GetIO();
+ for (auto data : data_vec) {
+ ImFontConfig font_cfg = ImFontConfig();
+ font_cfg.SizePixels = size;
+ font_cfg.OversampleH = font_cfg.OversampleV = 1;
+ font_cfg.PixelSnapH = true;
+ if (font_cfg.SizePixels <= 0.0f)
+ font_cfg.SizePixels = 13.0f * 1.0f;
+ if (font != nullptr) {
+ font_cfg.DstFont = font;
+ font_cfg.MergeMode = true;
+ }
+ //font_cfg.EllipsisChar = (ImWchar)0x0085;
+ //font_cfg.GlyphOffset.y = 1.0f * IM_FLOOR(font_cfg.SizePixels / 13.0f); // Add +1 offset per 13 units
+
+ const char* ttf_compressed_base85 = data.data;
+ const ImWchar* glyph_ranges = data.ranges;
+ auto new_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges);
+ if (font == nullptr) font = new_font;
+ }
+ {
+ ImFontConfig config;
+ config.MergeMode = true;
+ config.GlyphMinAdvanceX = size;
+ config.SizePixels = size;
+ config.DstFont = font;
+ static const ImWchar icon_ranges[] = { ICON_MIN_FK, ICON_MAX_FK, 0 };
+ io.Fonts->AddFontFromMemoryCompressedBase85TTF(forkawesome_compressed_data_base85, float(size), &config, icon_ranges);
+ }
+ return font;
+}
+RendererBackend::RendererBackend() {
+}
+RendererBackend::~RendererBackend() {
+
+}
+void RendererBackend::SetWindowTitle(const char *title) {
+ SDL_SetWindowTitle(window, title);
+}
+void RendererBackend::GuiFunction() {
+ // Do nothing by default.
+}
+int RendererBackend::Run() {
+ setlocale(LC_ALL, "");
+ bindtextdomain("neko_player", LOCALE_DIR);
+ textdomain("neko_player");
+ printf("Loaded locale '%s' from '%s'...\n", CURRENT_LANGUAGE, LOCALE_DIR);
+ printf("Locale name: %s\n", _TR_CTX("Language name", "English (United States)"));
+ bool enable_kms = std::getenv("LAP_KMS") != nullptr;
+ SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "false");
+ SDL_SetHint(SDL_HINT_APP_NAME, NAME);
+ // Setup SDL
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
+ {
+ printf("Error: %s\n", SDL_GetError());
+ return -1;
+ }
+ if (std::string(SDL_GetCurrentVideoDriver()) == "KMSDRM") {
+ enable_kms = true;
+ }
+ IMG_Init(IMG_INIT_PNG|IMG_INIT_WEBP);
+ prefPath = SDL_GetPrefPath("Catmeow72", NAME);
+ Theme::prefPath = prefPath;
+
+ // Decide GL+GLSL versions
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+ // GL ES 2.0 + GLSL 100
+ const char* glsl_version = "#version 100";
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+#elif defined(__APPLE__)
+ // GL 3.2 Core + GLSL 150
+ const char* glsl_version = "#version 150";
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
+#else
+ // GL 3.0 + GLSL 130
+ const char* glsl_version = "#version 130";
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
+#endif
+
+ // From 2.0.18: Enable native IME.
+#ifdef SDL_HINT_IME_SHOW_UI
+ SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
+#endif
+
+ // Create window with graphics context
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+ SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+ window = SDL_CreateWindow(NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, window_flags);
+ SDL_SetWindowMinimumSize(window, window_width, window_height);
+ if (enable_kms) {
+ SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
+ }
+ const vector icon_data = DecodeBase85(icon_compressed_data_base85);
+ SDL_Surface* icon = IMG_Load_RW(SDL_RWFromConstMem(icon_data.data(), icon_data.size()), 1);
+ SDL_SetWindowIcon(window, icon);
+ SDL_GLContext gl_context = SDL_GL_CreateContext(window);
+ SDL_GL_MakeCurrent(window, gl_context);
+
+ // Setup Dear ImGui context
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
+ io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
+ //io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
+ io.IniFilename = strdup((std::string(prefPath) + "imgui.ini").c_str());
+ if (enable_kms) {
+ io.MouseDrawCursor = true;
+ }
+ //io.ConfigViewportsNoAutoMerge = true;
+ //io.ConfigViewportsNoTaskBarIcon = true;
+
+ //ImGui::StyleColorsLight();
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
+ ImGui_ImplOpenGL3_Init(glsl_version);
+ // Load Fonts
+ // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
+ // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
+ // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
+ // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
+ // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
+ // - Read 'docs/FONTS.md' for more instructions and details.
+ // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
+ //io.Fonts->AddFontDefault();
+ //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
+ //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
+ //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
+ //IM_ASSERT(font != nullptr);
+ add_font({FontData {notosans_regular_compressed_data_base85, io.Fonts->GetGlyphRangesDefault()}, FontData {notosansjp_regular_compressed_data_base85, io.Fonts->GetGlyphRangesJapanese()}});
+ title = add_font({FontData {notosans_thin_compressed_data_base85, io.Fonts->GetGlyphRangesDefault()}, FontData {notosansjp_thin_compressed_data_base85, io.Fonts->GetGlyphRangesJapanese()}}, 48);
+
+
+ theme = new Theme(false);
+ userdir = std::getenv(
+ #ifdef _WIN32
+ "UserProfile"
+ #else
+ "HOME"
+ #endif
+ );
+ SDL_GL_SetSwapInterval(vsync ? 1 : 0);
+ theme->Apply(accent_color);
+ Init();
+#ifdef __EMSCRIPTEN__
+ // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
+ // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
+ io.IniFilename = nullptr;
+ EMSCRIPTEN_MAINLOOP_BEGIN
+#else
+ while (!done)
+#endif
+ {
+ auto next_frame = std::chrono::steady_clock::now() + std::chrono::milliseconds(1000 / framerate);
+ // Poll and handle events (inputs, window resize, etc.)
+ // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
+ // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
+ // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
+ // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ ImGui_ImplSDL2_ProcessEvent(&event);
+ if (event.type == SDL_QUIT)
+ done = true;
+ if (event.type == SDL_WINDOWEVENT) {
+ if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
+ window_width = event.window.data1;
+ window_height = event.window.data2;
+ //SDL_GetWindowSize(window, &window_width, &window_height);
+ }
+ if (event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) {
+ done = true;
+ }
+ }
+ }
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplSDL2_NewFrame();
+ ImGui::NewFrame();
+ // Run the GUI
+ GuiFunction();
+ // Rendering
+ ImGui::Render();
+ // Update the window size.
+ glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
+ // Clear the screen.
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+ // Tell ImGui to render.
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+
+ // Update and Render additional Platform Windows
+ // (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere.
+ // For this specific demo app we could also call SDL_GL_MakeCurrent(window, gl_context) directly)
+ if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
+ {
+ SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow();
+ SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
+ ImGui::UpdatePlatformWindows();
+ ImGui::RenderPlatformWindowsDefault();
+ SDL_GL_MakeCurrent(backup_current_window, backup_current_context);
+ }
+
+ // Swap the buffers, and do VSync if enabled.
+ SDL_GL_SwapWindow(window);
+ // If not doing VSync, wait until the next frame needs to be rendered.
+ if (!vsync) {
+ std::this_thread::sleep_until(next_frame);
+ }
+
+ }
+ // Cleanup
+#ifdef __EMSCRIPTEN__
+ EMSCRIPTEN_MAINLOOP_END;
+#endif
+ // Cleanup
+ ImGui_ImplOpenGL3_Shutdown();
+ ImGui_ImplSDL2_Shutdown();
+ ImGui::DestroyContext();
+
+ SDL_GL_DeleteContext(gl_context);
+ SDL_DestroyWindow(window);
+ IMG_Quit();
+ SDL_Quit();
+ free((void*)io.IniFilename);
+ Deinit();
+ return 0;
+}
+void RendererBackend::Init() {
+ // Do nothing by default.
+}
+void RendererBackend::Deinit() {
+ // Do nothing by default.
+}
\ No newline at end of file
diff --git a/RendererBackend.h b/RendererBackend.h
new file mode 100644
index 0000000..5f3c9e6
--- /dev/null
+++ b/RendererBackend.h
@@ -0,0 +1,36 @@
+#pragma once
+#include "imgui.h"
+#include
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+#include
+#else
+#include
+#endif
+#include
+#include
+#include
+#include "theme.h"
+static const char* NAME = "Neko Player";
+class RendererBackend {
+ public:
+ SDL_Window *window;
+ int window_width = 475;
+ int window_height = 354;
+ bool done = false;
+ Theme *theme;
+ bool vsync = false;
+ std::string lang;
+ std::string userdir;
+ int framerate = 60;
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+ ImFont *title;
+ const char *prefPath;
+ float accent_color = 280.0;
+ int Run();
+ void SetWindowTitle(const char *title);
+ virtual void Init();
+ virtual void GuiFunction();
+ virtual void Deinit();
+ RendererBackend();
+ ~RendererBackend();
+};
\ No newline at end of file
diff --git a/assets/translations/es_MX/LC_MESSAGES/es_MX.po b/assets/translations/es_MX/LC_MESSAGES/es_MX.po
new file mode 100644
index 0000000..7a269aa
--- /dev/null
+++ b/assets/translations/es_MX/LC_MESSAGES/es_MX.po
@@ -0,0 +1,583 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Neko Player\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-07-25 14:02-0700\n"
+"PO-Revision-Date: 2023-08-25 14:06-0700\n"
+"Last-Translator: \n"
+"Language-Team: None\n"
+"Language: es_MX\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 3.3.2\n"
+"X-Poedit-KeywordsList: _TR;_TRS;_TRIS:2;_TRI:2;_TR_CTX:1c,2;_TRS_CTX:1c,2;"
+"_TRIS_CTX:2c,3;_TRI_CTX:2c,3\n"
+"X-Poedit-Basepath: ../..\n"
+"X-Poedit-SearchPath-0: theme.cpp\n"
+"X-Poedit-SearchPath-1: main.cpp\n"
+
+#: main.cpp:120
+msgctxt "Language name"
+msgid "English (United States)"
+msgstr "English (United States)"
+
+#: main.cpp:292
+msgctxt "Built-in themes | Theme default strings | name"
+msgid "(built-in)"
+msgstr "(incorporado)"
+
+#: main.cpp:296
+msgctxt "Built-in light theme | Theme default strings | name"
+msgid "Default light"
+msgstr "Luz por defecto"
+
+#: main.cpp:304
+msgctxt "Built-in dark theme | Theme default strings | name"
+msgid "Default dark"
+msgstr "Oscuro por defecto"
+
+#: main.cpp:368
+msgctxt "Main menu"
+msgid "File"
+msgstr "Archivo"
+
+#: main.cpp:369
+msgctxt "Main menu | File"
+msgid "Open"
+msgstr "Abrir"
+
+#: main.cpp:371
+msgctxt "File dialog title"
+msgid "Open..."
+msgstr "Abre..."
+
+#: main.cpp:372
+msgctxt "File dialog filter name"
+msgid "Audio files"
+msgstr "Archivos de sonido"
+
+#: main.cpp:375
+msgctxt "Main menu | File"
+msgid "Quit"
+msgstr "Abandonar"
+
+#: main.cpp:380
+msgctxt "Main menu"
+msgid "Edit"
+msgstr "Editar"
+
+#: main.cpp:381
+msgctxt "Main menu | Edit"
+msgid "Preferences..."
+msgstr "Preferencias..."
+
+#: main.cpp:387
+msgctxt "Main menu (in debug builds)"
+msgid "Debug"
+msgstr "Depurar"
+
+#: main.cpp:388
+msgctxt "Main menu | Debug"
+msgid "Show ImGui Demo Window"
+msgstr "Mostrar ventana de demostración de ImGui"
+
+#: main.cpp:394
+msgctxt "Main menu"
+msgid "Help"
+msgstr "Ayudar"
+
+#: main.cpp:395
+msgctxt "Main menu | Help"
+msgid "About"
+msgstr "Sobre"
+
+#: main.cpp:403
+msgctxt "Main window title"
+msgid "Player"
+msgstr "Jugador"
+
+#: main.cpp:432
+#, c-format
+msgctxt "Playback controls | slider"
+msgid "Speed: %.2fx"
+msgstr "Velocidad: %.2fx"
+
+#: main.cpp:436
+#, c-format
+msgctxt "Playback controls | slider"
+msgid "Tempo: %.2fx"
+msgstr "Tempo: %.2fx"
+
+#: main.cpp:440
+#, c-format
+msgctxt "Playback controls | slider"
+msgid "Pitch: %.2fx"
+msgstr "Tono: %.2fx"
+
+#: main.cpp:448
+msgctxt "Window title, window opened by menu item"
+msgid "Preferences..."
+msgstr "Preferencias..."
+
+#: main.cpp:450
+msgctxt "Preference | VSync checkbox"
+msgid "Enable VSync"
+msgstr "Habilitar VSync"
+
+#: main.cpp:455
+#, c-format
+msgctxt "Preferences | Framerate slider"
+msgid "Max framerate without VSync: %d"
+msgstr "Frecuencia de imagen máxima sin VSync: %d"
+
+#: main.cpp:456
+msgctxt "Preference | Related non-preference button"
+msgid "Theme Editor"
+msgstr "Editor de temas"
+
+#: main.cpp:460
+msgctxt "Preference | override enable checkbox"
+msgid "Override language"
+msgstr "Anular el idioma"
+
+#: main.cpp:476
+msgctxt "Preference | Theme selector | Filter label"
+msgid "Filter:"
+msgstr "Filtro:"
+
+#: main.cpp:479
+msgctxt "Preferences | Theme selector | Selector label"
+msgid "Select a theme..."
+msgstr "Selecciona un tema..."
+
+#: main.cpp:516
+#, c-format
+msgctxt ""
+"Preference | Accent hue slider, range 0-360 from HSV algorithm hue component"
+msgid "Accent color hue: %.0f°"
+msgstr "Tono de color de acento %.0f°"
+
+#: main.cpp:524
+msgctxt "Window title, window opened by menu item"
+msgid "About and Licenses"
+msgstr "Sobre y Licencias"
+
+#: main.cpp:526
+msgctxt ""
+"Application name - Japanese word should remain Japanese and stay the same "
+"when translating for stylistic purposes."
+msgid "ねこ Player"
+msgstr "ねこ Jugador"
+
+#: main.cpp:530
+msgctxt ""
+"Application name - Japanese word should be converted to the translated "
+"language's characters. Use a string with only a single underscore to disable "
+"for Japanese."
+msgid "(Neko Player)"
+msgstr "(Neko Jugador)"
+
+#: main.cpp:535
+msgctxt "Version string format specifier"
+msgid "Version "
+msgstr "Versión"
+
+#: main.cpp:535
+msgctxt "Suffix to the version string in the about window, if needed"
+msgid " "
+msgstr ""
+
+#: main.cpp:541
+msgctxt "Library name"
+msgid "SDL Mixer X"
+msgstr "SDL Mixer X"
+
+#: main.cpp:542
+msgctxt "Library name"
+msgid "JsonCpp"
+msgstr "JsonCpp"
+
+#: main.cpp:543
+msgctxt "Library name"
+msgid "SoundTouch"
+msgstr "SoundTouch"
+
+#: main.cpp:544
+msgctxt "Library name"
+msgid "libintl"
+msgstr "libintl"
+
+#: main.cpp:545
+msgctxt "Library name"
+msgid "Dear ImGui"
+msgstr "Dear ImGui"
+
+#: main.cpp:546
+msgctxt "Library name"
+msgid "imgui-filebrowser"
+msgstr "imgui-filebrowser"
+
+#: main.cpp:548
+msgctxt "Library name"
+msgid "libportal"
+msgstr "libportal"
+
+#: main.cpp:550
+msgctxt "Library name"
+msgid "Noto Sans"
+msgstr "Noto Sans"
+
+#: main.cpp:551
+msgctxt "Library name"
+msgid "Fork Awesome"
+msgstr "Fork Awesome"
+
+#: main.cpp:552
+msgctxt "Library name"
+msgid "IconFontCppHeaders"
+msgstr "Fork Awesome"
+
+#: main.cpp:577
+msgctxt "Project selector label."
+msgid "Project"
+msgstr "Proyecto"
+
+#: main.cpp:592
+msgctxt "License viewer label"
+msgid "License"
+msgstr "Licensia"
+
+#: main.cpp:595
+#, c-format
+msgctxt ""
+"License viewer | information above license - string 1: selected project, "
+"string 2: SPDX license identifier"
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: theme.cpp:39
+msgctxt "Window title"
+msgid "Theme Editor"
+msgstr "Editor de temas"
+
+#: theme.cpp:43
+msgctxt "Theme Editor | preset button"
+msgid "Create light"
+msgstr "Crear luz"
+
+#: theme.cpp:52
+msgctxt "Theme Editor | preset button"
+msgid "Create dark"
+msgstr "Crear oscuro"
+
+#: theme.cpp:60
+msgctxt "Theme Editor | import button. Opens the theme import file dialog"
+msgid "Import..."
+msgstr "Importar..."
+
+#: theme.cpp:61
+msgctxt "Theme Editor file dialog title"
+msgid "Import theme..."
+msgstr "Importar tema..."
+
+#: theme.cpp:62 theme.cpp:76
+msgctxt "Theme Editor file dialog filter name"
+msgid "Theme JSON files"
+msgstr "Archivos JSON de tema"
+
+#: theme.cpp:74
+msgctxt "Theme Editor | export button. Opens the theme export file dialog"
+msgid "Export..."
+msgstr "Exportar..."
+
+#: theme.cpp:75
+msgctxt "Theme Editor file dialog title"
+msgid "Export theme..."
+msgstr "Exportar tema..."
+
+#: theme.cpp:98
+msgctxt "Theme Editor | button. Reverts to saved file."
+msgid "Revert"
+msgstr "Revertir"
+
+#: theme.cpp:107
+msgctxt ""
+"Theme Editor | button. Saves the theme to it's current location. Not shown "
+"when it doesn't already have one."
+msgid "Save"
+msgstr "Ahorrar"
+
+#: theme.cpp:111
+msgctxt ""
+"Theme Editor | button. Opens the theme loading dialog for themes created or "
+"imported by the user."
+msgid "Load..."
+msgstr "Cargar..."
+
+#: theme.cpp:115
+msgctxt ""
+"Theme Editor | button. Opens the theme saving dialog for themes created or "
+"imported by the user."
+msgid "Save as..."
+msgstr "Guardar como..."
+
+#: theme.cpp:120
+msgctxt "Theme Editor | slider. Simplified frame rounding."
+msgid "Frame Rounding"
+msgstr "Redondeo de marco"
+
+#: theme.cpp:122
+msgctxt "Theme Editor | checkbox"
+msgid "Window Border"
+msgstr "Borde de ventana"
+
+#: theme.cpp:124
+msgctxt "Theme Editor | checkbox"
+msgid "Frame Border"
+msgstr "Borde de"
+
+#: theme.cpp:126
+msgctxt "Theme Editor | checkbox"
+msgid "Popup Border"
+msgstr "Borde emergente"
+
+#: theme.cpp:132
+msgctxt "Theme Editor | Tab label"
+msgid "Strings"
+msgstr "Cadenas"
+
+#: theme.cpp:134
+msgctxt "Theme Editor | Strings | Name input label"
+msgid "Name"
+msgstr "Nombre"
+
+#: theme.cpp:135
+msgctxt "Theme Editor | Strings | Description input label"
+msgid "Description"
+msgstr "Descripción"
+
+#: theme.cpp:139
+msgctxt "Theme Editor | Tab label"
+msgid "Sizes"
+msgstr "Tallas"
+
+#: theme.cpp:141
+msgctxt "Theme Editor | Sizes | Section label"
+msgid "Sizing"
+msgstr "Dimensionamiento"
+
+#: theme.cpp:142
+msgctxt "Theme Editor | Sizes | Sizing | label of XY sliders"
+msgid "Window Padding"
+msgstr "Acolchado de ventana"
+
+#: theme.cpp:143
+msgctxt "Theme Editor | Sizes | Sizing | label of XY sliders"
+msgid "Frame Padding"
+msgstr "Acolchado del marco"
+
+#: theme.cpp:144
+msgctxt "Theme Editor | Sizes | Sizing | label of XY sliders"
+msgid "Cell Padding"
+msgstr "Relleno de celda"
+
+#: theme.cpp:145
+msgctxt "Theme Editor | Sizes | Sizing | label of XY sliders"
+msgid "Item Spacing"
+msgstr "Espaciado de elementos"
+
+#: theme.cpp:146
+msgctxt "Theme Editor | Sizes | Sizing | label of XY sliders"
+msgid "Inner Item Spacing"
+msgstr "Espaciado interior de elementos"
+
+#: theme.cpp:149
+msgctxt "Theme Editor | Sizes | Sizing | slider label"
+msgid "Scrollbar Size"
+msgstr "Tamaño de la barra de desplazamiento"
+
+#: theme.cpp:150
+msgctxt "Theme Editor | Sizes | Sizing | slider label"
+msgid "Minimum Grabber Size"
+msgstr "Tamaño mínimo del capturador"
+
+#: theme.cpp:151
+msgctxt "Theme Editor | Sizes | Sizing | label of XY sliders"
+msgid "Separator Text Padding"
+msgstr "Relleno de texto separador"
+
+#: theme.cpp:153
+msgctxt "Theme Editor | Sizes | Section label"
+msgid "Borders"
+msgstr "Bordes"
+
+#: theme.cpp:154
+msgctxt "Theme Editor | Sizes | Borders | slider label"
+msgid "Window Border Size"
+msgstr "Tamaño del borde de la ventana"
+
+#: theme.cpp:155
+msgctxt "Theme Editor | Sizes | Borders | slider label"
+msgid "Child Border Size"
+msgstr "Tamaño del borde secundario"
+
+#: theme.cpp:156
+msgctxt "Theme Editor | Sizes | Borders | slider label"
+msgid "Popup Border Size"
+msgstr "Tamaño del borde emergente"
+
+#: theme.cpp:157
+msgctxt "Theme Editor | Sizes | Borders | slider label"
+msgid "Frame Border Size"
+msgstr "Tamaño del borde del marco"
+
+#: theme.cpp:158
+msgctxt "Theme Editor | Sizes | Borders | slider label"
+msgid "Tab Border Size"
+msgstr "Tamaño del borde de la pestaña"
+
+#: theme.cpp:159
+msgctxt "Theme Editor | Sizes | Borders | slider label"
+msgid "Separator Text Border Size"
+msgstr "Tamaño del borde del texto separador"
+
+#: theme.cpp:161
+msgctxt "Theme Editor | Sizes | Section label"
+msgid "Rounding"
+msgstr "Redondeo"
+
+#: theme.cpp:162
+msgctxt "Theme Editor | Sizes | Rounding | slider label"
+msgid "Window Rounding"
+msgstr "Redondeo de ventana"
+
+#: theme.cpp:163
+msgctxt "Theme Editor | Sizes | Rounding | slider label"
+msgid "Child Rounding"
+msgstr "Redondeo infantil"
+
+#: theme.cpp:164
+msgctxt "Theme Editor | Sizes | Rounding | slider label"
+msgid "Frame Rounding"
+msgstr "Redondeo de marco"
+
+#: theme.cpp:165
+msgctxt "Theme Editor | Sizes | Rounding | slider label"
+msgid "Popup Rounding"
+msgstr "Redondeo emergente"
+
+#: theme.cpp:166
+msgctxt "Theme Editor | Sizes | Rounding | slider label"
+msgid "Scrollbar Rounding"
+msgstr "Redondeo de la barra de desplazamiento"
+
+#: theme.cpp:167
+msgctxt "Theme Editor | Sizes | Rounding | slider label"
+msgid "Grabber Rounding"
+msgstr "Redondeo del capturador"
+
+#: theme.cpp:168
+msgctxt "Theme Editor | Sizes | Rounding | slider label"
+msgid "Tab Rounding"
+msgstr "Redondeo de pestañas"
+
+#: theme.cpp:173
+msgctxt "Theme Editor | Tab label"
+msgid "Colors"
+msgstr "Colores"
+
+#: theme.cpp:177
+msgctxt "Theme Editor | Colors | text filter"
+msgid "Filter colors"
+msgstr "Filtrar colores"
+
+#: theme.cpp:180
+msgctxt "Theme Editor | Colors | preview settings radio button"
+msgid "Opaque"
+msgstr "Opaco"
+
+#: theme.cpp:181
+msgctxt "Theme Editor | Colors | preview settings radio button"
+msgid "Alpha"
+msgstr "Alfa"
+
+#: theme.cpp:182
+msgctxt "Theme Editor | Colors | preview settings radio button"
+msgid "Both"
+msgstr "ambas"
+
+#: theme.cpp:193
+msgctxt "Theme Editor | Colors | (Any color) | recoloring checkbox"
+msgid "Match hue preference"
+msgstr "Preferencia de tono coincidente"
+
+#: theme.cpp:230 theme.cpp:233
+msgctxt "Theme Editor | Custom modal dialog title"
+msgid "Load..."
+msgstr "Cargar..."
+
+#: theme.cpp:236
+msgctxt "Theme Editor | Load dialog | Theme selector | filter label"
+msgid "Filter:"
+msgstr "Filtro:"
+
+#: theme.cpp:239
+msgctxt "Theme Editor | Load dialog | Theme selector | label"
+msgid "Available themes..."
+msgstr "Teams disponibles..."
+
+#: theme.cpp:255
+msgctxt "Theme Editor | Load dialog | Load button"
+msgid "Load"
+msgstr "Cargar"
+
+#: theme.cpp:267
+msgctxt "Theme Editor | Load dialog | Cancel button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: theme.cpp:276 theme.cpp:279
+msgctxt "Theme Editor | Custom modal dialog title"
+msgid "Save as..."
+msgstr "Guardar como"
+
+#: theme.cpp:282
+msgctxt "Theme Editor | Save as dialog | Theme selector | filter label"
+msgid "Filter:"
+msgstr "Filtro:"
+
+#: theme.cpp:285
+msgctxt "Theme Editor | Save as dialog | Theme selector | label"
+msgid "Available themes..."
+msgstr "Teams disponibles..."
+
+#: theme.cpp:302
+msgctxt "Theme Editor | Save as dialog | Theme name input label"
+msgid "Theme name: "
+msgstr "Nombre de tema:"
+
+#: theme.cpp:303
+msgctxt "Theme Editor | Save as dialog | Save button"
+msgid "Save"
+msgstr "Ahorrar"
+
+#: theme.cpp:314
+msgctxt "Theme Editor | Save as dialog | Cancel button"
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: theme.cpp:473
+msgctxt "Theme default strings | name"
+msgid "A theme"
+msgstr "Un tema"
+
+#: theme.cpp:474
+msgctxt "Theme default strings | description"
+msgid "(No description)"
+msgstr "(Sin descripción)"
diff --git a/main.cpp b/main.cpp
index fa69035..8f96ddc 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,42 +1,5 @@
-#include "config.h"
-#include "imgui.h"
-#include "imgui_stdlib.h"
-#include "imgui_impl_sdl2.h"
-#include "imgui_impl_opengl3.h"
-#include "file_browser.h"
-#include "playback.h"
-#include "theme.h"
-#include "assets.h"
-#include "IconsForkAwesome.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#if defined(IMGUI_IMPL_OPENGL_ES2)
-#include
-#else
-#include
-#endif
-#include "license.h"
-#include "base85.h"
-static const char* NAME = "Neko Player";
-#ifdef __EMSCRIPTEN__
-#include "../libs/emscripten/emscripten_mainloop_stub.h"
-#endif
-#include
-using namespace std::filesystem;
-using namespace std::numbers;
-using std::string;
-static float accent_color = 280.0;
+#include "main.h"
+#include "assets.h"
string PadZeros(string input, size_t required_length) {
return std::string(required_length - std::min(required_length, input.length()), '0') + input;
@@ -71,185 +34,24 @@ string TimeToString(double time_code, uint8_t min_components = 1) {
}
return output;
}
-
-struct FontData {
- const char* data;
- const ImWchar *ranges;
-};
-
-ImFont *add_font(vector data_vec, int size = 13) {
- ImFont* font = nullptr;
- ImGuiIO& io = ImGui::GetIO();
- for (auto data : data_vec) {
- ImFontConfig font_cfg = ImFontConfig();
- font_cfg.SizePixels = size;
- font_cfg.OversampleH = font_cfg.OversampleV = 1;
- font_cfg.PixelSnapH = true;
- if (font_cfg.SizePixels <= 0.0f)
- font_cfg.SizePixels = 13.0f * 1.0f;
- if (font != nullptr) {
- font_cfg.DstFont = font;
- font_cfg.MergeMode = true;
- }
- //font_cfg.EllipsisChar = (ImWchar)0x0085;
- //font_cfg.GlyphOffset.y = 1.0f * IM_FLOOR(font_cfg.SizePixels / 13.0f); // Add +1 offset per 13 units
-
- const char* ttf_compressed_base85 = data.data;
- const ImWchar* glyph_ranges = data.ranges;
- auto new_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, glyph_ranges);
- if (font == nullptr) font = new_font;
- }
- {
- ImFontConfig config;
- config.MergeMode = true;
- config.GlyphMinAdvanceX = size;
- config.SizePixels = size;
- config.DstFont = font;
- static const ImWchar icon_ranges[] = { ICON_MIN_FK, ICON_MAX_FK, 0 };
- io.Fonts->AddFontFromMemoryCompressedBase85TTF(forkawesome_compressed_data_base85, float(size), &config, icon_ranges);
- }
- return font;
-}
-// Main code
-int main(int, char**)
-{
- setlocale(LC_ALL, "");
- bindtextdomain("neko_player", LOCALE_DIR);
- textdomain("neko_player");
- printf("Loaded locale '%s' from '%s'...\n", CURRENT_LANGUAGE, LOCALE_DIR);
- printf("Locale name: %s\n", _TR_CTX("Language name", "English (United States)"));
+void MainLoop::Init() {
#ifdef PORTALS
g_set_application_name("Neko Player");
#endif
- bool enable_kms = std::getenv("LAP_KMS") != nullptr;
- SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "false");
- SDL_SetHint(SDL_HINT_APP_NAME, NAME);
- // Setup SDL
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0)
- {
- printf("Error: %s\n", SDL_GetError());
- return -1;
- }
- if (std::string(SDL_GetCurrentVideoDriver()) == "KMSDRM") {
- enable_kms = true;
- }
- IMG_Init(IMG_INIT_PNG|IMG_INIT_WEBP);
- const char* prefPath = SDL_GetPrefPath("Catmeow72", NAME);
- Theme::prefPath = prefPath;
-
- // Decide GL+GLSL versions
-#if defined(IMGUI_IMPL_OPENGL_ES2)
- // GL ES 2.0 + GLSL 100
- const char* glsl_version = "#version 100";
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
-#elif defined(__APPLE__)
- // GL 3.2 Core + GLSL 150
- const char* glsl_version = "#version 150";
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
-#else
- // GL 3.0 + GLSL 130
- const char* glsl_version = "#version 130";
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
-#endif
-
- // From 2.0.18: Enable native IME.
-#ifdef SDL_HINT_IME_SHOW_UI
- SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
-#endif
-
- // Create window with graphics context
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
- SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
- int window_width = 475;
- int window_height = 354;
- SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
- SDL_Window* window = SDL_CreateWindow(NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_width, window_height, window_flags);
- SDL_SetWindowMinimumSize(window, window_width, window_height);
- if (enable_kms) {
- SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
- }
- const vector icon_data = DecodeBase85(icon_compressed_data_base85);
- SDL_Surface* icon = IMG_Load_RW(SDL_RWFromConstMem(icon_data.data(), icon_data.size()), 1);
- SDL_SetWindowIcon(window, icon);
- SDL_GLContext gl_context = SDL_GL_CreateContext(window);
- SDL_GL_MakeCurrent(window, gl_context);
-
- // Setup Dear ImGui context
- IMGUI_CHECKVERSION();
- ImGui::CreateContext();
- ImGuiIO& io = ImGui::GetIO(); (void)io;
- io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
- io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
- io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
- //io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
- io.IniFilename = strdup((std::string(prefPath) + "imgui.ini").c_str());
- if (enable_kms) {
- io.MouseDrawCursor = true;
- }
- //io.ConfigViewportsNoAutoMerge = true;
- //io.ConfigViewportsNoTaskBarIcon = true;
-
- //ImGui::StyleColorsLight();
-
- // Setup Platform/Renderer backends
- ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
- ImGui_ImplOpenGL3_Init(glsl_version);
-
- // Load Fonts
- // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
- // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
- // - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
- // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
- // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
- // - Read 'docs/FONTS.md' for more instructions and details.
- // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
- //io.Fonts->AddFontDefault();
- //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
- //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
- //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
- //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
- //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
- //IM_ASSERT(font != nullptr);
- add_font({FontData {notosans_regular_compressed_data_base85, io.Fonts->GetGlyphRangesDefault()}, FontData {notosansjp_regular_compressed_data_base85, io.Fonts->GetGlyphRangesJapanese()}});
- ImFont *title = add_font({FontData {notosans_thin_compressed_data_base85, io.Fonts->GetGlyphRangesDefault()}, FontData {notosansjp_thin_compressed_data_base85, io.Fonts->GetGlyphRangesJapanese()}}, 48);
-
// Our state
- bool show_demo_window = false;
- ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+ show_demo_window = false;
FileBrowser fileDialog(false, ImGuiFileBrowserFlags_NoTitleBar|ImGuiFileBrowserFlags_NoMove|ImGuiFileBrowserFlags_NoResize);
- std::string userdir = std::getenv(
- #ifdef _WIN32
- "UserProfile"
- #else
- "HOME"
- #endif
- );
fileDialog.SetPwd(path(userdir) / path("Music"));
fileDialog.SetWindowSize(window_width, window_height);
//fileDialog.SetWindowPos(0, 0);
- Playback *playback = new Playback();
- float position = 0.0;
- // Main loop
- bool done = false;
- Theme *theme = new Theme(false);
- bool prefs_window = false;
- bool theme_editor = false;
- bool stopped = true;
- bool vsync = false;
- bool about_window = false;
+ playback = new Playback();
+ position = 0.0;
+ prefs_window = false;
+ theme_editor = false;
+ stopped = true;
+ about_window = false;
string lang;
- int framerate = 60;
{
Json::Value config;
std::ifstream stream;
@@ -310,354 +112,280 @@ int main(int, char**)
theme = new Theme(darkPath);
}
}
- SDL_GL_SetSwapInterval(vsync ? 1 : 0);
- theme->Apply(accent_color);
-#ifdef __EMSCRIPTEN__
- // For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
- // You may manually call LoadIniSettingsFromMemory() to load settings from your own storage.
- io.IniFilename = nullptr;
- EMSCRIPTEN_MAINLOOP_BEGIN
-#else
- while (!done)
-#endif
- {/*
- {
- int min_x;
- int min_y;
- SDL_GetWindowMinimumSize(window, &min_x, &min_y);
- int height = ImGui::GetFrameHeightWithSpacing() + ImGui::GetFrameHeight() + (ImGui::GetStyle().WindowPadding.y * 2) + ((ImGui::GetStyle().FramePadding.y * 2) + ImGui::GetFontSize());
- if (height != min_y) {
- min_y = height;
- SDL_SetWindowMinimumSize(window, 475, min_y);
+}
+void MainLoop::GuiFunction() {
+ position = playback->GetPosition();
+ auto dockid = ImGui::DockSpaceOverViewport(nullptr, ImGuiDockNodeFlags_PassthruCentralNode|ImGuiDockNodeFlags_AutoHideTabBar);
+ // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
+ if (show_demo_window)
+ ImGui::ShowDemoWindow(&show_demo_window);
+ if (ImGui::BeginMainMenuBar()) {
+ if (ImGui::BeginMenu(_TRI_CTX(ICON_FK_FILE, "Main menu", "File"))) {
+ if (ImGui::MenuItem(_TRI_CTX(ICON_FK_FOLDER_OPEN, "Main menu | File", "Open"))) {
+ // Set translatable strings here so that they are in the correct language even when it changes at runtime.
+ fileDialog.SetTitle(_TR_CTX("File dialog title", "Open..."));
+ fileDialog.SetTypeFilters(_TR_CTX("File dialog filter name", "Audio files"), { ".wav", ".ogg", ".mp3", ".qoa", ".flac", ".xm", ".mod"});
+ fileDialog.Open();
}
- }*/
- auto next_frame = std::chrono::steady_clock::now() + std::chrono::milliseconds(1000 / framerate);
- position = playback->GetPosition();
- // Poll and handle events (inputs, window resize, etc.)
- // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
- // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
- // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
- // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
- SDL_Event event;
- while (SDL_PollEvent(&event))
- {
- ImGui_ImplSDL2_ProcessEvent(&event);
- if (event.type == SDL_QUIT)
+ if (ImGui::MenuItem(_TRI_CTX(ICON_FK_WINDOW_CLOSE, "Main menu | File", "Quit"))) {
done = true;
- if (event.type == SDL_WINDOWEVENT) {
- if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
- window_width = event.window.data1;
- window_height = event.window.data2;
- //SDL_GetWindowSize(window, &window_width, &window_height);
- }
- if (event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) {
- done = true;
- }
}
+ ImGui::EndMenu();
}
-
- // Start the Dear ImGui frame
- ImGui_ImplOpenGL3_NewFrame();
- ImGui_ImplSDL2_NewFrame();
- ImGui::NewFrame();
- auto dockid = ImGui::DockSpaceOverViewport(nullptr, ImGuiDockNodeFlags_PassthruCentralNode|ImGuiDockNodeFlags_AutoHideTabBar);
- // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
- if (show_demo_window)
- ImGui::ShowDemoWindow(&show_demo_window);
- if (ImGui::BeginMainMenuBar()) {
- if (ImGui::BeginMenu(_TRI_CTX(ICON_FK_FILE, "Main menu", "File"))) {
- if (ImGui::MenuItem(_TRI_CTX(ICON_FK_FOLDER_OPEN, "Main menu | File", "Open"))) {
- // Set translatable strings here so that they are in the correct language even when it changes at runtime.
- fileDialog.SetTitle(_TR_CTX("File dialog title", "Open..."));
- fileDialog.SetTypeFilters(_TR_CTX("File dialog filter name", "Audio files"), { ".wav", ".ogg", ".mp3", ".qoa", ".flac", ".xm", ".mod"});
- fileDialog.Open();
- }
- if (ImGui::MenuItem(_TRI_CTX(ICON_FK_WINDOW_CLOSE, "Main menu | File", "Quit"))) {
- done = true;
- }
- ImGui::EndMenu();
+ if (ImGui::BeginMenu(_TRI_CTX(ICON_FK_SCISSORS,"Main menu", "Edit"))) {
+ if (ImGui::MenuItem(_TRI_CTX(ICON_FK_COG, "Main menu | Edit", "Preferences..."))) {
+ prefs_window = true;
}
- if (ImGui::BeginMenu(_TRI_CTX(ICON_FK_SCISSORS,"Main menu", "Edit"))) {
- if (ImGui::MenuItem(_TRI_CTX(ICON_FK_COG, "Main menu | Edit", "Preferences..."))) {
- prefs_window = true;
- }
- ImGui::EndMenu();
- }
- #ifdef DEBUG
- if (ImGui::BeginMenu(_TRI_CTX(ICON_FK_COG, "Main menu (in debug builds)", "Debug"))) {
- if (ImGui::MenuItem(_TR_CTX("Main menu | Debug", "Show ImGui Demo Window"), nullptr, show_demo_window)) {
- show_demo_window = !show_demo_window;
- }
- ImGui::EndMenu();
- }
- #endif
- if (ImGui::BeginMenu(_TRI_CTX(ICON_FK_INFO_CIRCLE, "Main menu", "Help"))) {
- if (ImGui::MenuItem(_TRI_CTX(ICON_FK_INFO, "Main menu | Help", "About"), nullptr, about_window)) {
- about_window = !about_window;
- }
- ImGui::EndMenu();
- }
- ImGui::EndMainMenuBar();
+ ImGui::EndMenu();
}
+ #ifdef DEBUG
+ if (ImGui::BeginMenu(_TRI_CTX(ICON_FK_COG, "Main menu (in debug builds)", "Debug"))) {
+ if (ImGui::MenuItem(_TR_CTX("Main menu | Debug", "Show ImGui Demo Window"), nullptr, show_demo_window)) {
+ show_demo_window = !show_demo_window;
+ }
+ ImGui::EndMenu();
+ }
+ #endif
+ if (ImGui::BeginMenu(_TRI_CTX(ICON_FK_INFO_CIRCLE, "Main menu", "Help"))) {
+ if (ImGui::MenuItem(_TRI_CTX(ICON_FK_INFO, "Main menu | Help", "About"), nullptr, about_window)) {
+ about_window = !about_window;
+ }
+ ImGui::EndMenu();
+ }
+ ImGui::EndMainMenuBar();
+ }
+ ImGui::SetNextWindowDockID(dockid);
+ ImGui::Begin(_TRI_CTX(ICON_FK_PLAY, "Main window title", "Player"), nullptr, 0);
+ {
+ ImGui::SetCursorPosY(ImGui::GetWindowHeight() - ImGui::GetFrameHeightWithSpacing() - ImGui::GetFrameHeight() - ImGui::GetStyle().WindowPadding.y);
+ if (ImGui::Button(playback->IsPaused() ? ICON_FK_PLAY "##Pause" : ICON_FK_PAUSE "##Pause")) {
+ playback->Pause();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button(ICON_FK_REFRESH "##Restart")) {
+ playback->Seek(0.0);
+ }
+ ImGui::SameLine();
+ const int NEXT_SLIDER_COUNT = 1;
+ ImGui::SetNextItemWidth(-(ImGui::GetFontSize() * (1 + (8 * NEXT_SLIDER_COUNT))) - ((ImGui::GetStyle().ItemSpacing.x + ImGui::GetStyle().FramePadding.x) * (NEXT_SLIDER_COUNT + 1)));
+ uint8_t components = TimeToComponentCount(playback->GetLength());
+ string time_str = TimeToString(position, components);
+ if (ImGui::SliderFloat("##Seek", &position, 0.0f, playback->GetLength(), time_str.c_str(), ImGuiSliderFlags_NoRoundToFormat))
+ playback->Seek(position);
+ ImGui::SameLine();
+ if (ImGui::Button(ICON_FK_STOP "##Stop")) {
+ playback->Stop();
+ }
+ ImGui::SameLine();
+ ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
+ if (ImGui::SliderFloat("##Volume", &playback->volume, 0.0, 100.0, ICON_FK_VOLUME_UP ": %.0f%%")) {
+ playback->Update();
+ }
+ const float items = 3.0f;
+ const float between_items = items - 1.0f;
+ ImGui::PushItemWidth((ImGui::GetWindowWidth() / items) - (ImGui::GetStyle().ItemSpacing.x / (items / between_items)) - ((ImGui::GetStyle().WindowPadding.x / items) * 2.0f));
+ if (ImGui::SliderFloat("##Speed", &playback->speed, 0.25, 4.0, _TR_CTX("Playback controls | slider", "Speed: %.2fx"), ImGuiSliderFlags_Logarithmic)) {
+ playback->Update();
+ }
+ ImGui::SameLine();
+ if (ImGui::SliderFloat("##Tempo", &playback->tempo, 0.25, 4.0, _TR_CTX("Playback controls | slider", "Tempo: %.2fx"), ImGuiSliderFlags_Logarithmic)) {
+ playback->Update();
+ }
+ ImGui::SameLine();
+ if (ImGui::SliderFloat("##Pitch", &playback->pitch, 0.25, 4.0, _TR_CTX("Playback controls | slider", "Pitch: %.2fx"), ImGuiSliderFlags_Logarithmic)) {
+ playback->Update();
+ }
+ ImGui::PopItemWidth();
+ }
+ ImGui::End();
+ if (prefs_window) {
ImGui::SetNextWindowDockID(dockid);
- ImGui::Begin(_TRI_CTX(ICON_FK_PLAY, "Main window title", "Player"), nullptr, 0);
+ ImGui::Begin(_TRI_CTX(ICON_FK_COG, "Window title, window opened by menu item", "Preferences..."), &prefs_window);
{
- ImGui::SetCursorPosY(ImGui::GetWindowHeight() - ImGui::GetFrameHeightWithSpacing() - ImGui::GetFrameHeight() - ImGui::GetStyle().WindowPadding.y);
- if (ImGui::Button(playback->IsPaused() ? ICON_FK_PLAY "##Pause" : ICON_FK_PAUSE "##Pause")) {
- playback->Pause();
+ if (ImGui::Checkbox(_TR_CTX("Preference | VSync checkbox", "Enable VSync"), &vsync)) {
+ SDL_GL_SetSwapInterval(vsync ? 1 : 0);
}
ImGui::SameLine();
- if (ImGui::Button(ICON_FK_REFRESH "##Restart")) {
- playback->Seek(0.0);
+ ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - ImGui::GetStyle().WindowPadding.x);
+ ImGui::SliderInt("##Framerate", &framerate, 10, 480, _TR_CTX("Preferences | Framerate slider", "Max framerate without VSync: %d"));
+ if (ImGui::Button(_TRI_CTX(ICON_FK_MAGIC, "Preference | Related non-preference button", "Theme Editor"), ImVec2(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f), 0))) {
+ theme_editor = true;
}
- ImGui::SameLine();
- const int NEXT_SLIDER_COUNT = 1;
- ImGui::SetNextItemWidth(-(ImGui::GetFontSize() * (1 + (8 * NEXT_SLIDER_COUNT))) - ((ImGui::GetStyle().ItemSpacing.x + ImGui::GetStyle().FramePadding.x) * (NEXT_SLIDER_COUNT + 1)));
- uint8_t components = TimeToComponentCount(playback->GetLength());
- string time_str = TimeToString(position, components);
- if (ImGui::SliderFloat("##Seek", &position, 0.0f, playback->GetLength(), time_str.c_str(), ImGuiSliderFlags_NoRoundToFormat))
- playback->Seek(position);
- ImGui::SameLine();
- if (ImGui::Button(ICON_FK_STOP "##Stop")) {
- playback->Stop();
- }
- ImGui::SameLine();
- ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
- if (ImGui::SliderFloat("##Volume", &playback->volume, 0.0, 100.0, ICON_FK_VOLUME_UP ": %.0f%%")) {
- playback->Update();
- }
- const float items = 3.0f;
- const float between_items = items - 1.0f;
- ImGui::PushItemWidth((ImGui::GetWindowWidth() / items) - (ImGui::GetStyle().ItemSpacing.x / (items / between_items)) - ((ImGui::GetStyle().WindowPadding.x / items) * 2.0f));
- if (ImGui::SliderFloat("##Speed", &playback->speed, 0.25, 4.0, _TR_CTX("Playback controls | slider", "Speed: %.2fx"), ImGuiSliderFlags_Logarithmic)) {
- playback->Update();
- }
- ImGui::SameLine();
- if (ImGui::SliderFloat("##Tempo", &playback->tempo, 0.25, 4.0, _TR_CTX("Playback controls | slider", "Tempo: %.2fx"), ImGuiSliderFlags_Logarithmic)) {
- playback->Update();
- }
- ImGui::SameLine();
- if (ImGui::SliderFloat("##Pitch", &playback->pitch, 0.25, 4.0, _TR_CTX("Playback controls | slider", "Pitch: %.2fx"), ImGuiSliderFlags_Logarithmic)) {
- playback->Update();
- }
- ImGui::PopItemWidth();
- }
- ImGui::End();
- if (prefs_window) {
- ImGui::SetNextWindowDockID(dockid);
- ImGui::Begin(_TRI_CTX(ICON_FK_COG, "Window title, window opened by menu item", "Preferences..."), &prefs_window);
- {
- if (ImGui::Checkbox(_TR_CTX("Preference | VSync checkbox", "Enable VSync"), &vsync)) {
- SDL_GL_SetSwapInterval(vsync ? 1 : 0);
+ static bool override_lang = lang != DEFAULT_LANG;
+ if (ImGui::Checkbox(_TR_CTX("Preference | override enable checkbox", "Override language"), &override_lang)) {
+ if (!override_lang) {
+ lang = DEFAULT_LANG;
+ SET_LANG(lang.c_str());
}
+ }
+ if (override_lang) {
ImGui::SameLine();
- ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - ImGui::GetStyle().WindowPadding.x);
- ImGui::SliderInt("##Framerate", &framerate, 10, 480, _TR_CTX("Preferences | Framerate slider", "Max framerate without VSync: %d"));
- if (ImGui::Button(_TRI_CTX(ICON_FK_MAGIC, "Preference | Related non-preference button", "Theme Editor"), ImVec2(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f), 0))) {
- theme_editor = true;
+ ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - (ImGui::GetFontSize()) - ((ImGui::GetStyle().ItemSpacing.x + (ImGui::GetStyle().FramePadding.x * 2.0f))) - (ImGui::GetStyle().WindowPadding.x));
+ ImGui::InputText("##LanguageOverrideTextBox", &lang);
+ ImGui::SameLine();
+ if (ImGui::Button(ICON_FK_CHECK)) {
+ SET_LANG(lang.c_str());
}
- static bool override_lang = lang != DEFAULT_LANG;
- if (ImGui::Checkbox(_TR_CTX("Preference | override enable checkbox", "Override language"), &override_lang)) {
- if (!override_lang) {
- lang = DEFAULT_LANG;
- SET_LANG(lang.c_str());
- }
- }
- if (override_lang) {
- ImGui::SameLine();
- ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - (ImGui::GetFontSize()) - ((ImGui::GetStyle().ItemSpacing.x + (ImGui::GetStyle().FramePadding.x * 2.0f))) - (ImGui::GetStyle().WindowPadding.x));
- ImGui::InputText("##LanguageOverrideTextBox", &lang);
- ImGui::SameLine();
- if (ImGui::Button(ICON_FK_CHECK)) {
- SET_LANG(lang.c_str());
- }
- }
- static string filter = "";
- ImGui::Text(_TR_CTX("Preference | Theme selector | Filter label", "Filter:")); ImGui::SameLine();
- ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - ImGui::GetStyle().WindowPadding.x);
- ImGui::InputText("##FilterInput", &filter);
- ImGui::Text(_TR_CTX("Preferences | Theme selector | Selector label", "Select a theme..."));
- ImVec2 ChildSize = ImVec2(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f), -ImGui::GetFrameHeightWithSpacing());
- if (ImGui::BeginChildFrame(ImGui::GetID("##ThemesContainer"), ChildSize)) {
- ImVec2 TableSize = ImVec2(0, 0);
- if (ImGui::BeginTable("##Themes", 2, ImGuiTableFlags_SizingFixedFit|ImGuiTableFlags_NoSavedSettings|ImGuiTableFlags_ScrollY, TableSize)) {
- // Text in TableSetupColumn calls not translated because they're not visible to the user.
- ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
- ImGui::TableSetupColumn("Remove", 0);
- for (auto themePath : Theme::availableThemes) {
- string themeStem = themePath.stem().string();
- if (themeStem.starts_with(filter)) {
- ImGui::TableNextRow();
- ImGui::TableSetColumnIndex(0);
- const bool is_selected = themePath == theme->file_path;
- if (ImGui::Selectable((theme->themeStrings[themePath].name + string(" (") + string(themeStem) + string(")")).c_str(), is_selected, 0)) {
- delete theme;
- theme = new Theme(themePath);
- theme->Apply(accent_color);
+ }
+ static string filter = "";
+ ImGui::Text(_TR_CTX("Preference | Theme selector | Filter label", "Filter:")); ImGui::SameLine();
+ ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - ImGui::GetStyle().WindowPadding.x);
+ ImGui::InputText("##FilterInput", &filter);
+ ImGui::Text(_TR_CTX("Preferences | Theme selector | Selector label", "Select a theme..."));
+ ImVec2 ChildSize = ImVec2(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f), -ImGui::GetFrameHeightWithSpacing());
+ if (ImGui::BeginChildFrame(ImGui::GetID("##ThemesContainer"), ChildSize)) {
+ ImVec2 TableSize = ImVec2(0, 0);
+ if (ImGui::BeginTable("##Themes", 2, ImGuiTableFlags_SizingFixedFit|ImGuiTableFlags_NoSavedSettings|ImGuiTableFlags_ScrollY, TableSize)) {
+ // Text in TableSetupColumn calls not translated because they're not visible to the user.
+ ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
+ ImGui::TableSetupColumn("Remove", 0);
+ for (auto themePath : Theme::availableThemes) {
+ string themeStem = themePath.stem().string();
+ if (themeStem.starts_with(filter)) {
+ ImGui::TableNextRow();
+ ImGui::TableSetColumnIndex(0);
+ const bool is_selected = themePath == theme->file_path;
+ if (ImGui::Selectable((theme->themeStrings[themePath].name + string(" (") + string(themeStem) + string(")")).c_str(), is_selected, 0)) {
+ delete theme;
+ theme = new Theme(themePath);
+ theme->Apply(accent_color);
+ break;
+ }
+ if (is_selected) {
+ ImGui::SetItemDefaultFocus();
+ } else {
+ ImGui::TableSetColumnIndex(1);
+ if (ImGui::SmallButton((string(ICON_FK_WINDOW_CLOSE "##") + themeStem).c_str())) {
+ std::filesystem::remove(themePath);
+ Theme::updateAvailableThemes();
break;
}
- if (is_selected) {
- ImGui::SetItemDefaultFocus();
- } else {
- ImGui::TableSetColumnIndex(1);
- if (ImGui::SmallButton((string(ICON_FK_WINDOW_CLOSE "##") + themeStem).c_str())) {
- std::filesystem::remove(themePath);
- Theme::updateAvailableThemes();
- break;
- }
- }
}
}
- ImGui::EndTable();
}
- }
- ImGui::EndChildFrame();
- ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2));
- if (ImGui::SliderFloat("##AccentColor", &accent_color, 0.0, 360.0, _TR_CTX("Preference | Accent hue slider, range 0-360 from HSV algorithm hue component", "Accent color hue: %.0f°"), ImGuiSliderFlags_NoRoundToFormat)) {
- theme->Apply(accent_color);
- }
- }
- ImGui::End();
- }
- if (about_window) {
- ImGui::SetNextWindowDockID(dockid);
- if (ImGui::Begin(_TRI_CTX(ICON_FK_INFO, "Window title, window opened by menu item", "About and Licenses"), &about_window)) {
- ImGui::PushFont(title);
- static const string APP_NAME_STR = _TR_CTX("Application name - Japanese word should remain Japanese and stay the same when translating for stylistic purposes.", "ねこ Player");
- ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, 0.0f, APP_NAME_STR.c_str()).x) / 2.0f);
- ImGui::Text(APP_NAME_STR.c_str());
- ImGui::PopFont();
- static const string APP_NAME_ROMANIZED = _TR_CTX("Application name - Japanese word should be converted to the translated language's characters. Use a string with only a single underscore to disable for Japanese.", "(Neko Player)");
- if (APP_NAME_ROMANIZED != "_") {
- ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, 0.0f, APP_NAME_ROMANIZED.c_str()).x) / 2.0f);
- ImGui::Text(APP_NAME_ROMANIZED.c_str());
- }
- static const string VER_STRING = _TR_CTX("Version string format specifier", "Version ") + string(TAG) + _TRS_CTX("Suffix to the version string in the about window, if needed", " ");
- ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, 0.0f, VER_STRING.c_str()).x) / 2.0f);
- ImGui::Text(VER_STRING.c_str());
- ImGui::NewLine();
- static vector projects = {
- LicenseData(APP_NAME_STR, "MIT"),
- LicenseData(_TR_CTX("Library name", "SDL Mixer X"), "Zlib"),
- LicenseData(_TR_CTX("Library name", "JsonCpp"), "MIT"),
- LicenseData(_TR_CTX("Library name", "SoundTouch"), "LGPL-2.1-only"),
- LicenseData(_TR_CTX("Library name", "libintl"), "LGPL-2.1-only"),
- LicenseData(_TR_CTX("Library name", "Dear ImGui"), "MIT"),
- LicenseData(_TR_CTX("Library name", "imgui-filebrowser"), "MIT"),
- #ifdef PORTALS
- LicenseData(_TR_CTX("Library name", "libportal"), "LGPL-3.0-only"), // Only include the license if it applies.
- #endif
- LicenseData(_TR_CTX("Library name", "Noto Sans"), "OFL-1.1-RFN"),
- LicenseData(_TR_CTX("Library name", "Fork Awesome"), "OFL-1.1-RFN"),
- LicenseData(_TR_CTX("Library name", "IconFontCppHeaders"), "Zlib")
- };
- // Do this in an inner scope so that 'i' isn't accidentally used outside it,
- // and so that 'i' can refer to another variable such as in a for loop.
- {
- int i = 0;
- // Use a variable instead of hardcoding so that a #ifdef can change the indices later on.
- LOAD_LICENSE(projects[i], nekoplayer); i++;
- LOAD_LICENSE(projects[i], sdl_mixer_x); i++;
- LOAD_LICENSE(projects[i], jsoncpp); i++;
- LOAD_LICENSE(projects[i], soundtouch); i++;
- LOAD_LICENSE(projects[i], libintl); i++;
- LOAD_LICENSE(projects[i], imgui); i++;
- LOAD_LICENSE(projects[i], imgui_filebrowser); i++;
- #ifdef PORTALS
- LOAD_LICENSE(projects[i], libportal); i++;
- #endif
- LOAD_LICENSE(projects[i], notosans); i++;
- LOAD_LICENSE(projects[i], forkawesome); i++;
- LOAD_LICENSE(projects[i], icnfntcpphdrs); i++;
- }
- // Left
- static LicenseData selected = projects[0];
- {
- ImGui::BeginGroup();
- ImGui::TextUnformatted(_TR_CTX("Project selector label.", "Project"));
- // Next string is internal.
- ImGui::BeginChild("project selector", ImVec2(150, 0), true);
- for (auto project : projects)
- {
- if (ImGui::Selectable(project.Project.c_str(), selected.Project == project.Project))
- selected = project;
- }
- ImGui::EndChild();
- ImGui::EndGroup();
- }
- ImGui::SameLine();
- // Right
- {
- ImGui::BeginGroup();
- ImGui::TextUnformatted(_TR_CTX("License viewer label", "License"));
- // Next string is internal.
- ImGui::BeginChild("license view", ImVec2(0, 0), true); // *don't* leave room for the nonexistant line below us!
- ImGui::Text(_TR_CTX("License viewer | information above license - string 1: selected project, string 2: SPDX license identifier", "%s: %s"), selected.Project.c_str(), selected.Spdx.c_str());
- ImGui::Separator();
- ImGui::TextWrapped("%s", selected.LicenseContents.c_str());
- ImGui::EndChild();
- ImGui::EndGroup();
+ ImGui::EndTable();
}
}
- ImGui::End();
- }
- if (theme_editor) {
- Theme::ShowEditor(&theme_editor, theme, dockid, window_width, window_height);
- theme->Apply(accent_color);
- }
- if (fileDialog.IsOpened()) {
- fileDialog.SetWindowSize(window_width, window_height);
- fileDialog.SetWindowPos(0, 0);
- }
- fileDialog.Display();
-
- if (fileDialog.HasSelected()) {
- playback->Start(fileDialog.GetSelected().string());
- SDL_SetWindowTitle(window, (fileDialog.GetSelected().filename().replace_extension("").string() + std::string(" - ") + std::string(NAME)).c_str());
- fileDialog.ClearSelected();
- }
- if (playback->IsStopped() && !stopped) {
- SDL_SetWindowTitle(window, NAME);
- }
- // Rendering
- ImGui::Render();
- glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
- glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
- glClear(GL_COLOR_BUFFER_BIT);
- ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
-
- // Update and Render additional Platform Windows
- // (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere.
- // For this specific demo app we could also call SDL_GL_MakeCurrent(window, gl_context) directly)
- if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
- {
- SDL_Window* backup_current_window = SDL_GL_GetCurrentWindow();
- SDL_GLContext backup_current_context = SDL_GL_GetCurrentContext();
- ImGui::UpdatePlatformWindows();
- ImGui::RenderPlatformWindowsDefault();
- SDL_GL_MakeCurrent(backup_current_window, backup_current_context);
- }
-
- SDL_GL_SwapWindow(window);
- if (!vsync) {
- std::this_thread::sleep_until(next_frame);
+ ImGui::EndChildFrame();
+ ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2));
+ if (ImGui::SliderFloat("##AccentColor", &accent_color, 0.0, 360.0, _TR_CTX("Preference | Accent hue slider, range 0-360 from HSV algorithm hue component", "Accent color hue: %.0f°"), ImGuiSliderFlags_NoRoundToFormat)) {
+ theme->Apply(accent_color);
+ }
}
+ ImGui::End();
}
- // Cleanup
-#ifdef __EMSCRIPTEN__
- EMSCRIPTEN_MAINLOOP_END;
-#endif
+ if (about_window) {
+ ImGui::SetNextWindowDockID(dockid);
+ if (ImGui::Begin(_TRI_CTX(ICON_FK_INFO, "Window title, window opened by menu item", "About and Licenses"), &about_window)) {
+ ImGui::PushFont(title);
+ static const string APP_NAME_STR = _TR_CTX("Application name - Japanese word should remain Japanese and stay the same when translating for stylistic purposes.", "ねこ Player");
+ ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, 0.0f, APP_NAME_STR.c_str()).x) / 2.0f);
+ ImGui::Text(APP_NAME_STR.c_str());
+ ImGui::PopFont();
+ static const string APP_NAME_ROMANIZED = _TR_CTX("Application name - Japanese word should be converted to the translated language's characters. Use a string with only a single underscore to disable for Japanese.", "(Neko Player)");
+ if (APP_NAME_ROMANIZED != "_") {
+ ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, 0.0f, APP_NAME_ROMANIZED.c_str()).x) / 2.0f);
+ ImGui::Text(APP_NAME_ROMANIZED.c_str());
+ }
+ static const string VER_STRING = _TR_CTX("Version string format specifier", "Version ") + string(TAG) + _TRS_CTX("Suffix to the version string in the about window, if needed", " ");
+ ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, 0.0f, VER_STRING.c_str()).x) / 2.0f);
+ ImGui::Text(VER_STRING.c_str());
+ ImGui::NewLine();
+ static vector projects = {
+ LicenseData(APP_NAME_STR, "MIT"),
+ LicenseData(_TR_CTX("Library name", "SDL Mixer X"), "Zlib"),
+ LicenseData(_TR_CTX("Library name", "JsonCpp"), "MIT"),
+ LicenseData(_TR_CTX("Library name", "SoundTouch"), "LGPL-2.1-only"),
+ LicenseData(_TR_CTX("Library name", "libintl"), "LGPL-2.1-only"),
+ LicenseData(_TR_CTX("Library name", "Dear ImGui"), "MIT"),
+ LicenseData(_TR_CTX("Library name", "imgui-filebrowser"), "MIT"),
+ #ifdef PORTALS
+ LicenseData(_TR_CTX("Library name", "libportal"), "LGPL-3.0-only"), // Only include the license if it applies.
+ #endif
+ LicenseData(_TR_CTX("Library name", "Noto Sans"), "OFL-1.1-RFN"),
+ LicenseData(_TR_CTX("Library name", "Fork Awesome"), "OFL-1.1-RFN"),
+ LicenseData(_TR_CTX("Library name", "IconFontCppHeaders"), "Zlib")
+ };
+ // Do this in an inner scope so that 'i' isn't accidentally used outside it,
+ // and so that 'i' can refer to another variable such as in a for loop.
+ {
+ int i = 0;
+ // Use a variable instead of hardcoding so that a #ifdef can change the indices later on.
+ LOAD_LICENSE(projects[i], nekoplayer); i++;
+ LOAD_LICENSE(projects[i], sdl_mixer_x); i++;
+ LOAD_LICENSE(projects[i], jsoncpp); i++;
+ LOAD_LICENSE(projects[i], soundtouch); i++;
+ LOAD_LICENSE(projects[i], libintl); i++;
+ LOAD_LICENSE(projects[i], imgui); i++;
+ LOAD_LICENSE(projects[i], imgui_filebrowser); i++;
+ #ifdef PORTALS
+ LOAD_LICENSE(projects[i], libportal); i++;
+ #endif
+ LOAD_LICENSE(projects[i], notosans); i++;
+ LOAD_LICENSE(projects[i], forkawesome); i++;
+ LOAD_LICENSE(projects[i], icnfntcpphdrs); i++;
+ }
+ // Left
+ static LicenseData selected = projects[0];
+ {
+ ImGui::BeginGroup();
+ ImGui::TextUnformatted(_TR_CTX("Project selector label.", "Project"));
+ // Next string is internal.
+ ImGui::BeginChild("project selector", ImVec2(150, 0), true);
+ for (auto project : projects)
+ {
+ if (ImGui::Selectable(project.Project.c_str(), selected.Project == project.Project))
+ selected = project;
+ }
+ ImGui::EndChild();
+ ImGui::EndGroup();
+ }
+ ImGui::SameLine();
+ // Right
+ {
+ ImGui::BeginGroup();
+ ImGui::TextUnformatted(_TR_CTX("License viewer label", "License"));
+ // Next string is internal.
+ ImGui::BeginChild("license view", ImVec2(0, 0), true); // *don't* leave room for the nonexistant line below us!
+ ImGui::Text(_TR_CTX("License viewer | information above license - string 1: selected project, string 2: SPDX license identifier", "%s: %s"), selected.Project.c_str(), selected.Spdx.c_str());
+ ImGui::Separator();
+ ImGui::TextWrapped("%s", selected.LicenseContents.c_str());
+ ImGui::EndChild();
+ ImGui::EndGroup();
+ }
+ }
+ ImGui::End();
+ }
+ // Display the theme editor.
+ if (theme_editor) {
+ Theme::ShowEditor(&theme_editor, theme, dockid, window_width, window_height);
+ // Immediately apply any changes made in the theme editor.
+ theme->Apply(accent_color);
+ }
+ if (fileDialog.IsOpened()) {
+ // Make the fallback file dialog fill the window.
+ fileDialog.SetWindowSize(window_width, window_height);
+ fileDialog.SetWindowPos(0, 0);
+ }
+ // Display the file dialog
+ fileDialog.Display();
+
+ // Load a new file when it has been selected.
+ if (fileDialog.HasSelected()) {
+ playback->Start(fileDialog.GetSelected().string());
+ // Update the window title.
+ SetWindowTitle((fileDialog.GetSelected().filename().replace_extension("").string() + std::string(" - ") + std::string(NAME)).c_str());
+ // Make sure to not load the file unnecessarily.
+ fileDialog.ClearSelected();
+ }
+ if (playback->IsStopped() && !stopped) {
+ // Update the window title to reflect that no file is playing.
+ SetWindowTitle(NAME);
+ }
+}
+void MainLoop::Deinit() {
delete playback;
- // Cleanup
- ImGui_ImplOpenGL3_Shutdown();
- ImGui_ImplSDL2_Shutdown();
- ImGui::DestroyContext();
-
- SDL_GL_DeleteContext(gl_context);
- SDL_DestroyWindow(window);
- IMG_Quit();
- SDL_Quit();
{
Json::Value config;
std::ofstream stream;
@@ -679,6 +407,13 @@ int main(int, char**)
stream << config;
stream.close();
}
- free((void*)io.IniFilename);
- return 0;
+}
+MainLoop::MainLoop() : RendererBackend() {
+
+}
+// Main code
+int main(int, char**)
+{
+ MainLoop loop;
+ return loop.Run();
}
diff --git a/main.h b/main.h
new file mode 100644
index 0000000..3965763
--- /dev/null
+++ b/main.h
@@ -0,0 +1,53 @@
+#pragma once
+#include "RendererBackend.h"
+#include "config.h"
+#include "file_browser.h"
+#include "playback.h"
+#include "theme.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+#include
+#else
+#include
+#endif
+#include "license.h"
+#include "base85.h"
+#include "IconsForkAwesome.h"
+#include "imgui.h"
+#include "imgui_stdlib.h"
+#include "translation.h"
+#ifdef __EMSCRIPTEN__
+#include "../libs/emscripten/emscripten_mainloop_stub.h"
+#endif
+using namespace std::filesystem;
+using namespace std::numbers;
+using std::string;
+class MainLoop : public RendererBackend {
+ bool show_demo_window = false;
+ FileBrowser fileDialog = FileBrowser(false);
+ std::string userdir;
+ Playback *playback;
+ float position = 0.0;
+ bool prefs_window = false;
+ bool theme_editor = false;
+ bool about_window = false;
+ bool stopped = true;
+ public:
+ void Init() override;
+ void GuiFunction() override;
+ void Deinit() override;
+ MainLoop();
+};
\ No newline at end of file
diff --git a/meson.build b/meson.build
index a586067..b808d2a 100644
--- a/meson.build
+++ b/meson.build
@@ -55,6 +55,7 @@ endif
srcs = [
'main.cpp',
+ 'RendererBackend.cpp',
'playback.cpp',
'theme.cpp',
'file_browser.cpp',