logging.h previously had logic to enable debug logging even on release builds. This logic was moved to the QMAKE file, hence the logging.h file is no longer necessary.
394 lines
13 KiB
C++
394 lines
13 KiB
C++
#include "overlaycontroller.h"
|
|
#include <QApplication>
|
|
#include <QQmlApplicationEngine>
|
|
#include <QQuickView>
|
|
#include <QQmlEngine>
|
|
#include <QQmlComponent>
|
|
#include <QSettings>
|
|
#include <QStandardPaths>
|
|
#include <openvr.h>
|
|
#include <iostream>
|
|
#include <easylogging++.h>
|
|
|
|
INITIALIZE_EASYLOGGINGPP
|
|
|
|
void myQtMessageHandler( QtMsgType type,
|
|
const QMessageLogContext& context,
|
|
const QString& msg )
|
|
{
|
|
QByteArray localMsg = msg.toLocal8Bit();
|
|
switch ( type )
|
|
{
|
|
case QtDebugMsg:
|
|
LOG( DEBUG ) << localMsg.constData() << " (" << context.file << ":"
|
|
<< context.line << ")";
|
|
break;
|
|
case QtInfoMsg:
|
|
LOG( INFO ) << localMsg.constData() << " (" << context.file << ":"
|
|
<< context.line << ")";
|
|
break;
|
|
case QtWarningMsg:
|
|
LOG( WARNING ) << localMsg.constData() << " (" << context.file << ":"
|
|
<< context.line << ")";
|
|
break;
|
|
case QtCriticalMsg:
|
|
LOG( ERROR ) << localMsg.constData() << " (" << context.file << ":"
|
|
<< context.line << ")";
|
|
break;
|
|
case QtFatalMsg:
|
|
LOG( FATAL ) << localMsg.constData() << " (" << context.file << ":"
|
|
<< context.line << ")";
|
|
break;
|
|
}
|
|
}
|
|
|
|
void installManifest( bool cleaninstall = false )
|
|
{
|
|
auto manifestQPath
|
|
= QDir::cleanPath( QDir( QCoreApplication::applicationDirPath() )
|
|
.absoluteFilePath( "manifest.vrmanifest" ) );
|
|
if ( QFile::exists( manifestQPath ) )
|
|
{
|
|
bool alreadyInstalled = false;
|
|
if ( vr::VRApplications()->IsApplicationInstalled(
|
|
advsettings::OverlayController::applicationKey ) )
|
|
{
|
|
if ( cleaninstall )
|
|
{
|
|
char buffer[1024];
|
|
auto appError = vr::VRApplicationError_None;
|
|
vr::VRApplications()->GetApplicationPropertyString(
|
|
advsettings::OverlayController::applicationKey,
|
|
vr::VRApplicationProperty_WorkingDirectory_String,
|
|
buffer,
|
|
1024,
|
|
&appError );
|
|
if ( appError == vr::VRApplicationError_None )
|
|
{
|
|
auto oldManifestQPath
|
|
= QDir::cleanPath( QDir( buffer ).absoluteFilePath(
|
|
"manifest.vrmanifest" ) );
|
|
if ( oldManifestQPath.compare( manifestQPath,
|
|
Qt::CaseInsensitive )
|
|
!= 0 )
|
|
{
|
|
vr::VRApplications()->RemoveApplicationManifest(
|
|
QDir::toNativeSeparators( oldManifestQPath )
|
|
.toStdString()
|
|
.c_str() );
|
|
}
|
|
else
|
|
{
|
|
alreadyInstalled = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
alreadyInstalled = true;
|
|
}
|
|
}
|
|
auto apperror = vr::VRApplications()->AddApplicationManifest(
|
|
QDir::toNativeSeparators( manifestQPath ).toStdString().c_str() );
|
|
if ( apperror != vr::VRApplicationError_None )
|
|
{
|
|
throw std::runtime_error(
|
|
std::string( "Could not add application manifest: " )
|
|
+ std::string(
|
|
vr::VRApplications()->GetApplicationsErrorNameFromEnum(
|
|
apperror ) ) );
|
|
}
|
|
else if ( !alreadyInstalled || cleaninstall )
|
|
{
|
|
auto app_error = vr::VRApplications()->SetApplicationAutoLaunch(
|
|
advsettings::OverlayController::applicationKey, true );
|
|
if ( app_error != vr::VRApplicationError_None )
|
|
{
|
|
throw std::runtime_error(
|
|
std::string( "Could not set auto start: " )
|
|
+ std::string( vr::VRApplications()
|
|
->GetApplicationsErrorNameFromEnum(
|
|
apperror ) ) );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error(
|
|
std::string( "Could not find application manifest: " )
|
|
+ manifestQPath.toStdString() );
|
|
}
|
|
}
|
|
|
|
void removeManifest()
|
|
{
|
|
auto manifestQPath
|
|
= QDir::cleanPath( QDir( QCoreApplication::applicationDirPath() )
|
|
.absoluteFilePath( "manifest.vrmanifest" ) );
|
|
if ( QFile::exists( manifestQPath ) )
|
|
{
|
|
if ( vr::VRApplications()->IsApplicationInstalled(
|
|
advsettings::OverlayController::applicationKey ) )
|
|
{
|
|
vr::VRApplications()->RemoveApplicationManifest(
|
|
QDir::toNativeSeparators( manifestQPath )
|
|
.toStdString()
|
|
.c_str() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error(
|
|
std::string( "Could not find application manifest: " )
|
|
+ manifestQPath.toStdString() );
|
|
}
|
|
}
|
|
|
|
class MyQApplication : public QApplication
|
|
{
|
|
public:
|
|
using QApplication::QApplication;
|
|
|
|
virtual bool notify( QObject* receiver, QEvent* event ) override
|
|
{
|
|
try
|
|
{
|
|
return QApplication::notify( receiver, event );
|
|
}
|
|
catch ( std::exception& e )
|
|
{
|
|
LOG( ERROR ) << "Exception thrown from an event handler: "
|
|
<< e.what();
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
namespace argument
|
|
{
|
|
// Checks whether a specific string was passed as a launch argument.
|
|
bool CheckCommandLineArgument( int argc,
|
|
char* argv[],
|
|
const std::string parameter )
|
|
{
|
|
// The old way was one giant loop that tested every single parameter.
|
|
// Having an individual loop for all args most likely has a very small
|
|
// performance penalty compared to the original solution, but the gains in
|
|
// readability and ease of extension of not having a hundred line+ for loop
|
|
// are worth it.
|
|
for ( int i = 0; i < argc; i++ )
|
|
{
|
|
if ( std::string( argv[i] ) == parameter )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
constexpr auto DESKTOP_MODE = "-desktop";
|
|
constexpr auto NO_SOUND = "-nosound";
|
|
constexpr auto NO_MANIFEST = "-nomanifest";
|
|
constexpr auto INSTALL_MANIFEST = "-installmanifest";
|
|
constexpr auto REMOVE_MANIFEST = "-removemanifest";
|
|
} // namespace argument
|
|
|
|
enum ReturnErrorCode
|
|
{
|
|
SUCCESS = 0,
|
|
GENERAL_FAILURE = -1,
|
|
OPENVR_INIT_ERROR = -2,
|
|
};
|
|
|
|
int main( int argc, char* argv[] )
|
|
{
|
|
const char* logConfigFileName = "logging.conf";
|
|
|
|
const char* logConfigDefault
|
|
= "* GLOBAL:\n"
|
|
" FORMAT = \"[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg\"\n"
|
|
" FILENAME = \"AdvancedSettings.log\"\n"
|
|
" ENABLED = true\n"
|
|
" TO_FILE = true\n"
|
|
" TO_STANDARD_OUTPUT = true\n"
|
|
" MAX_LOG_FILE_SIZE = 2097152 ## 2MB\n"
|
|
"* TRACE:\n"
|
|
" ENABLED = false\n"
|
|
"* DEBUG:\n"
|
|
" ENABLED = false\n";
|
|
|
|
const bool desktop_mode = argument::CheckCommandLineArgument(
|
|
argc, argv, argument::DESKTOP_MODE );
|
|
const bool no_sound
|
|
= argument::CheckCommandLineArgument( argc, argv, argument::NO_SOUND );
|
|
const bool no_manifest = argument::CheckCommandLineArgument(
|
|
argc, argv, argument::NO_MANIFEST );
|
|
const bool install_manifest = argument::CheckCommandLineArgument(
|
|
argc, argv, argument::INSTALL_MANIFEST );
|
|
const bool remove_manifest = argument::CheckCommandLineArgument(
|
|
argc, argv, argument::REMOVE_MANIFEST );
|
|
|
|
if ( install_manifest || remove_manifest )
|
|
{
|
|
int exit_code = ReturnErrorCode::SUCCESS;
|
|
QCoreApplication coreApp( argc, argv );
|
|
auto openvr_init_status = vr::VRInitError_None;
|
|
vr::VR_Init( &openvr_init_status, vr::VRApplication_Utility );
|
|
|
|
if ( openvr_init_status == vr::VRInitError_None )
|
|
{
|
|
try
|
|
{
|
|
if ( install_manifest )
|
|
{
|
|
installManifest( true );
|
|
}
|
|
else if ( remove_manifest )
|
|
{
|
|
removeManifest();
|
|
}
|
|
}
|
|
catch ( std::exception& e )
|
|
{
|
|
exit_code = ReturnErrorCode::GENERAL_FAILURE;
|
|
std::cerr << e.what() << std::endl;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
exit_code = ReturnErrorCode::OPENVR_INIT_ERROR;
|
|
std::cerr << std::string(
|
|
"Failed to initialize OpenVR: "
|
|
+ std::string(
|
|
vr::VR_GetVRInitErrorAsEnglishDescription(
|
|
openvr_init_status ) ) )
|
|
<< std::endl;
|
|
}
|
|
|
|
vr::VR_Shutdown();
|
|
exit( exit_code );
|
|
}
|
|
|
|
try
|
|
{
|
|
MyQApplication a( argc, argv );
|
|
a.setOrganizationName( "matzman666" );
|
|
a.setApplicationName( "OpenVRAdvancedSettings" );
|
|
a.setApplicationDisplayName(
|
|
advsettings::OverlayController::applicationName );
|
|
a.setApplicationVersion(
|
|
advsettings::OverlayController::applicationVersionString );
|
|
|
|
qInstallMessageHandler( myQtMessageHandler );
|
|
|
|
// Configure logger
|
|
QString logFilePath;
|
|
START_EASYLOGGINGPP( argc, argv );
|
|
el::Loggers::addFlag(
|
|
el::LoggingFlag::DisableApplicationAbortOnFatalLog );
|
|
auto logconfigfile = QFileInfo( logConfigFileName ).absoluteFilePath();
|
|
el::Configurations conf;
|
|
if ( QFile::exists( logconfigfile ) )
|
|
{
|
|
conf.parseFromFile( logconfigfile.toStdString() );
|
|
}
|
|
else
|
|
{
|
|
conf.parseFromText( logConfigDefault );
|
|
}
|
|
if ( !conf.get( el::Level::Global, el::ConfigurationType::Filename ) )
|
|
{
|
|
logFilePath = QDir( QStandardPaths::writableLocation(
|
|
QStandardPaths::AppDataLocation ) )
|
|
.absoluteFilePath( "AdvancedSettings.log" );
|
|
conf.set( el::Level::Global,
|
|
el::ConfigurationType::Filename,
|
|
QDir::toNativeSeparators( logFilePath ).toStdString() );
|
|
}
|
|
conf.setRemainingToDefault();
|
|
el::Loggers::reconfigureAllLoggers( conf );
|
|
LOG( INFO ) << "Application started (Version "
|
|
<< advsettings::OverlayController::applicationVersionString
|
|
<< ")";
|
|
LOG( INFO ) << "Log Config: "
|
|
<< QDir::toNativeSeparators( logconfigfile ).toStdString();
|
|
if ( !logFilePath.isEmpty() )
|
|
{
|
|
LOG( INFO ) << "Log File: " << logFilePath;
|
|
}
|
|
|
|
if ( desktop_mode )
|
|
{
|
|
LOG( INFO ) << "Desktop mode enabled.";
|
|
}
|
|
if ( no_sound )
|
|
{
|
|
LOG( INFO ) << "Sound effects disabled.";
|
|
}
|
|
if ( no_manifest )
|
|
{
|
|
LOG( INFO ) << "vrmanifest disabled.";
|
|
}
|
|
|
|
QSettings appSettings( QSettings::IniFormat,
|
|
QSettings::UserScope,
|
|
a.organizationName(),
|
|
a.applicationName() );
|
|
advsettings::OverlayController::setAppSettings( &appSettings );
|
|
LOG( INFO ) << "Settings File: "
|
|
<< appSettings.fileName().toStdString();
|
|
|
|
QQmlEngine qmlEngine;
|
|
|
|
advsettings::OverlayController* controller
|
|
= advsettings::OverlayController::createInstance( desktop_mode,
|
|
no_sound );
|
|
controller->Init( &qmlEngine );
|
|
|
|
QQmlComponent component(
|
|
&qmlEngine, QUrl::fromLocalFile( "res/qml/mainwidget.qml" ) );
|
|
auto errors = component.errors();
|
|
for ( auto& e : errors )
|
|
{
|
|
LOG( ERROR ) << "QML Error: " << e.toString().toStdString()
|
|
<< std::endl;
|
|
}
|
|
auto quickObj = component.create();
|
|
controller->SetWidget( qobject_cast<QQuickItem*>( quickObj ),
|
|
advsettings::OverlayController::applicationName,
|
|
advsettings::OverlayController::applicationKey );
|
|
|
|
if ( !desktop_mode && !no_manifest )
|
|
{
|
|
try
|
|
{
|
|
installManifest();
|
|
}
|
|
catch ( std::exception& e )
|
|
{
|
|
LOG( ERROR ) << e.what();
|
|
}
|
|
}
|
|
|
|
if ( desktop_mode )
|
|
{
|
|
auto m_pWindow = new QQuickWindow();
|
|
qobject_cast<QQuickItem*>( quickObj )
|
|
->setParentItem( m_pWindow->contentItem() );
|
|
m_pWindow->setGeometry(
|
|
0,
|
|
0,
|
|
qobject_cast<QQuickItem*>( quickObj )->width(),
|
|
qobject_cast<QQuickItem*>( quickObj )->height() );
|
|
m_pWindow->show();
|
|
}
|
|
|
|
return a.exec();
|
|
}
|
|
catch ( const std::exception& e )
|
|
{
|
|
LOG( FATAL ) << e.what();
|
|
return ReturnErrorCode::GENERAL_FAILURE;
|
|
}
|
|
}
|