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