WKernel.cpp 7.68 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 25
//
// 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 <iostream>
ebaum's avatar
ebaum committed
26
#include <list>
27 28
#include <string>
#include <vector>
ebaum's avatar
ebaum committed
29 30

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

#include "WKernel.h"
ebaum's avatar
ebaum committed
33
#include "WModule.h"
34
#include "../modules/navigationSlices/WNavigationSliceModule.h"
ebaum's avatar
[ADD]  
ebaum committed
35 36
#include "../common/WException.h"

ebaum's avatar
ebaum committed
37 38
#include "../graphicsEngine/WGraphicsEngine.h"

39 40 41 42
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif

43
/**
ebaum's avatar
ebaum committed
44 45 46 47
 * Used for program wide access to the kernel.
 */
WKernel* kernel = NULL;

48 49
WKernel::WKernel( int argc, char* argv[], boost::shared_ptr< WGUI > gui )
    : m_Gui( gui )
ebaum's avatar
[ADD]  
ebaum committed
50
{
ebaum's avatar
ebaum committed
51 52 53 54
    std::cout << "Initializing Kernel" << std::endl;

    kernel = this;

ebaum's avatar
[ADD]  
ebaum committed
55
    // initialize members
ebaum's avatar
ebaum committed
56 57 58
    m_ArgC = argc;
    m_ArgV = argv;
    m_FinishRequested = false;
ebaum's avatar
[ADD]  
ebaum committed
59

ebaum's avatar
ebaum committed
60 61 62
    // init GE, DataHandler, ...
    init();

ebaum's avatar
[ADD]  
ebaum committed
63 64 65 66 67 68 69
    // load modules
    loadModules();
}

WKernel::~WKernel()
{
    // cleanup
70
    WLogger::getLogger()->addLogMessage( "Shutting down Kernel", "Kernel", LL_DEBUG );
71 72

    // finish running thread
73
    WLogger::getLogger()->wait( true );
74
    // write remaining log messages
75
    WLogger::getLogger()->processQueue();
ebaum's avatar
[ADD]  
ebaum committed
76 77 78 79 80 81 82
}

WKernel::WKernel( const WKernel& other )
{
    *this = other;
}

ebaum's avatar
ebaum committed
83 84 85 86 87
WKernel* WKernel::getRunningKernel()
{
    return kernel;
}

88
boost::shared_ptr<WGraphicsEngine> WKernel::getGraphicsEngine() const
ebaum's avatar
ebaum committed
89 90 91 92
{
    return m_GraphicsEngine;
}

93 94 95 96 97
boost::shared_ptr<WDataHandler> WKernel::getDataHandler() const
{
    return m_DataHandler;
}

98
boost::shared_ptr< WGUI > WKernel::getGui()
99 100 101 102
{
    return m_Gui;
}

103 104 105 106
void WKernel::setGui( boost::shared_ptr< WGUI > gui )
{
    m_Gui = gui;
}
107

108
int WKernel::getArgumentCount() const
ebaum's avatar
ebaum committed
109 110 111 112
{
    return m_ArgC;
}

113
char** WKernel::getArguments() const
ebaum's avatar
ebaum committed
114 115 116 117 118 119
{
    return m_ArgV;
}

int WKernel::run()
{
120
    WLogger::getLogger()->addLogMessage( "Starting Kernel", "Kernel", LL_DEBUG );
ebaum's avatar
ebaum committed
121 122 123 124 125 126 127 128 129 130

    // TODO(ebaum): add separate graphics thread here
    m_GraphicsEngine->run();

    // run Gui
    // TODO(all): clean up this option handler mess
    m_Gui->run();

    // run? data handler stuff?

131 132 133 134
    // **************************************************************************************************************************
    // This part will be exchanged by some kind of ModuleContainer managing module execution.
    // TODO(ebaum): replace by ModuleContainer
    // **************************************************************************************************************************
135

ebaum's avatar
ebaum committed
136 137 138
    // run module execution threads
    // TODO(ebaum): after having modules loaded they should be started here.
    // currently this is just the test module
139
    WLogger::getLogger()->addLogMessage( "*** Starting modules:", "Kernel", LL_DEBUG );
140
    for( std::list<boost::shared_ptr<WModule> >::iterator list_iter = m_modules.begin(); list_iter != m_modules.end();
wiebel's avatar
[STYLE]  
wiebel committed
141
            ++list_iter )
ebaum's avatar
ebaum committed
142
    {
143
        WLogger::getLogger()->addLogMessage( "Starting module: " + ( *list_iter )->getName(), "Kernel", LL_DEBUG );
ebaum's avatar
ebaum committed
144 145 146
        ( *list_iter )->run();
    }

147 148 149 150 151
    // TODO(schurade): this must be moved somewhere else, and realize the wait loop in another fashion
    while ( !m_Gui->isInitalized() )
    {
    }
    m_Gui->getLoadButtonSignal()->connect( boost::bind( &WKernel::doLoadDataSets, this, _1 ) );
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
152 153

    for( std::list<boost::shared_ptr<WModule> >::iterator list_iter = m_modules.begin(); list_iter != m_modules.end();
154 155 156 157 158
                ++list_iter )
    {
        ( *list_iter )->connectToGui();
    }

ebaum's avatar
ebaum committed
159
    // wait
160
    // TODO(ebaum): this is not the optimal. It would be better to quit OSG, GE and so on in the right order.
ebaum's avatar
ebaum committed
161 162 163 164
    m_Gui->wait( false );
    m_FinishRequested = true;

    // wait for modules to finish
165
    for( std::list<boost::shared_ptr<WModule> >::iterator list_iter = m_modules.begin(); list_iter != m_modules.end();
wiebel's avatar
[STYLE]  
wiebel committed
166
            ++list_iter )
ebaum's avatar
ebaum committed
167 168 169 170 171 172 173 174 175 176 177
    {
        ( *list_iter )->wait( true );
    }

    // finally GE
    m_GraphicsEngine->wait( true );

    // how to get QT return code from its thread?
    return 0;
}

