Files
OpenVR-AdvancedSettings-frame/src/utils/setup.cpp
T
Vasily 2e42773529 Add special message to Qt handler
This makes it more obvious where an error came from.
2019-03-31 14:19:05 +02:00

276 lines
9.6 KiB
C++

#include "setup.h"
// The default Qt message handler prints to stdout on X11 and to the debugger on
// Windows. That is borderline useless for us, therefore we create our own
// message handler.
void mainQtMessageHandler( QtMsgType type,
const QMessageLogContext& context,
const QString& msg )
{
// context contains null pointers on release builds. Cast to get rid of
// unreferenced formal parameter warnings.
static_cast<void>( context );
QByteArray localMsg = msg.toLocal8Bit();
switch ( type )
{
case QtDebugMsg:
LOG( DEBUG ) << "QTMSGH: " << localMsg.constData();
break;
case QtInfoMsg:
LOG( INFO ) << "QTMSGH: " << localMsg.constData();
break;
case QtWarningMsg:
LOG( WARNING ) << "QTMSGH: " << localMsg.constData();
break;
case QtCriticalMsg:
LOG( ERROR ) << "QTMSGH: " << localMsg.constData();
break;
case QtFatalMsg:
LOG( FATAL ) << "QTMSGH: " << localMsg.constData();
break;
}
}
namespace argument
{
CommandLineOptions returnCommandLineParser( const MyQApplication& application )
{
QCommandLineParser parser;
parser.setApplicationDescription(
"Advanced Settings overlay for SteamVR." );
parser.addHelpOption();
parser.addVersionOption();
QCommandLineOption desktopMode( k_desktopMode, k_desktopModeDescription );
parser.addOption( desktopMode );
QCommandLineOption forceNoSound( k_forceNoSound,
k_forceNoSoundDescription );
parser.addOption( forceNoSound );
QCommandLineOption forceNoManifest( k_forceNoManifest,
k_forceNoManifestDescription );
parser.addOption( forceNoManifest );
QCommandLineOption forceInstallManifest(
k_forceInstallManifest, k_forceInstallManifestDescription );
parser.addOption( forceInstallManifest );
QCommandLineOption forceRemoveManifest( k_forceRemoveManifest,
k_forceRemoveManifestDescription );
parser.addOption( forceRemoveManifest );
parser.process( application );
const bool desktopModeEnabled = parser.isSet( desktopMode );
LOG_IF( desktopModeEnabled, INFO ) << "Desktop mode enabled.";
const bool forceNoSoundEnabled = parser.isSet( forceNoSound );
LOG_IF( forceNoSoundEnabled, INFO ) << "Sound effects disabled.";
const bool forceNoManifestEnabled = parser.isSet( forceNoManifest );
LOG_IF( forceNoManifestEnabled, INFO )
<< "Running without applications manifest.";
const bool forceInstallManifestEnabled
= parser.isSet( forceInstallManifest );
LOG_IF( forceInstallManifestEnabled, INFO )
<< "Forcing install of applications manifest.";
const bool forceRemoveManifestEnabled = parser.isSet( forceRemoveManifest );
LOG_IF( forceRemoveManifestEnabled, INFO )
<< "Forcing removal of applications manifest.";
const CommandLineOptions commandLineArgs{ desktopModeEnabled,
forceNoSoundEnabled,
forceNoManifestEnabled,
forceInstallManifestEnabled,
forceRemoveManifestEnabled };
LOG( INFO ) << "Command line arguments processed.";
return commandLineArgs;
}
} // namespace argument
namespace manifest
{
// Enables autostart of OpenVR Advanced Settings.
void enableApplicationAutostart()
{
const auto app_error = vr::VRApplications()->SetApplicationAutoLaunch(
application_strings::applicationKey, true );
if ( app_error != vr::VRApplicationError_None )
{
throw std::runtime_error(
std::string( "Could not set auto start: " )
+ std::string(
vr::VRApplications()->GetApplicationsErrorNameFromEnum(
app_error ) ) );
}
}
// Installs the application manifest. If a manifest with the same application
// key is already installed, nothing will happen.
// OpenVR must be initialized before calling this function.
void installApplicationManifest( const std::string manifestPath )
{
const auto app_error
= vr::VRApplications()->AddApplicationManifest( manifestPath.c_str() );
if ( app_error != vr::VRApplicationError_None )
{
throw std::runtime_error(
std::string( "Could not add application manifest: " )
+ std::string(
vr::VRApplications()->GetApplicationsErrorNameFromEnum(
app_error ) ) );
}
}
// Removes the application manifest.
void removeApplicationManifest( const std::string manifestPath )
{
if ( vr::VRApplications()->IsApplicationInstalled(
application_strings::applicationKey ) )
{
vr::VRApplications()->RemoveApplicationManifest( manifestPath.c_str() );
}
}
// Removes and then installs the application manifest.
void reinstallApplicationManifest( const std::string manifestPath )
{
if ( vr::VRApplications()->IsApplicationInstalled(
application_strings::applicationKey ) )
{
LOG( INFO ) << "Manifest Previously Installed";
// String size was arbitrarily chosen by original author.
constexpr auto kStringSize = 1024;
char oldApplicationWorkingDir[kStringSize] = { 0 };
auto app_error = vr::VRApplicationError_None;
vr::VRApplications()->GetApplicationPropertyString(
application_strings::applicationKey,
vr::VRApplicationProperty_WorkingDirectory_String,
oldApplicationWorkingDir,
kStringSize,
&app_error );
if ( app_error != vr::VRApplicationError_None )
{
throw std::runtime_error(
"Could not find working directory of already "
"installed application: "
+ std::string(
vr::VRApplications()->GetApplicationsErrorNameFromEnum(
app_error ) ) );
}
const auto oldManifestPath
= QDir::cleanPath( QDir( oldApplicationWorkingDir )
.absoluteFilePath( kVRManifestName ) );
removeApplicationManifest( manifestPath );
}
installApplicationManifest( manifestPath );
}
// Initializes OpenVR and calls the relevant manifest functions.
// The .vrmanifest is used by SteamVR however the exact functiontionality is not
// documented in the official documentation.
// The manifest is installed upon using the NSIS installer for windows (this
// program is called with "--force-install-manifest" by the installer) and every
// time the program is launched without both "--desktop-mode" and
// "--force-no-manifest". The OpenVR initialization is necessary for both
// removing and installing manifests.
[[noreturn]] void handleManifests( const bool installManifest,
const bool removeManifest )
{
openvr_init::initializeOpenVR(
openvr_init::OpenVrInitializationType::Utility );
int exit_code = ReturnErrorCode::SUCCESS;
try
{
const auto manifestPath
= paths::binaryDirectoryFindFile( manifest::kVRManifestName );
if ( !manifestPath.has_value() )
{
throw std::runtime_error( "Could not find application manifest." );
}
if ( installManifest )
{
reinstallApplicationManifest( *manifestPath );
enableApplicationAutostart();
LOG( INFO ) << "Manifest reinstalled.";
}
else if ( removeManifest )
{
removeApplicationManifest( *manifestPath );
LOG( INFO ) << "Manifest removed.";
}
}
catch ( std::exception& e )
{
exit_code = ReturnErrorCode::GENERAL_FAILURE;
LOG( ERROR ) << e.what();
}
vr::VR_Shutdown();
exit( exit_code );
}
} // namespace manifest
void setUpLogging()
{
el::Loggers::addFlag( el::LoggingFlag::DisableApplicationAbortOnFatalLog );
el::Configurations conf;
conf.setToDefault();
using el::ConfigurationType;
using el::Level;
conf.set( Level::Global,
ConfigurationType::Format,
"[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg" );
constexpr auto logFileName = "AdvancedSettings.log";
conf.set( Level::Global, ConfigurationType::Filename, logFileName );
constexpr auto confEnabled = "true";
conf.set( Level::Global, ConfigurationType::Enabled, confEnabled );
conf.set( Level::Global, ConfigurationType::ToFile, confEnabled );
conf.set( Level::Global, ConfigurationType::ToStandardOutput, confEnabled );
constexpr auto TwoMegabytesInBytes = "2097152";
conf.set(
Level::Global, ConfigurationType::MaxLogFileSize, TwoMegabytesInBytes );
constexpr auto confDisabled = "false";
conf.set( Level::Trace, ConfigurationType::Enabled, confDisabled );
conf.set( Level::Debug, ConfigurationType::Enabled, confDisabled );
const auto appDataLocation
= std::string( "/" ) + application_strings::applicationOrganizationName
+ "/";
const auto logFilePath
= QDir( QString::fromStdString( *paths::settingsDirectory() )
+ appDataLocation.c_str() )
.absoluteFilePath( logFileName );
conf.set( el::Level::Global,
el::ConfigurationType::Filename,
QDir::toNativeSeparators( logFilePath ).toStdString() );
conf.setRemainingToDefault();
el::Loggers::reconfigureAllLoggers( conf );
LOG( INFO ) << "Application started (Version "
<< application_strings::applicationVersionString << ")";
LOG( INFO ) << "Log File: " << logFilePath;
}