OpenFlipper.cc 13.8 KB
Newer Older
Jan Möbius's avatar
 
Jan Möbius committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
//=============================================================================
//
//                               OpenFlipper
//        Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen
//                           www.openflipper.org
//
//-----------------------------------------------------------------------------
//
//                                License
//
//  OpenFlipper 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.
15
//
Jan Möbius's avatar
 
Jan Möbius committed
16 17 18 19
//  OpenFlipper 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.
20
//
Jan Möbius's avatar
 
Jan Möbius committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
//  You should have received a copy of the GNU Lesser General Public License
//  along with OpenFlipper.  If not, see <http://www.gnu.org/licenses/>.
//
//-----------------------------------------------------------------------------
//
//   $Revision$
//   $Author$
//   $Date$
//
//=============================================================================




// Mainwindow

#include "OpenFlipper/Core/Core.hh"

// Qt
#include <qapplication.h>
#include <qgl.h>

// stdc++
#include <iostream>
#include <fstream>
#include <csignal>
#include <cstdlib>

#include "OpenFlipper/common/GlobalOptions.hh"

#include <OpenFlipper/SimpleOpt/SimpleOpt.h>

Mike Kremer's avatar
Mike Kremer committed
53
#if ( defined(WIN32) || defined(ARCH_DARWIN) )
Mike Kremer's avatar
Mike Kremer committed
54 55 56 57
  #define NO_EXECINFO
#endif

#ifndef NO_EXECINFO
58
#include <execinfo.h>
Jan Möbius's avatar
 
Jan Möbius committed
59 60 61 62 63 64
#endif

#ifdef USE_OPENMP
#include <omp.h>
#endif

Jan Möbius's avatar
Jan Möbius committed
65

66 67 68 69 70 71 72 73
// Includes for windows debugging console
#ifdef WIN32
  #ifndef NDEBUG
    #include <fcntl.h>
    #include <io.h>
  #endif
#endif

Jan Möbius's avatar
Jan Möbius committed
74

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
// #ifndef WIN32
//
// #include <sys/resource.h>
//
// void getSystemInfo() {
//
//   struct rusage resource_usage;
//   if (getrusage(RUSAGE_SELF, &resource_usage))
//   {
//     //error - call to getrusage failed - handle it
//     std::cerr << "Unable to get process information" << std::endl;
//   }
//   else
//   {
//     std::cerr << "Got process information" << std::endl;
//     std::cerr << "Maximum resident size   : " << resource_usage.ru_maxrss << std::endl;
//     std::cerr << "Shared Memory size      : " << resource_usage.ru_ixrss << std::endl;
//     std::cerr << "Unshared Data size      : " << resource_usage.ru_idrss << std::endl;
//     std::cerr << "Unshared Stack size     : " << resource_usage.ru_isrss << std::endl;
//     std::cerr << "Page faults             : " << resource_usage.ru_majflt << std::endl;
//     std::cerr << "Block input operations  : " << resource_usage.ru_inblock << std::endl;
//     std::cerr << "Block output operations : " << resource_usage.ru_oublock << std::endl;
//
//
//     //call successful
//     //get values for resident set size (ru_idrss)
//     //swap space is probably not accounted for but thats all what this
//     //call gives you...

//     struct rusage {
//         struct timeval ru_utime; /* user time used */
//         struct timeval ru_stime; /* system time used */
//         long   ru_minflt;        /* page reclaims */
//         long   ru_nswap;         /* swaps */
//         long   ru_msgsnd;        /* messages sent */
//         long   ru_msgrcv;        /* messages received */
//         long   ru_nsignals;      /* signals received */
//         long   ru_nvcsw;         /* voluntary context switches */
//         long   ru_nivcsw;        /* involuntary context switches */
//     };


//   }

// }

// #endif



Jan Möbius's avatar
 
Jan Möbius committed
125
enum {OPT_HELP , OPT_STEREO, OPT_BATCH ,OPT_CONSOLE_LOG , OPT_DEBUGGING, OPT_FULLSCREEN,
126
      OPT_HIDDDEN_LOGGER , OPT_NOSPLASH ,OPT_HIDDDEN_TOOLBOX , OPT_LOAD_POLYMESHES,
Jan Möbius's avatar
 
Jan Möbius committed
127 128 129
      OPT_REMOTE};

