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 {
70 class GUISettingsCache
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  strlist << "LOCK_TUNER";
192 
194  int cardid = strlist[0].toInt();
195 
196  if (cardid >= 0)
197  {
198  s = s.arg(qPrintable(strlist[1]),
199  qPrintable(strlist[2]),
200  qPrintable(strlist[3]));
201 
202  myth_system(s);
203 
204  strlist = QStringList(QString("FREE_TUNER %1").arg(cardid));
206  }
207  else
208  {
209  QString label;
210 
211  if (cardidok)
212  {
213  if (cardid == -1)
214  {
215  label = QObject::tr("Could not find specified tuner (%1).")
216  .arg(wantcardid);
217  }
218  else
219  {
220  label = QObject::tr("Specified tuner (%1) is already in use.")
221  .arg(wantcardid);
222  }
223  }
224  else
225  {
226  label = QObject::tr("All tuners are currently in use. If you want "
227  "to watch TV, you can cancel one of the "
228  "in-progress recordings from the delete menu");
229  }
230 
231  LOG(VB_GENERAL, LOG_ALERT, QString("exec_program_tv: ") + label);
232 
233  ShowOkPopup(label);
234  }
235 }
236 
237 static void configplugin_cb(const QString &cmd)
238 {
240  if (!pmanager)
241  return;
242 
243  if (GetNotificationCenter() && pmanager->config_plugin(cmd.trimmed()))
244  {
246  QObject::tr("Failed to configure plugin"));
247  }
248 }
249 
250 static void plugin_cb(const QString &cmd)
251 {
253  if (!pmanager)
254  return;
255 
256  if (GetNotificationCenter() && pmanager->run_plugin(cmd.trimmed()))
257  {
258  ShowNotificationError(QObject::tr("Plugin failure"),
259  sLocation,
260  QObject::tr("%1 failed to run for some reason").arg(cmd));
261  }
262 }
263 
264 static void eject_cb(void)
265 {
267 }
268 
270  : m_parent(lparent),
271  m_sh(new MythContextSlotHandler(this))
272 {
273  m_loop = new QEventLoop(this);
275 }
276 
278 {
280  {
282  }
283 
284  delete m_loop;
285 
286  if (m_ui)
287  DestroyMythUI();
288  if (m_sh)
289  m_sh->deleteLater();
290 }
291 
302 void MythContextPrivate::TempMainWindow(bool languagePrompt)
303 {
304  if (HasMythMainWindow())
305  return;
306 
307  SilenceDBerrors();
308 
309 #ifdef Q_OS_DARWIN
310  // Qt 4.4 has window-focus problems
311  gCoreContext->OverrideSettingForSession("RunFrontendInWindow", "1");
312 #endif
313  GetMythUI()->Init();
314  MythMainWindow *mainWindow = MythMainWindow::getMainWindow(false);
315  mainWindow->Init();
316 
317  if (languagePrompt)
318  {
319  // ask user for language settings
321  MythTranslation::load("mythfrontend");
322  }
323 }
324 
326 {
327  if (HasMythMainWindow())
328  {
330  {
332  if (mainStack)
333  {
334  mainStack->PopScreen(m_guiStartup, false);
335  m_guiStartup = nullptr;
336  }
337  }
338  }
339  EnableDBerrors();
340 }
341 
351 bool MythContextPrivate::checkPort(QString &host, int port, std::chrono::seconds timeLimit) const
352 {
353  PortChecker checker;
354  if (m_guiStartup)
356  return checker.checkPort(host, port, timeLimit);
357 }
358 
359 
360 bool MythContextPrivate::Init(const bool gui,
361  const bool promptForBackend,
362  const bool disableAutoDiscovery,
363  const bool ignoreDB)
364 {
365  gCoreContext->GetDB()->IgnoreDatabase(ignoreDB);
366  m_gui = gui;
367  if (gui)
368  {
369  m_GUISettingsCache.loadOverrides();
370  }
371 
372  if (gCoreContext->IsFrontend())
373  m_needsBackend = true;
374 
375  // Creates screen saver control if we will have a GUI
376  if (gui)
377  m_ui = GetMythUI();
378 
379  // ---- database connection stuff ----
380 
381  if (!ignoreDB && !FindDatabase(promptForBackend, disableAutoDiscovery))
382  {
383  EndTempWindow();
384  return false;
385  }
386 
387  // ---- keep all DB-using stuff below this line ----
388 
389  // Prompt for language if this is a first time install and
390  // we didn't already do so.
391  if (m_gui && !gCoreContext->GetDB()->HaveSchema())
392  {
393  TempMainWindow(false);
395  MythTranslation::load("mythfrontend");
396  }
399 
400  // Close GUI Startup Window.
401  if (m_guiStartup)
402  {
404  if (mainStack)
405  mainStack->PopScreen(m_guiStartup, false);
406  m_guiStartup=nullptr;
407  }
408  EndTempWindow();
409 
410  if (gui)
411  {
412  MythUIMenuCallbacks cbs {};
414  cbs.exec_program_tv = exec_program_tv_cb;
415  cbs.configplugin = configplugin_cb;
416  cbs.plugin = plugin_cb;
417  cbs.eject = eject_cb;
418 
419  m_ui->Init(cbs);
420  }
421 
422  return true;
423 }
424 
437 bool MythContextPrivate::FindDatabase(bool prompt, bool noAutodetect)
438 {
439  // We can only prompt if autodiscovery is enabled..
440  bool manualSelect = prompt && !noAutodetect;
441 
442  QString failure;
443 
444  // 1. Either load XmlConfiguration::k_default_filename or use sensible "localhost" defaults:
445  bool loaded = LoadDatabaseSettings();
446  DatabaseParams dbParamsFromFile = m_dbParams;
447 
448  // In addition to the UI chooser, we can also try to autoSelect later,
449  // but only if we're not doing manualSelect and there was no
450  // valid XmlConfiguration::k_default_filename
451  bool autoSelect = !manualSelect && !loaded && !noAutodetect;
452 
453  // 2. If the user isn't forcing up the chooser UI, look for a default
454  // backend in XmlConfiguration::k_default_filename, then test DB settings we've got so far:
455  if (!manualSelect)
456  {
457  // XmlConfiguration::k_default_filename may contain a backend host UUID and PIN.
458  // If so, try to AutoDiscover UPnP server, and use its DB settings:
459 
460  if (DefaultUPnP(failure)) // Probably a valid backend,
461  autoSelect = manualSelect = false; // so disable any further UPnP
462  else
463  if (!failure.isEmpty())
464  LOG(VB_GENERAL, LOG_ALERT, failure);
465 
466  failure = TestDBconnection(loaded);
467  if (failure.isEmpty())
468  goto DBfound;
470  return false;
472  autoSelect=true;
473  }
474 
475  // 3. Try to automatically find the single backend:
476  if (autoSelect)
477  {
478  int count = UPnPautoconf();
479 
480  if (count == 0)
481  failure = QObject::tr("No UPnP backends found", "Backend Setup");
482 
483  if (count == 1)
484  {
485  failure = TestDBconnection();
486  if (failure.isEmpty())
487  goto DBfound;
489  return false;
490  }
491 
492  // Multiple BEs, or needs PIN.
493  manualSelect |= (count > 1 || count == -1);
494  // Search requested
496  manualSelect=true;
497  }
498 
499  manualSelect &= m_gui; // no interactive command-line chooser yet
500 
501  // Queries the user for the DB info
502  do
503  {
504  if (manualSelect)
505  {
506  // Get the user to select a backend from a possible list:
507  switch (ChooseBackend(failure))
508  {
510  break;
512  manualSelect = false;
513  break;
515  goto NoDBfound;
516  }
517  }
518 
519  if (!manualSelect)
520  {
521  // If this is a backend, No longer prompt for database.
522  // Instaed allow the web server to start so that the
523  // database can be set up there
524  if (gCoreContext->IsBackend()
525  || !PromptForDatabaseParams(failure))
526  goto NoDBfound;
527  }
528  failure = TestDBconnection();
529  if (!failure.isEmpty())
530  LOG(VB_GENERAL, LOG_ALERT, failure);
532  return false;
534  manualSelect=true;
536  manualSelect=false;
537  }
538  while (!failure.isEmpty());
539 
540 DBfound:
541  LOG(VB_GENERAL, LOG_DEBUG, "FindDatabase() - Success!");
542  // If we got the database from UPNP then the wakeup settings are lost.
543  // Restore them.
544  m_dbParams.m_wolEnabled = dbParamsFromFile.m_wolEnabled;
545  m_dbParams.m_wolReconnect = dbParamsFromFile.m_wolReconnect;
546  m_dbParams.m_wolRetry = dbParamsFromFile.m_wolRetry;
547  m_dbParams.m_wolCommand = dbParamsFromFile.m_wolCommand;
548 
550  !loaded || m_dbParams.m_forceSave ||
551  dbParamsFromFile != m_dbParams);
552  EnableDBerrors();
553  ResetDatabase();
554  return true;
555 
556 NoDBfound:
557  LOG(VB_GENERAL, LOG_DEBUG, "FindDatabase() - failed");
558  return false;
559 }
560 
565 {
566  auto config = XmlConfiguration(); // read-only
567 
569 
570  m_dbParams.m_localHostName = config.GetValue("LocalHostName", "");
571  m_dbParams.m_dbHostPing = config.GetValue(kDefaultDB + "PingHost", true);
572  m_dbParams.m_dbHostName = config.GetValue(kDefaultDB + "Host", "");
573  m_dbParams.m_dbUserName = config.GetValue(kDefaultDB + "UserName", "");
574  m_dbParams.m_dbPassword = config.GetValue(kDefaultDB + "Password", "");
575  m_dbParams.m_dbName = config.GetValue(kDefaultDB + "DatabaseName", "");
576  m_dbParams.m_dbPort = config.GetValue(kDefaultDB + "Port", 0);
577 
578  m_dbParams.m_wolEnabled = config.GetValue(kDefaultWOL + "Enabled", false);
580  config.GetDuration<std::chrono::seconds>(kDefaultWOL + "SQLReconnectWaitTime", 0s);
581  m_dbParams.m_wolRetry = config.GetValue(kDefaultWOL + "SQLConnectRetry", 5);
582  m_dbParams.m_wolCommand = config.GetValue(kDefaultWOL + "Command", "");
583 
585 
586  if (!ok)
588 
589  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
590 
592  if (hostname.isEmpty() ||
593  hostname == "my-unique-identifier-goes-here")
594  {
595  LOG(VB_GENERAL, LOG_INFO, "Empty LocalHostName. This is typical.");
596  hostname = QHostInfo::localHostName();
597 
598 #ifndef Q_OS_ANDROID
599  if (hostname.isEmpty())
600  {
601  LOG(VB_GENERAL, LOG_ALERT,
602  "MCP: Error, could not determine host name." + ENO);
603  }
604 #else //elif defined Q_OS_ANDROID
605 #define ANDROID_EXCEPTION_CHECK \
606  if (env->ExceptionCheck()) \
607  { \
608  env->ExceptionClear(); \
609  exception=true; \
610  }
611 
612  if ((hostname == "localhost") || hostname.isEmpty())
613  {
614  hostname = "android";
615  bool exception=false;
618 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
619  QAndroidJniObject activity = QtAndroid::androidActivity();
620 #else
621  QJniObject activity = QNativeInterface::QAndroidApplication::context();
622 #endif
624  QAndroidJniObject appctx = activity.callObjectMethod
625  ("getApplicationContext", "()Landroid/content/Context;");
627  QAndroidJniObject contentR = appctx.callObjectMethod
628  ("getContentResolver", "()Landroid/content/ContentResolver;");
630  QAndroidJniObject androidId = QAndroidJniObject::callStaticObjectMethod
631  ("android/provider/Settings$Secure", "getString",
632  "(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;",
633  contentR.object<jobject>(),
634  myID.object<jstring>());
636  if (exception)
637  LOG(VB_GENERAL, LOG_ALERT,
638  "Java exception looking for android id");
639  else
640  hostname = QString("android-%1").arg(androidId.toString());
641  }
642 #endif
643 
644  }
645  else
646  {
647  m_dbParams.m_localEnabled = true;
648  }
649 
650  LOG(VB_GENERAL, LOG_INFO, QString("Using a profile name of: '%1' (Usually the "
651  "same as this host's name.)")
652  .arg(hostname));
654 
655  return ok;
656 }
657 
659  const DatabaseParams &params, bool force)
660 {
661  bool success = true;
662 
663  // only rewrite file if it has changed
664  if (force || (params != m_dbParams))
665  {
666  /* Read in the current file on the filesystem, only setting/clearing as
667  necessary. This prevents losing changes to the file from between when it
668  was read at startup of MythTV and when this function is called.
669  */
670  auto config = XmlConfiguration();
671 
672  config.SetValue("LocalHostName", params.m_localHostName);
673 
674  config.SetValue(kDefaultDB + "PingHost", params.m_dbHostPing);
675 
676  // If dbHostName is an IPV6 address with scope,
677  // remove the scope. Unescaped % signs are an
678  // xml violation
679  QString dbHostName(params.m_dbHostName);
680  QHostAddress addr;
681  if (addr.setAddress(dbHostName))
682  {
683  addr.setScopeId(QString());
684  dbHostName = addr.toString();
685  }
686  config.SetValue(kDefaultDB + "Host", dbHostName);
687  config.SetValue(kDefaultDB + "UserName", params.m_dbUserName);
688  config.SetValue(kDefaultDB + "Password", params.m_dbPassword);
689  config.SetValue(kDefaultDB + "DatabaseName", params.m_dbName);
690  config.SetValue(kDefaultDB + "Port", params.m_dbPort);
691 
692  config.SetValue(kDefaultWOL + "Enabled", params.m_wolEnabled);
693  config.SetDuration(
694  kDefaultWOL + "SQLReconnectWaitTime", params.m_wolReconnect);
695  config.SetValue(kDefaultWOL + "SQLConnectRetry", params.m_wolRetry);
696  config.SetValue(kDefaultWOL + "Command", params.m_wolCommand);
697 
698  // actually save the file
699  success = config.Save();
700 
701  // Use the new settings:
702  m_dbParams = params;
703  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
704 
705  // If database has changed, force its use:
706  ResetDatabase();
707  }
708  return success;
709 }
710 
712 {
713  if (d && d->m_loop
714  && d->m_loop->isRunning())
715  d->m_loop->exit();
716 }
717 
718 
719 // No longer prompt for database, instaed allow the
720 // web server to start so that the datbase can be
721 // set up there
722 
724 {
725  bool accepted = false;
726  if (m_gui)
727  {
728  TempMainWindow();
729 
730  // Tell the user what went wrong:
731  if (!error.isEmpty())
733 
734  // ask user for database parameters
735 
736  EnableDBerrors();
738  auto *dbsetting = new DatabaseSettings();
739  auto *ssd = new StandardSettingDialog(mainStack, "databasesettings",
740  dbsetting);
741  if (ssd->Create())
742  {
743  mainStack->AddScreen(ssd);
744  connect(dbsetting, &DatabaseSettings::isClosing,
746  if (!m_loop->isRunning())
747  m_loop->exec();
748  }
749  else
750  delete ssd;
751  SilenceDBerrors();
752  EndTempWindow();
753  accepted = true;
754  }
755  else
756  {
757  DatabaseParams params = m_dbParams;
758  QString response;
759  std::this_thread::sleep_for(1s);
760  // give user chance to skip config
761  std::cout << std::endl << error.toLocal8Bit().constData() << std::endl << std::endl;
762  response = getResponse("Would you like to configure the database "
763  "connection now?",
764  "no");
765  if (!response.startsWith('y', Qt::CaseInsensitive))
766  return false;
767 
768  params.m_dbHostName = getResponse("Database host name:",
769  params.m_dbHostName);
770  response = getResponse("Should I test connectivity to this host "
771  "using the ping command?", "yes");
772  params.m_dbHostPing = response.startsWith('y', Qt::CaseInsensitive);
773 
774  params.m_dbPort = intResponse("Database non-default port:",
775  params.m_dbPort);
776  params.m_dbName = getResponse("Database name:",
777  params.m_dbName);
778  params.m_dbUserName = getResponse("Database user name:",
779  params.m_dbUserName);
780  params.m_dbPassword = getResponse("Database password:",
781  params.m_dbPassword);
782 
783  params.m_localHostName = getResponse("Unique identifier for this machine "
784  "(if empty, the local host name "
785  "will be used):",
786  params.m_localHostName);
787  params.m_localEnabled = !params.m_localHostName.isEmpty();
788 
789  response = getResponse("Would you like to use Wake-On-LAN to retry "
790  "database connections?",
791  (params.m_wolEnabled ? "yes" : "no"));
792  params.m_wolEnabled = response.startsWith('y', Qt::CaseInsensitive);
793 
794  if (params.m_wolEnabled)
795  {
796  params.m_wolReconnect =
797  std::chrono::seconds(intResponse("Seconds to wait for "
798  "reconnection:",
799  params.m_wolReconnect.count()));
800  params.m_wolRetry = intResponse("Number of times to retry:",
801  params.m_wolRetry);
802  params.m_wolCommand = getResponse("Command to use to wake server or server MAC address:",
803  params.m_wolCommand);
804  }
805 
806  accepted = m_parent->SaveDatabaseParams(params);
807  }
808  return accepted;
809 }
810 
817 {
818  QString err;
819  QString host;
820 
821  // Jan 20, 2017
822  // Changed to use port check instead of ping
823 
824  int port = 0;
825 
826  // 1 = db awake, 2 = db listening, 3 = db connects,
827  // 4 = backend awake, 5 = backend listening
828  // 9 = all ok, 10 = quit
829 
830  enum startupStates {
831  st_start = 0,
832  st_dbAwake = 1,
833  st_dbStarted = 2,
834  st_dbConnects = 3,
835  st_beWOL = 4,
836  st_beAwake = 5,
837  st_success = 6
838  } startupState = st_start;
839 
840  static const std::array<const QString, 7> kGuiStatuses
841  {"start", "dbAwake", "dbStarted", "dbConnects", "beWOL", "beAwake", "success"};
842 
843  auto secondsStartupScreenDelay = gCoreContext->GetDurSetting<std::chrono::seconds>("StartupScreenDelay", 2s);
844  auto msStartupScreenDelay = std::chrono::duration_cast<std::chrono::milliseconds>(secondsStartupScreenDelay);
845  do
846  {
847  QElapsedTimer timer;
848  timer.start();
849  if (m_dbParams.m_dbHostName.isNull() && !m_dbHostCp.isEmpty())
850  host = m_dbHostCp;
851  else
852  host = m_dbParams.m_dbHostName;
853  port = m_dbParams.m_dbPort;
854  if (port == 0)
855  port = 3306;
856  std::chrono::seconds wakeupTime = 3s;
857  int attempts = 11;
859  {
860  wakeupTime = m_dbParams.m_wolReconnect;
861  attempts = m_dbParams.m_wolRetry + 1;
862  startupState = st_start;
863  }
864  else
865  startupState = st_dbAwake;
866  if (attempts < 6)
867  attempts = 6;
868  if (!prompt)
869  attempts=1;
870  if (wakeupTime < 5s)
871  wakeupTime = 5s;
872 
873  std::chrono::seconds progressTotal = wakeupTime * attempts;
874 
876  m_guiStartup->setTotal(progressTotal);
877 
878  QString beWOLCmd = QString();
879  QString backendIP = QString();
880  int backendPort = 0;
881  QString masterserver;
882 
883  for (int attempt = 0;
884  attempt < attempts && startupState != st_success;
885  ++attempt)
886  {
887  // The first time do everything with minimum timeout and
888  // no GUI, for the normal case where all is OK
889  // After that show the GUI (if this is a GUI program)
890 
891  LOG(VB_GENERAL, LOG_INFO,
892  QString("Start up testing connections. DB %1, BE %2, attempt %3, status %4, Delay: %5")
893  .arg(host, backendIP, QString::number(attempt),
894  kGuiStatuses[startupState],
895  QString::number(msStartupScreenDelay.count())) );
896 
897  std::chrono::seconds useTimeout = wakeupTime;
898  if (attempt == 0)
899  useTimeout=1s;
900 
901  if (m_gui && !m_guiStartup)
902  {
903  if (msStartupScreenDelay==0ms || timer.hasExpired(msStartupScreenDelay.count()))
904  {
905  ShowGuiStartup();
906  if (m_guiStartup)
907  m_guiStartup->setTotal(progressTotal);
908  }
909  }
911  {
912  if (attempt > 0)
913  m_guiStartup->setStatusState(kGuiStatuses[startupState]);
914  m_guiStartup->setMessageState("empty");
915  processEvents();
916  }
917  switch (startupState)
918  {
919  case st_start:
921  {
922  if (attempt > 0)
924  if (!checkPort(host, port, useTimeout))
925  break;
926  }
927  startupState = st_dbAwake;
928  [[fallthrough]];
929  case st_dbAwake:
930  if (!checkPort(host, port, useTimeout))
931  break;
932  startupState = st_dbStarted;
933  [[fallthrough]];
934  case st_dbStarted:
935  // If the database is connecting with link-local
936  // address, it may have changed
937  if (m_dbParams.m_dbHostName != host)
938  {
939  m_dbParams.m_dbHostName = host;
940  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
941  }
942  EnableDBerrors();
943  ResetDatabase();
945  {
946  for (std::chrono::seconds temp = 0s; temp < useTimeout * 2 ; temp++)
947  {
948  processEvents();
949  std::this_thread::sleep_for(500ms);
950  }
951  break;
952  }
953  startupState = st_dbConnects;
954  [[fallthrough]];
955  case st_dbConnects:
956  if (m_needsBackend)
957  {
958  beWOLCmd = gCoreContext->GetSetting("WOLbackendCommand", "");
959  if (!beWOLCmd.isEmpty())
960  {
961  wakeupTime += gCoreContext->GetDurSetting<std::chrono::seconds>
962  ("WOLbackendReconnectWaitTime", 0s);
963  attempts += gCoreContext->GetNumSetting
964  ("WOLbackendConnectRetry", 0);
965  useTimeout = wakeupTime;
966  if (m_gui && !m_guiStartup && attempt == 0)
967  useTimeout=1s;
968  progressTotal = wakeupTime * attempts;
970  m_guiStartup->setTotal(progressTotal);
971  startupState = st_beWOL;
972  }
973  }
974  else
975  {
976  startupState = st_success;
977  break;
978  }
979  masterserver = gCoreContext->GetSetting
980  ("MasterServerName");
981  backendIP = gCoreContext->GetSettingOnHost
982  ("BackendServerAddr", masterserver);
983  backendPort = MythCoreContext::GetMasterServerPort();
984  [[fallthrough]];
985  case st_beWOL:
986  if (!beWOLCmd.isEmpty())
987  {
988  if (attempt > 0)
989  MythWakeup(beWOLCmd);
990  if (!checkPort(backendIP, backendPort, useTimeout))
991  break;
992  }
993  startupState = st_beAwake;
994  [[fallthrough]];
995  case st_beAwake:
996  if (!checkPort(backendIP, backendPort, useTimeout))
997  break;
998  startupState = st_success;
999  [[fallthrough]];
1000  case st_success:
1001  // Quiet compiler warning.
1002  break;
1003  }
1004  if (m_guiStartup)
1005  {
1006  if (m_guiStartup->m_Exit
1007  || m_guiStartup->m_Setup
1009  || m_guiStartup->m_Retry)
1010  break;
1011  }
1012  processEvents();
1013  }
1014  if (startupState == st_success)
1015  break;
1016 
1017  QString stateMsg = kGuiStatuses[startupState];
1018  stateMsg.append("Fail");
1019  LOG(VB_GENERAL, LOG_INFO,
1020  QString("Start up failure. host %1, status %2")
1021  .arg(host, stateMsg));
1022 
1023  if (m_gui && !m_guiStartup)
1024  {
1025  ShowGuiStartup();
1026  if (m_guiStartup)
1027  m_guiStartup->setTotal(progressTotal);
1028  }
1029 
1030  if (m_guiStartup
1031  && !m_guiStartup->m_Exit
1032  && !m_guiStartup->m_Setup
1033  && !m_guiStartup->m_Search
1034  && !m_guiStartup->m_Retry)
1035  {
1037  m_guiStartup->setStatusState(stateMsg);
1038  m_guiStartup->setMessageState("makeselection");
1039  m_loop->exec();
1040  }
1041  }
1042  while (m_guiStartup && m_guiStartup->m_Retry);
1043 
1044  if (startupState < st_dbAwake)
1045  {
1046  LOG(VB_GENERAL, LOG_WARNING, QString("Pinging to %1 failed, database will be unavailable").arg(host));
1047  SilenceDBerrors();
1048  err = QObject::tr(
1049  "Cannot find (ping) database host %1 on the network",
1050  "Backend Setup");
1051  return err.arg(host);
1052  }
1053 
1054  if (startupState < st_dbConnects)
1055  {
1056  SilenceDBerrors();
1057  return QObject::tr("Cannot login to database", "Backend Setup");
1058  }
1059 
1060  if (startupState < st_success)
1061  {
1062  return QObject::tr("Cannot connect to backend", "Backend Setup");
1063  }
1064 
1065  // Current DB connection may have been silenced (invalid):
1066  EnableDBerrors();
1067  ResetDatabase();
1068 
1069  return {};
1070 }
1071 
1072 // Show the Gui Startup window.
1073 // This is called if there is a delay in startup for any reason
1074 // such as the database being unavailable
1076 {
1077  if (!m_gui)
1078  return;
1079  TempMainWindow(false);
1080  MythMainWindow *mainWindow = GetMythMainWindow();
1081  MythScreenStack *mainStack = mainWindow->GetMainStack();
1082  if (mainStack)
1083  {
1084  if (!m_guiStartup)
1085  {
1086  m_guiStartup = new GUIStartup(mainStack, m_loop);
1087  if (!m_guiStartup->Create())
1088  {
1089  delete m_guiStartup;
1090  m_guiStartup = nullptr;
1091  }
1092  if (m_guiStartup)
1093  {
1094  mainStack->AddScreen(m_guiStartup, false);
1095  processEvents();
1096  }
1097  }
1098  }
1099 }
1100 
1110 {
1111  // This silences any DB errors from Get*Setting(),
1112  // (which is the vast majority of them)
1113  gCoreContext->GetDB()->SetSuppressDBMessages(true);
1114 
1115  // Save the configured hostname, so that we can
1116  // still display it in the DatabaseSettings screens
1117  if (!m_dbParams.m_dbHostName.isEmpty())
1119 
1120  m_dbParams.m_dbHostName.clear();
1121  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
1122 }
1123 
1125 {
1126  // Restore (possibly) blanked hostname
1127  if (m_dbParams.m_dbHostName.isNull() && !m_dbHostCp.isEmpty())
1128  {
1130  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
1131  }
1132 
1133  gCoreContext->GetDB()->SetSuppressDBMessages(false);
1134 }
1135 
1136 
1149 {
1151  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
1153 }
1154 
1159 {
1160  TempMainWindow();
1161 
1162  // Tell the user what went wrong:
1163  if (!error.isEmpty())
1164  {
1165  LOG(VB_GENERAL, LOG_ERR, QString("Error: %1").arg(error));
1166  ShowOkPopup(error);
1167  }
1168 
1169  LOG(VB_GENERAL, LOG_INFO, "Putting up the UPnP backend chooser");
1170 
1173  // TODO encapuslation: don't use a pointer
1174 
1175  EndTempWindow();
1176 
1177  return ret;
1178 }
1179 
1186 int MythContextPrivate::UPnPautoconf(const std::chrono::milliseconds milliSeconds)
1187 {
1188  auto seconds = duration_cast<std::chrono::seconds>(milliSeconds);
1189  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search %1 secs")
1190  .arg(seconds.count()));
1191 
1193 
1194  // Search for a total of 'milliSeconds' ms, sending new search packet
1195  // about every 250 ms until less than one second remains.
1196  MythTimer totalTime; totalTime.start();
1197  MythTimer searchTime; searchTime.start();
1198  while (totalTime.elapsed() < milliSeconds)
1199  {
1200  usleep(25000);
1201  auto ttl = milliSeconds - totalTime.elapsed();
1202  if ((searchTime.elapsed() > 249ms) && (ttl > 1s))
1203  {
1204  auto ttlSeconds = duration_cast<std::chrono::seconds>(ttl);
1205  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search %1 secs")
1206  .arg(ttlSeconds.count()));
1207  SSDP::Instance()->PerformSearch(kBackendURI, ttlSeconds);
1208  searchTime.start();
1209  }
1210  }
1211 
1213 
1214  if (!backends)
1215  {
1216  LOG(VB_GENERAL, LOG_INFO, "No UPnP backends found");
1217  return 0;
1218  }
1219 
1220  int count = backends->Count();
1221  if (count)
1222  {
1223  LOG(VB_GENERAL, LOG_INFO,
1224  QString("Found %1 UPnP backends").arg(count));
1225  }
1226  else
1227  {
1228  LOG(VB_GENERAL, LOG_ERR,
1229  "No UPnP backends found, but SSDP::Find() not NULL");
1230  }
1231 
1232  if (count != 1)
1233  {
1234  backends->DecrRef();
1235  return count;
1236  }
1237 
1238  // Get this backend's location:
1239  DeviceLocation *BE = backends->GetFirst();
1240  backends->DecrRef();
1241  backends = nullptr;
1242 
1243  // We don't actually know the backend's access PIN, so this will
1244  // only work for ones that have PIN access disabled (i.e. 0000)
1245  int ret = (UPnPconnect(BE, QString())) ? 1 : -1;
1246 
1247  BE->DecrRef();
1248 
1249  return ret;
1250 }
1251 
1258 {
1259  static const QString loc = "DefaultUPnP() - ";
1260 
1261  // potentially saved in backendselect
1262  QString pin;
1263  QString usn;
1264  {
1265  auto config = XmlConfiguration(); // read-only
1266  pin = config.GetValue(kDefaultPIN, QString(""));
1267  usn = config.GetValue(kDefaultUSN, QString(""));
1268  }
1269 
1270  if (usn.isEmpty())
1271  {
1272  LOG(VB_UPNP, LOG_INFO, loc + "No default UPnP backend");
1273  return false;
1274  }
1275 
1276  LOG(VB_UPNP, LOG_INFO,
1277  loc + QString(XmlConfiguration::kDefaultFilename) +
1278  QString(" has default PIN '%1' and host USN: %2").arg(pin, usn));
1279 
1280  // ----------------------------------------------------------------------
1281 
1282  std::chrono::milliseconds timeout_ms {2s};
1283  auto timeout_s = duration_cast<std::chrono::seconds>(timeout_ms);
1284  LOG(VB_GENERAL, LOG_INFO, loc + QString("UPNP Search up to %1 secs")
1285  .arg(timeout_s.count()));
1286  SSDP::Instance()->PerformSearch(kBackendURI, timeout_s);
1287 
1288  // ----------------------------------------------------------------------
1289  // We need to give the server time to respond...
1290  // ----------------------------------------------------------------------
1291 
1292  DeviceLocation* devicelocation = nullptr;
1293  MythTimer totalTime;
1294  MythTimer searchTime;
1295  totalTime.start();
1296  searchTime.start();
1297  while (totalTime.elapsed() < timeout_ms)
1298  {
1299  devicelocation = SSDP::Find(kBackendURI, usn);
1300  if (devicelocation)
1301  break;
1302 
1303  usleep(25000);
1304 
1305  auto ttl = timeout_ms - totalTime.elapsed();
1306  if ((searchTime.elapsed() > 249ms) && (ttl > 1s))
1307  {
1308  auto ttlSeconds = duration_cast<std::chrono::seconds>(ttl);
1309  LOG(VB_GENERAL, LOG_INFO, loc + QString("UPNP Search up to %1 secs")
1310  .arg(ttlSeconds.count()));
1311  SSDP::Instance()->PerformSearch(kBackendURI, ttlSeconds);
1312  searchTime.start();
1313  }
1314  }
1315 
1316  // ----------------------------------------------------------------------
1317 
1318  if (!devicelocation)
1319  {
1320  Error = "Cannot find default UPnP backend";
1321  return false;
1322  }
1323 
1324  if (UPnPconnect(devicelocation, pin))
1325  {
1326  devicelocation->DecrRef();
1327  return true;
1328  }
1329 
1330  devicelocation->DecrRef();
1331  Error = "Cannot connect to default backend via UPnP. Wrong saved PIN?";
1332  return false;
1333 }
1334 
1339  const QString &PIN)
1340 {
1341  QString error;
1342  QString loc = "UPnPconnect() - ";
1343  QString URL = backend->m_sLocation;
1344  MythXMLClient client(URL);
1345 
1346  LOG(VB_UPNP, LOG_INFO, loc + QString("Trying host at %1").arg(URL));
1347  switch (client.GetConnectionInfo(PIN, &m_dbParams, error))
1348  {
1349  case UPnPResult_Success:
1350  gCoreContext->GetDB()->SetDatabaseParams(m_dbParams);
1351  LOG(VB_UPNP, LOG_INFO, loc +
1352  "Got database hostname: " + m_dbParams.m_dbHostName);
1353  return true;
1354 
1356  // The stored PIN is probably not correct.
1357  // We could prompt for the PIN and try again, but that needs a UI.
1358  // Easier to fail for now, and put up the full UI selector later
1359  LOG(VB_UPNP, LOG_ERR, loc + "Wrong PIN?");
1360  return false;
1361 
1362  default:
1363  LOG(VB_UPNP, LOG_ERR, loc + error);
1364  break;
1365  }
1366 
1367  // This backend may have a local DB with the default user/pass/DBname.
1368  // For whatever reason, we have failed to get anything back via UPnP,
1369  // so we might as well try the database directly as a last resort.
1370  QUrl theURL(URL);
1371  URL = theURL.host();
1372  if (URL.isEmpty())
1373  return false;
1374 
1375  LOG(VB_UPNP, LOG_INFO, "Trying default DB credentials at " + URL);
1376  m_dbParams.m_dbHostName = URL;
1377 
1378  return true;
1379 }
1380 
1382 {
1383  if (e->type() == MythEvent::kMythEventMessage)
1384  {
1385  if (m_disableeventpopup)
1386  return true;
1387 
1389  {
1391  }
1392 
1393  auto *me = dynamic_cast<MythEvent*>(e);
1394  if (me == nullptr)
1395  return true;
1396 
1397  if (me->Message() == "VERSION_MISMATCH" && (1 == me->ExtraDataCount()))
1398  ShowVersionMismatchPopup(me->ExtraData(0).toUInt());
1399  else if (me->Message() == "CONNECTION_FAILURE")
1401  else if (me->Message() == "PERSISTENT_CONNECTION_FAILURE")
1403  else if (me->Message() == "CONNECTION_RESTABLISHED")
1405  return true;
1406  }
1407 
1408  return QObject::event(e);
1409 }
1410 
1412 {
1413  QDateTime now = MythDate::current();
1414 
1415  if (!GetNotificationCenter() || !m_ui || !m_ui->IsScreenSetup())
1416  return;
1417 
1418  if (m_lastCheck.isValid() && now < m_lastCheck)
1419  return;
1420 
1421  // When WOL is disallowed, standy mode,
1422  // we should not show connection failures.
1423  if (!gCoreContext->IsWOLAllowed())
1424  return;
1425 
1426  m_lastCheck = now.addMSecs(5000); // don't refresh notification more than every 5s
1427 
1428  QString description = (persistent) ?
1429  QObject::tr(
1430  "The connection to the master backend "
1431  "server has gone away for some reason. "
1432  "Is it running?") :
1433  QObject::tr(
1434  "Could not connect to the master backend server. Is "
1435  "it running? Is the IP address set for it in "
1436  "mythtv-setup correct?");
1437 
1438  QString message = QObject::tr("Could not connect to master backend");
1439  MythErrorNotification n(message, sLocation, description);
1440  n.SetId(m_registration);
1441  n.SetParent(this);
1443 }
1444 
1446 {
1447  if (!GetNotificationCenter())
1448  return;
1449 
1450  if (!m_lastCheck.isValid())
1451  return;
1452 
1453  MythCheckNotification n(QObject::tr("Backend is online"), sLocation);
1454  n.SetId(m_registration);
1455  n.SetParent(this);
1456  n.SetDuration(5s);
1458  m_lastCheck = QDateTime();
1459 }
1460 
1462 {
1463  if (m_mbeVersionPopup)
1464  return;
1465 
1466  QString message =
1467  QObject::tr(
1468  "The server uses network protocol version %1, "
1469  "but this client only understands version %2. "
1470  "Make sure you are running compatible versions of "
1471  "the backend and frontend.")
1472  .arg(remote_version).arg(MYTH_PROTO_VERSION);
1473 
1474  if (HasMythMainWindow() && m_ui && m_ui->IsScreenSetup())
1475  {
1478  }
1479  else
1480  {
1481  LOG(VB_GENERAL, LOG_ERR, LOC + message);
1482  qApp->exit(GENERIC_EXIT_SOCKET_ERROR);
1483  }
1484 }
1485 
1486 // Process Events while waiting for connection
1487 // return true if progress is 100%
1489 {
1490 // bool ret = false;
1491 // if (m_guiStartup)
1492 // ret = m_guiStartup->updateProgress();
1493  qApp->processEvents(QEventLoop::AllEvents, 250);
1494  qApp->processEvents(QEventLoop::AllEvents, 250);
1495 // return ret;
1496 }
1497 
1498 namespace
1499 {
1500 // cache some settings in GUISettingsCache::m_cacheFilename
1501 // only call this if the database is available.
1502 
1503 const std::array<QString, 13> GUISettingsCache::kSettings
1504 { "Theme", "Language", "Country", "GuiHeight",
1505  "GuiOffsetX", "GuiOffsetY", "GuiWidth", "RunFrontendInWindow",
1506  "AlwaysOnTop", "HideMouseCursor", "ThemePainter", "libCECEnabled",
1507  "StartupScreenDelay" };
1508 
1509 
1510 bool GUISettingsCache::save()
1511 {
1512  QString cacheDirName = GetConfDir() + '/' + m_cachePath;
1513  QDir dir(cacheDirName);
1514  dir.mkpath(cacheDirName);
1515  XmlConfiguration config = XmlConfiguration(m_cacheFilename);
1516  bool dirty = false;
1517  for (const auto & setting : kSettings)
1518  {
1519  QString cacheValue = config.GetValue("Settings/" + setting, QString());
1521  QString value = gCoreContext->GetSetting(setting, QString());
1522  if (value != cacheValue)
1523  {
1524  config.SetValue("Settings/" + setting, value);
1525  dirty = true;
1526  }
1527  }
1528  clearOverrides();
1529 
1530  if (dirty)
1531  {
1532 #ifndef Q_OS_ANDROID
1534 #endif
1535  return config.Save();
1536  }
1537  return true;
1538 }
1539 
1540 void GUISettingsCache::loadOverrides() const
1541 {
1542  auto config = XmlConfiguration(m_cacheFilename); // read only
1543  for (const auto & setting : kSettings)
1544  {
1545  if (!gCoreContext->GetSetting(setting, QString()).isEmpty())
1546  continue;
1547  QString value = config.GetValue("Settings/" + setting, QString());
1548  if (!value.isEmpty())
1549  gCoreContext->OverrideSettingForSession(setting, value);
1550  }
1551  // Prevent power off TV after temporary window
1552  gCoreContext->OverrideSettingForSession("PowerOffTVAllowed", nullptr);
1553 
1554  MythTranslation::load("mythfrontend");
1555 }
1556 
1557 void GUISettingsCache::clearOverrides()
1558 {
1559  QString language = gCoreContext->GetSetting("Language", QString());
1560  for (const auto & setting : kSettings)
1562  // Restore power off TV setting
1563  gCoreContext->ClearOverrideSettingForSession("PowerOffTVAllowed");
1564 
1565  if (language != gCoreContext->GetSetting("Language", QString()))
1566  MythTranslation::load("mythfrontend");
1567 }
1568 
1569 } // anonymous namespace
1570 
1572 {
1573  d->m_mbeVersionPopup = nullptr;
1574  qApp->exit(GENERIC_EXIT_SOCKET_ERROR);
1575 }
1576 
1577 MythContext::MythContext(QString binversion, bool needsBackend)
1578  : m_appBinaryVersion(std::move(binversion))
1579 {
1580 #ifdef _WIN32
1581  static bool WSAStarted = false;
1582  if (!WSAStarted)
1583  {
1584  WSADATA wsadata;
1585  int res = WSAStartup(MAKEWORD(2, 0), &wsadata);
1586  LOG(VB_SOCKET, LOG_INFO,
1587  QString("WSAStartup returned %1").arg(res));
1588  }
1589 #endif
1590 
1591  d = new MythContextPrivate(this);
1592  d->m_needsBackend = needsBackend;
1593 
1595 
1596  if (!gCoreContext || !gCoreContext->Init())
1597  {
1598  LOG(VB_GENERAL, LOG_EMERG, LOC + "Unable to allocate MythCoreContext");
1599  qApp->exit(GENERIC_EXIT_NO_MYTHCONTEXT);
1600  }
1601 }
1602 
1603 bool MythContext::Init(const bool gui,
1604  const bool promptForBackend,
1605  const bool disableAutoDiscovery,
1606  const bool ignoreDB)
1607 {
1608  if (!d)
1609  {
1610  LOG(VB_GENERAL, LOG_EMERG, LOC + "Init() Out-of-memory");
1611  return false;
1612  }
1613 
1614  qRegisterMetaType<std::chrono::seconds>("std::chrono::seconds");
1615  qRegisterMetaType<std::chrono::milliseconds>("std::chrono::milliseconds");
1616  qRegisterMetaType<std::chrono::microseconds>("std::chrono::microseconds");
1617 
1618  SetDisableEventPopup(true);
1619 
1620  if (gui && QCoreApplication::applicationName() == MYTH_APPNAME_MYTHTV_SETUP)
1621  {
1622  d->TempMainWindow(false);
1623  QString warning = QObject::tr("mythtv-setup is deprecated.\n"
1624  "To set up MythTV, start mythbackend and use:\n"
1625  "http://localhost:6544/setupwizard");
1626  WaitFor(ShowOkPopup(warning));
1627  }
1628 
1629  if (m_appBinaryVersion != MYTH_BINARY_VERSION)
1630  {
1631  LOG(VB_GENERAL, LOG_EMERG,
1632  QString("Application binary version (%1) does not "
1633  "match libraries (%2)")
1634  .arg(m_appBinaryVersion, MYTH_BINARY_VERSION));
1635 
1636  QString warning = QObject::tr(
1637  "This application is not compatible "
1638  "with the installed MythTV libraries.");
1639  if (gui)
1640  {
1641  d->TempMainWindow(false);
1642  WaitFor(ShowOkPopup(warning));
1643  }
1644  LOG(VB_GENERAL, LOG_WARNING, warning);
1645 
1646  return false;
1647  }
1648 
1649 #ifdef _WIN32
1650  // HOME environment variable might not be defined
1651  // some libraries will fail without it
1652  QString home = getenv("HOME");
1653  if (home.isEmpty())
1654  {
1655  home = getenv("LOCALAPPDATA"); // Vista
1656  if (home.isEmpty())
1657  home = getenv("APPDATA"); // XP
1658  if (home.isEmpty())
1659  home = QString("."); // getenv("TEMP")?
1660 
1661  _putenv(QString("HOME=%1").arg(home).toLocal8Bit().constData());
1662  }
1663 #endif
1664 
1665  // If HOME isn't defined, we won't be able to use default confdir of
1666  // $HOME/.mythtv nor can we rely on a MYTHCONFDIR that references $HOME
1667  QString homedir = QDir::homePath();
1668  QString confdir = qEnvironmentVariable("MYTHCONFDIR");
1669  if ((homedir.isEmpty() || homedir == "/") &&
1670  (confdir.isEmpty() || confdir.contains("$HOME")))
1671  {
1672  QString warning = "Cannot locate your home directory."
1673  " Please set the environment variable HOME";
1674  if (gui)
1675  {
1676  d->TempMainWindow(false);
1677  WaitFor(ShowOkPopup(warning));
1678  }
1679  LOG(VB_GENERAL, LOG_WARNING, warning);
1680 
1681  return false;
1682  }
1683 
1684  if (!d->Init(gui, promptForBackend, disableAutoDiscovery, ignoreDB))
1685  {
1686  return false;
1687  }
1688 
1689  SetDisableEventPopup(false);
1690 
1691  if (d->m_gui)
1692  {
1694  }
1695 
1698 
1699  return true;
1700 }
1701 
1703 {
1704  gCoreContext->InitPower(false /*destroy*/);
1705  if (MThreadPool::globalInstance()->activeThreadCount())
1706  LOG(VB_GENERAL, LOG_INFO, "Waiting for threads to exit.");
1707 
1709  SSDP::Shutdown();
1711 
1712  LOG(VB_GENERAL, LOG_INFO, "Exiting");
1713 
1714  logStop();
1715 
1716  delete gCoreContext;
1717  gCoreContext = nullptr;
1718 
1719  delete d;
1720 }
1721 
1723 {
1724  d->m_disableeventpopup = check;
1725 }
1726 
1728 {
1729  return d->SaveDatabaseParams(params, force);
1730 }
1731 
1733 {
1734  /* this check is technically redundant since this is only called from
1735  MythContext::Init() and mythfrontend::main(); however, it is for safety
1736  and clarity until MythGUIContext is refactored out.
1737  */
1738  if (d->m_gui)
1739  {
1740  return d->m_GUISettingsCache.save();
1741  }
1742  return true;
1743 }
1744 
1745 /* vim: set expandtab tabstop=4 shiftwidth=4: */
MythContextPrivate::ShowConnectionFailurePopup
void ShowConnectionFailurePopup(bool persistent)
Definition: mythcontext.cpp:1411
WaitFor
bool WaitFor(MythConfirmationDialog *dialog)
Blocks until confirmation dialog exits.
Definition: mythdialogbox.cpp:599
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:318
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:1577
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:967
MythContextSlotHandler::VersionMismatchPopupClosed
void VersionMismatchPopupClosed(void)
Definition: mythcontext.cpp:1571
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:642
QAndroidJniEnvironment
#define QAndroidJniEnvironment
Definition: audiooutputaudiotrack.cpp:8
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:1381
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:1371
MythContextPrivate::UPnPautoconf
int UPnPautoconf(std::chrono::milliseconds milliSeconds=2s)
If there is only a single UPnP backend, use it.
Definition: mythcontext.cpp:1186
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:1257
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:865
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:1850
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:1337
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
MythContext::SetDisableEventPopup
void SetDisableEventPopup(bool check)
Definition: mythcontext.cpp:1722
MythContextPrivate::TestDBconnection
QString TestDBconnection(bool prompt=true)
Some quick sanity checks before opening a database connection.
Definition: mythcontext.cpp:816
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:1727
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:277
MythContextPrivate::UPnPconnect
bool UPnPconnect(const DeviceLocation *backend, const QString &PIN)
Query a backend via UPnP for its database connection parameters.
Definition: mythcontext.cpp:1338
DatabaseSettings::isClosing
void isClosing(void)
MythContextPrivate::ShowVersionMismatchPopup
void ShowVersionMismatchPopup(uint remote_version)
Definition: mythcontext.cpp:1461
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:351
mythdirs.h
force
bool force
Definition: mythcommflag.cpp:70
MythContextPrivate::ShowGuiStartup
void ShowGuiStartup(void)
Definition: mythcontext.cpp:1075
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
HasMythMainWindow
bool HasMythMainWindow(void)
Definition: mythmainwindow.cpp:109
MythCoreContext::InitPower
void InitPower(bool Create=true)
Definition: mythcorecontext.cpp:1837
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:1124
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:264
MythCoreContext::ClearOverrideSettingForSession
void ClearOverrideSettingForSession(const QString &key)
Definition: mythcorecontext.cpp:1343
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
MDBManager::CloseDatabases
void CloseDatabases(void)
Definition: mythdbcon.cpp:484
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:220
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:256
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:325
configplugin_cb
static void configplugin_cb(const QString &cmd)
Definition: mythcontext.cpp:237
MThreadPool::waitForDone
void waitForDone(void)
Definition: mthreadpool.cpp:565
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:106
GENERIC_EXIT_SOCKET_ERROR
@ GENERIC_EXIT_SOCKET_ERROR
Socket error.
Definition: exitcodes.h:19
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:877
MythContextPrivate::MythContextPrivate
MythContextPrivate(MythContext *lparent)
Definition: mythcontext.cpp:269
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:654
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:410
MythCoreContext::GetDB
MythDB * GetDB(void)
Definition: mythcorecontext.cpp:1753
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:658
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:723
TaskQueue::Shutdown
static void Shutdown()
Definition: taskqueue.cpp:69
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
UPnPResult_ActionNotAuthorized
@ UPnPResult_ActionNotAuthorized
Definition: upnp.h:48
MythContextPrivate::m_ui
MythUIHelper * m_ui
Definition: mythcontext.cpp:156
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:912
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:1726
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:250
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:1109
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:980
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:437
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:564
MythContextPrivate::Init
bool Init(bool gui, bool promptForBackend, bool disableAutoDiscovery, bool ignoreDB)
Definition: mythcontext.cpp:360
MythCoreContext::IsBackend
bool IsBackend(void) const
is this process a backend process
Definition: mythcorecontext.cpp:644
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:1445
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:926
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
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: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:1158
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:302
MythCoreContext::ActivateSettingsCache
void ActivateSettingsCache(bool activate=true)
Definition: mythcorecontext.cpp:833
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:1148
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:711
MythContextPrivate::m_needsBackend
bool m_needsBackend
Definition: mythcontext.cpp:160
MythContextPrivate::processEvents
static void processEvents(void)
Definition: mythcontext.cpp:1488
GUIStartup::m_Setup
bool m_Setup
Definition: guistartup.h:58
MythCoreContext::ClearSettingsCache
void ClearSettingsCache(const QString &myKey=QString(""))
Definition: mythcorecontext.cpp:828
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:152
MythCoreContext::IsWOLAllowed
bool IsWOLAllowed() const
Definition: mythcorecontext.cpp:634
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:307
MythCoreContext::GetPluginManager
MythPluginManager * GetPluginManager(void)
Definition: mythcorecontext.cpp:2107
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
MythCoreContext::SaveLocaleDefaults
void SaveLocaleDefaults(void)
Definition: mythcorecontext.cpp:1882
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: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:245
MythContext::Init
bool Init(bool gui=true, bool promptForBackend=false, bool disableAutoDiscovery=false, bool ignoreDB=false)
Definition: mythcontext.cpp:1603
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:1732
DestroyMythUI
void DestroyMythUI()
Definition: mythuihelper.cpp:71
GUIStartup::cancelPortCheck
void cancelPortCheck(void)
MythContext::~MythContext
virtual ~MythContext()
Definition: mythcontext.cpp:1702
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:898
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