| 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;
|
| +}
|
| +
|
|
|