CSimpleOpt::SOption g_rgOptions[] = {
130 131 132 133
    { OPT_DEBUGGING        , (char*) "--debug"          , SO_NONE    },
    { OPT_HELP             , (char*) "-?"               , SO_NONE    },
    { OPT_HELP             , (char*) "--help"           , SO_NONE    },
    { OPT_HELP             , (char*) "-h"               , SO_NONE    },
Jan Möbius's avatar
Jan Möbius committed
134
    { OPT_STEREO           , (char*) "--disable-stereo" , SO_NONE    },
135 136 137 138 139 140 141
    { OPT_BATCH            , (char*) "-b"               , SO_NONE    },
    { OPT_CONSOLE_LOG      , (char*) "-c"               , SO_NONE    },
    { OPT_CONSOLE_LOG      , (char*) "--log-to-console" , SO_NONE    },
    { OPT_FULLSCREEN       , (char*) "-f"               , SO_NONE    },
    { OPT_HIDDDEN_LOGGER   , (char*) "-l"               , SO_NONE    },
    { OPT_NOSPLASH         , (char*) "--no-splash"      , SO_NONE    },
    { OPT_HIDDDEN_TOOLBOX  , (char*) "-t"               , SO_NONE    },
Mike Kremer's avatar
Mike Kremer committed
142
    { OPT_LOAD_POLYMESHES  , (char*) "-p"               , SO_NONE    },
143
    { OPT_REMOTE           , (char*) "--remote-control" , SO_NONE    },
Jan Möbius's avatar
 
Jan Möbius committed
144 145 146 147 148 149 150
    SO_END_OF_OPTIONS                       // END
};

void showHelp() {
  std::cerr << "OpenFlipper [Options] <filenames> " << std::endl << std::endl;;
  std::cerr << "Possible Options : " << std::endl;
  std::cerr << std::endl;
151 152 153 154 155 156 157 158 159 160 161

  std::cerr << "Load/Save Options:" << std::endl;
  std::cerr << " -p \t: Open files as PolyMeshes" << std::endl;
  std::cerr << std::endl;

  std::cerr << "Gui Options:" << std::endl;
  std::cerr << " -f \t\t: Start Fullscreen" << std::endl;
  std::cerr << " -l \t\t: Start with hidden logger" << std::endl;
  std::cerr << " -t \t\t: Start with hidden Toolbox" << std::endl;
  std::cerr << " --no-splash \t: Disable splash screen" << std::endl;

Jan Möbius's avatar
 
Jan Möbius committed
162
  std::cerr << " --disable-stereo \t: Disable Stereo Mode" << std::endl;
Jan Möbius's avatar
 
Jan Möbius committed
163
  std::cerr << std::endl;
164 165 166

  std::cerr << "Log options:" << std::endl;
  std::cerr << " --log-to-console ( -c ) \t: Write logger window contents to console" << std::endl;
Jan Möbius's avatar
 
Jan Möbius committed
167
  std::cerr << std::endl;
168 169 170 171 172

  std::cerr << "Other options:" << std::endl;
  std::cerr << " -b \t: Batch mode, you have to provide a script for execution" << std::endl;
  std::cerr << " --remote-control \t: Batch mode accepting remote connections" << std::endl;

Jan Möbius's avatar
 
Jan Möbius committed
173
  std::cerr << std::endl;
174 175 176


  std::cerr << " -h \t: This help" << std::endl;
Jan Möbius's avatar
 
Jan Möbius committed
177 178 179
}


Mike Kremer's avatar
Mike Kremer committed
180
#ifndef NO_EXECINFO
Jan Möbius's avatar
 
Jan Möbius committed
181 182
void backtrace()
{
183
  void *addresses[20];
Jan Möbius's avatar
 
Jan Möbius committed
184 185
  char **strings;

186
  int size = backtrace(addresses, 20);
Jan Möbius's avatar
 
Jan Möbius committed
187 188 189 190 191 192 193 194 195
  strings = backtrace_symbols(addresses, size);
  std::cerr << "Stack frames: " << size << std::endl;
  for(int i = 0; i < size; i++)
    std::cerr << i << ": " << strings[i] << std::endl;
  free(strings);
}
#endif

