Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:46:21

0001 // -*- C++ -*-
0002 //
0003 // Package:     Core
0004 // Class  :     CmsShowMain
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:
0010 //         Created:  Mon Dec  3 08:38:38 PST 2007
0011 //
0012 
0013 // system include files
0014 #include <memory>
0015 
0016 #include <sstream>
0017 #include <functional>
0018 #include <boost/program_options.hpp>
0019 #include <cstring>
0020 
0021 #include "TSystem.h"
0022 #include "TGLWidget.h"
0023 #include "TTimer.h"
0024 #include "TROOT.h"
0025 #include "TGFileDialog.h"
0026 #include "TGMsgBox.h"
0027 #include "TMonitor.h"
0028 #include "TServerSocket.h"
0029 #include "TEveLine.h"
0030 #include "TEveManager.h"
0031 #include "TFile.h"
0032 #include "TGClient.h"
0033 #include "TVirtualX.h"
0034 #include <KeySymbols.h>
0035 
0036 #include "Fireworks/Core/interface/CmsShowMain.h"
0037 
0038 #include "Fireworks/Core/interface/FWEveViewManager.h"
0039 
0040 #include "Fireworks/Core/interface/FWTableViewManager.h"
0041 #include "Fireworks/Core/interface/FWTriggerTableViewManager.h"
0042 #include "Fireworks/Core/interface/FWEventItemsManager.h"
0043 #include "Fireworks/Core/interface/FWViewManagerManager.h"
0044 #include "Fireworks/Core/interface/FWGUIManager.h"
0045 #include "Fireworks/Core/interface/FWLiteJobMetadataManager.h"
0046 #include "Fireworks/Core/interface/FWModelChangeManager.h"
0047 #include "Fireworks/Core/interface/FWColorManager.h"
0048 #include "Fireworks/Core/src/FWColorSelect.h"
0049 #include "Fireworks/Core/interface/FWSelectionManager.h"
0050 #include "Fireworks/Core/interface/FWConfigurationManager.h"
0051 #include "Fireworks/Core/interface/FWMagField.h"
0052 #include "Fireworks/Core/interface/Context.h"
0053 
0054 #include "Fireworks/Core/interface/CmsShowNavigator.h"
0055 #include "Fireworks/Core/interface/CSGAction.h"
0056 #include "Fireworks/Core/interface/CSGContinuousAction.h"
0057 #include "Fireworks/Core/interface/FWLiteJobMetadataUpdateRequest.h"
0058 
0059 #include "Fireworks/Core/interface/ActionsList.h"
0060 
0061 #include "Fireworks/Core/interface/Context.h"
0062 #include "Fireworks/Core/interface/FWMagField.h"
0063 
0064 #include "Fireworks/Core/interface/CmsShowTaskExecutor.h"
0065 #include "Fireworks/Core/interface/CmsShowMainFrame.h"
0066 #include "Fireworks/Core/interface/CmsShowSearchFiles.h"
0067 
0068 #include "Fireworks/Core/interface/fwLog.h"
0069 #include "Fireworks/Core/src/FWTTreeCache.h"
0070 
0071 #include "FWCore/FWLite/interface/FWLiteEnabler.h"
0072 
0073 #if defined(R__LINUX)
0074 #include "TGX11.h"  // !!!! AMT has to be at the end to pass build
0075 #include "X11/Xlib.h"
0076 #endif
0077 //
0078 // constants, enums and typedefs
0079 //
0080 
0081 static const char* const kInputFilesOpt = "input-files";
0082 static const char* const kInputFilesCommandOpt = "input-files,i";
0083 static const char* const kConfigFileOpt = "config-file";
0084 static const char* const kConfigFileCommandOpt = "config-file,c";
0085 static const char* const kGeomFileOpt = "geom-file";
0086 static const char* const kGeomFileCommandOpt = "geom-file,g";
0087 static const char* const kSimGeomFileOpt = "sim-geom-file";
0088 static const char* const kSimGeomFileCommandOpt = "sim-geom-file";
0089 static const char* const kTGeoNameOpt = "tgeo-name";
0090 static const char* const kTGeoNameCommandOpt = "tgeo-name";
0091 static const char* const kNoConfigFileOpt = "noconfig";
0092 static const char* const kNoConfigFileCommandOpt = "noconfig,n";
0093 static const char* const kPlayOpt = "play";
0094 static const char* const kPlayCommandOpt = "play,p";
0095 static const char* const kLoopOpt = "loop";
0096 static const char* const kLoopCommandOpt = "loop";
0097 static const char* const kLogLevelCommandOpt = "log";
0098 static const char* const kLogTreeCacheOpt = "log-tree-cache";
0099 static const char* const kSizeTreeCacheOpt = "tree-cache-size";
0100 static const char* const kPrefetchTreeCacheOpt = "tree-cache-prefetch";
0101 static const char* const kEveOpt = "eve";
0102 static const char* const kEveCommandOpt = "eve";
0103 static const char* const kAdvancedRenderOpt = "shine";
0104 static const char* const kAdvancedRenderCommandOpt = "shine,s";
0105 static const char* const kHelpOpt = "help";
0106 static const char* const kHelpCommandOpt = "help,h";
0107 static const char* const kSoftCommandOpt = "soft";
0108 static const char* const kExpertCommandOpt = "expert";
0109 static const char* const kPortCommandOpt = "port";
0110 static const char* const kPlainRootCommandOpt = "prompt";
0111 static const char* const kRootInteractiveCommandOpt = "root-interactive,r";
0112 static const char* const kChainCommandOpt = "chain";
0113 static const char* const kLiveCommandOpt = "live";
0114 static const char* const kFieldCommandOpt = "field";
0115 static const char* const kFreePaletteCommandOpt = "free-palette";
0116 static const char* const kAutoSaveAllViews = "auto-save-all-views";
0117 static const char* const kAutoSaveType = "auto-save-type";
0118 static const char* const kAutoSaveHeight = "auto-save-height";
0119 static const char* const kSyncAllViews = "sync-all-views";
0120 static const char* const kEnableFPE = "enable-fpe";
0121 static const char* const kZeroWinOffsets = "zero-window-offsets";
0122 static const char* const kNoVersionCheck = "no-version-check";
0123 
0124 //
0125 // constructors and destructor
0126 //
0127 CmsShowMain::CmsShowMain(int argc, char* argv[])
0128     : CmsShowMainBase(),
0129       m_navigator(new CmsShowNavigator(*this)),
0130       m_metadataManager(new FWLiteJobMetadataManager()),
0131       m_context(new fireworks::Context(
0132           changeManager(), selectionManager(), eiManager(), colorManager(), m_metadataManager.get())),
0133       m_loadedAnyInputFile(false),
0134       m_openFile(nullptr),
0135       m_live(false),
0136       m_liveTimer(new SignalTimer()),
0137       m_liveTimeout(600000),
0138       m_lastXEventSerial(0),
0139       m_noVersionCheck(false),
0140       m_globalTagCheck(true) {
0141   try {
0142     TGLWidget* w = TGLWidget::Create(gClient->GetDefaultRoot(), kTRUE, kTRUE, nullptr, 10, 10);
0143     delete w;
0144   } catch (std::exception& iException) {
0145     fwLog(fwlog::kError) << "Failed creating an OpenGL window: " << iException.what()
0146                          << "\n"
0147                             "Things to check:\n"
0148                             "- Is DISPLAY environment variable set?\n"
0149                             "- Are OpenGL libraries installed?\n"
0150                             "- If running remotely, make sure you use 'ssh -X' or 'ssh -Y'.\n"
0151                             "See also: https://twiki.cern.ch/twiki/bin/viewauth/CMS/WorkBookFireworks\n";
0152     gSystem->Exit(1);
0153   }
0154 
0155   eiManager()->setContext(m_context.get());
0156 
0157   std::string descString(argv[0]);
0158   descString += " [options] <data file>\nGeneral";
0159 
0160   namespace po = boost::program_options;
0161   po::options_description desc(descString);
0162   // clang-format off
0163   desc.add_options()(kInputFilesCommandOpt, po::value<std::vector<std::string> >(), "Input root files")(
0164       kConfigFileCommandOpt, po::value<std::string>(), "Include configuration file")(
0165       kNoConfigFileCommandOpt, "Empty configuration")(kNoVersionCheck, "No file version check")(
0166       kGeomFileCommandOpt, po::value<std::string>(), "Reco geometry file. Default is cmsGeom10.root")(
0167       kSimGeomFileCommandOpt,
0168       po::value<std::string>(),
0169       "Geometry file for browsing in table view. Default is CmsSimGeom-14.root. Can be simulation or reco geometry in "
0170       "TGeo format")(kTGeoNameCommandOpt, po::value<std::string>(), "TGeoManager name. The default is \"cmsGeo;1\"")(
0171       kFieldCommandOpt, po::value<double>(), "Set magnetic field value explicitly. Default is auto-field estimation")(
0172       kRootInteractiveCommandOpt, "Enable root interactive prompt")(
0173       kSoftCommandOpt, "Try to force software rendering to avoid problems with bad hardware drivers")(
0174       kExpertCommandOpt, "Enable PF user plugins.")(kHelpCommandOpt, "Display help message");
0175 
0176   po::options_description livedesc("Live Event Display");
0177   livedesc.add_options()(
0178       kPlayCommandOpt, po::value<float>(), "Start in play mode with given interval between events in seconds")(
0179       kPortCommandOpt, po::value<unsigned int>(), "Listen to port for new data files to open")(
0180       kLoopCommandOpt, "Loop events in play mode")(
0181       kChainCommandOpt,
0182       po::value<unsigned int>(),
0183       "Chain up to a given number of recently open files. Default is 1 - no chain")(
0184       kLiveCommandOpt, "Enforce playback mode if a user is not using display")(
0185       kAutoSaveAllViews,
0186       po::value<std::string>(),
0187       "Auto-save all views with given prefix (run_event_lumi_view.<auto-save-type> is appended)")(
0188       kAutoSaveType, po::value<std::string>(), "Image type of auto-saved views, png or jpg (png is default)")(
0189       kAutoSaveHeight, po::value<int>(), "Screenshots height when auto-save-all-views is enabled")(
0190       kSyncAllViews, "Synchronize all views on new event");
0191   // clang-format on
0192 
0193   po::options_description debugdesc("Debug");
0194   debugdesc.add_options()(kLogLevelCommandOpt,
0195                           po::value<unsigned int>(),
0196                           "Set log level starting from 0 to 4 : kDebug, kInfo, kWarning, kError")(
0197       kEveCommandOpt, "Show TEveBrowser to help debug problems")(kEnableFPE,
0198                                                                  "Enable detection of floating-point exceptions");
0199 
0200   po::options_description tcachedesc("TreeCache");
0201   tcachedesc.add_options()(kLogTreeCacheOpt, "Log tree cache operations and status")(
0202       kSizeTreeCacheOpt, po::value<int>(), "Set size of TTreeCache for data access in MB (default is 50)")(
0203       kPrefetchTreeCacheOpt, "Enable prefetching");
0204 
0205   po::options_description rnrdesc("Appearance");
0206   rnrdesc.add_options()(kFreePaletteCommandOpt, "Allow free color selection (requires special configuration!)")(
0207       kZeroWinOffsets, "Disable auto-detection of window position offsets")(kAdvancedRenderCommandOpt,
0208                                                                             "Enable line anti-aliasing");
0209   po::positional_options_description p;
0210   p.add(kInputFilesOpt, -1);
0211 
0212   po::options_description hiddendesc("hidden");
0213   hiddendesc.add_options();
0214 
0215   po::options_description all("");
0216   all.add(desc).add(rnrdesc).add(livedesc).add(debugdesc).add(tcachedesc);
0217 
0218   int newArgc = argc;
0219   char** newArgv = argv;
0220   po::variables_map vm;
0221   try {
0222     po::store(po::command_line_parser(newArgc, newArgv).options(all).positional(p).run(), vm);
0223 
0224     po::notify(vm);
0225   } catch (const std::exception& e) {
0226     // Return with exit status 0 to avoid generating crash reports
0227 
0228     fwLog(fwlog::kError) << e.what() << std::endl;
0229     std::cout << all << std::endl;
0230     exit(0);
0231   }
0232 
0233   if (vm.count(kHelpOpt)) {
0234     std::cout << all << std::endl;
0235     exit(0);
0236   }
0237 
0238   if (vm.count(kLogLevelCommandOpt)) {
0239     fwlog::LogLevel level = (fwlog::LogLevel)(vm[kLogLevelCommandOpt].as<unsigned int>());
0240     fwlog::setPresentLogLevel(level);
0241   }
0242 
0243   if (vm.count(kLogTreeCacheOpt)) {
0244     fwLog(fwlog::kInfo) << "Enabling logging of TTreCache operations." << std::endl;
0245     FWTTreeCache::LoggingOn();
0246   }
0247 
0248   if (vm.count(kPrefetchTreeCacheOpt)) {
0249     fwLog(fwlog::kInfo) << "Enabling TTreCache prefetching." << std::endl;
0250     FWTTreeCache::PrefetchingOn();
0251   }
0252 
0253   if (vm.count(kSizeTreeCacheOpt)) {
0254     int ds = vm[kSizeTreeCacheOpt].as<int>();
0255     if (ds < 0)
0256       throw std::runtime_error("tree-cache-size should be non negative");
0257     if (ds > 8192)
0258       throw std::runtime_error("tree-cache-size should be smaller than 8 GB");
0259     fwLog(fwlog::kInfo) << "Setting default TTreeCache size to " << ds << " MB." << std::endl;
0260     FWTTreeCache::SetDefaultCacheSize(ds * 1024 * 1024);
0261   }
0262 
0263   if (vm.count(kPlainRootCommandOpt)) {
0264     fwLog(fwlog::kInfo) << "Plain ROOT prompt requested" << std::endl;
0265     return;
0266   }
0267 
0268   const char* cmspath = gSystem->Getenv("CMSSW_BASE");
0269   if (nullptr == cmspath) {
0270     throw std::runtime_error("CMSSW_BASE environment variable not set");
0271   }
0272 
0273   // input file
0274   if (vm.count(kInputFilesOpt)) {
0275     m_inputFiles = vm[kInputFilesOpt].as<std::vector<std::string> >();
0276   }
0277 
0278   if (m_inputFiles.empty())
0279     fwLog(fwlog::kInfo) << "No data file given." << std::endl;
0280   else if (m_inputFiles.size() == 1)
0281     fwLog(fwlog::kInfo) << "Input " << m_inputFiles.front() << std::endl;
0282   else
0283     fwLog(fwlog::kInfo) << m_inputFiles.size() << " input files; first: " << m_inputFiles.front()
0284                         << ", last: " << m_inputFiles.back() << std::endl;
0285 
0286   // configuration file
0287   if (vm.count(kConfigFileOpt)) {
0288     setConfigFilename(vm[kConfigFileOpt].as<std::string>());
0289     if (access(configFilename(), R_OK) == -1) {
0290       fwLog(fwlog::kError) << "Specified configuration file does not exist. Quitting.\n";
0291       exit(1);
0292     }
0293 
0294     fwLog(fwlog::kInfo) << "Config " << configFilename() << std::endl;
0295   } else {
0296     if (vm.count(kNoConfigFileOpt)) {
0297       fwLog(fwlog::kInfo) << "No configuration is loaded.\n";
0298       configurationManager()->setIgnore();
0299     }
0300   }
0301 
0302   // geometry
0303   if (vm.count(kGeomFileOpt)) {
0304     m_globalTagCheck = false;
0305     setGeometryFilename(vm[kGeomFileOpt].as<std::string>());
0306     fwLog(fwlog::kInfo) << "Geometry file " << geometryFilename() << "\n";
0307   }
0308 
0309   if (vm.count(kSimGeomFileOpt)) {
0310     if (vm.count(kTGeoNameOpt))
0311       setSimGeometryFilename(vm[kSimGeomFileOpt].as<std::string>(), vm[kTGeoNameOpt].as<std::string>());
0312     else
0313       setSimGeometryFilename(vm[kSimGeomFileOpt].as<std::string>(), "cmsGeo;1");
0314   } else {
0315     setSimGeometryFilename("cmsSimGeom-14.root", "cmsGeo;1");
0316   }
0317 
0318   // Free-palette palette
0319   if (vm.count(kFreePaletteCommandOpt)) {
0320     FWColorPopup::EnableFreePalette();
0321     fwLog(fwlog::kInfo) << "Palette restriction removed on user request!\n";
0322   }
0323   bool eveMode = vm.count(kEveOpt);
0324 
0325   //Delay creating guiManager and enabling autoloading until here so that if we have a 'help' request we don't
0326   // open any graphics or build dictionaries
0327   FWLiteEnabler::enable();
0328 
0329   TEveManager::Create(kFALSE, eveMode ? "FIV" : "FI");
0330 
0331   if (vm.count(kExpertCommandOpt)) {
0332     m_context->setHidePFBuilders(false);
0333   } else {
0334     m_context->setHidePFBuilders(true);
0335   }
0336 
0337   if (vm.count(kExpertCommandOpt)) {
0338     m_context->setHidePFBuilders(false);
0339   } else {
0340     m_context->setHidePFBuilders(true);
0341   }
0342 
0343   setup(m_navigator.get(), m_context.get(), m_metadataManager.get());
0344 
0345   if (vm.count(kZeroWinOffsets)) {
0346     guiManager()->resetWMOffsets();
0347     fwLog(fwlog::kInfo) << "Window offsets reset on user request!\n";
0348   }
0349 
0350   if (vm.count(kAdvancedRenderOpt)) {
0351     TEveLine::SetDefaultSmooth(kTRUE);
0352   }
0353 
0354   //figure out where to find macros
0355   //tell ROOT where to find our macros
0356   CmsShowTaskExecutor::TaskFunctor f;
0357   // first check if port is not occupied
0358   if (vm.count(kPortCommandOpt)) {
0359     f = std::bind(&CmsShowMain::setupSocket, this, vm[kPortCommandOpt].as<unsigned int>());
0360     startupTasks()->addTask(f);
0361   }
0362   if (!geometryFilename().empty()) {
0363     f = std::bind(&CmsShowMainBase::loadGeometry, this);
0364     startupTasks()->addTask(f);
0365   }
0366   f = std::bind(&CmsShowMainBase::setupViewManagers, this);
0367   startupTasks()->addTask(f);
0368 
0369   if (vm.count(kLiveCommandOpt)) {
0370     f = std::bind(&CmsShowMain::setLiveMode, this);
0371     startupTasks()->addTask(f);
0372   }
0373 
0374   if (vm.count(kFieldCommandOpt)) {
0375     m_context->getField()->setSource(FWMagField::kUser);
0376     m_context->getField()->setUserField(vm[kFieldCommandOpt].as<double>());
0377   }
0378 
0379   f = std::bind(&CmsShowMain::setupDataHandling, this);
0380   startupTasks()->addTask(f);
0381 
0382   if (vm.count(kLoopOpt))
0383     setPlayLoop();
0384 
0385   if (eveMode) {
0386     f = std::bind(&CmsShowMainBase::setupDebugSupport, this);
0387     startupTasks()->addTask(f);
0388   }
0389   if (vm.count(kChainCommandOpt)) {
0390     f = std::bind(
0391         &CmsShowNavigator::setMaxNumberOfFilesToChain, m_navigator.get(), vm[kChainCommandOpt].as<unsigned int>());
0392     startupTasks()->addTask(f);
0393   }
0394   if (vm.count(kPlayOpt)) {
0395     f = std::bind(&CmsShowMainBase::setupAutoLoad, this, vm[kPlayOpt].as<float>());
0396     startupTasks()->addTask(f);
0397   }
0398 
0399   if (vm.count(kAutoSaveAllViews)) {
0400     std::string type = "png";
0401     if (vm.count(kAutoSaveType)) {
0402       type = vm[kAutoSaveType].as<std::string>();
0403       if (type != "png" && type != "jpg") {
0404         fwLog(fwlog::kError) << "Specified auto-save type not supported. Quitting.\n";
0405         exit(1);
0406       }
0407     }
0408     std::string fmt = vm[kAutoSaveAllViews].as<std::string>();
0409     fmt += "%u_%u_%llu_%s.";
0410     fmt += type;
0411     setAutoSaveAllViewsFormat(fmt);
0412   }
0413   if (vm.count(kAutoSaveHeight)) {
0414     setAutoSaveAllViewsHeight(vm[kAutoSaveHeight].as<int>());
0415   }
0416   if (vm.count(kSyncAllViews)) {
0417     FWEveViewManager::syncAllViews();
0418   }
0419   if (vm.count(kNoVersionCheck)) {
0420     m_noVersionCheck = true;
0421   }
0422   if (vm.count(kEnableFPE)) {
0423     gSystem->SetFPEMask();
0424   }
0425 
0426   if (vm.count(kPortCommandOpt)) {
0427     f = std::bind(&CmsShowMain::connectSocket, this);
0428     startupTasks()->addTask(f);
0429   }
0430 
0431   startupTasks()->startDoingTasks();
0432 }
0433 
0434 //
0435 // Destruction
0436 //
0437 
0438 CmsShowMain::~CmsShowMain() {
0439   //avoids a seg fault from eve which happens if eve is terminated after the GUI is gone
0440   selectionManager()->clearSelection();
0441 }
0442 
0443 class DieTimer : public TTimer {
0444 protected:
0445   CmsShowMain* fApp;
0446 
0447 public:
0448   DieTimer(CmsShowMain* app) : TTimer(), fApp(app) { Start(0, kTRUE); }
0449 
0450   Bool_t Notify() override {
0451     TurnOff();
0452     fApp->doExit();
0453     delete this;
0454     return kFALSE;
0455   }
0456 };
0457 
0458 void CmsShowMain::quit() { new DieTimer(this); }
0459 
0460 void CmsShowMain::doExit() {
0461   // pre terminate eve
0462   m_context->deleteEveElements();
0463   guiManager()->evePreTerminate();
0464 
0465   // sleep at least 150 ms
0466   // windows in ROOT GUI are destroyed in 150 ms timeout after
0467   gSystem->Sleep(151);
0468   gSystem->ProcessEvents();
0469   gSystem->ExitLoop();
0470 }
0471 
0472 //
0473 // assignment operators
0474 //
0475 // const CmsShowMain& CmsShowMain::operator=(const CmsShowMain& rhs)
0476 // {
0477 //   //An exception safe implementation is
0478 //   CmsShowMain temp(rhs);
0479 //   swap(rhs);
0480 //
0481 //   return *this;
0482 // }
0483 
0484 //
0485 // member functions
0486 //
0487 
0488 const fwlite::Event* CmsShowMain::getCurrentEvent() const {
0489   if (m_navigator.get())
0490     return static_cast<const fwlite::Event*>(m_navigator->getCurrentEvent());
0491   return nullptr;
0492 }
0493 
0494 void CmsShowMain::fileChangedSlot(const TFile* file) {
0495   m_openFile = file;
0496   if (file)
0497     guiManager()->titleChanged(m_navigator->frameTitle());
0498 
0499   if (context()->getField()->getSource() == FWMagField::kNone) {
0500     context()->getField()->resetFieldEstimate();
0501   }
0502   if (geometryFilename().empty()) {
0503     std::string gt = m_navigator->getCurrentGlobalTag();
0504     fireworks::Context::getInstance()->getGeom()->applyGlobalTag(gt);
0505   }
0506   m_metadataManager->update(new FWLiteJobMetadataUpdateRequest(getCurrentEvent(), m_openFile));
0507 }
0508 
0509 void CmsShowMain::eventChangedImp() {
0510   CmsShowMainBase::eventChangedImp();
0511   guiManager()->titleChanged(m_navigator->frameTitle());
0512   m_metadataManager->update(new FWLiteJobMetadataUpdateRequest(getCurrentEvent(), m_openFile));
0513 }
0514 
0515 void CmsShowMain::resetInitialization() {
0516   //printf("Need to reset\n");
0517 }
0518 
0519 void CmsShowMain::openData() {
0520   const char* kRootType[] = {"ROOT files", "*.root", nullptr, nullptr};
0521   TGFileInfo fi;
0522   fi.fFileTypes = kRootType;
0523   /* this is how things used to be done:
0524       fi.fIniDir = ".";
0525       this is bad because the destructor calls delete[] on fIniDir.
0526     */
0527   fi.fIniDir = new char[128];
0528   strncpy(fi.fIniDir, ".", 127);
0529   guiManager()->updateStatus("waiting for data file ...");
0530   new TGFileDialog(gClient->GetDefaultRoot(), guiManager()->getMainFrame(), kFDOpen, &fi);
0531   guiManager()->updateStatus("loading file ...");
0532   if (fi.fFilename) {
0533     m_navigator->openFile(fi.fFilename);
0534 
0535     setLoadedAnyInputFileAfterStartup();
0536     m_navigator->firstEvent();
0537     checkPosition();
0538     draw();
0539   }
0540   guiManager()->clearStatus();
0541 }
0542 
0543 void CmsShowMain::appendData() {
0544   const char* kRootType[] = {"ROOT files", "*.root", nullptr, nullptr};
0545   TGFileInfo fi;
0546   fi.fFileTypes = kRootType;
0547   /* this is how things used to be done:
0548       fi.fIniDir = ".";
0549       this is bad because the destructor calls delete[] on fIniDir.
0550    */
0551   fi.fIniDir = new char[128];
0552   strncpy(fi.fIniDir, ".", 127);
0553   guiManager()->updateStatus("waiting for data file ...");
0554   new TGFileDialog(gClient->GetDefaultRoot(), guiManager()->getMainFrame(), kFDOpen, &fi);
0555   guiManager()->updateStatus("loading file ...");
0556   if (fi.fFilename) {
0557     m_navigator->appendFile(fi.fFilename, false, false);
0558     setLoadedAnyInputFileAfterStartup();
0559     checkPosition();
0560     draw();
0561     guiManager()->titleChanged(m_navigator->frameTitle());
0562   }
0563   guiManager()->clearStatus();
0564 }
0565 
0566 void CmsShowMain::openDataViaURL() {
0567   if (m_searchFiles.get() == nullptr) {
0568     m_searchFiles =
0569         std::make_unique<CmsShowSearchFiles>("", "Open Remote Data Files", guiManager()->getMainFrame(), 500, 400);
0570     m_searchFiles->CenterOnParent(kTRUE, TGTransientFrame::kBottomRight);
0571   }
0572   std::string chosenFile = m_searchFiles->chooseFileFromURL();
0573   if (!chosenFile.empty()) {
0574     guiManager()->updateStatus("loading file ...");
0575     if (m_navigator->openFile(chosenFile)) {
0576       setLoadedAnyInputFileAfterStartup();
0577       m_navigator->firstEvent();
0578       checkPosition();
0579       draw();
0580       guiManager()->clearStatus();
0581     } else {
0582       guiManager()->updateStatus("failed to load data file");
0583     }
0584   }
0585 }
0586 
0587 //
0588 // const member functions
0589 //
0590 
0591 //_______________________________________________________________________________
0592 void CmsShowMain::autoLoadNewEvent() {
0593   stopAutoLoadTimer();
0594 
0595   // case when start with no input file
0596   if (!m_loadedAnyInputFile) {
0597     if (m_monitor.get())
0598       startAutoLoadTimer();
0599     return;
0600   }
0601 
0602   bool reachedEnd = (forward() && m_navigator->isLastEvent()) || (!forward() && m_navigator->isFirstEvent());
0603 
0604   if (loop() && reachedEnd) {
0605     forward() ? m_navigator->firstEvent() : m_navigator->lastEvent();
0606     draw();
0607   } else if (!reachedEnd) {
0608     forward() ? m_navigator->nextEvent() : m_navigator->previousEvent();
0609     draw();
0610   }
0611 
0612   // stop loop in case no loop or monitor mode
0613   if (reachedEnd && (loop() || m_monitor.get()) == kFALSE) {
0614     if (forward() && m_navigator->isLastEvent()) {
0615       guiManager()->enableActions();
0616       checkPosition();
0617     }
0618 
0619     if ((!forward()) && m_navigator->isFirstEvent()) {
0620       guiManager()->enableActions();
0621       checkPosition();
0622     }
0623   } else
0624     startAutoLoadTimer();
0625 }
0626 
0627 //______________________________________________________________________________
0628 
0629 void CmsShowMain::checkPosition() {
0630   if ((m_monitor.get() || loop()) && isPlaying())
0631     return;
0632 
0633   guiManager()->getMainFrame()->enableNavigatorControls();
0634 
0635   if (m_navigator->isFirstEvent())
0636     guiManager()->disablePrevious();
0637 
0638   if (m_navigator->isLastEvent()) {
0639     guiManager()->disableNext();
0640     // force enable play events action in --port mode
0641     if (m_monitor.get() && !guiManager()->playEventsAction()->isEnabled())
0642       guiManager()->playEventsAction()->enable();
0643   }
0644 }
0645 
0646 //==============================================================================
0647 void CmsShowMain::setupDataHandling() {
0648   guiManager()->updateStatus("Setting up data handling...");
0649 
0650   // navigator filtering  ->
0651   m_navigator->fileChanged_.connect(std::bind(&CmsShowMain::fileChangedSlot, this, std::placeholders::_1));
0652   m_navigator->editFiltersExternally_.connect(
0653       std::bind(&FWGUIManager::updateEventFilterEnable, guiManager(), std::placeholders::_1));
0654   m_navigator->filterStateChanged_.connect(
0655       std::bind(&CmsShowMain::navigatorChangedFilterState, this, std::placeholders::_1));
0656   m_navigator->postFiltering_.connect(std::bind(&CmsShowMain::postFiltering, this, std::placeholders::_1));
0657 
0658   // navigator fitlering <-
0659   guiManager()->showEventFilterGUI_.connect(
0660       std::bind(&CmsShowNavigator::showEventFilterGUI, m_navigator.get(), std::placeholders::_1));
0661   guiManager()->filterButtonClicked_.connect(std::bind(&CmsShowMain::filterButtonClicked, this));
0662 
0663   // Data handling. File related and therefore not in the base class.
0664   if (guiManager()->getAction(cmsshow::sOpenData) != nullptr)
0665     guiManager()->getAction(cmsshow::sOpenData)->activated.connect(sigc::mem_fun(*this, &CmsShowMain::openData));
0666   if (guiManager()->getAction(cmsshow::sAppendData) != nullptr)
0667     guiManager()->getAction(cmsshow::sAppendData)->activated.connect(sigc::mem_fun(*this, &CmsShowMain::appendData));
0668   if (guiManager()->getAction(cmsshow::sSearchFiles) != nullptr)
0669     guiManager()
0670         ->getAction(cmsshow::sSearchFiles)
0671         ->activated.connect(sigc::mem_fun(*this, &CmsShowMain::openDataViaURL));
0672 
0673   setupActions();
0674   // init data from  CmsShowNavigator configuration, can do this with signals since there were not connected yet
0675   guiManager()->setFilterButtonIcon(m_navigator->getFilterState());
0676 
0677   for (unsigned int ii = 0; ii < m_inputFiles.size(); ++ii) {
0678     const std::string& fname = m_inputFiles[ii];
0679     if (fname.empty())
0680       continue;
0681     guiManager()->updateStatus("loading data file ...");
0682     if (!m_navigator->appendFile(fname, false, false)) {
0683       guiManager()->updateStatus("failed to load data file");
0684     } else {
0685       m_loadedAnyInputFile = true;
0686     }
0687   }
0688 
0689   if (m_loadedAnyInputFile) {
0690     m_navigator->firstEvent();
0691     checkPosition();
0692     if (configurationManager()->getIgnore())
0693       guiManager()->initEmpty();
0694     else
0695       setupConfiguration();
0696   } else {
0697     if (configFilename()[0] == '\0') {
0698       guiManager()->initEmpty();
0699     } else {
0700       setupConfiguration();
0701     }
0702 
0703     bool geoBrowser = (configFilename()[0] != '\0') && (eiManager()->begin() == eiManager()->end());
0704 
0705     if (m_monitor.get() == nullptr && (configurationManager()->getIgnore() == false) && (!geoBrowser)) {
0706       if (m_inputFiles.empty())
0707         openDataViaURL();
0708       else
0709         openData();
0710     }
0711   }
0712 }
0713 
0714 void CmsShowMain::setLoadedAnyInputFileAfterStartup() {
0715   if (m_loadedAnyInputFile == false) {
0716     m_loadedAnyInputFile = true;
0717     if ((configFilename()[0] == '\0') && (configurationManager()->getIgnore() == false))
0718       setupConfiguration();
0719   }
0720 }
0721 
0722 void CmsShowMain::setupSocket(unsigned int iSocket) {
0723   m_monitor = std::make_unique<TMonitor>();
0724   TServerSocket* server = new TServerSocket(iSocket, kTRUE);
0725   if (server->GetErrorCode()) {
0726     fwLog(fwlog::kError) << "CmsShowMain::setupSocket, can't create socket on port " << iSocket << "." << std::endl;
0727     exit(0);
0728   }
0729   m_monitor->Add(server);
0730 }
0731 
0732 void CmsShowMain::connectSocket() { m_monitor->Connect("Ready(TSocket*)", "CmsShowMain", this, "notified(TSocket*)"); }
0733 
0734 void CmsShowMain::notified(TSocket* iSocket) {
0735   TServerSocket* server = dynamic_cast<TServerSocket*>(iSocket);
0736   if (server) {
0737     TSocket* connection = server->Accept();
0738     if (connection) {
0739       m_monitor->Add(connection);
0740       std::stringstream s;
0741       s << "received connection from " << iSocket->GetInetAddress().GetHostName();
0742       guiManager()->updateStatus(s.str().c_str());
0743     }
0744   } else {
0745     char buffer[4096];
0746     memset(buffer, 0, sizeof(buffer));
0747     if (iSocket->RecvRaw(buffer, sizeof(buffer)) <= 0) {
0748       m_monitor->Remove(iSocket);
0749       //std::stringstream s;
0750       //s << "closing connection to "<<iSocket->GetInetAddress().GetHostName();
0751       //m_guiManager->updateStatus(s.str().c_str());
0752       delete iSocket;
0753       return;
0754     }
0755     std::string fileName(buffer);
0756     std::string::size_type lastNonSpace = fileName.find_last_not_of(" \n\t");
0757     if (lastNonSpace != std::string::npos) {
0758       fileName.erase(lastNonSpace + 1);
0759     }
0760 
0761     std::stringstream s;
0762     s << "New file notified '" << fileName << "'";
0763     guiManager()->updateStatus(s.str().c_str());
0764 
0765     bool appended = m_navigator->appendFile(fileName, true, m_live);
0766 
0767     if (appended) {
0768       if (m_live && isPlaying() && forward())
0769         m_navigator->activateNewFileOnNextEvent();
0770       else if (!isPlaying())
0771         checkPosition();
0772 
0773       // bootstrap case: --port  and no input file
0774       if (!m_loadedAnyInputFile) {
0775         m_loadedAnyInputFile = true;
0776         m_navigator->firstEvent();
0777         if (!isPlaying())
0778           draw();
0779       }
0780 
0781       std::stringstream sr;
0782       sr << "New file registered '" << fileName << "'";
0783       guiManager()->updateStatus(sr.str().c_str());
0784     } else {
0785       std::stringstream sr;
0786       sr << "New file NOT registered '" << fileName << "'";
0787       guiManager()->updateStatus(sr.str().c_str());
0788     }
0789   }
0790 }
0791 
0792 void CmsShowMain::checkKeyBindingsOnPLayEventsStateChanged() {
0793   if (m_live) {
0794     Int_t keycode = gVirtualX->KeysymToKeycode((int)kKey_Space);
0795     Window_t id = FWGUIManager::getGUIManager()->getMainFrame()->GetId();
0796     gVirtualX->GrabKey(id, keycode, 0, isPlaying());
0797   }
0798 }
0799 
0800 void CmsShowMain::stopPlaying() {
0801   stopAutoLoadTimer();
0802   if (m_live)
0803     m_navigator->resetNewFileOnNextEvent();
0804   CmsShowMainBase::stopPlaying();
0805   guiManager()->enableActions();
0806   checkPosition();
0807 }
0808 
0809 void CmsShowMain::navigatorChangedFilterState(int state) {
0810   guiManager()->setFilterButtonIcon(state);
0811   if (m_navigator->filesNeedUpdate() == false) {
0812     guiManager()->setFilterButtonText(m_navigator->filterStatusMessage());
0813     checkPosition();
0814   }
0815 }
0816 
0817 void CmsShowMain::filterButtonClicked() {
0818   if (m_navigator->getFilterState() == CmsShowNavigator::kWithdrawn)
0819     guiManager()->showEventFilterGUI();
0820   else
0821     m_navigator->toggleFilterEnable();
0822 }
0823 
0824 void CmsShowMain::preFiltering() {
0825   // called only if filter has changed
0826   guiManager()->updateStatus("Filtering events");
0827 }
0828 
0829 void CmsShowMain::postFiltering(bool doDraw) {
0830   // called only filter is changed
0831   guiManager()->clearStatus();
0832   if (doDraw)
0833     draw();
0834   checkPosition();
0835   guiManager()->setFilterButtonText(m_navigator->filterStatusMessage());
0836 }
0837 
0838 //______________________________________________________________________________
0839 
0840 void CmsShowMain::setLiveMode() {
0841   m_live = true;
0842   m_liveTimer = std::make_unique<SignalTimer>();
0843   m_liveTimer->timeout_.connect(std::bind(&CmsShowMain::checkLiveMode, this));
0844 
0845   Window_t rootw, childw;
0846   Int_t root_x, root_y, win_x, win_y;
0847   UInt_t mask;
0848   gVirtualX->QueryPointer(gClient->GetDefaultRoot()->GetId(), rootw, childw, root_x, root_y, win_x, win_y, mask);
0849 
0850   m_liveTimer->SetTime(m_liveTimeout);
0851   m_liveTimer->Reset();
0852   m_liveTimer->TurnOn();
0853 }
0854 
0855 void CmsShowMain::checkLiveMode() {
0856   m_liveTimer->TurnOff();
0857 
0858 #if defined(R__LINUX)
0859   TGX11* x11 = dynamic_cast<TGX11*>(gVirtualX);
0860   if (x11) {
0861     XAnyEvent* ev = (XAnyEvent*)x11->GetNativeEvent();
0862     // printf("serial %d \n",(int)ev->serial );
0863 
0864     if (!isPlaying() && m_lastXEventSerial == ev->serial)
0865       guiManager()->playEventsAction()->switchMode();
0866     m_lastXEventSerial = ev->serial;
0867   }
0868 #endif
0869   m_liveTimer->SetTime((Long_t)(m_liveTimeout));
0870   m_liveTimer->Reset();
0871   m_liveTimer->TurnOn();
0872 }