Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-05 22:48:07

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,
0203       po::value<int>(),
0204       "Set size of TTreeCache for data access in MB (default is 50)")(kPrefetchTreeCacheOpt, "Enable prefetching");
0205 
0206   po::options_description rnrdesc("Appearance");
0207   rnrdesc.add_options()(kFreePaletteCommandOpt, "Allow free color selection (requires special configuration!)")(
0208       kZeroWinOffsets, "Disable auto-detection of window position offsets")(kAdvancedRenderCommandOpt,
0209                                                                             "Enable line anti-aliasing");
0210   po::positional_options_description p;
0211   p.add(kInputFilesOpt, -1);
0212 
0213   po::options_description hiddendesc("hidden");
0214   hiddendesc.add_options();
0215 
0216   po::options_description all("");
0217   all.add(desc).add(rnrdesc).add(livedesc).add(debugdesc).add(tcachedesc);
0218 
0219   int newArgc = argc;
0220   char** newArgv = argv;
0221   po::variables_map vm;
0222   try {
0223     po::store(po::command_line_parser(newArgc, newArgv).options(all).positional(p).run(), vm);
0224 
0225     po::notify(vm);
0226   } catch (const std::exception& e) {
0227     // Return with exit status 0 to avoid generating crash reports
0228 
0229     fwLog(fwlog::kError) << e.what() << std::endl;
0230     std::cout << all << std::endl;
0231     exit(0);
0232   }
0233 
0234   if (vm.count(kHelpOpt)) {
0235     std::cout << all << std::endl;
0236     exit(0);
0237   }
0238 
0239   if (vm.count(kLogLevelCommandOpt)) {
0240     fwlog::LogLevel level = (fwlog::LogLevel)(vm[kLogLevelCommandOpt].as<unsigned int>());
0241     fwlog::setPresentLogLevel(level);
0242   }
0243 
0244   if (vm.count(kLogTreeCacheOpt)) {
0245     fwLog(fwlog::kInfo) << "Enabling logging of TTreCache operations." << std::endl;
0246     FWTTreeCache::LoggingOn();
0247   }
0248 
0249   if (vm.count(kPrefetchTreeCacheOpt)) {
0250     fwLog(fwlog::kInfo) << "Enabling TTreCache prefetching." << std::endl;
0251     FWTTreeCache::PrefetchingOn();
0252   }
0253 
0254   if (vm.count(kSizeTreeCacheOpt)) {
0255     int ds = vm[kSizeTreeCacheOpt].as<int>();
0256     if (ds < 0)
0257       throw std::runtime_error("tree-cache-size should be non negative");
0258     if (ds > 8192)
0259       throw std::runtime_error("tree-cache-size should be smaller than 8 GB");
0260     fwLog(fwlog::kInfo) << "Setting default TTreeCache size to " << ds << " MB." << std::endl;
0261     FWTTreeCache::SetDefaultCacheSize(ds * 1024 * 1024);
0262   }
0263 
0264   if (vm.count(kPlainRootCommandOpt)) {
0265     fwLog(fwlog::kInfo) << "Plain ROOT prompt requested" << std::endl;
0266     return;
0267   }
0268 
0269   const char* cmspath = gSystem->Getenv("CMSSW_BASE");
0270   if (nullptr == cmspath) {
0271     throw std::runtime_error("CMSSW_BASE environment variable not set");
0272   }
0273 
0274   // input file
0275   if (vm.count(kInputFilesOpt)) {
0276     m_inputFiles = vm[kInputFilesOpt].as<std::vector<std::string> >();
0277   }
0278 
0279   if (m_inputFiles.empty())
0280     fwLog(fwlog::kInfo) << "No data file given." << std::endl;
0281   else if (m_inputFiles.size() == 1)
0282     fwLog(fwlog::kInfo) << "Input " << m_inputFiles.front() << std::endl;
0283   else
0284     fwLog(fwlog::kInfo) << m_inputFiles.size() << " input files; first: " << m_inputFiles.front()
0285                         << ", last: " << m_inputFiles.back() << std::endl;
0286 
0287   // configuration file
0288   if (vm.count(kConfigFileOpt)) {
0289     setConfigFilename(vm[kConfigFileOpt].as<std::string>());
0290     if (access(configFilename(), R_OK) == -1) {
0291       fwLog(fwlog::kError) << "Specified configuration file does not exist. Quitting.\n";
0292       exit(1);
0293     }
0294 
0295     fwLog(fwlog::kInfo) << "Config " << configFilename() << std::endl;
0296   } else {
0297     if (vm.count(kNoConfigFileOpt)) {
0298       fwLog(fwlog::kInfo) << "No configuration is loaded.\n";
0299       configurationManager()->setIgnore();
0300     }
0301   }
0302 
0303   // geometry
0304   if (vm.count(kGeomFileOpt)) {
0305     m_globalTagCheck = false;
0306     setGeometryFilename(vm[kGeomFileOpt].as<std::string>());
0307     fwLog(fwlog::kInfo) << "Geometry file " << geometryFilename() << "\n";
0308   }
0309 
0310   if (vm.count(kSimGeomFileOpt)) {
0311     if (vm.count(kTGeoNameOpt))
0312       setSimGeometryFilename(vm[kSimGeomFileOpt].as<std::string>(), vm[kTGeoNameOpt].as<std::string>());
0313     else
0314       setSimGeometryFilename(vm[kSimGeomFileOpt].as<std::string>(), "cmsGeo;1");
0315   } else {
0316     setSimGeometryFilename("cmsSimGeom-14.root", "cmsGeo;1");
0317   }
0318 
0319   // Free-palette palette
0320   if (vm.count(kFreePaletteCommandOpt)) {
0321     FWColorPopup::EnableFreePalette();
0322     fwLog(fwlog::kInfo) << "Palette restriction removed on user request!\n";
0323   }
0324   bool eveMode = vm.count(kEveOpt);
0325 
0326   //Delay creating guiManager and enabling autoloading until here so that if we have a 'help' request we don't
0327   // open any graphics or build dictionaries
0328   FWLiteEnabler::enable();
0329 
0330   TEveManager::Create(kFALSE, eveMode ? "FIV" : "FI");
0331 
0332   if (vm.count(kExpertCommandOpt)) {
0333     m_context->setHidePFBuilders(false);
0334   } else {
0335     m_context->setHidePFBuilders(true);
0336   }
0337 
0338   if (vm.count(kExpertCommandOpt)) {
0339     m_context->setHidePFBuilders(false);
0340   } else {
0341     m_context->setHidePFBuilders(true);
0342   }
0343 
0344   setup(m_navigator.get(), m_context.get(), m_metadataManager.get());
0345 
0346   if (vm.count(kZeroWinOffsets)) {
0347     guiManager()->resetWMOffsets();
0348     fwLog(fwlog::kInfo) << "Window offsets reset on user request!\n";
0349   }
0350 
0351   if (vm.count(kAdvancedRenderOpt)) {
0352     TEveLine::SetDefaultSmooth(kTRUE);
0353   }
0354 
0355   //figure out where to find macros
0356   //tell ROOT where to find our macros
0357   CmsShowTaskExecutor::TaskFunctor f;
0358   // first check if port is not occupied
0359   if (vm.count(kPortCommandOpt)) {
0360     f = std::bind(&CmsShowMain::setupSocket, this, vm[kPortCommandOpt].as<unsigned int>());
0361     startupTasks()->addTask(f);
0362   }
0363   if (!geometryFilename().empty()) {
0364     f = std::bind(&CmsShowMainBase::loadGeometry, this);
0365     startupTasks()->addTask(f);
0366   }
0367   f = std::bind(&CmsShowMainBase::setupViewManagers, this);
0368   startupTasks()->addTask(f);
0369 
0370   if (vm.count(kLiveCommandOpt)) {
0371     f = std::bind(&CmsShowMain::setLiveMode, this);
0372     startupTasks()->addTask(f);
0373   }
0374 
0375   if (vm.count(kFieldCommandOpt)) {
0376     m_context->getField()->setSource(FWMagField::kUser);
0377     m_context->getField()->setUserField(vm[kFieldCommandOpt].as<double>());
0378   }
0379 
0380   f = std::bind(&CmsShowMain::setupDataHandling, this);
0381   startupTasks()->addTask(f);
0382 
0383   if (vm.count(kLoopOpt))
0384     setPlayLoop();
0385 
0386   if (eveMode) {
0387     f = std::bind(&CmsShowMainBase::setupDebugSupport, this);
0388     startupTasks()->addTask(f);
0389   }
0390   if (vm.count(kChainCommandOpt)) {
0391     f = std::bind(
0392         &CmsShowNavigator::setMaxNumberOfFilesToChain, m_navigator.get(), vm[kChainCommandOpt].as<unsigned int>());
0393     startupTasks()->addTask(f);
0394   }
0395   if (vm.count(kPlayOpt)) {
0396     f = std::bind(&CmsShowMainBase::setupAutoLoad, this, vm[kPlayOpt].as<float>());
0397     startupTasks()->addTask(f);
0398   }
0399 
0400   if (vm.count(kAutoSaveAllViews)) {
0401     std::string type = "png";
0402     if (vm.count(kAutoSaveType)) {
0403       type = vm[kAutoSaveType].as<std::string>();
0404       if (type != "png" && type != "jpg") {
0405         fwLog(fwlog::kError) << "Specified auto-save type not supported. Quitting.\n";
0406         exit(1);
0407       }
0408     }
0409     std::string fmt = vm[kAutoSaveAllViews].as<std::string>();
0410     fmt += "%u_%u_%llu_%s.";
0411     fmt += type;
0412     setAutoSaveAllViewsFormat(fmt);
0413   }
0414   if (vm.count(kAutoSaveHeight)) {
0415     setAutoSaveAllViewsHeight(vm[kAutoSaveHeight].as<int>());
0416   }
0417   if (vm.count(kSyncAllViews)) {
0418     FWEveViewManager::syncAllViews();
0419   }
0420   if (vm.count(kNoVersionCheck)) {
0421     m_noVersionCheck = true;
0422   }
0423   if (vm.count(kEnableFPE)) {
0424     gSystem->SetFPEMask();
0425   }
0426 
0427   if (vm.count(kPortCommandOpt)) {
0428     f = std::bind(&CmsShowMain::connectSocket, this);
0429     startupTasks()->addTask(f);
0430   }
0431 
0432   startupTasks()->startDoingTasks();
0433 }
0434 
0435 //
0436 // Destruction
0437 //
0438 
0439 CmsShowMain::~CmsShowMain() {
0440   //avoids a seg fault from eve which happens if eve is terminated after the GUI is gone
0441   selectionManager()->clearSelection();
0442 }
0443 
0444 class DieTimer : public TTimer {
0445 protected:
0446   CmsShowMain* fApp;
0447 
0448 public:
0449   DieTimer(CmsShowMain* app) : TTimer(), fApp(app) { Start(0, kTRUE); }
0450 
0451   Bool_t Notify() override {
0452     TurnOff();
0453     fApp->doExit();
0454     delete this;
0455     return kFALSE;
0456   }
0457 };
0458 
0459 void CmsShowMain::quit() { new DieTimer(this); }
0460 
0461 void CmsShowMain::doExit() {
0462   // pre terminate eve
0463   m_context->deleteEveElements();
0464   guiManager()->evePreTerminate();
0465 
0466   // sleep at least 150 ms
0467   // windows in ROOT GUI are destroyed in 150 ms timeout after
0468   gSystem->Sleep(151);
0469   gSystem->ProcessEvents();
0470   gSystem->ExitLoop();
0471 }
0472 
0473 //
0474 // assignment operators
0475 //
0476 // const CmsShowMain& CmsShowMain::operator=(const CmsShowMain& rhs)
0477 // {
0478 //   //An exception safe implementation is
0479 //   CmsShowMain temp(rhs);
0480 //   swap(rhs);
0481 //
0482 //   return *this;
0483 // }
0484 
0485 //
0486 // member functions
0487 //
0488 
0489 const fwlite::Event* CmsShowMain::getCurrentEvent() const {
0490   if (m_navigator.get())
0491     return static_cast<const fwlite::Event*>(m_navigator->getCurrentEvent());
0492   return nullptr;
0493 }
0494 
0495 void CmsShowMain::fileChangedSlot(const TFile* file) {
0496   m_openFile = file;
0497   if (file)
0498     guiManager()->titleChanged(m_navigator->frameTitle());
0499 
0500   if (context()->getField()->getSource() == FWMagField::kNone) {
0501     context()->getField()->resetFieldEstimate();
0502   }
0503   if (geometryFilename().empty()) {
0504     std::string gt = m_navigator->getCurrentGlobalTag();
0505     fireworks::Context::getInstance()->getGeom()->applyGlobalTag(gt);
0506   }
0507   m_metadataManager->update(new FWLiteJobMetadataUpdateRequest(getCurrentEvent(), m_openFile));
0508 }
0509 
0510 void CmsShowMain::eventChangedImp() {
0511   CmsShowMainBase::eventChangedImp();
0512   guiManager()->titleChanged(m_navigator->frameTitle());
0513   m_metadataManager->update(new FWLiteJobMetadataUpdateRequest(getCurrentEvent(), m_openFile));
0514 }
0515 
0516 void CmsShowMain::resetInitialization() {
0517   //printf("Need to reset\n");
0518 }
0519 
0520 void CmsShowMain::openData() {
0521   const char* kRootType[] = {"ROOT files", "*.root", nullptr, nullptr};
0522   TGFileInfo fi;
0523   fi.fFileTypes = kRootType;
0524   /* this is how things used to be done:
0525       fi.fIniDir = ".";
0526       this is bad because the destructor calls delete[] on fIniDir.
0527     */
0528   fi.fIniDir = new char[128];
0529   strncpy(fi.fIniDir, ".", 127);
0530   guiManager()->updateStatus("waiting for data file ...");
0531   new TGFileDialog(gClient->GetDefaultRoot(), guiManager()->getMainFrame(), kFDOpen, &fi);
0532   guiManager()->updateStatus("loading file ...");
0533   if (fi.fFilename) {
0534     m_navigator->openFile(fi.fFilename);
0535 
0536     setLoadedAnyInputFileAfterStartup();
0537     m_navigator->firstEvent();
0538     checkPosition();
0539     draw();
0540   }
0541   guiManager()->clearStatus();
0542 }
0543 
0544 void CmsShowMain::appendData() {
0545   const char* kRootType[] = {"ROOT files", "*.root", nullptr, nullptr};
0546   TGFileInfo fi;
0547   fi.fFileTypes = kRootType;
0548   /* this is how things used to be done:
0549       fi.fIniDir = ".";
0550       this is bad because the destructor calls delete[] on fIniDir.
0551    */
0552   fi.fIniDir = new char[128];
0553   strncpy(fi.fIniDir, ".", 127);
0554   guiManager()->updateStatus("waiting for data file ...");
0555   new TGFileDialog(gClient->GetDefaultRoot(), guiManager()->getMainFrame(), kFDOpen, &fi);
0556   guiManager()->updateStatus("loading file ...");
0557   if (fi.fFilename) {
0558     m_navigator->appendFile(fi.fFilename, false, false);
0559     setLoadedAnyInputFileAfterStartup();
0560     checkPosition();
0561     draw();
0562     guiManager()->titleChanged(m_navigator->frameTitle());
0563   }
0564   guiManager()->clearStatus();
0565 }
0566 
0567 void CmsShowMain::openDataViaURL() {
0568   if (m_searchFiles.get() == nullptr) {
0569     m_searchFiles =
0570         std::make_unique<CmsShowSearchFiles>("", "Open Remote Data Files", guiManager()->getMainFrame(), 500, 400);
0571     m_searchFiles->CenterOnParent(kTRUE, TGTransientFrame::kBottomRight);
0572   }
0573   std::string chosenFile = m_searchFiles->chooseFileFromURL();
0574   if (!chosenFile.empty()) {
0575     guiManager()->updateStatus("loading file ...");
0576     if (m_navigator->openFile(chosenFile)) {
0577       setLoadedAnyInputFileAfterStartup();
0578       m_navigator->firstEvent();
0579       checkPosition();
0580       draw();
0581       guiManager()->clearStatus();
0582     } else {
0583       guiManager()->updateStatus("failed to load data file");
0584     }
0585   }
0586 }
0587 
0588 //
0589 // const member functions
0590 //
0591 
0592 //_______________________________________________________________________________
0593 void CmsShowMain::autoLoadNewEvent() {
0594   stopAutoLoadTimer();
0595 
0596   // case when start with no input file
0597   if (!m_loadedAnyInputFile) {
0598     if (m_monitor.get())
0599       startAutoLoadTimer();
0600     return;
0601   }
0602 
0603   bool reachedEnd = (forward() && m_navigator->isLastEvent()) || (!forward() && m_navigator->isFirstEvent());
0604 
0605   if (loop() && reachedEnd) {
0606     forward() ? m_navigator->firstEvent() : m_navigator->lastEvent();
0607     draw();
0608   } else if (!reachedEnd) {
0609     forward() ? m_navigator->nextEvent() : m_navigator->previousEvent();
0610     draw();
0611   }
0612 
0613   // stop loop in case no loop or monitor mode
0614   if (reachedEnd && (loop() || m_monitor.get()) == kFALSE) {
0615     if (forward() && m_navigator->isLastEvent()) {
0616       guiManager()->enableActions();
0617       checkPosition();
0618     }
0619 
0620     if ((!forward()) && m_navigator->isFirstEvent()) {
0621       guiManager()->enableActions();
0622       checkPosition();
0623     }
0624   } else
0625     startAutoLoadTimer();
0626 }
0627 
0628 //______________________________________________________________________________
0629 
0630 void CmsShowMain::checkPosition() {
0631   if ((m_monitor.get() || loop()) && isPlaying())
0632     return;
0633 
0634   guiManager()->getMainFrame()->enableNavigatorControls();
0635 
0636   if (m_navigator->isFirstEvent())
0637     guiManager()->disablePrevious();
0638 
0639   if (m_navigator->isLastEvent()) {
0640     guiManager()->disableNext();
0641     // force enable play events action in --port mode
0642     if (m_monitor.get() && !guiManager()->playEventsAction()->isEnabled())
0643       guiManager()->playEventsAction()->enable();
0644   }
0645 }
0646 
0647 //==============================================================================
0648 void CmsShowMain::setupDataHandling() {
0649   guiManager()->updateStatus("Setting up data handling...");
0650 
0651   // navigator filtering  ->
0652   m_navigator->fileChanged_.connect(std::bind(&CmsShowMain::fileChangedSlot, this, std::placeholders::_1));
0653   m_navigator->editFiltersExternally_.connect(
0654       std::bind(&FWGUIManager::updateEventFilterEnable, guiManager(), std::placeholders::_1));
0655   m_navigator->filterStateChanged_.connect(
0656       std::bind(&CmsShowMain::navigatorChangedFilterState, this, std::placeholders::_1));
0657   m_navigator->postFiltering_.connect(std::bind(&CmsShowMain::postFiltering, this, std::placeholders::_1));
0658 
0659   // navigator fitlering <-
0660   guiManager()->showEventFilterGUI_.connect(
0661       std::bind(&CmsShowNavigator::showEventFilterGUI, m_navigator.get(), std::placeholders::_1));
0662   guiManager()->filterButtonClicked_.connect(std::bind(&CmsShowMain::filterButtonClicked, this));
0663 
0664   // Data handling. File related and therefore not in the base class.
0665   if (guiManager()->getAction(cmsshow::sOpenData) != nullptr)
0666     guiManager()->getAction(cmsshow::sOpenData)->activated.connect(sigc::mem_fun(*this, &CmsShowMain::openData));
0667   if (guiManager()->getAction(cmsshow::sAppendData) != nullptr)
0668     guiManager()->getAction(cmsshow::sAppendData)->activated.connect(sigc::mem_fun(*this, &CmsShowMain::appendData));
0669   if (guiManager()->getAction(cmsshow::sSearchFiles) != nullptr)
0670     guiManager()
0671         ->getAction(cmsshow::sSearchFiles)
0672         ->activated.connect(sigc::mem_fun(*this, &CmsShowMain::openDataViaURL));
0673 
0674   setupActions();
0675   // init data from  CmsShowNavigator configuration, can do this with signals since there were not connected yet
0676   guiManager()->setFilterButtonIcon(m_navigator->getFilterState());
0677 
0678   for (unsigned int ii = 0; ii < m_inputFiles.size(); ++ii) {
0679     const std::string& fname = m_inputFiles[ii];
0680     if (fname.empty())
0681       continue;
0682     guiManager()->updateStatus("loading data file ...");
0683     if (!m_navigator->appendFile(fname, false, false)) {
0684       guiManager()->updateStatus("failed to load data file");
0685     } else {
0686       m_loadedAnyInputFile = true;
0687     }
0688   }
0689 
0690   if (m_loadedAnyInputFile) {
0691     m_navigator->firstEvent();
0692     checkPosition();
0693     if (configurationManager()->getIgnore())
0694       guiManager()->initEmpty();
0695     else
0696       setupConfiguration();
0697   } else {
0698     if (configFilename()[0] == '\0') {
0699       guiManager()->initEmpty();
0700     } else {
0701       setupConfiguration();
0702     }
0703 
0704     bool geoBrowser = (configFilename()[0] != '\0') && (eiManager()->begin() == eiManager()->end());
0705 
0706     if (m_monitor.get() == nullptr && (configurationManager()->getIgnore() == false) && (!geoBrowser)) {
0707       if (m_inputFiles.empty())
0708         openDataViaURL();
0709       else
0710         openData();
0711     }
0712   }
0713 }
0714 
0715 void CmsShowMain::setLoadedAnyInputFileAfterStartup() {
0716   if (m_loadedAnyInputFile == false) {
0717     m_loadedAnyInputFile = true;
0718     if ((configFilename()[0] == '\0') && (configurationManager()->getIgnore() == false))
0719       setupConfiguration();
0720   }
0721 }
0722 
0723 void CmsShowMain::setupSocket(unsigned int iSocket) {
0724   m_monitor = std::make_unique<TMonitor>();
0725   TServerSocket* server = new TServerSocket(iSocket, kTRUE);
0726   if (server->GetErrorCode()) {
0727     fwLog(fwlog::kError) << "CmsShowMain::setupSocket, can't create socket on port " << iSocket << "." << std::endl;
0728     exit(0);
0729   }
0730   m_monitor->Add(server);
0731 }
0732 
0733 void CmsShowMain::connectSocket() { m_monitor->Connect("Ready(TSocket*)", "CmsShowMain", this, "notified(TSocket*)"); }
0734 
0735 void CmsShowMain::notified(TSocket* iSocket) {
0736   TServerSocket* server = dynamic_cast<TServerSocket*>(iSocket);
0737   if (server) {
0738     TSocket* connection = server->Accept();
0739     if (connection) {
0740       m_monitor->Add(connection);
0741       std::stringstream s;
0742       s << "received connection from " << iSocket->GetInetAddress().GetHostName();
0743       guiManager()->updateStatus(s.str().c_str());
0744     }
0745   } else {
0746     char buffer[4096];
0747     memset(buffer, 0, sizeof(buffer));
0748     if (iSocket->RecvRaw(buffer, sizeof(buffer)) <= 0) {
0749       m_monitor->Remove(iSocket);
0750       //std::stringstream s;
0751       //s << "closing connection to "<<iSocket->GetInetAddress().GetHostName();
0752       //m_guiManager->updateStatus(s.str().c_str());
0753       delete iSocket;
0754       return;
0755     }
0756     std::string fileName(buffer);
0757     std::string::size_type lastNonSpace = fileName.find_last_not_of(" \n\t");
0758     if (lastNonSpace != std::string::npos) {
0759       fileName.erase(lastNonSpace + 1);
0760     }
0761 
0762     std::stringstream s;
0763     s << "New file notified '" << fileName << "'";
0764     guiManager()->updateStatus(s.str().c_str());
0765 
0766     bool appended = m_navigator->appendFile(fileName, true, m_live);
0767 
0768     if (appended) {
0769       if (m_live && isPlaying() && forward())
0770         m_navigator->activateNewFileOnNextEvent();
0771       else if (!isPlaying())
0772         checkPosition();
0773 
0774       // bootstrap case: --port  and no input file
0775       if (!m_loadedAnyInputFile) {
0776         m_loadedAnyInputFile = true;
0777         m_navigator->firstEvent();
0778         if (!isPlaying())
0779           draw();
0780       }
0781 
0782       std::stringstream sr;
0783       sr << "New file registered '" << fileName << "'";
0784       guiManager()->updateStatus(sr.str().c_str());
0785     } else {
0786       std::stringstream sr;
0787       sr << "New file NOT registered '" << fileName << "'";
0788       guiManager()->updateStatus(sr.str().c_str());
0789     }
0790   }
0791 }
0792 
0793 void CmsShowMain::checkKeyBindingsOnPLayEventsStateChanged() {
0794   if (m_live) {
0795     Int_t keycode = gVirtualX->KeysymToKeycode((int)kKey_Space);
0796     Window_t id = FWGUIManager::getGUIManager()->getMainFrame()->GetId();
0797     gVirtualX->GrabKey(id, keycode, 0, isPlaying());
0798   }
0799 }
0800 
0801 void CmsShowMain::stopPlaying() {
0802   stopAutoLoadTimer();
0803   if (m_live)
0804     m_navigator->resetNewFileOnNextEvent();
0805   CmsShowMainBase::stopPlaying();
0806   guiManager()->enableActions();
0807   checkPosition();
0808 }
0809 
0810 void CmsShowMain::navigatorChangedFilterState(int state) {
0811   guiManager()->setFilterButtonIcon(state);
0812   if (m_navigator->filesNeedUpdate() == false) {
0813     guiManager()->setFilterButtonText(m_navigator->filterStatusMessage());
0814     checkPosition();
0815   }
0816 }
0817 
0818 void CmsShowMain::filterButtonClicked() {
0819   if (m_navigator->getFilterState() == CmsShowNavigator::kWithdrawn)
0820     guiManager()->showEventFilterGUI();
0821   else
0822     m_navigator->toggleFilterEnable();
0823 }
0824 
0825 void CmsShowMain::preFiltering() {
0826   // called only if filter has changed
0827   guiManager()->updateStatus("Filtering events");
0828 }
0829 
0830 void CmsShowMain::postFiltering(bool doDraw) {
0831   // called only filter is changed
0832   guiManager()->clearStatus();
0833   if (doDraw)
0834     draw();
0835   checkPosition();
0836   guiManager()->setFilterButtonText(m_navigator->filterStatusMessage());
0837 }
0838 
0839 //______________________________________________________________________________
0840 
0841 void CmsShowMain::setLiveMode() {
0842   m_live = true;
0843   m_liveTimer = std::make_unique<SignalTimer>();
0844   m_liveTimer->timeout_.connect(std::bind(&CmsShowMain::checkLiveMode, this));
0845 
0846   Window_t rootw, childw;
0847   Int_t root_x, root_y, win_x, win_y;
0848   UInt_t mask;
0849   gVirtualX->QueryPointer(gClient->GetDefaultRoot()->GetId(), rootw, childw, root_x, root_y, win_x, win_y, mask);
0850 
0851   m_liveTimer->SetTime(m_liveTimeout);
0852   m_liveTimer->Reset();
0853   m_liveTimer->TurnOn();
0854 }
0855 
0856 void CmsShowMain::checkLiveMode() {
0857   m_liveTimer->TurnOff();
0858 
0859 #if defined(R__LINUX)
0860   TGX11* x11 = dynamic_cast<TGX11*>(gVirtualX);
0861   if (x11) {
0862     XAnyEvent* ev = (XAnyEvent*)x11->GetNativeEvent();
0863     // printf("serial %d \n",(int)ev->serial );
0864 
0865     if (!isPlaying() && m_lastXEventSerial == ev->serial)
0866       guiManager()->playEventsAction()->switchMode();
0867     m_lastXEventSerial = ev->serial;
0868   }
0869 #endif
0870   m_liveTimer->SetTime((Long_t)(m_liveTimeout));
0871   m_liveTimer->Reset();
0872   m_liveTimer->TurnOn();
0873 }