void segfaultHandling (int) {
196

Jan Möbius's avatar
 
Jan Möbius committed
197 198 199 200 201 202 203 204 205 206 207
  // prevent infinite recursion if segfaultHandling() causes another segfault
  std::signal(SIGSEGV, SIG_DFL);


  std::cerr << "\n" << std::endl;
  std::cerr << "\n" << std::endl;
  std::cerr << "\33[31m" << "=====================================================" << std::endl;
  std::cerr << "\33[31m" << "OpenFlipper or one of its plugins caused a Segfault." << std::endl;
  std::cerr << "\33[31m" << "This should not happen,... Sorry :-(" << std::endl;
  std::cerr << "\33[31m" << "=====================================================" << std::endl;
  std::cerr << "\n" << std::endl;
Mike Kremer's avatar
Mike Kremer committed
208
#ifndef NO_EXECINFO
Jan Möbius's avatar
 
Jan Möbius committed
209 210
  std::cerr << "\33[0m"  << "Trying a backtrace to show what happened last: " << std::endl;
  backtrace();
211

Jan Möbius's avatar
 
Jan Möbius committed
212 213
  std::cerr << "\n" << std::endl;
  std::cerr << "Backtrace completed, trying to abort now ..." << std::endl;
214

Jan Möbius's avatar
 
Jan Möbius committed
215
#endif
216

Jan Möbius's avatar
 
Jan Möbius committed
217 218 219
  std::abort();
}

220
#ifdef WIN32
Jan Möbius's avatar
Jan Möbius committed
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
  #ifndef NDEBUG
    void getConsole() {
      //Create a console for this application
      AllocConsole();
      //Redirect unbuffered STDOUT to the console
      HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
      int SystemOutput = _open_osfhandle(intptr_t(ConsoleOutput), _O_TEXT);
      FILE *COutputHandle = _fdopen(SystemOutput, "w" );
      *stdout = *COutputHandle;
      setvbuf(stdout, NULL, _IONBF, 0);
      //Redirect unbuffered STDERR to the console
      HANDLE ConsoleError = GetStdHandle(STD_ERROR_HANDLE);
      int SystemError = _open_osfhandle(intptr_t(ConsoleError), _O_TEXT);
      FILE *CErrorHandle = _fdopen(SystemError, "w" );
      *stderr = *CErrorHandle;
      setvbuf(stderr, NULL, _IONBF, 0);
      //Redirect unbuffered STDIN to the console
      HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
      int SystemInput = _open_osfhandle(intptr_t(ConsoleInput), _O_TEXT);
      FILE *CInputHandle = _fdopen(SystemInput, "r" );
      *stdin = *CInputHandle;
      setvbuf(stdin, NULL, _IONBF, 0);
    }
  #endif
245 246
#endif

Dirk Wilden's avatar
Dirk Wilden committed
247 248
bool openPolyMeshes = false;
bool remoteControl  = false;
249

Dirk Wilden's avatar
Dirk Wilden committed
250
bool parseCommandLineOptions(CSimpleOpt& args){
251

Jan Möbius's avatar
 
Jan Möbius committed
252 253
  // while there are arguments left to process
  while (args.Next()) {
Dirk Wilden's avatar
Dirk Wilden committed
254

Jan Möbius's avatar
 
Jan Möbius committed
255
    if (args.LastError() == SO_SUCCESS) {
Dirk Wilden's avatar
Dirk Wilden committed
256

Jan Möbius's avatar
 
Jan Möbius committed
257 258 259 260 261 262 263 264 265
      switch (args.OptionId() ) {
        case OPT_BATCH:
          OpenFlipper::Options::nogui(true);
        break;
        case OPT_CONSOLE_LOG:
          OpenFlipper::Options::logToConsole(true);
          break;
        case OPT_DEBUGGING:
          OpenFlipper::Options::debug(true);
266
          break;
Jan Möbius's avatar
 
Jan Möbius committed
267
        case OPT_STEREO:
Jan Möbius's avatar
Jan Möbius committed
268
            OpenFlipper::Options::stereo(false);
Jan Möbius's avatar
 
Jan Möbius committed
269 270
            break;
        case OPT_HIDDDEN_TOOLBOX:
Jan Möbius's avatar
Jan Möbius committed
271
            OpenFlipperSettings().setValue("Core/Gui/ToolBoxes/hidden",true);
Jan Möbius's avatar
 
Jan Möbius committed
272 273
            break;
        case OPT_HIDDDEN_LOGGER:
Jan Möbius's avatar
Jan Möbius committed
274
            OpenFlipper::Options::loggerState(OpenFlipper::Options::Hidden);
Jan Möbius's avatar
 
Jan Möbius committed
275 276
            break;
        case OPT_FULLSCREEN:
Jan Möbius's avatar
Jan Möbius committed
277
            OpenFlipperSettings().setValue("Core/Gui/fullscreen",false);
Jan Möbius's avatar
 
Jan Möbius committed
278 279 280 281 282
            break;
        case OPT_LOAD_POLYMESHES:
            openPolyMeshes = true;
            break;
        case OPT_NOSPLASH:
283
            OpenFlipperSettings().setValue("Core/Gui/splash",false);
Jan Möbius's avatar
 
Jan Möbius committed
284 285
            break;
        case OPT_REMOTE:
Dirk Wilden's avatar
Dirk Wilden committed
286
            OpenFlipper::Options::remoteControl(true);
Jan Möbius's avatar
 
Jan Möbius committed
287 288 289 290 291 292 293 294
            break;
        case OPT_HELP:
          showHelp();
          return 0;
      }
    } else {
      std::cerr << "Invalid argument: " << args.OptionText() << std::endl;
      showHelp();
Dirk Wilden's avatar
Dirk Wilden committed
295
      return false;
Jan Möbius's avatar
 
Jan Möbius committed
296 297
    }
  }
Dirk Wilden's avatar
Dirk Wilden committed
298 299 300 301 302
  return true;
}

