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:
110 
111  bool m_gui;
112 
114 
116  QString m_DBhostCp;
117 
119 
121 
125  QEventLoop *m_loop;
127 
128  private:
131  QDateTime m_lastCheck;
132  QTcpSocket *m_socket;
133  static const QString settingsToSave[];
134 };
135 
136 static void exec_program_cb(const QString &cmd)
137 {
138  myth_system(cmd);
139 }
140 
141 static void exec_program_tv_cb(const QString &cmd)
142 {
143  QString s = cmd;
144  QStringList tokens = cmd.simplified().split(" ");
145  QStringList strlist;
146 
147  bool cardidok;
148  int wantcardid = tokens[0].toInt(&cardidok, 10);
149 
150  if (cardidok && wantcardid > 0)
151  {
152  strlist << QString("LOCK_TUNER %1").arg(wantcardid);
153  s = s.replace(0, tokens[0].length() + 1, "");
154  }
155  else
156  strlist << "LOCK_TUNER";
157 
159  int cardid = strlist[0].toInt();
160 
161  if (cardid >= 0)
162  {
163  s = s.sprintf(qPrintable(s),
164  qPrintable(strlist[1]),
165  qPrintable(strlist[2]),
166  qPrintable(strlist[3]));
167 
168  myth_system(s);
169 
170  strlist = QStringList(QString("FREE_TUNER %1").arg(cardid));
172  QString ret = strlist[0];
173  }
174  else
175  {
176  QString label;
177 
178  if (cardidok)
179  {
180  if (cardid == -1)
181  label = QObject::tr("Could not find specified tuner (%1).")
182  .arg(wantcardid);
183  else
184  label = QObject::tr("Specified tuner (%1) is already in use.")
185  .arg(wantcardid);
186  }
187  else
188  {
189  label = QObject::tr("All tuners are currently in use. If you want "
190  "to watch TV, you can cancel one of the "
191  "in-progress recordings from the delete menu");
192  }
193 
194  LOG(VB_GENERAL, LOG_ALERT, QString("exec_program_tv: ") + label);
195 
196  ShowOkPopup(label);
197  }
198 }
199 
200 static void configplugin_cb(const QString &cmd)
201 {
203  if (!pmanager)
204  return;
205 
206  if (GetNotificationCenter() && pmanager->config_plugin(cmd.trimmed()))
207  {
209  QObject::tr("Failed to configure plugin"));
210  }
211 }
212 
213 static void plugin_cb(const QString &cmd)
214 {
216  if (!pmanager)
217  return;
218 
219  if (GetNotificationCenter() && pmanager->run_plugin(cmd.trimmed()))
220  {
221  ShowNotificationError(QObject::tr("Plugin failure"),
222  _Location,
223  QObject::tr("%1 failed to run for some reason").arg(cmd));
224  }
225 }
226 
227 static void eject_cb(void)
228 {
230 }
231 
233  : parent(lparent),
234  m_gui(false),
235  m_pConfig(NULL),
236  disableeventpopup(false),
237  m_ui(NULL),
238  m_sh(new MythContextSlotHandler(this)),
239  m_guiStartup(0),
240  needsBackend(false),
241  MBEversionPopup(NULL),
242  m_registration(-1),
243  m_socket(0)
244 {
245  m_loop = new QEventLoop(this);
247 }
248 
250 {
251  if (m_pConfig)
252  delete m_pConfig;
254  {
256  }
257 
258  if (m_loop)
259  {
260  delete m_loop;
261  }
262 
263  if (m_ui)
264  DestroyMythUI();
265  if (m_sh)
266  m_sh->deleteLater();
267 }
268 
279 void MythContextPrivate::TempMainWindow(bool languagePrompt)
280 {
281  if (HasMythMainWindow())
282  return;
283 
284  SilenceDBerrors();
285 
288 
289 #ifdef Q_OS_MAC
290  // Qt 4.4 has window-focus problems
291  gCoreContext->OverrideSettingForSession("RunFrontendInWindow", "1");
292 #endif
293  GetMythUI()->Init();
294  GetMythUI()->LoadQtConfig();
295 
296  MythMainWindow *mainWindow = MythMainWindow::getMainWindow(false);
297  mainWindow->Init();
298 
299  if (languagePrompt)
300  {
301  // ask user for language settings
303  MythTranslation::load("mythfrontend");
304  }
305 }
306 
308 {
309  if (HasMythMainWindow())
310  {
312  {
314  if (mainStack) {
315  mainStack->PopScreen(m_guiStartup, false);
316  m_guiStartup = 0;
317  }
318  }
320  }
323  EnableDBerrors();
324 }
325 
333 bool MythContextPrivate::checkPort(QString &host, int port, int timeLimit)
334 {
335  PortChecker checker;
336  if (m_guiStartup)
337  QObject::connect(m_guiStartup,SIGNAL(cancelPortCheck()),&checker,SLOT(cancelPortCheck()));
338  return checker.checkPort(host, port, timeLimit*1000);
339 }
340 
341 
342 bool MythContextPrivate::Init(const bool gui,
343  const bool promptForBackend,
344  const bool noPrompt,
345  const bool ignoreDB)
346 {
347  gCoreContext->GetDB()->IgnoreDatabase(ignoreDB);
348  m_gui = gui;
349 
350  if (gCoreContext->IsFrontend())
351  needsBackend = true;
352 
353  // We don't have a database yet, so lets use the config.xml file.
354  m_pConfig = new XmlConfiguration("config.xml");
355 
356  // Creates screen saver control if we will have a GUI
357  if (gui)
358  m_ui = GetMythUI();
359 
360  // ---- database connection stuff ----
361 
362  if (!ignoreDB && !FindDatabase(promptForBackend, noPrompt))
363  {
364  EndTempWindow();
365  return false;
366  }
367 
368  // ---- keep all DB-using stuff below this line ----
369 
370  // Prompt for language if this is a first time install and
371  // we didn't already do so.
372  if (m_gui && !gCoreContext->GetDB()->HaveSchema())
373  {
374  TempMainWindow(false);
376  MythTranslation::load("mythfrontend");
377  }
380 
381  // Close GUI Startup Window.
382  if (m_guiStartup) {
384  if (mainStack)
385  mainStack->PopScreen(m_guiStartup, false);
386  m_guiStartup=0;
387  }
388  EndTempWindow();
389 
390  if (gui)
391  {
396  cbs.plugin = plugin_cb;
397  cbs.eject = eject_cb;
398 
399  m_ui->Init(cbs);
400  }
401 
402  return true;
403 }
404 
417 bool MythContextPrivate::FindDatabase(bool prompt, bool noAutodetect)
418 {
419  // We can only prompt if autodiscovery is enabled..
420  bool manualSelect = prompt && !noAutodetect;
421 
422  QString failure;
423 
424  // 1. Either load config.xml or use sensible "localhost" defaults:
425  bool loaded = LoadDatabaseSettings();
426  DatabaseParams dbParamsFromFile = m_DBparams;
427 
428  // In addition to the UI chooser, we can also try to autoSelect later,
429  // but only if we're not doing manualSelect and there was no
430  // valid config.xml
431  bool autoSelect = !manualSelect && !loaded && !noAutodetect;
432 
433  // 2. If the user isn't forcing up the chooser UI, look for a default
434  // backend in config.xml, then test DB settings we've got so far:
435  if (!manualSelect)
436  {
437  // config.xml may contain a backend host UUID and PIN.
438  // If so, try to AutoDiscover UPnP server, and use its DB settings:
439 
440  if (DefaultUPnP(failure)) // Probably a valid backend,
441  autoSelect = manualSelect = false; // so disable any further UPnP
442  else
443  if (failure.length())
444  LOG(VB_GENERAL, LOG_ALERT, failure);
445 
446  failure = TestDBconnection(loaded);
447  if (failure.isEmpty())
448  goto DBfound;
450  return false;
452  autoSelect=true;
453  }
454 
455  // 3. Try to automatically find the single backend:
456  if (autoSelect)
457  {
458  int count = UPnPautoconf();
459 
460  if (count == 0)
461  failure = QObject::tr("No UPnP backends found", "Backend Setup");
462 
463  if (count == 1)
464  {
465  failure = TestDBconnection();
466  if (failure.isEmpty())
467  goto DBfound;
469  return false;
470  }
471 
472  // Multiple BEs, or needs PIN.
473  manualSelect |= (count > 1 || count == -1);
474  // Search requested
476  manualSelect=true;
477  }
478 
479  manualSelect &= m_gui; // no interactive command-line chooser yet
480 
481  // Queries the user for the DB info
482  do
483  {
484  if (manualSelect)
485  {
486  // Get the user to select a backend from a possible list:
488  ChooseBackend(failure);
489  switch (d)
490  {
492  break;
494  manualSelect = false;
495  break;
497  goto NoDBfound;
498  }
499  }
500 
501  if (!manualSelect)
502  {
503  if (!PromptForDatabaseParams(failure))
504  goto NoDBfound;
505  }
506  failure = TestDBconnection();
507  if (!failure.isEmpty())
508  LOG(VB_GENERAL, LOG_ALERT, failure);
510  return false;
512  manualSelect=true;
514  manualSelect=false;
515  }
516  while (!failure.isEmpty());
517 
518 DBfound:
519  LOG(VB_GENERAL, LOG_DEBUG, "FindDatabase() - Success!");
521  !loaded || m_DBparams.forceSave ||
522  dbParamsFromFile != m_DBparams);
523  EnableDBerrors();
524  ResetDatabase();
525  return true;
526 
527 NoDBfound:
528  LOG(VB_GENERAL, LOG_DEBUG, "FindDatabase() - failed");
529  return false;
530 }
531 
536 {
537  // try new format first
539 
540  m_DBparams.localHostName = m_pConfig->GetValue("LocalHostName", "");
541  m_DBparams.dbHostPing = m_pConfig->GetValue(kDefaultDB + "PingHost", true);
543  m_DBparams.dbUserName = m_pConfig->GetValue(kDefaultDB + "UserName", "");
544  m_DBparams.dbPassword = m_pConfig->GetValue(kDefaultDB + "Password", "");
545  m_DBparams.dbName = m_pConfig->GetValue(kDefaultDB + "DatabaseName", "");
547 
549  m_pConfig->GetValue(kDefaultWOL + "Enabled", false);
551  m_pConfig->GetValue(kDefaultWOL + "SQLReconnectWaitTime", 0);
553  m_pConfig->GetValue(kDefaultWOL + "SQLConnectRetry", 5);
555  m_pConfig->GetValue(kDefaultWOL + "Command", "");
556 
557  bool ok = m_DBparams.IsValid("config.xml");
558  if (!ok) // if new format fails, try legacy format
559  {
562  kDefaultMFE + "DBHostName", "");
564  kDefaultMFE + "DBUserName", "");
566  kDefaultMFE + "DBPassword", "");
568  kDefaultMFE + "DBName", "");
570  kDefaultMFE + "DBPort", 0);
571  m_DBparams.forceSave = true;
572  ok = m_DBparams.IsValid("config.xml");
573  }
574  if (!ok)
576 
577  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
578 
580  if (hostname.isEmpty() ||
581  hostname == "my-unique-identifier-goes-here")
582  {
583  char localhostname[1024];
584  if (gethostname(localhostname, 1024))
585  {
586  LOG(VB_GENERAL, LOG_ALERT,
587  "MCP: Error, could not determine host name." + ENO);
588  localhostname[0] = '\0';
589  }
590  hostname = localhostname;
591  LOG(VB_GENERAL, LOG_NOTICE, "Empty LocalHostName.");
592  }
593  else
594  {
595  m_DBparams.localEnabled = true;
596  }
597 
598  LOG(VB_GENERAL, LOG_INFO, QString("Using localhost value of %1")
599  .arg(hostname));
600  gCoreContext->SetLocalHostname(hostname);
601 
602  return ok;
603 }
604 
606  const DatabaseParams &params, bool force)
607 {
608  bool ret = true;
609 
610  // only rewrite file if it has changed
611  if (params != m_DBparams || force)
612  {
614  "LocalHostName", params.localHostName);
615 
617  kDefaultDB + "PingHost", params.dbHostPing);
618 
619  // If dbHostName is an IPV6 address with scope,
620  // remove the scope. Unescaped % signs are an
621  // xml violation
622  QString dbHostName(params.dbHostName);
623  QHostAddress addr;
624  if (addr.setAddress(dbHostName))
625  {
626  addr.setScopeId(QString());
627  dbHostName = addr.toString();
628  }
630  kDefaultDB + "Host", dbHostName);
632  kDefaultDB + "UserName", params.dbUserName);
634  kDefaultDB + "Password", params.dbPassword);
636  kDefaultDB + "DatabaseName", params.dbName);
638  kDefaultDB + "Port", params.dbPort);
639 
641  kDefaultWOL + "Enabled", params.wolEnabled);
643  kDefaultWOL + "SQLReconnectWaitTime", params.wolReconnect);
645  kDefaultWOL + "SQLConnectRetry", params.wolRetry);
647  kDefaultWOL + "Command", params.wolCommand);
648 
649  // clear out any legacy nodes..
650  m_pConfig->ClearValue(kDefaultMFE + "DBHostName");
651  m_pConfig->ClearValue(kDefaultMFE + "DBUserName");
652  m_pConfig->ClearValue(kDefaultMFE + "DBPassword");
653  m_pConfig->ClearValue(kDefaultMFE + "DBName");
654  m_pConfig->ClearValue(kDefaultMFE + "DBPort");
655  m_pConfig->ClearValue(kDefaultMFE + "DBHostPing");
656 
657  // actually save the file
658  m_pConfig->Save();
659 
660  // Save the new settings:
661  m_DBparams = params;
662  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
663 
664  // If database has changed, force its use:
665  ResetDatabase();
666  }
667  return ret;
668 }
669 
671 {
672  bool accepted = false;
673  if (m_gui)
674  {
675  TempMainWindow();
676 
677  // Tell the user what went wrong:
678  if (error.length())
679  ShowOkPopup(error);
680 
681  // ask user for database parameters
682  DatabaseSettings settings(m_DBhostCp);
683  accepted = (settings.exec() == QDialog::Accepted);
684  if (!accepted)
685  LOG(VB_GENERAL, LOG_ALERT,
686  "User cancelled database configuration");
687 
688  EndTempWindow();
689  }
690  else
691  {
693  QString response;
694  std::this_thread::sleep_for(std::chrono::seconds(1));
695  // give user chance to skip config
696  cout << endl << error.toLocal8Bit().constData() << endl << endl;
697  response = getResponse("Would you like to configure the database "
698  "connection now?",
699  "no");
700  if (!response.startsWith('y', Qt::CaseInsensitive))
701  return false;
702 
703  params.dbHostName = getResponse("Database host name:",
704  params.dbHostName);
705  response = getResponse("Should I test connectivity to this host "
706  "using the ping command?", "yes");
707  params.dbHostPing = response.startsWith('y', Qt::CaseInsensitive);
708 
709  params.dbPort = intResponse("Database non-default port:",
710  params.dbPort);
711  params.dbName = getResponse("Database name:",
712  params.dbName);
713  params.dbUserName = getResponse("Database user name:",
714  params.dbUserName);
715  params.dbPassword = getResponse("Database password:",
716  params.dbPassword);
717 
718  params.localHostName = getResponse("Unique identifier for this machine "
719  "(if empty, the local host name "
720  "will be used):",
721  params.localHostName);
722  params.localEnabled = !params.localHostName.isEmpty();
723 
724  response = getResponse("Would you like to use Wake-On-LAN to retry "
725  "database connections?",
726  (params.wolEnabled ? "yes" : "no"));
727  params.wolEnabled = response.startsWith('y', Qt::CaseInsensitive);
728 
729  if (params.wolEnabled)
730  {
731  params.wolReconnect = intResponse("Seconds to wait for "
732  "reconnection:",
733  params.wolReconnect);
734  params.wolRetry = intResponse("Number of times to retry:",
735  params.wolRetry);
736  params.wolCommand = getResponse("Command to use to wake server:",
737  params.wolCommand);
738  }
739 
740  accepted = parent->SaveDatabaseParams(params);
741  }
742  return accepted;
743 }
744 
751 {
752  QString err = QString::null;
753  QString host = m_DBparams.dbHostName;
754 
755  // Jan 20, 2017
756  // Changed to use port check instead of ping
757 
758  int port = m_DBparams.dbPort;
759  if (port == 0)
760  port = 3306;
761 
762  // 1 = db awake, 2 = db listening, 3 = db connects,
763  // 4 = backend awake, 5 = backend listening
764  // 9 = all ok, 10 = quit
765 
766  enum startupStates {
767  st_start = 0,
768  st_dbAwake = 1,
769  st_dbStarted = 2,
770  st_dbConnects = 3,
771  st_beWOL = 4,
772  st_beAwake = 5,
773  st_success = 6
774  } startupState = st_start;
775 
776  static const QString guiStatuses[7] =
777  {"start","dbAwake","dbStarted","dbConnects","beWOL","beAwake",
778  "success" };
779 
780  do
781  {
782  int wakeupTime = 3;
783  int attempts = 21;
784  if (m_DBparams.wolEnabled) {
785  wakeupTime = m_DBparams.wolReconnect;
786  attempts = m_DBparams.wolRetry + 1;
787  startupState = st_start;
788  }
789  else
790  startupState = st_dbAwake;
791  if (attempts < 6)
792  attempts = 6;
793  if (!prompt)
794  attempts=1;
795  if (wakeupTime < 5)
796  wakeupTime = 5;
797 
798  int progressTotal = wakeupTime * attempts;
799 
801  m_guiStartup->setTotal(progressTotal);
802 
803  QString beWOLCmd = QString();
804  QString backendIP = QString();
805  int backendPort = 0;
806  QString masterserver;
807 
808  for (int attempt = 0;
809  attempt < attempts && startupState != st_success;
810  ++attempt)
811  {
812  // The first time do everything with minimum timeout and
813  // no GUI, for the normal case where all is OK
814  // After that show the GUI (if this is a GUI program)
815 
816  LOG(VB_GENERAL, LOG_INFO,
817  QString("Start up testing connections. DB %1, BE %2, attempt %3, status %4")
818  .arg(host).arg(backendIP).arg(attempt).arg(guiStatuses[startupState]));
819 
820  int useTimeout = wakeupTime;
821  if (attempt == 0)
822  useTimeout=1;
823 
824  if (m_gui && !m_guiStartup)
825  {
826  if (attempt > 0)
827  {
828  ShowGuiStartup();
829  if (m_guiStartup)
830  m_guiStartup->setTotal(progressTotal);
831  }
832  }
834  {
835  if (attempt > 0)
836  m_guiStartup->setStatusState(guiStatuses[startupState]);
837  m_guiStartup->setMessageState("empty");
838  processEvents();
839  }
840  switch (startupState) {
841  case st_start:
843  {
844  if (attempt > 0)
846  if (!checkPort(host, port, useTimeout))
847  break;
848  }
849  startupState = st_dbAwake;
850  // Fall through to next case
851  case st_dbAwake:
852  if (!checkPort(host, port, useTimeout))
853  break;
854  startupState = st_dbStarted;
855  // Fall through to next case
856  case st_dbStarted:
857  // If the database is connecting with link-local
858  // address, it may have changed
859  if (m_DBparams.dbHostName != host)
860  {
861  m_DBparams.dbHostName = host;
862  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
863  }
864  EnableDBerrors();
865  ResetDatabase();
867  {
868  for (int temp = 0; temp < useTimeout * 2 ; temp++)
869  {
870  processEvents();
871  std::this_thread::sleep_for(std::chrono::milliseconds(500));
872  }
873  break;
874  }
875  startupState = st_dbConnects;
876  // Fall through to next case
877  case st_dbConnects:
878  if (needsBackend)
879  {
880  beWOLCmd = gCoreContext->GetSetting("WOLbackendCommand", "");
881  if (!beWOLCmd.isEmpty())
882  {
883  wakeupTime += gCoreContext->GetNumSetting
884  ("WOLbackendReconnectWaitTime", 0);
885  attempts += gCoreContext->GetNumSetting
886  ("WOLbackendConnectRetry", 0);
887  useTimeout = wakeupTime;
888  if (m_gui && !m_guiStartup && attempt == 0)
889  useTimeout=1;
890  progressTotal = wakeupTime * attempts;
892  m_guiStartup->setTotal(progressTotal);
893  startupState = st_beWOL;
894  }
895  }
896  else {
897  startupState = st_success;
898  break;
899  }
900  masterserver = gCoreContext->GetSetting
901  ("MasterServerName");
902  backendIP = gCoreContext->GetSettingOnHost
903  ("BackendServerAddr", masterserver);
904  backendPort = gCoreContext->GetMasterServerPort();
905  // Fall through to next case
906  case st_beWOL:
907  if (!beWOLCmd.isEmpty()) {
908  if (attempt > 0)
909  myth_system(beWOLCmd);
910  if (!checkPort(backendIP, backendPort, useTimeout))
911  break;
912  }
913  startupState = st_beAwake;
914  // Fall through to next case
915  case st_beAwake:
916  if (!checkPort(backendIP, backendPort, useTimeout))
917  break;
918  startupState = st_success;
919  }
920  if (m_guiStartup)
921  {
922  if (m_guiStartup->m_Exit
925  || m_guiStartup->m_Retry)
926  break;
927  }
928  processEvents();
929  }
930  if (startupState == st_success)
931  break;
932 
933  QString stateMsg = guiStatuses[startupState];
934  stateMsg.append("Fail");
935  LOG(VB_GENERAL, LOG_INFO,
936  QString("Start up failure. host %1, status %2")
937  .arg(host).arg(stateMsg));
938 
939  if (m_guiStartup
940  && !m_guiStartup->m_Exit
941  && !m_guiStartup->m_Setup
943  && !m_guiStartup->m_Retry)
944  {
946  m_guiStartup->setStatusState(stateMsg);
947  m_guiStartup->setMessageState("makeselection");
948  m_loop->exec();
949  }
950  }
951  while (m_guiStartup && m_guiStartup->m_Retry);
952 
953  if (startupState < st_dbAwake)
954  {
955  LOG(VB_GENERAL, LOG_WARNING, QString("Pinging to %1 failed, database will be unavailable").arg(host));
956  SilenceDBerrors();
957  err = QObject::tr(
958  "Cannot find (ping) database host %1 on the network",
959  "Backend Setup");
960  return err.arg(host);
961  }
962 
963  if (startupState < st_dbConnects)
964  {
965  SilenceDBerrors();
966  return QObject::tr("Cannot login to database", "Backend Setup");
967  }
968 
969  if (startupState < st_success)
970  {
971  return QObject::tr("Cannot connect to backend", "Backend Setup");
972  }
973 
974  // Current DB connection may have been silenced (invalid):
975  EnableDBerrors();
976  ResetDatabase();
978 
979  return QString::null;
980 }
981 
982 // Show the Gui Startup window.
983 // This is called if there is a delay in startup for any reason
984 // such as the database being unavailable
986 {
987  if (!m_gui)
988  return;
989  TempMainWindow(false);
990  MythMainWindow *mainWindow = GetMythMainWindow();
991  MythScreenStack *mainStack = mainWindow->GetMainStack();
992  if (mainStack) {
993  if (!m_guiStartup) {
994  m_guiStartup = new GUIStartup(mainStack,m_loop);
995  if (!m_guiStartup->Create()) {
996  delete m_guiStartup;
997  m_guiStartup = 0;
998  }
999  if (m_guiStartup) {
1000  mainStack->AddScreen(m_guiStartup, false);
1001  processEvents();
1002  }
1003  }
1004  }
1005 }
1006 
1016 {
1017  // This silences any DB errors from Get*Setting(),
1018  // (which is the vast majority of them)
1019  gCoreContext->GetDB()->SetSuppressDBMessages(true);
1020 
1021  // Save the configured hostname, so that we can
1022  // still display it in the DatabaseSettings screens
1023  if (m_DBparams.dbHostName.length())
1025 
1026  m_DBparams.dbHostName.clear();
1027  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
1028 }
1029 
1031 {
1032  // Restore (possibly) blanked hostname
1033  if (m_DBparams.dbHostName.isNull() && m_DBhostCp.length())
1034  {
1036  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
1037  }
1038 
1039  gCoreContext->GetDB()->SetSuppressDBMessages(false);
1040 }
1041 
1042 
1055 {
1057  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
1059 }
1060 
1065 {
1066  TempMainWindow();
1067 
1068  // Tell the user what went wrong:
1069  if (!error.isEmpty())
1070  {
1071  LOG(VB_GENERAL, LOG_ERR, QString("Error: %1").arg(error));
1072  ShowOkPopup(error);
1073  }
1074 
1075  LOG(VB_GENERAL, LOG_INFO, "Putting up the UPnP backend chooser");
1076 
1079 
1080  EndTempWindow();
1081 
1082  return (int)ret;
1083 }
1084 
1091 int MythContextPrivate::UPnPautoconf(const int milliSeconds)
1092 {
1093  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search %1 secs")
1094  .arg(milliSeconds / 1000));
1095 
1096  SSDP::Instance()->PerformSearch(gBackendURI, milliSeconds / 1000);
1097 
1098  // Search for a total of 'milliSeconds' ms, sending new search packet
1099  // about every 250 ms until less than one second remains.
1100  MythTimer totalTime; totalTime.start();
1101  MythTimer searchTime; searchTime.start();
1102  while (totalTime.elapsed() < milliSeconds)
1103  {
1104  usleep(25000);
1105  int ttl = milliSeconds - totalTime.elapsed();
1106  if ((searchTime.elapsed() > 249) && (ttl > 1000))
1107  {
1108  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search %1 secs")
1109  .arg(ttl / 1000));
1110  SSDP::Instance()->PerformSearch(gBackendURI, ttl / 1000);
1111  searchTime.start();
1112  }
1113  }
1114 
1116 
1117  if (!backends)
1118  {
1119  LOG(VB_GENERAL, LOG_INFO, "No UPnP backends found");
1120  return 0;
1121  }
1122 
1123  int count = backends->Count();
1124  if (count)
1125  {
1126  LOG(VB_GENERAL, LOG_INFO,
1127  QString("Found %1 UPnP backends").arg(count));
1128  }
1129  else
1130  {
1131  LOG(VB_GENERAL, LOG_ERR,
1132  "No UPnP backends found, but SSDP::Find() not NULL");
1133  }
1134 
1135  if (count != 1)
1136  {
1137  backends->DecrRef();
1138  return count;
1139  }
1140 
1141  // Get this backend's location:
1142  DeviceLocation *BE = backends->GetFirst();
1143  backends->DecrRef();
1144  backends = NULL;
1145 
1146  // We don't actually know the backend's access PIN, so this will
1147  // only work for ones that have PIN access disabled (i.e. 0000)
1148  int ret = (UPnPconnect(BE, QString::null)) ? 1 : -1;
1149 
1150  BE->DecrRef();
1151 
1152  return ret;
1153 }
1154 
1161 {
1162  QString loc = "DefaultUPnP() - ";
1163  QString PIN = m_pConfig->GetValue(kDefaultPIN, "");
1164  QString USN = m_pConfig->GetValue(kDefaultUSN, "");
1165 
1166  if (USN.isEmpty())
1167  {
1168  LOG(VB_UPNP, LOG_INFO, loc + "No default UPnP backend");
1169  return false;
1170  }
1171 
1172  LOG(VB_UPNP, LOG_INFO, loc + "config.xml has default " +
1173  QString("PIN '%1' and host USN: %2") .arg(PIN).arg(USN));
1174 
1175  // ----------------------------------------------------------------------
1176 
1177  int timeout_ms = 2000;
1178  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search up to %1 secs")
1179  .arg(timeout_ms / 1000));
1180  SSDP::Instance()->PerformSearch(gBackendURI, timeout_ms / 1000);
1181 
1182  // ----------------------------------------------------------------------
1183  // We need to give the server time to respond...
1184  // ----------------------------------------------------------------------
1185 
1186  DeviceLocation *pDevLoc = NULL;
1187  MythTimer totalTime; totalTime.start();
1188  MythTimer searchTime; searchTime.start();
1189  while (totalTime.elapsed() < timeout_ms)
1190  {
1191  pDevLoc = SSDP::Instance()->Find( gBackendURI, USN );
1192 
1193  if (pDevLoc)
1194  break;
1195 
1196  usleep(25000);
1197 
1198  int ttl = timeout_ms - totalTime.elapsed();
1199  if ((searchTime.elapsed() > 249) && (ttl > 1000))
1200  {
1201  LOG(VB_GENERAL, LOG_INFO, QString("UPNP Search up to %1 secs")
1202  .arg(ttl / 1000));
1203  SSDP::Instance()->PerformSearch(gBackendURI, ttl / 1000);
1204  searchTime.start();
1205  }
1206  }
1207 
1208  // ----------------------------------------------------------------------
1209 
1210  if (!pDevLoc)
1211  {
1212  error = "Cannot find default UPnP backend";
1213  return false;
1214  }
1215 
1216  if (UPnPconnect(pDevLoc, PIN))
1217  {
1218  pDevLoc->DecrRef();
1219  return true;
1220  }
1221 
1222  pDevLoc->DecrRef();
1223 
1224  error = "Cannot connect to default backend via UPnP. Wrong saved PIN?";
1225  return false;
1226 }
1227 
1232  const QString &PIN)
1233 {
1234  QString error;
1235  QString loc = "UPnPconnect() - ";
1236  QString URL = backend->m_sLocation;
1237  MythXMLClient client(URL);
1238 
1239  LOG(VB_UPNP, LOG_INFO, loc + QString("Trying host at %1").arg(URL));
1240  switch (client.GetConnectionInfo(PIN, &m_DBparams, error))
1241  {
1242  case UPnPResult_Success:
1243  gCoreContext->GetDB()->SetDatabaseParams(m_DBparams);
1244  LOG(VB_UPNP, LOG_INFO, loc +
1245  "Got database hostname: " + m_DBparams.dbHostName);
1246  return true;
1247 
1249  // The stored PIN is probably not correct.
1250  // We could prompt for the PIN and try again, but that needs a UI.
1251  // Easier to fail for now, and put up the full UI selector later
1252  LOG(VB_UPNP, LOG_ERR, loc + "Wrong PIN?");
1253  return false;
1254 
1255  default:
1256  LOG(VB_UPNP, LOG_ERR, loc + error);
1257  break;
1258  }
1259 
1260  // This backend may have a local DB with the default user/pass/DBname.
1261  // For whatever reason, we have failed to get anything back via UPnP,
1262  // so we might as well try the database directly as a last resort.
1263  QUrl theURL(URL);
1264  URL = theURL.host();
1265  if (URL.isEmpty())
1266  return false;
1267 
1268  LOG(VB_UPNP, LOG_INFO, "Trying default DB credentials at " + URL);
1270 
1271  return true;
1272 }
1273 
1275 {
1276  if (e->type() == (QEvent::Type) MythEvent::MythEventMessage)
1277  {
1278  if (disableeventpopup)
1279  return true;
1280 
1282  {
1284  }
1285 
1286  MythEvent *me = (MythEvent*)e;
1287  if (me->Message() == "VERSION_MISMATCH" && (1 == me->ExtraDataCount()))
1288  ShowVersionMismatchPopup(me->ExtraData(0).toUInt());
1289  else if (me->Message() == "CONNECTION_FAILURE")
1291  else if (me->Message() == "PERSISTENT_CONNECTION_FAILURE")
1293  else if (me->Message() == "CONNECTION_RESTABLISHED")
1295  return true;
1296  }
1297 
1298  return QObject::event(e);
1299 }
1300 
1302 {
1303  QDateTime now = MythDate::current();
1304 
1305  if (!GetNotificationCenter() || !m_ui || !m_ui->IsScreenSetup())
1306  return;
1307 
1308  if (m_lastCheck.isValid() && now < m_lastCheck)
1309  return;
1310 
1311  m_lastCheck = now.addMSecs(5000); // don't refresh notification more than every 5s
1312 
1313  QString description = (persistent) ?
1314  QObject::tr(
1315  "The connection to the master backend "
1316  "server has gone away for some reason. "
1317  "Is it running?") :
1318  QObject::tr(
1319  "Could not connect to the master backend server. Is "
1320  "it running? Is the IP address set for it in "
1321  "mythtv-setup correct?");
1322 
1323  QString message = QObject::tr("Could not connect to master backend");
1324  MythErrorNotification n(message, _Location, description);
1325  n.SetId(m_registration);
1326  n.SetParent(this);
1328 }
1329 
1331 {
1332  if (!GetNotificationCenter())
1333  return;
1334 
1335  if (!m_lastCheck.isValid())
1336  return;
1337 
1338  MythCheckNotification n(QObject::tr("Backend is online"), _Location);
1339  n.SetId(m_registration);
1340  n.SetParent(this);
1341  n.SetDuration(5);
1343  m_lastCheck = QDateTime();
1344 }
1345 
1347 {
1348  if (MBEversionPopup)
1349  return;
1350 
1351  QString message =
1352  QObject::tr(
1353  "The server uses network protocol version %1, "
1354  "but this client only understands version %2. "
1355  "Make sure you are running compatible versions of "
1356  "the backend and frontend.")
1357  .arg(remote_version).arg(MYTH_PROTO_VERSION);
1358 
1359  if (HasMythMainWindow() && m_ui && m_ui->IsScreenSetup())
1360  {
1362  message, m_sh, SLOT(VersionMismatchPopupClosed()));
1363  }
1364  else
1365  {
1366  LOG(VB_GENERAL, LOG_ERR, LOC + message);
1367  qApp->exit(GENERIC_EXIT_SOCKET_ERROR);
1368  }
1369 }
1370 
1371 // Process Events while waiting for connection
1372 // return true if progress is 100%
1374 {
1375 // bool ret = false;
1376 // if (m_guiStartup)
1377 // ret = m_guiStartup->updateProgress();
1378  qApp->processEvents(QEventLoop::AllEvents, 250);
1379  qApp->processEvents(QEventLoop::AllEvents, 250);
1380 // return ret;
1381 }
1382 
1383 // cache some settings in cache/contextcache.xml
1384 // only call this if the database is available.
1385 
1386 const QString MythContextPrivate::settingsToSave[] =
1387 { "Theme", "Language", "Country", "GuiHeight",
1388  "GuiOffsetX", "GuiOffsetY", "GuiWidth", "RunFrontendInWindow" };
1389 
1390 
1392 {
1393  QString cacheDirName = GetConfDir() + "/cache/";
1394  QDir dir(cacheDirName);
1395  dir.mkpath(cacheDirName);
1396  // remove prior cache in case it was corrupt
1397  QFile::remove(cacheDirName+"contextcache.xml");
1398  XmlConfiguration config = XmlConfiguration("cache/contextcache.xml");
1399 
1401 
1402  static const int arraySize = sizeof(settingsToSave)/sizeof(settingsToSave[0]);
1403  for (int ix = 0; ix < arraySize; ix++)
1404  {
1405  QString value = gCoreContext->GetSetting(settingsToSave[ix],QString());
1406  if (!value.isEmpty())
1407  config.SetValue("Settings/"+settingsToSave[ix],value);
1408  }
1409  return config.Save();
1410 }
1411 
1413 {
1414  XmlConfiguration config = XmlConfiguration("cache/contextcache.xml");
1415  static const int arraySize = sizeof(settingsToSave)/sizeof(settingsToSave[0]);
1416  for (int ix = 0; ix < arraySize; ix++)
1417  {
1418  QString value = config.GetValue("Settings/"+settingsToSave[ix],QString());
1419  if (!value.isEmpty())
1421  }
1422  // Prevent power off TV after temporary window
1423  gCoreContext->OverrideSettingForSession("PowerOffTVAllowed", 0);
1424 
1425  QString language = gCoreContext->GetSetting("Language",QString());
1426  MythTranslation::load("mythfrontend");
1427 }
1428 
1430 {
1431  QString language = gCoreContext->GetSetting("Language",QString());
1432  static const int arraySize = sizeof(settingsToSave)/sizeof(settingsToSave[0]);
1433  for (int ix = 0; ix < arraySize; ix++)
1434  {
1436  }
1437  // Restore power off TV setting
1438  gCoreContext->ClearOverrideSettingForSession("PowerOffTVAllowed");
1439 
1440  if (language != gCoreContext->GetSetting("Language",QString()))
1441  MythTranslation::load("mythfrontend");
1442 }
1443 
1444 
1446 {
1447  d->MBEversionPopup = NULL;
1448  qApp->exit(GENERIC_EXIT_SOCKET_ERROR);
1449 }
1450 
1451 MythContext::MythContext(const QString &binversion, bool needsBackend)
1452  : d(NULL), app_binary_version(binversion)
1453 {
1454 #ifdef _WIN32
1455  static bool WSAStarted = false;
1456  if (!WSAStarted) {
1457  WSADATA wsadata;
1458  int res = WSAStartup(MAKEWORD(2, 0), &wsadata);
1459  LOG(VB_SOCKET, LOG_INFO,
1460  QString("WSAStartup returned %1").arg(res));
1461  }
1462 #endif
1463 
1464  d = new MythContextPrivate(this);
1465  d->needsBackend = needsBackend;
1466 
1468 
1469  if (!gCoreContext || !gCoreContext->Init())
1470  {
1471  LOG(VB_GENERAL, LOG_EMERG, LOC + "Unable to allocate MythCoreContext");
1472  qApp->exit(GENERIC_EXIT_NO_MYTHCONTEXT);
1473  }
1474 }
1475 
1476 bool MythContext::Init(const bool gui,
1477  const bool promptForBackend,
1478  const bool disableAutoDiscovery,
1479  const bool ignoreDB)
1480 {
1481  if (!d)
1482  {
1483  LOG(VB_GENERAL, LOG_EMERG, LOC + "Init() Out-of-memory");
1484  return false;
1485  }
1486 
1487  if (app_binary_version != MYTH_BINARY_VERSION)
1488  {
1489  LOG(VB_GENERAL, LOG_EMERG,
1490  QString("Application binary version (%1) does not "
1491  "match libraries (%2)")
1492  .arg(app_binary_version) .arg(MYTH_BINARY_VERSION));
1493 
1494  QString warning = QObject::tr(
1495  "This application is not compatible "
1496  "with the installed MythTV libraries.");
1497  if (gui)
1498  {
1499  d->TempMainWindow(false);
1500  ShowOkPopup(warning);
1501  }
1502  LOG(VB_GENERAL, LOG_WARNING, warning);
1503 
1504  return false;
1505  }
1506 
1507 #ifdef _WIN32
1508  // HOME environment variable might not be defined
1509  // some libraries will fail without it
1510  QString home = getenv("HOME");
1511  if (home.isEmpty())
1512  {
1513  home = getenv("LOCALAPPDATA"); // Vista
1514  if (home.isEmpty())
1515  home = getenv("APPDATA"); // XP
1516  if (home.isEmpty())
1517  home = QString("."); // getenv("TEMP")?
1518 
1519  _putenv(QString("HOME=%1").arg(home).toLocal8Bit().constData());
1520  }
1521 #endif
1522 
1523  // If HOME isn't defined, we won't be able to use default confdir of
1524  // $HOME/.mythtv nor can we rely on a MYTHCONFDIR that references $HOME
1525  QString homedir = QDir::homePath();
1526  QString confdir = getenv("MYTHCONFDIR");
1527  if ((homedir.isEmpty() || homedir == "/") &&
1528  (confdir.isEmpty() || confdir.contains("$HOME")))
1529  {
1530  QString warning = "Cannot locate your home directory."
1531  " Please set the environment variable HOME";
1532  if (gui)
1533  {
1534  d->TempMainWindow(false);
1535  ShowOkPopup(warning);
1536  }
1537  LOG(VB_GENERAL, LOG_WARNING, warning);
1538 
1539  return false;
1540  }
1541 
1542  if (!d->Init(gui, promptForBackend, disableAutoDiscovery, ignoreDB))
1543  {
1544  return false;
1545  }
1546 
1548 
1549  return true;
1550 }
1551 
1553 {
1554  if (MThreadPool::globalInstance()->activeThreadCount())
1555  LOG(VB_GENERAL, LOG_INFO, "Waiting for threads to exit.");
1556 
1558  logStop();
1559 
1560  SSDP::Shutdown();
1562 
1563  delete gCoreContext;
1564  gCoreContext = NULL;
1565 
1566  delete d;
1567 }
1568 
1570 {
1571  d->disableeventpopup = check;
1572 }
1573 
1575 {
1576  return d->m_DBparams;
1577 }
1578 
1580 {
1581  return d->SaveDatabaseParams(params, false);
1582 }
1583 
1585 {
1586  return d->saveSettingsCache();
1587 }
1588 
1589 /* vim: set expandtab tabstop=4 shiftwidth=4: */
void SaveLocaleDefaults(void)
void ShowGuiStartup(void)
virtual bool Save(void)
Startup context for MythTV.
Definition: mythcontext.h:39
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:122
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)
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:58
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:132
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:82
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
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:81
QString GetConfDir(void)
Definition: mythdirs.cpp:212
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)
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:143
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:160
QEventLoop * m_loop
MythContextPrivate * d
Definition: mythcontext.h:57
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:881
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.
void Init(QString forcedpainter=QString())
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
virtual DialogCode exec(bool saveOnExec=true, bool doLoad=true)
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 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:479
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:26
virtual void SetValue(const QString &sSetting, int value)=0
bool m_gui
Should this context use GUI elements?