Aufgrund von Umarbeiten des s3 Storage wird es in GitLab, in nächster Zeit, mögliche Performance-Einbußen geben. Näheres dazu unter: https://maintenance.itc.rwth-aachen.de/ticket/status/messages/43/show_ticket/6670

main.cpp 16 KB
Newer Older
1
#include "applicationdata.h"
2 3 4 5
#include "audio/audiocapturemanager.h"
#include "codeeditorhelper.h"
#include "dmx/HardwareInterface.h"
#include "dmx/channel.h"
6
#include "dmx/device.h"
7 8 9 10
#include "dmx/dmxchannelfilter.h"
#include "dmx/driver.h"
#include "dmx/programm.h"
#include "errornotifier.h"
11
#include "gui/audioeventdataview.h"
12
#include "gui/channelprogrammeditor.h"
13
#include "gui/colorplot.h"
14
#include "gui/controlitem.h"
15
#include "gui/controlitemdata.h"
16 17
#include "gui/controlpanel.h"
#include "gui/graph.h"
18 19
#include "gui/mapeditor.h"
#include "gui/mapview.h"
20
#include "gui/oscillogram.h"
21 22
#include "gui/programblockeditor.h"
#include "modelmanager.h"
23
#include "modules/dmxconsumer.h"
24 25 26
#include "modules/ledconsumer.h"
#include "modules/programblock.h"
#include "settings.h"
27
#include "sortedmodelview.h"
28
#include "spotify/spotify.h"
29
#include "system_error_handler.h"
30 31 32
#include "test/testloopprogramm.h"
#include "test/testmodulsystem.h"
#include "test/testsampleclass.h"
33
#include "updater.h"
34 35 36 37 38 39 40 41 42 43 44 45 46
#include "usermanagment.h"
#include <QCoreApplication>
#include <QCryptographicHash>
#include <QDebug>
#include <QDir>
#include <QEasingCurve>
#include <QFileInfo>
#include <QGuiApplication>
#include <QLibrary>
#include <QMetaProperty>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickView>
47
#include <QSharedMemory>
48
#include <QSslSocket>
49 50 51 52 53
#include <QTimer>
#include <chrono>
#include <cmath>
#include <id.h>
#include <limits>
54

55 56 57 58
#ifdef Q_OS_WIN
#include <winuser.h>
#endif

59
#ifdef DrMinGW
60 61
#include "exchndl.h"
#include <QNetworkReply>
62
#endif
63

64
int main(int argc, char *argv[]) {
65 66 67 68 69 70 71
    QSharedMemory mem(QStringLiteral("Lichteuerung Leander Schulten"));
    if (!mem.create(1)) {
#ifdef Q_OS_WIN
        MessageBoxA(nullptr, "The Lichtsteuerung is already running on this computer.", nullptr, MB_OK);
#endif
        return 0;
    }
72
    error::initErrorHandler();
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
#ifdef DrMinGW
    ExcHndlInit();
    auto path = QStandardPaths::writableLocation(QStandardPaths::QStandardPaths::AppDataLocation);
    path += QLatin1String("/Lichtsteuerung");
    QDir dir(path);
    if(!dir.mkpath(path)){
        qWarning() << "Error creating dirs : " << path;
    }
    path += QLatin1String("/crash_dump_");
    path += QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yyyy HH.mm.ss"));
    path += QLatin1String(".txt");
    qDebug() << "The crash report file is : " << path;
    ExcHndlSetLogFileNameA(path.toStdString().c_str());
#endif

88
    if (!QSslSocket::supportsSsl()) {
89
        ErrorNotifier::showError(QStringLiteral("No OpenSSL library found!\nUpdates are not possible and the Spotify support does not work."));
90 91
    }

92 93 94 95
    Updater updater;
    QObject::connect(&updater,&Updater::needUpdate,[&](){
        updater.update();
    });
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 125 126 127 128 129 130 131 132 133 134
#ifdef DrMinGW
    // send crash reports
    auto files = dir.entryInfoList(QDir::Filter::Files);
    for(auto & file : files){
        if(file.fileName().startsWith(QLatin1String("crash_dump"))){
            auto newFileName = file.absolutePath() + "/sended_" +file.fileName();
            if(!QFile::rename(file.absoluteFilePath(),newFileName)){
                qWarning() << "Failed to rename file from " << file.absoluteFilePath() << " to " << newFileName;
                continue;
            }
            auto upload = [newFileName,&updater](){
                // we only want to report Bugs for new versions
                if(updater.getState() == Updater::UpdaterState::NoUpdateAvailible){
                    QFile file(newFileName);
                    if(!file.open(QIODevice::ReadOnly)){
                        qWarning() <<  "Failed to open file " << newFileName;
                        return;
                    }
                    auto request = QNetworkRequest(QUrl(QStringLiteral("https://orga.symposion.hilton.rwth-aachen.de/send_crash_report")));
                    request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader,"text/plain");
                    auto response = updater.getQNetworkAccessManager()->post(request,file.readAll());
                    QObject::connect(response,&QNetworkReply::finished,[=](){
                        if(response->error() == QNetworkReply::NoError){
                            qDebug() << "crash report erfolgreich hochlgeladen";
                        }else{
                            qWarning() << "Fehler beim hochladen des crash reports : " << response->errorString();
                        }
                        response->deleteLater();
                    });
                }
            };
            if(updater.getState() == Updater::UpdaterState::NotChecked){
                QObject::connect(&updater,&Updater::stateChanged,upload);
            }else{
                upload();
            }
        }
    }
