WKernel.cpp 9.37 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
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#endif

ebaum's avatar
[ADD]  
ebaum committed
29
#include <iostream>
ebaum's avatar
ebaum committed
30
#include <list>
31 32
#include <string>
#include <vector>
ebaum's avatar
ebaum committed
33 34

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

ebaum's avatar
ebaum committed
36
#include "WModule.h"
37
#include "WModuleFactory.h"
38
#include "../modules/data/WMData.hpp"
39 40
#include "../modules/navSlices/WMNavSlices.h"
#include "../modules/coordinateSystem/WMCoordinateSystem.h"
41 42 43
#include "../modules/fiberDisplay/WMFiberDisplay.h"
#include "../modules/fiberCulling/WMFiberCulling.h"
#include "../modules/fiberClustering/WMFiberClustering.h"
ebaum's avatar
[ADD]  
ebaum committed
44 45
#include "../common/WException.h"

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

48
#include "WKernel.h"
49

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

55
WKernel::WKernel( int argc, char* argv[], boost::shared_ptr< WGUI > gui )
56
    : m_gui( gui )
ebaum's avatar
[ADD]  
ebaum committed
57
{
58
    WLogger::getLogger()->addLogMessage( "Initializing Kernel", "Kernel", LL_DEBUG );
ebaum's avatar
ebaum committed
59 60 61

    kernel = this;

ebaum's avatar
[ADD]  
ebaum committed
62
    // initialize members
ebaum's avatar
ebaum committed
63 64 65
    m_ArgC = argc;
    m_ArgV = argv;
    m_FinishRequested = false;
ebaum's avatar
[ADD]  
ebaum committed
66

67 68
    // get module factory
    m_moduleFactory = WModuleFactory::getModuleFactory();
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
69 70
    m_moduleContainer = boost::shared_ptr< WModuleContainer >( new WModuleContainer( "KernelRootContainer", "Root module\
                container in Kernel." ) );
71

ebaum's avatar
ebaum committed
72 73 74
    // init GE, DataHandler, ...
    init();

ebaum's avatar
[ADD]  
ebaum committed
75 76 77 78 79 80 81
    // load modules
    loadModules();
}

WKernel::~WKernel()
{
    // cleanup
82
    WLogger::getLogger()->addLogMessage( "Shutting down Kernel", "Kernel", LL_DEBUG );
83 84

    // finish running thread
85
    WLogger::getLogger()->wait( true );
86
    // write remaining log messages
87
    WLogger::getLogger()->processQueue();
ebaum's avatar
[ADD]  
ebaum committed
88 89 90 91 92 93 94
}

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

ebaum's avatar
ebaum committed
95 96 97 98 99
WKernel* WKernel::getRunningKernel()
{
    return kernel;
}

100
boost::shared_ptr< WGraphicsEngine > WKernel::getGraphicsEngine() const
ebaum's avatar
ebaum committed
101
{
102
    return m_graphicsEngine;
ebaum's avatar
ebaum committed
103 104
}

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
105
boost::shared_ptr< WModuleContainer > WKernel::getRootContainer() const
106
{
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
107
    return m_moduleContainer;
108 109
}

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
110
boost::shared_ptr< WGUI > WKernel::getGui() const
111
{
112
    return m_gui;
113 114
}

115 116
void WKernel::setGui( boost::shared_ptr< WGUI > gui )
{
117
    m_gui = gui;
118
}
119

120
int WKernel::getArgumentCount() const
ebaum's avatar
ebaum committed
121 122 123 124
{
    return m_ArgC;
}

125
char** WKernel::getArguments() const
ebaum's avatar
ebaum committed
126 127 128 129
{
    return m_ArgV;
}

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
130 131 132 133 134
void WKernel::stop()
{
   getRootContainer()->stop(); 
}

