MythTV  master
mythcorecontext.cpp
Go to the documentation of this file.
1 // Qt
2 #include <QtGlobal>
3 #include <QCoreApplication>
4 #include <QUrl>
5 #include <QDir>
6 #include <QFileInfo>
7 #include <QDebug>
8 #include <QMutex>
9 #include <QRunnable>
10 #include <QWaitCondition>
11 #include <QAbstractSocket>
12 #include <QHostAddress>
13 #include <QHostInfo>
14 #include <QNetworkInterface>
15 #include <QNetworkAddressEntry>
16 #include <QLocale>
17 #include <QPair>
18 #include <QRegularExpression>
19 #include <QDateTime>
20 
21 // Std
22 #include <algorithm>
23 #include <cmath>
24 #include <cstdarg>
25 #include <queue>
26 #include <unistd.h> // for usleep()
27 
28 #ifdef _WIN32
29 #include <winsock2.h>
30 #else
31 #include <clocale>
32 #include <utility>
33 #endif
34 
35 // MythTV
36 #include "compat.h"
37 #include "mythdownloadmanager.h"
38 #include "mythcorecontext.h"
39 #include "mythsocket.h"
40 #include "mythsystemlegacy.h"
41 #include "mthreadpool.h"
42 #include "exitcodes.h"
43 #include "mythlogging.h"
44 #include "mythversion.h"
45 #include "logging.h"
46 #include "mthread.h"
47 #include "serverpool.h"
48 #include "mythdate.h"
49 #include "mythplugin.h"
50 #include "mythmiscutil.h"
51 #include "mythpower.h"
52 
53 #define LOC QString("MythCoreContext::%1(): ").arg(__func__)
54 
56 
57 class MythCoreContextPrivate : public QObject
58 {
59  public:
60  MythCoreContextPrivate(MythCoreContext *lparent, QString binversion,
61  QObject *guicontext);
62  ~MythCoreContextPrivate() override;
63 
64  bool WaitForWOL(std::chrono::milliseconds timeout = std::chrono::milliseconds::max());
65 
66  public:
67  MythCoreContext *m_parent { nullptr };
68  QObject *m_guiContext { nullptr };
69  QObject *m_guiObject { nullptr };
71 
72  QMutex m_localHostLock;
73  QString m_localHostname;
75  QString m_masterHostname;
76  QMutex m_scopesLock;
77  QMap<QString, QString> m_scopes;
78 
79  QMutex m_sockLock;
80  MythSocket *m_serverSock { nullptr };
81  MythSocket *m_eventSock { nullptr };
82 
85  bool m_wolInProgress { false };
86  bool m_isWOLAllowed { true };
87 
88  bool m_backend { false };
89  bool m_frontend { false };
90 
91  MythDB *m_database { nullptr };
92 
93  QThread *m_uiThread { nullptr };
94 
95  MythLocale *m_locale { nullptr };
96  QString m_language;
97 
98  MythScheduler *m_scheduler { nullptr };
99 
100  bool m_blockingClient { true };
101 
102  QMap<QObject *, MythCoreContext::PlaybackStartCb> m_playbackClients;
104  bool m_inwanting { false };
105  bool m_intvwanting { false };
106 
107  bool m_announcedProtocol { false };
108 
110 
111  bool m_isexiting { false };
112 
113  QMap<QString, QPair<int64_t, uint64_t> > m_fileswritten;
114  QMutex m_fileslock;
115 
117 
118  QList<QHostAddress> m_approvedIps;
119  QList<QHostAddress> m_deniedIps;
120 
121  MythPower *m_power { nullptr };
122 };
123 
125  QString binversion,
126  QObject *guicontext)
127  : m_parent(lparent),
128  m_guiContext(guicontext),
129  m_appBinaryVersion(std::move(binversion)),
130  m_database(GetMythDB()),
131  m_uiThread(QThread::currentThread())
132 {
133  MThread::ThreadSetup("CoreContext");
134 }
135 
136 static void delete_sock(
137 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
138  QMutexLocker &locker,
139 #else
140  QMutexLocker<QMutex> &locker,
141 #endif
142  MythSocket **s)
143 {
144  if (*s)
145  {
146  MythSocket *tmp = *s;
147  *s = nullptr;
148  locker.unlock();
149  tmp->DecrRef();
150  locker.relock();
151  }
152 }
153 
155 {
156  if (m_power)
157  MythPower::AcquireRelease(this, false);
158 
160 
161  {
162  QMutexLocker locker(&m_sockLock);
163  delete_sock(locker, &m_serverSock);
164  delete_sock(locker, &m_eventSock);
165  }
166 
167  delete m_locale;
168 
169  delete m_sessionManager;
170 
172 
174 
176 
177  // This has already been run in the MythContext dtor. Do we need it here
178  // too?
179 #if 0
180  logStop(); // need to shutdown db logger before we kill db
181 #endif
182 
184 
185  GetMythDB()->GetDBManager()->CloseDatabases();
186 
187  if (m_database) {
188  DestroyMythDB();
189  m_database = nullptr;
190  }
191 
193 }
194 
198 bool MythCoreContextPrivate::WaitForWOL(std::chrono::milliseconds timeout)
199 {
200  std::chrono::milliseconds timeout_remaining = timeout;
201  while (m_wolInProgress && (timeout_remaining > 0ms))
202  {
203  LOG(VB_GENERAL, LOG_INFO, LOC + "Wake-On-LAN in progress, waiting...");
204 
205  std::chrono::milliseconds max_wait = std::min(1000ms, timeout_remaining);
206  m_wolInProgressWaitCondition.wait(&m_wolInProgressLock, max_wait.count());
207  timeout_remaining -= max_wait;
208  }
209 
210  return !m_wolInProgress;
211 }
212 
213 MythCoreContext::MythCoreContext(const QString &binversion,
214  QObject *guiContext)
215 {
216  d = new MythCoreContextPrivate(this, binversion, guiContext);
217 }
218 
220 {
221  if (!d)
222  {
223  LOG(VB_GENERAL, LOG_EMERG, LOC + "Out-of-memory");
224  return false;
225  }
226 
227  if (d->m_appBinaryVersion != MYTH_BINARY_VERSION)
228  {
229  LOG(VB_GENERAL, LOG_CRIT,
230  QString("Application binary version (%1) does not "
231  "match libraries (%2)")
232  .arg(d->m_appBinaryVersion, MYTH_BINARY_VERSION));
233 
234  QString warning = tr("This application is not compatible with the "
235  "installed MythTV libraries. Please recompile "
236  "after a make distclean");
237  LOG(VB_GENERAL, LOG_WARNING, warning);
238 
239  return false;
240  }
241 
242 #ifndef _WIN32
243  static const QRegularExpression utf8
244  { "utf-?8", QRegularExpression::CaseInsensitiveOption };
245  QString lang_variables("");
246  QString lc_value = setlocale(LC_CTYPE, nullptr);
247  if (lc_value.isEmpty())
248  {
249  // try fallback to environment variables for non-glibc systems
250  // LC_ALL, then LC_CTYPE
251  lc_value = qEnvironmentVariable("LC_ALL");
252  if (lc_value.isEmpty())
253  lc_value = qEnvironmentVariable("LC_CTYPE");
254  }
255  if (!lc_value.contains(utf8))
256  lang_variables.append("LC_ALL or LC_CTYPE");
257  lc_value = qEnvironmentVariable("LANG");
258  if (!lc_value.contains(utf8))
259  {
260  if (!lang_variables.isEmpty())
261  lang_variables.append(", and ");
262  lang_variables.append("LANG");
263  }
264  LOG(VB_GENERAL, LOG_INFO, QString("Assumed character encoding: %1")
265  .arg(lc_value));
266  if (!lang_variables.isEmpty())
267  {
268  LOG(VB_GENERAL, LOG_WARNING, QString("This application expects to "
269  "be running a locale that specifies a UTF-8 codeset, and many "
270  "features may behave improperly with your current language "
271  "settings. Please set the %1 variable(s) in the environment "
272  "in which this program is executed to include a UTF-8 codeset "
273  "(such as 'en_US.UTF-8').").arg(lang_variables));
274  }
275 #endif
276 
277  return true;
278 }
279 
281 {
282  delete d;
283  d = nullptr;
284 }
285 
286 void MythCoreContext::setTestIntSettings(QMap<QString,int> &overrides)
287 {
288  m_testOverrideInts = std::move(overrides);
289 }
290 
291 void MythCoreContext::setTestFloatSettings(QMap<QString,double> &overrides)
292 {
293  m_testOverrideFloats = std::move(overrides);
294 }
295 
296 void MythCoreContext::setTestStringSettings(QMap<QString,QString> &overrides)
297 {
298  m_testOverrideStrings = std::move(overrides);
299 }
300 
302  const QString &announcement,
303  [[maybe_unused]] std::chrono::milliseconds timeout,
304  bool &proto_mismatch)
305 {
306  proto_mismatch = false;
307 
308 #ifndef IGNORE_PROTO_VER_MISMATCH
309  if (!CheckProtoVersion(serverSock, timeout, true))
310  {
311  proto_mismatch = true;
312  return false;
313  }
314 #endif
315 
316  QStringList strlist(announcement);
317 
318  if (!serverSock->WriteStringList(strlist))
319  {
320  LOG(VB_GENERAL, LOG_ERR, LOC + "Connecting server socket to "
321  "master backend, socket write failed");
322  return false;
323  }
324 
325  if (!serverSock->ReadStringList(strlist, MythSocket::kShortTimeout) ||
326  strlist.empty() || (strlist[0] == "ERROR"))
327  {
328  if (!strlist.empty())
329  {
330  LOG(VB_GENERAL, LOG_ERR, LOC + "Problem connecting "
331  "server socket to master backend");
332  }
333  else
334  {
335  LOG(VB_GENERAL, LOG_ERR, LOC + "Timeout connecting "
336  "server socket to master backend");
337  }
338  return false;
339  }
340 
341  return true;
342 }
343 
344 // Connects to master server safely (i.e. by taking m_sockLock)
346  bool openEventSocket)
347 {
348  QMutexLocker locker(&d->m_sockLock);
349  bool success = ConnectToMasterServer(blockingClient, openEventSocket);
350 
351  return success;
352 }
353 
354 // Assumes that either m_sockLock is held, or the app is still single
355 // threaded (i.e. during startup).
356 bool MythCoreContext::ConnectToMasterServer(bool blockingClient,
357  bool openEventSocket)
358 {
359  if (IsMasterBackend())
360  {
361  // Should never get here unless there is a bug in the code somewhere.
362  // If this happens, it can cause endless event loops.
363  LOG(VB_GENERAL, LOG_ERR, LOC + "ERROR: Master backend tried to connect back "
364  "to itself!");
365  return false;
366  }
367  if (IsExiting())
368  return false;
369 
370  QString server = GetMasterServerIP();
371  if (server.isEmpty())
372  return false;
373 
374  int port = GetMasterServerPort();
375  bool proto_mismatch = false;
376 
377  if (d->m_serverSock && !d->m_serverSock->IsConnected())
378  {
379  d->m_serverSock->DecrRef();
380  d->m_serverSock = nullptr;
381  }
382 
383  if (!d->m_serverSock)
384  {
385  QString type = IsFrontend() ? "Frontend" : (blockingClient ? "Playback" : "Monitor");
386  QString ann = QString("ANN %1 %2 %3")
387  .arg(type, d->m_localHostname, QString::number(static_cast<int>(false)));
389  server, port, ann, &proto_mismatch);
390  }
391 
392  if (!d->m_serverSock)
393  return false;
394 
395  d->m_blockingClient = blockingClient;
396 
397  if (!openEventSocket)
398  return true;
399 
400 
401  if (!IsBackend())
402  {
403  if (d->m_eventSock && !d->m_eventSock->IsConnected())
404  {
405  d->m_eventSock->DecrRef();
406  d->m_eventSock = nullptr;
407  }
408  if (!d->m_eventSock)
409  d->m_eventSock = ConnectEventSocket(server, port);
410 
411  if (!d->m_eventSock)
412  {
413  d->m_serverSock->DecrRef();
414  d->m_serverSock = nullptr;
415 
416  QCoreApplication::postEvent(
417  d->m_guiContext, new MythEvent("CONNECTION_FAILURE"));
418 
419  return false;
420  }
421  }
422 
423  return true;
424 }
425 
427  const QString &hostname, int port, const QString &announce,
428  bool *p_proto_mismatch, int maxConnTry, std::chrono::milliseconds setup_timeout)
429 {
430  MythSocket *serverSock = nullptr;
431 
432  {
433  QMutexLocker locker(&d->m_wolInProgressLock);
434  d->WaitForWOL();
435  }
436 
437  QString WOLcmd;
438  if (IsWOLAllowed())
439  WOLcmd = GetSetting("WOLbackendCommand", "");
440 
441  if (maxConnTry < 1)
442  maxConnTry = std::max(GetNumSetting("BackendConnectRetry", 1), 1);
443 
444  std::chrono::seconds WOLsleepTime = 0s;
445  int WOLmaxConnTry = 0;
446  if (!WOLcmd.isEmpty())
447  {
448  WOLsleepTime = GetDurSetting<std::chrono::seconds>("WOLbackendReconnectWaitTime", 0s);
449  WOLmaxConnTry = std::max(GetNumSetting("WOLbackendConnectRetry", 1), 1);
450  maxConnTry = std::max(maxConnTry, WOLmaxConnTry);
451  }
452 
453  bool we_attempted_wol = false;
454 
455  if (setup_timeout <= 0ms)
456  setup_timeout = MythSocket::kShortTimeout;
457 
458  bool proto_mismatch = false;
459  for (int cnt = 1; cnt <= maxConnTry; cnt++)
460  {
461  LOG(VB_GENERAL, LOG_INFO, LOC +
462  QString("Connecting to backend server: %1:%2 (try %3 of %4)")
463  .arg(hostname).arg(port).arg(cnt).arg(maxConnTry));
464 
465  serverSock = new MythSocket();
466 
467  std::chrono::microseconds sleepus = 0us;
468  if (serverSock->ConnectToHost(hostname, port))
469  {
470  if (SetupCommandSocket(
471  serverSock, announce, setup_timeout, proto_mismatch))
472  {
473  break;
474  }
475 
476  if (proto_mismatch)
477  {
478  if (p_proto_mismatch)
479  *p_proto_mismatch = true;
480 
481  serverSock->DecrRef();
482  serverSock = nullptr;
483  break;
484  }
485 
486  setup_timeout += setup_timeout / 2;
487  }
488  else if (!WOLcmd.isEmpty() && (cnt < maxConnTry))
489  {
490  if (!we_attempted_wol)
491  {
492  QMutexLocker locker(&d->m_wolInProgressLock);
493  if (d->m_wolInProgress)
494  {
495  d->WaitForWOL();
496  continue;
497  }
498 
499  d->m_wolInProgress = we_attempted_wol = true;
500  }
501 
504  sleepus = WOLsleepTime;
505  }
506 
507  serverSock->DecrRef();
508  serverSock = nullptr;
509 
510  if (cnt == 1)
511  {
512  QCoreApplication::postEvent(
513  d->m_guiContext, new MythEvent("CONNECTION_FAILURE"));
514  }
515 
516  if (sleepus != 0us)
517  usleep(sleepus.count());
518  }
519 
520  if (we_attempted_wol)
521  {
522  QMutexLocker locker(&d->m_wolInProgressLock);
523  d->m_wolInProgress = false;
524  d->m_wolInProgressWaitCondition.wakeAll();
525  }
526 
527  if (!serverSock && !proto_mismatch)
528  {
529  LOG(VB_GENERAL, LOG_ERR,
530  "Connection to master server timed out.\n\t\t\t"
531  "Either the server is down or the master server settings"
532  "\n\t\t\t"
533  "in mythtv-settings does not contain the proper IP address\n");
534  }
535  else
536  {
537  QCoreApplication::postEvent(
538  d->m_guiContext, new MythEvent("CONNECTION_RESTABLISHED"));
539  }
540 
541  return serverSock;
542 }
543 
545  int port)
546 {
547  auto *eventSock = new MythSocket(-1, this);
548 
549  // Assume that since we _just_ connected the command socket,
550  // this one won't need multiple retries to work...
551  if (!eventSock->ConnectToHost(hostname, port))
552  {
553  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to connect event "
554  "socket to master backend");
555  eventSock->DecrRef();
556  return nullptr;
557  }
558 
559  QString str = QString("ANN Monitor %1 %2")
560  .arg(d->m_localHostname).arg(static_cast<int>(true));
561  QStringList strlist(str);
562  eventSock->WriteStringList(strlist);
563  bool ok = true;
564  if (!eventSock->ReadStringList(strlist) || strlist.empty() ||
565  (strlist[0] == "ERROR"))
566  {
567  if (!strlist.empty())
568  {
569  LOG(VB_GENERAL, LOG_ERR, LOC +
570  "Problem connecting event socket to master backend");
571  }
572  else
573  {
574  LOG(VB_GENERAL, LOG_ERR, LOC +
575  "Timeout connecting event socket to master backend");
576  }
577  ok = false;
578  }
579 
580  if (!ok)
581  {
582  eventSock->DecrRef();
583  eventSock = nullptr;
584  }
585 
586  return eventSock;
587 }
588 
590 {
591  QMutexLocker locker(&d->m_sockLock);
592  return d->m_serverSock;
593 }
594 
596 {
597  QStringList strlist;
598 
599  QMutexLocker locker(&d->m_sockLock);
600  if (d->m_serverSock == nullptr)
601  return;
602 
603  strlist << "BLOCK_SHUTDOWN";
605 
606  d->m_blockingClient = true;
607 }
608 
610 {
611  QStringList strlist;
612 
613  QMutexLocker locker(&d->m_sockLock);
614  if (d->m_serverSock == nullptr)
615  return;
616 
617  strlist << "ALLOW_SHUTDOWN";
619 
620  d->m_blockingClient = false;
621 }
622 
624 {
625  return d->m_blockingClient;
626 }
627 
629 {
630  d->m_isWOLAllowed = allow;
631 }
632 
634 {
635  return d->m_isWOLAllowed;
636 }
637 
639 {
640  d->m_backend = backend;
641 }
642 
644 {
645  return d->m_backend;
646 }
647 
649 {
650  d->m_frontend = frontend;
651 }
652 
654 {
655  return d->m_frontend;
656 }
657 
659 {
660  QString host = GetHostName();
661  return IsMasterHost(host);
662 }
663 
664 bool MythCoreContext::IsMasterHost(const QString &host)
665 {
666  // Temporary code here only to facilitate the upgrade
667  // from 1346 or earlier. The way of determining master host is
668  // changing, and the new way of determning master host
669  // will not work with earlier databases.
670  // This code can be removed when updating from prior to
671  // 1347 is no longer allowed.
672  // Note that we are deprecating some settings including
673  // MasterServerIP, and can remove them at a future time.
674  if (GetNumSetting("DBSchemaVer") < 1347)
675  {
676  // Temporary copy of code from old version of
677  // IsThisHost(Qstring&,QString&)
678  QString addr(resolveSettingAddress("MasterServerIP"));
679  if (addr.toLower() == host.toLower())
680  return true;
681  QHostAddress addrfix(addr);
682  addrfix.setScopeId(QString());
683  QString addrstr = addrfix.toString();
684  if (addrfix.isNull())
685  addrstr = resolveAddress(addr);
686  QString thisip = GetBackendServerIP4(host);
687  QString thisip6 = GetBackendServerIP6(host);
688  return !addrstr.isEmpty()
689  && ((addrstr == thisip) || (addrstr == thisip6));
690  }
691  return GetSetting("MasterServerName") == host;
692 }
693 
695 {
696  return (IsBackend() && IsMasterHost());
697 }
698 
700 {
701 #if defined(Q_OS_DARWIN) || defined(__FreeBSD__) || defined(__OpenBSD__)
702  const char *command = "ps -axc | grep -i mythbackend | grep -v grep > /dev/null";
703 #elif defined _WIN32
704  const char *command = "%systemroot%\\system32\\tasklist.exe "
705  " | %systemroot%\\system32\\find.exe /i \"mythbackend.exe\" ";
706 #else
707  const char *command = "ps ch -C mythbackend -o pid > /dev/null";
708 #endif
709  uint res = myth_system(command, kMSDontBlockInputDevs |
712  return (res == GENERIC_EXIT_OK);
713 }
714 
715 bool MythCoreContext::IsThisBackend(const QString &addr)
716 {
717  return IsBackend() && IsThisHost(addr);
718 }
719 
720 bool MythCoreContext::IsThisHost(const QString &addr)
721 {
722  return IsThisHost(addr, GetHostName());
723 }
724 
725 bool MythCoreContext::IsThisHost(const QString &addr, const QString &host)
726 {
727  if (addr.toLower() == host.toLower())
728  return true;
729 
730  QHostAddress addrfix(addr);
731  addrfix.setScopeId(QString());
732  QString addrstr = addrfix.toString();
733 
734  if (addrfix.isNull())
735  {
736  addrstr = resolveAddress(addr);
737  }
738 
739  QString thisip = GetBackendServerIP(host);
740 
741  return !addrstr.isEmpty() && ((addrstr == thisip));
742 }
743 
745 {
746  // find out if a backend runs on this host...
747  bool backendOnLocalhost = false;
748 
749  QStringList strlist("QUERY_IS_ACTIVE_BACKEND");
750  strlist << GetHostName();
751 
752  SendReceiveStringList(strlist);
753 
754  backendOnLocalhost = strlist[0] != "FALSE";
755 
756  return !backendOnLocalhost;
757 }
758 
759 QString MythCoreContext::GenMythURL(const QString& host, int port, QString path, const QString& storageGroup)
760 {
761  QUrl ret;
762 
763  QString m_host;
764 
765  QHostAddress addr(host);
766  if (!addr.isNull())
767  {
768  LOG(VB_GENERAL, LOG_CRIT, LOC + QString("(%1/%2): Given "
769  "IP address instead of hostname "
770  "(ID). This is invalid.").arg(host, path));
771  }
772 
773  m_host = host;
774 
775  // Basically if it appears to be an IPv6 IP surround the IP with [] otherwise don't bother
776  if (!addr.isNull() && addr.protocol() == QAbstractSocket::IPv6Protocol)
777  m_host = "[" + addr.toString().toLower() + "]";
778 
779  ret.setScheme("myth");
780  if (!storageGroup.isEmpty())
781  ret.setUserName(storageGroup);
782  ret.setHost(m_host);
783  if (port > 0 && port != 6543)
784  ret.setPort(port);
785  if (!path.startsWith("/"))
786  path = QString("/") + path;
787  ret.setPath(path);
788 
789 #if 0
790  LOG(VB_GENERAL, LOG_DEBUG, LOC +
791  QString("GenMythURL returning %1").arg(ret.toString()));
792 #endif
793 
794  return ret.toString();
795 }
796 
797 QString MythCoreContext::GetMasterHostPrefix(const QString &storageGroup,
798  const QString &path)
799 {
800  return GenMythURL(GetMasterHostName(),
802  path,
803  storageGroup);
804 }
805 
807 {
808  QMutexLocker locker(&d->m_masterHostLock);
809 
810  if (d->m_masterHostname.isEmpty())
811  {
812 
813  if (IsMasterBackend())
815  else
816  {
817  QStringList strlist("QUERY_HOSTNAME");
818 
819  if (SendReceiveStringList(strlist))
820  d->m_masterHostname = strlist[0];
821  }
822  }
823 
824  return d->m_masterHostname;
825 }
826 
827 void MythCoreContext::ClearSettingsCache(const QString &myKey)
828 {
829  d->m_database->ClearSettingsCache(myKey);
830 }
831 
833 {
834  d->m_database->ActivateSettingsCache(activate);
835 }
836 
838 {
839  QMutexLocker locker(&d->m_localHostLock);
840  return d->m_localHostname;
841 }
842 
844 {
845  return GetSetting("RecordFilePrefix");
846 }
847 
849  int &width, int &height,
850  double &forced_aspect,
851  double &refresh_rate,
852  int index)
853 {
854  d->m_database->GetResolutionSetting(type, width, height, forced_aspect,
855  refresh_rate, index);
856 }
857 
858 void MythCoreContext::GetResolutionSetting(const QString &t, int &w,
859  int &h, int i)
860 {
861  d->m_database->GetResolutionSetting(t, w, h, i);
862 }
863 
865 {
866  return d->m_database->GetDBManager();
867 }
868 
876 {
877  return d->m_database->IsDatabaseIgnored();
878 }
879 
880 void MythCoreContext::SaveSetting(const QString &key, int newValue)
881 {
882  d->m_database->SaveSetting(key, newValue);
883 }
884 
885 void MythCoreContext::SaveSetting(const QString &key, const QString &newValue)
886 {
887  d->m_database->SaveSetting(key, newValue);
888 }
889 
890 bool MythCoreContext::SaveSettingOnHost(const QString &key,
891  const QString &newValue,
892  const QString &host)
893 {
894  return d->m_database->SaveSettingOnHost(key, newValue, host);
895 }
896 
897 QString MythCoreContext::GetSetting(const QString &key,
898  const QString &defaultval)
899 {
900  if (!m_testOverrideStrings.empty())
901  return m_testOverrideStrings[key];
902  return d->m_database->GetSetting(key, defaultval);
903 }
904 
905 bool MythCoreContext::GetBoolSetting(const QString &key, bool defaultval)
906 {
907  int result = GetNumSetting(key, static_cast<int>(defaultval));
908  return result > 0;
909 }
910 
911 int MythCoreContext::GetNumSetting(const QString &key, int defaultval)
912 {
913  if (!m_testOverrideInts.empty())
914  return m_testOverrideInts[key];
915  return d->m_database->GetNumSetting(key, defaultval);
916 }
917 
918 double MythCoreContext::GetFloatSetting(const QString &key, double defaultval)
919 {
920  if (!m_testOverrideFloats.empty())
921  return m_testOverrideFloats[key];
922  return d->m_database->GetFloatSetting(key, defaultval);
923 }
924 
925 QString MythCoreContext::GetSettingOnHost(const QString &key,
926  const QString &host,
927  const QString &defaultval)
928 {
929  if (!m_testOverrideStrings.empty())
930  return m_testOverrideStrings[key];
931  return d->m_database->GetSettingOnHost(key, host, defaultval);
932 }
933 
935  const QString &host,
936  bool defaultval)
937 {
938  int result = GetNumSettingOnHost(key, host, static_cast<int>(defaultval));
939  return result > 0;
940 }
941 
943  const QString &host,
944  int defaultval)
945 {
946  if (!m_testOverrideInts.empty())
947  return m_testOverrideInts[key];
948  return d->m_database->GetNumSettingOnHost(key, host, defaultval);
949 }
950 
951 double MythCoreContext::GetFloatSettingOnHost(const QString &key,
952  const QString &host,
953  double defaultval)
954 {
955  if (!m_testOverrideFloats.empty())
956  return m_testOverrideFloats[key];
957  return d->m_database->GetFloatSettingOnHost(key, host, defaultval);
958 }
959 
966 {
967  QString masterserver = gCoreContext->GetSetting("MasterServerName");
968  QString masterip = resolveSettingAddress("BackendServerAddr",masterserver);
969  // Even if empty, return it here if we were to assume that localhost
970  // should be used it just causes a lot of unnecessary error messages.
971  return masterip;
972 }
973 
980 {
981  QString masterserver = gCoreContext->GetSetting
982  ("MasterServerName");
984  ("BackendServerPort", masterserver, 6543);
985 }
986 
993 {
994  QString masterhost = GetMasterHostName();
995 
996  return GetBackendStatusPort(masterhost);
997 }
998 
1004 {
1006 }
1007 
1017 QString MythCoreContext::GetBackendServerIP(const QString &host)
1018 {
1019  return resolveSettingAddress("BackendServerAddr",host);
1020 }
1021 
1027 {
1029 }
1030 
1036 QString MythCoreContext::GetBackendServerIP4(const QString &host)
1037 {
1038  return resolveSettingAddress("BackendServerIP", host, ResolveIPv4);
1039 }
1040 
1046 {
1048 }
1049 
1055 QString MythCoreContext::GetBackendServerIP6(const QString &host)
1056 {
1057  return resolveSettingAddress("BackendServerIP6", host, ResolveIPv6);
1058 }
1059 
1064 {
1066 }
1067 
1068 QHash<QString,int> MythCoreContext::s_serverPortCache;
1069 
1071 {
1072  s_serverPortCache.clear();
1073 }
1074 
1079 {
1080  int port = s_serverPortCache.value(host, -1);
1081  if (port != -1)
1082  return port;
1083  port = GetNumSettingOnHost("BackendServerPort", host, 6543);
1084  s_serverPortCache[host] = port;
1085  return port;
1086 }
1087 
1092 {
1094 }
1095 
1100 {
1101  return GetNumSettingOnHost("BackendStatusPort", host, 6544);
1102 }
1103 
1108 bool MythCoreContext::GetScopeForAddress(QHostAddress &addr) const
1109 {
1110  QHostAddress addr1 = addr;
1111  addr1.setScopeId(QString());
1112  QString addrstr = addr1.toString();
1113  QMutexLocker lock(&d->m_scopesLock);
1114 
1115  if (!d->m_scopes.contains(addrstr))
1116  return false;
1117 
1118  addr.setScopeId(d->m_scopes[addrstr]);
1119  return true;
1120 }
1121 
1128 void MythCoreContext::SetScopeForAddress(const QHostAddress &addr)
1129 {
1130  QHostAddress addr1 = addr;
1131  addr1.setScopeId(QString());
1132  QMutexLocker lock(&d->m_scopesLock);
1133 
1134  d->m_scopes.insert(addr1.toString(), addr.scopeId());
1135 }
1136 
1142 void MythCoreContext::SetScopeForAddress(const QHostAddress &addr, int scope)
1143 {
1144  QHostAddress addr1 = addr;
1145  addr1.setScopeId(QString());
1146  QMutexLocker lock(&d->m_scopesLock);
1147 
1148  d->m_scopes.insert(addr1.toString(), QString::number(scope));
1149 }
1150 
1162 QString MythCoreContext::resolveSettingAddress(const QString &name,
1163  const QString &host,
1164  ResolveType type, bool keepscope)
1165 {
1166  QString value;
1167 
1168  if (host.isEmpty())
1169  {
1170  value = GetSetting(name);
1171  }
1172  else
1173  {
1174  value = GetSettingOnHost(name, host);
1175  }
1176 
1177  return resolveAddress(value, type, keepscope);
1178 }
1179 
1191 QString MythCoreContext::resolveAddress(const QString &host, ResolveType type,
1192  bool keepscope)
1193 {
1194  QHostAddress addr(host);
1195 
1196  if (!host.isEmpty() && addr.isNull())
1197  {
1198  // address is likely a hostname, attempts to resolve it
1199  QHostInfo info = QHostInfo::fromName(host);
1200  QList<QHostAddress> list = info.addresses();
1201 
1202  if (list.isEmpty())
1203  {
1204  LOG(VB_GENERAL, LOG_WARNING, LOC +
1205  QString("Can't resolve hostname:'%1', using localhost").arg(host));
1206  return type == ResolveIPv4 ? "127.0.0.1" : "::1";
1207  }
1208  QHostAddress v4;
1209  QHostAddress v6;
1210 
1211  // Return the first address fitting the type critera
1212  for (const auto& item : qAsConst(list))
1213  {
1214  addr = item;
1215  QAbstractSocket::NetworkLayerProtocol prot = addr.protocol();
1216 
1217  if (prot == QAbstractSocket::IPv4Protocol)
1218  {
1219  v4 = addr;
1220  if (type == 0)
1221  break;
1222  }
1223  else if (prot == QAbstractSocket::IPv6Protocol)
1224  {
1225  v6 = addr;
1226  if (type != 0)
1227  break;
1228  }
1229  }
1230  switch (type)
1231  {
1232  case ResolveIPv4:
1233  addr = v4.isNull() ? QHostAddress::LocalHost : v4;
1234  break;
1235  case ResolveIPv6:
1236  addr = v6.isNull() ? QHostAddress::LocalHostIPv6 : v6;
1237  break;
1238  default:
1239  addr = v6.isNull() ?
1240  (v4.isNull() ? QHostAddress::LocalHostIPv6 : v4) : v6;
1241  break;
1242  }
1243  }
1244  else if (host.isEmpty())
1245  {
1246  return {};
1247  }
1248 
1249  if (!keepscope)
1250  {
1251  addr.setScopeId(QString());
1252  }
1253  return addr.toString();
1254 }
1255 
1267 bool MythCoreContext::CheckSubnet(const QAbstractSocket *socket)
1268 {
1269  QHostAddress peer = socket->peerAddress();
1270  return CheckSubnet(peer);
1271 }
1272 
1284 bool MythCoreContext::CheckSubnet(const QHostAddress &peer)
1285 {
1286  static const QHostAddress kLinkLocal("fe80::");
1287  if (GetBoolSetting("AllowConnFromAll",false))
1288  return true;
1289  if (d->m_approvedIps.contains(peer))
1290  return true;
1291  if (d->m_deniedIps.contains(peer))
1292  {
1293  LOG(VB_GENERAL, LOG_WARNING, LOC +
1294  QString("Repeat denied connection from ip address: %1")
1295  .arg(peer.toString()));
1296  return false;
1297  }
1298 
1299  // allow all link-local
1300  if (peer.isInSubnet(kLinkLocal,10))
1301  {
1302  d->m_approvedIps.append(peer);
1303  return true;
1304  }
1305 
1306  // loop through all available interfaces
1307  QList<QNetworkInterface> IFs = QNetworkInterface::allInterfaces();
1308  for (const auto & qni : qAsConst(IFs))
1309  {
1310  if ((qni.flags() & QNetworkInterface::IsRunning) == 0)
1311  continue;
1312 
1313  QList<QNetworkAddressEntry> IPs = qni.addressEntries();
1314  for (const auto & qnai : qAsConst(IPs))
1315  {
1316  int pfxlen = qnai.prefixLength();
1317  // Set this to test rejection without having an extra
1318  // network.
1319  if (GetBoolSetting("DebugSubnet"))
1320  pfxlen += 4;
1321  if (peer.isInSubnet(qnai.ip(),pfxlen))
1322  {
1323  d->m_approvedIps.append(peer);
1324  return true;
1325  }
1326  }
1327  }
1328  d->m_deniedIps.append(peer);
1329  LOG(VB_GENERAL, LOG_WARNING, LOC +
1330  QString("Denied connection from ip address: %1")
1331  .arg(peer.toString()));
1332  return false;
1333 }
1334 
1335 
1337  const QString &value)
1338 {
1339  d->m_database->OverrideSettingForSession(key, value);
1340 }
1341 
1343 {
1344  d->m_database->ClearOverrideSettingForSession(key);
1345 }
1346 
1348 {
1349  return is_current_thread(d->m_uiThread);
1350 }
1351 
1371  QStringList &strlist, bool quickTimeout, bool block)
1372 {
1373  QString msg;
1374  if (HasGUI() && IsUIThread())
1375  {
1376  msg = "SendReceiveStringList(";
1377  for (uint i=0; i<(uint)strlist.size() && i<2; i++)
1378  msg += (i?",":"") + strlist[i];
1379  msg += (strlist.size() > 2) ? "...)" : ")";
1380  LOG(VB_GENERAL, LOG_DEBUG, LOC + msg + " called from UI thread");
1381  }
1382 
1383  QString query_type = "UNKNOWN";
1384 
1385  if (!strlist.isEmpty())
1386  query_type = strlist[0];
1387 
1388  QMutexLocker locker(&d->m_sockLock);
1389  if (!d->m_serverSock)
1390  {
1391  bool blockingClient = d->m_blockingClient &&
1392  (GetNumSetting("idleTimeoutSecs",0) > 0);
1393  ConnectToMasterServer(blockingClient);
1394  }
1395 
1396  bool ok = false;
1397 
1398  if (d->m_serverSock)
1399  {
1400  std::chrono::milliseconds timeout = quickTimeout ?
1402  ok = d->m_serverSock->SendReceiveStringList(strlist, 0, timeout);
1403 
1404  if (!ok)
1405  {
1406  LOG(VB_GENERAL, LOG_NOTICE, LOC +
1407  QString("Connection to backend server lost"));
1408  d->m_serverSock->DecrRef();
1409  d->m_serverSock = nullptr;
1410 
1411  if (d->m_eventSock)
1412  {
1413  d->m_eventSock->DecrRef();
1414  d->m_eventSock = nullptr;
1415  }
1416 
1417  if (block)
1418  {
1420 
1421  if (d->m_serverSock)
1422  {
1424  strlist, 0, timeout);
1425  }
1426  }
1427  }
1428 
1429  // this should not happen
1430  while (ok && strlist[0] == "BACKEND_MESSAGE")
1431  {
1432  // oops, not for us
1433  LOG(VB_GENERAL, LOG_EMERG, LOC + "SRSL you shouldn't see this!!");
1434  QString message = strlist[1];
1435  strlist.pop_front(); strlist.pop_front();
1436 
1437  MythEvent me(message, strlist);
1438  dispatch(me);
1439 
1440  ok = d->m_serverSock->ReadStringList(strlist, timeout);
1441  }
1442 
1443  if (!ok)
1444  {
1445  if (d->m_serverSock)
1446  {
1447  d->m_serverSock->DecrRef();
1448  d->m_serverSock = nullptr;
1449  }
1450 
1451  LOG(VB_GENERAL, LOG_CRIT, LOC +
1452  QString("Reconnection to backend server failed"));
1453 
1454  QCoreApplication::postEvent(d->m_guiContext,
1455  new MythEvent("PERSISTENT_CONNECTION_FAILURE"));
1456  }
1457  }
1458 
1459  if (ok)
1460  {
1461  if (strlist.isEmpty())
1462  ok = false;
1463  else if (strlist[0] == "ERROR")
1464  {
1465  if (strlist.size() == 2)
1466  {
1467  LOG(VB_GENERAL, LOG_INFO, LOC +
1468  QString("Protocol query '%1' responded with the error '%2'")
1469  .arg(query_type, strlist[1]));
1470  }
1471  else
1472  {
1473  LOG(VB_GENERAL, LOG_INFO, LOC +
1474  QString("Protocol query '%1' responded with an error, but "
1475  "no error message.") .arg(query_type));
1476  }
1477 
1478  ok = false;
1479  }
1480  else if (strlist[0] == "UNKNOWN_COMMAND")
1481  {
1482  LOG(VB_GENERAL, LOG_ERR, LOC +
1483  QString("Protocol query '%1' responded with the error 'UNKNOWN_COMMAND'")
1484  .arg(query_type));
1485 
1486  ok = false;
1487  }
1488  }
1489 
1490  return ok;
1491 }
1492 
1493 class SendAsyncMessage : public QRunnable
1494 {
1495  public:
1496  SendAsyncMessage(QString msg, QStringList extra) :
1497  m_message(std::move(msg)), m_extraData(std::move(extra))
1498  {
1499  }
1500 
1501  explicit SendAsyncMessage(QString msg) : m_message(std::move(msg)) { }
1502 
1503  void run(void) override // QRunnable
1504  {
1505  QStringList strlist("MESSAGE");
1506  strlist << m_message;
1507  strlist << m_extraData;
1509  }
1510 
1511  private:
1512  QString m_message;
1513  QStringList m_extraData;
1514 };
1515 
1516 void MythCoreContext::SendMessage(const QString &message)
1517 {
1518  if (IsBackend())
1519  {
1520  dispatch(MythEvent(message));
1521  }
1522  else
1523  {
1525  new SendAsyncMessage(message), "SendMessage");
1526  }
1527 }
1528 
1530 {
1531  if (IsBackend())
1532  {
1533  dispatch(event);
1534  }
1535  else
1536  {
1538  new SendAsyncMessage(event.Message(), event.ExtraDataList()),
1539  "SendEvent");
1540  }
1541 }
1542 
1543 void MythCoreContext::SendSystemEvent(const QString &msg)
1544 {
1545  if (QCoreApplication::applicationName() == MYTH_APPNAME_MYTHTV_SETUP)
1546  return;
1547 
1548  SendMessage(QString("SYSTEM_EVENT %1 SENDER %2")
1549  .arg(msg, GetHostName()));
1550 }
1551 
1553  const QString &hostname,
1554  const QString &args)
1555 {
1556  SendSystemEvent(QString("%1 HOST %2 %3").arg(msg, hostname, args));
1557 }
1558 
1559 
1561 {
1562  do
1563  {
1564  QStringList strlist;
1565  if (!sock->ReadStringList(strlist))
1566  continue;
1567 
1568  if (strlist.size() < 2)
1569  continue;
1570 
1571  QString prefix = strlist[0];
1572  QString message = strlist[1];
1573 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
1574  QStringList tokens = message.split(" ", QString::SkipEmptyParts);
1575 #else
1576  QStringList tokens = message.split(" ", Qt::SkipEmptyParts);
1577 #endif
1578 
1579  if (prefix == "OK")
1580  {
1581  }
1582  else if (prefix != "BACKEND_MESSAGE")
1583  {
1584  LOG(VB_NETWORK, LOG_ERR, LOC +
1585  QString("Received a: %1 message from the backend "
1586  "but I don't know what to do with it.")
1587  .arg(prefix));
1588  }
1589  else if (message == "CLEAR_SETTINGS_CACHE")
1590  {
1591  // No need to dispatch this message to ourself, so handle it
1592  LOG(VB_NETWORK, LOG_INFO, LOC + "Received remote 'Clear Cache' request");
1594  }
1595  else if (message.startsWith("FILE_WRITTEN"))
1596  {
1597  QString file;
1598  uint64_t size = 0;
1599  int NUMTOKENS = 3; // Number of tokens expected
1600 
1601  if (tokens.size() == NUMTOKENS)
1602  {
1603  file = tokens[1];
1604  size = tokens[2].toULongLong();
1605  }
1606  else
1607  {
1608  LOG(VB_NETWORK, LOG_ERR, LOC +
1609  QString("FILE_WRITTEN event received "
1610  "with invalid number of arguments, "
1611  "%1 expected, %2 actual")
1612  .arg(NUMTOKENS-1)
1613  .arg(tokens.size()-1));
1614  return;
1615  }
1616  // No need to dispatch this message to ourself, so handle it
1617  LOG(VB_NETWORK, LOG_INFO, LOC +
1618  QString("Received remote 'FILE_WRITTEN %1' request").arg(file));
1619  RegisterFileForWrite(file, size);
1620  }
1621  else if (message.startsWith("FILE_CLOSED"))
1622  {
1623  QString file;
1624  int NUMTOKENS = 2; // Number of tokens expected
1625 
1626  if (tokens.size() == NUMTOKENS)
1627  {
1628  file = tokens[1];
1629  }
1630  else
1631  {
1632  LOG(VB_NETWORK, LOG_ERR, LOC +
1633  QString("FILE_CLOSED event received "
1634  "with invalid number of arguments, "
1635  "%1 expected, %2 actual")
1636  .arg(NUMTOKENS-1)
1637  .arg(tokens.size()-1));
1638  return;
1639  }
1640  // No need to dispatch this message to ourself, so handle it
1641  LOG(VB_NETWORK, LOG_INFO, LOC +
1642  QString("Received remote 'FILE_CLOSED %1' request").arg(file));
1644  }
1645  else
1646  {
1647  strlist.pop_front();
1648  strlist.pop_front();
1649  MythEvent me(message, strlist);
1650  dispatch(me);
1651  }
1652  }
1653  while (sock->IsDataAvailable());
1654 }
1655 
1656 void MythCoreContext::connectionClosed([[maybe_unused]] MythSocket *sock)
1657 {
1658  LOG(VB_GENERAL, LOG_NOTICE, LOC +
1659  "Event socket closed. No connection to the backend.");
1660 
1661  dispatch(MythEvent("BACKEND_SOCKETS_CLOSED"));
1662 }
1663 
1665  std::chrono::milliseconds timeout,
1666  bool error_dialog_desired)
1667 {
1668  if (!socket)
1669  return false;
1670 
1671  QStringList strlist(QString("MYTH_PROTO_VERSION %1 %2")
1672  .arg(MYTH_PROTO_VERSION,
1673  QString::fromUtf8(MYTH_PROTO_TOKEN)));
1674  socket->WriteStringList(strlist);
1675 
1676  if (!socket->ReadStringList(strlist, timeout) || strlist.empty())
1677  {
1678  LOG(VB_GENERAL, LOG_CRIT, "Protocol version check failure.\n\t\t\t"
1679  "The response to MYTH_PROTO_VERSION was empty.\n\t\t\t"
1680  "This happens when the backend is too busy to respond,\n\t\t\t"
1681  "or has deadlocked due to bugs or hardware failure.");
1682 
1683  return false;
1684  }
1685  if (strlist[0] == "REJECT" && strlist.size() >= 2)
1686  {
1687  LOG(VB_GENERAL, LOG_CRIT, LOC + QString("Protocol version or token mismatch "
1688  "(frontend=%1/%2,backend=%3/\?\?)\n")
1689  .arg(MYTH_PROTO_VERSION,
1690  QString::fromUtf8(MYTH_PROTO_TOKEN),
1691  strlist[1]));
1692 
1693  if (error_dialog_desired && d->m_guiContext)
1694  {
1695  QStringList list(strlist[1]);
1696  QCoreApplication::postEvent(
1697  d->m_guiContext, new MythEvent("VERSION_MISMATCH", list));
1698  }
1699 
1700  return false;
1701  }
1702  if (strlist[0] == "ACCEPT")
1703  {
1704  if (!d->m_announcedProtocol)
1705  {
1706  d->m_announcedProtocol = true;
1707  LOG(VB_GENERAL, LOG_INFO, LOC +
1708  QString("Using protocol version %1 %2")
1709  .arg(MYTH_PROTO_VERSION,
1710  QString::fromUtf8(MYTH_PROTO_TOKEN)));
1711  }
1712 
1713  return true;
1714  }
1715 
1716  LOG(VB_GENERAL, LOG_ERR, LOC +
1717  QString("Unexpected response to MYTH_PROTO_VERSION: %1")
1718  .arg(strlist[0]));
1719  return false;
1720 }
1721 
1723 {
1724  LOG(VB_NETWORK, LOG_INFO, LOC + QString("MythEvent: %1").arg(event.Message()));
1725 
1726  MythObservable::dispatch(event);
1727 }
1728 
1730 {
1731  QMutexLocker locker(&d->m_localHostLock);
1733  d->m_database->SetLocalHostname(hostname);
1734 }
1735 
1737 {
1738  d->m_guiObject = gui;
1739 }
1740 
1741 bool MythCoreContext::HasGUI(void) const
1742 {
1743  return d->m_guiObject;
1744 }
1745 
1747 {
1748  return d->m_guiObject;
1749 }
1750 
1752 {
1753  return d->m_guiContext;
1754 }
1755 
1757 {
1758  return d->m_database;
1759 }
1760 
1762 {
1763  return d->m_locale;
1764 }
1765 
1771 {
1772  return GetLanguageAndVariant().left(2);
1773 }
1774 
1783 {
1784  if (d->m_language.isEmpty())
1785  d->m_language = GetSetting("Language", "en_US").toLower();
1786 
1787  return d->m_language;
1788 }
1789 
1791 {
1792  d->m_language.clear();
1793 }
1794 
1796 {
1797  QMutexLocker locker(&d->m_sockLock);
1798  LOG(VB_GENERAL, LOG_INFO, "Restarting Backend Connections");
1799  if (d->m_serverSock)
1801  if (d->m_eventSock)
1803  dispatch(MythEvent("BACKEND_SOCKETS_CLOSED"));
1804 }
1805 
1807 {
1808  if (Create && !d->m_power)
1809  {
1811  }
1812  else if (!Create && d->m_power)
1813  {
1814  MythPower::AcquireRelease(d, false);
1815  d->m_power = nullptr;
1816  }
1817 }
1818 
1820 {
1821  if (!d->m_locale)
1822  d->m_locale = new MythLocale();
1823 
1824  QString localeCode = d->m_locale->GetLocaleCode();
1825  LOG(VB_GENERAL, LOG_NOTICE, QString("Setting QT default locale to %1")
1826  .arg(localeCode));
1827  QLocale::setDefault(d->m_locale->ToQLocale());
1828 }
1829 
1831 {
1832  if (!d->m_locale)
1833  d->m_locale = new MythLocale();
1834  else
1835  d->m_locale->ReInit();
1836 
1837  QString localeCode = d->m_locale->GetLocaleCode();
1838  LOG(VB_GENERAL, LOG_NOTICE, QString("Setting QT default locale to %1")
1839  .arg(localeCode));
1840  QLocale::setDefault(d->m_locale->ToQLocale());
1841 }
1842 
1844 {
1845  if (!d->m_locale)
1846  InitLocale();
1847 
1848  return d->m_locale->ToQLocale();
1849 }
1850 
1852 {
1853  if (!d->m_locale)
1854  InitLocale();
1855 
1856  if (!d->m_locale->GetLocaleCode().isEmpty())
1857  {
1858  LOG(VB_GENERAL, LOG_INFO,
1859  QString("Current locale %1") .arg(d->m_locale->GetLocaleCode()));
1860 
1862  return;
1863  }
1864 
1865  LOG(VB_GENERAL, LOG_ERR, LOC +
1866  "No locale defined! We weren't able to set locale defaults.");
1867 }
1868 
1870 {
1871  d->m_scheduler = sched;
1872 }
1873 
1875 {
1876  return d->m_scheduler;
1877 }
1878 
1883 void MythCoreContext::WaitUntilSignals(std::vector<CoreWaitInfo> & sigs) const
1884 {
1885  if (sigs.empty())
1886  return;
1887 
1888  QEventLoop eventLoop;
1889  for (const auto& s : sigs)
1890  {
1891  LOG(VB_GENERAL, LOG_DEBUG, LOC +
1892  QString("Waiting for signal %1")
1893  .arg(s.name));
1894  connect(this, s.fn, &eventLoop, &QEventLoop::quit);// clazy:exclude connect-non-signal
1895  }
1896 
1897  eventLoop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
1898 }
1899 
1907 {
1908  if (!sender || !method)
1909  return;
1910 
1911  QMutexLocker lock(&d->m_playbackLock);
1912 
1913  if (!d->m_playbackClients.contains(sender))
1914  {
1915  d->m_playbackClients.insert(sender, method);
1917  sender, method,
1918  Qt::BlockingQueuedConnection);
1919  }
1920 }
1921 
1928 {
1929  QMutexLocker lock(&d->m_playbackLock);
1930 
1931  if (d->m_playbackClients.contains(sender))
1932  {
1933  PlaybackStartCb method = d->m_playbackClients.value(sender);
1934  disconnect(this, &MythCoreContext::TVPlaybackAboutToStart,
1935  sender, method);
1936  d->m_playbackClients.remove(sender);
1937  }
1938 }
1939 
1947 {
1948  QMutexLocker lock(&d->m_playbackLock);
1949  PlaybackStartCb method { nullptr };
1950  d->m_inwanting = true;
1951 
1952  // If any registered client are in the same thread, they will deadlock, so rebuild
1953  // connections for any clients in the same thread as non-blocking connection
1954  QThread *currentThread = QThread::currentThread();
1955 
1956  QMap<QObject *, PlaybackStartCb>::iterator it = d->m_playbackClients.begin();
1957  for (; it != d->m_playbackClients.end(); ++it)
1958  {
1959  if (it.key() == sender)
1960  continue; // will be done separately, no need to do it again
1961 
1962  QThread *thread = it.key()->thread();
1963 
1964  if (thread != currentThread)
1965  continue;
1966 
1967  disconnect(this, &MythCoreContext::TVPlaybackAboutToStart, it.key(), it.value());
1968  connect(this, &MythCoreContext::TVPlaybackAboutToStart, it.key(), it.value());
1969  }
1970 
1971  // disconnect sender so it won't receive the message
1972  if (d->m_playbackClients.contains(sender))
1973  {
1974  method = d->m_playbackClients.value(sender);
1975  disconnect(this, &MythCoreContext::TVPlaybackAboutToStart, sender, method);
1976  }
1977 
1978  // emit signal
1979  emit TVPlaybackAboutToStart();
1980 
1981  // reconnect sender
1982  if (method)
1983  {
1985  sender, method,
1986  Qt::BlockingQueuedConnection);
1987  }
1988  // Restore blocking connections
1989  for (; it != d->m_playbackClients.end(); ++it)
1990  {
1991  if (it.key() == sender)
1992  continue; // already done above, no need to do it again
1993 
1994  QThread *thread = it.key()->thread();
1995 
1996  if (thread != currentThread)
1997  continue;
1998 
1999  disconnect(this, &MythCoreContext::TVPlaybackAboutToStart,
2000  it.key(), it.value());
2002  it.key(), it.value(), Qt::BlockingQueuedConnection);
2003  }
2004  d->m_inwanting = false;
2005 }
2006 
2013 {
2014  // when called, it will be while the m_playbackLock is held
2015  // following a call to WantingPlayback
2016  d->m_intvwanting = b;
2017 }
2018 
2025 {
2026  bool locked = d->m_playbackLock.tryLock();
2027  bool intvplayback = d->m_intvwanting;
2028 
2029  if (!locked && d->m_inwanting)
2030  return true; // we're in the middle of WantingPlayback
2031 
2032  if (!locked)
2033  return false;
2034 
2035  d->m_playbackLock.unlock();
2036 
2037  return intvplayback;
2038 }
2039 
2041 {
2042  if (!d->m_sessionManager)
2044 
2045  return d->m_sessionManager;
2046 }
2047 
2048 bool MythCoreContext::TestPluginVersion(const QString &name,
2049  const QString &libversion,
2050  const QString &pluginversion)
2051 {
2052  if (libversion == pluginversion)
2053  return true;
2054 
2055  LOG(VB_GENERAL, LOG_EMERG, LOC +
2056  QString("Plugin %1 (%2) binary version does not "
2057  "match libraries (%3)")
2058  .arg(name, pluginversion, libversion));
2059  return false;
2060 }
2061 
2063 {
2064  if (d->m_pluginmanager == pmanager)
2065  return;
2066 
2067  if (d->m_pluginmanager)
2068  {
2069  delete d->m_pluginmanager;
2070  d->m_pluginmanager = nullptr;
2071  }
2072 
2073  d->m_pluginmanager = pmanager;
2074 }
2075 
2077 {
2078  return d->m_pluginmanager;
2079 }
2080 
2082 {
2083  d->m_isexiting = exiting;
2084 }
2085 
2087 {
2088  return d->m_isexiting;
2089 }
2090 
2091 void MythCoreContext::RegisterFileForWrite(const QString& file, uint64_t size)
2092 {
2093  QMutexLocker lock(&d->m_fileslock);
2094 
2095  QPair<int64_t, uint64_t> pair(QDateTime::currentMSecsSinceEpoch(), size);
2096  d->m_fileswritten.insert(file, pair);
2097 
2098  if (IsBackend())
2099  {
2100  QString message = QString("FILE_WRITTEN %1 %2").arg(file).arg(size);
2101  MythEvent me(message);
2102  dispatch(me);
2103  }
2104 
2105  LOG(VB_FILE, LOG_DEBUG, LOC +
2106  QString("%1").arg(file));
2107 }
2108 
2110 {
2111  QMutexLocker lock(&d->m_fileslock);
2112 
2113  d->m_fileswritten.remove(file);
2114 
2115  if (IsBackend())
2116  {
2117  QString message = QString("FILE_CLOSED %1").arg(file);
2118  MythEvent me(message);
2119  dispatch(me);
2120  }
2121 
2122  LOG(VB_FILE, LOG_DEBUG, LOC +
2123  QString("%1").arg(file));
2124 }
2125 
2127 {
2128  QMutexLocker lock(&d->m_fileslock);
2129 
2130  return d->m_fileswritten.contains(file);
2131 }
2132 
2133 /* vim: set expandtab tabstop=4 shiftwidth=4: */
MythCoreContext::resolveSettingAddress
QString resolveSettingAddress(const QString &name, const QString &host=QString(), ResolveType type=ResolveAny, bool keepscope=false)
Retrieve IP setting "name" for "host".
Definition: mythcorecontext.cpp:1162
MythCoreContext::SetPluginManager
void SetPluginManager(MythPluginManager *pmanager)
Definition: mythcorecontext.cpp:2062
loggingDeregisterThread
void loggingDeregisterThread(void)
Deregister the current thread's name.
Definition: logging.cpp:703
MythCoreContext::SetWOLAllowed
void SetWOLAllowed(bool allow)
Definition: mythcorecontext.cpp:628
build_compdb.args
args
Definition: build_compdb.py:11
DestroyMythDB
void DestroyMythDB(void)
Definition: mythdb.cpp:55
MythLocale::ReInit
void ReInit()
Definition: mythlocale.cpp:52
MythCoreContextPrivate::WaitForWOL
bool WaitForWOL(std::chrono::milliseconds timeout=std::chrono::milliseconds::max())
If another thread has already started WOL process, wait on them...
Definition: mythcorecontext.cpp:198
MythCoreContext::SendMessage
void SendMessage(const QString &message)
Definition: mythcorecontext.cpp:1516
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
MythCoreContext::GetMasterHostName
QString GetMasterHostName(void)
Definition: mythcorecontext.cpp:806
MythPower
Definition: mythpower.h:23
MythPluginManager
Definition: mythplugin.h:62
MythCoreContextPrivate::m_fileswritten
QMap< QString, QPair< int64_t, uint64_t > > m_fileswritten
Definition: mythcorecontext.cpp:113
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
MythScheduler
This is an generic interface to a program scheduler.
Definition: mythscheduler.h:17
kMSDontBlockInputDevs
@ kMSDontBlockInputDevs
avoid blocking LIRC & Joystick Menu
Definition: mythsystem.h:36
MythCoreContext::GetScheduler
MythScheduler * GetScheduler(void)
Definition: mythcorecontext.cpp:1874
MythCoreContext::SendReceiveStringList
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
Definition: mythcorecontext.cpp:1370
MythCoreContext::IsBlockingClient
bool IsBlockingClient(void) const
is this client blocking shutdown
Definition: mythcorecontext.cpp:623
MythCoreContext::IsFrontendOnly
bool IsFrontendOnly(void)
is there a frontend, but no backend, running on this host
Definition: mythcorecontext.cpp:744
MythCoreContext::AllowShutdown
void AllowShutdown(void)
Definition: mythcorecontext.cpp:609
MythCoreContextPrivate::m_masterHostLock
QMutex m_masterHostLock
Locking for m_masterHostname.
Definition: mythcorecontext.cpp:74
MythCoreContext::ResetSockets
void ResetSockets(void)
Definition: mythcorecontext.cpp:1795
MythLocale
Definition: mythlocale.h:12
MythCoreContext::GetDBManager
MDBManager * GetDBManager(void)
Definition: mythcorecontext.cpp:864
MythCoreContext::UnregisterFileForWrite
void UnregisterFileForWrite(const QString &file)
Definition: mythcorecontext.cpp:2109
MythCoreContext::ConnectToMasterServer
bool ConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
Definition: mythcorecontext.cpp:356
MythCoreContextPrivate::m_eventSock
MythSocket * m_eventSock
socket events arrive on
Definition: mythcorecontext.cpp:81
MythCoreContext::GetLocale
MythLocale * GetLocale(void) const
Definition: mythcorecontext.cpp:1761
MythCoreContext::~MythCoreContext
~MythCoreContext() override
Definition: mythcorecontext.cpp:280
mythplugin.h
MythCoreContext::InitLocale
void InitLocale(void)
Definition: mythcorecontext.cpp:1819
ShutdownMythDownloadManager
void ShutdownMythDownloadManager(void)
Deletes the running MythDownloadManager at program exit.
Definition: mythdownloadmanager.cpp:133
MythCoreContext::SetScheduler
void SetScheduler(MythScheduler *sched)
Definition: mythcorecontext.cpp:1869
MythCoreContext::GetBackendStatusPort
int GetBackendStatusPort(void)
Returns the locally defined backend status port.
Definition: mythcorecontext.cpp:1091
MythCoreContext::OverrideSettingForSession
void OverrideSettingForSession(const QString &key, const QString &value)
Definition: mythcorecontext.cpp:1336
MDBManager
DB connection pool, used by MSqlQuery. Do not use directly.
Definition: mythdbcon.h:55
MythCoreContextPrivate::m_backend
bool m_backend
Definition: mythcorecontext.cpp:88
MythLocale::ToQLocale
QLocale ToQLocale() const
Definition: mythlocale.h:29
MythCoreContext::s_serverPortCache
static QHash< QString, int > s_serverPortCache
Definition: mythcorecontext.h:207
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
MythCoreContextPrivate::m_appBinaryVersion
QString m_appBinaryVersion
Definition: mythcorecontext.cpp:70
sched
Scheduler * sched
MythCoreContext::RegisterFileForWrite
void RegisterFileForWrite(const QString &file, uint64_t size=0LL)
Definition: mythcorecontext.cpp:2091
MythCoreContext::IsDatabaseIgnored
bool IsDatabaseIgnored(void) const
/brief Returns true if database is being ignored.
Definition: mythcorecontext.cpp:875
MythCoreContext::GetGUIObject
QObject * GetGUIObject(void)
Definition: mythcorecontext.cpp:1746
MythCoreContext::GetFilePrefix
QString GetFilePrefix(void)
Definition: mythcorecontext.cpp:843
MythCoreContext::IsUIThread
bool IsUIThread(void)
Definition: mythcorecontext.cpp:1347
MythCoreContext::connectionClosed
void connectionClosed(MythSocket *sock) override
Definition: mythcorecontext.cpp:1656
MythSocket::DisconnectFromHost
void DisconnectFromHost(void)
Definition: mythsocket.cpp:504
MythCoreContext::CheckProtoVersion
bool CheckProtoVersion(MythSocket *socket, std::chrono::milliseconds timeout=kMythSocketLongTimeout, bool error_dialog_desired=false)
Definition: mythcorecontext.cpp:1664
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
is_current_thread
bool is_current_thread(MThread *thread)
Use this to determine if you are in the named thread.
Definition: mthread.cpp:40
MythCoreContextPrivate::m_blockingClient
bool m_blockingClient
Definition: mythcorecontext.cpp:100
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:50
MythCoreContext::TestPluginVersion
static bool TestPluginVersion(const QString &name, const QString &libversion, const QString &pluginversion)
Definition: mythcorecontext.cpp:2048
build_compdb.file
file
Definition: build_compdb.py:55
MythCoreContextPrivate::m_intvwanting
bool m_intvwanting
Definition: mythcorecontext.cpp:105
MythObservable::dispatch
void dispatch(const MythEvent &event)
Dispatch an event to all listeners.
Definition: mythobservable.cpp:73
myth_system
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
Definition: mythsystemlegacy.cpp:506
GENERIC_EXIT_OK
@ GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:11
MythCoreContext::GetScopeForAddress
bool GetScopeForAddress(QHostAddress &addr) const
Return the cached scope Id for the given address.
Definition: mythcorecontext.cpp:1108
MythSocket::ConnectToHost
bool ConnectToHost(const QString &hostname, quint16 port)
connect to host
Definition: mythsocket.cpp:380
MythCoreContext::setTestStringSettings
void setTestStringSettings(QMap< QString, QString > &overrides)
Definition: mythcorecontext.cpp:296
MythCoreContext::InitPower
void InitPower(bool Create=true)
Definition: mythcorecontext.cpp:1806
MythCoreContext::SafeConnectToMasterServer
bool SafeConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
Definition: mythcorecontext.cpp:345
hardwareprofile.distros.mythtv_data.data_mythtv.prefix
string prefix
Definition: data_mythtv.py:40
MythEvent::Message
const QString & Message() const
Definition: mythevent.h:65
MythSocket::IsConnected
bool IsConnected(void) const
Definition: mythsocket.cpp:557
MythCoreContextPrivate::m_wolInProgressWaitCondition
QWaitCondition m_wolInProgressWaitCondition
Definition: mythcorecontext.cpp:84
MythCoreContextPrivate::m_database
MythDB * m_database
Definition: mythcorecontext.cpp:91
MythCoreContext::GetMasterServerStatusPort
int GetMasterServerStatusPort(void)
Returns the Master Backend status port If no master server status port has been defined in the databa...
Definition: mythcorecontext.cpp:992
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
MythCoreContextPrivate::m_scopesLock
QMutex m_scopesLock
Locking for m_masterHostname.
Definition: mythcorecontext.cpp:76
mythsystemlegacy.h
SendAsyncMessage::SendAsyncMessage
SendAsyncMessage(QString msg, QStringList extra)
Definition: mythcorecontext.cpp:1496
MYTH_APPNAME_MYTHTV_SETUP
static constexpr const char * MYTH_APPNAME_MYTHTV_SETUP
Definition: mythcorecontext.h:23
MythCoreContext::SendHostSystemEvent
void SendHostSystemEvent(const QString &msg, const QString &hostname, const QString &args)
Definition: mythcorecontext.cpp:1552
MythCoreContextPrivate::m_pluginmanager
MythPluginManager * m_pluginmanager
Definition: mythcorecontext.cpp:109
LOC
#define LOC
Definition: mythcorecontext.cpp:53
MythSocket
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:25
MythCoreContext::ClearOverrideSettingForSession
void ClearOverrideSettingForSession(const QString &key)
Definition: mythcorecontext.cpp:1342
MythCoreContext::IsConnectedToMaster
bool IsConnectedToMaster(void)
Definition: mythcorecontext.cpp:589
MythCoreContext::MythCoreContext
MythCoreContext(const QString &binversion, QObject *guiContext)
Definition: mythcorecontext.cpp:213
quit
@ quit
Definition: lirc_client.h:30
MThreadPool::ShutdownAllPools
static void ShutdownAllPools(void)
Definition: mthreadpool.cpp:336
MythCoreContext::UnregisterForPlayback
void UnregisterForPlayback(QObject *sender)
Definition: mythcorecontext.cpp:1927
MythCoreContext::IsRegisteredFileForWrite
bool IsRegisteredFileForWrite(const QString &file)
Definition: mythcorecontext.cpp:2126
MythCoreContext::IsMasterBackend
bool IsMasterBackend(void)
is this the actual MBE process
Definition: mythcorecontext.cpp:694
MythCoreContextPrivate::m_playbackLock
QMutex m_playbackLock
Definition: mythcorecontext.cpp:103
mythdate.h
MythCoreContextPrivate::m_localHostname
QString m_localHostname
hostname from config.xml or gethostname()
Definition: mythcorecontext.cpp:73
MythCoreContextPrivate::m_isWOLAllowed
bool m_isWOLAllowed
Definition: mythcorecontext.cpp:86
mythlogging.h
MythCoreContext::Init
bool Init(void)
Definition: mythcorecontext.cpp:219
MythCoreContext::GenMythURL
static QString GenMythURL(const QString &host=QString(), int port=0, QString path=QString(), const QString &storageGroup=QString())
Definition: mythcorecontext.cpp:759
MythCoreContext::GetGUIContext
QObject * GetGUIContext(void)
Definition: mythcorecontext.cpp:1751
MythCoreContext::GetQLocale
QLocale GetQLocale(void)
Definition: mythcorecontext.cpp:1843
MythCoreContext::BackendIsRunning
static bool BackendIsRunning(void)
a backend process is running on this host
Definition: mythcorecontext.cpp:699
MythSocket::WriteStringList
bool WriteStringList(const QStringList &list)
Definition: mythsocket.cpp:307
MythCoreContext::SetAsFrontend
void SetAsFrontend(bool frontend)
Definition: mythcorecontext.cpp:648
MThreadPool::StopAllPools
static void StopAllPools(void)
Definition: mthreadpool.cpp:325
MythCoreContext::GetBackendServerPort
int GetBackendServerPort(void)
Returns the locally defined backend control port.
Definition: mythcorecontext.cpp:1063
MythCoreContext::SendSystemEvent
void SendSystemEvent(const QString &msg)
Definition: mythcorecontext.cpp:1543
MythCoreContextPrivate::m_isexiting
bool m_isexiting
Definition: mythcorecontext.cpp:111
MythCoreContext::SendEvent
void SendEvent(const MythEvent &event)
Definition: mythcorecontext.cpp:1529
MythCoreContext::GetMasterServerIP
QString GetMasterServerIP(void)
Returns the Master Backend IP address If the address is an IPv6 address, the scope Id is removed.
Definition: mythcorecontext.cpp:965
MythCoreContext::WaitUntilSignals
void WaitUntilSignals(std::vector< CoreWaitInfo > &sigs) const
Wait until any of the provided signals have been received.
Definition: mythcorecontext.cpp:1883
MythCoreContextPrivate::m_parent
MythCoreContext * m_parent
Definition: mythcorecontext.cpp:67
hardwareprofile.i18n.t
t
Definition: i18n.py:36
MythCoreContextPrivate::m_frontend
bool m_frontend
Definition: mythcorecontext.cpp:89
compat.h
MythPower::AcquireRelease
static MythPower * AcquireRelease(void *Reference, bool Acquire, std::chrono::seconds MinimumDelay=0s)
Definition: mythpower.cpp:75
MythCoreContext::GetBackendServerIP
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
Definition: mythcorecontext.cpp:1003
MythCoreContextPrivate::m_sessionManager
MythSessionManager * m_sessionManager
Definition: mythcorecontext.cpp:116
MythCoreContext::IsFrontend
bool IsFrontend(void) const
is this process a frontend process
Definition: mythcorecontext.cpp:653
MythCoreContextPrivate::m_guiObject
QObject * m_guiObject
Definition: mythcorecontext.cpp:69
MythCoreContext::GetDB
MythDB * GetDB(void)
Definition: mythcorecontext.cpp:1756
MythCoreContext::readyRead
void readyRead(MythSocket *sock) override
Definition: mythcorecontext.cpp:1560
MythWakeup
bool MythWakeup(const QString &wakeUpCommand, uint flags, std::chrono::seconds timeout)
Definition: mythmiscutil.cpp:630
MythCoreContext::GetNumSettingOnHost
int GetNumSettingOnHost(const QString &key, const QString &host, int defaultval=0)
Definition: mythcorecontext.cpp:942
MythCoreContextPrivate::m_approvedIps
QList< QHostAddress > m_approvedIps
Definition: mythcorecontext.cpp:118
MythCoreContextPrivate::m_wolInProgressLock
QMutex m_wolInProgressLock
Definition: mythcorecontext.cpp:83
MythCoreContext::GetResolutionSetting
void GetResolutionSetting(const QString &type, int &width, int &height, double &forced_aspect, double &refresh_rate, int index=-1)
Definition: mythcorecontext.cpp:848
MythCoreContext::RegisterForPlayback
void RegisterForPlayback(QObject *sender, PlaybackStartCb method)
Definition: mythcorecontext.cpp:1906
MythCoreContext::GetBackendServerIP4
QString GetBackendServerIP4(void)
Returns the IPv4 address defined for the current host see GetBackendServerIP4(host)
Definition: mythcorecontext.cpp:1026
MythCoreContext::m_testOverrideStrings
QMap< QString, QString > m_testOverrideStrings
Definition: mythcorecontext.h:322
SendAsyncMessage::m_message
QString m_message
Definition: mythcorecontext.cpp:1512
MythCoreContext::TVPlaybackAboutToStart
void TVPlaybackAboutToStart(void)
MythSocket::kShortTimeout
static constexpr std::chrono::milliseconds kShortTimeout
Definition: mythsocket.h:70
SendAsyncMessage
Definition: mythcorecontext.cpp:1493
MythCoreContext::ConnectCommandSocket
MythSocket * ConnectCommandSocket(const QString &hostname, int port, const QString &announcement, bool *proto_mismatch=nullptr, int maxConnTry=-1, std::chrono::milliseconds setup_timeout=-1ms)
Definition: mythcorecontext.cpp:426
uint
unsigned int uint
Definition: compat.h:81
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
SendAsyncMessage::m_extraData
QStringList m_extraData
Definition: mythcorecontext.cpp:1513
MythCoreContextPrivate::~MythCoreContextPrivate
~MythCoreContextPrivate() override
Definition: mythcorecontext.cpp:154
MythCoreContext::ConnectEventSocket
MythSocket * ConnectEventSocket(const QString &hostname, int port)
Definition: mythcorecontext.cpp:544
MythCoreContext::GetLanguage
QString GetLanguage(void)
Returns two character ISO-639 language descriptor for UI language.
Definition: mythcorecontext.cpp:1770
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:911
logStop
void logStop(void)
Entry point for stopping logging for an application.
Definition: logging.cpp:669
MythLocale::SaveLocaleDefaults
void SaveLocaleDefaults(bool overwrite=false)
Definition: mythlocale.cpp:171
MythCoreContext::ResolveIPv6
@ ResolveIPv6
Definition: mythcorecontext.h:212
MythCoreContext::resolveAddress
static QString resolveAddress(const QString &host, ResolveType type=ResolveAny, bool keepscope=false)
if host is an IP address, it will be returned or resolved otherwise.
Definition: mythcorecontext.cpp:1191
MythCoreContext::SetLocalHostname
void SetLocalHostname(const QString &hostname)
Definition: mythcorecontext.cpp:1729
MythCoreContextPrivate::m_locale
MythLocale * m_locale
Definition: mythcorecontext.cpp:95
SendAsyncMessage::run
void run(void) override
Definition: mythcorecontext.cpp:1503
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:905
mthreadpool.h
MythEvent::ExtraDataList
const QStringList & ExtraDataList() const
Definition: mythevent.h:67
MythCoreContext::GetMasterServerPort
static int GetMasterServerPort(void)
Returns the Master Backend control port If no master server port has been defined in the database,...
Definition: mythcorecontext.cpp:979
MythCoreContextPrivate::m_playbackClients
QMap< QObject *, MythCoreContext::PlaybackStartCb > m_playbackClients
Definition: mythcorecontext.cpp:102
MythCoreContext::InWantingPlayback
bool InWantingPlayback(void)
Returns true if a client has requested playback.
Definition: mythcorecontext.cpp:2024
MythCoreContext::ResolveIPv4
@ ResolveIPv4
Definition: mythcorecontext.h:212
MythCoreContext
This class contains the runtime context for MythTV.
Definition: mythcorecontext.h:63
mythmiscutil.h
MythCoreContext::setTestIntSettings
void setTestIntSettings(QMap< QString, int > &overrides)
Definition: mythcorecontext.cpp:286
mythcorecontext.h
MythCoreContext::m_testOverrideFloats
QMap< QString, double > m_testOverrideFloats
Definition: mythcorecontext.h:321
MythCoreContextPrivate::m_announcedProtocol
bool m_announcedProtocol
Definition: mythcorecontext.cpp:107
MythCoreContext::IsBackend
bool IsBackend(void) const
is this process a backend process
Definition: mythcorecontext.cpp:643
kLinkLocal
static QPair< QHostAddress, int > kLinkLocal
Definition: serverpool.cpp:27
MythCoreContextPrivate::m_masterHostname
QString m_masterHostname
master backend hostname
Definition: mythcorecontext.cpp:75
MythCoreContext::ResetLanguage
void ResetLanguage(void)
Definition: mythcorecontext.cpp:1790
MythCoreContext::GetSettingOnHost
QString GetSettingOnHost(const QString &key, const QString &host, const QString &defaultval="")
Definition: mythcorecontext.cpp:925
MythCoreContextPrivate::m_scopes
QMap< QString, QString > m_scopes
Scope Id cache for Link-Local addresses.
Definition: mythcorecontext.cpp:77
kMSProcessEvents
@ kMSProcessEvents
process events while waiting
Definition: mythsystem.h:39
MythCoreContext::GetLanguageAndVariant
QString GetLanguageAndVariant(void)
Returns the user-set language and variant.
Definition: mythcorecontext.cpp:1782
std
Definition: mythchrono.h:23
MythCoreContextPrivate::m_serverSock
MythSocket * m_serverSock
socket for sending MythProto requests
Definition: mythcorecontext.cpp:80
serverpool.h
MythCoreContextPrivate::m_wolInProgress
bool m_wolInProgress
Definition: mythcorecontext.cpp:85
MythSocket::IsDataAvailable
bool IsDataAvailable(void)
Definition: mythsocket.cpp:563
MythCoreContextPrivate::m_inwanting
bool m_inwanting
Definition: mythcorecontext.cpp:104
MythCoreContext::ClearBackendServerPortCache
static void ClearBackendServerPortCache()
Definition: mythcorecontext.cpp:1070
logging.h
mthread.h
MythCoreContext::TVInWantingPlayback
void TVInWantingPlayback(bool b)
Let the TV class tell us if we was interrupted following a call to WantingPlayback().
Definition: mythcorecontext.cpp:2012
MythCoreContext::d
MythCoreContextPrivate * d
Definition: mythcorecontext.h:313
MythCoreContextPrivate::m_uiThread
QThread * m_uiThread
Definition: mythcorecontext.cpp:93
SendAsyncMessage::SendAsyncMessage
SendAsyncMessage(QString msg)
Definition: mythcorecontext.cpp:1501
MythCoreContext::ActivateSettingsCache
void ActivateSettingsCache(bool activate=true)
Definition: mythcorecontext.cpp:832
MThread::Cleanup
static void Cleanup(void)
This will print out all the running threads, call exit(1) on each and then wait up to 5 seconds total...
Definition: mthread.cpp:142
MythCoreContext::ResolveType
ResolveType
Definition: mythcorecontext.h:212
MythCoreContextPrivate::m_sockLock
QMutex m_sockLock
protects both m_serverSock and m_eventSock
Definition: mythcorecontext.cpp:79
MythLocale::GetLocaleCode
QString GetLocaleCode() const
Name of language in that language.
Definition: mythlocale.h:27
MythCoreContext::WantingPlayback
void WantingPlayback(QObject *sender)
All the objects that have registered using MythCoreContext::RegisterForPlayback but sender will be ca...
Definition: mythcorecontext.cpp:1946
ShutdownMythSystemLegacy
void MBASE_PUBLIC ShutdownMythSystemLegacy(void)
Definition: mythsystemunix.cpp:75
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:837
MythCoreContextPrivate::m_scheduler
MythScheduler * m_scheduler
Definition: mythcorecontext.cpp:98
MythCoreContext::ReInitLocale
void ReInitLocale(void)
Definition: mythcorecontext.cpp:1830
MThread::ThreadSetup
static void ThreadSetup(const QString &name)
This is to be called on startup in those few threads that haven't been ported to MThread.
Definition: mthread.cpp:221
MythCoreContextPrivate::m_deniedIps
QList< QHostAddress > m_deniedIps
Definition: mythcorecontext.cpp:119
MythCoreContext::IsExiting
bool IsExiting(void)
Definition: mythcorecontext.cpp:2086
MythCoreContext::GetBoolSettingOnHost
bool GetBoolSettingOnHost(const QString &key, const QString &host, bool defaultval=false)
Definition: mythcorecontext.cpp:934
MythCoreContext::ClearSettingsCache
void ClearSettingsCache(const QString &myKey=QString(""))
Definition: mythcorecontext.cpp:827
MythCoreContext::IsThisHost
bool IsThisHost(const QString &addr)
is this address mapped to this host
Definition: mythcorecontext.cpp:720
MythCoreContext::HasGUI
bool HasGUI(void) const
Definition: mythcorecontext.cpp:1741
MythCoreContext::IsMasterHost
bool IsMasterHost(void)
is this the same host as the master
Definition: mythcorecontext.cpp:658
MythCoreContextPrivate::m_localHostLock
QMutex m_localHostLock
Locking for m_localHostname.
Definition: mythcorecontext.cpp:72
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
mythpower.h
MythCoreContext::BlockShutdown
void BlockShutdown(void)
Definition: mythcorecontext.cpp:595
MythCoreContext::IsWOLAllowed
bool IsWOLAllowed() const
Definition: mythcorecontext.cpp:633
MythCoreContext::GetFloatSetting
double GetFloatSetting(const QString &key, double defaultval=0.0)
Definition: mythcorecontext.cpp:918
kMSDontDisableDrawing
@ kMSDontDisableDrawing
avoid disabling UI drawing
Definition: mythsystem.h:37
MythCoreContextPrivate::m_fileslock
QMutex m_fileslock
Definition: mythcorecontext.cpp:114
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:880
MythCoreContext::GetMasterHostPrefix
QString GetMasterHostPrefix(const QString &storageGroup=QString(), const QString &path=QString())
Definition: mythcorecontext.cpp:797
MythCoreContext::GetSessionManager
MythSessionManager * GetSessionManager(void)
Definition: mythcorecontext.cpp:2040
exitcodes.h
mythdownloadmanager.h
MythCoreContext::GetBackendServerIP6
QString GetBackendServerIP6(void)
Returns the IPv6 address defined for the current host see GetBackendServerIP6(host)
Definition: mythcorecontext.cpp:1045
delete_sock
static void delete_sock(QMutexLocker< QMutex > &locker, MythSocket **s)
Definition: mythcorecontext.cpp:136
MThreadPool::globalInstance
static MThreadPool * globalInstance(void)
Definition: mthreadpool.cpp:317
MythCoreContext::GetPluginManager
MythPluginManager * GetPluginManager(void)
Definition: mythcorecontext.cpp:2076
MythCoreContext::SetScopeForAddress
void SetScopeForAddress(const QHostAddress &addr)
Record the scope Id of the given IP address.
Definition: mythcorecontext.cpp:1128
MythSocket::kLongTimeout
static constexpr std::chrono::milliseconds kLongTimeout
Definition: mythsocket.h:71
MythCoreContext::SetupCommandSocket
bool SetupCommandSocket(MythSocket *serverSock, const QString &announcement, std::chrono::milliseconds timeout, bool &proto_mismatch)
Definition: mythcorecontext.cpp:301
MythCoreContext::CheckSubnet
bool CheckSubnet(const QAbstractSocket *socket)
Check if a socket is connected to an approved peer.
Definition: mythcorecontext.cpp:1267
mythsocket.h
MythCoreContextPrivate::m_guiContext
QObject * m_guiContext
Definition: mythcorecontext.cpp:68
MythCoreContextPrivate
Definition: mythcorecontext.cpp:57
MythCoreContext::SaveLocaleDefaults
void SaveLocaleDefaults(void)
Definition: mythcorecontext.cpp:1851
MythCoreContext::dispatch
void dispatch(const MythEvent &event)
Definition: mythcorecontext.cpp:1722
MythCoreContextPrivate::m_language
QString m_language
Definition: mythcorecontext.cpp:96
MythCoreContext::SaveSettingOnHost
bool SaveSettingOnHost(const QString &key, const QString &newValue, const QString &host)
Definition: mythcorecontext.cpp:890
MythSocket::ReadStringList
bool ReadStringList(QStringList &list, std::chrono::milliseconds timeoutMS=kShortTimeout)
Definition: mythsocket.cpp:319
MythCoreContext::SetAsBackend
void SetAsBackend(bool backend)
Definition: mythcorecontext.cpp:638
MythCoreContext::m_testOverrideInts
QMap< QString, int > m_testOverrideInts
Definition: mythcorecontext.h:320
MythCoreContext::PlaybackStartCb
void(QObject::*)(void) PlaybackStartCb
Definition: mythcorecontext.h:241
MythCoreContext::IsThisBackend
bool IsThisBackend(const QString &addr)
is this address mapped to this backend host
Definition: mythcorecontext.cpp:715
MythCoreContext::setTestFloatSettings
void setTestFloatSettings(QMap< QString, double > &overrides)
Definition: mythcorecontext.cpp:291
MythCoreContext::GetFloatSettingOnHost
double GetFloatSettingOnHost(const QString &key, const QString &host, double defaultval=0.0)
Definition: mythcorecontext.cpp:951
MThreadPool::start
void start(QRunnable *runnable, const QString &debugName, int priority=0)
Definition: mthreadpool.cpp:352
MythCoreContext::SetExiting
void SetExiting(bool exiting=true)
Definition: mythcorecontext.cpp:2081
MythCoreContext::SetGUIObject
void SetGUIObject(QObject *gui)
Definition: mythcorecontext.cpp:1736
MythSocket::SendReceiveStringList
bool SendReceiveStringList(QStringList &list, uint min_reply_length=0, std::chrono::milliseconds timeoutMS=kLongTimeout)
Definition: mythsocket.cpp:332
MythCoreContextPrivate::m_power
MythPower * m_power
Definition: mythcorecontext.cpp:121
MythCoreContextPrivate::MythCoreContextPrivate
MythCoreContextPrivate(MythCoreContext *lparent, QString binversion, QObject *guicontext)
Definition: mythcorecontext.cpp:124
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:897
MythSessionManager
Definition: mythsession.h:102