#endif
135
    /*Test::TestModulSystem testModulSystem;
Leander Schulten's avatar
Leander Schulten committed
136
    testModulSystem.runTest();
137
    return 0;*/
138 139
    // init the rand function for different random numbers each startup
    srand(static_cast<unsigned int>(time(nullptr)));
140

141
    Test::testSampleClass();
Leander Schulten's avatar
Leander Schulten committed
142

143 144 145
    class CatchingErrorApplication : public QGuiApplication{
    public:
        CatchingErrorApplication(int &argc, char **argv):QGuiApplication(argc,argv){}
146
        bool notify(QObject* receiver, QEvent* event) override
147 148 149 150 151 152 153
        {
            try {
                return QGuiApplication::notify(receiver, event);
            } catch (std::exception &e) {
                qCritical("Error %s sending event %s to object %s (%s)",
                    e.what(), typeid(*event).name(), qPrintable(receiver->objectName()),
                    receiver->metaObject()->className());
154
                QString error = QStringLiteral("Error ") +e.what()+"sending event "+typeid(*event).name()+" to object "+ qPrintable(receiver->objectName())+" "+ receiver->metaObject()->className();
155
                ErrorNotifier::get()->newError(error);
156 157 158 159
            } catch (...) {
                qCritical("Error <unknown> sending event %s to object %s (%s)",
                    typeid(*event).name(), qPrintable(receiver->objectName()),
                    receiver->metaObject()->className());
160
                QString error = QStringLiteral("Error ") + "<unknown> sending event "+typeid(*event).name()+" to object "+ qPrintable(receiver->objectName())+" "+ receiver->metaObject()->className();
161
                ErrorNotifier::get()->newError(error);
162 163 164 165 166 167
            }

            return false;
        }
    };

168
    using namespace GUI;
169
    using namespace DMX;
170

Leander Schulten's avatar
Leander Schulten committed
171 172 173 174
//    auto defaultFormat = QSurfaceFormat::defaultFormat();
//    defaultFormat.setSamples(8);
//    QSurfaceFormat::setDefaultFormat(defaultFormat);
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
175
    CatchingErrorApplication app(argc, argv);
Leander Schulten's avatar
Leander Schulten committed
176 177
    QQmlApplicationEngine engine;
    ControlPanel::setQmlEngine(&engine);
178
    ProgramBlockEditor::engine = &engine;
179
    Driver::dmxValueModel.setQMLEngineThread(engine.thread());
180 181 182
    // normally this should be done automatically
    qRegisterMetaType<QAbstractListModel*>("QAbstractListModel*");
    qRegisterMetaType<PropertyInformationModel*>("PropertyInformationModel*");
183 184
    //qmlRegisterType<const ChannelVector*>("my.models",1,0,"ChannelVector");
    qmlRegisterType<ChannelProgrammEditor>("custom.licht",1,0,"ChannelProgrammEditor");
