OpenFlipper.cc 12.4 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
2
3
/*===========================================================================*\
*                                                                            *
*                              OpenFlipper                                   *
Martin Schultz's avatar
Martin Schultz committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openflipper.org                            *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenFlipper.                                         *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
Jan Möbius's avatar
Jan Möbius committed
39
40
*                                                                            *
\*===========================================================================*/
Jan Möbius's avatar
 
Jan Möbius committed
41

42

Jan Möbius's avatar
 
Jan Möbius committed
43
44
45
46
47
48



// Mainwindow

#include "OpenFlipper/Core/Core.hh"
Hans-Christian Ebke's avatar
Hans-Christian Ebke committed
49
#include "common/glew_wrappers.hh"
50
#include "OpenFlipper/BasePlugin/PluginFunctionsCore.hh"
Jan Möbius's avatar
 
Jan Möbius committed
51
52
53
54
55
56

// Qt
#include <qgl.h>

// stdc++
#include <csignal>
57
#include <regex>
58
59

#include <QCommandLineParser>
Jan Möbius's avatar
 
Jan Möbius committed
60

Matthias Möller's avatar
Matthias Möller committed
61
#if ( defined(WIN32))
Mike Kremer's avatar
Mike Kremer committed
62
63
64
65
  #define NO_EXECINFO
#endif

#ifndef NO_EXECINFO
66
#include <execinfo.h>
Jan Möbius's avatar
 
Jan Möbius committed
67
68
#endif

69
70
71
72
#ifdef PYTHON_ENABLED
  #include <PythonInterpreter/PythonInterpreter.hh>
#endif

Jan Möbius's avatar
 
Jan Möbius committed
73
74
75
#ifdef USE_OPENMP
#endif

76
#ifdef WIN32
77
  #include <Windows/windows-startup.hh>
78
79
#endif

80
#include <CommandLine/CommandLineParser.hh>
81

82
83
84
85
86
87
88

/* ==========================================================
 *
 * Linux function printing a full stack trace to the console
 *
 * ==========================================================*/
#ifndef NO_EXECINFO
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

#if defined(__GLIBCXX__) || defined(__GLIBCPP__)
// GCC: implement demangling using cxxabi
#include <cxxabi.h>
std::string demangle(const std::string& _symbol)
{
    int status;
    char* demangled = abi::__cxa_demangle(_symbol.c_str(), nullptr, nullptr, &status);
    if (demangled) {
        std::string result{demangled};
        free(demangled);
        if (status == 0) {
            return result;
        }
        else {
            return _symbol;
        }
    }
    else {
        return _symbol;
    }
}
#else
// other compiler environment: no demangling
std::string demangle(const std::string& _symbol)
114
{
115
116
117
    return _symbol;
}
#endif
118

119
120
121
122
void backtrace()
{
    void *addresses[20];
    char **strings;
Jan Möbius's avatar
Jan Möbius committed
123

124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    int size = backtrace(addresses, 20);
    strings = backtrace_symbols(addresses, size);
    std::cerr << "Stack frames: " << size << std::endl;
    // line format:
    // <path>(<mangled_name>+<offset>) [<address>]
    std::regex line_format{R"(^\s*(.+)\((([^()]+)?\+(0x[0-9a-f]+))?\)\s+\[(0x[0-9a-f]+)\]\s*$)"};
    for(int i = 0; i < size; i++) {
        std::string line{strings[i]};
        std::smatch match;
        std::regex_match(line, match, line_format);
        if (!match.empty()) {
            auto file_name = match[1].str();
            auto symbol = demangle(match[3].str());
            auto offset = match[4].str();
            auto address = match[5].str();
            std::cerr << i << ":";
            if (!file_name.empty()) std::cerr << " " << file_name << " ::";
            if (!symbol.empty()) std::cerr << " " << symbol;
            if (!offset.empty()) std::cerr << " (+" << offset << ")";
            if (!address.empty()) std::cerr << " [" << address << "]";
            std::cerr << std::endl;
        }
    }
    free(strings);
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
}
#endif

/* ==========================================================
 *
 * General segfault handler. This function is called if OpenFlipper
 * crashes
 *
 * ==========================================================*/
