mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 18:38:55 +00:00
250 lines
7.7 KiB
C++
250 lines
7.7 KiB
C++
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
#include <map>
|
|
#include <vector>
|
|
#include <SDL2/SDL.h>
|
|
#include "glad.h"
|
|
#if defined(__APPLE__)
|
|
#define USE_GLES3
|
|
#include <OpenGL/gl3.h>
|
|
#endif
|
|
#include "FreeSans.h"
|
|
#include "audio_sdl.h"
|
|
#include "decode.h"
|
|
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
#include "stb_image.h"
|
|
//#define NK_INCLUDE_FIXED_TYPES
|
|
//#define NK_INCLUDE_STANDARD_IO
|
|
#define NK_INCLUDE_STANDARD_VARARGS
|
|
#define NK_INCLUDE_DEFAULT_ALLOCATOR
|
|
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
|
|
#define NK_INCLUDE_FONT_BAKING
|
|
#define NK_INCLUDE_DEFAULT_FONT
|
|
#define NK_IMPLEMENTATION
|
|
#define NK_SDL_GL3_IMPLEMENTATION
|
|
#include "nuklear.h"
|
|
#include "nuklear_sdl_gl3.h"
|
|
#include "style.h"
|
|
|
|
#define MAX_VERTEX_BUFFER 512 * 1024
|
|
#define MAX_ELEMENT_BUFFER 128 * 1024
|
|
|
|
#ifdef USE_GLES3
|
|
static PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
|
|
#endif
|
|
static void *_ctx;
|
|
static SDL_Window *_mainWindow;
|
|
static SDL_GLContext _mainContext;
|
|
static std::map<std::string, int> _previews;
|
|
static std::vector<std::string> _playlist;
|
|
static void *_render;
|
|
static bool _closeNextFrame;
|
|
decoder _dec;
|
|
|
|
static int load_image(const stbi_uc *data, int len)
|
|
{
|
|
GLuint tex;
|
|
int width, height, n;
|
|
unsigned char *pix = stbi_load_from_memory(data, len, &width, &height, &n, 4);
|
|
if (!pix)
|
|
return 0;
|
|
glGenTextures(1, &tex);
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
|
#ifndef USE_GLES3
|
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
|
#endif
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
|
|
#ifdef USE_GLES3
|
|
if (glGenerateMipmap)
|
|
glGenerateMipmap(GL_TEXTURE_2D);
|
|
#endif
|
|
return (int)tex;
|
|
}
|
|
|
|
static void close()
|
|
{
|
|
nk_sdl_shutdown();
|
|
SDL_GL_MakeCurrent(_mainWindow, _mainContext);
|
|
for (auto it = _previews.begin(); it != _previews.end(); it++)
|
|
{
|
|
GLuint tex = it->second;
|
|
glDeleteTextures(1, &tex);
|
|
}
|
|
SDL_GL_DeleteContext(_mainContext);
|
|
SDL_DestroyWindow(_mainWindow);
|
|
SDL_Quit();
|
|
}
|
|
|
|
static int init()
|
|
{
|
|
SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
|
|
if (!SDL_Init(SDL_INIT_VIDEO) < 0)
|
|
{
|
|
printf("error: sdl2 video init failed %s\n", SDL_GetError());
|
|
return false;
|
|
}
|
|
#ifdef USE_GLES3
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
// SDL_GL_SetAttribute(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
|
#else
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
|
#endif
|
|
_mainWindow = SDL_CreateWindow("minimp3", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 600, SDL_WINDOW_RESIZABLE|SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI);
|
|
if (!_mainWindow)
|
|
{
|
|
printf("error: create window failed: %s\n", SDL_GetError());
|
|
fflush(stdout);
|
|
exit(1);
|
|
}
|
|
if((_mainContext = SDL_GL_CreateContext(_mainWindow)) == NULL)
|
|
{
|
|
printf("error: create context failed: %s\n", SDL_GetError());
|
|
fflush(stdout);
|
|
exit(1);
|
|
}
|
|
SDL_GL_MakeCurrent(_mainWindow, _mainContext);
|
|
|
|
#ifdef USE_GLES3
|
|
glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)SDL_GL_GetProcAddress("glGenerateMipmap");
|
|
#endif
|
|
|
|
gladLoadGL();
|
|
_ctx = (void*)nk_sdl_init(_mainWindow);
|
|
struct nk_font_atlas *atlas;
|
|
struct nk_font_config fconfig = nk_font_config(20);
|
|
fconfig.range = nk_font_cyrillic_glyph_ranges();
|
|
nk_sdl_font_stash_begin(&atlas);
|
|
atlas->default_font = nk_font_atlas_add_from_memory(atlas, FreeSans, FreeSansLen, 20, &fconfig);;
|
|
nk_sdl_font_stash_end();
|
|
return true;
|
|
}
|
|
|
|
static void tick()
|
|
{
|
|
nk_context *ctx = (nk_context *)_ctx;
|
|
|
|
float bg[4];
|
|
nk_color_fv(bg, nk_rgb(28,48,62));
|
|
int width, height, i;
|
|
SDL_GL_GetDrawableSize(_mainWindow, &width, &height);
|
|
glViewport(0, 0, width, height);
|
|
glClearColor(bg[0], bg[1], bg[2], bg[3]);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
// Run events
|
|
SDL_Event event;
|
|
nk_input_begin(ctx);
|
|
while(SDL_PollEvent(&event))
|
|
{
|
|
nk_sdl_handle_event(&event);
|
|
|
|
if(event.type == SDL_QUIT)
|
|
_closeNextFrame = true;
|
|
}
|
|
nk_input_end(ctx);
|
|
|
|
if (nk_begin(ctx, "Player", nk_rect(0, 0, width, height), 0))
|
|
{
|
|
nk_layout_row_dynamic(ctx, 25, 2);
|
|
nk_label(ctx, "Theme:", NK_TEXT_LEFT);
|
|
static int _cur_theme;
|
|
static const char *themes[] = { "black", "white", "red", "blue", "dark"};
|
|
int res = nk_combo(ctx, themes, sizeof(themes)/sizeof(themes[0]), _cur_theme, 25, nk_vec2(200,200));
|
|
if (_cur_theme != res)
|
|
set_style(ctx, (theme)res);
|
|
_cur_theme = res;
|
|
|
|
nk_layout_row_dynamic(ctx, 25, 2);
|
|
nk_label(ctx, "Audio Playback Device:", NK_TEXT_LEFT);
|
|
static int _cur_apdevice;
|
|
const char **devs = (const char**)alloca(1*sizeof(char*));
|
|
//for (i = 0; i < ; i++)
|
|
// devs[i] = ;
|
|
devs[0] = "default";
|
|
res = nk_combo(ctx, devs, 1, _cur_apdevice, 25, nk_vec2(200,200));
|
|
//if (_cur_apdevice != res)
|
|
// change_device(res);
|
|
_cur_apdevice = res;
|
|
|
|
nk_layout_row_dynamic(ctx, 25, 1);
|
|
nk_button_push_behavior(ctx, NK_BUTTON_DEFAULT2);
|
|
static int _play_state, _selected;
|
|
if (!_play_state)
|
|
{
|
|
if (nk_button_label(ctx, "Play") && _selected < (int)_playlist.size())
|
|
{
|
|
_play_state = 1;
|
|
sdl_audio_set_dec(_render, 0);
|
|
open_dec(&_dec, _playlist[_selected].c_str());
|
|
sdl_audio_set_dec(_render, &_dec);
|
|
}
|
|
} else
|
|
{
|
|
if (nk_button_label(ctx, "Stop"))
|
|
{
|
|
_play_state = 0;
|
|
sdl_audio_set_dec(_render, 0);
|
|
//stop();
|
|
}
|
|
}
|
|
nk_button_pop_behavior(ctx);
|
|
static size_t progress = 0;
|
|
uint64_t cur_sample = _dec.mp3d.cur_sample;
|
|
progress = cur_sample;
|
|
nk_progress(ctx, &progress, _dec.mp3d.samples, NK_MODIFIABLE);
|
|
if (progress != cur_sample)
|
|
{
|
|
SDL_PauseAudio(1);
|
|
mp3dec_ex_seek(&_dec.mp3d, progress);
|
|
SDL_PauseAudio(0);
|
|
}
|
|
|
|
if (nk_tree_push(ctx, NK_TREE_TAB, "Playlist", NK_MAXIMIZED))
|
|
{
|
|
for (i = 0; i < (int)_playlist.size(); i++)
|
|
{
|
|
nk_layout_row_begin(ctx, NK_DYNAMIC, 32, 2);
|
|
nk_layout_row_push(ctx, 0.1f);
|
|
auto av = _previews.find(_playlist[i].c_str());
|
|
if (av != _previews.end())
|
|
{
|
|
nk_image(ctx, nk_image_id(av->second));
|
|
}
|
|
nk_layout_row_push(ctx, 0.9f);
|
|
const char *name = _playlist[i].c_str();
|
|
if (nk_select_label(ctx, name, NK_TEXT_LEFT, _selected == i))
|
|
_selected = i;
|
|
nk_layout_row_end(ctx);
|
|
}
|
|
nk_tree_pop(ctx);
|
|
}
|
|
}
|
|
nk_end(ctx);
|
|
nk_sdl_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER);
|
|
SDL_GL_SwapWindow(_mainWindow);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
_closeNextFrame = false;
|
|
sdl_audio_init(&_render, 44100, 2, 0, 0);
|
|
init();
|
|
for (int i = 1; i < argc; i++)
|
|
_playlist.push_back(argv[i]);
|
|
while (!_closeNextFrame)
|
|
{
|
|
tick();
|
|
}
|
|
close();
|
|
sdl_audio_release(_render);
|
|
}
|