Index: third_party/openvr/src/src/vrcommon/vrpathregistry_public.cpp |
diff --git a/third_party/openvr/src/src/vrcommon/vrpathregistry_public.cpp b/third_party/openvr/src/src/vrcommon/vrpathregistry_public.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3aeca3a42e7b86bcf7aa7da588eac98c0e26e9a0 |
--- /dev/null |
+++ b/third_party/openvr/src/src/vrcommon/vrpathregistry_public.cpp |
@@ -0,0 +1,409 @@ |
+//========= Copyright Valve Corporation ============// |
+ |
+#include "vrpathregistry_public.h" |
+#include "json/json.h" |
+#include "pathtools_public.h" |
+#include "envvartools_public.h" |
+#include "strtools_public.h" |
+#include "dirtools_public.h" |
+ |
+#if defined( WIN32 ) |
+#include <windows.h> |
+#include <Shlobj.h> |
+ |
+#undef GetEnvironmentVariable |
+#elif defined OSX |
+#include <Foundation/Foundation.h> |
+#include <AppKit/AppKit.h> |
+#elif defined(LINUX) |
+#include <dlfcn.h> |
+#include <stdio.h> |
+#endif |
+ |
+#include <algorithm> |
+ |
+#ifndef VRLog |
+ #if defined( WIN32 ) |
+ #define VRLog(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) |
+ #else |
+ #define VRLog(args...) fprintf(stderr, args) |
+ #endif |
+#endif |
+ |
+/** Returns the root of the directory the system wants us to store user config data in */ |
+static std::string GetAppSettingsPath() |
+{ |
+#if defined( WIN32 ) |
+ WCHAR rwchPath[MAX_PATH]; |
+ |
+ if( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) ) |
+ { |
+ return ""; |
+ } |
+ |
+ // Convert the path to UTF-8 and store in the output |
+ std::string sUserPath = UTF16to8( rwchPath ); |
+ |
+ return sUserPath; |
+#elif defined( OSX ) |
+ std::string sSettingsDir; |
+ @autoreleasepool { |
+ // Search for the path |
+ NSArray *paths = NSSearchPathForDirectoriesInDomains( NSApplicationSupportDirectory, NSUserDomainMask, YES ); |
+ if ( [paths count] == 0 ) |
+ { |
+ return ""; |
+ } |
+ |
+ NSString *resolvedPath = [paths objectAtIndex:0]; |
+ resolvedPath = [resolvedPath stringByAppendingPathComponent: @"OpenVR"]; |
+ |
+ if ( ![[NSFileManager new] createDirectoryAtPath: resolvedPath withIntermediateDirectories:YES attributes:nil error:nil] ) |
+ { |
+ return ""; |
+ } |
+ |
+ sSettingsDir.assign( [resolvedPath UTF8String] ); |
+ } |
+ return sSettingsDir; |
+#elif defined( LINUX ) |
+ |
+ // As defined by XDG Base Directory Specification |
+ // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html |
+ |
+ const char *pchHome = getenv("XDG_CONFIG_HOME"); |
+ if ( ( pchHome != NULL) && ( pchHome[0] != '\0' ) ) |
+ { |
+ return pchHome; |
+ } |
+ |
+ // |
+ // XDG_CONFIG_HOME is not defined, use ~/.config instead |
+ // |
+ pchHome = getenv( "HOME" ); |
+ if ( pchHome == NULL ) |
+ { |
+ return ""; |
+ } |
+ |
+ std::string sUserPath( pchHome ); |
+ sUserPath = Path_Join( sUserPath, ".config" ); |
+ return sUserPath; |
+#else |
+ #warning "Unsupported platform" |
+#endif |
+} |
+ |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Constructor |
+// --------------------------------------------------------------------------- |
+CVRPathRegistry_Public::CVRPathRegistry_Public() |
+{ |
+ |
+} |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Computes the registry filename |
+// --------------------------------------------------------------------------- |
+std::string CVRPathRegistry_Public::GetOpenVRConfigPath() |
+{ |
+ std::string sConfigPath = GetAppSettingsPath(); |
+ if( sConfigPath.empty() ) |
+ return ""; |
+ |
+#if defined( _WIN32 ) || defined( LINUX ) |
+ sConfigPath = Path_Join( sConfigPath, "openvr" ); |
+#elif defined ( OSX ) |
+ sConfigPath = Path_Join( sConfigPath, ".openvr" ); |
+#else |
+ #warning "Unsupported platform" |
+#endif |
+ sConfigPath = Path_FixSlashes( sConfigPath ); |
+ return sConfigPath; |
+} |
+ |
+ |
+ |
+//----------------------------------------------------------------------------- |
+// Purpose: |
+//----------------------------------------------------------------------------- |
+std::string CVRPathRegistry_Public::GetVRPathRegistryFilename() |
+{ |
+ std::string sPath = GetOpenVRConfigPath(); |
+ if ( sPath.empty() ) |
+ return ""; |
+ |
+#if defined( _WIN32 ) |
+ sPath = Path_Join( sPath, "openvrpaths.vrpath" ); |
+#elif defined ( POSIX ) |
+ sPath = Path_Join( sPath, "openvrpaths.vrpath" ); |
+#else |
+ #error "Unsupported platform" |
+#endif |
+ sPath = Path_FixSlashes( sPath ); |
+ return sPath; |
+} |
+ |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Converts JSON to a history array |
+// --------------------------------------------------------------------------- |
+static void ParseStringListFromJson( std::vector< std::string > *pvecHistory, const Json::Value & root, const char *pchArrayName ) |
+{ |
+ if( !root.isMember( pchArrayName ) ) |
+ return; |
+ |
+ const Json::Value & arrayNode = root[ pchArrayName ]; |
+ if( !arrayNode ) |
+ { |
+ VRLog( "VR Path Registry node %s is not an array\n", pchArrayName ); |
+ return; |
+ } |
+ |
+ pvecHistory->clear(); |
+ pvecHistory->reserve( arrayNode.size() ); |
+ for( uint32_t unIndex = 0; unIndex < arrayNode.size(); unIndex++ ) |
+ { |
+ std::string sPath( arrayNode[ unIndex ].asString() ); |
+ pvecHistory->push_back( sPath ); |
+ } |
+} |
+ |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Converts a history array to JSON |
+// --------------------------------------------------------------------------- |
+static void StringListToJson( const std::vector< std::string > & vecHistory, Json::Value & root, const char *pchArrayName ) |
+{ |
+ Json::Value & arrayNode = root[ pchArrayName ]; |
+ for( auto i = vecHistory.begin(); i != vecHistory.end(); i++ ) |
+ { |
+ arrayNode.append( *i ); |
+ } |
+} |
+ |
+ |
+//----------------------------------------------------------------------------- |
+// Purpose: |
+//----------------------------------------------------------------------------- |
+bool CVRPathRegistry_Public::ToJsonString( std::string &sJsonString ) |
+{ |
+ std::string sRegPath = GetVRPathRegistryFilename(); |
+ if( sRegPath.empty() ) |
+ return false; |
+ |
+ std::string sRegistryContents = Path_ReadTextFile( sRegPath ); |
+ if( sRegistryContents.empty() ) |
+ return false; |
+ |
+ sJsonString = sRegistryContents; |
+ |
+ return true; |
+} |
+ |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Loads the config file from its well known location |
+// --------------------------------------------------------------------------- |
+bool CVRPathRegistry_Public::BLoadFromFile() |
+{ |
+ std::string sRegPath = GetVRPathRegistryFilename(); |
+ if( sRegPath.empty() ) |
+ { |
+ VRLog( "Unable to determine VR Path Registry filename\n" ); |
+ return false; |
+ } |
+ |
+ std::string sRegistryContents = Path_ReadTextFile( sRegPath ); |
+ if( sRegistryContents.empty() ) |
+ { |
+ VRLog( "Unable to read VR Path Registry from %s\n", sRegPath.c_str() ); |
+ return false; |
+ } |
+ |
+ Json::Value root; |
+ Json::Reader reader; |
+ |
+ if( !reader.parse( sRegistryContents, root ) ) |
+ { |
+ VRLog( "Unable to parse %s: %s\n", sRegPath.c_str(), reader.getFormattedErrorMessages().c_str() ); |
+ return false; |
+ } |
+ |
+ ParseStringListFromJson( &m_vecRuntimePath, root, "runtime" ); |
+ ParseStringListFromJson( &m_vecConfigPath, root, "config" ); |
+ ParseStringListFromJson( &m_vecLogPath, root, "log" ); |
+ if (root.isMember( "external_drivers" ) && root[ "external_drivers" ].isArray() ) |
+ { |
+ ParseStringListFromJson( &m_vecExternalDrivers, root, "external_drivers" ); |
+ } |
+ |
+ return true; |
+} |
+ |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Saves the config file to its well known location |
+// --------------------------------------------------------------------------- |
+bool CVRPathRegistry_Public::BSaveToFile() const |
+{ |
+#if defined( DASHBOARD_BUILD_MODE ) |
+ return false; |
+#else |
+ std::string sRegPath = GetVRPathRegistryFilename(); |
+ if( sRegPath.empty() ) |
+ return false; |
+ |
+ Json::Value root; |
+ |
+ root[ "version" ] = 1; |
+ root[ "jsonid" ] = "vrpathreg"; |
+ |
+ StringListToJson( m_vecRuntimePath, root, "runtime" ); |
+ StringListToJson( m_vecConfigPath, root, "config" ); |
+ StringListToJson( m_vecLogPath, root, "log" ); |
+ StringListToJson( m_vecExternalDrivers, root, "external_drivers" ); |
+ |
+ Json::StyledWriter writer; |
+ std::string sRegistryContents = writer.write( root ); |
+ |
+ // make sure the directory we're writing into actually exists |
+ std::string sRegDirectory = Path_StripFilename( sRegPath ); |
+ if( !BCreateDirectoryRecursive( sRegDirectory.c_str() ) ) |
+ { |
+ VRLog( "Unable to create path registry directory %s\n", sRegDirectory.c_str() ); |
+ return false; |
+ } |
+ |
+ if( !Path_WriteStringToTextFile( sRegPath, sRegistryContents.c_str() ) ) |
+ { |
+ VRLog( "Unable to write VR path registry to %s\n", sRegPath.c_str() ); |
+ return false; |
+ } |
+ |
+ return true; |
+#endif |
+} |
+ |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Returns the current runtime path or NULL if no path is configured. |
+// --------------------------------------------------------------------------- |
+std::string CVRPathRegistry_Public::GetRuntimePath() const |
+{ |
+ if( m_vecRuntimePath.empty() ) |
+ return ""; |
+ else |
+ return m_vecRuntimePath.front().c_str(); |
+} |
+ |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Returns the current config path or NULL if no path is configured. |
+// --------------------------------------------------------------------------- |
+std::string CVRPathRegistry_Public::GetConfigPath() const |
+{ |
+ if( m_vecConfigPath.empty() ) |
+ return ""; |
+ else |
+ return m_vecConfigPath.front().c_str(); |
+} |
+ |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Returns the current log path or NULL if no path is configured. |
+// --------------------------------------------------------------------------- |
+std::string CVRPathRegistry_Public::GetLogPath() const |
+{ |
+ if( m_vecLogPath.empty() ) |
+ return ""; |
+ else |
+ return m_vecLogPath.front().c_str(); |
+} |
+ |
+ |
+ |
+// --------------------------------------------------------------------------- |
+// Purpose: Returns paths using the path registry and the provided override |
+// values. Pass NULL for any paths you don't care about. |
+// --------------------------------------------------------------------------- |
+bool CVRPathRegistry_Public::GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers ) |
+{ |
+ CVRPathRegistry_Public pathReg; |
+ bool bLoadedRegistry = pathReg.BLoadFromFile(); |
+ int nCountEnvironmentVariables = 0; |
+ |
+ if( psRuntimePath ) |
+ { |
+ if ( GetEnvironmentVariable( k_pchRuntimeOverrideVar ).length() != 0 ) |
+ { |
+ *psRuntimePath = GetEnvironmentVariable( k_pchRuntimeOverrideVar ); |
+ nCountEnvironmentVariables++; |
+ } |
+ else if( !pathReg.GetRuntimePath().empty() ) |
+ { |
+ *psRuntimePath = pathReg.GetRuntimePath(); |
+ } |
+ else |
+ { |
+ *psRuntimePath = ""; |
+ } |
+ } |
+ |
+ if( psConfigPath ) |
+ { |
+ if ( GetEnvironmentVariable( k_pchConfigOverrideVar ).length() != 0 ) |
+ { |
+ *psConfigPath = GetEnvironmentVariable( k_pchConfigOverrideVar ); |
+ nCountEnvironmentVariables++; |
+ } |
+ else if( pchConfigPathOverride ) |
+ { |
+ *psConfigPath = pchConfigPathOverride; |
+ } |
+ else if( !pathReg.GetConfigPath().empty() ) |
+ { |
+ *psConfigPath = pathReg.GetConfigPath(); |
+ } |
+ else |
+ { |
+ *psConfigPath = ""; |
+ } |
+ } |
+ |
+ if( psLogPath ) |
+ { |
+ if ( GetEnvironmentVariable( k_pchLogOverrideVar ).length() != 0 ) |
+ { |
+ *psLogPath = GetEnvironmentVariable( k_pchLogOverrideVar ); |
+ nCountEnvironmentVariables++; |
+ } |
+ else if( pchLogPathOverride ) |
+ { |
+ *psLogPath = pchLogPathOverride; |
+ } |
+ else if( !pathReg.GetLogPath().empty() ) |
+ { |
+ *psLogPath = pathReg.GetLogPath(); |
+ } |
+ else |
+ { |
+ *psLogPath = ""; |
+ } |
+ } |
+ |
+ if ( pvecExternalDrivers ) |
+ { |
+ *pvecExternalDrivers = pathReg.m_vecExternalDrivers; |
+ } |
+ |
+ if ( nCountEnvironmentVariables == 3 ) |
+ { |
+ // all three environment variables where set, so we don't need the physical file |
+ return true; |
+ } |
+ |
+ return bLoadedRegistry; |
+} |
+ |