MythTV  master
mythcontext.cpp
Go to the documentation of this file.
1 #include <QCoreApplication>
2 #include <QDir>
3 #include <QFileInfo>
4 #include <QDebug>
5 #include <QMutex>
6 #include <QDateTime>
7 #include <QTcpSocket>
8 #include <QEventLoop>
9 
10 #include <cmath>
11 #include <iostream>
12 
13 #include <queue>
14 #include <algorithm>
15 #include <thread>
16 
17 using namespace std;
18 
19 #include "config.h"
20 #include "mythcontext.h"
21 #include "exitcodes.h"
22 #include "mythdate.h"
23 #include "remotefile.h"
24 #include "backendselect.h"
25 #include "dbsettings.h"
26 #include "langsettings.h"
27 #include "mythtranslation.h"
28 #include "mythxdisplay.h"
29 #include "mythevent.h"
30 #include "dbutil.h"
31 #include "DisplayRes.h"
32 #include "mythmediamonitor.h"
33 
34 #include "mythdb.h"
35 #include "mythdirs.h"
36 #include "mythversion.h"
37 #include "mythdialogbox.h"
38 #include "mythmainwindow.h"
39 #include "mythuihelper.h"
40 #include "mythimage.h"
41 #include "mythxmlclient.h"
42 #include "upnp.h"
43 #include "mythlogging.h"
44 #include "mythsystemlegacy.h"
45 #include "mythmiscutil.h"
46 
47 #include "mythplugin.h"
48 #include "portchecker.h"
49 #include "guistartup.h"
50 
51 #include <unistd.h> // for usleep(), gethostname
52 
53 #ifdef _WIN32
54 #include "compat.h"
55 #endif
56 
57 #define LOC QString("MythContext: ")
58 
60 
61 static const QString _Location = "MythContext";
62 
63 class MythContextPrivate : public QObject
64 {
65  friend class MythContextSlotHandler;
66 
67  public:
70 
71  bool Init (const bool gui,
72  const bool prompt, const bool noPrompt,
73  const bool ignoreDB);
74  bool FindDatabase(const bool prompt, const bool noPrompt);
75 
76  void TempMainWindow(bool languagePrompt = true);
77  void EndTempWindow(void);
78 
79  bool LoadDatabaseSettings(void);
80  bool SaveDatabaseParams(const DatabaseParams &params, bool force);
81 
82  bool PromptForDatabaseParams(const QString &error);
83  QString TestDBconnection(bool prompt=true);
84  void SilenceDBerrors(void);
85  void EnableDBerrors(void);
86  void ResetDatabase(void);
87 
88  int ChooseBackend(const QString &error);
89  int UPnPautoconf(const int milliSeconds = 2000);
90  bool DefaultUPnP(QString &error);
91  bool UPnPconnect(const DeviceLocation *device, const QString &PIN);
92  void ShowGuiStartup(void);
93  bool checkPort(QString &host, int port, int wakeupTime);
94  void processEvents(void);
95  bool saveSettingsCache(void);
96  void loadSettingsCacheOverride(void);
97  void clearSettingsCacheOverride(void);
98 
99 
100  protected:
101  bool event(QEvent*);
102 
103  void ShowConnectionFailurePopup(bool persistent);
104  void HideConnectionFailurePopup(void);
105 
106  void ShowVersionMismatchPopup(uint remoteVersion);
107 
108  public slots:
109  void OnCloseDialog();
110 
111  public:
113 
114  bool m_gui;
115 
117 
119  QString m_DBhostCp;
120 
122 
124 
128  QEventLoop *m_loop;
131 
132  private:
135  QDateTime m_lastCheck;
136  QTcpSocket *m_socket;
137  static const QString settingsToSave[];
138 };
139 
140 static void exec_program_cb(const QString &cmd)
141 {
142  myth_system(cmd);
143 }
144 
145 static void exec_program_tv_cb(const QString &cmd)
146 {
147  QString s = cmd;
148  QStringList tokens = cmd.simplified().split(" ");
149  QStringList strlist;
150 
151  bool cardidok;
152  int wantcardid = tokens[0].toInt(&cardidok, 10);
153 
154  if (cardidok && wantcardid > 0)
155  {
156  strlist << QString("LOCK_TUNER %1").arg(wantcardid);
157  s = s.replace(0, tokens[0].length() + 1, "");
158  }
159  else
160  strlist << "LOCK_TUNER";
161 
163  int cardid = strlist[0].toInt();
164 
165  if (cardid >= 0)
166  {
167  s = s.sprintf(qPrintable(s),
168  qPrintable(strlist[1]),
169  qPrintable(strlist[2]),
170  qPrintable(strlist[3]));
171 
172  myth_system(s);
173 
174  strlist = QStringList(QString("FREE_TUNER %1").arg(cardid));
176  QString ret = strlist[0];
177  }
178  else
179  {
180  QString label;
181 
182  if (cardidok)
183  {
184  if (cardid == -1)
185  label = QObject::tr("Could not find specified tuner (%1).")
186  .arg(wantcardid);
187  else
188  label = QObject::tr("Specified tuner (%1) is already in use.")
189  .arg(wantcardid);
190  }
191  else
192  {
193  label = QObject::tr("All tuners are currently in use. If you want "
194  "to watch TV, you can cancel one of the "
195  "in-progress recordings from the delete menu");
196  }
197 
198  LOG(VB_GENERAL, LOG_ALERT, QString("exec_program_tv: ") + label);
199 
200  ShowOkPopup(label);
201  }
202 }
203 
204 static void configplugin_cb(const QString &cmd)
205 {
207  if (!pmanager)
208  return;
209 
210  if (GetNotificationCenter() && pmanager->config_plugin(cmd.trimmed()))
211  {
213  QObject::tr("Failed to configure plugin"));
214  }
215 }
216 
217 static void plugin_cb(const QString &cmd)
218 {
220  if (!pmanager)
221  return;
222 
223  if (GetNotificationCenter() && pmanager->run_plugin(cmd.trimmed()))
224  {
225  ShowNotificationError(QObject::tr("Plugin failure"),
226  _Location,
227  QObject::tr("%1 failed to run for some reason").arg(cmd));
228  }
229 }
230 
231 static void eject_cb(void)
232 {
234 }
235 
237  : parent(lparent),
238  m_gui(false),
239  m_pConfig(NULL),
240  disableeventpopup(false),
241  m_ui(NULL),
242  m_sh(new MythContextSlotHandler(this)),
243  m_guiStartup(0),
244  needsBackend(false),
245  m_settingsCacheDirty(false),
246  MBEversionPopup(NULL),
247  m_registration(-1),
248  m_socket(0)
249 {
250  m_loop = new QEventLoop(this);
252 }
253 
255 {
256  if (m_pConfig)
257  delete m_pConfig;
259  {
261  }
262 
263  if (m_loop)
264  {
265  delete m_loop;
266  }
267 
268  if (m_ui)
269  DestroyMythUI();
270  if (m_sh)
271  m_sh->deleteLater();
272 }
273 
284 void MythContextPrivate::TempMainWindow(bool languagePrompt)
285 {
286  if (HasMythMainWindow())
287  return;
288 
289  SilenceDBerrors();
290 
292 
293 #ifdef Q_OS_MAC
294  // Qt 4.4 has window-focus problems
295  gCoreContext->OverrideSettingForSession("RunFrontendInWindow", "1");
296 #endif
297  GetMythUI()->Init();
298  GetMythUI()->LoadQtConfig();
299 
300  MythMainWindow *mainWindow = MythMainWindow::getMainWindow(false);
301  mainWindow->Init();
302 
303  if (languagePrompt)
304  {
305  // ask user for language settings
307  MythTranslation::load("mythfrontend");
308  }
309 }
310 
312 {
313  if (HasMythMainWindow())
314  {
316  {
318  if (mainStack) {
319  mainStack->PopScreen(m_guiStartup, false);
320  m_guiStartup = 0;
321  }
322  }
323  }
324  EnableDBerrors();
325 }
326 
334 bool MythContextPrivate::checkPort(QString &host, int port, int timeLimit)
335 {
336  PortChecker checker;
337  if (m_guiStartup)
338  QObject::connect(m_guiStartup,SIGNAL(cancelPortCheck()),&checker,SLOT(cancelPortCheck()));
339  return checker.checkPort(host, port, timeLimit*1000);
340 }
341 
342 
343 bool MythContextPrivate::Init(const bool gui,
344  const bool promptForBackend,
345  const bool noPrompt,
346  const bool ignoreDB)
347 {
348  gCoreContext->GetDB()->IgnoreDatabase(ignoreDB);
349  m_gui = gui;
350 
351  if (gCoreContext->IsFrontend())
352  needsBackend = true;
353 
354  // We don't have a database yet, so lets use the config.xml file.
355  m_pConfig = new XmlConfiguration("config.xml");
356 
357  // Creates screen saver control if we will have a GUI
358  if (gui)
359  m_ui = GetMythUI();
360 
361  // ---- database connection stuff ----
362 
363  if (!ignoreDB && !FindDatabase(promptForBackend, noPrompt))
364  {
365  EndTempWindow();
366  return false;
367  }
368 
369  // ---- keep all DB-using stuff below this line ----
370 
371  // Prompt for language if this is a first time install and
372  // we didn't already do so.
373  if (m_gui && !gCoreContext->GetDB()->HaveSchema())
374  {
375  TempMainWindow(false);
377  MythTranslation::load("mythfrontend");
378  }
381 
382  // Close GUI Startup Window.
383  if (m_guiStartup) {
385  if (mainStack)
386  mainStack->PopScreen(m_guiStartup, false);
387  m_guiStartup=0;
388  }
389  EndTempWindow();
390 
391  if (gui)
392  {
397  cbs.plugin = plugin_cb;
398  cbs.eject = eject_cb;
399 
400  m_ui->Init(cbs);
401  }
402 
403  return true;
404 }
405 
418 bool MythContextPrivate::FindDatabase(bool prompt, bool noAutodetect)
419 {
420  // We can only prompt if autodiscovery is enabled..
421  bool manualSelect = prompt && !noAutodetect;
422 
423  QString failure;
424 
425  // 1. Either load config.xml or use sensible "localhost" defaults:
426  bool loaded = LoadDatabaseSettings();
427  DatabaseParams dbParamsFromFile = m_DBparams;
428 
429  // In addition to the UI chooser, we can also try to autoSelect later,
430  // but only if we're not doing manualSelect and there was no
431  // valid config.xml
432  bool autoSelect = !manualSelect && !loaded && !noAutodetect;
433 
434  // 2. If the user isn't forcing up the chooser UI, look for a default
435  // backend in config.xml, then test DB settings we've got so far:
436  if (!manualSelect)
437  {
438  // config.xml may contain a backend host UUID and PIN.
439  // If so, try to AutoDiscover UPnP server, and use its DB settings:
440 
441  if (DefaultUPnP(failure)) // Probably a valid backend,
442  autoSelect = manualSelect = false; // so disable any further UPnP
443  else
444  if (failure.length())
445  LOG(VB_GENERAL, LOG_ALERT, failure);
446 
447  failure = TestDBconnection(loaded);
448  if (failure.isEmpty())
449  goto DBfound;
451  return false;
453  autoSelect=true;
454  }
455 
456  // 3. Try to automatically find the single backend:
457  if (autoSelect)
458  {
459  int count = UPnPautoconf();
460 
461  if (count == 0)
462  failure = QObject::tr("No UPnP backends found", "Backend Setup");
463 
464  if (count == 1)
465  {
466  failure = TestDBconnection();
467  if (failure.isEmpty())
468  goto DBfound;
470  return false;
471  }
472 
473  // Multiple BEs, or needs PIN.
474  manualSelect |= (count > 1 || count == -1);
475  // Search requested
477  manualSelect=true;
478  }
479 
480  manualSelect &= m_gui; // no interactive command-line chooser yet
481 
482  // Queries the user for the DB info
483  do
484  {
485  if (manualSelect)
486  {
487  // Get the user to select a backend from a possible list:
489  ChooseBackend(failure);
490  switch (d)
491  {
493  break;
495  manualSelect = false;
496  break;
498  goto NoDBfound;
499  }
500  }
501 
502  if (!manualSelect)
503  {
504  if (!PromptForDatabaseParams(failure))
505  goto NoDBfound;
506  }
507  failure = TestDBconnection();
508  if (!failure.isEmpty())
509  LOG(VB_GENERAL, LOG_ALERT, failure);
511  return false;
513  manualSelect=true;
515  manualSelect=false;
516  }
517  while (!failure.isEmpty());
518 
519 DBfound:
520  LOG(VB_GENERAL, LOG_DEBUG, "FindDatabase() - Success!");
521  // If we got the database from UPNP then the wakeup settings are lost.
522  // Restore them.
523  m_DBparams.wolEnabled = dbParamsFromFile.wolEnabled;
524  m_DBparams.wolReconnect = dbParamsFromFile.wolReconnect;
525  m_DBparams.wolRetry = dbParamsFromFile.wolRetry;
526  m_DBparams.wolCommand = dbParamsFromFile.wolCommand;
527 
529  !loaded || m_DBparams.forceSave ||
530  dbParamsFromFile != m_DBparams);
531  EnableDBerrors();
532  ResetDatabase();
533  return true;
534 
535 NoDBfound:
536  LOG(VB_GENERAL, LOG_DEBUG, "FindDatabase() - failed");
537  return false;
538 }
539 
544 {
545  // try new format first
547 
548  m_DBparams.localHostName = m_pConfig->GetValue("LocalHostName", "");
549  m_DBparams.dbHostPing = m_pConfig->GetValue(kDefaultDB + "PingHost", true);
551  m_DBparams.dbUserName = m_pConfig->GetValue(kDefaultDB + "UserName", "");
552  m_DBparams.dbPassword = m_pConfig->GetValue(kDefaultDB + "Password", "");
553  m_DBparams.dbName = m_pConfig->GetValue(kDefaultDB + "DatabaseName", "");
555 
557  m_pConfig->GetValue(kDefaultWOL + "Enabled", false);
559  m_pConfig->GetValue(kDefaultWOL + "SQLReconnectWaitTime", 0);
561  m_pConfig->GetValue(kDefaultWOL + "SQLConnectRetry", 5);
563  m_pConfig->GetValue(kDefaultWOL + "Command", "");
564 
565  bool ok = m_DBparams.IsValid("config.xml");
566  if (!ok) // if new format fails, try legacy format
567  {
570  kDefaultMFE + "DBHostName", "");
572  kDefaultMFE + "DBUserName", "");
574  kDefaultMFE + "DBPassword", "");
576  kDefaultMFE + "DBName", "");
578  kDefaultMFE + "DBPort", 0);
579  m_DBparams.forceSave = true;
580  ok = m_DBparams.IsValid("config.xml");
581  }
582  if (!ok)
584 
585  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
586 
588  if (hostname.isEmpty() ||
589  hostname == "my-unique-identifier-goes-here")
590  {
591  char localhostname[1024];
592  if (gethostname(localhostname, 1024))
593  {
594  LOG(VB_GENERAL, LOG_ALERT,
595  "MCP: Error, could not determine host name." + ENO);
596  localhostname[0] = '\0';
597  }
598  hostname = localhostname;
599  LOG(VB_GENERAL, LOG_NOTICE, "Empty LocalHostName.");
600  }
601  else
602  {
603  m_DBparams.localEnabled = true;
604  }
605 
606  LOG(VB_GENERAL, LOG_INFO, QString("Using localhost value of %1")
607  .arg(hostname));
608  gCoreContext->SetLocalHostname(hostname);
609 
610  return ok;
611 }
612 
614  const DatabaseParams &params, bool force)
615 {
616  bool ret = true;
617 
618  // only rewrite file if it has changed
619  if (params != m_DBparams || force)
620  {
622  "LocalHostName", params.localHostName);
623 
625  kDefaultDB + "PingHost", params.dbHostPing);
626 
627  // If dbHostName is an IPV6 address with scope,
628  // remove the scope. Unescaped % signs are an
629  // xml violation
630  QString dbHostName(params.dbHostName);
631  QHostAddress addr;
632  if (addr.setAddress(dbHostName))
633  {
634  addr.setScopeId(QString());
635  dbHostName = addr.toString();
636  }
638  kDefaultDB + "Host", dbHostName);
640  kDefaultDB + "UserName", params.dbUserName);
642  kDefaultDB + "Password", params.dbPassword);
644  kDefaultDB + "DatabaseName", params.dbName);
646  kDefaultDB + "Port", params.dbPort);
647 
649  kDefaultWOL + "Enabled", params.wolEnabled);
651  kDefaultWOL + "SQLReconnectWaitTime", params.wolReconnect);
653  kDefaultWOL + "SQLConnectRetry", params.wolRetry);
655  kDefaultWOL + "Command", params.wolCommand);
656 
657  // clear out any legacy nodes..
658  m_pConfig->ClearValue(kDefaultMFE + "DBHostName");
659  m_pConfig->ClearValue(kDefaultMFE + "DBUserName");
660  m_pConfig->ClearValue(kDefaultMFE + "DBPassword");
661  m_pConfig->ClearValue(kDefaultMFE + "DBName");
662  m_pConfig->ClearValue(kDefaultMFE + "DBPort");
663  m_pConfig->ClearValue(kDefaultMFE + "DBHostPing");
664 
665  // actually save the file
666  m_pConfig->Save();
667 
668  // Save the new settings:
669  m_DBparams = params;
670  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
671 
672  // If database has changed, force its use:
673  ResetDatabase();
674  }
675  return ret;
676 }
677 
679 {
680  if (d && d->m_loop
681  && d->m_loop->isRunning())
682  d->m_loop->exit();
683 }
684 
685 
687 {
688  bool accepted = false;
689  if (m_gui)
690  {
691  TempMainWindow();
692 
693  // Tell the user what went wrong:
694  if (error.length())
695  ShowOkPopup(error);
696 
697  // ask user for database parameters
698 
699  EnableDBerrors();
701  DatabaseSettings *dbsetting = new DatabaseSettings();
702  StandardSettingDialog *ssd =
703  new StandardSettingDialog(mainStack, "databasesettings",
704  dbsetting);
705  if (ssd->Create())
706  {
707  mainStack->AddScreen(ssd);
708  connect(dbsetting, &DatabaseSettings::isClosing,
710  if (!m_loop->isRunning())
711  m_loop->exec();
712  }
713  else
714  delete ssd;
715  SilenceDBerrors();
716  EndTempWindow();
717  accepted = true;
718  }
719  else
720  {
722  QString response;
723  std::this_thread::sleep_for(std::chrono::seconds(1));
724  // give user chance to skip config
725  cout << endl << error.toLocal8Bit().constData() << endl << endl;
726  response = getResponse("Would you like to configure the database "
727  "connection now?",
728  "no");
729  if (!response.startsWith('y', Qt::CaseInsensitive))
730  return false;
731 
732  params.dbHostName = getResponse("Database host name:",
733  params.dbHostName);
734  response = getResponse("Should I test connectivity to this host "
735  "using the ping command?", "yes");
736  params.dbHostPing = response.startsWith('y', Qt::CaseInsensitive);
737 
738  params.dbPort = intResponse("Database non-default port:",
739  params.dbPort);
740  params.dbName = getResponse("Database name:",
741  params.dbName);
742  params.dbUserName = getResponse("Database user name:",
743  params.dbUserName);
744  params.dbPassword = getResponse("Database password:",
745  params.dbPassword);
746 
747  params.localHostName = getResponse("Unique identifier for this machine "
748  "(if empty, the local host name "
749  "will be used):",
750  params.localHostName);
751  params.localEnabled = !params.localHostName.isEmpty();
752 
753  response = getResponse("Would you like to use Wake-On-LAN to retry "
754  "database connections?",
755  (params.wolEnabled ? "yes" : "no"));
756  params.wolEnabled = response.startsWith('y', Qt::CaseInsensitive);
757 
758  if (params.wolEnabled)
759  {
760  params.wolReconnect = intResponse("Seconds to wait for "
761  "reconnection:",
762  params.wolReconnect);
763  params.wolRetry = intResponse("Number of times to retry:",
764  params.wolRetry);
765  params.wolCommand = getResponse("Command to use to wake server:",
766  params.wolCommand);
767  }
768 
769  accepted = parent->SaveDatabaseParams(params);
770  }
771  return accepted;
772 }
773 
780 {
781  QString err = QString::null;
782  QString host;
783 
784  // Jan 20, 2017
785  // Changed to use port check instead of ping
786 
787  int port;
788 
789  // 1 = db awake, 2 = db listening, 3 = db connects,
790  // 4 = backend awake, 5 = backend listening
791  // 9 = all ok, 10 = quit
792 
793  enum startupStates {
794  st_start = 0,
795  st_dbAwake = 1,
796  st_dbStarted = 2,
797  st_dbConnects = 3,
798  st_beWOL = 4,
799  st_beAwake = 5,
800  st_success = 6
801  } startupState = st_start;
802 
803  static const QString guiStatuses[7] =
804  {"start","dbAwake","dbStarted","dbConnects","beWOL","beAwake",
805  "success" };
806 
807  do
808  {
809  host = m_DBparams.dbHostName;
810  port = m_DBparams.dbPort;
811  if (port == 0)
812  port = 3306;
813  int wakeupTime = 3;
814  int attempts = 11;
815  if (m_DBparams.wolEnabled) {
816  wakeupTime = m_DBparams.wolReconnect;
817  attempts = m_DBparams.wolRetry + 1;
818  startupState = st_start;
819  }
820  else
821  startupState = st_dbAwake;
822  if (attempts < 6)
823  attempts = 6;
824  if (!prompt)
825  attempts=1;
826  if (wakeupTime < 5)
827  wakeupTime = 5;
828 
829  int progressTotal = wakeupTime * attempts;
830 
832  m_guiStartup->setTotal(progressTotal);
833 
834  QString beWOLCmd = QString();
835  QString backendIP = QString();
836  int backendPort = 0;
837  QString masterserver;
838 
839  for (int attempt = 0;
840  attempt < attempts && startupState != st_success;
841  ++attempt)
842  {
843  // The first time do everything with minimum timeout and
844  // no GUI, for the normal case where all is OK
845  // After that show the GUI (if this is a GUI program)
846 
847  LOG(VB_GENERAL, LOG_INFO,
848  QString("Start up testing connections. DB %1, BE %2, attempt %3, status %4")
849  .arg(host).arg(backendIP).arg(attempt).arg(guiStatuses[startupState]));
850 
851  int useTimeout = wakeupTime;
852  if (attempt == 0)
853  useTimeout=1;
854 
855  if (m_gui && !m_guiStartup)
856  {
857  if (attempt > 0)
858  {
859  ShowGuiStartup();
860  if (m_guiStartup)
861  m_guiStartup->setTotal(progressTotal);
862  }
863  }
865  {
866  if (attempt > 0)
867  m_guiStartup->setStatusState(guiStatuses[startupState]);
868  m_guiStartup->setMessageState("empty");
869  processEvents();
870  }
871  switch (startupState) {
872  case st_start:
874  {
875  if (attempt > 0)
877  if (!checkPort(host, port, useTimeout))
878  break;
879  }
880  startupState = st_dbAwake;
881  // Fall through to next case
882  case st_dbAwake:
883  if (!checkPort(host, port, useTimeout))
884  break;
885  startupState = st_dbStarted;
886  // Fall through to next case
887  case st_dbStarted:
888  // If the database is connecting with link-local
889  // address, it may have changed
890  if (m_DBparams.dbHostName != host)
891  {
892  m_DBparams.dbHostName = host;
893  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
894  }
895  EnableDBerrors();
896  ResetDatabase();
898  {
899  for (int temp = 0; temp < useTimeout * 2 ; temp++)
900  {
901  processEvents();
902  std::this_thread::sleep_for(std::chrono::milliseconds(500));
903  }
904  break;
905  }
906  startupState = st_dbConnects;
907  // Fall through to next case
908  case st_dbConnects:
909  if (needsBackend)
910  {
911  beWOLCmd = gCoreContext->GetSetting("WOLbackendCommand", "");
912  if (!beWOLCmd.isEmpty())
913  {
914  wakeupTime += gCoreContext->GetNumSetting
915  ("WOLbackendReconnectWaitTime", 0);
916  attempts += gCoreContext->GetNumSetting
917  ("WOLbackendConnectRetry", 0);
918  useTimeout = wakeupTime;
919  if (m_gui && !m_guiStartup && attempt == 0)
920  useTimeout=1;
921  progressTotal = wakeupTime * attempts;
923  m_guiStartup->setTotal(progressTotal);
924  startupState = st_beWOL;
925  }
926  }
927  else {
928  startupState = st_success;
929  break;
930  }
931  masterserver = gCoreContext->GetSetting
932  ("MasterServerName");
933  backendIP = gCoreContext->GetSettingOnHost
934  ("BackendServerAddr", masterserver);
935  backendPort = gCoreContext->GetMasterServerPort();
936  // Fall through to next case
937  case st_beWOL:
938  if (!beWOLCmd.isEmpty()) {
939  if (attempt > 0)
940  myth_system(beWOLCmd);
941  if (!checkPort(backendIP, backendPort, useTimeout))
942  break;
943  }
944  startupState = st_beAwake;
945  // Fall through to next case
946  case st_beAwake:
947  if (!checkPort(backendIP, backendPort, useTimeout))
948  break;
949  startupState = st_success;
950  }
951  if (m_guiStartup)
952  {
953  if (m_guiStartup->m_Exit
956  || m_guiStartup->m_Retry)
957  break;
958  }
959  processEvents();
960  }
961  if (startupState == st_success)
962  break;
963 
964  QString stateMsg = guiStatuses[startupState];
965  stateMsg.append("Fail");
966  LOG(VB_GENERAL, LOG_INFO,
967  QString("Start up failure. host %1, status %2")
968  .arg(host).arg(stateMsg));
969 
970  if (m_guiStartup
971  && !m_guiStartup->m_Exit
972  && !m_guiStartup->m_Setup
974  && !m_guiStartup->m_Retry)
975  {
977  m_guiStartup->setStatusState(stateMsg);
978  m_guiStartup->setMessageState("makeselection");
979  m_loop->exec();
980  }
981  }
982  while (m_guiStartup && m_guiStartup->m_Retry);
983 
984  if (startupState < st_dbAwake)
985  {
986  LOG(VB_GENERAL, LOG_WARNING, QString("Pinging to %1 failed, database will be unavailable").arg(host));
987  SilenceDBerrors();
988  err = QObject::tr(
989  "Cannot find (ping) database host %1 on the network",
990  "Backend Setup");
991  return err.arg(host);
992  }
993 
994  if (startupState < st_dbConnects)
995  {
996  SilenceDBerrors();
997  return QObject::tr("Cannot login to database", "Backend Setup");
998  }
999 
1000  if (startupState < st_success)
1001  {
1002  return QObject::tr("Cannot connect to backend", "Backend Setup");
1003  }
1004 
1005  // Current DB connection may have been silenced (invalid):
1006  EnableDBerrors();
1007  ResetDatabase();
1008 
1009  return QString::null;
1010 }
1011 
1012 // Show the Gui Startup window.
1013 // This is called if there is a delay in startup for any reason
1014 // such as the database being unavailable
1016 {
1017  if (!m_gui)
1018  return;
1019  TempMainWindow(false);
1020  MythMainWindow *mainWindow = GetMythMainWindow();
1021  MythScreenStack *mainStack = mainWindow->GetMainStack();
1022  if (mainStack) {
1023  if (!m_guiStartup) {
1024  m_guiStartup = new GUIStartup(mainStack,m_loop);
1025  if (!m_guiStartup->Create()) {
1026  delete m_guiStartup;
1027  m_guiStartup = 0;
1028  }
1029  if (m_guiStartup) {
1030  mainStack->AddScreen(m_guiStartup, false);
1031  processEvents();
1032  }
1033  }
1034  }
1035 }
1036 
1046 {
1047  // This silences any DB errors from Get*Setting(),
1048  // (which is the vast majority of them)
1049  gCoreContext->GetDB()->SetSuppressDBMessages(true);
1050 
1051  // Save the configured hostname, so that we can
1052  // still display it in the DatabaseSettings screens
1053  if (m_DBparams.dbHostName.length())
1055 
1056  m_DBparams.dbHostName.clear();
1057  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
1058 }
1059 
1061 {
1062  // Restore (possibly) blanked hostname
1063  if (m_DBparams.dbHostName.isNull() && m_DBhostCp.length())
1064  {
1066  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
1067  }
1068 
1069  gCoreContext->GetDB()->SetSuppressDBMessages(false);
1070 }
1071 
1072 
1085 {
1087  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
1089 }
1090 
1095 {
1096  TempMainWindow();
1097 
1098  // Tell the user what went wrong:
1099  if (!error.isEmpty())
1100  {
1101  LOG(VB_GENERAL, LOG_ERR, QString("Error: %1").arg(error));
1102  ShowOkPopup(error);
1103  }
1104 
1105  LOG(VB_GENERAL, LOG_INFO, "Putting up the UPnP backend chooser");
1106 
1109 
1110  EndTempWindow();
1111 
1112  return (int)ret;
1113 }
1114 
1121 int MythContextPrivate::UPnPautoconf(const int milliSeconds)
1122 {
1123  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search %1 secs")
1124  .arg(milliSeconds / 1000));
1125 
1126  SSDP::Instance()->PerformSearch(gBackendURI, milliSeconds / 1000);
1127 
1128  // Search for a total of 'milliSeconds' ms, sending new search packet
1129  // about every 250 ms until less than one second remains.
1130  MythTimer totalTime; totalTime.start();
1131  MythTimer searchTime; searchTime.start();
1132  while (totalTime.elapsed() < milliSeconds)
1133  {
1134  usleep(25000);
1135  int ttl = milliSeconds - totalTime.elapsed();
1136  if ((searchTime.elapsed() > 249) && (ttl > 1000))
1137  {
1138  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search %1 secs")
1139  .arg(ttl / 1000));
1140  SSDP::Instance()->PerformSearch(gBackendURI, ttl / 1000);
1141  searchTime.start();
1142  }
1143  }
1144 
1146 
1147  if (!backends)
1148  {
1149  LOG(VB_GENERAL, LOG_INFO, "No UPnP backends found");
1150  return 0;
1151  }
1152 
1153  int count = backends->Count();
1154  if (count)
1155  {
1156  LOG(VB_GENERAL, LOG_INFO,
1157  QString("Found %1 UPnP backends").arg(count));
1158  }
1159  else
1160  {
1161  LOG(VB_GENERAL, LOG_ERR,
1162  "No UPnP backends found, but SSDP::Find() not NULL");
1163  }
1164 
1165  if (count != 1)
1166  {
1167  backends->DecrRef();
1168  return count;
1169  }
1170 
1171  // Get this backend's location:
1172  DeviceLocation *BE = backends->GetFirst();
1173  backends->DecrRef();
1174  backends = NULL;
1175 
1176  // We don't actually know the backend's access PIN, so this will
1177  // only work for ones that have PIN access disabled (i.e. 0000)
1178  int ret = (UPnPconnect(BE, QString::null)) ? 1 : -1;
1179 
1180  BE->DecrRef();
1181 
1182  return ret;
1183 }
1184 
1191 {
1192  QString loc = "DefaultUPnP() - ";
1193  QString PIN = m_pConfig->GetValue(kDefaultPIN, "");
1194  QString USN = m_pConfig->GetValue(kDefaultUSN, "");
1195 
1196  if (USN.isEmpty())
1197  {
1198  LOG(VB_UPNP, LOG_INFO, loc + "No default UPnP backend");
1199  return false;
1200  }
1201 
1202  LOG(VB_UPNP, LOG_INFO, loc + "config.xml has default " +
1203  QString("PIN '%1' and host USN: %2") .arg(PIN).arg(USN));
1204 
1205  // ----------------------------------------------------------------------
1206 
1207  int timeout_ms = 2000;
1208  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search up to %1 secs")
1209  .arg(timeout_ms / 1000));
1210  SSDP::Instance()->PerformSearch(gBackendURI, timeout_ms / 1000);
1211 
1212  // ----------------------------------------------------------------------
1213  // We need to give the server time to respond...
1214  // ----------------------------------------------------------------------
1215 
1216  DeviceLocation *pDevLoc = NULL;
1217  MythTimer totalTime; totalTime.start();
1218  MythTimer searchTime; searchTime.start();
1219  while (totalTime.elapsed() < timeout_ms)
1220  {
1221  pDevLoc = SSDP::Instance()->Find( gBackendURI, USN );
1222 
1223  if (pDevLoc)
1224  break;
1225 
1226  usleep(25000);
1227 
1228  int ttl = timeout_ms - totalTime.elapsed();
1229  if ((searchTime.elapsed() > 249) && (ttl > 1000))
1230  {
1231  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search up to %1 secs")
1232  .arg(ttl / 1000));
1233  SSDP::Instance()->PerformSearch(gBackendURI, ttl / 1000);
1234  searchTime.start();
1235  }
1236  }
1237 
1238  // ----------------------------------------------------------------------
1239 
1240  if (!pDevLoc)
1241  {
1242  error = "Cannot find default UPnP backend";
1243  return false;
1244  }
1245 
1246  if (UPnPconnect(pDevLoc, PIN))
1247  {
1248  pDevLoc->DecrRef();
1249  return true;
1250  }
1251 
1252  pDevLoc->DecrRef();
1253 
1254  error = "Cannot connect to default backend via UPnP. Wrong saved PIN?";
1255  return false;
1256 }
1257 
1262  const QString &PIN)
1263 {
1264  QString error;
1265  QString loc = "UPnPconnect() - ";
1266  QString URL = backend->m_sLocation;
1267  MythXMLClient client(URL);
1268 
1269  LOG(VB_UPNP, LOG_INFO, loc + QString("Trying host at %1").arg(URL));
1270  switch (client.GetConnectionInfo(PIN, &m_DBparams, error))
1271  {
1272  case UPnPResult_Success:
1273  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
1274  LOG(VB_UPNP, LOG_INFO, loc +
1275  "Got database hostname: " + m_DBparams.dbHostName);
1276  return true;
1277 
1279  // The stored PIN is probably not correct.
1280  // We could prompt for the PIN and try again, but that needs a UI.
1281  // Easier to fail for now, and put up the full UI selector later
1282  LOG(VB_UPNP, LOG_ERR, loc + "Wrong PIN?");
1283  return false;
1284 
1285  default:
1286  LOG(VB_UPNP, LOG_ERR, loc + error);
1287  break;
1288  }
1289 
1290  // This backend may have a local DB with the default user/pass/DBname.
1291  // For whatever reason, we have failed to get anything back via UPnP,
1292  // so we might as well try the database directly as a last resort.
1293  QUrl theURL(URL);
1294  URL = theURL.host();
1295  if (URL.isEmpty())
1296  return false;
1297 
1298  LOG(VB_UPNP, LOG_INFO, "Trying default DB credentials at " + URL);
1300 
1301  return true;
1302 }
1303 
1305 {
1306  if (e->type() == (QEvent::Type) MythEvent::MythEventMessage)
1307  {
1308  if (disableeventpopup)
1309  return true;
1310 
1312  {
1314  }
1315 
1316  MythEvent *me = (MythEvent*)e;
1317  if (me->Message() == "VERSION_MISMATCH" && (1 == me->ExtraDataCount()))
1318  ShowVersionMismatchPopup(me->ExtraData(0).toUInt());
1319  else if (me->Message() == "CONNECTION_FAILURE")
1321  else if (me->Message() == "PERSISTENT_CONNECTION_FAILURE")
1323  else if (me->Message() == "CONNECTION_RESTABLISHED")
1325  return true;
1326  }
1327 
1328  return QObject::event(e);
1329 }
1330 
1332 {
1333  QDateTime now = MythDate::current();
1334 
1335  if (!GetNotificationCenter() || !m_ui || !m_ui->IsScreenSetup())
1336  return;
1337 
1338  if (m_lastCheck.isValid() && now < m_lastCheck)
1339  return;
1340 
1341  // When WOL is disallowed, standy mode,
1342  // we should not show connection failures.
1343  if (!gCoreContext->IsWOLAllowed())
1344  return;
1345 
1346  m_lastCheck = now.addMSecs(5000); // don't refresh notification more than every 5s
1347 
1348  QString description = (persistent) ?
1349  QObject::tr(
1350  "The connection to the master backend "
1351  "server has gone away for some reason. "
1352  "Is it running?") :
1353  QObject::tr(
1354  "Could not connect to the master backend server. Is "
1355  "it running? Is the IP address set for it in "
1356  "mythtv-setup correct?");
1357 
1358  QString message = QObject::tr("Could not connect to master backend");
1359  MythErrorNotification n(message, _Location, description);
1360  n.SetId(m_registration);
1361  n.SetParent(this);
1363 }
1364 
1366 {
1367  if (!GetNotificationCenter())
1368  return;
1369 
1370  if (!m_lastCheck.isValid())
1371  return;
1372 
1373  MythCheckNotification n(QObject::tr("Backend is online"), _Location);
1374  n.SetId(m_registration);
1375  n.SetParent(this);
1376  n.SetDuration(5);
1378  m_lastCheck = QDateTime();
1379 }
1380 
1382 {
1383  if (MBEversionPopup)
1384  return;
1385 
1386  QString message =
1387  QObject::tr(
1388  "The server uses network protocol version %1, "
1389  "but this client only understands version %2. "
1390  "Make sure you are running compatible versions of "
1391  "the backend and frontend.")
1392  .arg(remote_version).arg(MYTH_PROTO_VERSION);
1393 
1394  if (HasMythMainWindow() && m_ui && m_ui->IsScreenSetup())
1395  {
1397  message, m_sh, SLOT(VersionMismatchPopupClosed()));
1398  }
1399  else
1400  {
1401  LOG(VB_GENERAL, LOG_ERR, LOC + message);
1402  qApp->exit(GENERIC_EXIT_SOCKET_ERROR);
1403  }
1404 }
1405 
1406 // Process Events while waiting for connection
1407 // return true if progress is 100%
1409 {
1410 // bool ret = false;
1411 // if (m_guiStartup)
1412 // ret = m_guiStartup->updateProgress();
1413  qApp->processEvents(QEventLoop::AllEvents, 250);
1414  qApp->processEvents(QEventLoop::AllEvents, 250);
1415 // return ret;
1416 }
1417 
1418 // cache some settings in cache/contextcache.xml
1419 // only call this if the database is available.
1420 
1421 const QString MythContextPrivate::settingsToSave[] =
1422 { "Theme", "Language", "Country", "GuiHeight",
1423  "GuiOffsetX", "GuiOffsetY", "GuiWidth", "RunFrontendInWindow",
1424  "AlwaysOnTop", "HideMouseCursor", "ThemePainter" };
1425 
1426 
1428 {
1429  if (!m_gui)
1430  return true;
1431  QString cacheDirName = GetConfDir() + "/cache/";
1432  QDir dir(cacheDirName);
1433  dir.mkpath(cacheDirName);
1434  XmlConfiguration config = XmlConfiguration("cache/contextcache.xml");
1435  static const int arraySize = sizeof(settingsToSave)/sizeof(settingsToSave[0]);
1436  for (int ix = 0; ix < arraySize; ix++)
1437  {
1438  QString cacheValue = config.GetValue("Settings/"+settingsToSave[ix],QString());
1440  QString value = gCoreContext->GetSetting(settingsToSave[ix],QString());
1441  if (value != cacheValue)
1442  {
1443  config.SetValue("Settings/"+settingsToSave[ix],value);
1444  m_settingsCacheDirty = true;
1445  }
1446  }
1448  return config.Save();
1449 }
1450 
1452 {
1453  if (!m_gui)
1454  return;
1455  XmlConfiguration config = XmlConfiguration("cache/contextcache.xml");
1456  static const int arraySize = sizeof(settingsToSave)/sizeof(settingsToSave[0]);
1457  for (int ix = 0; ix < arraySize; ix++)
1458  {
1459  QString value = config.GetValue("Settings/"+settingsToSave[ix],QString());
1460  if (!value.isEmpty())
1462  }
1463  // Prevent power off TV after temporary window
1464  gCoreContext->OverrideSettingForSession("PowerOffTVAllowed", 0);
1465 
1466  QString language = gCoreContext->GetSetting("Language",QString());
1467  MythTranslation::load("mythfrontend");
1468 }
1469 
1471 {
1472  QString language = gCoreContext->GetSetting("Language",QString());
1473  static const int arraySize = sizeof(settingsToSave)/sizeof(settingsToSave[0]);
1474  for (int ix = 0; ix < arraySize; ix++)
1475  {
1477  }
1478  // Restore power off TV setting
1479  gCoreContext->ClearOverrideSettingForSession("PowerOffTVAllowed");
1480 
1481  if (language != gCoreContext->GetSetting("Language",QString()))
1482  MythTranslation::load("mythfrontend");
1483 }
1484 
1485 
1487 {
1488  d->MBEversionPopup = NULL;
1489  qApp->exit(GENERIC_EXIT_SOCKET_ERROR);
1490 }
1491 
1492 MythContext::MythContext(const QString &binversion, bool needsBackend)
1493  : d(NULL), app_binary_version(binversion)
1494 {
1495 #ifdef _WIN32
1496  static bool WSAStarted = false;
1497  if (!WSAStarted) {
1498  WSADATA wsadata;
1499  int res = WSAStartup(MAKEWORD(2, 0), &wsadata);
1500  LOG(VB_SOCKET, LOG_INFO,
1501  QString("WSAStartup returned %1").arg(res));
1502  }
1503 #endif
1504 
1505  d = new MythContextPrivate(this);
1506  d->needsBackend = needsBackend;
1507 
1509 
1510  if (!gCoreContext || !gCoreContext->Init())
1511  {
1512  LOG(VB_GENERAL, LOG_EMERG, LOC + "Unable to allocate MythCoreContext");
1513  qApp->exit(GENERIC_EXIT_NO_MYTHCONTEXT);
1514  }
1515 }
1516 
1517 bool MythContext::Init(const bool gui,
1518  const bool promptForBackend,
1519  const bool disableAutoDiscovery,
1520  const bool ignoreDB)
1521 {
1522  SetDisableEventPopup(true);
1523 
1524  if (!d)
1525  {
1526  LOG(VB_GENERAL, LOG_EMERG, LOC + "Init() Out-of-memory");
1527  return false;
1528  }
1529 
1530  if (app_binary_version != MYTH_BINARY_VERSION)
1531  {
1532  LOG(VB_GENERAL, LOG_EMERG,
1533  QString("Application binary version (%1) does not "
1534  "match libraries (%2)")
1535  .arg(app_binary_version) .arg(MYTH_BINARY_VERSION));
1536 
1537  QString warning = QObject::tr(
1538  "This application is not compatible "
1539  "with the installed MythTV libraries.");
1540  if (gui)
1541  {
1542  d->TempMainWindow(false);
1543  ShowOkPopup(warning);
1544  }
1545  LOG(VB_GENERAL, LOG_WARNING, warning);
1546 
1547  return false;
1548  }
1549 
1550 #ifdef _WIN32
1551  // HOME environment variable might not be defined
1552  // some libraries will fail without it
1553  QString home = getenv("HOME");
1554  if (home.isEmpty())
1555  {
1556  home = getenv("LOCALAPPDATA"); // Vista
1557  if (home.isEmpty())
1558  home = getenv("APPDATA"); // XP
1559  if (home.isEmpty())
1560  home = QString("."); // getenv("TEMP")?
1561 
1562  _putenv(QString("HOME=%1").arg(home).toLocal8Bit().constData());
1563  }
1564 #endif
1565 
1566  // If HOME isn't defined, we won't be able to use default confdir of
1567  // $HOME/.mythtv nor can we rely on a MYTHCONFDIR that references $HOME
1568  QString homedir = QDir::homePath();
1569  QString confdir = getenv("MYTHCONFDIR");
1570  if ((homedir.isEmpty() || homedir == "/") &&
1571  (confdir.isEmpty() || confdir.contains("$HOME")))
1572  {
1573  QString warning = "Cannot locate your home directory."
1574  " Please set the environment variable HOME";
1575  if (gui)
1576  {
1577  d->TempMainWindow(false);
1578  ShowOkPopup(warning);
1579  }
1580  LOG(VB_GENERAL, LOG_WARNING, warning);
1581 
1582  return false;
1583  }
1584 
1585  if (!d->Init(gui, promptForBackend, disableAutoDiscovery, ignoreDB))
1586  {
1587  return false;
1588  }
1589 
1590  SetDisableEventPopup(false);
1592  if (d->m_settingsCacheDirty)
1593  {
1595  d->m_settingsCacheDirty = false;
1596  }
1598 
1599  return true;
1600 }
1601 
1603 {
1604  if (MThreadPool::globalInstance()->activeThreadCount())
1605  LOG(VB_GENERAL, LOG_INFO, "Waiting for threads to exit.");
1606 
1608  logStop();
1609 
1610  SSDP::Shutdown();
1612 
1613  delete gCoreContext;
1614  gCoreContext = NULL;
1615 
1616  delete d;
1617 }
1618 
1620 {
1621  d->disableeventpopup = check;
1622 }
1623 
1625 {
1626  return d->m_DBparams;
1627 }
1628 
1630 {
1631  return d->SaveDatabaseParams(params, false);
1632 }
1633 
1635 {
1636  return d->saveSettingsCache();
1637 }
1638 
1639 /* vim: set expandtab tabstop=4 shiftwidth=4: */
void SaveLocaleDefaults(void)
void ShowGuiStartup(void)
virtual bool Save(void)
Startup context for MythTV.
Definition: mythcontext.h:42
void SetParent(void *parent)
contains the parent address.
bool wolEnabled
true if wake-on-lan params are used
Definition: mythdbparams.h:32
virtual int GetValue(const QString &sSetting, int Default)=0
bool setStatusState(const QString &name)
Definition: guistartup.cpp:123
int intResponse(const QString &query, int def)
In an interactive shell, prompt the user to input a number.
virtual int GetValue(const QString &sSetting, int Default)
unsigned int slots[4]
Definition: element.c:38
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
QString wolCommand
command to use for wake-on-lan
Definition: mythdbparams.h:35
static void configplugin_cb(const QString &cmd)
QString dbName
database name
Definition: mythdbparams.h:26
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:83
QString app_binary_version
Definition: mythcontext.h:61
void LoadQtConfig(void)
Dialog asking for user confirmation.
int UPnPautoconf(const int milliSeconds=2000)
If there is only a single UPnP backend, use it.
void EndTempWindow(void)
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
virtual void ClearValue(const QString &sSetting)=0
void SetId(int id)
Optional MythNotification elements.
bool setMessageState(const QString &name)
Definition: guistartup.cpp:133
static void exec_program_tv_cb(const QString &cmd)
const QString kDefaultWOL
Definition: backendselect.h:23
static Type MythEventMessage
Definition: mythevent.h:65
static void error(const char *str,...)
Definition: vbi.c:41
virtual void SetValue(const QString &sSetting, int value)
int GetMasterServerPort(void)
static void ejectOpticalDisc(void)
Eject a disk, unmount a drive, open a tray.
bool Create(void)
Definition: guistartup.cpp:83
static MythMainWindow * getMainWindow(const bool useDB=true)
Return the existing main window, or create one.
const QString gBackendURI
Service type for the backend&#39;s UPnP server.
Definition: backendselect.h:21
void isClosing(void)
static const char URL[]
Definition: cddb.cpp:29
bool m_Retry
Definition: guistartup.h:56
void UnRegister(void *from, int id, bool closeimemdiately=false)
Unregister the client.
bool IsFrontend(void) const
is this process a frontend process
QString GetSettingOnHost(const QString &key, const QString &host, const QString &defaultval="")
bool SaveDatabaseParams(const DatabaseParams &params, bool force)
void DestroyMythMainWindow(void)
void SetDisableEventPopup(bool check)
bool IsScreenSetup(void)
unsigned int uint
Definition: compat.h:136
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static Decision Prompt(DatabaseParams *dbParams, Configuration *pConfig)
MythScreenStack * GetMainStack()
DatabaseParams GetDatabaseParams(void)
bool saveSettingsCache(void)
void waitForDone(void)
bool localEnabled
true if localHostName is not default
Definition: mythdbparams.h:29
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:59
bool Init(const bool gui, const bool prompt, const bool noPrompt, const bool ignoreDB)
void DestroyMythUI()
void SetLocalHostname(const QString &hostname)
const QString kDefaultDB
Definition: backendselect.h:22
void(* exec_program)(const QString &cmd)
Definition: mythuihelper.h:35
bool checkPort(QString &host, int port, int wakeupTime)
Check if a port is open and sort out the link-local scope.
QString dbPassword
DB password.
Definition: mythdbparams.h:25
bool checkPort(QString &host, int port, int timeLimit=30000, bool linkLocalOnly=false)
Check if a port is open and sort out the link-local scope.
Definition: portchecker.cpp:82
QString GetConfDir(void)
Definition: mythdirs.cpp:224
static void Shutdown()
Definition: taskqueue.cpp:76
void Init(MythUIMenuCallbacks &cbs)
MythContextPrivate(MythContext *lparent)
static void eject_cb(void)
bool FindDatabase(const bool prompt, const bool noPrompt)
Get database connection settings and test connectivity.
bool config_plugin(const QString &plugname)
Definition: mythplugin.cpp:202
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
MythContext * parent
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
MythContextSlotHandler * m_sh
QString dbUserName
DB user name.
Definition: mythdbparams.h:24
__u32 addr
Definition: videodev2.h:1040
DeviceLocation * GetFirst(void)
Returns random entry in cache, returns NULL when list is empty.
Definition: ssdpcache.cpp:72
bool Init(const bool gui=true, const bool promptForBackend=false, const bool bypassAutoDiscovery=false, const bool ignoreDB=false)
static void plugin_cb(const QString &cmd)
void PerformSearch(const QString &sST, uint timeout_secs=2)
Definition: ssdp.cpp:214
MythPluginManager * GetPluginManager(void)
This class is used as a container for messages.
Definition: mythevent.h:15
void ClearOverrideSettingForSession(const QString &key)
void EnableDBerrors(void)
void VersionMismatchPopupClosed(void)
void Init(QString forcedpainter=QString(), bool mayReInit=true)
int ChooseBackend(const QString &error)
Search for backends via UPnP, put up a UI for the user to choose one.
QString TestDBconnection(bool prompt=true)
Some quick sanity checks before opening a database connection.
uint Count(void) const
Definition: ssdpcache.h:44
void setTotal(int total)
Definition: guistartup.cpp:144
bool PromptForDatabaseParams(const QString &error)
static const uint16_t * d
void OverrideSettingForSession(const QString &key, const QString &value)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString GetSetting(const QString &key, const QString &defaultval="")
DatabaseParams m_DBparams
Current database host & WOL details.
MythContext(const QString &binversion, bool needsBackend=false)
void SetDuration(int duration)
contains a duration during which the notification will be displayed for.
bool m_Setup
Definition: guistartup.h:55
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual bool Save(void)=0
bool updateProgress(bool finished=false)
Definition: guistartup.cpp:161
QEventLoop * m_loop
MythContextPrivate * d
Definition: mythcontext.h:60
static void load(const QString &module_name)
Load a QTranslator for the user&#39;s preferred language.
MythConfirmationDialog * MBEversionPopup
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
Small class to handle TCP port checking and finding link-local context.
Definition: portchecker.h:43
static bool testDBConnection()
Checks DB connection + login (login info via Mythcontext)
Definition: mythdbcon.cpp:885
void(* configplugin)(const QString &cmd)
Definition: mythuihelper.h:37
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
bool dbHostPing
Can we test connectivity using ping?
Definition: mythdbparams.h:22
string hostname
Definition: caa.py:17
void TempMainWindow(bool languagePrompt=true)
Setup a minimal themed main window, and prompt for user&#39;s language.
QString m_masterhostname
master backend hostname
QString m_DBhostCp
dbHostName backup
QString getResponse(const QString &query, const QString &def)
In an interactive shell, prompt the user to input a string.
static bool prompt(bool force=false)
Ask the user for the language to use.
uint myth_system(const QString &command, uint flags, uint timeout)
static const QString _Location
Definition: mythcontext.cpp:61
bool LoadDatabaseSettings(void)
Load database and host settings from config.xml, or set some defaults.
bool IsValid(const QString &source=QString("Unknown")) const
MythUIHelper * GetMythUI()
void SilenceDBerrors(void)
Cause MSqlDatabase::OpenDatabase() and MSqlQuery to fail silently.
int wolReconnect
seconds to wait for reconnect
Definition: mythdbparams.h:33
bool HasMythMainWindow(void)
MythMainWindow * GetMythMainWindow(void)
void clearSettingsCacheOverride(void)
int elapsed(void) const
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:90
bool m_Exit
Definition: guistartup.h:54
static MThreadPool * globalInstance(void)
static void exec_program_cb(const QString &cmd)
bool SaveDatabaseParams(const DatabaseParams &params)
int Register(void *from)
An application can register in which case it will be assigned a reusable screen, which can be modifie...
bool event(QEvent *)
int GetNumSetting(const QString &key, int defaultval=0)
static const QString settingsToSave[]
bool UPnPconnect(const DeviceLocation *device, const QString &PIN)
Query a backend via UPnP for its database connection parameters.
Structure containing the basic Database parameters.
Definition: mythdbparams.h:9
QString m_sLocation
Definition: upnpdevice.h:232
QString dbHostName
database server
Definition: mythdbparams.h:21
void LoadDefaults(void)
Load sensible connection defaults.
Definition: mythdbparams.cpp:5
static SSDP * Instance()
Definition: ssdp.cpp:54
bool forceSave
set to true to force a save of the settings file
Definition: mythdbparams.h:37
const QString & ExtraData(int idx=0) const
Definition: mythevent.h:58
void(* eject)(void)
Definition: mythuihelper.h:39
void logStop(void)
Entry point for stopping logging for an application.
Definition: logging.cpp:953
Configuration * m_pConfig
UPnPResultCode GetConnectionInfo(const QString &sPin, DatabaseParams *pParams, QString &sMsg)
QTcpSocket * m_socket
void(* plugin)(const QString &cmd)
Definition: mythuihelper.h:38
const QString kDefaultPIN
Definition: backendselect.h:25
void ClearSettingsCache(const QString &myKey=QString(""))
static MythPluginManager * pmanager
bool IsWOLAllowed() const
bool saveSettingsCache(void)
MythDB * GetDB(void)
MDBManager * GetDBManager(void)
void loadSettingsCacheOverride(void)
static const QString LOC
void HideConnectionFailurePopup(void)
virtual void PopScreen(MythScreenType *screen=NULL, bool allowFade=true, bool deleteScreen=true)
const QString kDefaultUSN
Definition: backendselect.h:26
int ExtraDataCount() const
Definition: mythevent.h:60
bool m_Search
Definition: guistartup.h:57
MythUIHelper * m_ui
static SSDPCacheEntries * Find(const QString &sURI)
Definition: ssdp.h:129
const QString kDefaultMFE
Definition: backendselect.h:24
void(* exec_program_tv)(const QString &cmd)
Definition: mythuihelper.h:36
void ResetDatabase(void)
Called when the user changes the DB connection settings.
const QString & Message() const
Definition: mythevent.h:57
QString localHostName
name used for loading/saving settings
Definition: mythdbparams.h:30
void ActivateSettingsCache(bool activate=true)
int dbPort
database port
Definition: mythdbparams.h:23
void processEvents(void)
GUIStartup * m_guiStartup
void ShowConnectionFailurePopup(bool persistent)
__s32 value
Definition: videodev2.h:1042
void ShowVersionMismatchPopup(uint remoteVersion)
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
void CloseDatabases(void)
Definition: mythdbcon.cpp:483
virtual ~MythContext()
int wolRetry
times to retry to reconnect
Definition: mythdbparams.h:34
bool DefaultUPnP(QString &error)
Get the default backend from config.xml, use UPnP to find it.
static QString confdir
Definition: mythdirs.cpp:20
This class contains the runtime context for MythTV.
static void Shutdown()
Definition: ssdp.cpp:64
MythNotificationCenter * GetNotificationCenter(void)
bool run_plugin(const QString &plugname)
Definition: mythplugin.cpp:184
void InitializeMythDirs(void)
Definition: mythdirs.cpp:30
virtual void SetValue(const QString &sSetting, int value)=0
bool m_gui
Should this context use GUI elements?