OpenWalnutScript.cpp 7.91 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

30 31
#ifdef OW_BOOST_PROGRAM_OPTIONS_FIX
// This circumvents an issue with boost program_options. The linker complains about missing "arg".
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
32 33 34 35 36 37 38
namespace boost
{
    namespace program_options
    {
        std::string arg;
    }
}
39
#endif  // OW_BOOST_PROGRAM_OPTIONS_FIX
40 41 42 43 44 45 46 47 48 49 50 51 52
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>

#include "core/common/WLogger.h"
#include "core/common/WIOTools.h"
#include "core/common/WLogStream.h"
#include "core/common/WThreadedRunner.h"
#include "core/common/WSegmentationFault.h"
#include "core/common/WPathHelper.h"

#include "core/kernel/WKernel.h"
#include "core/kernel/WModuleFactory.h"

53
#include "WScriptUI.h"
54

55
#include "core/WVersion.h"   // NOTE: this file is auto-generated by CMAKE
56 57 58 59 60 61 62 63 64 65 66

/**
 * Print version info to std::cout.
 */
void printVersion()
{
    std::cout << "OpenWalnut -- Version: " << W_VERSION << " ( http://www.openwalnut.org )"
              << std::endl
              << std::endl;

    std::cout <<
67 68 69 70
    "Copyright 2009-2014 The OpenWalnut Community\n"
    "          2012-2014 Nemtics\n"
    "          2009-2014 Abteilung fuer Bild- und Signalverarbeitung, Universitaet Leipzig\n"
    "          2009-2013 Max-Planck Institute of Cognitive Neuroscience, Leipzig, Germany\n"
71 72 73 74 75 76 77 78
    "For more information see http://www.openwalnut.org/copying\n"
    "This program comes with ABSOLUTELY NO WARRANTY.\n"
    "This is free software, and you are welcome to redistribute it\n"
    "under the terms of the GNU Lesser General Public License.\n"
    "You should have received a copy of the GNU Lesser General Public License\n"
    "along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>." << std::endl;
    std::cout << std::endl;  // Create new line after message for clarity.

79
    std::cout << "Written by the OpenWalnut Community, Nemtics, BSV@Uni-Leipzig and CNCF@MPI-CBS." << std::endl;
80 81 82 83 84 85 86 87 88 89 90 91
}

/**
 * The main routine starting up the whole application.
 *
 * \param argc As always.
 * \param argv Nothing to see here.
 *
 * \return 0 on success.
 */
int main( int argc, char** argv )
{
92
    WThreadedRunner::setThisThreadName( "Script UI" );
93 94 95 96 97 98

    // where to write the by default?
    std::string logFile = "openwalnut.log";

    // process user parameter
    namespace po = boost::program_options; // since the namespace is far to big we use a shortcut here
99
    po::options_description desc( "Options" );
100 101 102 103 104 105 106 107

    // NOTE: if you modify this, also modify the manual pages! (use help2man or do it manually) But be careful. There need
    // to be several manual changes to be done in the manual after help2man has done its job.
    desc.add_options()
        ( "help,h", "Prints this help message" )
        ( "version,v", "Prints the version information" )
        ( "log,l", po::value< std::string >(), ( std::string( "The log-file to use. If not specified, \"" ) + logFile +
                                                 std::string( "\" is used in the current directory." ) ).c_str() )
108
        ( "interp,i", po::value< std::string >(), "The interpreter to use." )
109
        ( "file,f", po::value< std::vector< std::string > >()->multitoken(), "The script file to load and its parameters." );
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124

    boost::program_options::variables_map optionsMap;
    try
    {
        po::store( po::command_line_parser( argc, argv ).options( desc ).run(), optionsMap );
    }
    catch( const po::error &e )
    {
        std::cerr << e.what() << std::endl;
        return false;
    }

    po::notify( optionsMap );

    // print usage information if command line asks for help.
125
    if( optionsMap.count( "help" ) || ( optionsMap.count( "interp" ) == 0 && optionsMap.count( "file" ) == 0 ) )
126 127 128 129 130 131 132 133 134 135
    {
        // NOTE: if you modify this, check that help2man still works properly! (http://www.gnu.org/software/help2man) But be careful. There need
        // to be several manual changes to be done in the manual after help2man has done its job.
        std::cout << "OpenWalnut is a highly expansible visualization system with focus on brain- and neurological data." << std::endl
                  << std::endl
                  << "Usage: openwalnut [OPTION]... [FILE]..." << std::endl
                  << std::endl
                  << desc << std::endl
                  << std::endl
                  << "Examples:" << std::endl
136 137
                  << "  openwalnut-script -i lua \t\tStartup OpenWalnut in lua interpreter mode." << std::endl
                  << "  openwalnut-script -f doSth.py\t\tStart OpenWalnut and execute the doSth.py python script." << std::endl
138 139 140 141 142 143 144 145 146 147 148 149 150 151
                  << std::endl;
        return 0;
    }
    else if( optionsMap.count( "version" ) )
    {
        printVersion();
        return 0;
    }

    printVersion();

    // install signal handler as early as possible
    WSegmentationFault::installSignalHandler();

152
    // initialize logger here. It will be started by the UI with one default console stream
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
    WLogger::startup();

    // add a crash-log.
    if( optionsMap.count( "log" ) )
    {
        logFile = optionsMap["log"].as< std::string >();
    }

    // determine log paths
    boost::filesystem::path logPath( logFile );
    logPath = boost::filesystem::system_complete( logPath );
    bool fallbackLog = false; // if true, the original log file could not be opened. A fallback is provided.
    boost::filesystem::path fallbackLogFile = tempFilename( "OpenWalnutLog-%%%%%%%%.log" );

    // is the log writeable?
    std::ofstream crashLogFile( logPath.string().c_str() );
    if( !crashLogFile.is_open() )
    {
        // try to create fallback
        crashLogFile.open( fallbackLogFile.string().c_str() );
        fallbackLog = true;
    }

    // create log stream
    if( crashLogFile.is_open() )
    {
        // create the WLogStream. Set special format and DISABLE colors.
        WLogStream::SharedPtr crashLog = WLogStream::SharedPtr( new WLogStream( crashLogFile, LL_DEBUG, "%t %l %s: %m\n", false ) );
        WLogger::getLogger()->addStream( crashLog );

        // NOTE: the stream flushes after each entry. This is needed if a crash occurs.
        if( !fallbackLog )
        {
            wlog::info( "Walnut" ) << "Using the file \"" << logPath.string() << "\" for logging.";
        }
        else
        {
            wlog::info( "Walnut" ) << "Using the fallback file \"" << fallbackLogFile.string() << "\" for logging.";
        }
    }
    else
    {
        wlog::warn( "Walnut" ) << "Could not open \"" << logPath.string() << "\" for writing. You will have no log-file.";
    }

198
    // the kernel, and the UI should print their version info. This helps processing crashlogs from users.
199 200
    wlog::info( "Walnut" ) << "Version: " << W_VERSION;

201
    // initialize UI
202
    // NOTE: we need a shared_ptr here since WUI uses enable_shared_from_this.
203 204
    boost::shared_ptr< WScriptUI > ui( new WScriptUI( argc, argv, optionsMap ) );
    int result = ui->run();
205 206 207

    std::cout << "Closed OpenWalnut smoothly. Goodbye!" << std::endl;

208
    return result;
209 210
}