From 7ff679769bf6bc49619b19da00772a88758827e5 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 22 Oct 2022 14:17:03 +0200 Subject: Add a config file to store position/rotation/zoom and use those the next time vr-video-player starts --- README.md | 2 +- build.sh | 6 +- include/config.hpp | 299 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/mpv.hpp | 2 +- src/main.cpp | 230 ++++++++++++++++++++++++----------------- src/mpv.cpp | 9 +- 6 files changed, 446 insertions(+), 102 deletions(-) create mode 100644 include/config.hpp diff --git a/README.md b/README.md index 20d2839..c75d463 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ The video might not be in front of you, so to move the video in front of you, yo * Press the select/back button on an xbox controller while the application is focused * Send a SIGUSR1 signal to the application, using the following command: `killall -USR1 vr-video-player` -You can zoom the view with alt + Q/E. +You can zoom the view with Alt + Q/E. When using the built-in video player and the vr window is focused you can then use left/right arrow keys to move back/forward in the video and space to pause. In the future vr-video-player will show a graphical interface inside vr to manipulate the video. diff --git a/build.sh b/build.sh index 1f2d44b..132f12d 100755 --- a/build.sh +++ b/build.sh @@ -3,7 +3,7 @@ dependencies="glm glew sdl2 openvr x11 xcomposite xfixes mpv" includes=$(pkg-config --cflags $dependencies) libs=$(pkg-config --libs $dependencies) -gcc -c src/window_texture.c -O2 $includes -g++ -c src/mpv.cpp -O2 $includes -g++ -c src/main.cpp -O2 $includes +gcc -c src/window_texture.c -O2 -DNDEBUG $includes +g++ -c src/mpv.cpp -O2 -DNDEBUG $includes +g++ -c src/main.cpp -O2 -DNDEBUG $includes g++ -o vr-video-player -O2 window_texture.o mpv.o main.o -s $libs diff --git a/include/config.hpp b/include/config.hpp new file mode 100644 index 0000000..fcf69bf --- /dev/null +++ b/include/config.hpp @@ -0,0 +1,299 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct SphereConfig { + glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f); + glm::quat rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f); + float zoom = 0.0f; +}; + +struct Sphere360Config { + glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f); + glm::quat rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f); + float zoom = 0.0f; +}; + +struct FlatConfig { + glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f); + glm::quat rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f); + float zoom = 0.0f; +}; + +struct PlaneConfig { + glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f); + glm::quat rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f); + float zoom = 0.0f; +}; + +struct Config { + SphereConfig sphere; + Sphere360Config sphere360; + FlatConfig flat; + PlaneConfig plane; +}; + +static std::string get_home_dir() { + const char *home_dir = getenv("HOME"); + if(!home_dir) { + passwd *pw = getpwuid(getuid()); + home_dir = pw->pw_dir; + } + + if(!home_dir) { + fprintf(stderr, "Error: Failed to get home directory of user, using /tmp directory\n"); + home_dir = "/tmp"; + } + + return home_dir; +} + +static std::string get_config_dir() { + std::string config_dir; + const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); + if(xdg_config_home) { + config_dir = xdg_config_home; + } else { + config_dir = get_home_dir() + "/.config"; + } + config_dir += "/vr-video-player"; + return config_dir; +} + +static int create_directory_recursive(char *path) { + int path_len = strlen(path); + char *p = path; + char *end = path + path_len; + for(;;) { + char *slash_p = strchr(p, '/'); + + // Skips first '/', we don't want to try and create the root directory + if(slash_p == path) { + ++p; + continue; + } + + if(!slash_p) + slash_p = end; + + char prev_char = *slash_p; + *slash_p = '\0'; + int err = mkdir(path, S_IRWXU); + *slash_p = prev_char; + + if(err == -1 && errno != EEXIST) + return err; + + if(slash_p == end) + break; + else + p = slash_p + 1; + } + return 0; +} + +static bool file_get_content(const char *filepath, std::string &file_content) { + file_content.clear(); + bool success = false; + + FILE *file = fopen(filepath, "rb"); + if(!file) + return success; + + fseek(file, 0, SEEK_END); + long file_size = ftell(file); + if(file_size != -1) { + file_content.resize(file_size); + fseek(file, 0, SEEK_SET); + if((long)fread(&file_content[0], 1, file_size, file) == file_size) + success = true; + } + + fclose(file); + return success; +} + +struct StringView { + const char *str; + size_t size; + + bool operator == (const char *other) const { + int len = strlen(other); + return (size_t)len == size && memcmp(str, other, size) == 0; + } + + size_t find(char c) const { + const void *p = memchr(str, c, size); + if(!p) + return std::string::npos; + return (const char*)p - str; + } +}; + +using StringSplitCallback = std::function; + +static void string_split_char(const std::string &str, char delimiter, StringSplitCallback callback_func) { + size_t index = 0; + while(index < str.size()) { + size_t new_index = str.find(delimiter, index); + if(new_index == std::string::npos) + new_index = str.size(); + + if(!callback_func({str.data() + index, new_index - index})) + break; + + index = new_index + 1; + } +} + +static bool config_split_key_value(const StringView str, StringView &key, StringView &value) { + key.str = nullptr; + key.size = 0; + + value.str = nullptr; + value.size = 0; + + size_t index = str.find(' '); + if(index == std::string::npos) + return std::string::npos; + + key.str = str.str; + key.size = index; + + value.str = str.str + index + 1; + value.size = str.size - (index + 1); + + return true; +} + +static bool string_to_float(std::string str, float &value, const StringView key) { + value = 0.0; + errno = 0; + char *endptr; + value = strtod(str.c_str(), &endptr); + if(endptr == str.c_str() || errno != 0) { + fprintf(stderr, "Warning: Invalid config option %.*s is not a float\n", (int)key.size, key.str); + return false; + } + return true; +} + +static bool string_to_vec3(std::string str, glm::vec3 &value, const StringView key) { + if(sscanf(str.data(), "%f|%f|%f", &value.x, &value.y, &value.z) != 3) { + fprintf(stderr, "Warning: Invalid config option %.*s is not a glm::vec3\n", (int)key.size, key.str); + return false; + } + return true; +} + +static bool string_to_quat(std::string str, glm::quat &value, const StringView key) { + if(sscanf(str.data(), "%f|%f|%f|%f", &value.x, &value.y, &value.z, &value.w) != 4) { + fprintf(stderr, "Warning: Invalid config option %.*s is not a glm::quat\n", (int)key.size, key.str); + return false; + } + return true; +} + +static Config read_config(bool &exists) { + setlocale(LC_ALL, "C"); + + Config config; + + const std::string config_path = get_config_dir() + "/config"; + std::string file_content; + if(!file_get_content(config_path.c_str(), file_content)) { + fprintf(stderr, "Warning: Failed to read config file: %s\n", config_path.c_str()); + exists = false; + return config; + } + + string_split_char(file_content, '\n', [&](StringView line) { + StringView key, value; + if(!config_split_key_value(line, key, value)) { + fprintf(stderr, "Warning: Invalid config option format: %.*s\n", (int)line.size, line.str); + return true; + } + + if(key == "sphere.position") { + string_to_vec3(std::string(value.str, value.size), config.sphere.position, key); + } else if(key == "sphere.rotation") { + string_to_quat(std::string(value.str, value.size), config.sphere.rotation, key); + } else if(key == "sphere.zoom") { + string_to_float(std::string(value.str, value.size), config.sphere.zoom, key); + } else if(key == "sphere360.position") { + string_to_vec3(std::string(value.str, value.size), config.sphere360.position, key); + } else if(key == "sphere360.rotation") { + string_to_quat(std::string(value.str, value.size), config.sphere360.rotation, key); + } else if(key == "sphere360.zoom") { + string_to_float(std::string(value.str, value.size), config.sphere360.zoom, key); + } else if(key == "flat.position") { + string_to_vec3(std::string(value.str, value.size), config.flat.position, key); + } else if(key == "flat.rotation") { + string_to_quat(std::string(value.str, value.size), config.flat.rotation, key); + } else if(key == "flat.zoom") { + string_to_float(std::string(value.str, value.size), config.flat.zoom, key); + } else if(key == "plane.position") { + string_to_vec3(std::string(value.str, value.size), config.plane.position, key); + } else if(key == "plane.rotation") { + string_to_quat(std::string(value.str, value.size), config.plane.rotation, key); + } else if(key == "plane.zoom") { + string_to_float(std::string(value.str, value.size), config.plane.zoom, key); + } else { + fprintf(stderr, "Warning: Invalid config option: %.*s\n", (int)line.size, line.str); + } + + return true; + }); + + exists = true; + return config; +} + +static void save_config(const Config &config) { + setlocale(LC_ALL, "C"); + + const std::string config_path = get_config_dir() + "/config"; + + char dir_tmp[PATH_MAX]; + strcpy(dir_tmp, config_path.c_str()); + char *dir = dirname(dir_tmp); + + if(create_directory_recursive(dir) != 0) { + fprintf(stderr, "Warning: Failed to create config directory: %s\n", dir); + return; + } + + FILE *file = fopen(config_path.c_str(), "wb"); + if(!file) { + fprintf(stderr, "Warning: Failed to create config file: %s\n", config_path.c_str()); + return; + } + + fprintf(file, "sphere.position %f|%f|%f\n", config.sphere.position.x, config.sphere.position.y, config.sphere.position.z); + fprintf(file, "sphere.rotation %f|%f|%f|%f\n", config.sphere.rotation.x, config.sphere.rotation.y, config.sphere.rotation.z, config.sphere.rotation.w); + fprintf(file, "sphere.zoom %f\n", config.sphere.zoom); + + fprintf(file, "sphere360.position %f|%f|%f\n", config.sphere360.position.x, config.sphere360.position.y, config.sphere360.position.z); + fprintf(file, "sphere360.rotation %f|%f|%f|%f\n", config.sphere360.rotation.x, config.sphere360.rotation.y, config.sphere360.rotation.z, config.sphere360.rotation.w); + fprintf(file, "sphere360.zoom %f\n", config.sphere360.zoom); + + fprintf(file, "flat.position %f|%f|%f\n", config.flat.position.x, config.flat.position.y, config.flat.position.z); + fprintf(file, "flat.rotation %f|%f|%f|%f\n", config.flat.rotation.x, config.flat.rotation.y, config.flat.rotation.z, config.flat.rotation.w); + fprintf(file, "flat.zoom %f\n", config.flat.zoom); + + fprintf(file, "plane.position %f|%f|%f\n", config.plane.position.x, config.plane.position.y, config.plane.position.z); + fprintf(file, "plane.rotation %f|%f|%f|%f\n", config.plane.rotation.x, config.plane.rotation.y, config.plane.rotation.z, config.plane.rotation.w); + fprintf(file, "plane.zoom %f\n", config.plane.zoom); + + fclose(file); +} \ No newline at end of file diff --git a/include/mpv.hpp b/include/mpv.hpp index b4e22b3..09ba2c1 100644 --- a/include/mpv.hpp +++ b/include/mpv.hpp @@ -16,7 +16,7 @@ public: bool load_file(const char *path); // |width| and |ħeight| are set to 0 unless there is an event to reconfigure video size - void on_event(SDL_Event &event, bool *render_update, int64_t *width, int64_t *height, bool *quit); + void on_event(SDL_Event &event, bool *render_update, int64_t *width, int64_t *height, bool *quit, int *error); void seek(double seconds); void toggle_pause(); void draw(unsigned int framebuffer_id, int width, int height); diff --git a/src/main.cpp b/src/main.cpp index 016a392..8e74185 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,7 @@ #include #include "../include/window_texture.h" #include "../include/mpv.hpp" +#include "../include/config.hpp" #include #include @@ -70,6 +71,20 @@ static bool g_bPrintf = true; +enum class ViewMode { + LEFT_RIGHT, + RIGHT_LEFT, + PLANE, + SPHERE360 +}; + +enum class ProjectionMode { + SPHERE, + FLAT, + CYLINDER, /* aka plane */ + SPHERE360 +}; + //----------------------------------------------------------------------------- // Purpose: //------------------------------------------------------------------------------ @@ -121,10 +136,12 @@ public: // Get focused window or None Window get_focused_window(); + void save_config(); + + int exit_code = 0; + bool bQuit = false; private: bool m_bDebugOpenGL; - bool m_bVerbose; - bool m_bPerf; bool m_bVblank; bool m_bGlFinishHack; @@ -146,7 +163,6 @@ private: // OpenGL bookkeeping int m_iValidPoseCount; int m_iValidPoseCount_Last; bool m_bResetRotation; - glm::vec2 m_vAnalogValue; std::string m_strPoseClasses; // what classes we saw poses for this frame char m_rDevClassChar[ vr::k_unMaxTrackedDeviceCount ]; // for each device, a character representing its class @@ -171,15 +187,10 @@ private: // OpenGL bookkeeping GLuint m_glCompanionWindowIDIndexBuffer; unsigned int m_uiCompanionWindowIndexSize; - GLuint m_glControllerVertBuffer; - GLuint m_unControllerVAO; - unsigned int m_uiControllerVertcount; - glm::mat4 m_mat4HMDPose; glm::mat4 m_mat4eyePosLeft; glm::mat4 m_mat4eyePosRight; - glm::mat4 m_mat4ProjectionCenter; glm::mat4 m_mat4ProjectionLeft; glm::mat4 m_mat4ProjectionRight; @@ -188,6 +199,8 @@ private: // OpenGL bookkeeping glm::quat hmd_rot = glm::quat(0.0f, 0.0f, 0.0f, 1.0f); glm::quat m_reset_rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f); + Config config; + struct VertexDataScene { glm::vec3 position; @@ -235,10 +248,6 @@ private: // OpenGL bookkeeping uint32_t m_nRenderHeight; vr::VRActionHandle_t m_actionHideCubes = vr::k_ulInvalidActionHandle; - vr::VRActionHandle_t m_actionHideThisController = vr::k_ulInvalidActionHandle; - vr::VRActionHandle_t m_actionTriggerHaptic = vr::k_ulInvalidActionHandle; - vr::VRActionHandle_t m_actionAnalongInput = vr::k_ulInvalidActionHandle; - vr::VRActionSetHandle_t m_actionsetDemo = vr::k_ulInvalidActionSetHandle; private: // X compositor @@ -278,20 +287,6 @@ private: // X compositor GLint pixmap_texture_width = 1; GLint pixmap_texture_height = 1; - enum class ViewMode { - LEFT_RIGHT, - RIGHT_LEFT, - PLANE, - SPHERE360 - }; - - enum class ProjectionMode { - SPHERE, - FLAT, - CYLINDER, /* aka plane */ - SPHERE360 - }; - ProjectionMode projection_mode = ProjectionMode::SPHERE; double zoom = 0.0; float cursor_scale = 2.0f; @@ -312,6 +307,8 @@ private: // X compositor float cursor_scale_uniform[2]; double arrow_ratio; bool cursor_image_set = false; + + bool config_exists = false; }; @@ -401,7 +398,7 @@ void dprintf( const char *fmt, ... ) } static void usage() { - fprintf(stderr, "usage: vr-video-player [--sphere|--sphere360|--flat|--plane] [--left-right|--right-left] [--stretch|--no-stretch] [--zoom zoom-level] [--cursor-scale scale] [--cursor-wrap|--no-cursor-wrap] [--follow-focused] [--video video] \n"); + fprintf(stderr, "usage: vr-video-player [--sphere|--sphere360|--flat|--plane] [--left-right|--right-left] [--stretch|--no-stretch] [--zoom zoom-level] [--cursor-scale scale] [--cursor-wrap|--no-cursor-wrap] [--follow-focused|--video video|] [--use-system-mpv-config] [--free-camera] [--reduce-flicker]\n"); fprintf(stderr, "\n"); fprintf(stderr, "OPTIONS\n"); fprintf(stderr, " --sphere View the window as a stereoscopic 180 degrees screen (half sphere). The view will be attached to your head in vr. This is recommended for 180 degrees videos. This is the default value\n"); @@ -435,6 +432,35 @@ static void usage() { exit(1); } +static void get_config_values(const Config &config, ProjectionMode projection_mode, glm::vec3 &pos, glm::quat &rot, float &zoom) { + switch(projection_mode) { + case ProjectionMode::SPHERE: { + pos = config.sphere.position; + rot = config.sphere.rotation; + zoom = config.sphere.zoom; + break; + } + case ProjectionMode::FLAT: { + pos = config.flat.position; + rot = config.flat.rotation; + zoom = config.flat.zoom; + break; + } + case ProjectionMode::CYLINDER: { + pos = config.plane.position; + rot = config.plane.rotation; + zoom = config.plane.zoom; + break; + } + case ProjectionMode::SPHERE360: { + pos = config.sphere360.position; + rot = config.sphere360.rotation; + zoom = config.sphere360.zoom; + break; + } + } +} + //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- @@ -448,12 +474,8 @@ CMainApplication::CMainApplication( int argc, char *argv[] ) , m_unCompanionWindowProgramID( 0 ) , m_pHMD( NULL ) , m_bDebugOpenGL( false ) - , m_bVerbose( false ) - , m_bPerf( false ) , m_bVblank( false ) , m_bGlFinishHack( false ) - , m_glControllerVertBuffer( 0 ) - , m_unControllerVAO( 0 ) , m_unSceneVAO( 0 ) , m_nSceneMatrixLocation( -1 ) , m_nSceneTextureOffsetXLocation( -1 ) @@ -623,6 +645,15 @@ CMainApplication::CMainApplication( int argc, char *argv[] ) #ifdef _DEBUG m_bDebugOpenGL = true; #endif + + config = read_config(config_exists); + if(!config_exists) + return; + + float saved_config = 0.0f; + get_config_values(config, projection_mode, hmd_pos, m_reset_rotation, saved_config); + if(!zoom_set) + zoom = saved_config; }; @@ -748,7 +779,8 @@ bool CMainApplication::BInit() } auto standing_pos = m_pHMD->GetSeatedZeroPoseToStandingAbsoluteTrackingPose(); - hmd_pos += glm::vec3(standing_pos.m[0][3], standing_pos.m[1][3], standing_pos.m[2][3]); + if(!config_exists) + hmd_pos += glm::vec3(standing_pos.m[0][3], standing_pos.m[1][3], standing_pos.m[2][3]); int nWindowPosX = 700; int nWindowPosY = 100; @@ -895,29 +927,20 @@ bool CMainApplication::BInit() }); } - //char cwd[4096]; - //getcwd(cwd, sizeof(cwd)); - //printf("cwd: %s\n", cwd); - //dirname(cwd); char action_manifest_path[PATH_MAX]; realpath("config/hellovr_actions.json", action_manifest_path); if(access(action_manifest_path, F_OK) == -1) { strcpy(action_manifest_path, "/usr/share/vr-video-player/hellovr_actions.json"); if(access(action_manifest_path, F_OK) == -1) { fprintf(stderr, "Unable to find hellovr_action.json!\n"); - exit(1); + return false; } } - fprintf(stderr, "Using config file: %s\n", action_manifest_path); + fprintf(stderr, "Using openvr config file: %s\n", action_manifest_path); vr::VRInput()->SetActionManifestPath(action_manifest_path); - vr::VRInput()->GetActionHandle( "/actions/demo/in/HideCubes", &m_actionHideCubes ); - vr::VRInput()->GetActionHandle( "/actions/demo/in/HideThisController", &m_actionHideThisController); - vr::VRInput()->GetActionHandle( "/actions/demo/in/TriggerHaptic", &m_actionTriggerHaptic ); - vr::VRInput()->GetActionHandle( "/actions/demo/in/AnalogInput", &m_actionAnalongInput ); - vr::VRInput()->GetActionSetHandle( "/actions/demo", &m_actionsetDemo ); return true; @@ -993,8 +1016,6 @@ bool CMainApplication::BInitGL() //----------------------------------------------------------------------------- bool CMainApplication::BInitCompositor() { - vr::EVRInitError peError = vr::VRInitError_None; - if ( !vr::VRCompositor() ) { printf( "Compositor initialization failed. See log file for details\n" ); @@ -1068,10 +1089,6 @@ void CMainApplication::Shutdown() { glDeleteVertexArrays( 1, &m_unSceneVAO ); } - if( m_unControllerVAO != 0 ) - { - glDeleteVertexArrays( 1, &m_unControllerVAO ); - } } window_texture_deinit(&window_texture); @@ -1171,8 +1188,12 @@ bool CMainApplication::HandleInput() } bool opdoot = false; - if(mpv_file) - mpv.on_event(sdlEvent, &opdoot, &video_width, &video_height, &mpv_quit); + if(mpv_file) { + int error = 0; + mpv.on_event(sdlEvent, &opdoot, &video_width, &video_height, &mpv_quit, &error); + if(mpv_quit && error != 0) + exit_code = 2; + } if(opdoot) set_render_update(); @@ -1180,7 +1201,7 @@ bool CMainApplication::HandleInput() if(mpv_quit) bRet = true; - // TODO: Allow resize config + // TODO: Allow video resize to update texture size if(video_width > 0 && video_height > 0 && video_width != mpv_video_width && video_height != mpv_video_height && !mpv_video_loaded && !mpv_loaded_in_thread) { mpv_video_width = video_width; mpv_video_height = video_height; @@ -1326,13 +1347,6 @@ bool CMainApplication::HandleInput() if(!free_camera) hmd_pos = current_pos; - vr::InputAnalogActionData_t analogData; - if ( vr::VRInput()->GetAnalogActionData( m_actionAnalongInput, &analogData, sizeof( analogData ), vr::k_ulInvalidInputValueHandle ) == vr::VRInputError_None && analogData.bActive ) - { - m_vAnalogValue[0] = analogData.x; - m_vAnalogValue[1] = analogData.y; - } - return bRet; } @@ -1341,8 +1355,6 @@ bool CMainApplication::HandleInput() //----------------------------------------------------------------------------- void CMainApplication::RunMainLoop() { - bool bQuit = false; - SDL_StartTextInput(); SDL_Joystick *controller = SDL_JoystickOpen(0); @@ -1718,7 +1730,7 @@ bool CMainApplication::SetCursorFromX11CursorImage(XFixesCursorImage *x11_cursor } } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, arrow_image_width, arrow_image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, cursor_data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, arrow_image_width, arrow_image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, cursor_data); delete []cursor_data; glGenerateMipmap(GL_TEXTURE_2D); @@ -1757,6 +1769,52 @@ Window CMainApplication::get_focused_window() { return None; } +void CMainApplication::save_config() { + if(free_camera) { + switch(projection_mode) { + case ProjectionMode::SPHERE: { + config.sphere.position = hmd_pos; + break; + } + case ProjectionMode::FLAT: { + config.flat.position = hmd_pos; + break; + } + case ProjectionMode::CYLINDER: { + config.plane.position = hmd_pos; + break; + } + case ProjectionMode::SPHERE360: { + config.sphere360.position = hmd_pos; + break; + } + } + } + switch(projection_mode) { + case ProjectionMode::SPHERE: { + config.sphere.rotation = m_reset_rotation; + config.sphere.zoom = zoom; + break; + } + case ProjectionMode::FLAT: { + config.flat.rotation = m_reset_rotation; + config.flat.zoom = zoom; + break; + } + case ProjectionMode::CYLINDER: { + config.plane.rotation = m_reset_rotation; + config.plane.zoom = zoom; + break; + } + case ProjectionMode::SPHERE360: { + config.sphere360.rotation = m_reset_rotation; + config.sphere360.zoom = zoom; + break; + } + } + ::save_config(config); +} + //----------------------------------------------------------------------------- // Purpose: create a sea of cubes @@ -2400,36 +2458,7 @@ void CMainApplication::RenderScene( vr::Hmd_Eye nEye ) glDrawArrays( GL_TRIANGLES, 0, m_uiVertcount ); glBindVertexArray( 0 ); - glActiveTexture(GL_TEXTURE0); -#if 0 - bool bIsInputAvailable = m_pHMD->IsInputAvailable(); - - if( bIsInputAvailable ) - { - // draw the controller axis lines - glUseProgram( m_unControllerTransformProgramID ); - glUniformMatrix4fv( m_nControllerMatrixLocation, 1, GL_FALSE, glm::value_ptr(GetCurrentViewProjectionMatrix( nEye ))); - glBindVertexArray( m_unControllerVAO ); - glDrawArrays( GL_LINES, 0, m_uiControllerVertcount ); - glBindVertexArray( 0 ); - } - - // ----- Render Model rendering ----- - glUseProgram( m_unRenderModelProgramID ); - - for ( EHand eHand = Left; eHand <= Right; ((int&)eHand)++ ) - { - if ( !m_rHand[eHand].m_bShowController || !m_rHand[eHand].m_pRenderModel ) - continue; - - const glm::mat4 & matDeviceToTracking = m_rHand[eHand].m_rmat4Pose; - glm::mat4 matMVP = GetCurrentViewProjectionMatrix( nEye ) * matDeviceToTracking; - glUniformMatrix4fv( m_nRenderModelMatrixLocation, 1, GL_FALSE, glm::value_ptr(matMVP)); - - m_rHand[eHand].m_pRenderModel->Draw(); - } -#endif glUseProgram( 0 ); } @@ -2548,7 +2577,7 @@ void CMainApplication::UpdateHMDMatrixPose() m_iValidPoseCount = 0; m_strPoseClasses = ""; - for ( int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice ) + for ( int nDevice = 0; nDevice < (int)vr::k_unMaxTrackedDeviceCount; ++nDevice ) { if ( m_rTrackedDevicePose[nDevice].bPoseIsValid ) { @@ -2603,7 +2632,13 @@ CMainApplication *pMainApplication; void reset_position(int signum) { printf("ok\n"); - pMainApplication->ResetRotation(); + if(pMainApplication) + pMainApplication->ResetRotation(); +} + +void quit(int signum) { + if(pMainApplication) + pMainApplication->bQuit = true; } //----------------------------------------------------------------------------- @@ -2616,6 +2651,9 @@ int main(int argc, char *argv[]) signal(SIGUSR1, reset_position); signal(SIGUSR2, reset_position); + signal(SIGINT, quit); + signal(SIGTERM, quit); + if (!pMainApplication->BInit()) { pMainApplication->Shutdown(); @@ -2623,8 +2661,10 @@ int main(int argc, char *argv[]) } pMainApplication->RunMainLoop(); - pMainApplication->Shutdown(); - return 0; + if(pMainApplication->exit_code == 0) + pMainApplication->save_config(); + + return pMainApplication->exit_code; } diff --git a/src/mpv.cpp b/src/mpv.cpp index 164021e..0880049 100644 --- a/src/mpv.cpp +++ b/src/mpv.cpp @@ -159,7 +159,7 @@ bool Mpv::load_file(const char *path) { return true; } -void Mpv::on_event(SDL_Event &event, bool *render_update, int64_t *width, int64_t *height, bool *quit) { +void Mpv::on_event(SDL_Event &event, bool *render_update, int64_t *width, int64_t *height, bool *quit, int *error) { if(render_update) *render_update = false; @@ -172,6 +172,9 @@ void Mpv::on_event(SDL_Event &event, bool *render_update, int64_t *width, int64_ if(quit) *quit = false; + if(error) + *error = 0; + if(!created) return; @@ -200,8 +203,10 @@ void Mpv::on_event(SDL_Event &event, bool *render_update, int64_t *width, int64_ mpv_event_end_file *msg = (mpv_event_end_file*)mp_event->data; if(msg->reason == MPV_END_FILE_REASON_ERROR) { show_notification("vr video player mpv video error", mpv_error_string(msg->error), "critical"); - if(quit) + if(quit) { *quit = true; + *error = -1; + } } if(msg->reason == MPV_END_FILE_REASON_EOF) { show_notification("vr video player", "the video ended", "low"); -- cgit v1.2.3