MythTV  master
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  QWriteLocker tvlocker(&TVRec::inputsLock);
157 
158  for (uint i = 0; i < cardids.size(); i++)
159  {
160  if (hosts[i] == localhostname)
161  new TVRec(cardids[i]);
162  }
163 
164  for (uint i = 0; i < cardids.size(); i++)
165  {
166  uint cardid = cardids[i];
167  QString host = hosts[i];
168  QString cidmsg = QString("Card %1").arg(cardid);
169 
170  if (!ismaster)
171  {
172  if (host == localhostname)
173  {
174  TVRec *tv = TVRec::GetTVRec(cardid);
175  if (tv && tv->Init())
176  {
177  EncoderLink *enc = new EncoderLink(cardid, tv);
178  tvList[cardid] = enc;
179  }
180  else
181  {
182  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
183  cidmsg + " failed init");
184  delete tv;
185  // The master assumes card comes up so we need to
186  // set error and exit if a non-master card fails.
187  error = true;
188  }
189  }
190  }
191  else
192  {
193  if (host == localhostname)
194  {
195  TVRec *tv = TVRec::GetTVRec(cardid);
196  if (tv && tv->Init())
197  {
198  EncoderLink *enc = new EncoderLink(cardid, tv);
199  tvList[cardid] = enc;
200  }
201  else
202  {
203  LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards. " +
204  cidmsg + " failed init");
205  delete tv;
206  }
207  }
208  else
209  {
210  EncoderLink *enc = new EncoderLink(cardid, NULL, host);
211  tvList[cardid] = enc;
212  }
213  }
214  }
215 
216  if (tvList.empty())
217  {
218  LOG(VB_GENERAL, LOG_WARNING, LOC +
219  "No valid capture cards are defined in the database.");
220  }
221 
222  return true;
223 }
224 
225 void cleanup(void)
226 {
227  if (mainServer)
228  {
229  mainServer->Stop();
230  qApp->processEvents();
231  }
232 
233  if (gCoreContext)
235 
236  delete housekeeping;
237  housekeeping = NULL;
238 
239  if (gCoreContext)
240  {
241  delete gCoreContext->GetScheduler();
242  gCoreContext->SetScheduler(NULL);
243  }
244 
245  delete expirer;
246  expirer = NULL;
247 
248  delete jobqueue;
249  jobqueue = NULL;
250 
251  delete g_pUPnp;
252  g_pUPnp = NULL;
253 
254  if (SSDP::Instance())
255  {
257  SSDP::Instance()->wait();
258  }
259 
260  if (TaskQueue::Instance())
261  {
264  }
265 
266  while (!TVRec::inputs.empty())
267  {
268  TVRec *rec = *TVRec::inputs.begin();
269  delete rec;
270  }
271 
272 
273  delete gContext;
274  gContext = NULL;
275 
276  delete mainServer;
277  mainServer = NULL;
278 
279  delete gBackendContext;
280  gBackendContext = NULL;
281 
282  if (pidfile.size())
283  {
284  unlink(pidfile.toLatin1().constData());
285  pidfile.clear();
286  }
287 
289 }
290 
292 {
293  QString eventString;
294 
295  if (cmdline.toBool("event"))
296  eventString = cmdline.toString("event");
297  else if (cmdline.toBool("systemevent"))
298  eventString = "SYSTEM_EVENT " +
299  cmdline.toString("systemevent") +
300  QString(" SENDER %1").arg(gCoreContext->GetHostName());
301 
302  if (!eventString.isEmpty())
303  {
305  {
306  gCoreContext->SendMessage(eventString);
307  return GENERIC_EXIT_OK;
308  }
310  }
311 
312  if (cmdline.toBool("setverbose"))
313  {
315  {
316  QString message = "SET_VERBOSE ";
317  message += cmdline.toString("setverbose");
318 
319  gCoreContext->SendMessage(message);
320  LOG(VB_GENERAL, LOG_INFO,
321  QString("Sent '%1' message").arg(message));
322  return GENERIC_EXIT_OK;
323  }
324  else
325  {
326  LOG(VB_GENERAL, LOG_ERR,
327  "Unable to connect to backend, verbose mask unchanged ");
329  }
330  }
331 
332  if (cmdline.toBool("setloglevel"))
333  {
335  {
336  QString message = "SET_LOG_LEVEL ";
337  message += cmdline.toString("setloglevel");
338 
339  gCoreContext->SendMessage(message);
340  LOG(VB_GENERAL, LOG_INFO,
341  QString("Sent '%1' message").arg(message));
342  return GENERIC_EXIT_OK;
343  }
344  else
345  {
346  LOG(VB_GENERAL, LOG_ERR,
347  "Unable to connect to backend, log level unchanged ");
349  }
350  }
351 
352  if (cmdline.toBool("clearcache"))
353  {
355  {
356  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
357  LOG(VB_GENERAL, LOG_INFO, "Sent CLEAR_SETTINGS_CACHE message");
358  return GENERIC_EXIT_OK;
359  }
360  else
361  {
362  LOG(VB_GENERAL, LOG_ERR, "Unable to connect to backend, settings "
363  "cache will not be cleared.");
365  }
366  }
367 
368  if (cmdline.toBool("printsched") ||
369  cmdline.toBool("testsched"))
370  {
371  Scheduler *sched = new Scheduler(false, &tvList);
372  if (cmdline.toBool("printsched"))
373  {
375  {
376  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master");
377  delete sched;
379  }
380  cout << "Retrieving Schedule from Master backend.\n";
381  sched->FillRecordListFromMaster();
382  }
383  else
384  {
385  cout << "Calculating Schedule from database.\n" <<
386  "Inputs, Card IDs, and Conflict info may be invalid "
387  "if you have multiple tuners.\n";
389  sched->FillRecordListFromDB();
390  }
391 
392  verboseMask |= VB_SCHEDULE;
393  LogLevel_t oldLogLevel = logLevel;
394  logLevel = LOG_DEBUG;
395  sched->PrintList(true);
396  logLevel = oldLogLevel;
397  delete sched;
398  return GENERIC_EXIT_OK;
399  }
400 
401  if (cmdline.toBool("resched"))
402  {
403  bool ok = false;
405  {
406  LOG(VB_GENERAL, LOG_INFO, "Connected to master for reschedule");
407  ScheduledRecording::RescheduleMatch(0, 0, 0, QDateTime(),
408  "MythBackendCommand");
409  ok = true;
410  }
411  else
412  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for reschedule");
413 
415  }
416 
417  if (cmdline.toBool("scanvideos"))
418  {
419  bool ok = false;
421  {
422  gCoreContext->SendReceiveStringList(QStringList() << "SCAN_VIDEOS");
423  LOG(VB_GENERAL, LOG_INFO, "Requested video scan");
424  ok = true;
425  }
426  else
427  LOG(VB_GENERAL, LOG_ERR, "Cannot connect to master for video scan");
428 
430  }
431 
432  if (cmdline.toBool("printexpire"))
433  {
434  expirer = new AutoExpire();
435  expirer->PrintExpireList(cmdline.toString("printexpire"));
436  return GENERIC_EXIT_OK;
437  }
438 
439  // This should never actually be reached..
440  return GENERIC_EXIT_OK;
441 }
442 using namespace MythTZ;
443 
445 {
446  MythSocket *tempMonitorConnection = new MythSocket();
447  if (tempMonitorConnection->ConnectToHost(
450  {
451  if (!gCoreContext->CheckProtoVersion(tempMonitorConnection))
452  {
453  LOG(VB_GENERAL, LOG_ERR, "Master backend is incompatible with "
454  "this backend.\nCannot become a slave.");
455  tempMonitorConnection->DecrRef();
457  }
458 
459  QStringList tempMonitorDone("DONE");
460 
461  QStringList tempMonitorAnnounce(QString("ANN Monitor %1 0")
462  .arg(gCoreContext->GetHostName()));
463  tempMonitorConnection->SendReceiveStringList(tempMonitorAnnounce);
464  if (tempMonitorAnnounce.empty() ||
465  tempMonitorAnnounce[0] == "ERROR")
466  {
467  tempMonitorConnection->DecrRef();
468  tempMonitorConnection = NULL;
469  if (tempMonitorAnnounce.empty())
470  {
471  LOG(VB_GENERAL, LOG_ERR, LOC +
472  "Failed to open event socket, timeout");
473  }
474  else
475  {
476  LOG(VB_GENERAL, LOG_ERR, LOC +
477  "Failed to open event socket" +
478  ((tempMonitorAnnounce.size() >= 2) ?
479  QString(", error was %1").arg(tempMonitorAnnounce[1]) :
480  QString(", remote error")));
481  }
482  }
483 
484  QStringList timeCheck;
485  if (tempMonitorConnection)
486  {
487  timeCheck.push_back("QUERY_TIME_ZONE");
488  tempMonitorConnection->SendReceiveStringList(timeCheck);
489  tempMonitorConnection->WriteStringList(tempMonitorDone);
490  }
491  if (timeCheck.size() < 3)
492  {
493  if (tempMonitorConnection)
494  tempMonitorConnection->DecrRef();
496  }
497 
498  QDateTime our_time = MythDate::current();
499  QDateTime master_time = MythDate::fromString(timeCheck[2]);
500  int timediff = abs(our_time.secsTo(master_time));
501 
502  if (timediff > 300)
503  {
504  LOG(VB_GENERAL, LOG_ERR,
505  QString("Current time on the master backend differs by "
506  "%1 seconds from time on this system. Exiting.")
507  .arg(timediff));
508  if (tempMonitorConnection)
509  tempMonitorConnection->DecrRef();
511  }
512 
513  if (timediff > 20)
514  {
515  LOG(VB_GENERAL, LOG_WARNING,
516  QString("Time difference between the master "
517  "backend and this system is %1 seconds.")
518  .arg(timediff));
519  }
520  }
521  if (tempMonitorConnection)
522  tempMonitorConnection->DecrRef();
523 
524  return GENERIC_EXIT_OK;
525 }
526 
527 
529 {
530  if (cmdline.toBool("nohousekeeper"))
531  {
532  LOG(VB_GENERAL, LOG_WARNING, LOC +
533  "****** The Housekeeper has been DISABLED with "
534  "the --nohousekeeper option ******");
535  }
536  if (cmdline.toBool("nosched"))
537  {
538  LOG(VB_GENERAL, LOG_WARNING, LOC +
539  "********** The Scheduler has been DISABLED with "
540  "the --nosched option **********");
541  }
542  if (cmdline.toBool("noautoexpire"))
543  {
544  LOG(VB_GENERAL, LOG_WARNING, LOC +
545  "********* Auto-Expire has been DISABLED with "
546  "the --noautoexpire option ********");
547  }
548  if (cmdline.toBool("nojobqueue"))
549  {
550  LOG(VB_GENERAL, LOG_WARNING, LOC +
551  "********* The JobQueue has been DISABLED with "
552  "the --nojobqueue option *********");
553  }
554 }
555 
557 {
559 
561  {
562  LOG(VB_GENERAL, LOG_ERR,
563  "MySQL time zone support is missing. "
564  "Please install it and try again. "
565  "See 'mysql_tzinfo_to_sql' for assistance.");
567  }
568 
569  bool ismaster = gCoreContext->IsMasterHost();
570 
571  if (!UpgradeTVDatabaseSchema(ismaster, ismaster))
572  {
573  LOG(VB_GENERAL, LOG_ERR, "Couldn't upgrade database to new schema");
575  }
576 
577  MythTranslation::load("mythfrontend");
578 
579  if (!ismaster)
580  {
581  int ret = connect_to_master();
582  if (ret != GENERIC_EXIT_OK)
583  return ret;
584  }
585 
586  int port = gCoreContext->GetBackendServerPort();
587  if (gCoreContext->GetBackendServerIP().isEmpty())
588  {
589  cerr << "No setting found for this machine's BackendServerIP.\n"
590  << "Please run setup on this machine and modify the first page\n"
591  << "of the general settings.\n";
593  }
594 
595  MythSystemEventHandler *sysEventHandler = new MythSystemEventHandler();
596 
597  if (ismaster)
598  {
599  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Starting up as the master server.");
600  }
601  else
602  {
603  LOG(VB_GENERAL, LOG_NOTICE, LOC + "Running as a slave backend.");
604  }
605 
606  print_warnings(cmdline);
607 
608  bool fatal_error = false;
609  bool runsched = setupTVs(ismaster, fatal_error);
610  if (fatal_error)
611  {
612  delete sysEventHandler;
614  }
615 
616  Scheduler *sched = NULL;
617  if (ismaster)
618  {
619  if (runsched)
620  {
621  sched = new Scheduler(true, &tvList);
622  int err = sched->GetError();
623  if (err)
624  return err;
625 
626  if (cmdline.toBool("nosched"))
627  sched->DisableScheduling();
628  }
629 
630  if (!cmdline.toBool("noautoexpire"))
631  {
632  expirer = new AutoExpire(&tvList);
633  if (sched)
634  sched->SetExpirer(expirer);
635  }
636  gCoreContext->SetScheduler(sched);
637  }
638 
639  if (!cmdline.toBool("nohousekeeper"))
640  {
641  housekeeping = new HouseKeeper();
642 
643  if (ismaster)
644  {
650 
651  // only run this task if MythMusic is installed and we have a new enough schema
652  if (gCoreContext->GetNumSetting("MusicDBSchemaVer", 0) >= 1024)
654  }
655 
657 #ifdef __linux__
658  #ifdef CONFIG_BINDINGS_PYTHON
660  #endif
661 #endif
662 
663  housekeeping->Start();
664  }
665 
666  if (!cmdline.toBool("nojobqueue"))
667  jobqueue = new JobQueue(ismaster);
668 
669  // ----------------------------------------------------------------------
670  //
671  // ----------------------------------------------------------------------
672 
673  if (g_pUPnp == NULL)
674  {
675  g_pUPnp = new MediaServer();
676 
677  g_pUPnp->Init(ismaster, cmdline.toBool("noupnp"));
678  }
679 
680  // ----------------------------------------------------------------------
681  // Setup status server
682  // ----------------------------------------------------------------------
683 
684  HttpStatus *httpStatus = NULL;
685  HttpServer *pHS = g_pUPnp->GetHttpServer();
686 
687  if (pHS)
688  {
689  LOG(VB_GENERAL, LOG_INFO, "Main::Registering HttpStatus Extension");
690 
691  httpStatus = new HttpStatus( &tvList, sched, expirer, ismaster );
692  pHS->RegisterExtension( httpStatus );
693  }
694 
695  mainServer = new MainServer(
696  ismaster, port, &tvList, sched, expirer);
697 
698  int exitCode = mainServer->GetExitCode();
699  if (exitCode != GENERIC_EXIT_OK)
700  {
701  LOG(VB_GENERAL, LOG_CRIT,
702  "Backend exiting, MainServer initialization error.");
703  cleanup();
704  return exitCode;
705  }
706 
707  if (httpStatus && mainServer)
708  httpStatus->SetMainServer(mainServer);
709 
711 
713  gCoreContext->SendSystemEvent("MASTER_STARTED");
714 
715 #ifdef USING_SYSTEMD_NOTIFY
716  // Provide systemd ready notification (for type=notify units)
717  (void)sd_notify(0, "READY=1");
718 #endif
719 
722  exitCode = qApp->exec();
725 
727  {
728  gCoreContext->SendSystemEvent("MASTER_SHUTDOWN");
729  qApp->processEvents();
730  }
731 
732  LOG(VB_GENERAL, LOG_NOTICE, "MythBackend exiting");
733 
734  delete sysEventHandler;
735 
736  return exitCode;
737 }
static void CheckProgramIDAuthorities(void)
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:810
MythScheduler * GetScheduler(void)
void FillRecordListFromMaster(void)
Definition: scheduler.cpp:585
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:915
static TaskQueue * Instance()
Definition: taskqueue.cpp:66
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
#define GENERIC_EXIT_CONNECT_ERROR
Can&#39;t connect to master backend.
Definition: exitcodes.h:20
void RegisterTask(HouseKeeperTask *task)
QString pidfile
static void error(const char *str,...)
Definition: vbi.c:41
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
#define LOC
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:31
bool wait(unsigned long time=ULONG_MAX)
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:312
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:430
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:113
bool toBool(QString key) const
Returns stored QVariant as a boolean.
static QReadWriteLock inputsLock
Definition: tv_rec.h:429
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:63
bool Init(void)
Performs instance initialization, returns true on success.
Definition: tv_rec.cpp:173
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:182
void Stop(void)
Definition: mainserver.cpp:360
bool SendReceiveStringList(QStringList &strlist, bool quickTimeout=false, bool block=true)
Send a message to the backend and wait for a response.
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: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:103
#define GENERIC_EXIT_SOCKET_ERROR
Socket error.
Definition: exitcodes.h:18
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
void RequestTerminate(void)
Definition: ssdp.cpp:149
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&#39;s preferred language.
void cleanup(void)
void FillRecordListFromDB(uint recordid=0)
Definition: scheduler.cpp:497
void Init(bool bMaster, bool bDisableUPnp=false)
Definition: mediaserver.cpp:74
BackendContext * gBackendContext
static void Done(void)
#define GENERIC_EXIT_INVALID_TIME
Invalid time.
Definition: exitcodes.h:22
QString toString(QString key) const
Returns stored QVariant as a QString, falling to default if not provided.
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:555
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:62
int GetExitCode() const
Definition: mainserver.h:146
void RequestTerminate()
Definition: taskqueue.cpp:109
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
Definition: mythdbcon.cpp:820
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:835
HttpServer * GetHttpServer()
Definition: upnp.h:129
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:38
static SSDP * Instance()
Definition: ssdp.cpp:54
LogLevel_t logLevel
Definition: logging.cpp:101
bool ConnectToHost(const QString &hostname, quint16 port)
connect to host
Definition: mythsocket.cpp:394
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:800
#define GENERIC_EXIT_SETUP_ERROR
Incorrectly setup system.
Definition: exitcodes.h:21
static TVRec * GetTVRec(uint inputid)
Definition: tv_rec.cpp:4827
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:346
Handles incoming MythSystemEvent messages.
void print_warnings(const MythBackendCommandLineParser &cmdline)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:623
bool WriteStringList(const QStringList &list)
Definition: mythsocket.cpp:321
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:13
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:30
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)
Check if MySQL has working timz zone support.
Definition: dbutil.cpp:879
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16
void Start(void)
int GetError(void) const
Definition: scheduler.h:122