MythTV  master
main_helpers.cpp
Go to the documentation of this file.
1 #include "mythconfig.h"
2 #if CONFIG_SYSTEMD_NOTIFY
3  #include <systemd/sd-daemon.h>
4  #define be_sd_notify(x) \
5  (void)sd_notify(0, x);
6 #else
7  #define be_sd_notify(x)
8 #endif
9 
10 // C++ headers
11 #include <cerrno>
12 #include <csignal>
13 #include <cstdlib>
14 #include <fcntl.h>
15 #include <sys/stat.h>
16 #include <sys/time.h> // for setpriority
17 #include <sys/types.h>
18 #include <unistd.h>
19 
20 #include <QCoreApplication>
21 #include <QFileInfo>
22 #include <QFile>
23 #include <QDir>
24 #include <QMap>
25 
26 #include "tv_rec.h"
27 #include "scheduledrecording.h"
28 #include "autoexpire.h"
29 #include "scheduler.h"
30 #include "mainserver.h"
31 #include "encoderlink.h"
32 #include "remoteutil.h"
33 #include "backendhousekeeper.h"
34 
35 #include "mythcontext.h"
36 #include "mythversion.h"
37 #include "mythdb.h"
38 #include "dbutil.h"
39 #include "exitcodes.h"
40 #include "compat.h"
41 #include "storagegroup.h"
42 #include "programinfo.h"
43 #include "dbcheck.h"
44 #include "jobqueue.h"
45 #include "previewgenerator.h"
46 #include "commandlineparser.h"
47 #include "mythsystemevent.h"
48 #include "main_helpers.h"
49 #include "backendcontext.h"
50 #include "mythtranslation.h"
51 #include "mythtimezone.h"
52 #include "signalhandling.h"
53 #include "hardwareprofile.h"
54 #include "eitcache.h"
55 
56 #include "mediaserver.h"
57 #include "httpstatus.h"
58 #include "mythlogging.h"
59 
60 // New webserver
64 #include "servicesv2/v2myth.h"
65 #include "servicesv2/v2video.h"
66 #include "servicesv2/v2dvr.h"
67 #include "servicesv2/v2content.h"
68 #include "servicesv2/v2guide.h"
69 #include "servicesv2/v2channel.h"
70 #include "servicesv2/v2status.h"
71 #include "servicesv2/v2capture.h"
72 #include "servicesv2/v2music.h"
73 
74 #define LOC QString("MythBackend: ")
75 #define LOC_WARN QString("MythBackend, Warning: ")
76 #define LOC_ERR QString("MythBackend, Error: ")
77 
78 static MainServer *mainServer = nullptr;
79 
80 bool setupTVs(bool ismaster, bool &error)
81 {
82  error = false;
83  QString localhostname = gCoreContext->GetHostName();
84 
86 
87  if (ismaster)
88  {
89  // Hack to make sure recorded.basename gets set if the user
90  // downgrades to a prior version and creates new entries
91  // without it.
92  if (!query.exec("UPDATE recorded SET basename = CONCAT(chanid, '_', "
93  "DATE_FORMAT(starttime, '%Y%m%d%H%i00'), '_', "
94  "DATE_FORMAT(endtime, '%Y%m%d%H%i00'), '.nuv') "
95  "WHERE basename = '';"))
96  MythDB::DBError("Updating record basename", query);
97 
98  // Hack to make sure record.station gets set if the user
99  // downgrades to a prior version and creates new entries
100  // without it.
101  if (!query.exec("UPDATE channel SET callsign=chanid "
102  "WHERE callsign IS NULL OR callsign='';"))
103  MythDB::DBError("Updating channel callsign", query);
104 
105  if (query.exec("SELECT MIN(chanid) FROM channel;"))
106  {
107  query.first();
108  int min_chanid = query.value(0).toInt();
109  if (!query.exec(QString("UPDATE record SET chanid = %1 "
110  "WHERE chanid IS NULL;").arg(min_chanid)))
111  MythDB::DBError("Updating record chanid", query);
112  }
113  else
114  MythDB::DBError("Querying minimum chanid", query);
115 
116  MSqlQuery records_without_station(MSqlQuery::InitCon());
117  records_without_station.prepare("SELECT record.chanid,"
118  " channel.callsign FROM record LEFT JOIN channel"
119  " ON record.chanid = channel.chanid WHERE record.station='';");
120  if (records_without_station.exec() && records_without_station.next())
121  {
122  MSqlQuery update_record(MSqlQuery::InitCon());
123  update_record.prepare("UPDATE record SET station = :CALLSIGN"
124  " WHERE chanid = :CHANID;");
125  do
126  {
127  update_record.bindValue(":CALLSIGN",
128  records_without_station.value(1));
129  update_record.bindValue(":CHANID",
130  records_without_station.value(0));
131  if (!update_record.exec())
132  {
133  MythDB::DBError("Updating record station", update_record);
134  }
135  } while (records_without_station.next());
136  }
137  }
138 
139  if (!query.exec(
140  "SELECT cardid, parentid, videodevice, hostname, sourceid "
141  "FROM capturecard "
142  "ORDER BY cardid"))
143  {
144  MythDB::DBError("Querying Recorders", query);
145  return false;
146  }
147 
148  std::vector<unsigned int> cardids;
149  std::vector<QString> hosts;
150  while (query.next())
151  {
152  uint cardid = query.value(0).toUInt();
153  uint parentid = query.value(1).toUInt();
154  QString videodevice = query.value(2).toString();
155  QString hostname = query.value(3).toString();
156  uint sourceid = query.value(4).toUInt();
157  QString cidmsg = QString("Card[%1](%2)").arg(cardid).arg(videodevice);
158 
159  if (hostname.isEmpty())
160  {
161  LOG(VB_GENERAL, LOG_ERR, cidmsg +
162  " does not have a hostname defined.\n"
163  "Please run setup and confirm all of the capture cards.\n");
164  continue;
165  }
166 
167  // Skip all cards that do not have a video source
168  if (sourceid == 0)
169  {
170  if (parentid == 0)
171  {
172  LOG(VB_GENERAL, LOG_WARNING, cidmsg +
173  " does not have a video source");
174  }
175  continue;
176  }
177 
178  cardids.push_back(cardid);
179  hosts.push_back(hostname);
180  }
181 
182  QWriteLocker tvlocker(&TVRec::s_inputsLock);
183 
184  // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
185  for (size_t i = 0; i < cardids.size(); i++)
186  {
187  if (hosts[i] == localhostname) {
188  // No memory leak. The constructor for TVRec adds the item
189  // to the static map TVRec::s_inputs.
190  new TVRec(cardids[i]);
191  }
192  }
193 
194  for (size_t i = 0; i < cardids.size(); i++)
195  {
196  uint cardid = cardids[i];
197  QString host = hosts[i];
198  QString cidmsg = QString("Card %1").arg(cardid);
199 
200  if (!ismaster)
201  {
202  if (host == localhostname)
203  {
204  TVRec *tv = TVRec::GetTVRec(cardid);
205  if (tv && tv->Init())
206  {
207  auto *enc = new EncoderLink(cardid, tv);
208  gTVList[cardid] = enc;
209  }
210  else
211  {
212  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
213  cidmsg + " failed init");
214  delete tv;
215  // The master assumes card comes up so we need to
216  // set error and exit if a non-master card fails.
217  error = true;
218  }
219  }
220  }
221  else
222  {
223  if (host == localhostname)
224  {
225  TVRec *tv = TVRec::GetTVRec(cardid);
226  if (tv && tv->Init())
227  {
228  auto *enc = new EncoderLink(cardid, tv);
229  gTVList[cardid] = enc;
230  }
231  else
232  {
233  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
234  cidmsg + " failed init");
235  delete tv;
236  }
237  }
238  else
239  {
240  auto *enc = new EncoderLink(cardid, nullptr, host);
241  gTVList[cardid] = enc;
242  }
243  }
244  }
245 
246  if (gTVList.empty())
247  {
248  LOG(VB_GENERAL, LOG_WARNING, LOC +
249  "No valid capture cards are defined in the database.");
250  }
251 
252  return true;
253 }
254 
255 void cleanup(void)
256 {
257  if (mainServer)
258  {
259  mainServer->Stop();
260  qApp->processEvents();
261  }
262 
263  if (gCoreContext)
265 
266  delete gSysEventHandler;
267  gSysEventHandler = nullptr;
268 
269  delete gHousekeeping;
270  gHousekeeping = nullptr;
271 
272  if (gCoreContext)
273  {
274  delete gCoreContext->GetScheduler();
275  gCoreContext->SetScheduler(nullptr);
276  }
277 
278  delete gExpirer;
279  gExpirer = nullptr;
280 
281  delete gJobQueue;
282  gJobQueue = nullptr;
283 
284  delete g_pUPnp;
285  g_pUPnp = nullptr;
286 
287  if (SSDP::Instance())
288  {
290  SSDP::Instance()->wait();
291  }
292 
293  if (TaskQueue::Instance())
294  {
297  }
298 
299  while (!TVRec::s_inputs.empty())
300  {
301  TVRec *rec = *TVRec::s_inputs.begin();
302  delete rec;
303  }
304 
305 
306  delete gContext;
307  gContext = nullptr;
308 
309  delete mainServer;
310  mainServer = nullptr;
311 
312  delete gBackendContext;
313  gBackendContext = nullptr;
314 
315  if (!gPidFile.isEmpty())
316  {
317  unlink(gPidFile.toLatin1().constData());
318  gPidFile.clear();
319  }
320 
322 }
323 
325 {
326  QString eventString;
327 
328  if (cmdline.toBool("event"))
329  eventString = cmdline.toString("event");
330  else if (cmdline.toBool("systemevent"))
331  {
332  eventString = "SYSTEM_EVENT " +
333  cmdline.toString("systemevent") +
334  QString(" SENDER %1").arg(gCoreContext->GetHostName());
335  }
336 
337  if (!eventString.isEmpty())
338  {
340  {
341  gCoreContext->SendMessage(eventString);
342  return GENERIC_EXIT_OK;
343  }
345  }
346 
347  if (cmdline.toBool("setverbose"))
348  {
350  {
351  QString message = "SET_VERBOSE ";
352  message += cmdline.toString("setverbose");
353 
354  gCoreContext->SendMessage(message);
355  LOG(VB_GENERAL, LOG_INFO,
356  QString("Sent '%1' message").arg(message));
357  return GENERIC_EXIT_OK;
358  }
359  LOG(VB_GENERAL, LOG_ERR,
360  "Unable to connect to backend, verbose mask unchanged ");
362  }
363 
364  if (cmdline.toBool("setloglevel"))
365  {
367  {
368  QString message = "SET_LOG_LEVEL ";
369  message += cmdline.toString("setloglevel");
370 
371  gCoreContext->SendMessage(message);
372  LOG(VB_GENERAL, LOG_INFO,
373  QString("Sent '%1' message").arg(message));
374  return GENERIC_EXIT_OK;
375  }
376  LOG(VB_GENERAL, LOG_ERR,
377  "Unable to connect to backend, log level unchanged ");
379  }
380 
381  if (cmdline.toBool("clearcache"))
382  {
384  {
385  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
386  LOG(VB_GENERAL, LOG_INFO, "Sent CLEAR_SETTINGS_CACHE message");
387  return GENERIC_EXIT_OK;
388  }
389  LOG(VB_GENERAL, LOG_ERR, "Unable to connect to backend, settings "
390  "cache will not be cleared.");
392  }
393 
394  if (cmdline.toBool("printsched") ||
395  cmdline.toBool("testsched"))
396  {
397  auto *sched = new Scheduler(false, &gTVList);
398  if (cmdline.toBool("printsched"))
399  {
401  {
402  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master");
403  delete sched;
405  }
406  std::cout << "Retrieving Schedule from Master backend.\n";
408  }
409  else
410  {
411  std::cout << "Calculating Schedule from database.\n" <<
412  "Inputs, Card IDs, and Conflict info may be invalid "
413  "if you have multiple tuners.\n";
416  }
417 
418  verboseMask |= VB_SCHEDULE;
419  LogLevel_t oldLogLevel = logLevel;
420  logLevel = LOG_DEBUG;
421  sched->PrintList(true);
422  logLevel = oldLogLevel;
423  delete sched;
424  return GENERIC_EXIT_OK;
425  }
426 
427  if (cmdline.toBool("resched"))
428  {
429  bool ok = false;
431  {
432  LOG(VB_GENERAL, LOG_INFO, "Connected to master for reschedule");
433  ScheduledRecording::RescheduleMatch(0, 0, 0, QDateTime(),
434  "MythBackendCommand");
435  ok = true;
436  }
437  else
438  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for reschedule");
439 
441  }
442 
443  if (cmdline.toBool("scanvideos"))
444  {
445  bool ok = false;
447  {
448  gCoreContext->SendReceiveStringList(QStringList() << "SCAN_VIDEOS");
449  LOG(VB_GENERAL, LOG_INFO, "Requested video scan");
450  ok = true;
451  }
452  else
453  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for video scan");
454 
456  }
457 
458  if (cmdline.toBool("printexpire"))
459  {
460  gExpirer = new AutoExpire();
461  gExpirer->PrintExpireList(cmdline.toString("printexpire"));
462  return GENERIC_EXIT_OK;
463  }
464 
465  // This should never actually be reached..
466  return GENERIC_EXIT_OK;
467 }
468 using namespace MythTZ;
469 
471 {
472  auto *tempMonitorConnection = new MythSocket();
473  if (tempMonitorConnection->ConnectToHost(
476  {
477  if (!gCoreContext->CheckProtoVersion(tempMonitorConnection))
478  {
479  LOG(VB_GENERAL, LOG_ERR, "Master backend is incompatible with "
480  "this backend.\nCannot become a slave.");
481  tempMonitorConnection->DecrRef();
483  }
484 
485  QStringList tempMonitorDone("DONE");
486 
487  QStringList tempMonitorAnnounce(QString("ANN Monitor %1 0")
488  .arg(gCoreContext->GetHostName()));
489  tempMonitorConnection->SendReceiveStringList(tempMonitorAnnounce);
490  if (tempMonitorAnnounce.empty() ||
491  tempMonitorAnnounce[0] == "ERROR")
492  {
493  tempMonitorConnection->DecrRef();
494  tempMonitorConnection = nullptr;
495  if (tempMonitorAnnounce.empty())
496  {
497  LOG(VB_GENERAL, LOG_ERR, LOC +
498  "Failed to open event socket, timeout");
499  }
500  else
501  {
502  LOG(VB_GENERAL, LOG_ERR, LOC +
503  "Failed to open event socket" +
504  ((tempMonitorAnnounce.size() >= 2) ?
505  QString(", error was %1").arg(tempMonitorAnnounce[1]) :
506  QString(", remote error")));
507  }
508  }
509 
510  QStringList timeCheck;
511  if (tempMonitorConnection)
512  {
513  timeCheck.push_back("QUERY_TIME_ZONE");
514  tempMonitorConnection->SendReceiveStringList(timeCheck);
515  tempMonitorConnection->WriteStringList(tempMonitorDone);
516  }
517  if (timeCheck.size() < 3)
518  {
519  if (tempMonitorConnection)
520  tempMonitorConnection->DecrRef();
522  }
523 
524  QDateTime our_time = MythDate::current();
525  QDateTime master_time = MythDate::fromString(timeCheck[2]);
526  int timediff = abs(our_time.secsTo(master_time));
527 
528  if (timediff > 300)
529  {
530  LOG(VB_GENERAL, LOG_ERR,
531  QString("Current time on the master backend differs by "
532  "%1 seconds from time on this system. Exiting.")
533  .arg(timediff));
534  if (tempMonitorConnection)
535  tempMonitorConnection->DecrRef();
537  }
538 
539  if (timediff > 20)
540  {
541  LOG(VB_GENERAL, LOG_WARNING,
542  QString("Time difference between the master "
543  "backend and this system is %1 seconds.")
544  .arg(timediff));
545  }
546  }
547  if (tempMonitorConnection)
548  tempMonitorConnection->DecrRef();
549 
550  return GENERIC_EXIT_OK;
551 }
552 
553 
555 {
556  if (cmdline.toBool("nohousekeeper"))
557  {
558  LOG(VB_GENERAL, LOG_WARNING, LOC +
559  "****** The Housekeeper has been DISABLED with "
560  "the --nohousekeeper option ******");
561  }
562  if (cmdline.toBool("nosched"))
563  {
564  LOG(VB_GENERAL, LOG_WARNING, LOC +
565  "********** The Scheduler has been DISABLED with "
566  "the --nosched option **********");
567  }
568  if (cmdline.toBool("noautoexpire"))
569  {
570  LOG(VB_GENERAL, LOG_WARNING, LOC +
571  "********* Auto-Expire has been DISABLED with "
572  "the --noautoexpire option ********");
573  }
574  if (cmdline.toBool("nojobqueue"))
575  {
576  LOG(VB_GENERAL, LOG_WARNING, LOC +
577  "********* The JobQueue has been DISABLED with "
578  "the --nojobqueue option *********");
579  }
580 }
581 
583 {
585 
587  {
588  LOG(VB_GENERAL, LOG_ERR,
589  "MySQL time zone support is missing. "
590  "Please install it and try again. "
591  "See 'mysql_tzinfo_to_sql' for assistance.");
593  }
594 
595  bool ismaster = gCoreContext->IsMasterHost();
596 
597  if (!UpgradeTVDatabaseSchema(ismaster, ismaster, true))
598  {
599  LOG(VB_GENERAL, LOG_ERR,
600  QString("Couldn't upgrade database to new schema on %1 backend.")
601  .arg(ismaster ? "master" : "slave"));
603  }
604 
605  be_sd_notify("STATUS=Loading translation");
606  MythTranslation::load("mythfrontend");
607 
608  if (!ismaster)
609  {
610  be_sd_notify("STATUS=Connecting to master backend");
611  int ret = connect_to_master();
612  if (ret != GENERIC_EXIT_OK)
613  return ret;
614  }
615 
616  be_sd_notify("STATUS=Get backend server port");
617  int port = gCoreContext->GetBackendServerPort();
618  if (gCoreContext->GetBackendServerIP().isEmpty())
619  {
620  std::cerr << "No setting found for this machine's BackendServerAddr.\n"
621  << "Please run mythtv-setup on this machine.\n"
622  << "Go to page \"1. General\" / \"Host Address Backend Setup\" and examine the values.\n"
623  << "N.B. The default values are correct for a combined frontend/backend machine.\n"
624  << "Press Escape, select \"Save and Exit\" and exit mythtv-setup.\n"
625  << "Then start mythbackend again.\n";
627  }
628 
630 
631  if (ismaster)
632  {
633  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Starting up as the master server.");
634  }
635  else
636  {
637  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Running as a slave backend.");
638  }
639 
640  if (ismaster)
641  {
643  }
644 
646 
647  bool fatal_error = false;
648  bool runsched = setupTVs(ismaster, fatal_error);
649  if (fatal_error)
651 
652  Scheduler *sched = nullptr;
653  if (ismaster)
654  {
655  if (runsched)
656  {
657  be_sd_notify("STATUS=Creating scheduler");
658  sched = new Scheduler(true, &gTVList);
659  int err = sched->GetError();
660  if (err)
661  {
662  delete sched;
663  return err;
664  }
665 
666  if (cmdline.toBool("nosched"))
668  }
669 
670  if (!cmdline.toBool("noautoexpire"))
671  {
672  gExpirer = new AutoExpire(&gTVList);
673  if (sched)
675  }
677  }
678 
679  if (!cmdline.toBool("nohousekeeper"))
680  {
681  be_sd_notify("STATUS=Creating housekeeper");
682  gHousekeeping = new HouseKeeper();
683 
684  if (ismaster)
685  {
691 
692  // only run this task if MythMusic is installed and we have a new enough schema
693  if (gCoreContext->GetNumSetting("MusicDBSchemaVer", 0) >= 1024)
695  }
696 
698 #ifdef __linux__
699  #ifdef CONFIG_BINDINGS_PYTHON
701  #endif
702 #endif
703 
704  gHousekeeping->Start();
705  }
706 
707  if (!cmdline.toBool("nojobqueue"))
708  gJobQueue = new JobQueue(ismaster);
709 
710  // ----------------------------------------------------------------------
711  //
712  // ----------------------------------------------------------------------
713 
714  if (g_pUPnp == nullptr)
715  {
716  be_sd_notify("STATUS=Creating UPnP media server");
717  g_pUPnp = new MediaServer();
718 
719  g_pUPnp->Init(ismaster, cmdline.toBool("noupnp"));
720  }
721 
722  if (cmdline.toBool("dvbv3"))
723  {
724  LOG(VB_GENERAL, LOG_INFO, LOC + "Use legacy DVBv3 API");
725  gCoreContext->SetDVBv3(true);
726  }
727 
728  // ----------------------------------------------------------------------
729  // Setup status server
730  // ----------------------------------------------------------------------
731 
732  HttpStatus *httpStatus = nullptr;
733  HttpServer *pHS = g_pUPnp->GetHttpServer();
734 
735  if (pHS)
736  {
737  LOG(VB_GENERAL, LOG_INFO, "Main::Registering HttpStatus Extension");
738  be_sd_notify("STATUS=Registering HttpStatus Extension");
739 
740  httpStatus = new HttpStatus( &gTVList, sched, gExpirer, ismaster );
741  pHS->RegisterExtension( httpStatus );
742  }
743 
744  be_sd_notify("STATUS=Creating main server");
745  mainServer = new MainServer(
746  ismaster, port, &gTVList, sched, gExpirer);
747 
748  int exitCode = mainServer->GetExitCode();
749  if (exitCode != GENERIC_EXIT_OK)
750  {
751  LOG(VB_GENERAL, LOG_CRIT,
752  "Backend exiting, MainServer initialization error.");
753  cleanup();
754  return exitCode;
755  }
756 
757  if (httpStatus && mainServer)
758  httpStatus->SetMainServer(mainServer);
759 
760  be_sd_notify("STATUS=Check all storage groups");
762 
763  be_sd_notify("STATUS=Sending \"master started\" message");
765  gCoreContext->SendSystemEvent("MASTER_STARTED");
766 
767  // Provide systemd ready notification (for type=notify units)
768  be_sd_notify("READY=1");
769 
770  const HTTPServices be_services = {
771  { VIDEO_SERVICE, &MythHTTPService::Create<V2Video> },
772  { MYTH_SERVICE, &MythHTTPService::Create<V2Myth> },
773  { DVR_SERVICE, &MythHTTPService::Create<V2Dvr> },
774  { CONTENT_SERVICE, &MythHTTPService::Create<V2Content> },
775  { GUIDE_SERVICE, &MythHTTPService::Create<V2Guide> },
776  { CHANNEL_SERVICE, &MythHTTPService::Create<V2Channel> },
777  { STATUS_SERVICE, &MythHTTPService::Create<V2Status> },
778  { CAPTURE_SERVICE, &MythHTTPService::Create<V2Capture> },
779  { MUSIC_SERVICE, &MythHTTPService::Create<V2Music> },
780  };
781 
782  MythHTTPInstance::Addservices(be_services);
783 
784  // Send all unknown requests into the web app. make bookmarks and direct access work.
785  auto spa_index = [](auto && PH1) { return MythHTTPRewrite::RewriteToSPA(std::forward<decltype(PH1)>(PH1), "apps/backend/index.html"); };
786  MythHTTPInstance::AddErrorPageHandler({ "=404", spa_index });
787 
788  // Serve components of the backend web app as if they were hosted at '/'
789  auto main_js = [](auto && PH1) { return MythHTTPRewrite::RewriteFile(std::forward<decltype(PH1)>(PH1), "apps/backend/main.js"); };
790  auto styles_css = [](auto && PH1) { return MythHTTPRewrite::RewriteFile(std::forward<decltype(PH1)>(PH1), "apps/backend/styles.css"); };
791  auto polyfills_js = [](auto && PH1) { return MythHTTPRewrite::RewriteFile(std::forward<decltype(PH1)>(PH1), "apps/backend/polyfills.js"); };
792  auto runtime_js = [](auto && PH1) { return MythHTTPRewrite::RewriteFile(std::forward<decltype(PH1)>(PH1), "apps/backend/runtime.js"); };
793 
794  // Default index page
795  auto root = [](auto && PH1) { return MythHTTPRoot::RedirectRoot(std::forward<decltype(PH1)>(PH1), "apps/backend/index.html"); };
796 
797  const HTTPHandlers be_handlers = {
798  { "/main.js", main_js },
799  { "/styles.css", styles_css },
800  { "/polyfills.js", polyfills_js },
801  { "/runtime.js", runtime_js },
802  { "/", root }
803  };
804 
805  MythHTTPScopedInstance webserver(be_handlers);
806 
809  exitCode = qApp->exec();
812 
814  {
815  gCoreContext->SendSystemEvent("MASTER_SHUTDOWN");
816  qApp->processEvents();
817  }
818 
819  LOG(VB_GENERAL, LOG_NOTICE, "MythBackend exiting");
820  be_sd_notify("STOPPING=1\nSTATUS=Exiting");
821 
822  return exitCode;
823 }
main_helpers.h
Scheduler
Definition: scheduler.h:45
be_sd_notify
#define be_sd_notify(x)
Definition: main_helpers.cpp:7
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:806
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
hardwareprofile.h
v2video.h
HouseKeeper
Manages registered HouseKeeperTasks and queues tasks for operation.
Definition: housekeeper.h:150
MythCoreContext::SendMessage
void SendMessage(const QString &message)
Definition: mythcorecontext.cpp:1543
AutoExpire::PrintExpireList
void PrintExpireList(const QString &expHost="ALL")
Prints a summary of the files that can be deleted.
Definition: autoexpire.cpp:788
GENERIC_EXIT_OK
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
MythHTTPScopedInstance
Definition: mythhttpinstance.h:35
ThemeUpdateTask
Definition: backendhousekeeper.h:42
v2music.h
Scheduler::GetError
int GetError(void) const
Definition: scheduler.h:118
dbutil.h
backendcontext.h
EITCache::ClearChannelLocks
static MTV_PUBLIC void ClearChannelLocks(void)
Removes old channel locks, use it only at master backend start.
Definition: eitcache.cpp:434
CONTENT_SERVICE
#define CONTENT_SERVICE
Definition: v2content.h:34
error
static void error(const char *str,...)
Definition: vbi.cpp:35
MediaServer
Definition: mediaserver.h:32
MythCoreContext::GetScheduler
MythScheduler * GetScheduler(void)
Definition: mythcorecontext.cpp:1920
mythdb.h
MythCoreContext::SendReceiveStringList
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
Definition: mythcorecontext.cpp:1397
UpgradeTVDatabaseSchema
bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, const bool upgradeIfNoUI, const bool informSystemd)
Called from outside dbcheck.cpp to update the schema.
Definition: dbcheck.cpp:360
HttpStatus
Definition: httpstatus.h:42
connect_to_master
int connect_to_master(void)
Definition: main_helpers.cpp:470
TVRec::Init
bool Init(void)
Performs instance initialization, returns true on success.
Definition: tv_rec.cpp:150
MythHTTPRewrite::RewriteToSPA
static HTTPResponse RewriteToSPA(HTTPRequest2 Request, const QString &File)
A convenience method to seemlessly redirect requests to a Single Page web app (SPA)
Definition: mythhttprewrite.cpp:50
BackendContext
Definition: backendcontext.h:41
MythCoreContext::ConnectToMasterServer
bool ConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
Definition: mythcorecontext.cpp:383
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:303
logLevel
LogLevel_t logLevel
Definition: logging.cpp:89
TaskQueue::RequestTerminate
void RequestTerminate()
Definition: taskqueue.cpp:101
gExpirer
AutoExpire * gExpirer
Definition: backendcontext.cpp:8
HttpServer::RegisterExtension
void RegisterExtension(HttpServerExtension *pExtension)
Definition: httpserver.cpp:318
MythCoreContext::SetScheduler
void SetScheduler(MythScheduler *sched)
Definition: mythcorecontext.cpp:1915
Scheduler::FillRecordListFromDB
void FillRecordListFromDB(uint recordid=0)
Definition: scheduler.cpp:486
v2content.h
GENERIC_EXIT_DB_NOTIMEZONE
#define GENERIC_EXIT_DB_NOTIMEZONE
Missing DB time zone support.
Definition: exitcodes.h:36
httpstatus.h
sched
Scheduler * sched
mythhttpinstance.h
LOC
#define LOC
Definition: main_helpers.cpp:74
RadioStreamUpdateTask
Definition: backendhousekeeper.h:30
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:202
MainServer
Definition: mainserver.h:113
AutoExpire
Used to expire recordings to make space for new recordings.
Definition: autoexpire.h:60
v2myth.h
Scheduler::DisableScheduling
void DisableScheduling(void)
Definition: scheduler.h:109
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:607
UPnp::GetHttpServer
HttpServer * GetHttpServer()
Definition: upnp.h:128
MythCoreContext::CheckProtoVersion
bool CheckProtoVersion(MythSocket *socket, std::chrono::milliseconds timeout=kMythSocketLongTimeout, bool error_dialog_desired=false)
Definition: mythcorecontext.cpp:1693
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
print_warnings
void print_warnings(const MythBackendCommandLineParser &cmdline)
Definition: main_helpers.cpp:554
mythsystemevent.h
HouseKeeper::RegisterTask
void RegisterTask(HouseKeeperTask *task)
Definition: housekeeper.cpp:635
gBackendContext
BackendContext * gBackendContext
Definition: backendcontext.cpp:12
HttpStatus::SetMainServer
void SetMainServer(MainServer *mainServer)
Definition: httpstatus.h:88
gHousekeeping
HouseKeeper * gHousekeeping
Definition: backendcontext.cpp:10
v2dvr.h
remoteutil.h
scheduler.h
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
LogCleanerTask
Definition: backendhousekeeper.h:7
VIDEO_SERVICE
#define VIDEO_SERVICE
Definition: v2video.h:11
mythversion.h
MythSocket
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:25
SSDP::Instance
static SSDP * Instance()
Definition: ssdp.cpp:55
run_backend
int run_backend(MythBackendCommandLineParser &cmdline)
Definition: main_helpers.cpp:582
MythCoreContext::IsMasterBackend
bool IsMasterBackend(void)
is this the actual MBE process
Definition: mythcorecontext.cpp:721
v2channel.h
autoexpire.h
MythHTTPInstance::Addservices
static void Addservices(const HTTPServices &Services)
Definition: mythhttpinstance.cpp:102
programinfo.h
g_pUPnp
MediaServer * g_pUPnp
Definition: backendcontext.cpp:11
mythlogging.h
handle_command
int handle_command(const MythBackendCommandLineParser &cmdline)
Definition: main_helpers.cpp:324
dbcheck.h
MythCoreContext::GetBackendServerPort
int GetBackendServerPort(void)
Returns the locally defined backend control port.
Definition: mythcorecontext.cpp:1090
MythCoreContext::SendSystemEvent
void SendSystemEvent(const QString &msg)
Definition: mythcorecontext.cpp:1570
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:992
signalhandling.h
verboseMask
uint64_t verboseMask
Definition: logging.cpp:101
MSqlQuery::first
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
Definition: mythdbcon.cpp:816
TaskQueue::Instance
static TaskQueue * Instance()
Definition: taskqueue.cpp:58
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:539
gSysEventHandler
MythSystemEventHandler * gSysEventHandler
Definition: backendcontext.cpp:14
compat.h
MythHTTPRewrite::RewriteFile
static HTTPResponse RewriteFile(HTTPRequest2 Request, const QString &File)
A convenience method to seemlessly redirect requests for files to a context specific file.
Definition: mythhttprewrite.cpp:22
MythCoreContext::GetBackendServerIP
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
Definition: mythcorecontext.cpp:1030
MythCoreContext::SetDVBv3
void SetDVBv3(bool dvbv3)
Definition: mythcorecontext.h:334
eitcache.h
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:227
mythhttprewrite.h
GENERIC_EXIT_SETUP_ERROR
#define GENERIC_EXIT_SETUP_ERROR
Incorrectly setup system.
Definition: exitcodes.h:21
Scheduler::SetExpirer
void SetExpirer(AutoExpire *autoExpirer)
Definition: scheduler.h:55
mythtranslation.h
v2capture.h
MythTZ
Definition: mythtimezone.cpp:21
setupTVs
bool setupTVs(bool ismaster, bool &error)
Definition: main_helpers.cpp:80
HardwareProfileTask
Definition: hardwareprofile.h:52
scheduledrecording.h
ArtworkTask
Definition: backendhousekeeper.h:57
DBUtil::CheckTimeZoneSupport
static bool CheckTimeZoneSupport(void)
Check if MySQL has working timz zone support.
Definition: dbutil.cpp:867
CHANNEL_SERVICE
#define CHANNEL_SERVICE
Definition: v2channel.h:35
storagegroup.h
jobqueue.h
Scheduler::PrintList
void PrintList(bool onlyFutureRecordings=false)
Definition: scheduler.h:98
cleanup
void cleanup(void)
Definition: main_helpers.cpp:255
TVRec::s_inputsLock
static QReadWriteLock s_inputsLock
Definition: tv_rec.h:433
DVR_SERVICE
#define DVR_SERVICE
Definition: v2dvr.h:39
commandlineparser.h
uint
unsigned int uint
Definition: compat.h:144
gTVList
QMap< int, EncoderLink * > gTVList
Definition: backendcontext.cpp:7
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:61
JobQueueRecoverTask
Definition: backendhousekeeper.h:70
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:938
MediaServer::Init
void Init(bool bIsMaster, bool bDisableUPnp=false)
Definition: mediaserver.cpp:70
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
MainServer::GetExitCode
int GetExitCode() const
Definition: mainserver.h:152
gJobQueue
JobQueue * gJobQueue
Definition: backendcontext.cpp:9
STATUS_SERVICE
#define STATUS_SERVICE
Definition: v2status.h:31
GUIDE_SERVICE
#define GUIDE_SERVICE
Definition: v2guide.h:38
MythHTTPRoot::RedirectRoot
static HTTPResponse RedirectRoot(HTTPRequest2 Request, const QString &File)
A convenience method to seemlessly redirect requests for index.html to a context specific file.
Definition: mythhttproot.cpp:24
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:1006
backendhousekeeper.h
mediaserver.h
cmdline
MythCommFlagCommandLineParser cmdline
Definition: mythtv/programs/mythcommflag/main.cpp:75
CleanupTask
Definition: backendhousekeeper.h:15
MythCommandLineParser::toString
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
Definition: mythcommandlineparser.cpp:2252
gPidFile
QString gPidFile
Definition: backendcontext.cpp:13
mythhttproot.h
MythCommandLineParser::toBool
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
Definition: mythcommandlineparser.cpp:2095
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:882
CAPTURE_SERVICE
#define CAPTURE_SERVICE
Definition: v2capture.h:32
GENERIC_EXIT_SOCKET_ERROR
#define GENERIC_EXIT_SOCKET_ERROR
Socket error.
Definition: exitcodes.h:18
TVRec
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:145
mythcontext.h
GENERIC_EXIT_NO_MYTHCONTEXT
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:13
tv_rec.h
v2guide.h
MYTH_SERVICE
#define MYTH_SERVICE
Definition: v2myth.h:16
HttpServer
Definition: httpserver.h:109
mainserver.h
MUSIC_SERVICE
#define MUSIC_SERVICE
Definition: v2music.h:17
JobQueue
Definition: jobqueue.h:126
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:864
MythBackendCommandLineParser
Definition: mythbackend/commandlineparser.h:7
HTTPServices
std::vector< HTTPService > HTTPServices
Definition: mythhttptypes.h:54
mainServer
static MainServer * mainServer
Definition: main_helpers.cpp:78
MythCoreContext::IsMasterHost
bool IsMasterHost(void)
is this the same host as the master
Definition: mythcorecontext.cpp:685
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
previewgenerator.h
GENERIC_EXIT_CONNECT_ERROR
#define GENERIC_EXIT_CONNECT_ERROR
Can't connect to master backend.
Definition: exitcodes.h:20
MythFillDatabaseTask
Definition: backendhousekeeper.h:79
ProgramInfo::CheckProgramIDAuthorities
static void CheckProgramIDAuthorities(void)
Definition: programinfo.cpp:2365
MythTranslation::load
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
Definition: mythtranslation.cpp:37
exitcodes.h
MainServer::Stop
void Stop(void)
Definition: mainserver.cpp:358
MythSystemEventHandler
Handles incoming MythSystemEvent messages.
Definition: mythsystemevent.h:24
Scheduler::FillRecordListFromMaster
void FillRecordListFromMaster(void)
Definition: scheduler.cpp:569
ScheduledRecording::RescheduleMatch
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
Definition: scheduledrecording.h:17
StorageGroup::CheckAllStorageGroupDirs
static void CheckAllStorageGroupDirs(void)
Definition: storagegroup.cpp:729
gContext
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:64
HouseKeeper::Start
void Start(void)
Definition: housekeeper.cpp:669
mythtimezone.h
SignalHandler::Done
static void Done(void)
Definition: signalhandling.cpp:134
MythCoreContext::SetExiting
void SetExiting(bool exiting=true)
Definition: mythcorecontext.cpp:2127
TVRec::GetTVRec
static TVRec * GetTVRec(uint inputid)
Definition: tv_rec.cpp:4762
v2status.h
SSDP::RequestTerminate
void RequestTerminate(void)
Definition: ssdp.cpp:137
GENERIC_EXIT_INVALID_TIME
#define GENERIC_EXIT_INVALID_TIME
Invalid time.
Definition: exitcodes.h:22
HTTPHandlers
std::vector< HTTPHandler > HTTPHandlers
Definition: mythhttptypes.h:47
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:831
TVRec::s_inputs
static QMap< uint, TVRec * > s_inputs
Definition: tv_rec.h:434
MythHTTPInstance::AddErrorPageHandler
static void AddErrorPageHandler(const HTTPHandler &Handler)
Definition: mythhttpinstance.cpp:112
GENERIC_EXIT_DB_OUTOFDATE
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16