main.cpp 15.9 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/channelprogrammeditor.h"
12
#include "gui/colorplot.h"
13
#include "gui/controlitem.h"
14
#include "gui/controlitemdata.h"
15
16
#include "gui/controlpanel.h"
#include "gui/graph.h"
17
18
#include "gui/mapeditor.h"
#include "gui/mapview.h"
19
#include "gui/oscillogram.h"
20
21
#include "gui/programblockeditor.h"
#include "modelmanager.h"
22
#include "modules/dmxconsumer.h"
23
24
25
#include "modules/ledconsumer.h"
#include "modules/programblock.h"
#include "settings.h"
26
#include "sortedmodelview.h"
27
#include "spotify/spotify.h"
28
#include "system_error_handler.h"
29
30
31
#include "test/testloopprogramm.h"
#include "test/testmodulsystem.h"
#include "test/testsampleclass.h"
32
#include "updater.h"
33
34
35
36
37
38
39
40
41
42
43
44
45
#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>
46
#include <QSslSocket>
47
48
49
50
51
#include <QTimer>
#include <chrono>
#include <cmath>
#include <id.h>
#include <limits>
52
53

#ifdef DrMinGW
54
55
#include "exchndl.h"
#include <QNetworkReply>
56
#endif
57

58
59
int main(int argc, char *argv[]) {
    error::initErrorHandler();
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#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

75
    if (!QSslSocket::supportsSsl()) {
76
        ErrorNotifier::showError(QStringLiteral("No OpenSSL library found!\nUpdates are not possible and the Spotify support does not work."));
77
78
    }

79
80
81
82
    Updater updater;
    QObject::connect(&updater,&Updater::needUpdate,[&](){
        updater.update();
    });
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
#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
122
    /*Test::TestModulSystem testModulSystem;
Leander Schulten's avatar
Leander Schulten committed
123
    testModulSystem.runTest();
124
    return 0;*/
125
126
    // init the rand function for different random numbers each startup
    srand(static_cast<unsigned int>(time(nullptr)));
127

128
    Test::testSampleClass();
Leander Schulten's avatar
Leander Schulten committed
129

130
131
132
    class CatchingErrorApplication : public QGuiApplication{
    public:
        CatchingErrorApplication(int &argc, char **argv):QGuiApplication(argc,argv){}
133
        bool notify(QObject* receiver, QEvent* event) override
134
135
136
137
138
139
140
        {
            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());
141
                QString error = QStringLiteral("Error ") +e.what()+"sending event "+typeid(*event).name()+" to object "+ qPrintable(receiver->objectName())+" "+ receiver->metaObject()->className();
142
                ErrorNotifier::get()->newError(error);
143
144
145
146
            } catch (...) {
                qCritical("Error <unknown> sending event %s to object %s (%s)",
                    typeid(*event).name(), qPrintable(receiver->objectName()),
                    receiver->metaObject()->className());
147
                QString error = QStringLiteral("Error ") + "<unknown> sending event "+typeid(*event).name()+" to object "+ qPrintable(receiver->objectName())+" "+ receiver->metaObject()->className();
148
                ErrorNotifier::get()->newError(error);
149
150
151
152
153
154
            }

            return false;
        }
    };

155
    using namespace GUI;
156
    using namespace DMX;
157

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

198
199
200

    updater.checkForUpdate();

201
    // Load Settings and ApplicationData
202
    Settings::setLocalSettingFile(QFileInfo(QStringLiteral("settings.ini")));
203
    Settings settings;
204
    QFile file(QStringLiteral("QTJSONFile.json"));
205
206
207
208
    if(!file.exists()){
        file.setFileName(settings.getJsonSettingsFilePath());
    }
    if(file.exists()){
209
        file.copy(file.fileName()+"_"+QDateTime::currentDateTime().toString(QStringLiteral("dd.MM.yyyy HH.mm.ss")));
210
211
    }
    auto after = ApplicationData::loadData(file);
212
213
    // nachdem die Benutzer geladen wurden, auto login durchführen
    UserManagment::get()->autoLoginUser();
Leander Schulten's avatar
Leander Schulten committed
214

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

217
    std::thread t(Test::testLoopProgramm);
218
    t.join();
Leander Schulten's avatar
Leander Schulten committed
219

220
221
    auto & spotify = Spotify::get();
    Modules::ModuleManager::singletone()->setSpotify(&spotify);
222
    spotify.autoLoginUser();
Leander Schulten's avatar
Leander Schulten committed
223

224
225
226
227
228
229
    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
230
231
    QStringList moduleTypeList;
    const QMetaObject &_mom = Modules::Module::staticMetaObject;
232
    QMetaEnum _metaEnum =_mom.enumerator(_mom.indexOfEnumerator("Type"));
