MythTV  master
main_helpers.cpp
Go to the documentation of this file.
1 #include "mythconfig.h"
2 #if CONFIG_DARWIN
3  #include <sys/aio.h> // O_SYNC
4 #endif
5 #if CONFIG_SYSTEMD_NOTIFY
6  #include <systemd/sd-daemon.h>
7  #define be_sd_notify(x) \
8  (void)sd_notify(0, x);
9 #else
10  #define be_sd_notify(x)
11 #endif
12 
13 // C++ headers
14 #include <cerrno>
15 #include <csignal>
16 #include <cstdlib>
17 #include <fcntl.h>
18 #include <sys/stat.h>
19 #include <sys/time.h> // for setpriority
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 #include <QCoreApplication>
24 #include <QFileInfo>
25 #include <QRegExp>
26 #include <QFile>
27 #include <QDir>
28 #include <QMap>
29 
30 #include "tv_rec.h"
31 #include "scheduledrecording.h"
32 #include "autoexpire.h"
33 #include "scheduler.h"
34 #include "mainserver.h"
35 #include "encoderlink.h"
36 #include "remoteutil.h"
37 #include "backendhousekeeper.h"
38 
39 #include "mythcontext.h"
40 #include "mythversion.h"
41 #include "mythdb.h"
42 #include "dbutil.h"
43 #include "exitcodes.h"
44 #include "compat.h"
45 #include "storagegroup.h"
46 #include "programinfo.h"
47 #include "dbcheck.h"
48 #include "jobqueue.h"
49 #include "previewgenerator.h"
50 #include "commandlineparser.h"
51 #include "mythsystemevent.h"
52 #include "main_helpers.h"
53 #include "backendcontext.h"
54 #include "mythtranslation.h"
55 #include "mythtimezone.h"
56 #include "signalhandling.h"
57 #include "hardwareprofile.h"
58 #include "eitcache.h"
59 
60 #include "mediaserver.h"
61 #include "httpstatus.h"
62 #include "mythlogging.h"
63 
64 #define LOC QString("MythBackend: ")
65 #define LOC_WARN QString("MythBackend, Warning: ")
66 #define LOC_ERR QString("MythBackend, Error: ")
67 
68 static MainServer *mainServer = nullptr;
69 
70 bool setupTVs(bool ismaster, bool &error)
71 {
72  error = false;
73  QString localhostname = gCoreContext->GetHostName();
74 
76 
77  if (ismaster)
78  {
79  // Hack to make sure recorded.basename gets set if the user
80  // downgrades to a prior version and creates new entries
81  // without it.
82  if (!query.exec("UPDATE recorded SET basename = CONCAT(chanid, '_', "
83  "DATE_FORMAT(starttime, '%Y%m%d%H%i00'), '_', "
84  "DATE_FORMAT(endtime, '%Y%m%d%H%i00'), '.nuv') "
85  "WHERE basename = '';"))
86  MythDB::DBError("Updating record basename", query);
87 
88  // Hack to make sure record.station gets set if the user
89  // downgrades to a prior version and creates new entries
90  // without it.
91  if (!query.exec("UPDATE channel SET callsign=chanid "
92  "WHERE callsign IS NULL OR callsign='';"))
93  MythDB::DBError("Updating channel callsign", query);
94 
95  if (query.exec("SELECT MIN(chanid) FROM channel;"))
96  {
97  query.first();
98  int min_chanid = query.value(0).toInt();
99  if (!query.exec(QString("UPDATE record SET chanid = %1 "
100  "WHERE chanid IS NULL;").arg(min_chanid)))
101  MythDB::DBError("Updating record chanid", query);
102  }
103  else
104  MythDB::DBError("Querying minimum chanid", query);
105 
106  MSqlQuery records_without_station(MSqlQuery::InitCon());
107  records_without_station.prepare("SELECT record.chanid,"
108  " channel.callsign FROM record LEFT JOIN channel"
109  " ON record.chanid = channel.chanid WHERE record.station='';");
110  if (records_without_station.exec() && records_without_station.next())
111  {
112  MSqlQuery update_record(MSqlQuery::InitCon());
113  update_record.prepare("UPDATE record SET station = :CALLSIGN"
114  " WHERE chanid = :CHANID;");
115  do
116  {
117  update_record.bindValue(":CALLSIGN",
118  records_without_station.value(1));
119  update_record.bindValue(":CHANID",
120  records_without_station.value(0));
121  if (!update_record.exec())
122  {
123  MythDB::DBError("Updating record station", update_record);
124  }
125  } while (records_without_station.next());
126  }
127  }
128 
129  if (!query.exec(
130  "SELECT cardid, hostname "
131  "FROM capturecard "
132  "ORDER BY cardid"))
133  {
134  MythDB::DBError("Querying Recorders", query);
135  return false;
136  }
137 
138  vector<uint> cardids;
139  vector<QString> hosts;
140  while (query.next())
141  {
142  uint cardid = query.value(0).toUInt();
143  QString host = query.value(1).toString();
144  QString cidmsg = QString("Card %1").arg(cardid);
145 
146  if (host.isEmpty())
147  {
148  LOG(VB_GENERAL, LOG_ERR, cidmsg +
149  " does not have a hostname defined.\n"
150  "Please run setup and confirm all of the capture cards.\n");
151  continue;
152  }
153 
154  cardids.push_back(cardid);
155  hosts.push_back(host);
156  }
157 
158  QWriteLocker tvlocker(&TVRec::s_inputsLock);
159 
160  for (size_t i = 0; i < cardids.size(); i++)
161  {
162  if (hosts[i] == localhostname) {
163  // No memory leak. The constructor for TVRec adds the item
164  // to the static map TVRec::s_inputs.
165  new TVRec(cardids[i]);
166  }
167  }
168 
169  for (size_t i = 0; i < cardids.size(); i++)
170  {
171  uint cardid = cardids[i];
172  QString host = hosts[i];
173  QString cidmsg = QString("Card %1").arg(cardid);
174 
175  if (!ismaster)
176  {
177  if (host == localhostname)
178  {
179  TVRec *tv = TVRec::GetTVRec(cardid);
180  if (tv && tv->Init())
181  {
182  auto *enc = new EncoderLink(cardid, tv);
183  tvList[cardid] = enc;
184  }
185  else
186  {
187  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
188  cidmsg + " failed init");
189  delete tv;
190  // The master assumes card comes up so we need to
191  // set error and exit if a non-master card fails.
192  error = true;
193  }
194  }
195  }
196  else
197  {
198  if (host == localhostname)
199  {
200  TVRec *tv = TVRec::GetTVRec(cardid);
201  if (tv && tv->Init())
202  {
203  auto *enc = new EncoderLink(cardid, tv);
204  tvList[cardid] = enc;
205  }
206  else
207  {
208  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
209  cidmsg + " failed init");
210  delete tv;
211  }
212  }
213  else
214  {
215  auto *enc = new EncoderLink(cardid, nullptr, host);
216  tvList[cardid] = enc;
217  }
218  }
219  }
220 
221  if (tvList.empty())
222  {
223  LOG(VB_GENERAL, LOG_WARNING, LOC +
224  "No valid capture cards are defined in the database.");
225  }
226 
227  return true;
228 }
229 
230 void cleanup(void)
231 {
232  if (mainServer)
233  {
234  mainServer->Stop();
235  qApp->processEvents();
236  }
237 
238  if (gCoreContext)
240 
241  delete sysEventHandler;
242  sysEventHandler = nullptr;
243 
244  delete housekeeping;
245  housekeeping = nullptr;
246 
247  if (gCoreContext)
248  {
249  delete gCoreContext->GetScheduler();
250  gCoreContext->SetScheduler(nullptr);
251  }
252 
253  delete expirer;
254  expirer = nullptr;
255 
256  delete jobqueue;
257  jobqueue = nullptr;
258 
259  delete g_pUPnp;
260  g_pUPnp = nullptr;
261 
262  if (SSDP::Instance())
263  {
265  SSDP::Instance()->wait();
266  }
267 
268  if (TaskQueue::Instance())
269  {
272  }
273 
274  while (!TVRec::s_inputs.empty())
275  {
276  TVRec *rec = *TVRec::s_inputs.begin();
277  delete rec;
278  }
279 
280 
281  delete gContext;
282  gContext = nullptr;
283 
284  delete mainServer;
285  mainServer = nullptr;
286 
287  delete gBackendContext;
288  gBackendContext = nullptr;
289 
290  if (pidfile.size())
291  {
292  unlink(pidfile.toLatin1().constData());
293  pidfile.clear();
294  }
295 
297 }
298 
300 {
301  QString eventString;
302 
303  if (cmdline.toBool("event"))
304  eventString = cmdline.toString("event");
305  else if (cmdline.toBool("systemevent"))
306  eventString = "SYSTEM_EVENT " +
307  cmdline.toString("systemevent") +
308  QString(" SENDER %1").arg(gCoreContext->GetHostName());
309 
310  if (!eventString.isEmpty())
311  {
313  {
314  gCoreContext->SendMessage(eventString);
315  return GENERIC_EXIT_OK;
316  }
318  }
319 
320  if (cmdline.toBool("setverbose"))
321  {
323  {
324  QString message = "SET_VERBOSE ";
325  message += cmdline.toString("setverbose");
326 
327  gCoreContext->SendMessage(message);
328  LOG(VB_GENERAL, LOG_INFO,
329  QString("Sent '%1' message").arg(message));
330  return GENERIC_EXIT_OK;
331  }
332  LOG(VB_GENERAL, LOG_ERR,
333  "Unable to connect to backend, verbose mask unchanged ");
335  }
336 
337  if (cmdline.toBool("setloglevel"))
338  {
340  {
341  QString message = "SET_LOG_LEVEL ";
342  message += cmdline.toString("setloglevel");
343 
344  gCoreContext->SendMessage(message);
345  LOG(VB_GENERAL, LOG_INFO,
346  QString("Sent '%1' message").arg(message));
347  return GENERIC_EXIT_OK;
348  }
349  LOG(VB_GENERAL, LOG_ERR,
350  "Unable to connect to backend, log level unchanged ");
352  }
353 
354  if (cmdline.toBool("clearcache"))
355  {
357  {
358  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
359  LOG(VB_GENERAL, LOG_INFO, "Sent CLEAR_SETTINGS_CACHE message");
360  return GENERIC_EXIT_OK;
361  }
362  LOG(VB_GENERAL, LOG_ERR, "Unable to connect to backend, settings "
363  "cache will not be cleared.");
365  }
366 
367  if (cmdline.toBool("printsched") ||
368  cmdline.toBool("testsched"))
369  {
370  auto *sched = new Scheduler(false, &tvList);
371  if (cmdline.toBool("printsched"))
372  {
374  {
375  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master");
376  delete sched;
378  }
379  cout << "Retrieving Schedule from Master backend.\n";
381  }
382  else
383  {
384  cout << "Calculating Schedule from database.\n" <<
385  "Inputs, Card IDs, and Conflict info may be invalid "
386  "if you have multiple tuners.\n";
389  }
390 
391  verboseMask |= VB_SCHEDULE;
392  LogLevel_t oldLogLevel = logLevel;
393  logLevel = LOG_DEBUG;
394  sched->PrintList(true);
395  logLevel = oldLogLevel;
396  delete sched;
397  return GENERIC_EXIT_OK;
398  }
399 
400  if (cmdline.toBool("resched"))
401  {
402  bool ok = false;
404  {
405  LOG(VB_GENERAL, LOG_INFO, "Connected to master for reschedule");
406  ScheduledRecording::RescheduleMatch(0, 0, 0, QDateTime(),
407  "MythBackendCommand");
408  ok = true;
409  }
410  else
411  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for reschedule");
412 
414  }
415 
416  if (cmdline.toBool("scanvideos"))
417  {
418  bool ok = false;
420  {
421  gCoreContext->SendReceiveStringList(QStringList() << "SCAN_VIDEOS");
422  LOG(VB_GENERAL, LOG_INFO, "Requested video scan");
423  ok = true;
424  }
425  else
426  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for video scan");
427 
429  }
430 
431  if (cmdline.toBool("printexpire"))
432  {
433  expirer = new AutoExpire();
434  expirer->PrintExpireList(cmdline.toString("printexpire"));
435  return GENERIC_EXIT_OK;
436  }
437 
438  // This should never actually be reached..
439  return GENERIC_EXIT_OK;
440 }
441 using namespace MythTZ;
442 
444 {
445  auto *tempMonitorConnection = new MythSocket();
446  if (tempMonitorConnection->ConnectToHost(
449  {
450  if (!gCoreContext->CheckProtoVersion(tempMonitorConnection))
451  {
452  LOG(VB_GENERAL, LOG_ERR, "Master backend is incompatible with "
453  "this backend.\nCannot become a slave.");
454  tempMonitorConnection->DecrRef();
456  }
457 
458  QStringList tempMonitorDone("DONE");
459 
460  QStringList tempMonitorAnnounce(QString("ANN Monitor %1 0")
461  .arg(gCoreContext->GetHostName()));
462  tempMonitorConnection->SendReceiveStringList(tempMonitorAnnounce);
463  if (tempMonitorAnnounce.empty() ||
464  tempMonitorAnnounce[0] == "ERROR")
465  {
466  tempMonitorConnection->DecrRef();
467  tempMonitorConnection = nullptr;
468  if (tempMonitorAnnounce.empty())
469  {
470  LOG(VB_GENERAL, LOG_ERR, LOC +
471  "Failed to open event socket, timeout");
472  }
473  else
474  {
475  LOG(VB_GENERAL, LOG_ERR, LOC +
476  "Failed to open event socket" +
477  ((tempMonitorAnnounce.size() >= 2) ?
478  QString(", error was %1").arg(tempMonitorAnnounce[1]) :
479  QString(", remote error")));
480  }
481  }
482 
483  QStringList timeCheck;
484  if (tempMonitorConnection)
485  {
486  timeCheck.push_back("QUERY_TIME_ZONE");
487  tempMonitorConnection->SendReceiveStringList(timeCheck);
488  tempMonitorConnection->WriteStringList(tempMonitorDone);
489  }
490  if (timeCheck.size() < 3)
491  {
492  if (tempMonitorConnection)
493  tempMonitorConnection->DecrRef();
495  }
496 
497  QDateTime our_time = MythDate::current();
498  QDateTime master_time = MythDate::fromString(timeCheck[2]);
499  int timediff = abs(our_time.secsTo(master_time));
500 
501  if (timediff > 300)
502  {
503  LOG(VB_GENERAL, LOG_ERR,
504  QString("Current time on the master backend differs by "
505  "%1 seconds from time on this system. Exiting.")
506  .arg(timediff));
507  if (tempMonitorConnection)
508  tempMonitorConnection->DecrRef();
510  }
511 
512  if (timediff > 20)
513  {
514  LOG(VB_GENERAL, LOG_WARNING,
515  QString("Time difference between the master "
516  "backend and this system is %1 seconds.")
517  .arg(timediff));
518  }
519  }
520  if (tempMonitorConnection)
521  tempMonitorConnection->DecrRef();
522 
523  return GENERIC_EXIT_OK;
524 }
525 
526 
528 {
529  if (cmdline.toBool("nohousekeeper"))
530  {
531  LOG(VB_GENERAL, LOG_WARNING, LOC +
532  "****** The Housekeeper has been DISABLED with "
533  "the --nohousekeeper option ******");
534  }
535  if (cmdline.toBool("nosched"))
536  {
537  LOG(VB_GENERAL, LOG_WARNING, LOC +
538  "********** The Scheduler has been DISABLED with "
539  "the --nosched option **********");
540  }
541  if (cmdline.toBool("noautoexpire"))
542  {
543  LOG(VB_GENERAL, LOG_WARNING, LOC +
544  "********* Auto-Expire has been DISABLED with "
545  "the --noautoexpire option ********");
546  }
547  if (cmdline.toBool("nojobqueue"))
548  {
549  LOG(VB_GENERAL, LOG_WARNING, LOC +
550  "********* The JobQueue has been DISABLED with "
551  "the --nojobqueue option *********");
552  }
553 }
554 
556 {
558 
560  {
561  LOG(VB_GENERAL, LOG_ERR,
562  "MySQL time zone support is missing. "
563  "Please install it and try again. "
564  "See 'mysql_tzinfo_to_sql' for assistance.");
566  }
567 
568  bool ismaster = gCoreContext->IsMasterHost();
569 
570  if (!UpgradeTVDatabaseSchema(ismaster, ismaster, true))
571  {
572  LOG(VB_GENERAL, LOG_ERR,
573  QString("Couldn't upgrade database to new schema on %1 backend.")
574  .arg(ismaster ? "master" : "slave"));
576  }
577 
578  be_sd_notify("STATUS=Loading translation");
579  MythTranslation::load("mythfrontend");
580 
581  if (!ismaster)
582  {
583  be_sd_notify("STATUS=Connecting to master backend");
584  int ret = connect_to_master();
585  if (ret != GENERIC_EXIT_OK)
586  return ret;
587  }
588 
589  be_sd_notify("STATUS=Get backend server port");
590  int port = gCoreContext->GetBackendServerPort();
591  if (gCoreContext->GetBackendServerIP().isEmpty())
592  {
593  cerr << "No setting found for this machine's BackendServerIP.\n"
594  << "Please run setup on this machine and modify the first page\n"
595  << "of the general settings.\n";
597  }
598 
600 
601  if (ismaster)
602  {
603  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Starting up as the master server.");
604  }
605  else
606  {
607  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Running as a slave backend.");
608  }
609 
610  if (ismaster)
611  {
613  }
614 
616 
617  bool fatal_error = false;
618  bool runsched = setupTVs(ismaster, fatal_error);
619  if (fatal_error)
621 
622  Scheduler *sched = nullptr;
623  if (ismaster)
624  {
625  if (runsched)
626  {
627  be_sd_notify("STATUS=Creating scheduler");
628  sched = new Scheduler(true, &tvList);
629  int err = sched->GetError();
630  if (err)
631  return err;
632 
633  if (cmdline.toBool("nosched"))
635  }
636 
637  if (!cmdline.toBool("noautoexpire"))
638  {
639  expirer = new AutoExpire(&tvList);
640  if (sched)
642  }
644  }
645 
646  if (!cmdline.toBool("nohousekeeper"))
647  {
648  be_sd_notify("STATUS=Creating housekeeper");
649  housekeeping = new HouseKeeper();
650 
651  if (ismaster)
652  {
658 
659  // only run this task if MythMusic is installed and we have a new enough schema
660  if (gCoreContext->GetNumSetting("MusicDBSchemaVer", 0) >= 1024)
662  }
663 
665 #ifdef __linux__
666  #ifdef CONFIG_BINDINGS_PYTHON
668  #endif
669 #endif
670 
671  housekeeping->Start();
672  }
673 
674  if (!cmdline.toBool("nojobqueue"))
675  jobqueue = new JobQueue(ismaster);
676 
677  // ----------------------------------------------------------------------
678  //
679  // ----------------------------------------------------------------------
680 
681  if (g_pUPnp == nullptr)
682  {
683  be_sd_notify("STATUS=Creating UPnP media server");
684  g_pUPnp = new MediaServer();
685 
686  g_pUPnp->Init(ismaster, cmdline.toBool("noupnp"));
687  }
688 
689  // ----------------------------------------------------------------------
690  // Setup status server
691  // ----------------------------------------------------------------------
692 
693  HttpStatus *httpStatus = nullptr;
694  HttpServer *pHS = g_pUPnp->GetHttpServer();
695 
696  if (pHS)
697  {
698  LOG(VB_GENERAL, LOG_INFO, "Main::Registering HttpStatus Extension");
699  be_sd_notify("STATUS=Registering HttpStatus Extension");
700 
701  httpStatus = new HttpStatus( &tvList, sched, expirer, ismaster );
702  pHS->RegisterExtension( httpStatus );
703  }
704 
705  be_sd_notify("STATUS=Creating main server");
706  mainServer = new MainServer(
707  ismaster, port, &tvList, sched, expirer);
708 
709  int exitCode = mainServer->GetExitCode();
710  if (exitCode != GENERIC_EXIT_OK)
711  {
712  LOG(VB_GENERAL, LOG_CRIT,
713  "Backend exiting, MainServer initialization error.");
714  cleanup();
715  return exitCode;
716  }
717 
718  if (httpStatus && mainServer)
719  httpStatus->SetMainServer(mainServer);
720 
721  be_sd_notify("STATUS=Check all storage groups");
723 
724  be_sd_notify("STATUS=Sending \"master started\" message");
726  gCoreContext->SendSystemEvent("MASTER_STARTED");
727 
728  // Provide systemd ready notification (for type=notify units)
729  be_sd_notify("READY=1");
730 
733  exitCode = qApp->exec();
736 
738  {
739  gCoreContext->SendSystemEvent("MASTER_SHUTDOWN");
740  qApp->processEvents();
741  }
742 
743  LOG(VB_GENERAL, LOG_NOTICE, "MythBackend exiting");
744  be_sd_notify("STOPPING=1\nSTATUS=Exiting");
745 
746  return exitCode;
747 }
static void CheckProgramIDAuthorities(void)
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:781
MythScheduler * GetScheduler(void)
void FillRecordListFromMaster(void)
Definition: scheduler.cpp:567
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:862
bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, const bool upgradeIfNoUI, const bool informSystemd)
Called from outside dbcheck.cpp to update the schema.
static TaskQueue * Instance()
Definition: taskqueue.cpp:58
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
#define GENERIC_EXIT_CONNECT_ERROR
Can't connect to master backend.
Definition: exitcodes.h:20
void RegisterTask(HouseKeeperTask *task)
QString pidfile
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
static MTV_PUBLIC void ClearChannelLocks(void)
removes old channel locks, use it only at master backend start
Definition: eitcache.cpp:441
static void error(const char *str,...)
Definition: vbi.c:42
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
#define LOC
static int GetMasterServerPort(void)
Returns the Master Backend control port If no master server port has been defined in the database,...
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
A simple wrapper containing details about a UPnP Media Server.
Definition: mediaserver.h:32
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:311
MediaServer * g_pUPnp
HouseKeeper * housekeeping
bool ConnectToMasterServer(bool blockingClient=true, bool openEventSocket=true)
MythSystemEventHandler * sysEventHandler
void RegisterExtension(HttpServerExtension *)
Definition: httpserver.cpp:321
void SetScheduler(MythScheduler *sched)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
uint64_t verboseMask
Definition: logging.cpp:107
void DisableScheduling(void)
Definition: scheduler.h:109
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:62
bool Init(void)
Performs instance initialization, returns true on success.
Definition: tv_rec.cpp:139
void SendMessage(const QString &message)
int GetBackendServerPort(void)
Returns the locally defined backend control port.
QString GetMasterServerIP(void)
Returns the Master Backend IP address If the address is an IPv6 address, the scope Id is removed.
int connect_to_master(void)
QVariant value(int i) const
Definition: mythdbcon.h:198
void Stop(void)
Definition: mainserver.cpp:358
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
static QReadWriteLock s_inputsLock
Definition: tv_rec.h:424
int run_backend(MythBackendCommandLineParser &cmdline)
#define GENERIC_EXIT_DB_NOTIMEZONE
Missing DB time zone support.
Definition: exitcodes.h:36
static void CheckAllStorageGroupDirs(void)
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:141
void SetMainServer(MainServer *mainServer)
Definition: httpstatus.h:88
void SetExiting(bool exiting=true)
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
void PrintList(bool onlyFutureRecordings=false)
Definition: scheduler.h:99
#define GENERIC_EXIT_SOCKET_ERROR
Socket error.
Definition: exitcodes.h:18
void RequestTerminate(void)
Definition: ssdp.cpp:141
Manages registered HouseKeeperTasks and queues tasks for operation.
Definition: housekeeper.h:148
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
void cleanup(void)
void FillRecordListFromDB(uint recordid=0)
Definition: scheduler.cpp:479
BackendContext * gBackendContext
static void Done(void)
#define GENERIC_EXIT_INVALID_TIME
Invalid time.
Definition: exitcodes.h:22
unsigned int uint
Definition: compat.h:140
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:534
MythCommFlagCommandLineParser cmdline
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
bool IsMasterHost(void)
is this the same host as the master
void SetExpirer(AutoExpire *autoExpirer)
Definition: scheduler.h:58
int GetExitCode() const
Definition: mainserver.h:150
void RequestTerminate()
Definition: taskqueue.cpp:101
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
Definition: mythdbcon.cpp:791
int GetNumSetting(const QString &key, int defaultval=0)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:806
HttpServer * GetHttpServer()
Definition: upnp.h:128
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
static SSDP * Instance()
Definition: ssdp.cpp:54
LogLevel_t logLevel
Definition: logging.cpp:95
Used to expire recordings to make space for new recordings.
Definition: autoexpire.h:61
AutoExpire * expirer
bool CheckProtoVersion(MythSocket *socket, uint timeout_ms=kMythSocketLongTimeout, bool error_dialog_desired=false)
void Init(bool bIsMaster, bool bDisableUPnp=false)
Definition: mediaserver.cpp:69
#define GENERIC_EXIT_SETUP_ERROR
Incorrectly setup system.
Definition: exitcodes.h:21
void PrintExpireList(const QString &expHost="ALL")
Prints a summary of the files that can be deleted.
Definition: autoexpire.cpp:794
static TVRec * GetTVRec(uint inputid)
Definition: tv_rec.cpp:4819
Class for communcating between myth backends and frontends.
Definition: mythsocket.h:26
static MainServer * mainServer
Scheduler * sched
Handles incoming MythSystemEvent messages.
void print_warnings(const MythBackendCommandLineParser &cmdline)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:602
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:13
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
bool IsMasterBackend(void)
is this the actual MBE process
#define be_sd_notify(x)
JobQueue * jobqueue
QString GetHostName(void)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
void SendSystemEvent(const QString &msg)
QMap< int, EncoderLink * > tvList
static QMap< uint, TVRec * > s_inputs
Definition: tv_rec.h:425
int handle_command(const MythBackendCommandLineParser &cmdline)
bool setupTVs(bool ismaster, bool &error)
static bool CheckTimeZoneSupport(void)
Check if MySQL has working timz zone support.
Definition: dbutil.cpp:868
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16
void Start(void)
int GetError(void) const
Definition: scheduler.h:118