185 186
    qmlRegisterType<GUI::MapView>("custom.licht",1,0,"MapView");
    qmlRegisterType<GUI::MapEditor>("custom.licht",1,0,"MapEditor");
Leander Schulten's avatar
Leander Schulten committed
187
    qmlRegisterType<ControlPanel>("custom.licht",1,0,"ControlPanel");
188 189 190
    qmlRegisterType<Graph>("custom.licht",1,0,"Graph");
    qmlRegisterType<Oscillogram>("custom.licht",1,0,"Oscillogram");
    qmlRegisterType<Colorplot>("custom.licht",1,0,"Colorplot");
191
    //qmlRegisterType<ErrorNotifier>("custom.licht",1,0,"ErrorNotifier");
Leander Schulten's avatar
Leander Schulten committed
192
    qmlRegisterType<ControlItem>("custom.licht.template",1,0,"ControlItemTemplate");
Leander Schulten's avatar
Leander Schulten committed
193
    qmlRegisterType<ControlItemData>("custom.licht.template",1,0,"ControlItemData");
Leander Schulten's avatar
Leander Schulten committed
194 195
    qmlRegisterType<DimmerGroupControlItemData>("custom.licht",1,0,"DimmerGroupControlItemData");
    qmlRegisterType<DMXChannelFilter>("custom.licht",1,0,"DMXChannelFilter");
196
    qmlRegisterType<CodeEditorHelper>("custom.licht",1,0,"CodeEditorHelper");
197
    qmlRegisterType<ProgramBlockEditor>("custom.licht",1,0,"ProgramBlockEditor");
198
    qmlRegisterType<GUI::AudioEventDataView>("custom.licht", 1, 0, "AudioEventDataView");
199
    qmlRegisterType<SortedModelVectorView>("custom.licht",1,0,"SortedModelVectorView");
Leander Schulten's avatar
Leander Schulten committed
200
    qRegisterMetaType<DMXChannelFilter::Operation>("Operation");
201
    qmlRegisterUncreatableType<UserManagment>("custom.licht",1,0,"Permission",QStringLiteral("Singletone in c++"));
202
    qmlRegisterUncreatableMetaObject(Updater::staticMetaObject,"custom.licht",1,0,"UpdaterState",QStringLiteral("Enum in c++"));
Leander Schulten's avatar
Leander Schulten committed
203
    qmlRegisterUncreatableMetaObject(ControlItemData::staticMetaObject,"custom.licht",1,0,"ControlType",QStringLiteral("Enum in c++"));
Leander Schulten's avatar
Leander Schulten committed
204
    qRegisterMetaType<UserManagment::Permission>("Permission");
205
    qRegisterMetaType<Modules::detail::PropertyInformation::Type>("Type");
206
    qRegisterMetaType<Modules::ValueType>("ValueType");
207
    qRegisterMetaType<Modules::ProgramBlock::Status>("Status");
208
    qRegisterMetaType<Modules::PropertiesVector*>("PropertiesVector*");
209
    qRegisterMetaType<Driver::DMXQMLValue*>("DMXQMLValue*");
Leander Schulten's avatar
Leander Schulten committed
210
    qRegisterMetaType<DMX::DMXChannelFilter*>("DMXChannelFilter*");
211

212 213 214

    updater.checkForUpdate();

215
    // Load Settings and ApplicationData
216
    Settings::setLocalSettingFile(QFileInfo(QStringLiteral("settings.ini")));
217
    Settings settings;
218
    QFile file(QStringLiteral("QTJSONFile.json"));