ebaum's avatar
ebaum committed
135 136
int WKernel::run()
{
137
    WLogger::getLogger()->addLogMessage( "Starting Kernel", "Kernel", LL_DEBUG );
ebaum's avatar
ebaum committed
138 139

    // TODO(ebaum): add separate graphics thread here
140
    m_graphicsEngine->run();
ebaum's avatar
ebaum committed
141 142 143

    // run Gui
    // TODO(all): clean up this option handler mess
144
    m_gui->run();
ebaum's avatar
ebaum committed
145 146 147

    // run? data handler stuff?

148 149 150 151
    // **************************************************************************************************************************
    // This part will be exchanged by some kind of ModuleContainer managing module execution.
    // TODO(ebaum): replace by ModuleContainer
    // **************************************************************************************************************************
152

ebaum's avatar
ebaum committed
153 154 155
    // run module execution threads
    // TODO(ebaum): after having modules loaded they should be started here.
    // currently this is just the test module
156
    /*WLogger::getLogger()->addLogMessage( "*** Starting modules:", "Kernel", LL_DEBUG );
157
    for( std::list< boost::shared_ptr< WModule > >::iterator list_iter = m_modules.begin(); list_iter != m_modules.end();
wiebel's avatar
[STYLE]  
wiebel committed
158
            ++list_iter )
ebaum's avatar
ebaum committed
159
    {
160
        WLogger::getLogger()->addLogMessage( "Starting module: " + ( *list_iter )->getName(), "Kernel", LL_DEBUG );
ebaum's avatar
ebaum committed
161 162 163
        ( *list_iter )->run();
    }

164
    // TODO(schurade): this must be moved somewhere else, and realize the wait loop in another fashion
165
    while ( !m_gui->isInitalized() )
166 167
    {
    }
168
    m_gui->getLoadButtonSignal()->connect( boost::bind( &WKernel::doLoadDataSets, this, _1 ) );
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
169

170
    for( std::list< boost::shared_ptr< WModule > >::iterator list_iter = m_modules.begin(); list_iter != m_modules.end();
171 172 173 174 175
                ++list_iter )
    {
        ( *list_iter )->connectToGui();
    }

ebaum's avatar
ebaum committed
176
    // wait
177
    // TODO(ebaum): this is not the optimal. It would be better to quit OSG, GE and so on in the right order.
178
    m_gui->wait( false );
ebaum's avatar
ebaum committed
179 180 181
    m_FinishRequested = true;

    // wait for modules to finish
182
    for( std::list< boost::shared_ptr< WModule > >::iterator list_iter = m_modules.begin(); list_iter != m_modules.end();
wiebel's avatar
[STYLE]  
wiebel committed
183
            ++list_iter )
ebaum's avatar
ebaum committed
184 185
    {
        ( *list_iter )->wait( true );
186
    }*/
ebaum's avatar
ebaum committed
187

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
188 189 190
    // TODO(schurade): this must be moved somewhere else, and realize the wait loop in another fashion
    while ( !m_gui->isInitalized() )
    {
ebaum's avatar
ebaum committed
191
    }
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
192 193 194 195
    m_gui->getLoadButtonSignal()->connect( boost::bind( &WKernel::doLoadDataSets, this, _1 ) );

    m_gui->wait( false );
    m_FinishRequested = true;
ebaum's avatar
ebaum committed
196 197

    // finally GE
198
    m_graphicsEngine->wait( true );
ebaum's avatar
ebaum committed
199 200 201 202 203

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

ebaum's avatar
[ADD]  
ebaum committed
204 205
void WKernel::loadModules()
{
206 207
    // load all modules
    m_moduleFactory->load();
ebaum's avatar
ebaum committed
208 209 210 211
}

void WKernel::init()
{
212
     // initialize
213
    findAppPath();
ebaum's avatar
ebaum committed
214 215 216

    // initialize graphics engine
    // this also includes initialization of WGEScene and OpenSceneGraph
217
    m_graphicsEngine = boost::shared_ptr< WGraphicsEngine >( new WGraphicsEngine( m_shaderPath ) );
218 219

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

222 223
    // m_gui->createMainWindow();

224
    m_dataHandler->getSignalAddDataset()->connect( boost::bind( &WKernel::slotFinishLoadData, this, _1 ) );
225 226 227 228 229 230
}

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
231
#ifdef __linux__
232 233 234 235 236 237 238 239
    int length;
    char appPath[255];

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

    // Catch some errors
    if ( length < 0 )
    {
240
        WLogger::getLogger()->addLogMessage( "Error resolving symlink /proc/self/exe.", "Kernel", LL_ERROR );
241 242 243 244
        return false;
    }
    if ( length >= 255 )
    {
245
        WLogger::getLogger()->addLogMessage( "Path too long. Truncated.", "Kernel", LL_ERROR );
246 247 248 249 250 251 252 253 254 255 256
        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
257
        assert( length >= 0 );
258 259 260 261 262
    }

    m_AppPath = appPath;

    std::string shaderPath( appPath );
263
    m_shaderPath = shaderPath + "shaders/";
264 265

    return true;
schurade's avatar
schurade committed
266
#elif defined( __APPLE__ )
267
    char path[1024];
schurade's avatar
schurade committed
268
    uint32_t size = sizeof( path );
269
    if( _NSGetExecutablePath( path, &size ) == 0 )
270
    {
271 272 273
        WLogger::getLogger()->addLogMessage( "Executable path is " + std::string( path ), "Kernel", LL_ERROR );

        int i = strlen( path );
schurade's avatar
schurade committed
274 275 276 277 278 279
        while( path[i] != '/' )
        {
            path[i] = '\0';
            i--;
            assert( i >= 0 );
        }
280
        WLogger::getLogger()->addLogMessage( "Application path is " + std::string( path ), "Kernel", LL_ERROR );
schurade's avatar
schurade committed
281 282 283 284 285 286
        m_AppPath = path;

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

        return true;
287 288 289
    }
    else
    {
290
        WLogger::getLogger()->addLogMessage( "Buffer too small; need size " + boost::lexical_cast< std::string >( size ),
291
                                             "Kernel", LL_ERROR );
schurade's avatar
schurade committed
292
        assert( size <= sizeof( path ) );
293 294 295 296 297 298
    }
#else
#error findAppPath not implemented for this platform
#endif

    return false;
ebaum's avatar
ebaum committed
299 300
}

