Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
OpenFlipper.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 
52 // Mainwindow
53 
54 #include "OpenFlipper/Core/Core.hh"
55 #include "common/glew_wrappers.hh"
56 
57 // Qt
58 #include <qgl.h>
59 
60 // stdc++
61 #include <csignal>
62 
63 #include <OpenFlipper/SimpleOpt/SimpleOpt.h>
64 
65 #if ( defined(WIN32))
66  #define NO_EXECINFO
67 #endif
68 
69 #ifndef NO_EXECINFO
70 #include <execinfo.h>
71 #endif
72 
73 #ifdef USE_OPENMP
74 #endif
75 
76 /* ==========================================================
77  *
78  * Stackwalker code. Used to get a backtrace if OpenFlipper
79  * crashes under windows
80  *
81  * ==========================================================*/
82 
83 
84 #ifdef WIN32
85  #include "StackWalker/StackWalker.hh"
86  #include <fstream>
87 
88  class StackWalkerToConsole : public StackWalker
89  {
90  protected:
91  virtual void OnOutput(LPCSTR szText)
92  {
93  // Writes crash dump to .OpenFlipper config directory
94  std::ofstream crashFile;
95  QString crashName = OpenFlipper::Options::configDirStr() + QDir::separator() + "CrashDump.txt";
96  crashFile.open(crashName.toLatin1(),std::ios::out | std::ios::app);
97  crashFile << szText;
98  crashFile.close();
99  }
100  };
101 #endif
102 
103 
104 /* ==========================================================
105  *
106  * Console for Windows to get additional output written via
107  * cerr, cout, ... that is not forwarded to log window
108  *
109  * ==========================================================*/
110 
111 // Includes for windows debugging console
112 #ifdef WIN32
113 #ifdef WIN_GET_DEBUG_CONSOLE
114  #include <fcntl.h>
115  #include <io.h>
116 #endif
117 #endif
118 
119 #ifdef WIN32
120 #ifdef WIN_GET_DEBUG_CONSOLE
121  void getConsole() {
122  //Create a console for this application
123  AllocConsole();
124  //Redirect unbuffered STDOUT to the console
125  HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
126  int SystemOutput = _open_osfhandle(intptr_t(ConsoleOutput), _O_TEXT);
127  FILE *COutputHandle = _fdopen(SystemOutput, "w" );
128  *stdout = *COutputHandle;
129  setvbuf(stdout, NULL, _IONBF, 0);
130  //Redirect unbuffered STDERR to the console
131  HANDLE ConsoleError = GetStdHandle(STD_ERROR_HANDLE);
132  int SystemError = _open_osfhandle(intptr_t(ConsoleError), _O_TEXT);
133  FILE *CErrorHandle = _fdopen(SystemError, "w" );
134  *stderr = *CErrorHandle;
135  setvbuf(stderr, NULL, _IONBF, 0);
136  //Redirect unbuffered STDIN to the console
137  HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
138  int SystemInput = _open_osfhandle(intptr_t(ConsoleInput), _O_TEXT);
139  FILE *CInputHandle = _fdopen(SystemInput, "r" );
140  *stdin = *CInputHandle;
141  setvbuf(stdin, NULL, _IONBF, 0);
142  }
143 #endif
144 #endif
145 
146 /* ==========================================================
147  *
148  * Linux function printing a full stack trace to the console
149  *
150  * ==========================================================*/
151 #ifndef NO_EXECINFO
152 void backtrace()
153 {
154  void *addresses[20];
155  char **strings;
156 
157  int size = backtrace(addresses, 20);
158  strings = backtrace_symbols(addresses, size);
159  std::cerr << "Stack frames: " << size << std::endl;
160  for(int i = 0; i < size; i++)
161  std::cerr << i << ": " << strings[i] << std::endl;
162  free(strings);
163 
164 }
165 #endif
166 
167 /* ==========================================================
168  *
169  * General segfault handler. This function is called if OpenFlipper
170  * crashes
171  *
172  * ==========================================================*/
173 void segfaultHandling (int) {
174 
175  // prevent infinite recursion if segfaultHandling() causes another segfault
176  std::signal(SIGSEGV, SIG_DFL);
177 
178 
179  std::cerr << "\n" << std::endl;
180  std::cerr << "\n" << std::endl;
181  std::cerr << "\33[31m" << "=====================================================" << std::endl;
182  std::cerr << "\33[31m" << "OpenFlipper or one of its plugins caused a Segfault." << std::endl;
183  std::cerr << "\33[31m" << "This should not happen,... Sorry :-(" << std::endl;
184  std::cerr << "\33[31m" << "=====================================================" << std::endl;
185  std::cerr << "\n" << std::endl;
186 
187  // Linux Handler
188 #ifndef NO_EXECINFO
189  std::cerr << "\33[0m" << "Trying a backtrace to show what happened last: " << std::endl;
190  backtrace();
191 
192  std::cerr << "\n" << std::endl;
193  std::cerr << "Backtrace completed, trying to abort now ..." << std::endl;
194 #endif
195 
196  // Windows handler via StackWalker
197 #ifdef WIN32
198  StackWalkerToConsole sw;
199  sw.ShowCallstack();
200 #endif
201 
202 
203  std::cerr << "Trying to get additional information (This might fail if the memory is corrupted)." << std::endl;
204 
205  if (OpenFlipper::Options::gui()) {
206  for ( unsigned int i = 0 ; i < 4 ; ++i) {
207  std::cerr << "DrawMode Viewer "<< i << " " << PluginFunctions::drawMode(i).description() << std::endl;
208  }
209  }
210 
211  std::abort();
212 }
213 
214 enum {OPT_HELP , OPT_STEREO, OPT_BATCH ,OPT_CONSOLE_LOG , OPT_DEBUGGING, OPT_FULLSCREEN,
215  OPT_HIDDDEN_LOGGER , OPT_NOSPLASH ,OPT_HIDDDEN_TOOLBOX , OPT_LOAD_POLYMESHES,
216  OPT_REMOTE, OPT_REMOTE_PORT};
217 
218 CSimpleOpt::SOption g_rgOptions[] = {
219  { OPT_DEBUGGING , (char*) "--debug" , SO_NONE },
220  { OPT_HELP , (char*) "-?" , SO_NONE },
221  { OPT_HELP , (char*) "--help" , SO_NONE },
222  { OPT_HELP , (char*) "-h" , SO_NONE },
223  { OPT_STEREO , (char*) "--disable-stereo" , SO_NONE },
224  { OPT_BATCH , (char*) "-b" , SO_NONE },
225  { OPT_CONSOLE_LOG , (char*) "-c" , SO_NONE },
226  { OPT_CONSOLE_LOG , (char*) "--log-to-console" , SO_NONE },
227  { OPT_FULLSCREEN , (char*) "-f" , SO_NONE },
228  { OPT_HIDDDEN_LOGGER , (char*) "-l" , SO_NONE },
229  { OPT_NOSPLASH , (char*) "--no-splash" , SO_NONE },
230  { OPT_HIDDDEN_TOOLBOX , (char*) "-t" , SO_NONE },
231  { OPT_LOAD_POLYMESHES , (char*) "-p" , SO_NONE },
232  { OPT_REMOTE , (char*) "--remote-control" , SO_NONE },
233  { OPT_REMOTE_PORT , (char*) "--remote-port" , SO_REQ_SEP },
234  SO_END_OF_OPTIONS // END
235 };
236 
237 void showHelp() {
238  std::cerr << "OpenFlipper [Options] <filenames> " << std::endl << std::endl;;
239  std::cerr << "Possible Options : " << std::endl;
240  std::cerr << std::endl;
241 
242  std::cerr << "Load/Save Options:" << std::endl;
243  std::cerr << " -p \t: Open files as PolyMeshes" << std::endl;
244  std::cerr << std::endl;
245 
246  std::cerr << "Gui Options:" << std::endl;
247  std::cerr << " -f \t\t: Start Fullscreen" << std::endl;
248  std::cerr << " -l \t\t: Start with hidden logger" << std::endl;
249  std::cerr << " -t \t\t: Start with hidden Toolbox" << std::endl;
250  std::cerr << " --no-splash \t: Disable splash screen" << std::endl;
251 
252  std::cerr << " --disable-stereo \t: Disable Stereo Mode" << std::endl;
253  std::cerr << std::endl;
254 
255  std::cerr << "Log options:" << std::endl;
256  std::cerr << " --log-to-console ( -c ) \t: Write logger window contents to console" << std::endl;
257  std::cerr << std::endl;
258 
259  std::cerr << "Other options:" << std::endl;
260  std::cerr << " -b \t: Batch mode, you have to provide a script for execution" << std::endl;
261  std::cerr << " --remote-control \t: Batch mode accepting remote connections" << std::endl;
262 
263  std::cerr << std::endl;
264 
265 
266  std::cerr << " -h \t: This help" << std::endl;
267 }
268 
269 
270 
271 
272 
273 
274 bool openPolyMeshes = false;
275 bool remoteControl = false;
276 
277 bool parseCommandLineOptions(CSimpleOpt& args){
278 
279  QString port;
280 
281  // while there are arguments left to process
282  while (args.Next()) {
283 
284  if (args.LastError() == SO_SUCCESS) {
285 
286  switch (args.OptionId() ) {
287  case OPT_BATCH:
288  OpenFlipper::Options::nogui(true);
289  break;
290  case OPT_CONSOLE_LOG:
291  OpenFlipper::Options::logToConsole(true);
292  break;
293  case OPT_DEBUGGING:
294  OpenFlipper::Options::debug(true);
295  break;
296  case OPT_STEREO:
297  OpenFlipper::Options::stereo(false);
298  break;
299  case OPT_HIDDDEN_TOOLBOX:
300  OpenFlipperSettings().setValue("Core/Gui/ToolBoxes/hidden",true);
301  break;
302  case OPT_HIDDDEN_LOGGER:
303  OpenFlipper::Options::loggerState(OpenFlipper::Options::Hidden);
304  break;
305  case OPT_FULLSCREEN:
306  OpenFlipperSettings().setValue("Core/Gui/fullscreen",false);
307  break;
308  case OPT_LOAD_POLYMESHES:
309  openPolyMeshes = true;
310  break;
311  case OPT_NOSPLASH:
312  OpenFlipperSettings().setValue("Core/Gui/splash",false);
313  break;
314  case OPT_REMOTE:
315  OpenFlipper::Options::remoteControl(true);
316  break;
317  case OPT_REMOTE_PORT:
318  port = args.OptionArg();
319  std::cerr << "Got option : " << port.toStdString() << std::endl;
320  OpenFlipper::Options::remoteControl(port.toInt());
321  break;
322  case OPT_HELP:
323  showHelp();
324  return 0;
325  }
326  } else {
327  std::cerr << "Invalid argument: " << args.OptionText() << std::endl;
328  showHelp();
329  return false;
330  }
331  }
332  return true;
333 }
334 
335 int main(int argc, char **argv)
336 {
337 
338  // Remove -psn_0_xxxxx argument which is automatically
339  // attached by MacOSX
340  for (int i = 0; i < argc; i++) {
341  if(strlen(argv[i]) > 4) {
342  if( ( (argv[i])[0] == '-' ) &&
343  ( (argv[i])[1] == 'p' ) &&
344  ( (argv[i])[2] == 's' ) &&
345  ( (argv[i])[3] == 'n' ) ) {
346  argc--;
347  argv[i] = (char *)"";
348  }
349  }
350  }
351 
352  OpenFlipper::Options::argc(&argc);
353  OpenFlipper::Options::argv(&argv);
354 
355  CSimpleOpt argBatch(argc, argv, g_rgOptions);
356 
357  //check only batchMode before the core is created
358  while (argBatch.Next())
359  if (argBatch.OptionId() == OPT_BATCH ){
360  OpenFlipper::Options::nogui(true);
361  break;
362  }
363 
364  CSimpleOpt args(argc, argv, g_rgOptions);
365 
366 #ifndef NO_CATCH_SIGSEGV
367  // Set a handler for segfaults
368  std::signal(SIGSEGV, segfaultHandling);
369 #endif
370 
371  OpenFlipper::Options::windowTitle(TOSTRING(PRODUCT_STRING)" v" + OpenFlipper::Options::coreVersion());
372 
373 #ifdef WIN32
374 #ifdef WIN_GET_DEBUG_CONSOLE
375  getConsole();
376 #endif
377 #endif
378 
379  if ( !OpenFlipper::Options::nogui() ) {
380 
381  // OpenGL check
382  QApplication::setColorSpec( QApplication::CustomColor );
383  QApplication app(argc,argv);
384 
385 #ifdef __APPLE__
386  // Set organization and application names
387  QCoreApplication::setOrganizationName("rwth-aachen.de");
388  QCoreApplication::setApplicationName("graphics.openflipper");
389 #endif
390 
391  if ( !QGLFormat::hasOpenGL() ) {
392  std::cerr << "This system has no OpenGL support.\n";
393  return -1;
394  }
395 
396 #ifndef __APPLE__
397  glutInit(&argc,argv);
398 #endif
399 
400  // create core ( this also reads the ini files )
401  Core * w = new Core( );
402 
403  if ( !parseCommandLineOptions(args) ) {
404  delete w;
405  return 1;
406  }
407 
408  QString tLang = OpenFlipperSettings().value("Core/Language/Translation","en_US").toString();
409 
410  if (tLang == "locale")
411  tLang = QLocale::system().name();
412 
413  // Install translator for qt internals
414  QTranslator qtTranslator;
415 // std::cerr << "Loading qt translations from: " << QLibraryInfo::location(QLibraryInfo::TranslationsPath).toStdString() << std::endl;
416 // if ( qtTranslator.load("qt_" + tLang, QLibraryInfo::location(QLibraryInfo::TranslationsPath)) )
417 // std::cerr << "Loaded" << std::endl;
418 // std::cerr << "Loading qt translations from: " << QLibraryInfo::location(QLibraryInfo::TranslationsPath).toStdString() << std::endl;
419  qtTranslator.load("qt_" + tLang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
420 // std::cerr << "Loaded" << std::endl;
421 
422  app.installTranslator(&qtTranslator);
423 
424  // install translator for Core Application
425  QString translationDir = OpenFlipper::Options::translationsDirStr() + QDir::separator();
426 
427 // std::cerr << "Loading own translations from: " << QString(translationDir + " (" + tLang + ")").toStdString() << std::endl;
428 
429  QDir dir(translationDir);
430  dir.setFilter(QDir::Files);
431 
432  QFileInfoList list = dir.entryInfoList();
433 
434  for (int i = 0; i < list.size(); ++i) {
435  QFileInfo fileInfo = list.at(i);
436 
437  if ( fileInfo.baseName().contains(tLang) ){
438  QTranslator* myAppTranslator = new QTranslator();
439 
440  if ( myAppTranslator->load( fileInfo.filePath() ) ){
441 // std::cerr << "Loaded " << fileInfo.fileName().toStdString() << std::endl;
442 
443  app.installTranslator(myAppTranslator);
444  } else {
445  delete myAppTranslator;
446  }
447  }
448  }
449 
450  // After setting all Options from command line, build the real gui
451  w->init();
452 
453  #ifndef __APPLE__
454  initGlew();
455  #endif
456 
457  for ( int i = 0 ; i < args.FileCount(); ++i )
458  w->commandLineOpen(args.File(i), openPolyMeshes);
459 
460  return app.exec();
461 
462  } else {
463 
464  QCoreApplication app(argc,argv);
465 
466 #ifdef __APPLE__
467  // Set organization and application names
468  QCoreApplication::setOrganizationName("rwth-aachen.de");
469  QCoreApplication::setApplicationName("graphics.openflipper");
470 #endif
471 
472  // create widget ( this also reads the ini files )
473  Core * w = new Core( );
474 
475  if ( !parseCommandLineOptions(args) ) {
476  delete w;
477  return 1;
478  }
479 
480  // After setting all Options from command line, build the real gui
481  w->init();
482 
483  for ( int i = 0 ; i < args.FileCount(); ++i )
484  w->commandLineScript(args.File(i));
485 
486  return app.exec();
487  }
488 
489  return 0;
490 }
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
ACG::SceneGraph::DrawModes::DrawMode drawMode(int _viewer)
Get the current draw Mode of a Viewer.
void init()
Second initialization stage.
Definition: Core.cc:193
void commandLineOpen(const char *_filename, bool _asPolyMesh)
Load an object from the commandline on application start.
Definition: Core.hh:139
#define TOSTRING(x)
QSettings object containing all program settings of OpenFlipper.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
void commandLineScript(const char *_filename)
Load a script from the commandline on application start.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...