WKernel.cpp 7.89 KB
Newer Older
ebaum's avatar
[ADD]  
ebaum committed
1 2
//---------------------------------------------------------------------------
//
3
// Project: OpenWalnut ( http://www.openwalnut.org )
ebaum's avatar
[ADD]  
ebaum committed
4
//
5 6
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
ebaum's avatar
[ADD]  
ebaum committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
//
// 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/>.
//
//---------------------------------------------------------------------------

25 26 27 28
#ifdef __linux__
#include <unistd.h> // used for getcwd (to get current directory)
#endif

29 30 31 32
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif

ebaum's avatar
[ADD]  
ebaum committed
33
#include <iostream>
ebaum's avatar
ebaum committed
34
#include <list>
35 36
#include <string>
#include <vector>
ebaum's avatar
ebaum committed
37 38

#include <boost/thread/xtime.hpp>
ebaum's avatar
[ADD]  
ebaum committed
39

ebaum's avatar
ebaum committed
40
#include "WModule.h"
41
#include "WModuleFactory.h"
ebaum's avatar
[ADD]  
ebaum committed
42
#include "../common/WException.h"
43
#include "../common/WCondition.h"
44
#include "../common/WConditionOneShot.h"
45
#include "../common/WFlag.h"
46
#include "../common/WPreferences.h"
ebaum's avatar
[ADD]  
ebaum committed
47

ebaum's avatar
ebaum committed
48 49
#include "../graphicsEngine/WGraphicsEngine.h"

50
#include "WKernel.h"
51

52
/**
ebaum's avatar
ebaum committed
53 54 55 56
 * Used for program wide access to the kernel.
 */
WKernel* kernel = NULL;

57 58 59 60 61 62 63 64 65 66
/**
 * Define shader path.
 */
std::string WKernel::m_shaderPath = std::string();

/**
 * Define app path.
 */
std::string WKernel::m_AppPath = std::string();

67
WKernel::WKernel( boost::shared_ptr< WGraphicsEngine > ge, boost::shared_ptr< WGUI > gui ):
68
    WThreadedRunner()
ebaum's avatar
[ADD]  
ebaum committed
69
{
70
    WLogger::getLogger()->addLogMessage( "Initializing Kernel", "Kernel", LL_INFO );
ebaum's avatar
ebaum committed
71

72
    // init the singleton
ebaum's avatar
ebaum committed
73 74
    kernel = this;

ebaum's avatar
[ADD]  
ebaum committed
75
    // initialize members
76 77
    m_gui = gui;
    m_graphicsEngine = ge;
78

79
    // init
ebaum's avatar
ebaum committed
80
    init();
ebaum's avatar
[ADD]  
ebaum committed
81 82 83 84 85
}

WKernel::~WKernel()
{
    // cleanup
86
    WLogger::getLogger()->addLogMessage( "Shutting down Kernel", "Kernel", LL_INFO );
ebaum's avatar
[ADD]  
ebaum committed
87 88
}

89
void WKernel::init()
ebaum's avatar
[ADD]  
ebaum committed
90
{
91
    // initialize
92 93 94 95 96 97 98 99 100 101
    findAppPath();

    // get module factory
    m_moduleFactory = WModuleFactory::getModuleFactory();

    // initialize module container
    m_moduleContainer = boost::shared_ptr< WModuleContainer >( new WModuleContainer( "KernelRootContainer",
                "Root module container in Kernel." ) );

    // initialize graphics engine, or, at least set some stuff
102
    m_graphicsEngine->setShaderPath( WKernel::m_shaderPath );
103 104 105

    // load all modules
    m_moduleFactory->load();
ebaum's avatar
[ADD]  
ebaum committed
106 107
}

ebaum's avatar
ebaum committed
108 109 110 111 112
WKernel* WKernel::getRunningKernel()
{
    return kernel;
}

113
boost::shared_ptr< WGraphicsEngine > WKernel::getGraphicsEngine() const
ebaum's avatar
ebaum committed
114
{
115
    return m_graphicsEngine;
ebaum's avatar
ebaum committed
116 117
}

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
118
boost::shared_ptr< WModuleContainer > WKernel::getRootContainer() const
119
{
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
120
    return m_moduleContainer;
121 122
}

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
123
boost::shared_ptr< WGUI > WKernel::getGui() const
124
{
125
    return m_gui;
126 127
}

128
void WKernel::finalize()
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
129
{
130
    WLogger::getLogger()->addLogMessage( "Stopping Kernel", "Kernel", LL_INFO );
131 132

    // NOTE: stopping a container erases all modules inside.
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
133
    getRootContainer()->stop();
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
134 135
}

136
void WKernel::threadMain()
ebaum's avatar
ebaum committed
137
{
138
    WLogger::getLogger()->addLogMessage( "Starting Kernel", "Kernel", LL_INFO );
ebaum's avatar
ebaum committed
139

140
    // wait for GUI to be initialized properly
141
    m_gui->isInitialized().wait();
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
142

143 144 145
    // start GE
    m_graphicsEngine->run();

146
    // default modules
147 148 149 150 151 152 153 154 155
    {
        bool ignore;
        m_moduleContainer->add( m_moduleFactory->create( m_moduleFactory->getPrototypeByName( "Navigation Slice Module" ) ) , true );
        m_moduleContainer->add( m_moduleFactory->create( m_moduleFactory->getPrototypeByName( "Coordinate System Module" ) ) , true );
        if( !( WPreferences::getPreference( "modules.standard.ignoreHUD", &ignore ) && ignore ) )
        {
            m_moduleContainer->add( m_moduleFactory->create( m_moduleFactory->getPrototypeByName( "HUD" ) ) , true );
        }
    }
156

157 158
    // actually there is nothing more to do here
    waitForStop();
159

160
    WLogger::getLogger()->addLogMessage( "Shutting down Kernel", "Kernel", LL_INFO );
161 162
}

