#include <config.h>
#include <iostream>
#include <ctime>
#include <utils/common/RandHelper.h>
#include <utils/common/UtilExceptions.h>
#include <utils/common/MsgHandler.h>
#include <utils/common/MsgRetrievingFunction.h>
#include <utils/options/OptionsCont.h>
#include <utils/options/Option.h>
#include <utils/options/OptionsIO.h>
#include <utils/foxtools/MFXSynchQue.h>
#include <utils/gui/events/GUIEvent_Message.h>
#include <utils/gui/windows/GUIAppEnum.h>
#include <utils/gui/globjects/GUIGlObjectStorage.h>
#include <utils/gui/images/GUITexturesHelper.h>
#include <utils/xml/XMLSubSys.h>
#include <guisim/GUINet.h>
#include <guisim/GUIEventControl.h>
#include <guisim/GUIVehicleControl.h>
#include <netload/NLBuilder.h>
#include <netload/NLHandler.h>
#include <netload/NLJunctionControlBuilder.h>
#include <guinetload/GUIEdgeControlBuilder.h>
#include <guinetload/GUIDetectorBuilder.h>
#include <guinetload/GUITriggerBuilder.h>
#include <microsim/output/MSDetectorControl.h>
#include <microsim/devices/MSDevice.h>
#include <microsim/MSGlobals.h>
#include <microsim/MSFrame.h>
#include <microsim/MSRouteHandler.h>
#include <mesogui/GUIMEVehicleControl.h>
#include <libsumo/Helper.h>
#include <traci-server/TraCIServer.h>
#include "TraCIServerAPI_GUI.h"
#include "GUIApplicationWindow.h"
#include "GUILoadThread.h"
#include "GUIGlobals.h"
#include "GUIEvent_SimulationLoaded.h"
GUILoadThread::GUILoadThread(FXApp* app, GUIApplicationWindow* mw,
MFXSynchQue<GUIEvent*>& eq, FXEX::MFXThreadEvent& ev, const bool isLibsumo)
: MFXSingleEventThread(app, mw), myParent(mw), myEventQue(eq),
myEventThrow(ev), myAmLibsumo(isLibsumo) {
myErrorRetriever = new MsgRetrievingFunction<GUILoadThread>(this, &GUILoadThread::retrieveMessage, MsgHandler::MsgType::MT_ERROR);
myMessageRetriever = new MsgRetrievingFunction<GUILoadThread>(this, &GUILoadThread::retrieveMessage, MsgHandler::MsgType::MT_MESSAGE);
myWarningRetriever = new MsgRetrievingFunction<GUILoadThread>(this, &GUILoadThread::retrieveMessage, MsgHandler::MsgType::MT_WARNING);
MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever);
}
GUILoadThread::~GUILoadThread() {
delete myErrorRetriever;
delete myMessageRetriever;
delete myWarningRetriever;
}
FXint
GUILoadThread::run() {
MsgHandler::getMessageInstance()->addRetriever(myMessageRetriever);
MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever);
if (!OptionsCont::getOptions().getBool("no-warnings")) {
MsgHandler::getWarningInstance()->addRetriever(myWarningRetriever);
}
OptionsCont& oc = OptionsCont::getOptions();
try {
if (myFile != "") {
oc.clear();
MSFrame::fillOptions();
oc.setByRootElement(OptionsIO::getRoot(myFile), myFile);
oc.resetWritable();
OptionsIO::getOptions();
} else {
OptionsIO::loadConfiguration();
if (oc.isSet("configuration-file")) {
myFile = oc.getString("configuration-file");
myParent->addRecentConfig(FXPath::absolute(myFile.c_str()));
} else if (oc.isSet("net-file")) {
myFile = oc.getString("net-file");
myParent->addRecentNetwork(FXPath::absolute(myFile.c_str()));
}
myEventQue.push_back(new GUIEvent_Message("Loading '" + myFile + "'."));
myEventThrow.signal();
}
myTitle = myFile;
if (!myAmLibsumo) {
MsgHandler::getMessageInstance()->removeRetriever(&OutputDevice::getDevice("stdout"));
MsgHandler::getWarningInstance()->removeRetriever(&OutputDevice::getDevice("stderr"));
MsgHandler::getErrorInstance()->removeRetriever(&OutputDevice::getDevice("stderr"));
}
if (oc.getBool("duration-log.statistics") && oc.isDefault("verbose")) {
oc.setDefault("verbose", "true");
}
MsgHandler::initOutputOptions();
if (!MSFrame::checkOptions()) {
throw ProcessError();
}
XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), oc.getString("xml-validation.routes"));
GUIGlobals::gRunAfterLoad = oc.getBool("start") || (myAmLibsumo && std::getenv("LIBSUMO_GUI") != nullptr);
GUIGlobals::gQuitOnEnd = oc.getBool("quit-on-end");
GUIGlobals::gDemoAutoReload = oc.getBool("demo");
GUIGlobals::gTrackerInterval = STEPS2TIME(string2time(oc.getString("tracker-interval")));
} catch (ProcessError& e) {
if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
WRITE_ERROR(e.what());
}
GUIGlobals::gQuitOnEnd = oc.getBool("quit-on-end");
MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
submitEndAndCleanup(nullptr, 0, 0);
return 0;
}
NLBuilder::initRandomness();
MSFrame::setMSGlobals(oc);
GUITexturesHelper::allowTextures(!oc.getBool("disable-textures"));
MSVehicleControl* vehControl = nullptr;
GUIVisualizationSettings::UseMesoSim = MSGlobals::gUseMesoSim;
if (MSGlobals::gUseMesoSim) {
vehControl = new GUIMEVehicleControl();
} else {
vehControl = new GUIVehicleControl();
}
GUINet* net = nullptr;
SUMOTime simStartTime = 0;
SUMOTime simEndTime = 0;
std::vector<std::string> guiSettingsFiles;
bool osgView = false;
GUIEdgeControlBuilder* eb = nullptr;
try {
net = new GUINet(
vehControl,
new GUIEventControl(),
new GUIEventControl(),
new GUIEventControl());
std::map<int, TraCIServer::CmdExecutor> execs;
execs[libsumo::CMD_GET_GUI_VARIABLE] = &TraCIServerAPI_GUI::processGet;
execs[libsumo::CMD_SET_GUI_VARIABLE] = &TraCIServerAPI_GUI::processSet;
TraCIServer::openSocket(execs);
if (myAmLibsumo) {
libsumo::Helper::registerStateListener();
}
eb = new GUIEdgeControlBuilder();
GUIDetectorBuilder db(*net);
NLJunctionControlBuilder jb(*net, db);
GUITriggerBuilder tb;
NLHandler handler("", *net, db, tb, *eb, jb);
tb.setHandler(&handler);
NLBuilder builder(oc, *net, *eb, jb, db, handler);
MsgHandler::getErrorInstance()->clear();
MsgHandler::getWarningInstance()->clear();
MsgHandler::getMessageInstance()->clear();
if (!builder.build()) {
throw ProcessError();
} else {
net->initGUIStructures();
simStartTime = string2time(oc.getString("begin"));
simEndTime = string2time(oc.getString("end"));
guiSettingsFiles = oc.getStringVector("gui-settings-file");
#ifdef HAVE_OSG
osgView = oc.getBool("osg-view");
#endif
if (oc.isSet("edgedata-files")) {
if (!oc.isUsableFileList("edgedata-files")) {
WRITE_ERRORF(TL("Could not load edgedata-files '%'"), oc.getString("edgedata-files"));
} else {
for (const std::string& file : oc.getStringVector("edgedata-files")) {
net->loadEdgeData(file);
}
}
}
}
} catch (ProcessError& e) {
if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
WRITE_ERROR(e.what());
}
MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
delete net;
net = nullptr;
#ifndef _DEBUG
} catch (std::exception& e) {
WRITE_ERROR(e.what());
delete net;
net = nullptr;
#endif
}
if (net == nullptr) {
MSNet::clearAll();
}
delete eb;
submitEndAndCleanup(net, simStartTime, simEndTime, guiSettingsFiles, osgView,
oc.getBool("registry-viewport"));
return 0;
}
void
GUILoadThread::submitEndAndCleanup(GUINet* net,
const SUMOTime simStartTime,
const SUMOTime simEndTime,
const std::vector<std::string>& guiSettingsFiles,
const bool osgView,
const bool viewportFromRegistry) {
MsgHandler::getErrorInstance()->removeRetriever(myErrorRetriever);
MsgHandler::getWarningInstance()->removeRetriever(myWarningRetriever);
MsgHandler::getMessageInstance()->removeRetriever(myMessageRetriever);
GUIEvent* e = new GUIEvent_SimulationLoaded(net, simStartTime, simEndTime, myTitle, guiSettingsFiles, osgView, viewportFromRegistry);
myEventQue.push_back(e);
myEventThrow.signal();
}
void
GUILoadThread::loadConfigOrNet(const std::string& file) {
myFile = file;
if (myFile != "") {
OptionsIO::setArgs(0, nullptr);
}
start();
}
void
GUILoadThread::retrieveMessage(const MsgHandler::MsgType type, const std::string& msg) {
GUIEvent* e = new GUIEvent_Message(type, msg);
myEventQue.push_back(e);
myEventThrow.signal();
}
const std::string&
GUILoadThread::getFileName() const {
return myFile;
}