MythTV  master
mythcontext.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 #include <array>
3 #include <cmath>
4 #include <iostream>
5 #include <queue>
6 #include <thread>
7 #include <unistd.h> // for usleep(), gethostname
8 #include <vector>
9 
10 #include <QCoreApplication>
11 #include <QDateTime>
12 #include <QDebug>
13 #include <QDir>
14 #include <QEventLoop>
15 #include <QFileInfo>
16 #include <QHostInfo>
17 #include <QMutex>
18 #include <QTcpSocket>
19 #ifdef Q_OS_ANDROID
20 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
21 #include <QtAndroidExtras>
22 #else
23 #include <QJniEnvironment>
24 #include <QJniObject>
25 #define QAndroidJniEnvironment QJniEnvironment
26 #define QAndroidJniObject QJniObject
27 #endif
28 #endif
29 
30 #ifdef _WIN32
31 #include "libmythbase/compat.h"
32 #endif
34 #include "libmythbase/dbutil.h"
35 #include "libmythbase/exitcodes.h"
36 #include "libmythbase/mythdate.h"
37 #include "libmythbase/mythdb.h"
38 #include "libmythbase/mythdirs.h"
39 #include "libmythbase/mythevent.h"
42 #include "libmythbase/mythplugin.h"
45 #include "libmythbase/mythversion.h"
47 #include "libmythbase/remotefile.h"
49 #include "libmythui/mythimage.h"
51 #include "libmythui/mythuihelper.h"
53 #include "libmythupnp/upnp.h"
54 
55 #include "backendselect.h"
56 #include "dbsettings.h"
57 #include "guistartup.h"
58 #include "langsettings.h"
59 #include "mythcontext.h"
60 #include "mythmediamonitor.h"
61 
62 #define LOC QString("MythContext: ")
63 
64 MythContext *gContext = nullptr;
65 
66 static const QString sLocation = "MythContext";
67 
68 namespace
69 {
71 {
72  public:
73  GUISettingsCache() = default;
74  GUISettingsCache(const QString& cache_filename, QString cache_path)
75  : m_cachePath(std::move(cache_path))
76  {
77  m_cacheFilename = m_cachePath + '/' + cache_filename;
78  if (m_cachePath.isEmpty() || cache_filename.isEmpty())
79  {
80  m_cacheFilename = m_cachePath = QString();
81  }
82  }
83 
84  bool save();
85  void loadOverrides() const;
86  static void clearOverrides();
87 
88  private:
89  QString m_cacheFilename {"cache/contextcache.xml"};
90  QString m_cachePath {"cache"};
91 
92  static const std::array<QString, 13> kSettings;
93 };
94 
95 } // anonymous namespace
96 
97 class MythContextPrivate : public QObject
98 {
99  friend class MythContextSlotHandler;
100 
101  public:
102  explicit MythContextPrivate(MythContext *lparent);
103  ~MythContextPrivate() override;
104 
105  bool Init (bool gui,
106  bool promptForBackend,
107  bool disableAutoDiscovery,
108  bool ignoreDB);
109  bool FindDatabase(bool prompt, bool noAutodetect);
110 
111  void TempMainWindow(bool languagePrompt = true);
112  void EndTempWindow(void);
113 
114  bool LoadDatabaseSettings(void);
115  bool SaveDatabaseParams(const DatabaseParams &params, bool force);
116 
117  bool PromptForDatabaseParams(const QString &error);
118  QString TestDBconnection(bool prompt=true);
119  void SilenceDBerrors(void);
120  void EnableDBerrors(void);
121  void ResetDatabase(void) const;
122 
124  ChooseBackend(const QString &error);
125  int UPnPautoconf(std::chrono::milliseconds milliSeconds = 2s);
126  bool DefaultUPnP(QString& Error);
127  bool UPnPconnect(const DeviceLocation *backend, const QString &PIN);
128  void ShowGuiStartup(void);
129  bool checkPort(QString &host, int port, std::chrono::seconds timeLimit) const;
130  static void processEvents(void);
131 
132  protected:
133  bool event(QEvent* /*e*/) override; // QObject
134 
135  void ShowConnectionFailurePopup(bool persistent);
136  void HideConnectionFailurePopup(void);
137 
138  void ShowVersionMismatchPopup(uint remote_version);
139 
140  public slots:
141  void OnCloseDialog();
142 
143  public:
144  MythContext *m_parent {nullptr};
145 
147  bool m_gui {false};
148 
150 
152  QString m_dbHostCp;
153 
154  bool m_disableeventpopup {false};
155 
156  MythUIHelper *m_ui {nullptr};
159  QEventLoop *m_loop {nullptr};
160  bool m_needsBackend {false};
161 
162  GUISettingsCache m_GUISettingsCache;
163 
164  private:
166  int m_registration {-1};
167  QDateTime m_lastCheck;
168  QTcpSocket *m_socket {nullptr};
169 };
170 
171 static void exec_program_cb(const QString &cmd)
172 {
173  myth_system(cmd);
174 }
175 
176 static void exec_program_tv_cb(const QString &cmd)
177 {
178  QString s = cmd;
179  QStringList tokens = cmd.simplified().split(" ");
180  QStringList strlist;
181 
182  bool cardidok = false;
183  int wantcardid = tokens[0].toInt(&cardidok, 10);
184 
185  if (cardidok && wantcardid > 0)
186  {
187  strlist << QString("LOCK_TUNER %1").arg(wantcardid);
188  s = s.replace(0, tokens[0].length() + 1, "");
189  }
190  else
191  {
192  strlist << "LOCK_TUNER";
193  }
194 
196  int cardid = strlist[0].toInt();
197 
198  if (cardid >= 0)
199  {
200  s = s.arg(qPrintable(strlist[1]),
201  qPrintable(strlist[2]),
202  qPrintable(strlist[3]));
203 
204  myth_system(s);
205 
206  strlist = QStringList(QString("FREE_TUNER %1").arg(cardid));
208  }
209  else
210  {
211  QString label;
212 
213  if (cardidok)
214  {
215  if (cardid == -1)
216  {
217  label = QObject::tr("Could not find specified tuner (%1).")
218  .arg(wantcardid);
219  }
220  else
221  {
222  label = QObject::tr("Specified tuner (%1) is already in use.")
223  .arg(wantcardid);
224  }
225  }
226  else
227  {
228  label = QObject::tr("All tuners are currently in use. If you want "
229  "to watch TV, you can cancel one of the "
230  "in-progress recordings from the delete menu");
231  }
232 
233  LOG(VB_GENERAL, LOG_ALERT, QString("exec_program_tv: ") + label);
234 
235  ShowOkPopup(label);
236  }
237 }
238 
239 static void configplugin_cb(const QString &cmd)
240 {
242  if (!pmanager)
243  return;
244 
245  if (GetNotificationCenter() && pmanager->config_plugin(cmd.trimmed()))
246  {
248  QObject::tr("Failed to configure plugin"));
249  }
250 }
251 
252 static void plugin_cb(const QString &cmd)
253 {
255  if (!pmanager)
256  return;
257 
258  if (GetNotificationCenter() && pmanager->run_plugin(cmd.trimmed()))
259  {
260  ShowNotificationError(QObject::tr("Plugin failure"),
261  sLocation,
262  QObject::tr("%1 failed to run for some reason").arg(cmd));
263  }
264 }
265 
266 static void eject_cb(void)
267 {
269 }
270 
272  : m_parent(lparent),
273  m_sh(new MythContextSlotHandler(this)),
274  m_loop(new QEventLoop(this))
275 {
277 }
278 
280 {
282  {
284  }
285 
286  delete m_loop;
287 
288  if (m_ui)
289  DestroyMythUI();
290  if (m_sh)
291  m_sh->deleteLater();
292 }
293 
304 void MythContextPrivate::TempMainWindow(bool languagePrompt)
305 {
306  if (HasMythMainWindow())
307  return;
308 
309  SilenceDBerrors();
310 
311 #ifdef Q_OS_DARWIN
312  // Qt 4.4 has window-focus problems
313  gCoreContext->OverrideSettingForSession("RunFrontendInWindow", "1");
314 #endif
315  GetMythUI()->Init();
316  MythMainWindow *mainWindow = MythMainWindow::getMainWindow(false);
317  mainWindow->Init();
318 
319  if (languagePrompt)
320  {
321  // ask user for language settings
323  MythTranslation::load("mythfrontend");
324  }
325 }
326 
328 {
329  if (HasMythMainWindow())
330  {
332  {
334  if (mainStack)
335  {
336  mainStack->PopScreen(m_guiStartup, false);
337  m_guiStartup = nullptr;
338  }
339  }
340  }
341  EnableDBerrors();
342 }
343 
353 bool MythContextPrivate::checkPort(QString &host, int port, std::chrono::seconds timeLimit) const
354 {
355  PortChecker checker;
356  if (m_guiStartup)
358  return checker.checkPort(host, port, timeLimit);
359 }
360 
361 
362 bool MythContextPrivate::Init(const bool gui,
363  const bool promptForBackend,
364  const bool disableAutoDiscovery,
365  const bool ignoreDB)
366 {
367  gCoreContext->GetDB()->IgnoreDatabase(ignoreDB);
368  m_gui = gui;
369  if (gui)
370  {
371  m_GUISettingsCache.loadOverrides();
372  }
373 
374  if (gCoreContext->IsFrontend())
375  m_needsBackend = true;
376 
377  // Creates screen saver control if we will have a GUI
378  if (gui)
379  m_ui = GetMythUI();
380 
381  // ---- database connection stuff ----
382 
383  if (!ignoreDB && !FindDatabase(promptForBackend, disableAutoDiscovery))
384  {
385  EndTempWindow();
386  return false;
387  }
388 
389  // ---- keep all DB-using stuff below this line ----
390 
391  // Prompt for language if this is a first time install and
392  // we didn't already do so.
393  if (m_gui && !gCoreContext->GetDB()->HaveSchema())
394  {
395  TempMainWindow(false);
397  MythTranslation::load("mythfrontend");
398  }
401 
402  // Close GUI Startup Window.
403  if (m_guiStartup)
404  {
406  if (mainStack)
407  mainStack->PopScreen(m_guiStartup, false);
408  m_guiStartup=nullptr;
409  }
410  EndTempWindow();
411 
412  if (gui)
413  {
414  MythUIMenuCallbacks cbs {};
416  cbs.exec_program_tv = exec_program_tv_cb;
417  cbs.configplugin = configplugin_cb;
418  cbs.plugin = plugin_cb;
419  cbs.eject = eject_cb;
420 
421  m_ui->Init(cbs);
422  }
423 
424  return true;
425 }
426 
439 bool MythContextPrivate::FindDatabase(bool prompt, bool noAutodetect)
440 {
441  // We can only prompt if autodiscovery is enabled..
442  bool manualSelect = prompt && !noAutodetect;
443 
444  QString failure;
445 
446  // 1. Either load XmlConfiguration::k_default_filename or use sensible "localhost" defaults:
447  bool loaded = LoadDatabaseSettings();
448  DatabaseParams dbParamsFromFile = m_dbParams;
449 
450  // In addition to the UI chooser, we can also try to autoSelect later,
451  // but only if we're not doing manualSelect and there was no
452  // valid XmlConfiguration::k_default_filename
453  bool autoSelect = !manualSelect && !loaded && !noAutodetect;
454 
455  // 2. If the user isn't forcing up the chooser UI, look for a default
456  // backend in XmlConfiguration::k_default_filename, then test DB settings we've got so far:
457  if (!manualSelect)
458  {
459  // XmlConfiguration::k_default_filename may contain a backend host UUID and PIN.
460  // If so, try to AutoDiscover UPnP server, and use its DB settings:
461 
462  if (DefaultUPnP(failure)) // Probably a valid backend,
463  autoSelect = manualSelect = false; // so disable any further UPnP
464  else
465  if (!failure.isEmpty())
466  LOG(VB_GENERAL, LOG_ALERT, failure);
467 
468  failure = TestDBconnection(loaded);
469  if (failure.isEmpty())
470  goto DBfound;
472  return false;
474  autoSelect=true;
475  }
476 
477  // 3. Try to automatically find the single backend:
478  if (autoSelect)
479  {
480  int count = UPnPautoconf();
481 
482  if (count == 0)
483  failure = QObject::tr("No UPnP backends found", "Backend Setup");
484 
485  if (count == 1)
486  {
487  failure = TestDBconnection();
488  if (failure.isEmpty())
489  goto DBfound;
491  return false;
492  }
493 
494  // Multiple BEs, or needs PIN.
495  manualSelect |= (count > 1 || count == -1);
496  // Search requested
498  manualSelect=true;
499  }
500 
501  manualSelect &= m_gui; // no interactive command-line chooser yet
502 
503  // Queries the user for the DB info
504  do
505  {
506  if (manualSelect)
507  {
508  // Get the user to select a backend from a possible list:
509  switch (ChooseBackend(failure))
510  {
512  break;
514  manualSelect = false;
515  break;
517  goto NoDBfound;
518  }
519  }
520 
521  if (!manualSelect)
522  {
523  // If this is a backend, No longer prompt for database.
524  // Instaed allow the web server to start so that the
525  // database can be set up there
526  if (gCoreContext->IsBackend()
527  || !PromptForDatabaseParams(failure))
528  goto NoDBfound;
529  }
530  failure = TestDBconnection();
531  if (!failure.isEmpty())
532  LOG(VB_GENERAL, LOG_ALERT, failure);
534  return false;
536  manualSelect=true;
538  manualSelect=false;
539  }
540  while (!failure.isEmpty());
541 
542 DBfound:
543  LOG(VB_GENERAL, LOG_DEBUG, "FindDatabase() - Success!");
544  // If we got the database from UPNP then the wakeup settings are lost.
545  // Restore them.
546  m_dbParams.m_wolEnabled = dbParamsFromFile.m_wolEnabled;
547  m_dbParams.m_wolReconnect = dbParamsFromFile.m_wolReconnect;
548  m_dbParams.m_wolRetry = dbParamsFromFile.m_wolRetry;
549  m_dbParams.m_wolCommand = dbParamsFromFile.m_wolCommand;
550 
552  !loaded || m_dbParams.m_forceSave ||
553  dbParamsFromFile != m_dbParams);
554  EnableDBerrors();
555  ResetDatabase();
556  return true;
557 
558 NoDBfound:
559  LOG(VB_GENERAL, LOG_DEBUG, "FindDatabase() - failed");
560  return false;
561 }
562 
567 {
568  auto config = XmlConfiguration(); // read-only
569 
571 
572  m_dbParams.m_localHostName = config.GetValue("LocalHostName", "");
573  m_dbParams.m_dbHostPing = config.GetValue(kDefaultDB + "PingHost", true);
574  m_dbParams.m_dbHostName = config.GetValue(kDefaultDB + "Host", "");
575  m_dbParams.m_dbUserName = config.GetValue(kDefaultDB + "UserName", "");
576  m_dbParams.m_dbPassword = config.GetValue(kDefaultDB + "Password", "");
577  m_dbParams.m_dbName = config.GetValue(kDefaultDB + "DatabaseName", "");
578  m_dbParams.m_dbPort = config.GetValue(kDefaultDB + "Port", 0);
579 
580  m_dbParams.m_wolEnabled = config.GetValue(kDefaultWOL + "Enabled", false);
582  config.GetDuration<std::chrono::seconds>(kDefaultWOL + "SQLReconnectWaitTime", 0s);
583  m_dbParams.m_wolRetry = config.GetValue(kDefaultWOL + "SQLConnectRetry", 5);
584  m_dbParams.m_wolCommand = config.GetValue(kDefaultWOL + "Command", "");
585 
587 
588  if (!ok)
590 
591  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
592 
594  if (hostname.isEmpty() ||
595  hostname == "my-unique-identifier-goes-here")
596  {
597  LOG(VB_GENERAL, LOG_INFO, "Empty LocalHostName. This is typical.");
598  hostname = QHostInfo::localHostName();
599 
600 #ifndef Q_OS_ANDROID
601  if (hostname.isEmpty())
602  {
603  LOG(VB_GENERAL, LOG_ALERT,
604  "MCP: Error, could not determine host name." + ENO);
605  }
606 #else //elif defined Q_OS_ANDROID
607 #define ANDROID_EXCEPTION_CHECK \
608  if (env->ExceptionCheck()) \
609  { \
610  env->ExceptionClear(); \
611  exception=true; \
612  }
613 
614  if ((hostname == "localhost") || hostname.isEmpty())
615  {
616  hostname = "android";
617  bool exception=false;
620 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
621  QAndroidJniObject activity = QtAndroid::androidActivity();
622 #else
623  QJniObject activity = QNativeInterface::QAndroidApplication::context();
624 #endif
626  QAndroidJniObject appctx = activity.callObjectMethod
627  ("getApplicationContext", "()Landroid/content/Context;");
629  QAndroidJniObject contentR = appctx.callObjectMethod
630  ("getContentResolver", "()Landroid/content/ContentResolver;");
632  QAndroidJniObject androidId = QAndroidJniObject::callStaticObjectMethod
633  ("android/provider/Settings$Secure", "getString",
634  "(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;",
635  contentR.object<jobject>(),
636  myID.object<jstring>());
638  if (exception)
639  LOG(VB_GENERAL, LOG_ALERT,
640  "Java exception looking for android id");
641  else
642  hostname = QString("android-%1").arg(androidId.toString());
643  }
644 #endif
645 
646  }
647  else
648  {
649  m_dbParams.m_localEnabled = true;
650  }
651 
652  LOG(VB_GENERAL, LOG_INFO, QString("Using a profile name of: '%1' (Usually the "
653  "same as this host's name.)")
654  .arg(hostname));
656 
657  return ok;
658 }
659 
661  const DatabaseParams &params, bool force)
662 {
663  bool success = true;
664 
665  // only rewrite file if it has changed
666  if (force || (params != m_dbParams))
667  {
668  /* Read in the current file on the filesystem, only setting/clearing as
669  necessary. This prevents losing changes to the file from between when it
670  was read at startup of MythTV and when this function is called.
671  */
672  auto config = XmlConfiguration();
673 
674  config.SetValue("LocalHostName", params.m_localHostName);
675 
676  config.SetValue(kDefaultDB + "PingHost", params.m_dbHostPing);
677 
678  // If dbHostName is an IPV6 address with scope,
679  // remove the scope. Unescaped % signs are an
680  // xml violation
681  QString dbHostName(params.m_dbHostName);
682  QHostAddress addr;
683  if (addr.setAddress(dbHostName))
684  {
685  addr.setScopeId(QString());
686  dbHostName = addr.toString();
687  }
688  config.SetValue(kDefaultDB + "Host", dbHostName);
689  config.SetValue(kDefaultDB + "UserName", params.m_dbUserName);
690  config.SetValue(kDefaultDB + "Password", params.m_dbPassword);
691  config.SetValue(kDefaultDB + "DatabaseName", params.m_dbName);
692  config.SetValue(kDefaultDB + "Port", params.m_dbPort);
693 
694  config.SetValue(kDefaultWOL + "Enabled", params.m_wolEnabled);
695  config.SetDuration(
696  kDefaultWOL + "SQLReconnectWaitTime", params.m_wolReconnect);
697  config.SetValue(kDefaultWOL + "SQLConnectRetry", params.m_wolRetry);
698  config.SetValue(kDefaultWOL + "Command", params.m_wolCommand);
699 
700  // actually save the file
701  success = config.Save();
702 
703  // Use the new settings:
704  m_dbParams = params;
705  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
706 
707  // If database has changed, force its use:
708  ResetDatabase();
709  }
710  return success;
711 }
712 
714 {
715  if (d && d->m_loop
716  && d->m_loop->isRunning())
717  d->m_loop->exit();
718 }
719 
720 
721 // No longer prompt for database, instaed allow the
722 // web server to start so that the datbase can be
723 // set up there
724 
726 {
727  bool accepted = false;
728  if (m_gui)
729  {
730  TempMainWindow();
731 
732  // Tell the user what went wrong:
733  if (!error.isEmpty())
735 
736  // ask user for database parameters
737 
738  EnableDBerrors();
740  auto *dbsetting = new DatabaseSettings();
741  auto *ssd = new StandardSettingDialog(mainStack, "databasesettings",
742  dbsetting);
743  if (ssd->Create())
744  {
745  mainStack->AddScreen(ssd);
746  connect(dbsetting, &DatabaseSettings::isClosing,
748  if (!m_loop->isRunning())
749  m_loop->exec();
750  }
751  else
752  {
753  delete ssd;
754  }
755  SilenceDBerrors();
756  EndTempWindow();
757  accepted = true;
758  }
759  else
760  {
761  DatabaseParams params = m_dbParams;
762  QString response;
763  std::this_thread::sleep_for(1s);
764  // give user chance to skip config
765  std::cout << std::endl << error.toLocal8Bit().constData() << std::endl << std::endl;
766  response = getResponse("Would you like to configure the database "
767  "connection now?",
768  "no");
769  if (!response.startsWith('y', Qt::CaseInsensitive))
770  return false;
771 
772  params.m_dbHostName = getResponse("Database host name:",
773  params.m_dbHostName);
774  response = getResponse("Should I test connectivity to this host "
775  "using the ping command?", "yes");
776  params.m_dbHostPing = response.startsWith('y', Qt::CaseInsensitive);
777 
778  params.m_dbPort = intResponse("Database non-default port:",
779  params.m_dbPort);
780  params.m_dbName = getResponse("Database name:",
781  params.m_dbName);
782  params.m_dbUserName = getResponse("Database user name:",
783  params.m_dbUserName);
784  params.m_dbPassword = getResponse("Database password:",
785  params.m_dbPassword);
786 
787  params.m_localHostName = getResponse("Unique identifier for this machine "
788  "(if empty, the local host name "
789  "will be used):",
790  params.m_localHostName);
791  params.m_localEnabled = !params.m_localHostName.isEmpty();
792 
793  response = getResponse("Would you like to use Wake-On-LAN to retry "
794  "database connections?",
795  (params.m_wolEnabled ? "yes" : "no"));
796  params.m_wolEnabled = response.startsWith('y', Qt::CaseInsensitive);
797 
798  if (params.m_wolEnabled)
799  {
800  params.m_wolReconnect =
801  std::chrono::seconds(intResponse("Seconds to wait for "
802  "reconnection:",
803  params.m_wolReconnect.count()));
804  params.m_wolRetry = intResponse("Number of times to retry:",
805  params.m_wolRetry);
806  params.m_wolCommand = getResponse("Command to use to wake server or server MAC address:",
807  params.m_wolCommand);
808  }
809 
810  accepted = m_parent->SaveDatabaseParams(params);
811  }
812  return accepted;
813 }
814 
821 {
822  QString err;
823  QString host;
824 
825  // Jan 20, 2017
826  // Changed to use port check instead of ping
827 
828  int port = 0;
829 
830  // 1 = db awake, 2 = db listening, 3 = db connects,
831  // 4 = backend awake, 5 = backend listening
832  // 9 = all ok, 10 = quit
833 
834  enum startupStates : std::uint8_t {
835  st_start = 0,
836  st_dbAwake = 1,
837  st_dbStarted = 2,
838  st_dbConnects = 3,
839  st_beWOL = 4,
840  st_beAwake = 5,
841  st_success = 6
842  } startupState = st_start;
843 
844  static const std::array<const QString, 7> kGuiStatuses
845  {"start", "dbAwake", "dbStarted", "dbConnects", "beWOL", "beAwake", "success"};
846 
847  auto secondsStartupScreenDelay = gCoreContext->GetDurSetting<std::chrono::seconds>("StartupScreenDelay", 2s);
848  auto msStartupScreenDelay = std::chrono::duration_cast<std::chrono::milliseconds>(secondsStartupScreenDelay);
849  do
850  {
851  QElapsedTimer timer;
852  timer.start();
853  if (m_dbParams.m_dbHostName.isNull() && !m_dbHostCp.isEmpty())
854  host = m_dbHostCp;
855  else
856  host = m_dbParams.m_dbHostName;
857  port = m_dbParams.m_dbPort;
858  if (port == 0)
859  port = 3306;
860  std::chrono::seconds wakeupTime = 3s;
861  int attempts = 11;
863  {
864  wakeupTime = m_dbParams.m_wolReconnect;
865  attempts = m_dbParams.m_wolRetry + 1;
866  startupState = st_start;
867  }
868  else
869  {
870  startupState = st_dbAwake;
871  }
872  attempts = std::max(attempts, 6);
873  if (!prompt)
874  attempts=1;
875  if (wakeupTime < 5s)
876  wakeupTime = 5s;
877 
878  std::chrono::seconds progressTotal = wakeupTime * attempts;
879 
881  m_guiStartup->setTotal(progressTotal);
882 
883  QString beWOLCmd = QString();
884  QString backendIP = QString();
885  int backendPort = 0;
886  QString masterserver;
887 
888  for (int attempt = 0;
889  attempt < attempts && startupState != st_success;
890  ++attempt)
891  {
892  // The first time do everything with minimum timeout and
893  // no GUI, for the normal case where all is OK
894  // After that show the GUI (if this is a GUI program)
895 
896  LOG(VB_GENERAL, LOG_INFO,
897  QString("Start up testing connections. DB %1, BE %2, attempt %3, status %4, Delay: %5")
898  .arg(host, backendIP, QString::number(attempt),
899  kGuiStatuses[startupState],
900  QString::number(msStartupScreenDelay.count())) );
901 
902  std::chrono::seconds useTimeout = wakeupTime;
903  if (attempt == 0)
904  useTimeout=1s;
905 
906  if (m_gui && !m_guiStartup)
907  {
908  if (msStartupScreenDelay==0ms || timer.hasExpired(msStartupScreenDelay.count()))
909  {
910  ShowGuiStartup();
911  if (m_guiStartup)
912  m_guiStartup->setTotal(progressTotal);
913  }
914  }
916  {
917  if (attempt > 0)
918  m_guiStartup->setStatusState(kGuiStatuses[startupState]);
919  m_guiStartup->setMessageState("empty");
920  processEvents();
921  }
922  switch (startupState)
923  {
924  case st_start:
926  {
927  if (attempt > 0)
929  if (!checkPort(host, port, useTimeout))
930  break;
931  }
932  startupState = st_dbAwake;
933  [[fallthrough]];
934  case st_dbAwake:
935  if (!checkPort(host, port, useTimeout))
936  break;
937  startupState = st_dbStarted;
938  [[fallthrough]];
939  case st_dbStarted:
940  // If the database is connecting with link-local
941  // address, it may have changed
942  if (m_dbParams.m_dbHostName != host)
943  {
944  m_dbParams.m_dbHostName = host;
945  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
946  }
947  EnableDBerrors();
948  ResetDatabase();
950  {
951  for (std::chrono::seconds temp = 0s; temp < useTimeout * 2 ; temp++)
952  {
953  processEvents();
954  std::this_thread::sleep_for(500ms);
955  }
956  break;
957  }
958  startupState = st_dbConnects;
959  [[fallthrough]];
960  case st_dbConnects:
961  if (m_needsBackend)
962  {
963  beWOLCmd = gCoreContext->GetSetting("WOLbackendCommand", "");
964  if (!beWOLCmd.isEmpty())
965  {
966  wakeupTime += gCoreContext->GetDurSetting<std::chrono::seconds>
967  ("WOLbackendReconnectWaitTime", 0s);
968  attempts += gCoreContext->GetNumSetting
969  ("WOLbackendConnectRetry", 0);
970  useTimeout = wakeupTime;
971  if (m_gui && !m_guiStartup && attempt == 0)
972  useTimeout=1s;
973  progressTotal = wakeupTime * attempts;
975  m_guiStartup->setTotal(progressTotal);
976  startupState = st_beWOL;
977  }
978  }
979  else
980  {
981  startupState = st_success;
982  break;
983  }
984  masterserver = gCoreContext->GetSetting
985  ("MasterServerName");
986  backendIP = gCoreContext->GetSettingOnHost
987  ("BackendServerAddr", masterserver);
988  backendPort = MythCoreContext::GetMasterServerPort();
989  [[fallthrough]];
990  case st_beWOL:
991  if (!beWOLCmd.isEmpty())
992  {
993  if (attempt > 0)
994  MythWakeup(beWOLCmd);
995  if (!checkPort(backendIP, backendPort, useTimeout))
996  break;
997  }
998  startupState = st_beAwake;
999  [[fallthrough]];
1000  case st_beAwake:
1001  if (!checkPort(backendIP, backendPort, useTimeout))
1002  break;
1003  startupState = st_success;
1004  [[fallthrough]];
1005  case st_success:
1006  // Quiet compiler warning.
1007  break;
1008  }
1009  if (m_guiStartup)
1010  {
1011  if (m_guiStartup->m_Exit
1012  || m_guiStartup->m_Setup
1014  || m_guiStartup->m_Retry)
1015  break;
1016  }
1017  processEvents();
1018  }
1019  if (startupState == st_success)
1020  break;
1021 
1022  QString stateMsg = kGuiStatuses[startupState];
1023  stateMsg.append("Fail");
1024  LOG(VB_GENERAL, LOG_INFO,
1025  QString("Start up failure. host %1, status %2")
1026  .arg(host, stateMsg));
1027 
1028  if (m_gui && !m_guiStartup)
1029  {
1030  ShowGuiStartup();
1031  if (m_guiStartup)
1032  m_guiStartup->setTotal(progressTotal);
1033  }
1034 
1035  if (m_guiStartup
1036  && !m_guiStartup->m_Exit
1037  && !m_guiStartup->m_Setup
1038  && !m_guiStartup->m_Search
1039  && !m_guiStartup->m_Retry)
1040  {
1042  m_guiStartup->setStatusState(stateMsg);
1043  m_guiStartup->setMessageState("makeselection");
1044  m_loop->exec();
1045  }
1046  }
1047  while (m_guiStartup && m_guiStartup->m_Retry);
1048 
1049  if (startupState < st_dbAwake)
1050  {
1051  LOG(VB_GENERAL, LOG_WARNING, QString("Pinging to %1 failed, database will be unavailable").arg(host));
1052  SilenceDBerrors();
1053  err = QObject::tr(
1054  "Cannot find (ping) database host %1 on the network",
1055  "Backend Setup");
1056  return err.arg(host);
1057  }
1058 
1059  if (startupState < st_dbConnects)
1060  {
1061  SilenceDBerrors();
1062  return QObject::tr("Cannot login to database", "Backend Setup");
1063  }
1064 
1065  if (startupState < st_success)
1066  {
1067  return QObject::tr("Cannot connect to backend", "Backend Setup");
1068  }
1069 
1070  // Current DB connection may have been silenced (invalid):
1071  EnableDBerrors();
1072  ResetDatabase();
1073 
1074  return {};
1075 }
1076 
1077 // Show the Gui Startup window.
1078 // This is called if there is a delay in startup for any reason
1079 // such as the database being unavailable
1081 {
1082  if (!m_gui)
1083  return;
1084  TempMainWindow(false);
1085  MythMainWindow *mainWindow = GetMythMainWindow();
1086  MythScreenStack *mainStack = mainWindow->GetMainStack();
1087  if (mainStack)
1088  {
1089  if (!m_guiStartup)
1090  {
1091  m_guiStartup = new GUIStartup(mainStack, m_loop);
1092  if (!m_guiStartup->Create())
1093  {
1094  delete m_guiStartup;
1095  m_guiStartup = nullptr;
1096  }
1097  if (m_guiStartup)
1098  {
1099  mainStack->AddScreen(m_guiStartup, false);
1100  processEvents();
1101  }
1102  }
1103  }
1104 }
1105 
1115 {
1116  // This silences any DB errors from Get*Setting(),
1117  // (which is the vast majority of them)
1118  gCoreContext->GetDB()->SetSuppressDBMessages(true);
1119 
1120  // Save the configured hostname, so that we can
1121  // still display it in the DatabaseSettings screens
1122  if (!m_dbParams.m_dbHostName.isEmpty())
1124 
1125  m_dbParams.m_dbHostName.clear();
1126  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
1127 }
1128 
1130 {
1131  // Restore (possibly) blanked hostname
1132  if (m_dbParams.m_dbHostName.isNull() && !m_dbHostCp.isEmpty())
1133  {
1135  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
1136  }
1137 
1138  gCoreContext->GetDB()->SetSuppressDBMessages(false);
1139 }
1140 
1141 
1154 {
1156  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
1158 }
1159 
1164 {
1165  TempMainWindow();
1166 
1167  // Tell the user what went wrong:
1168  if (!error.isEmpty())
1169  {
1170  LOG(VB_GENERAL, LOG_ERR, QString("Error: %1").arg(error));
1171  ShowOkPopup(error);
1172  }
1173 
1174  LOG(VB_GENERAL, LOG_INFO, "Putting up the UPnP backend chooser");
1175 
1178  // TODO encapuslation: don't use a pointer
1179 
1180  EndTempWindow();
1181 
1182  return ret;
1183 }
1184 
1191 int MythContextPrivate::UPnPautoconf(const std::chrono::milliseconds milliSeconds)
1192 {
1193  auto seconds = duration_cast<std::chrono::seconds>(milliSeconds);
1194  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search %1 secs")
1195  .arg(seconds.count()));
1196 
1198 
1199  // Search for a total of 'milliSeconds' ms, sending new search packet
1200  // about every 250 ms until less than one second remains.
1201  MythTimer totalTime; totalTime.start();
1202  MythTimer searchTime; searchTime.start();
1203  while (totalTime.elapsed() < milliSeconds)
1204  {
1205  usleep(25000);
1206  auto ttl = milliSeconds - totalTime.elapsed();
1207  if ((searchTime.elapsed() > 249ms) && (ttl > 1s))
1208  {
1209  auto ttlSeconds = duration_cast<std::chrono::seconds>(ttl);
1210  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search %1 secs")
1211  .arg(ttlSeconds.count()));
1212  SSDP::Instance()->PerformSearch(kBackendURI, ttlSeconds);
1213  searchTime.start();
1214  }
1215  }
1216 
1218 
1219  if (!backends)
1220  {
1221  LOG(VB_GENERAL, LOG_INFO, "No UPnP backends found");
1222  return 0;
1223  }
1224 
1225  int count = backends->Count();
1226  if (count)
1227  {
1228  LOG(VB_GENERAL, LOG_INFO,
1229  QString("Found %1 UPnP backends").arg(count));
1230  }
1231  else
1232  {
1233  LOG(VB_GENERAL, LOG_ERR,
1234  "No UPnP backends found, but SSDP::Find() not NULL");
1235  }
1236 
1237  if (count != 1)
1238  {
1239  backends->DecrRef();
1240  return count;
1241  }
1242 
1243  // Get this backend's location:
1244  DeviceLocation *BE = backends->GetFirst();
1245  backends->DecrRef();
1246  backends = nullptr;
1247 
1248  // We don't actually know the backend's access PIN, so this will
1249  // only work for ones that have PIN access disabled (i.e. 0000)
1250  int ret = (UPnPconnect(BE, QString())) ? 1 : -1;
1251 
1252  BE->DecrRef();
1253 
1254  return ret;
1255 }
1256 
1263 {
1264  static const QString loc = "DefaultUPnP() - ";
1265 
1266  // potentially saved in backendselect
1267  QString pin;
1268  QString usn;
1269  {
1270  auto config = XmlConfiguration(); // read-only
1271  pin = config.GetValue(kDefaultPIN, QString(""));
1272  usn = config.GetValue(kDefaultUSN, QString(""));
1273  }
1274 
1275  if (usn.isEmpty())
1276  {
1277  LOG(VB_UPNP, LOG_INFO, loc + "No default UPnP backend");
1278  return false;
1279  }
1280 
1281  LOG(VB_UPNP, LOG_INFO,
1282  loc + QString(XmlConfiguration::kDefaultFilename) +
1283  QString(" has default PIN '%1' and host USN: %2").arg(pin, usn));
1284 
1285  // ----------------------------------------------------------------------
1286 
1287  std::chrono::milliseconds timeout_ms {2s};
1288  auto timeout_s = duration_cast<std::chrono::seconds>(timeout_ms);
1289  LOG(VB_GENERAL, LOG_INFO, loc + QString("UPNP Search up to %1 secs")
1290  .arg(timeout_s.count()));
1291  SSDP::Instance()->PerformSearch(kBackendURI, timeout_s);
1292 
1293  // ----------------------------------------------------------------------
1294  // We need to give the server time to respond...
1295  // ----------------------------------------------------------------------
1296 
1297  DeviceLocation* devicelocation = nullptr;
1298  MythTimer totalTime;
1299  MythTimer searchTime;
1300  totalTime.start();
1301  searchTime.start();
1302  while (totalTime.elapsed() < timeout_ms)
1303  {
1304  devicelocation = SSDP::Find(kBackendURI, usn);
1305  if (devicelocation)
1306  break;
1307 
1308  usleep(25000);
1309 
1310  auto ttl = timeout_ms - totalTime.elapsed();
1311  if ((searchTime.elapsed() > 249ms) && (ttl > 1s))
1312  {
1313  auto ttlSeconds = duration_cast<std::chrono::seconds>(ttl);
1314  LOG(VB_GENERAL, LOG_INFO, loc + QString("UPNP Search up to %1 secs")
1315  .arg(ttlSeconds.count()));
1316  SSDP::Instance()->PerformSearch(kBackendURI, ttlSeconds);
1317  searchTime.start();
1318  }
1319  }
1320 
1321  // ----------------------------------------------------------------------
1322 
1323  if (!devicelocation)
1324  {
1325  Error = "Cannot find default UPnP backend";
1326  return false;
1327  }
1328 
1329  if (UPnPconnect(devicelocation, pin))
1330  {
1331  devicelocation->DecrRef();
1332  return true;
1333  }
1334 
1335  devicelocation->DecrRef();
1336  Error = "Cannot connect to default backend via UPnP. Wrong saved PIN?";
1337  return false;
1338 }
1339 
1344  const QString &PIN)
1345 {
1346  QString error;
1347  QString loc = "UPnPconnect() - ";
1348  QString URL = backend->m_sLocation;
1349  MythXMLClient client(URL);
1350 
1351  LOG(VB_UPNP, LOG_INFO, loc + QString("Trying host at %1").arg(URL));
1352  switch (client.GetConnectionInfo(PIN, &m_dbParams, error))
1353  {
1354  case UPnPResult_Success:
1355  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
1356  LOG(VB_UPNP, LOG_INFO, loc +
1357  "Got database hostname: " + m_dbParams.m_dbHostName);
1358  return true;
1359 
1361  // The stored PIN is probably not correct.
1362  // We could prompt for the PIN and try again, but that needs a UI.
1363  // Easier to fail for now, and put up the full UI selector later
1364  LOG(VB_UPNP, LOG_ERR, loc + "Wrong PIN?");
1365  return false;
1366 
1367  default:
1368  LOG(VB_UPNP, LOG_ERR, loc + error);
1369  break;
1370  }
1371 
1372  // This backend may have a local DB with the default user/pass/DBname.
1373  // For whatever reason, we have failed to get anything back via UPnP,
1374  // so we might as well try the database directly as a last resort.
1375  QUrl theURL(URL);
1376  URL = theURL.host();
1377  if (URL.isEmpty())
1378  return false;
1379 
1380  LOG(VB_UPNP, LOG_INFO, "Trying default DB credentials at " + URL);
1381  m_dbParams.m_dbHostName = URL;
1382 
1383  return true;
1384 }
1385 
1387 {
1388  if (e->type() == MythEvent::kMythEventMessage)
1389  {
1390  if (m_disableeventpopup)
1391  return true;
1392 
1394  {
1396  }
1397 
1398  auto *me = dynamic_cast<MythEvent*>(e);
1399  if (me == nullptr)
1400  return true;
1401 
1402  if (me->Message() == "VERSION_MISMATCH" && (1 == me->ExtraDataCount()))
1403  ShowVersionMismatchPopup(me->ExtraData(0).toUInt());
1404  else if (me->Message() == "CONNECTION_FAILURE")
1406  else if (me->Message() == "PERSISTENT_CONNECTION_FAILURE")
1408  else if (me->Message() == "CONNECTION_RESTABLISHED")
1410  return true;
1411  }
1412 
1413  return QObject::event(e);
1414 }
1415 
1417 {
1418  QDateTime now = MythDate::current();
1419 
1420  if (!GetNotificationCenter() || !m_ui || !m_ui->IsScreenSetup())
1421  return;
1422 
1423  if (m_lastCheck.isValid() && now < m_lastCheck)
1424  return;
1425 
1426  // When WOL is disallowed, standy mode,
1427  // we should not show connection failures.
1428  if (!gCoreContext->IsWOLAllowed())
1429  return;
1430 
1431  m_lastCheck = now.addMSecs(5000); // don't refresh notification more than every 5s
1432 
1433  QString description = (persistent) ?
1434  QObject::tr(
1435  "The connection to the master backend "
1436  "server has gone away for some reason. "
1437  "Is it running?") :
1438  QObject::tr(
1439  "Could not connect to the master backend server. Is "
1440  "it running? Is the IP address set for it in "
1441  "mythtv-setup correct?");
1442 
1443  QString message = QObject::tr("Could not connect to master backend");
1444  MythErrorNotification n(message, sLocation, description);
1445  n.SetId(m_registration);
1446  n.SetParent(this);
1448 }
1449 
1451 {
1452  if (!GetNotificationCenter())
1453  return;
1454 
1455  if (!m_lastCheck.isValid())
1456  return;
1457 
1458  MythCheckNotification n(QObject::tr("Backend is online"), sLocation);
1459  n.SetId(m_registration);
1460  n.SetParent(this);
1461  n.SetDuration(5s);
1463  m_lastCheck = QDateTime();
1464 }
1465 
1467 {
1468  if (m_mbeVersionPopup)
1469  return;
1470 
1471  QString message =
1472  QObject::tr(
1473  "The server uses network protocol version %1, "
1474  "but this client only understands version %2. "
1475  "Make sure you are running compatible versions of "
1476  "the backend and frontend.")
1477  .arg(remote_version).arg(MYTH_PROTO_VERSION);
1478 
1479  if (HasMythMainWindow() && m_ui && m_ui->IsScreenSetup())
1480  {
1483  }
1484  else
1485  {
1486  LOG(VB_GENERAL, LOG_ERR, LOC + message);
1487  qApp->exit(GENERIC_EXIT_SOCKET_ERROR);
1488  }
1489 }
1490 
1491 // Process Events while waiting for connection
1492 // return true if progress is 100%
1494 {
1495 // bool ret = false;
1496 // if (m_guiStartup)
1497 // ret = m_guiStartup->updateProgress();
1498  qApp->processEvents(QEventLoop::AllEvents, 250);
1499  qApp->processEvents(QEventLoop::AllEvents, 250);
1500 // return ret;
1501 }
1502 
1503 namespace
1504 {
1505 // cache some settings in GUISettingsCache::m_cacheFilename
1506 // only call this if the database is available.
1507 
1508 const std::array<QString, 13> GUISettingsCache::kSettings
1509 { "Theme", "Language", "Country", "GuiHeight",
1510  "GuiOffsetX", "GuiOffsetY", "GuiWidth", "RunFrontendInWindow",
1511  "AlwaysOnTop", "HideMouseCursor", "ThemePainter", "libCECEnabled",
1512  "StartupScreenDelay" };
1513 
1514 
1515 bool GUISettingsCache::save()
1516 {
1517  QString cacheDirName = GetConfDir() + '/' + m_cachePath;
1518  QDir dir(cacheDirName);
1519  dir.mkpath(cacheDirName);
1520  XmlConfiguration config = XmlConfiguration(m_cacheFilename);
1521  bool dirty = false;
1522  for (const auto & setting : kSettings)
1523  {
1524  QString cacheValue = config.GetValue("Settings/" + setting, QString());
1526  QString value = gCoreContext->GetSetting(setting, QString());
1527  if (value != cacheValue)
1528  {
1529  config.SetValue("Settings/" + setting, value);
1530  dirty = true;
1531  }
1532  }
1533  clearOverrides();
1534 
1535  if (dirty)
1536  {
1537 #ifndef Q_OS_ANDROID
1539 #endif
1540  return config.Save();
1541  }
1542  return true;
1543 }
1544 
1545 void GUISettingsCache::loadOverrides() const
1546 {
1547  auto config = XmlConfiguration(m_cacheFilename); // read only
1548  for (const auto & setting : kSettings)
1549  {
1550  if (!gCoreContext->GetSetting(setting, QString()).isEmpty())
1551  continue;
1552  QString value = config.GetValue("Settings/" + setting, QString());
1553  if (!value.isEmpty())
1554  gCoreContext->OverrideSettingForSession(setting, value);
1555  }
1556  // Prevent power off TV after temporary window
1557  gCoreContext->OverrideSettingForSession("PowerOffTVAllowed", nullptr);
1558 
1559  MythTranslation::load("mythfrontend");
1560 }
1561 
1562 void GUISettingsCache::clearOverrides()
1563 {
1564  QString language = gCoreContext->GetSetting("Language", QString());
1565  for (const auto & setting : kSettings)
1567  // Restore power off TV setting
1568  gCoreContext->ClearOverrideSettingForSession("PowerOffTVAllowed");
1569 
1570  if (language != gCoreContext->GetSetting("Language", QString()))
1571  MythTranslation::load("mythfrontend");
1572 }
1573 
1574 } // anonymous namespace
1575 
1577 {
1578  d->m_mbeVersionPopup = nullptr;
1579  qApp->exit(GENERIC_EXIT_SOCKET_ERROR);
1580 }
1581 
1582 MythContext::MythContext(QString binversion, bool needsBackend)
1583  : d(new MythContextPrivate(this)),
1584  m_appBinaryVersion(std::move(binversion))
1585 {
1586 #ifdef _WIN32
1587  static bool WSAStarted = false;
1588  if (!WSAStarted)
1589  {
1590  WSADATA wsadata;
1591  int res = WSAStartup(MAKEWORD(2, 0), &wsadata);
1592  LOG(VB_SOCKET, LOG_INFO,
1593  QString("WSAStartup returned %1").arg(res));
1594  }
1595 #endif
1596 
1597  d->m_needsBackend = needsBackend;
1598 
1600 
1601  if (!gCoreContext || !gCoreContext->Init())
1602  {
1603  LOG(VB_GENERAL, LOG_EMERG, LOC + "Unable to allocate MythCoreContext");
1604  qApp->exit(GENERIC_EXIT_NO_MYTHCONTEXT);
1605  }
1606 }
1607 
1608 bool MythContext::Init(const bool gui,
1609  const bool promptForBackend,
1610  const bool disableAutoDiscovery,
1611  const bool ignoreDB)
1612 {
1613  if (!d)
1614  {
1615  LOG(VB_GENERAL, LOG_EMERG, LOC + "Init() Out-of-memory");
1616  return false;
1617  }
1618 
1619  qRegisterMetaType<std::chrono::seconds>("std::chrono::seconds");
1620  qRegisterMetaType<std::chrono::milliseconds>("std::chrono::milliseconds");
1621  qRegisterMetaType<std::chrono::microseconds>("std::chrono::microseconds");
1622 
1623  SetDisableEventPopup(true);
1624 
1625  if (gui && QCoreApplication::applicationName() == MYTH_APPNAME_MYTHTV_SETUP)
1626  {
1627  d->TempMainWindow(false);
1628  QString warning = QObject::tr("mythtv-setup is deprecated.\n"
1629  "To set up MythTV, start mythbackend and use:\n"
1630  "http://localhost:6544/setupwizard");
1631  WaitFor(ShowOkPopup(warning));
1632  }
1633 
1634  if (m_appBinaryVersion != MYTH_BINARY_VERSION)
1635  {
1636  LOG(VB_GENERAL, LOG_EMERG,
1637  QString("Application binary version (%1) does not "
1638  "match libraries (%2)")
1639  .arg(m_appBinaryVersion, MYTH_BINARY_VERSION));
1640 
1641  QString warning = QObject::tr(
1642  "This application is not compatible "
1643  "with the installed MythTV libraries.");
1644  if (gui)
1645  {
1646  d->TempMainWindow(false);
1647  WaitFor(ShowOkPopup(warning));
1648  }
1649  LOG(VB_GENERAL, LOG_WARNING, warning);
1650 
1651  return false;
1652  }
1653 
1654 #ifdef _WIN32
1655  // HOME environment variable might not be defined
1656  // some libraries will fail without it
1657  QString home = getenv("HOME");
1658  if (home.isEmpty())
1659  {
1660  home = getenv("LOCALAPPDATA"); // Vista
1661  if (home.isEmpty())
1662  home = getenv("APPDATA"); // XP
1663  if (home.isEmpty())
1664  home = QString("."); // getenv("TEMP")?
1665 
1666  _putenv(QString("HOME=%1").arg(home).toLocal8Bit().constData());
1667  }
1668 #endif
1669 
1670  // If HOME isn't defined, we won't be able to use default confdir of
1671  // $HOME/.mythtv nor can we rely on a MYTHCONFDIR that references $HOME
1672  QString homedir = QDir::homePath();
1673  QString confdir = qEnvironmentVariable("MYTHCONFDIR");
1674  if ((homedir.isEmpty() || homedir == "/") &&
1675  (confdir.isEmpty() || confdir.contains("$HOME")))
1676  {
1677  QString warning = "Cannot locate your home directory."
1678  " Please set the environment variable HOME";
1679  if (gui)
1680  {
1681  d->TempMainWindow(false);
1682  WaitFor(ShowOkPopup(warning));
1683  }
1684  LOG(VB_GENERAL, LOG_WARNING, warning);
1685 
1686  return false;
1687  }
1688 
1689  if (!d->Init(gui, promptForBackend, disableAutoDiscovery, ignoreDB))
1690  {
1691  return false;
1692  }
1693 
1694  SetDisableEventPopup(false);
1695 
1696  if (d->m_gui)
1697  {
1699  }
1700 
1703 
1704  return true;
1705 }
1706 
1708 {
1709  gCoreContext->InitPower(false /*destroy*/);
1710  if (MThreadPool::globalInstance()->activeThreadCount())
1711  LOG(VB_GENERAL, LOG_INFO, "Waiting for threads to exit.");
1712 
1714  SSDP::Shutdown();
1716 
1717  LOG(VB_GENERAL, LOG_INFO, "Exiting");
1718 
1719  logStop();
1720 
1721  delete gCoreContext;
1722  gCoreContext = nullptr;
1723 
1724  delete d;
1725 }
1726 
1728 {
1729  d->m_disableeventpopup = check;
1730 }
1731 
1733 {
1734  return d->SaveDatabaseParams(params, force);
1735 }
1736 
1738 {
1739  /* this check is technically redundant since this is only called from
1740  MythContext::Init() and mythfrontend::main(); however, it is for safety
1741  and clarity until MythGUIContext is refactored out.
1742  */
1743  if (d->m_gui)
1744  {
1745  return d->m_GUISettingsCache.save();
1746  }
1747  return true;
1748 }
1749 
1750 /* vim: set expandtab tabstop=4 shiftwidth=4: */
BackendSelection::Decision
Decision
Definition: backendselect.h:41
MythContextPrivate::ShowConnectionFailurePopup
void ShowConnectionFailurePopup(bool persistent)
Definition: mythcontext.cpp:1416
WaitFor
bool WaitFor(MythConfirmationDialog *dialog)
Blocks until confirmation dialog exits.
Definition: mythdialogbox.cpp:603
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:317
MythTimer::elapsed
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
mythevent.h
MythContext::MythContext
MythContext(QString binversion, bool needsBackend=false)
Definition: mythcontext.cpp:1582
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:73
PortChecker
Small class to handle TCP port checking and finding link-local context.
Definition: portchecker.h:44
GUIStartup::Create
bool Create(void) override
Definition: guistartup.cpp:70
DatabaseParams::m_dbHostName
QString m_dbHostName
database server
Definition: mythdbparams.h:22
MediaMonitor::ejectOpticalDisc
static void ejectOpticalDisc(void)
Eject a disk, unmount a drive, open a tray.
Definition: mythmediamonitor.cpp:969
MythContextSlotHandler::VersionMismatchPopupClosed
void VersionMismatchPopupClosed(void)
Definition: mythcontext.cpp:1576
MythPluginManager
Definition: mythplugin.h:62
dbutil.h
MythEvent::kMythEventMessage
static const Type kMythEventMessage
Definition: mythevent.h:79
MythMainWindow::Init
void Init(bool MayReInit=true)
Definition: mythmainwindow.cpp:641
QAndroidJniEnvironment
#define QAndroidJniEnvironment
Definition: audiooutputaudiotrack.cpp:8
error
static void error(const char *str,...)
Definition: vbi.cpp:37
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
ShowNotificationError
void ShowNotificationError(const QString &msg, const QString &from, const QString &detail, const VNMask visibility, const MythNotification::Priority priority)
convenience utility to display error message as notification
Definition: mythnotificationcenter.cpp:1426
SSDP::PerformSearch
void PerformSearch(const QString &sST, std::chrono::seconds timeout=2s)
Definition: ssdp.cpp:204
MythContextPrivate::event
bool event(QEvent *) override
Definition: mythcontext.cpp:1386
mythdb.h
MythCoreContext::SendReceiveStringList
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
Definition: mythcorecontext.cpp:1379
MythContextPrivate::UPnPautoconf
int UPnPautoconf(std::chrono::milliseconds milliSeconds=2s)
If there is only a single UPnP backend, use it.
Definition: mythcontext.cpp:1191
MythTimer
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
MythCheckNotification
Definition: mythnotification.h:212
MythContextPrivate::DefaultUPnP
bool DefaultUPnP(QString &Error)
Get the default backend from XmlConfiguration::kDefaultFilename, use UPnP to find it.
Definition: mythcontext.cpp:1262
DatabaseParams::m_forceSave
bool m_forceSave
set to true to force a save of the settings file
Definition: mythdbparams.h:40
MythNotification::SetDuration
void SetDuration(std::chrono::seconds Duration)
Contains a duration during which the notification will be displayed for. The duration is informative ...
Definition: mythnotification.cpp:144
MythContextPrivate::m_mbeVersionPopup
MythConfirmationDialog * m_mbeVersionPopup
Definition: mythcontext.cpp:165
MythNotificationCenter::Register
int Register(void *from)
An application can register in which case it will be assigned a reusable screen, which can be modifie...
Definition: mythnotificationcenter.cpp:1368
MythCoreContext::GetDBManager
MDBManager * GetDBManager(void)
Definition: mythcorecontext.cpp:869
MythUIHelper::IsScreenSetup
bool IsScreenSetup() const
Definition: mythuihelper.cpp:98
MythPluginManager::run_plugin
bool run_plugin(const QString &plugname)
Definition: mythplugin.cpp:162
DatabaseParams
Structure containing the basic Database parameters.
Definition: mythdbparams.h:10
dbsettings.h
mythplugin.h
MythCoreContext::InitLocale
void InitLocale(void)
Definition: mythcorecontext.cpp:1858
MythContext
Startup context for MythTV.
Definition: mythcontext.h:43
MythMainWindow::getMainWindow
static MythMainWindow * getMainWindow(bool UseDB=true)
Return the existing main window, or create one.
Definition: mythmainwindow.cpp:80
MythXMLClient
Definition: mythxmlclient.h:31
MythCoreContext::OverrideSettingForSession
void OverrideSettingForSession(const QString &key, const QString &value)
Definition: mythcorecontext.cpp:1345
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
MythContext::SetDisableEventPopup
void SetDisableEventPopup(bool check)
Definition: mythcontext.cpp:1727
MythContextPrivate::TestDBconnection
QString TestDBconnection(bool prompt=true)
Some quick sanity checks before opening a database connection.
Definition: mythcontext.cpp:820
mythxmlclient.h
kDefaultWOL
const QString kDefaultWOL
Definition: backendselect.h:22
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
SSDP::Find
static SSDPCacheEntries * Find(const QString &sURI)
Definition: ssdp.h:132
mythmediamonitor.h
MythContextPrivate::m_loop
QEventLoop * m_loop
Definition: mythcontext.cpp:159
MythContextPrivate::m_parent
MythContext * m_parent
Definition: mythcontext.cpp:144
MythContext::SaveDatabaseParams
bool SaveDatabaseParams(const DatabaseParams &params, bool force=false)
Definition: mythcontext.cpp:1732
confdir
static QString confdir
Definition: mythdirs.cpp:22
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythContextPrivate::~MythContextPrivate
~MythContextPrivate() override
Definition: mythcontext.cpp:279
MythContextPrivate::UPnPconnect
bool UPnPconnect(const DeviceLocation *backend, const QString &PIN)
Query a backend via UPnP for its database connection parameters.
Definition: mythcontext.cpp:1343
DatabaseSettings::isClosing
void isClosing(void)
MythContextPrivate::ShowVersionMismatchPopup
void ShowVersionMismatchPopup(uint remote_version)
Definition: mythcontext.cpp:1466
MythContextPrivate::checkPort
bool checkPort(QString &host, int port, std::chrono::seconds timeLimit) const
Check if a port is open and sort out the link-local scope.
Definition: mythcontext.cpp:353
mythdirs.h
force
bool force
Definition: mythcommflag.cpp:70
MythContextPrivate::ShowGuiStartup
void ShowGuiStartup(void)
Definition: mythcontext.cpp:1080
myth_system
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
Definition: mythsystemlegacy.cpp:506
DeviceLocation
Definition: upnpdevice.h:210
MythContextPrivate::m_disableeventpopup
bool m_disableeventpopup
Definition: mythcontext.cpp:154
anonymous_namespace{mythcontext.cpp}::GUISettingsCache
Definition: mythcontext.cpp:70
HasMythMainWindow
bool HasMythMainWindow(void)
Definition: mythmainwindow.cpp:109
MythCoreContext::InitPower
void InitPower(bool Create=true)
Definition: mythcorecontext.cpp:1845
GUIStartup::m_Search
bool m_Search
Definition: guistartup.h:60
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
DatabaseParams::m_wolReconnect
std::chrono::seconds m_wolReconnect
seconds to wait for reconnect
Definition: mythdbparams.h:35
MythContextPrivate::EnableDBerrors
void EnableDBerrors(void)
Definition: mythcontext.cpp:1129
XmlConfiguration
Definition: configuration.h:38
SSDP::Shutdown
static void Shutdown()
Definition: ssdp.cpp:65
langsettings.h
MythContext::m_appBinaryVersion
QString m_appBinaryVersion
Definition: mythcontext.h:74
InitializeMythDirs
void InitializeMythDirs(void)
Definition: mythdirs.cpp:32
DatabaseSettings
Definition: dbsettings.h:10
exec_program_tv_cb
static void exec_program_tv_cb(const QString &cmd)
Definition: mythcontext.cpp:176
mythsystemlegacy.h
MYTH_APPNAME_MYTHTV_SETUP
static constexpr const char * MYTH_APPNAME_MYTHTV_SETUP
Definition: mythcorecontext.h:22
eject_cb
static void eject_cb(void)
Definition: mythcontext.cpp:266
MythCoreContext::ClearOverrideSettingForSession
void ClearOverrideSettingForSession(const QString &key)
Definition: mythcorecontext.cpp:1351
SSDP::Instance
static SSDP * Instance()
Definition: ssdp.cpp:55
QAndroidJniObject
#define QAndroidJniObject
Definition: audiooutputaudiotrack.cpp:9
MythContext::d
MythContextPrivate * d
Definition: mythcontext.h:73
StandardSettingDialog
Definition: standardsettings.h:468
DatabaseParams::m_dbPort
int m_dbPort
database port
Definition: mythdbparams.h:24
kDefaultDB
const QString kDefaultDB
Definition: backendselect.h:21
mythdate.h
XmlConfiguration::SetValue
void SetValue(const QString &setting, bool value)
Definition: configuration.h:93
BackendSelection::kManualConfigure
@ kManualConfigure
Definition: backendselect.h:43
MDBManager::CloseDatabases
void CloseDatabases(void)
Definition: mythdbcon.cpp:484
upnp.h
guistartup.h
mythlogging.h
MythContextPrivate::OnCloseDialog
void OnCloseDialog()
MythCoreContext::Init
bool Init(void)
Definition: mythcorecontext.cpp:220
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:256
DatabaseParams::m_dbHostPing
bool m_dbHostPing
No longer used.
Definition: mythdbparams.h:23
remotefile.h
MythContextPrivate::EndTempWindow
void EndTempWindow(void)
Definition: mythcontext.cpp:327
configplugin_cb
static void configplugin_cb(const QString &cmd)
Definition: mythcontext.cpp:239
MThreadPool::waitForDone
void waitForDone(void)
Definition: mthreadpool.cpp:565
compat.h
MythNotification::SetParent
void SetParent(void *Parent)
Contains the parent address. Required if id is set Id provided must match the parent address as provi...
Definition: mythnotification.cpp:106
MythContextPrivate::m_socket
QTcpSocket * m_socket
Definition: mythcontext.cpp:168
MythCoreContext::GetDurSetting
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
Definition: mythcorecontext.h:168
XmlConfiguration::Save
bool Save()
Definition: configuration.cpp:79
MSqlQuery::testDBConnection
static bool testDBConnection()
Checks DB connection + login (login info via Mythcontext)
Definition: mythdbcon.cpp:876
MythContextPrivate::MythContextPrivate
MythContextPrivate(MythContext *lparent)
Definition: mythcontext.cpp:271
DestroyMythMainWindow
void DestroyMythMainWindow(void)
Definition: mythmainwindow.cpp:114
DeviceLocation::m_sLocation
QString m_sLocation
Definition: upnpdevice.h:236
MythCoreContext::IsFrontend
bool IsFrontend(void) const
is this process a frontend process
Definition: mythcorecontext.cpp:658
MythErrorNotification
Definition: mythnotification.h:198
getResponse
QString getResponse(const QString &query, const QString &def)
In an interactive shell, prompt the user to input a string.
Definition: mythmiscutil.cpp:410
MythCoreContext::GetDB
MythDB * GetDB(void)
Definition: mythcorecontext.cpp:1761
anonymous_namespace{mythcontext.cpp}::GUISettingsCache::kSettings
static const std::array< QString, 13 > kSettings
Definition: mythcontext.cpp:92
MythWakeup
bool MythWakeup(const QString &wakeUpCommand, uint flags, std::chrono::seconds timeout)
Definition: mythmiscutil.cpp:630
mythtranslation.h
MythContextPrivate::SaveDatabaseParams
bool SaveDatabaseParams(const DatabaseParams &params, bool force)
Definition: mythcontext.cpp:660
DatabaseParams::m_dbPassword
QString m_dbPassword
DB password.
Definition: mythdbparams.h:26
portchecker.h
sLocation
static const QString sLocation
Definition: mythcontext.cpp:66
DatabaseParams::m_wolRetry
int m_wolRetry
times to retry to reconnect
Definition: mythdbparams.h:36
kBackendURI
const QString kBackendURI
Definition: backendselect.h:20
DatabaseParams::m_dbName
QString m_dbName
database name
Definition: mythdbparams.h:27
MythContextPrivate::PromptForDatabaseParams
bool PromptForDatabaseParams(const QString &error)
Definition: mythcontext.cpp:725
TaskQueue::Shutdown
static void Shutdown()
Definition: taskqueue.cpp:70
SSDPCacheEntries
Definition: ssdpcache.h:35
uint
unsigned int uint
Definition: compat.h:81
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
BackendSelection::kCancelConfigure
@ kCancelConfigure
Definition: backendselect.h:44
MythContextPrivate::m_ui
MythUIHelper * m_ui
Definition: mythcontext.cpp:156
UPnPResult_ActionNotAuthorized
@ UPnPResult_ActionNotAuthorized
Definition: upnp.h:48
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:916
logStop
void logStop(void)
Entry point for stopping logging for an application.
Definition: logging.cpp:669
MythContextPrivate::m_registration
int m_registration
Definition: mythcontext.cpp:166
MythContextPrivate::m_masterhostname
QString m_masterhostname
master backend hostname
Definition: mythcontext.cpp:149
exec_program_cb
static void exec_program_cb(const QString &cmd)
Definition: mythcontext.cpp:171
MythUIMenuCallbacks::exec_program
void(* exec_program)(const QString &cmd)
Definition: mythuihelper.h:16
MythCoreContext::SetLocalHostname
void SetLocalHostname(const QString &hostname)
Definition: mythcorecontext.cpp:1734
MythContextSlotHandler::d
MythContextPrivate * d
Definition: mythcontext.h:31
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:34
GUIStartup::setTotal
void setTotal(std::chrono::seconds total)
Definition: guistartup.cpp:131
BackendSelection::Prompt
static Decision Prompt(DatabaseParams *dbParams, const QString &config_filename)
Definition: backendselect.cpp:54
plugin_cb
static void plugin_cb(const QString &cmd)
Definition: mythcontext.cpp:252
GUIStartup::updateProgress
bool updateProgress(bool finished)
Definition: guistartup.cpp:147
MythPluginManager::config_plugin
bool config_plugin(const QString &plugname)
Definition: mythplugin.cpp:180
mythuihelper.h
UPnPResult_Success
@ UPnPResult_Success
Definition: upnp.h:37
MythContextPrivate::SilenceDBerrors
void SilenceDBerrors(void)
Cause MSqlDatabase::OpenDatabase() and MSqlQuery to fail silently.
Definition: mythcontext.cpp:1114
MythContextPrivate::m_sh
MythContextSlotHandler * m_sh
Definition: mythcontext.cpp:157
MythCoreContext::GetMasterServerPort
static int GetMasterServerPort(void)
Returns the Master Backend control port If no master server port has been defined in the database,...
Definition: mythcorecontext.cpp:984
PortChecker::checkPort
bool checkPort(QString &host, int port, std::chrono::milliseconds timeLimit=30s, bool linkLocalOnly=false)
Check if a port is open and sort out the link-local scope.
Definition: portchecker.cpp:73
GUIStartup::m_Retry
bool m_Retry
Definition: guistartup.h:59
mythimage.h
DatabaseParams::LoadDefaults
void LoadDefaults(void)
Load sensible connection defaults.
Definition: mythdbparams.cpp:9
GUIStartup::setMessageState
bool setMessageState(const QString &name)
Definition: guistartup.cpp:120
MythContextPrivate::FindDatabase
bool FindDatabase(bool prompt, bool noAutodetect)
Get database connection settings and test connectivity.
Definition: mythcontext.cpp:439
GUIStartup::setStatusState
bool setStatusState(const QString &name)
Definition: guistartup.cpp:110
MythCoreContext
This class contains the runtime context for MythTV.
Definition: mythcorecontext.h:62
XmlConfiguration::GetValue
QString GetValue(const QString &setting)
Definition: configuration.cpp:185
mythmiscutil.h
MythContextPrivate::m_GUISettingsCache
GUISettingsCache m_GUISettingsCache
Definition: mythcontext.cpp:162
MythConfirmationDialog
Dialog asking for user confirmation. Ok and optional Cancel button.
Definition: mythdialogbox.h:272
MythContextPrivate::LoadDatabaseSettings
bool LoadDatabaseSettings(void)
Load database and host settings from XmlConfiguration::k_default_filename, or set some defaults.
Definition: mythcontext.cpp:566
MythContextPrivate::Init
bool Init(bool gui, bool promptForBackend, bool disableAutoDiscovery, bool ignoreDB)
Definition: mythcontext.cpp:362
MythCoreContext::IsBackend
bool IsBackend(void) const
is this process a backend process
Definition: mythcorecontext.cpp:648
GUIStartup
Definition: guistartup.h:51
intResponse
int intResponse(const QString &query, int def)
In an interactive shell, prompt the user to input a number.
Definition: mythmiscutil.cpp:440
MythContextPrivate::m_dbParams
DatabaseParams m_dbParams
Current database host & WOL details.
Definition: mythcontext.cpp:151
MythContextPrivate::HideConnectionFailurePopup
void HideConnectionFailurePopup(void)
Definition: mythcontext.cpp:1450
DatabaseParams::m_wolCommand
QString m_wolCommand
command to use for wake-on-lan
Definition: mythdbparams.h:37
MythCoreContext::GetSettingOnHost
QString GetSettingOnHost(const QString &key, const QString &host, const QString &defaultval="")
Definition: mythcorecontext.cpp:930
LOC
#define LOC
Definition: mythcontext.cpp:62
LanguageSelection::prompt
static bool prompt(bool force=false)
Ask the user for the language to use.
Definition: langsettings.cpp:173
DatabaseParams::m_dbUserName
QString m_dbUserName
DB user name.
Definition: mythdbparams.h:25
XmlConfiguration::kDefaultFilename
static constexpr auto kDefaultFilename
Definition: configuration.h:55
configuration.h
GetNotificationCenter
MythNotificationCenter * GetNotificationCenter(void)
Definition: mythmainwindow.cpp:124
mythcontext.h
MythNotificationCenter::UnRegister
void UnRegister(void *from, int id, bool closeimemdiately=false)
Unregister the client.
Definition: mythnotificationcenter.cpp:1373
MythScreenStack::PopScreen
virtual void PopScreen(MythScreenType *screen=nullptr, bool allowFade=true, bool deleteScreen=true)
Definition: mythscreenstack.cpp:86
kDefaultUSN
const QString kDefaultUSN
Definition: backendselect.h:25
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
MythContextPrivate::ChooseBackend
BackendSelection::Decision ChooseBackend(const QString &error)
Search for backends via UPnP, put up a UI for the user to choose one.
Definition: mythcontext.cpp:1163
BackendSelection::kAcceptConfigure
@ kAcceptConfigure
Definition: backendselect.h:45
MythNotification::SetId
void SetId(int Id)
Contains the application registration id.
Definition: mythnotification.cpp:93
MythXMLClient::GetConnectionInfo
UPnPResultCode GetConnectionInfo(const QString &sPin, DatabaseParams *pParams, QString &sMsg)
Definition: mythxmlclient.cpp:35
MythContextPrivate::TempMainWindow
void TempMainWindow(bool languagePrompt=true)
Setup a minimal themed main window, and prompt for user's language.
Definition: mythcontext.cpp:304
MythCoreContext::ActivateSettingsCache
void ActivateSettingsCache(bool activate=true)
Definition: mythcorecontext.cpp:837
MythContextPrivate::m_lastCheck
QDateTime m_lastCheck
Definition: mythcontext.cpp:167
MythContextPrivate::ResetDatabase
void ResetDatabase(void) const
Called when the user changes the DB connection settings.
Definition: mythcontext.cpp:1153
kDefaultPIN
const QString kDefaultPIN
Definition: backendselect.h:24
MythUIHelper::Init
void Init(MythUIMenuCallbacks &cbs)
Definition: mythuihelper.cpp:76
MythContextSlotHandler::OnCloseDialog
void OnCloseDialog(void)
Definition: mythcontext.cpp:713
MythContextPrivate::m_needsBackend
bool m_needsBackend
Definition: mythcontext.cpp:160
MythContextPrivate::processEvents
static void processEvents(void)
Definition: mythcontext.cpp:1493
GUIStartup::m_Setup
bool m_Setup
Definition: guistartup.h:58
MythCoreContext::ClearSettingsCache
void ClearSettingsCache(const QString &myKey=QString(""))
Definition: mythcorecontext.cpp:832
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
DatabaseParams::m_localEnabled
bool m_localEnabled
true if localHostName is not default
Definition: mythdbparams.h:30
backendselect.h
MythContextPrivate::m_dbHostCp
QString m_dbHostCp
dbHostName backup
Definition: mythcontext.cpp:152
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
MythCoreContext::IsWOLAllowed
bool IsWOLAllowed() const
Definition: mythcorecontext.cpp:638
MythUIHelper
Definition: mythuihelper.h:23
MythContextSlotHandler
Definition: mythcontext.h:14
DatabaseParams::m_wolEnabled
bool m_wolEnabled
true if wake-on-lan params are used
Definition: mythdbparams.h:34
anonymous_namespace{mythcontext.cpp}::GUISettingsCache::GUISettingsCache
GUISettingsCache(const QString &cache_filename, QString cache_path)
Definition: mythcontext.cpp:74
MythTranslation::load
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
Definition: mythtranslation.cpp:37
exitcodes.h
SSDPCacheEntries::Count
uint Count(void) const
Definition: ssdpcache.h:45
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:66
MThreadPool::globalInstance
static MThreadPool * globalInstance(void)
Definition: mthreadpool.cpp:307
MythCoreContext::GetPluginManager
MythPluginManager * GetPluginManager(void)
Definition: mythcorecontext.cpp:2115
mythmainwindow.h
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
DatabaseParams::m_localHostName
QString m_localHostName
name used for loading/saving settings
Definition: mythdbparams.h:31
GENERIC_EXIT_SOCKET_ERROR
@ GENERIC_EXIT_SOCKET_ERROR
Socket error.
Definition: exitcodes.h:21
MythCoreContext::SaveLocaleDefaults
void SaveLocaleDefaults(void)
Definition: mythcorecontext.cpp:1890
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:566
MythContextPrivate::m_gui
bool m_gui
Should this context use GUI elements?
Definition: mythcontext.cpp:147
ANDROID_EXCEPTION_CHECK
#define ANDROID_EXCEPTION_CHECK
Definition: audiooutputaudiotrack.cpp:19
gContext
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:64
PortChecker::cancelPortCheck
void cancelPortCheck(void)
Cancel the checkPort operation currently in progress.
Definition: portchecker.cpp:249
MythContext::Init
bool Init(bool gui=true, bool promptForBackend=false, bool disableAutoDiscovery=false, bool ignoreDB=false)
Definition: mythcontext.cpp:1608
MythMainWindow
Definition: mythmainwindow.h:28
DatabaseParams::IsValid
bool IsValid(const QString &source=QString("Unknown")) const
Definition: mythdbparams.cpp:36
MythContextPrivate::m_guiStartup
GUIStartup * m_guiStartup
Definition: mythcontext.cpp:158
SSDPCacheEntries::GetFirst
DeviceLocation * GetFirst(void)
Returns random entry in cache, returns nullptr when list is empty.
Definition: ssdpcache.cpp:73
MythContext::saveSettingsCache
bool saveSettingsCache(void)
Definition: mythcontext.cpp:1737
DestroyMythUI
void DestroyMythUI()
Definition: mythuihelper.cpp:71
GUIStartup::cancelPortCheck
void cancelPortCheck(void)
GENERIC_EXIT_NO_MYTHCONTEXT
@ GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:16
MythContext::~MythContext
virtual ~MythContext()
Definition: mythcontext.cpp:1707
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:902
MythContextPrivate
Definition: mythcontext.cpp:97
MythNotificationCenter::Queue
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
Definition: mythnotificationcenter.cpp:1349
MythUIMenuCallbacks
Definition: mythuihelper.h:14
GUIStartup::m_Exit
bool m_Exit
Definition: guistartup.h:57