ebaum's avatar
[ADD]  
ebaum committed
178 179
void WKernel::loadModules()
{
ebaum's avatar
ebaum committed
180
    // TODO(ebaum): add dynamic loading here
181
    WLogger::getLogger()->addLogMessage( "*** Loading Modules: ", "Kernel", LL_DEBUG );
ebaum's avatar
ebaum committed
182 183
    m_modules.clear();

184
    boost::shared_ptr<WModule> m = boost::shared_ptr<WModule>( new WNavigationSliceModule() );
185
    WLogger::getLogger()->addLogMessage( "Loading module: " + m->getName(), "Kernel", LL_DEBUG );
ebaum's avatar
ebaum committed
186 187

    m_modules.push_back( m );
ebaum's avatar
ebaum committed
188 189 190 191 192
}

void WKernel::init()
{
    // initialize
193
    findAppPath();
ebaum's avatar
ebaum committed
194 195 196

    // initialize graphics engine
    // this also includes initialization of WGEScene and OpenSceneGraph
197
    m_GraphicsEngine = boost::shared_ptr<WGraphicsEngine>( new WGraphicsEngine( m_shaderPath ) );
198 199 200

    // initialize Datahandler
    m_DataHandler = boost::shared_ptr<WDataHandler>( new WDataHandler() );
201 202 203 204 205 206
}

bool WKernel::findAppPath()
{
    // FIXME (schurade)
    // this should work on linux, have to implement it for windows and mac later
Alexander Wiebel's avatar
Alexander Wiebel committed
207
#ifdef __linux__
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
    int length;
    char appPath[255];

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

    // Catch some errors
    if ( length < 0 )
    {
        fprintf( stderr, "Error resolving symlink /proc/self/exe.\n" );
        return false;
    }
    if ( length >= 255 )
    {
        fprintf( stderr, "Path too long. Truncated.\n" );
        return false;
    }

    // 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
233
        assert( length >= 0 );
234 235 236 237 238
    }

    m_AppPath = appPath;

    std::string shaderPath( appPath );
239
    m_shaderPath = shaderPath + "shaders/";
240 241

    return true;
schurade's avatar
schurade committed
242
#elif defined( __APPLE__ )
243
    char path[1024];
schurade's avatar
schurade committed
244 245
    uint32_t size = sizeof( path );
    if(_NSGetExecutablePath( path, &size ) == 0 )
246
    {
schurade's avatar
schurade committed
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
        fprintf( stderr, "Executable path is %s\n", path );
        int i= strlen( path );
        while( path[i] != '/' )
        {
            path[i] = '\0';
            i--;
            assert( i >= 0 );
        }
        fprintf( stderr, "Application path is %s\n", path );
        m_AppPath = path;

        std::string shaderPath( path );
        m_shaderPath = shaderPath + "shaders/";

        return true;
262 263 264
    }
    else
    {
schurade's avatar
schurade committed
265 266
        fprintf( stderr, "buffer too small; need size %u\n", size );
        assert( size <= sizeof( path ) );
267 268 269 270 271 272
    }
#else
#error findAppPath not implemented for this platform
#endif

    return false;
ebaum's avatar
ebaum committed
273 274
}

275
bool WKernel::isFinishRequested() const
ebaum's avatar
ebaum committed
276 277
{
    return m_FinishRequested;
ebaum's avatar
[ADD]  
ebaum committed
278 279
}

280 281 282 283 284
void WKernel::doLoadDataSets( std::vector< std::string > fileNames )
{
    m_DataHandler->loadDataSets( fileNames );
}

285 286 287 288 289
boost::shared_ptr<WDataHandler> WKernel::getDataHandler()
{
    return m_DataHandler;
}

290 291 292 293 294 295 296
std::string WKernel::getAppPath()
{
    return m_AppPath;
}

std::string WKernel::getShaderPath()
{
297
    return m_shaderPath;
298
}