diff --git a/CMakeLists.txt b/CMakeLists.txt index 02bc748..f61f531 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,10 +24,15 @@ set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 17) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}) target_compile_definitions(${PROJECT_NAME} PRIVATE ${RENDER_DRIVER}) +find_package(PkgConfig REQUIRED) +pkg_search_module(MPV REQUIRED mpv) +target_include_directories(xplayer PRIVATE ${MPV_INCLUDE_DIRS}) + if (NINTENDO_SWITCH) target_link_libraries(${PROJECT_NAME} PRIVATE glfw3 glapi drm_nouveau nx m + ${MPV_LINK_LIBRARIES} ) nx_generate_nacp(${PROJECT_NAME}.nacp NAME ${PROJECT_NAME} AUTHOR dragonflylee VERSION 1.0) nx_create_nro(${PROJECT_NAME} ICON ${CMAKE_SOURCE_DIR}/icon.jpg NACP ${PROJECT_NAME}.nacp) @@ -36,6 +41,6 @@ else () if (MINGW) set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") endif () - target_link_libraries(${PROJECT_NAME} PRIVATE glfw) + target_link_libraries(${PROJECT_NAME} PRIVATE glfw ${MPV_LINK_LIBRARIES}) endif () diff --git a/Makefile b/Makefile index 5a0cd1e..883466d 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,8 @@ CFLAGS += $(INCLUDE) -D__SWITCH__ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -LIBS := -lglfw3 -lEGL -lglapi -ldrm_nouveau -lm -lnx +LIBS := `$(PREFIX)pkg-config mpv --libs` \ + -lglfw3 -lEGL -lglapi -ldrm_nouveau -lm -lnx #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/Makefile.mingw b/Makefile.mingw index 037a5af..7de3b91 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -11,7 +11,7 @@ OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) INCLUDES := -I$(CURDIR)/imgui CFLAGS := -O2 -Wall $(INCLUDES) `pkg-config --cflags glfw3` CXXFLAGS := $(CFLAGS) -std=c++17 -LDFLAGS := `pkg-config glfw3 --libs` -lgdi32 +LDFLAGS := `pkg-config mpv glfw3 --libs` -lgdi32 all: $(TARGET) diff --git a/src/main.cpp b/src/main.cpp index 6e4b12b..b2df83f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,9 @@ #include #include +#include +#include + #define GLFW_INCLUDE_NONE #include @@ -20,24 +23,56 @@ extern "C" void userAppExit() { } #endif +static void die(const char* msg) { + fprintf(stderr, "%s\n", msg); + exit(1); +} // Main code int main(int argc, char* argv[]) { - if (!glfwInit()) return -1; + if (argc < 2) die("pass a single media file as argument"); + + if (!glfwInit()) die("init glfw failed"); + + mpv_render_context* mpv_context = nullptr; + mpv_handle* mpv = mpv_create(); + mpv_set_option_string(mpv, "subs-fallback", "yes"); + mpv_set_option_string(mpv, "video-timing-offset", "0"); // 60fps + mpv_set_option_string(mpv, "vd-lavc-dr", "yes"); + mpv_set_option_string(mpv, "terminal", "yes"); + mpv_set_option_string(mpv, "ytdl", "no"); + mpv_set_option_string(mpv, "hwdec", "auto"); +#ifdef _DEBUG + mpv_set_option_string(this->mpv, "msg-level", "all=v"); +#endif + if (mpv_initialize(mpv) < 0) die("init mpv failed"); - static int osdShow = 0; // Create window with graphics context - GLFWwindow* window = glfwCreateWindow(1280, 720, "xPlayer", nullptr, nullptr); + GLFWwindow* window = glfwCreateWindow(1280, 720, argv[1], nullptr, nullptr); if (!window) { glfwTerminate(); return -1; } + glfwSetWindowUserPointer(window, mpv); glfwSetKeyCallback(window, [](GLFWwindow* window, int key, int scancode, int action, int mods) { + mpv_handle* mpv = static_cast(glfwGetWindowUserPointer(window)); if (action == GLFW_PRESS) { if (key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, 1); else if (key == GLFW_KEY_ENTER) - osdShow = !osdShow; + mpv_command_string(mpv, "script-binding stats/display-stats-toggle"); + else if (key == GLFW_KEY_SPACE) + mpv_command_string(mpv, "cycle pause"); + else if (key == GLFW_KEY_LEFT) + mpv_command_string(mpv, "seek -15"); + else if (key == GLFW_KEY_RIGHT) + mpv_command_string(mpv, "seek 15"); + else if (key == GLFW_KEY_UP) + mpv_command_string(mpv, "playlist-prev"); + else if (key == GLFW_KEY_DOWN) + mpv_command_string(mpv, "playlist-next"); + else + printf("glfwKeyCallback key press %d\n", key); } }); @@ -45,14 +80,45 @@ int main(int argc, char* argv[]) { glfwSwapInterval(1); glfwSetTime(0); + mpv_opengl_init_params gl_init_params{ + [](void* fn_ctx, const char* name) { return (void*)glfwGetProcAddress(name); }, nullptr}; + mpv_render_param params[] = { + {MPV_RENDER_PARAM_API_TYPE, const_cast(MPV_RENDER_API_TYPE_OPENGL)}, + {MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params}, + {MPV_RENDER_PARAM_INVALID, nullptr}, + }; + if (mpv_render_context_create(&mpv_context, mpv, params) < 0) die("init mpv context failed"); + mpv_render_context_set_update_callback( + mpv_context, + [](void* obj) { + mpv_render_context* ctx = static_cast(obj); + uint64_t flags = mpv_render_context_update(ctx); + if (flags & MPV_RENDER_UPDATE_FRAME) glfwPostEmptyEvent(); + }, + mpv_context); + + const char* args[] = {"loadfile", argv[1], nullptr}; + if (mpv_command_async(mpv, 0, args) < 0) die("load file failed"); + int fbw = 0, fbh = 0; // Main loop while (!glfwWindowShouldClose(window)) { glfwGetFramebufferSize(window, &fbw, &fbh); - + mpv_opengl_fbo mpv_fbo{0, fbw, fbh}; + int flip_y{1}; + mpv_render_param mpv_params[3] = { + {MPV_RENDER_PARAM_OPENGL_FBO, &mpv_fbo}, + {MPV_RENDER_PARAM_FLIP_Y, &flip_y}, + {MPV_RENDER_PARAM_INVALID, nullptr}, + }; + mpv_render_context_render(mpv_context, mpv_params); glfwSwapBuffers(window); glfwWaitEvents(); } + + mpv_render_context_free(mpv_context); + mpv_terminate_destroy(mpv); + glfwDestroyWindow(window); glfwTerminate();