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