int main(int argc, char **argv)
{
303 304

  #ifdef WIN32
Jan Möbius's avatar
Jan Möbius committed
305 306 307
    #ifndef NDEBUG
      getConsole();
    #endif
308
  #endif
Jan Möbius's avatar
Jan Möbius committed
309
  
310 311
  // Remove -psn_0_xxxxx argument which is automatically
  // attached by MacOSX
Mike Kremer's avatar
 
Mike Kremer committed
312
  for (int i = 0; i < argc; i++) {
313 314 315 316 317 318
    if(strlen(argv[i]) > 4) {
      if( ( (argv[i])[0] == '-' ) &&
        ( (argv[i])[1] == 'p' ) &&
        ( (argv[i])[2] == 's' ) &&
        ( (argv[i])[3] == 'n' ) ) {
	 argc--;
319
	 argv[i] = (char *)"";
320 321 322
      }
    }
  }
Jan Möbius's avatar
Jan Möbius committed
323

Dirk Wilden's avatar
Dirk Wilden committed
324 325 326
  OpenFlipper::Options::argc(&argc);
  OpenFlipper::Options::argv(&argv);

Dirk Wilden's avatar
Dirk Wilden committed
327
  CSimpleOpt argBatch(argc, argv, g_rgOptions);
Dirk Wilden's avatar
Dirk Wilden committed
328

Dirk Wilden's avatar
Dirk Wilden committed
329
  //check only batchMode before the core is created
Dirk Wilden's avatar
Dirk Wilden committed
330 331
  while (argBatch.Next())
    if (argBatch.OptionId() == OPT_BATCH ){
Dirk Wilden's avatar
Dirk Wilden committed
332 333 334 335
      OpenFlipper::Options::nogui(true);
      break;
    }

Dirk Wilden's avatar
Dirk Wilden committed
336 337
  CSimpleOpt args(argc, argv, g_rgOptions);

Dirk Wilden's avatar
Dirk Wilden committed
338 339 340 341 342 343 344
// Only Install signal handler if not running in debug version, otherwise gdb will get confused
// #ifndef DEBUG
  // Set a handler for segfaults
  std::signal(SIGSEGV, segfaultHandling);
// #endif

  OpenFlipper::Options::windowTitle("OpenFlipper v" + OpenFlipper::Options::coreVersion());
345

Jan Möbius's avatar
 
Jan Möbius committed
346
  if ( !OpenFlipper::Options::nogui() ) {
347

Jan Möbius's avatar
 
Jan Möbius committed
348 349 350
    // OpenGL check
    QApplication::setColorSpec( QApplication::CustomColor );
    QApplication app(argc,argv);
351

Jan Möbius's avatar
 
Jan Möbius committed
352 353 354 355
    if ( !QGLFormat::hasOpenGL() ) {
      std::cerr << "This system has no OpenGL support.\n";
      return -1;
    }
356

Jan Möbius's avatar
 
Jan Möbius committed
357
    glutInit(&argc,argv);
358

Jan Möbius's avatar
 
Jan Möbius committed
359 360
    // create core ( this also reads the ini files )
    Core * w = new Core( );
361

Jan Möbius's avatar
Jan Möbius committed
362 363
    if ( !parseCommandLineOptions(args) ) {
      delete w;
Dirk Wilden's avatar
Dirk Wilden committed
364
      return 1;
Jan Möbius's avatar
Jan Möbius committed
365
    }
Dirk Wilden's avatar
Dirk Wilden committed
366

367 368 369 370 371
    QString tLang = OpenFlipper::Options::translation();

    if (tLang == "locale")
      tLang = QLocale::system().name();

372 373
    // Install translator for qt internals
    QTranslator qtTranslator;
Jan Möbius's avatar
Jan Möbius committed
374 375 376 377 378 379 380
//     std::cerr << "Loading qt translations from: " << QLibraryInfo::location(QLibraryInfo::TranslationsPath).toStdString() << std::endl;
//     if ( qtTranslator.load("qt_" + tLang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) )
//       std::cerr << "Loaded" << std::endl;
//     std::cerr << "Loading qt translations from: " << QLibraryInfo::location(QLibraryInfo::TranslationsPath).toStdString() << std::endl;
    qtTranslator.load("qt_" + tLang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
//       std::cerr << "Loaded" << std::endl;

381 382 383
    app.installTranslator(&qtTranslator);
    
    // install translator for Core Application
Dirk Wilden's avatar
Dirk Wilden committed
384
    QString translationDir = OpenFlipper::Options::translationsDirStr() + QDir::separator();
385

Jan Möbius's avatar
Jan Möbius committed
386
//     std::cerr << "Loading own translations from: " << QString(translationDir + " (" + tLang + ")").toStdString() << std::endl;
Dirk Wilden's avatar
Dirk Wilden committed
387 388 389 390 391 392 393 394 395 396 397 398 399

    QDir dir(translationDir);
    dir.setFilter(QDir::Files);

    QFileInfoList list = dir.entryInfoList();

    for (int i = 0; i < list.size(); ++i) {
      QFileInfo fileInfo = list.at(i);

      if ( fileInfo.baseName().contains(tLang) ){
        QTranslator* myAppTranslator = new QTranslator();

        if ( myAppTranslator->load( fileInfo.filePath() ) ){
Jan Möbius's avatar
Jan Möbius committed
400
//           std::cerr << "Loaded " << fileInfo.fileName().toStdString() << std::endl;
401
    
Dirk Wilden's avatar
Dirk Wilden committed
402
          app.installTranslator(myAppTranslator);
Jan Möbius's avatar
Jan Möbius committed
403 404
        } else {
  	  delete myAppTranslator;
Dirk Wilden's avatar
Dirk Wilden committed
405 406 407
        }
      }
     }
408
    
Jan Möbius's avatar
 
Jan Möbius committed
409 410
    // After setting all Options from command line, build the real gui
    w->init();
411

412 413 414 415 416 417
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
      /* Problem: glewInit failed, something is seriously wrong. */
      fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
    }
Jan Möbius's avatar
Jan Möbius committed
418 419
    
 
420
    for ( int i = 0 ; i < args.FileCount(); ++i )
421
      w->commandLineOpen(args.File(i), openPolyMeshes);    
422

Jan Möbius's avatar
 
Jan Möbius committed
423
    return app.exec();
424

Jan Möbius's avatar
 
Jan Möbius committed
425
  } else {
426

Jan Möbius's avatar
 
Jan Möbius committed
427
    QCoreApplication app(argc,argv);
428

Jan Möbius's avatar
 
Jan Möbius committed
429 430
    // create widget ( this also reads the ini files )
    Core * w = new Core( );
431

Jan Möbius's avatar
Jan Möbius committed
432 433
    if ( !parseCommandLineOptions(args) ) {
      delete w;
Dirk Wilden's avatar
Dirk Wilden committed
434
      return 1;
Jan Möbius's avatar
Jan Möbius committed
435
    }
Dirk Wilden's avatar
Dirk Wilden committed
436

Jan Möbius's avatar
 
Jan Möbius committed
437 438
    // After setting all Options from command line, build the real gui
    w->init();
439 440 441 442

    for ( int i = 0 ; i < args.FileCount(); ++i )
      w->commandLineScript(args.File(i));

Dirk Wilden's avatar
Dirk Wilden committed
443
    return app.exec();
Jan Möbius's avatar
 
Jan Möbius committed
444 445 446 447
  }

  return 0;
}