WKernel.cpp 7.7 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"
ebaum's avatar
[ADD]  
ebaum committed
46

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

49
#include "WKernel.h"
50

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

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

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

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

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

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

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

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

88
void WKernel::init()
ebaum's avatar
[ADD]  
ebaum committed
89
{
90
    // initialize
91 92 93 94 95 96 97 98 99 100
    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
101
    m_graphicsEngine->setShaderPath( WKernel::m_shaderPath );
102 103 104 105 106 107

    // initialize Datahandler
    m_dataHandler = boost::shared_ptr< WDataHandler >( new WDataHandler() );

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

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

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

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

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

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

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

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

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

145 146 147
    // start GE
    m_graphicsEngine->run();

148
    // default modules
149 150
    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 );
schurade's avatar
schurade committed
151
    m_moduleContainer->add( m_moduleFactory->create( m_moduleFactory->getPrototypeByName( "HUD" ) ) , true );
152

153 154
    // actually there is nothing more to do here
    waitForStop();
155

156
    WLogger::getLogger()->addLogMessage( "Shutting down Kernel", "Kernel", LL_INFO );
157 158
}

159
void WKernel::findAppPath()
160
{
161 162 163 164 165 166
    // only get the path if not already done
    if ( m_AppPath != "" )
    {
        return;
    }

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

    // 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
    // char* sappPath = get_current_dir_name();

175 176 177 178 179 180 181 182
    int length;
    char appPath[255];

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

    // Catch some errors
    if ( length < 0 )
    {
183
        WLogger::getLogger()->addLogMessage( "Error resolving symlink /proc/self/exe.", "Kernel", LL_ERROR );
184 185 186
    }
    if ( length >= 255 )
    {
187
        WLogger::getLogger()->addLogMessage( "Path too long. Truncated.", "Kernel", LL_ERROR );
188 189 190 191 192 193 194 195 196 197
    }

    // 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;
schurade's avatar
schurade committed
198
        assert( length >= 0 );
199 200 201 202 203
    }

    m_AppPath = appPath;

    std::string shaderPath( appPath );
204
    m_shaderPath = shaderPath + "shaders/";
205

schurade's avatar
schurade committed
206
#elif defined( __APPLE__ )
207
    char path[1024];
schurade's avatar
schurade committed
208
    uint32_t size = sizeof( path );
209
    if( _NSGetExecutablePath( path, &size ) == 0 )
210
    {
211
        WLogger::getLogger()->addLogMessage( "Executable path is " + std::string( path ), "Kernel", LL_DEBUG );
212 213

        int i = strlen( path );
schurade's avatar
schurade committed
214 215 216 217 218 219
        while( path[i] != '/' )
        {
            path[i] = '\0';
            i--;
            assert( i >= 0 );
        }
220
        WLogger::getLogger()->addLogMessage( "Application path is " + std::string( path ), "Kernel", LL_DEBUG );
schurade's avatar
schurade committed
221 222 223 224
        m_AppPath = path;

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

242
const WBoolFlag& WKernel::isFinishRequested() const
ebaum's avatar
ebaum committed
243
{
244
    return m_shutdownFlag;
ebaum's avatar
[ADD]  
ebaum committed
245 246
}

247
void WKernel::loadDataSets( std::vector< std::string > fileNames )
248
{
249
    // add a new data module for each file to load
250 251
    using boost::shared_ptr;
    for( std::vector< std::string >::iterator iter = fileNames.begin(); iter != fileNames.end(); ++iter )
252
    {
253
        shared_ptr< WModule > mod = m_moduleFactory->create( m_moduleFactory->getPrototypeByName( "Data Module" ) );
254 255 256
        mod->getProperties()->setValue( "filename" , ( *iter ) );
        m_moduleContainer->add( mod );
    }
257 258
}

259
boost::shared_ptr< WModule > WKernel::applyModule( boost::shared_ptr< WModule > applyOn, boost::shared_ptr< WModule > prototype )
260
{
261
    return getRootContainer()->applyModule( applyOn, prototype );
262 263
}

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
264
boost::shared_ptr< WDataHandler > WKernel::getDataHandler() const
265
{
266
    return m_dataHandler;
267 268
}

269
std::string WKernel::getAppPath()
270
{
271 272
    findAppPath();
    return WKernel::m_AppPath;
273 274
}

275
std::string WKernel::getShaderPath()
276
{
277 278
    findAppPath();
    return WKernel::m_shaderPath;
279
}