301
bool WKernel::isFinishRequested() const
ebaum's avatar
ebaum committed
302 303
{
    return m_FinishRequested;
ebaum's avatar
[ADD]  
ebaum committed
304 305
}

306 307
void WKernel::doLoadDataSets( std::vector< std::string > fileNames )
{
308
    m_dataHandler->loadDataSets( fileNames );
309
}
310

311 312
void WKernel::slotFinishLoadData( boost::shared_ptr< WDataSet > dataSet )
{
313
    boost::shared_ptr< WModule > module = boost::shared_ptr< WModule >( new WMData< int >( dataSet ) );
314

315
    module->getProperties()->addBool( "active", true );
316
    module->getProperties()->hideProperty( "active" );
317
    module->getProperties()->addBool( "interpolation", true );
318 319
    module->getProperties()->addInt( "threshold", 0 );
    module->getProperties()->addInt( "alpha", 100 );
320
    module->getProperties()->setMax( "alpha", 100 );
321
    module->getProperties()->setValue( "name", dataSet->getFileName() );
322

323
    m_gui->addDatasetToBrowser( module, 0 );
324 325
}

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
326
boost::shared_ptr< WDataHandler > WKernel::getDataHandler() const
327
{
328
    return m_dataHandler;
329 330
}

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
331
std::string WKernel::getAppPath() const
332 333 334 335
{
    return m_AppPath;
}

Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
336
std::string WKernel::getShaderPath() const
337
{
338
    return m_shaderPath;
339
}