Leander Schulten's avatar
Leander Schulten committed
233
234
235
    for (int i = 0; i < _metaEnum.keyCount(); ++i) {
        moduleTypeList.append(_metaEnum.key(i));
    }
236
    QStringList valueTypeList;
237
    valueTypeList << QStringLiteral("Brightness") << QStringLiteral("RGB") ;
Leander Schulten's avatar
Leander Schulten committed
238

239
    QStringList modolePropertyTypeList;
240
    modolePropertyTypeList << QStringLiteral("Int") << QStringLiteral("Long") << QStringLiteral("Float") << QStringLiteral("Double") << QStringLiteral("Bool") << QStringLiteral("String");
241
242
243
244
245
246
247
248
    // 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));
    }*/

249
    CatchingErrorApplication::connect(&app,&QGuiApplication::lastWindowClosed,[&](){
250
251
        QFile savePath(settings.getJsonSettingsFilePath());
        ApplicationData::saveData(savePath);
252
        Driver::stopAndUnloadDriver();
253
        updater.runUpdateInstaller();
254
    });
255
    Settings::connect(&settings,&Settings::driverFilePathChanged,[&](){
256
        Driver::loadAndStartDriver(settings.getDriverFilePath());
257
    });
258
259
260
    Settings::connect(&settings,&Settings::audioCaptureFilePathChanged,[&](){
        if(!Audio::AudioCaptureManager::get().startCapturing(settings.getAudioCaptureFilePath())){
            ErrorNotifier::get()->newError(QStringLiteral("Failed to load Audio Capture Library"));
Leander Schulten's avatar
Leander Schulten committed
261
262
        }
    });
263
    Settings::connect(&settings,&Settings::updatePauseInMsChanged,[&](){
Leander Schulten's avatar
Leander Schulten committed
264
265
266
267
        if(Driver::getCurrentDriver()){
            Driver::getCurrentDriver()->setWaitTime(std::chrono::milliseconds(settings.getUpdatePauseInMs()));
        }
    });
268
    Modules::ModuleManager::singletone()->loadAllModulesInDir(settings.getModuleDirPath());
269
    Settings::connect(&settings,&Settings::moduleDirPathChanged,[&](){
270
271
        Modules::ModuleManager::singletone()->loadAllModulesInDir(settings.getModuleDirPath());
    });
Leander Schulten's avatar
Leander Schulten committed
272

273
    ModelManager::get().setSettings(&settings);
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
    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);
293
    QQmlEngine::setObjectOwnership(&Driver::dmxValueModel,QQmlEngine::CppOwnership);
294
295
    engine.rootContext()->setContextProperty(QStringLiteral("dmxOutputValues"),&Driver::dmxValueModel);
    engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
Leander Schulten's avatar
Leander Schulten committed
296

297

Leander Schulten's avatar
Leander Schulten committed
298
299
    // laden erst nach dem laden des qml ausführen
    after();
300
301
302


    // Treiber laden
Leander Schulten's avatar
Leander Schulten committed
303
#define USE_DUMMY_DRIVER
304
#ifndef USE_DUMMY_DRIVER
305
    if(!Driver::loadAndStartDriver(settings.getDriverFilePath())){
306
        ErrorNotifier::showError("Cant start driver.");
307
308
    }else {
        Driver::getCurrentDriver()->setWaitTime(std::chrono::milliseconds(40));
309
    }
310

311
312
313
#else
#include "test/DriverDummy.h"

314
    DriverDummy driver;
315
    driver.setSetValuesCallback([](unsigned char* values, int size, double time){
316
        std::memset(values,0,size);
317
        DMXChannelFilter::initValues(values,size);
318
        DMX::Programm::fill(values,size,time);
319
        Modules::DMXConsumer::fillWithDMXConsumer(values,size);
320
        DMXChannelFilter::filterValues(values,size);
321
        Driver::dmxValueModel.setValues(values,size);
322
    });
323
    driver.setWaitTime(std::chrono::milliseconds(40));
324
    driver.init();
325
    driver.start();
326
#endif
327

328
329
330
    QTimer timer;
    timer.setInterval(15);
    QObject::connect(&timer,&QTimer::timeout,[&](){
331
        if(Audio::AudioCaptureManager::get().isCapturing()){
332
            if(Graph::getLast()) {
333
                Graph::getLast()->update();
334
335
            }
            if(Oscillogram::getLast()) {
336
                Oscillogram::getLast()->update();
337
338
            }
            if(Colorplot::getLast()) {
339
                Colorplot::getLast()->update();
340
            }
341
        }
342
343
    });
    timer.start();
344

345
346
    qDebug() << "start capturing : " << Audio::AudioCaptureManager::get().startCapturing(settings.getAudioCaptureFilePath());

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