void segfaultHandling (int) {

  // 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;

  // Linux Handler
#ifndef NO_EXECINFO
  std::cerr << "\33[0m"  << "Trying a backtrace to show what happened last: " << std::endl;
  backtrace();

  std::cerr << "\n" << std::endl;
  std::cerr << "Backtrace completed, trying to abort now ..." << std::endl;
#endif

  // Windows handler via StackWalker
#ifdef WIN32
  StackWalkerToConsole sw;
  sw.ShowCallstack();
#endif


Jan Möbius's avatar
Jan Möbius committed
187
188
189
190
191
192
193
194
  std::cerr << "Trying to get additional information (This might fail if the memory is corrupted)." << std::endl;

  if (OpenFlipper::Options::gui()) {
    for ( unsigned int i = 0 ; i <  4 ; ++i) {
      std::cerr << "DrawMode Viewer "<<  i << " " << PluginFunctions::drawMode(i).description() << std::endl;
    }
  }

195
196
  std::abort();
}
197

Dirk Wilden's avatar
Dirk Wilden committed
198

199
200
// Detector for OpenGL
#include "OpenGL/OpenGLDetection.hh"
201

Dirk Wilden's avatar
Dirk Wilden committed
202
203
int main(int argc, char **argv)
{
204
205
206
207
208
209
210
#ifdef _WIN32
  // This make crashes visible - without them, starting the
  // application from cmd.exe or powershell can surprisingly hide
  // any signs of a an application crash!
  SetErrorMode(0); // 0: Use the system default, which is to display all error dialog boxes.
#endif

211

212
213
  // Remove -psn_0_xxxxx argument which is automatically
  // attached by MacOSX
Mike Kremer's avatar
   
Mike Kremer committed
214
  for (int i = 0; i < argc; i++) {
215
216
217
218
219
    if(strlen(argv[i]) > 4) {
      if( ( (argv[i])[0] == '-' ) &&
        ( (argv[i])[1] == 'p' ) &&
        ( (argv[i])[2] == 's' ) &&
        ( (argv[i])[3] == 'n' ) ) {
Jan Möbius's avatar
Jan Möbius committed
220
221
        argc--;
        argv[i] = (char *)"";
222
223
224
      }
    }
  }
Jan Möbius's avatar
Jan Möbius committed
225

Dirk Wilden's avatar
Dirk Wilden committed
226
227
228
  OpenFlipper::Options::argc(&argc);
  OpenFlipper::Options::argv(&argv);

229
  // Set organization and application names
230
  QCoreApplication::setOrganizationName("VCI");
231
232
  QCoreApplication::setApplicationName(TOSTRING(PRODUCT_STRING));
  QCoreApplication::setApplicationVersion(OpenFlipper::Options::coreVersion());
Dirk Wilden's avatar
Dirk Wilden committed
233

234
235
236
237
  // initialize a core application to check for commandline parameters
  QCoreApplication* coreApp = new QCoreApplication(argc, argv);

  OpenFlipper::Options::initializeSettings();
238
239
240

  QCommandLineParser parser;
  QString errorMessage;
Dirk Wilden's avatar
Dirk Wilden committed
241

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  // parse command line options
  switch (parseCommandLine(parser, &errorMessage)) {
  case CommandLineOk:
	  break;
  case CommandLineError:
	  fputs(qPrintable(errorMessage), stderr);
	  fputs("\n\n", stderr);
	  fputs(qPrintable(parser.helpText()), stderr);
	  return 1;
  case CommandLineVersionRequested:
	  printf("%s %s\n", qPrintable(QCoreApplication::applicationName()),
		  qPrintable(QCoreApplication::applicationVersion()));
	  return 0;
  case CommandLineHelpRequested:
	  parser.showHelp();
	  Q_UNREACHABLE();
  }

  // only one application is allowed so delete the core application
  // once cmdline parsing is done
  delete coreApp;



266
267
268
269
#ifdef WIN32
  //attach a console if necessary
  attachConsole();
#endif
Dirk Wilden's avatar
Dirk Wilden committed
270

271
#ifndef NO_CATCH_SIGSEGV
Dirk Wilden's avatar
Dirk Wilden committed
272
273
  // Set a handler for segfaults
  std::signal(SIGSEGV, segfaultHandling);
274
#endif
Dirk Wilden's avatar
Dirk Wilden committed
275

Jan Möbius's avatar
Jan Möbius committed
276
  OpenFlipper::Options::windowTitle(TOSTRING(PRODUCT_STRING)" v" + OpenFlipper::Options::coreVersion());
277

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

Jan Möbius's avatar
 
Jan Möbius committed
280
    // OpenGL check
281
    QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
282

283
284
    // Try creating a valid OpenGL context
    /******************************/
285

286
287
    // Get a valid context format
    QSurfaceFormat resultFormat = getContextFormat();
288

289
290
291
292
293
    // Set temporary(!) OpenGL settings
    OpenFlipper::Options::samples(resultFormat.samples(), true);
    OpenFlipper::Options::glStereo(resultFormat.stereo(), true);
    OpenFlipper::Options::glVersion(resultFormat.version(), true);
    OpenFlipper::Options::coreProfile(resultFormat.profile() == QSurfaceFormat::CoreProfile, true);
294

295
296
    // Create the actual context
    QSurfaceFormat::setDefaultFormat(resultFormat);
297
    QApplication app(argc, argv);
298
299
300
    QOffscreenSurface *surface = new QOffscreenSurface();
    surface->create();

301
    // Make the globally shared OpenGLContext current
302
    QOpenGLContext::globalShareContext()->makeCurrent(surface);
303
    /******************************/
304
305


306
    // Check whether there is OpenGL support. If not, return.
Jan Möbius's avatar
 
Jan Möbius committed
307
308
309
310
    if ( !QGLFormat::hasOpenGL() ) {
      std::cerr << "This system has no OpenGL support.\n";
      return -1;
    }
311

Jan Möbius's avatar
 
Jan Möbius committed
312
313
    // create core ( this also reads the ini files )
    Core * w = new Core( );
314
315
316
#ifdef PYTHON_ENABLED
    setCorePointer(w);
#endif
317

318
    QString tLang = OpenFlipperSettings().value("Core/Language/Translation","en_US").toString();
319
320
321
322

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

323
324
    // Install translator for qt internals
    QTranslator qtTranslator;
Jan Möbius's avatar
Jan Möbius committed
325
    qtTranslator.load("qt_" + tLang, QLibraryInfo::location(QLibraryInfo::TranslationsPath));
326
327
328
    app.installTranslator(&qtTranslator);
    
    // install translator for Core Application
Dirk Wilden's avatar
Dirk Wilden committed
329
330
331
332
333
334
335
336
337
338
339
340
    QString translationDir = OpenFlipper::Options::translationsDirStr() + QDir::separator();
    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();

schultz's avatar
schultz committed
341
342
        if ( myAppTranslator->load( fileInfo.filePath() ) )
        {    
Dirk Wilden's avatar
Dirk Wilden committed
343
          app.installTranslator(myAppTranslator);
schultz's avatar
schultz committed
344
345
346
        } else 
        {
  	        delete myAppTranslator;
Dirk Wilden's avatar
Dirk Wilden committed
347
348
349
        }
      }
     }
Jan's avatar
Jan committed
350
351
352
353

    #ifndef __APPLE__
    initGlew();
    #endif
354
355
356
357

    // After setting all Options from command line, build the real gui
    w->init();

358
359
360
361
362
    const QStringList positionalArguments = parser.positionalArguments();

    for ( auto file: positionalArguments ) {
      w->commandLineOpen(file, openPolyMeshes);
    }
363

Jan Möbius's avatar
 
Jan Möbius committed
364
    return app.exec();
365

Jan Möbius's avatar
 
Jan Möbius committed
366
  } else {
367

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

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

373
374
375
376
377

#ifdef PYTHON_ENABLED
    setCorePointer(w);
#endif

Jan Möbius's avatar
 
Jan Möbius committed
378
379
    // After setting all Options from command line, build the real gui
    w->init();
380

381
382
383
384
385
    const QStringList positionalArguments = parser.positionalArguments();

    for ( auto file: positionalArguments ) {
      w->commandLineOpen(file, openPolyMeshes);
    }
386

Dirk Wilden's avatar
Dirk Wilden committed
387
    return app.exec();
Jan Möbius's avatar
 
Jan Möbius committed
388
389
390
391
  }

  return 0;
}