| //========= Copyright Valve Corporation ============// |
| #define VR_API_EXPORT 1 |
| #include "openvr.h" |
| #include "ivrclientcore.h" |
| #include "pathtools_public.h" |
| #include "sharedlibtools_public.h" |
| #include "envvartools_public.h" |
| #include "hmderrors_public.h" |
| #include "vrpathregistry_public.h" |
| #include <mutex> |
| |
| using vr::EVRInitError; |
| using vr::IVRSystem; |
| using vr::IVRClientCore; |
| using vr::VRInitError_None; |
| |
| namespace vr |
| { |
| |
| static void *g_pVRModule = NULL; |
| static IVRClientCore *g_pHmdSystem = NULL; |
| static std::recursive_mutex g_mutexSystem; |
| |
| |
| typedef void* (*VRClientCoreFactoryFn)(const char *pInterfaceName, int *pReturnCode); |
| |
| static uint32_t g_nVRToken = 0; |
| |
| uint32_t VR_GetInitToken() |
| { |
| return g_nVRToken; |
| } |
| |
| EVRInitError VR_LoadHmdSystemInternal(); |
| void CleanupInternalInterfaces(); |
| |
| |
| uint32_t VR_InitInternal2( EVRInitError *peError, vr::EVRApplicationType eApplicationType, const char *pStartupInfo ) |
| { |
| std::lock_guard<std::recursive_mutex> lock( g_mutexSystem ); |
| |
| EVRInitError err = VR_LoadHmdSystemInternal(); |
| if ( err == vr::VRInitError_None ) |
| { |
| err = g_pHmdSystem->Init( eApplicationType, pStartupInfo ); |
| } |
| |
| if ( peError ) |
| *peError = err; |
| |
| if ( err != VRInitError_None ) |
| { |
| SharedLib_Unload( g_pVRModule ); |
| g_pHmdSystem = NULL; |
| g_pVRModule = NULL; |
| |
| return 0; |
| } |
| |
| return ++g_nVRToken; |
| } |
| |
| VR_INTERFACE uint32_t VR_CALLTYPE VR_InitInternal( EVRInitError *peError, EVRApplicationType eApplicationType ); |
| |
| uint32_t VR_InitInternal( EVRInitError *peError, vr::EVRApplicationType eApplicationType ) |
| { |
| return VR_InitInternal2( peError, eApplicationType, nullptr ); |
| } |
| |
| void VR_ShutdownInternal() |
| { |
| std::lock_guard<std::recursive_mutex> lock( g_mutexSystem ); |
| |
| if ( g_pHmdSystem ) |
| { |
| g_pHmdSystem->Cleanup(); |
| g_pHmdSystem = NULL; |
| } |
| if ( g_pVRModule ) |
| { |
| SharedLib_Unload( g_pVRModule ); |
| g_pVRModule = NULL; |
| } |
| |
| #if !defined( VR_API_PUBLIC ) |
| CleanupInternalInterfaces(); |
| #endif |
| |
| ++g_nVRToken; |
| } |
| |
| EVRInitError VR_LoadHmdSystemInternal() |
| { |
| std::string sRuntimePath, sConfigPath, sLogPath; |
| |
| bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL ); |
| if( !bReadPathRegistry ) |
| { |
| return vr::VRInitError_Init_PathRegistryNotFound; |
| } |
| |
| // figure out where we're going to look for vrclient.dll |
| // see if the specified path actually exists. |
| if( !Path_IsDirectory( sRuntimePath ) ) |
| { |
| return vr::VRInitError_Init_InstallationNotFound; |
| } |
| |
| // Because we don't have a way to select debug vs. release yet we'll just |
| // use debug if it's there |
| #if defined( LINUX64 ) |
| std::string sTestPath = Path_Join( sRuntimePath, "bin", PLATSUBDIR ); |
| #else |
| std::string sTestPath = Path_Join( sRuntimePath, "bin" ); |
| #endif |
| if( !Path_IsDirectory( sTestPath ) ) |
| { |
| return vr::VRInitError_Init_InstallationCorrupt; |
| } |
| |
| #if defined( WIN64 ) |
| std::string sDLLPath = Path_Join( sTestPath, "vrclient_x64" DYNAMIC_LIB_EXT ); |
| #else |
| std::string sDLLPath = Path_Join( sTestPath, "vrclient" DYNAMIC_LIB_EXT ); |
| #endif |
| |
| // only look in the override |
| void *pMod = SharedLib_Load( sDLLPath.c_str() ); |
| // nothing more to do if we can't load the DLL |
| if( !pMod ) |
| { |
| return vr::VRInitError_Init_VRClientDLLNotFound; |
| } |
| |
| VRClientCoreFactoryFn fnFactory = ( VRClientCoreFactoryFn )( SharedLib_GetFunction( pMod, "VRClientCoreFactory" ) ); |
| if( !fnFactory ) |
| { |
| SharedLib_Unload( pMod ); |
| return vr::VRInitError_Init_FactoryNotFound; |
| } |
| |
| int nReturnCode = 0; |
| g_pHmdSystem = static_cast< IVRClientCore * > ( fnFactory( vr::IVRClientCore_Version, &nReturnCode ) ); |
| if( !g_pHmdSystem ) |
| { |
| SharedLib_Unload( pMod ); |
| return vr::VRInitError_Init_InterfaceNotFound; |
| } |
| |
| g_pVRModule = pMod; |
| return VRInitError_None; |
| } |
| |
| |
| void *VR_GetGenericInterface(const char *pchInterfaceVersion, EVRInitError *peError) |
| { |
| std::lock_guard<std::recursive_mutex> lock( g_mutexSystem ); |
| |
| if (!g_pHmdSystem) |
| { |
| if (peError) |
| *peError = vr::VRInitError_Init_NotInitialized; |
| return NULL; |
| } |
| |
| return g_pHmdSystem->GetGenericInterface(pchInterfaceVersion, peError); |
| } |
| |
| bool VR_IsInterfaceVersionValid(const char *pchInterfaceVersion) |
| { |
| std::lock_guard<std::recursive_mutex> lock( g_mutexSystem ); |
| |
| if (!g_pHmdSystem) |
| { |
| return false; |
| } |
| |
| return g_pHmdSystem->IsInterfaceVersionValid(pchInterfaceVersion) == VRInitError_None; |
| } |
| |
| bool VR_IsHmdPresent() |
| { |
| std::lock_guard<std::recursive_mutex> lock( g_mutexSystem ); |
| |
| if( g_pHmdSystem ) |
| { |
| // if we're already initialized, just call through |
| return g_pHmdSystem->BIsHmdPresent(); |
| } |
| else |
| { |
| // otherwise we need to do a bit more work |
| EVRInitError err = VR_LoadHmdSystemInternal(); |
| if( err != VRInitError_None ) |
| return false; |
| |
| bool bHasHmd = g_pHmdSystem->BIsHmdPresent(); |
| |
| g_pHmdSystem = NULL; |
| SharedLib_Unload( g_pVRModule ); |
| g_pVRModule = NULL; |
| |
| return bHasHmd; |
| } |
| } |
| |
| /** Returns true if the OpenVR runtime is installed. */ |
| bool VR_IsRuntimeInstalled() |
| { |
| std::lock_guard<std::recursive_mutex> lock( g_mutexSystem ); |
| |
| if( g_pHmdSystem ) |
| { |
| // if we're already initialized, OpenVR is obviously installed |
| return true; |
| } |
| else |
| { |
| // otherwise we need to do a bit more work |
| std::string sRuntimePath, sConfigPath, sLogPath; |
| |
| bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL ); |
| if( !bReadPathRegistry ) |
| { |
| return false; |
| } |
| |
| // figure out where we're going to look for vrclient.dll |
| // see if the specified path actually exists. |
| if( !Path_IsDirectory( sRuntimePath ) ) |
| { |
| return false; |
| } |
| |
| // the installation may be corrupt in some way, but it certainly looks installed |
| return true; |
| } |
| } |
| |
| |
| /** Returns where OpenVR runtime is installed. */ |
| const char *VR_RuntimePath() |
| { |
| // otherwise we need to do a bit more work |
| static std::string sRuntimePath; |
| std::string sConfigPath, sLogPath; |
| |
| bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL ); |
| if ( !bReadPathRegistry ) |
| { |
| return nullptr; |
| } |
| |
| // figure out where we're going to look for vrclient.dll |
| // see if the specified path actually exists. |
| if ( !Path_IsDirectory( sRuntimePath ) ) |
| { |
| return nullptr; |
| } |
| |
| return sRuntimePath.c_str(); |
| } |
| |
| |
| /** Returns the symbol version of an HMD error. */ |
| const char *VR_GetVRInitErrorAsSymbol( EVRInitError error ) |
| { |
| std::lock_guard<std::recursive_mutex> lock( g_mutexSystem ); |
| |
| if( g_pHmdSystem ) |
| return g_pHmdSystem->GetIDForVRInitError( error ); |
| else |
| return GetIDForVRInitError( error ); |
| } |
| |
| |
| /** Returns the english string version of an HMD error. */ |
| const char *VR_GetVRInitErrorAsEnglishDescription( EVRInitError error ) |
| { |
| std::lock_guard<std::recursive_mutex> lock( g_mutexSystem ); |
| |
| if ( g_pHmdSystem ) |
| return g_pHmdSystem->GetEnglishStringForHmdError( error ); |
| else |
| return GetEnglishStringForHmdError( error ); |
| } |
| |
| |
| VR_INTERFACE const char *VR_CALLTYPE VR_GetStringForHmdError( vr::EVRInitError error ); |
| |
| /** Returns the english string version of an HMD error. */ |
| const char *VR_GetStringForHmdError( EVRInitError error ) |
| { |
| return VR_GetVRInitErrorAsEnglishDescription( error ); |
| } |
| |
| } |
| |