163
void WKernel::findAppPath()
164
{
165 166 167 168 169 170
    // only get the path if not already done
    if ( m_AppPath != "" )
    {
        return;
    }

171 172
    // FIXME (schurade)
    // this should work on linux, have to implement it for windows and mac later
Alexander Wiebel's avatar
Alexander Wiebel committed
173
#ifdef __linux__
174 175 176

    // This might be the better alternative to the below code but it does not print the path to the executable, but to the current
    // working directory, which in the unix world is the better choice as path
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
    char* appPath = get_current_dir_name();

    // int length;
    //char appPath[255];

    //length = readlink( "/proc/self/exe", appPath, sizeof( appPath ) );

    //// Catch some errors
    //if ( length < 0 )
    //{
    //    WLogger::getLogger()->addLogMessage( "Error resolving symlink /proc/self/exe.", "Kernel", LL_ERROR );
    //}
    //if ( length >= 255 )
    //{
    //    WLogger::getLogger()->addLogMessage( "Path too long. Truncated.", "Kernel", LL_ERROR );
    //}

    //// the string this readlink() function returns is appended with a '@'.
    //appPath[length] = '\0';

    //// strip off the executable name
    //while ( appPath[length] != '/' )
    //{
    //    appPath[length] = '\0';
    //    --length;
    //    assert( length >= 0 );
    //}
204 205

    m_AppPath = appPath;
206 207
    m_AppPath += "/";
    m_shaderPath = m_AppPath + "shaders/";
208

209 210
    // getcwd/get_current_dir_name() mallocs memory, free it here
    delete appPath;
211

schurade's avatar
schurade committed
212
#elif defined( __APPLE__ )
213
    char path[1024];
schurade's avatar
schurade committed
214
    uint32_t size = sizeof( path );
215
    if( _NSGetExecutablePath( path, &size ) == 0 )
216
    {
217
        WLogger::getLogger()->addLogMessage( "Executable path is " + std::string( path ), "Kernel", LL_DEBUG );
218 219

        int i = strlen( path );
schurade's avatar
schurade committed
220 221 222 223 224 225
        while( path[i] != '/' )
        {
            path[i] = '\0';
            i--;
            assert( i >= 0 );
        }
226
        WLogger::getLogger()->addLogMessage( "Application path is " + std::string( path ), "Kernel", LL_DEBUG );
schurade's avatar
schurade committed
227 228 229 230
        m_AppPath = path;

        std::string shaderPath( path );
        m_shaderPath = shaderPath + "shaders/";
231 232 233
    }
    else
    {
234
        WLogger::getLogger()->addLogMessage( "Buffer too small; need size " + boost::lexical_cast< std::string >( size ),
235
                                             "Kernel", LL_ERROR );
schurade's avatar
schurade committed
236
        assert( size <= sizeof( path ) );
237 238
    }
#else
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
239
#pragma message( "Error: findAppPath not implemented for this platform" )
240 241 242 243 244
    // for windows, use something like this:
    // DWORD GetModuleFileName( NULL, HMODULE hModule, // handle to module
    //                                LPTSTR lpFilename, // path buffer
    //                                DWORD nSize // size of buffer
    // );
245
#endif
ebaum's avatar
ebaum committed
246 247
}

248
const WBoolFlag& WKernel::isFinishRequested() const
ebaum's avatar
ebaum committed
249
{
250
    return m_shutdownFlag;
ebaum's avatar
[ADD]  
ebaum committed
251 252
}

253
void WKernel::loadDataSets( std::vector< std::string > fileNames )
254
{
255
    // add a new data module for each file to load
256 257
    using boost::shared_ptr;
    for( std::vector< std::string >::iterator iter = fileNames.begin(); iter != fileNames.end(); ++iter )
258
    {
259
        shared_ptr< WModule > mod = m_moduleFactory->create( m_moduleFactory->getPrototypeByName( "Data Module" ) );
260 261
        mod->getProperties()->setValue( "filename" , ( *iter ) );
        m_moduleContainer->add( mod );
Alexander Wiebel's avatar
Alexander Wiebel committed
262
        // serialize loading of a couple of data sets
263
        mod->isReady().wait();
264
    }
265 266
}

267
boost::shared_ptr< WModule > WKernel::applyModule( boost::shared_ptr< WModule > applyOn, boost::shared_ptr< WModule > prototype )
268
{
269
    return getRootContainer()->applyModule( applyOn, prototype );
270 271
}

272
std::string WKernel::getAppPath()
273
{
274 275
    findAppPath();
    return WKernel::m_AppPath;
276 277
}

278
std::string WKernel::getShaderPath()
279
{
280 281
    findAppPath();
    return WKernel::m_shaderPath;
282
}