summaryrefslogtreecommitdiffstats
path: root/gfx/vr/service/openvr/src/vrpathregistry_public.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/vr/service/openvr/src/vrpathregistry_public.cpp')
-rw-r--r--gfx/vr/service/openvr/src/vrpathregistry_public.cpp442
1 files changed, 442 insertions, 0 deletions
diff --git a/gfx/vr/service/openvr/src/vrpathregistry_public.cpp b/gfx/vr/service/openvr/src/vrpathregistry_public.cpp
new file mode 100644
index 0000000000..0af46e57cb
--- /dev/null
+++ b/gfx/vr/service/openvr/src/vrpathregistry_public.cpp
@@ -0,0 +1,442 @@
+//========= 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( __MINGW32__ )
+ #define VRLog(args...) fprintf(stderr, args)
+ #elif 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 defaultManager] 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 sOverridePath = GetEnvironmentVariable( "VR_PATHREG_OVERRIDE" );
+ if ( !sOverridePath.empty() )
+ return sOverridePath;
+
+ 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;
+}
+
+// Mozilla: see mozilla.patch for more details
+// ---------------------------------------------------------------------------
+// Purpose: Loads the config file from its well known location
+// ---------------------------------------------------------------------------
+bool CVRPathRegistry_Public::BLoadFromFile( std::string *psLoadError )
+{
+ std::string sRegPath = GetVRPathRegistryFilename();
+ if( sRegPath.empty() )
+ {
+ if ( psLoadError )
+ {
+ *psLoadError = "Unable to determine VR Path Registry filename";
+ }
+ return false;
+ }
+
+ std::string sRegistryContents = Path_ReadTextFile( sRegPath );
+ if( sRegistryContents.empty() )
+ {
+ if ( psLoadError )
+ {
+ *psLoadError = "Unable to read VR Path Registry from " + sRegPath;
+ }
+ return false;
+ }
+
+ Json::Value root;
+ Json::CharReaderBuilder builder;
+ std::istringstream istream( sRegistryContents );
+ std::string sErrors;
+
+// try
+ {
+ if ( !parseFromStream( builder, istream, &root, &sErrors ) )
+ {
+ if ( psLoadError )
+ {
+ *psLoadError = "Unable to parse " + sRegPath + ": " + sErrors;
+ }
+ 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" );
+ }
+ }
+// catch ( ... )
+// {
+// if ( psLoadError )
+// {
+// *psLoadError = "Unable to parse " + sRegPath + ": exception thrown in JSON library";
+// }
+// return false;
+// }
+
+ return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Saves the config file to its well known location
+// ---------------------------------------------------------------------------
+bool CVRPathRegistry_Public::BSaveToFile() const
+{
+ 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::StreamWriterBuilder builder;
+ std::string sRegistryContents = Json::writeString( builder, 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;
+}
+
+
+// ---------------------------------------------------------------------------
+// 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 )
+{
+ std::string sLoadError;
+ CVRPathRegistry_Public pathReg;
+ bool bLoadedRegistry = pathReg.BLoadFromFile( &sLoadError );
+ int nCountEnvironmentVariables = 0;
+ int nRequestedPaths = 0;
+
+ if( psRuntimePath )
+ {
+ nRequestedPaths++;
+ if ( GetEnvironmentVariable( k_pchRuntimeOverrideVar ).length() != 0 )
+ {
+ *psRuntimePath = GetEnvironmentVariable( k_pchRuntimeOverrideVar );
+ nCountEnvironmentVariables++;
+ }
+ else if( !pathReg.GetRuntimePath().empty() )
+ {
+ *psRuntimePath = pathReg.GetRuntimePath();
+ }
+ else
+ {
+ *psRuntimePath = "";
+ }
+ }
+
+ if( psConfigPath )
+ {
+ nRequestedPaths++;
+ 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 )
+ {
+ nRequestedPaths++;
+ 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 == nRequestedPaths )
+ {
+ // all three environment variables were set, so we don't need the physical file
+ return true;
+ }
+ else if( !bLoadedRegistry )
+ {
+ VRLog( "%s\n", sLoadError.c_str() );
+ }
+
+ return bLoadedRegistry;
+}
+