219 220 221 222
    if(!file.exists()){
        file.setFileName(settings.getJsonSettingsFilePath());
    }
    if(file.exists()){
223
        file.copy(file.fileName()+"_"+QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yyyy HH.mm.ss")));
224 225
    }
    auto after = ApplicationData::loadData(file);
226 227
    // nachdem die Benutzer geladen wurden, auto login durchführen
    UserManagment::get()->autoLoginUser();
Leander Schulten's avatar
Leander Schulten committed
228

Leander Schulten's avatar
Leander Schulten committed
229
//#warning Dont use IDBase<xxxxx>::getAllIDBases() in this file. It will crash the aplication when its closing
Leander Schulten's avatar
Leander Schulten committed
230

231
    std::thread t(Test::testLoopProgramm);
232
    t.join();
Leander Schulten's avatar
Leander Schulten committed
233

234 235
    auto & spotify = Spotify::get();
    Modules::ModuleManager::singletone()->setSpotify(&spotify);
236
    spotify.autoLoginUser();
Leander Schulten's avatar
Leander Schulten committed
237

238 239 240 241 242 243
    QStringList dataList;
    const QMetaObject &mo = QEasingCurve::staticMetaObject;
    QMetaEnum metaEnum = mo.enumerator(mo.indexOfEnumerator("Type"));
    for (int i = 0; i < QEasingCurve::NCurveTypes - 1; ++i) {
        dataList.append(metaEnum.key(i));
    }
Leander Schulten's avatar
Leander Schulten committed
244 245
    QStringList moduleTypeList;
    const QMetaObject &_mom = Modules::Module::staticMetaObject;
246
    QMetaEnum _metaEnum =_mom.enumerator(_mom.indexOfEnumerator("Type"));
Leander Schulten's avatar
Leander Schulten committed
247 248 249
    for (int i = 0; i < _metaEnum.keyCount(); ++i) {
        moduleTypeList.append(_metaEnum.key(i));
    }
250
    QStringList valueTypeList;
251
    valueTypeList << QStringLiteral("Brightness") << QStringLiteral("RGB") ;
Leander Schulten's avatar
Leander Schulten committed
252

253
    QStringList modolePropertyTypeList;
254
    modolePropertyTypeList << QStringLiteral("Int") << QStringLiteral("Long") << QStringLiteral("Float") << QStringLiteral("Double") << QStringLiteral("Bool") << QStringLiteral("String") << QStringLiteral("RGB Color");
255 256 257 258 259 260 261 262
    // Does not work: do it manually
    /*const QMetaObject &_momProp = Modules::detail::PropertyInformation::staticMetaObject;
    qDebug() << "Enum count" <<_momProp.enumeratorCount();
    QMetaEnum _metaEnumP =_momProp.enumerator(mo.indexOfEnumerator("Type"));
    for (int i = 0; i < _metaEnumP.keyCount(); ++i) {
        modolePropertyTypeList.append(_metaEnumP.key(i));
    }*/

263 264 265
    CatchingErrorApplication::connect(&app, &QGuiApplication::lastWindowClosed, [&]() {
        Modules::ModuleManager::singletone()->controller().stop();
        Audio::AudioCaptureManager::get().stopCapturingAndWait();
266 267
        QFile savePath(settings.getJsonSettingsFilePath());
        ApplicationData::saveData(savePath);
268
        Driver::stopAndUnloadDriver();
269
        updater.runUpdateInstaller();
270
    });
271
    Settings::connect(&settings,&Settings::driverFilePathChanged,[&](){
272
        Driver::loadAndStartDriver(settings.getDriverFilePath());
273
    });
274
    Settings::connect(&settings,&Settings::updatePauseInMsChanged,[&](){
Leander Schulten's avatar
Leander Schulten committed
275 276 277 278
        if(Driver::getCurrentDriver()){
            Driver::getCurrentDriver()->setWaitTime(std::chrono::milliseconds(settings.getUpdatePauseInMs()));
        }
    });
279
    Modules::ModuleManager::singletone()->loadAllModulesInDir(settings.getModuleDirPath());
280
    Settings::connect(&settings,&Settings::moduleDirPathChanged,[&](){
281 282
        Modules::ModuleManager::singletone()->loadAllModulesInDir(settings.getModuleDirPath());
    });
Leander Schulten's avatar
Leander Schulten committed
283

284
    ModelManager::get().setSettings(&settings);
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
    engine.rootContext()->setContextProperty(QStringLiteral("ModelManager"),&ModelManager::get());
    engine.rootContext()->setContextProperty(QStringLiteral("easingModel"),dataList);
    engine.rootContext()->setContextProperty(QStringLiteral("ErrorNotifier"),ErrorNotifier::get());
    QQmlApplicationEngine::setObjectOwnership(ErrorNotifier::get(),QQmlEngine::CppOwnership);
    engine.rootContext()->setContextProperty(QStringLiteral("devicePrototypeModel"),ModelManager::get().getDevicePrototypeModel());
    engine.rootContext()->setContextProperty(QStringLiteral("modulesModel"),Modules::ModuleManager::singletone()->getModules());
    engine.rootContext()->setContextProperty(QStringLiteral("moduleTypeModel"),moduleTypeList);
    engine.rootContext()->setContextProperty(QStringLiteral("valueTypeList"),valueTypeList);
    engine.rootContext()->setContextProperty(QStringLiteral("modolePropertyTypeList"),modolePropertyTypeList);
    engine.rootContext()->setContextProperty(QStringLiteral("deviceModel"),ModelManager::get().getDeviceModel());
    engine.rootContext()->setContextProperty(QStringLiteral("programmModel"),ModelManager::get().getProgramModel());
    engine.rootContext()->setContextProperty(QStringLiteral("programmPrototypeModel"),ModelManager::get().getProgramPrototypeModel());
    engine.rootContext()->setContextProperty(QStringLiteral("programBlocksModel"),&Modules::ProgramBlockManager::model);
    engine.rootContext()->setContextProperty(QStringLiteral("userModel"),UserManagment::get()->getUserModel());
    engine.rootContext()->setContextProperty(QStringLiteral("UserManagment"),UserManagment::get());
    engine.rootContext()->setContextProperty(QStringLiteral("Settings"),&settings);
    engine.rootContext()->setContextProperty(QStringLiteral("spotify"),&spotify);
    engine.rootContext()->setContextProperty(QStringLiteral("updater"),&updater);
    engine.rootContext()->setContextProperty(QStringLiteral("ledConsumer"),&Modules::LedConsumer::allLedConsumer);
304
    QQmlEngine::setObjectOwnership(&Driver::dmxValueModel,QQmlEngine::CppOwnership);
305
    engine.rootContext()->setContextProperty(QStringLiteral("dmxOutputValues"),&Driver::dmxValueModel);
306
    engine.rootContext()->setContextProperty(QStringLiteral("AudioManager"), &Audio::AudioCaptureManager::get());
307
    engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
Leander Schulten's avatar
Leander Schulten committed
308

309

Leander Schulten's avatar
Leander Schulten committed
310 311
    // laden erst nach dem laden des qml ausführen
    after();
312 313 314


    // Treiber laden
Leander Schulten's avatar
Leander Schulten committed
315
#define USE_DUMMY_DRIVER
316
#ifndef USE_DUMMY_DRIVER
317 318 319
    if (!Driver::loadAndStartDriver(settings.getDriverFilePath())) {
        ErrorNotifier::showError(QStringLiteral("Can`t start the DMX driver. The DMX output will not work. You can load a different driver in the Settings tab."));
    } else {
320
        Driver::getCurrentDriver()->setWaitTime(std::chrono::milliseconds(40));
321
    }
322

323 324 325
#else
#include "test/DriverDummy.h"

326
    DriverDummy driver;
327
    driver.setSetValuesCallback([](unsigned char* values, int size, double time){
328
        std::memset(values,0,size);
329
        DMXChannelFilter::initValues(values,size);
330
        DMX::Programm::fill(values,size,time);
331
        Modules::DMXConsumer::fillWithDMXConsumer(values,size);
332
        DMXChannelFilter::filterValues(values,size);
333
        Driver::dmxValueModel.setValues(values,size);
334
    });
335
    driver.setWaitTime(std::chrono::milliseconds(40));
336
    driver.init();
337
    driver.start();
338
#endif
339

340
    auto &audioManager = Audio::AudioCaptureManager::get();
341 342
    if (!audioManager.startCapturingFromDefaultInput()) {
        ErrorNotifier::showError("Audio capturing not possible");
343
    }
344

345
    Modules::ModuleManager::singletone()->controller().start();
Leander Schulten's avatar
Leander Schulten committed
346
    //ControlPanel::getLastCreated()->addDimmerGroupControl();
347
    return CatchingErrorApplication::exec();
Leander Schulten's avatar
Leander Schulten committed
348
}