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