MythTV  master
mythtv/programs/mythfrontend/main.cpp
Go to the documentation of this file.
1 #include <cerrno>
2 #include <csignal>
3 #include <cstdlib>
4 #include <fcntl.h>
5 #include <iostream>
6 using namespace std;
7 
8 #include <QFile>
9 #include <QFileInfo>
10 #include <QMap>
11 #include <QKeyEvent>
12 #include <QEvent>
13 #include <QDir>
14 #include <QTextCodec>
15 #include <QApplication>
16 #include <QSurfaceFormat>
17 #include <QTimer>
18 #ifdef Q_OS_MAC
19 #include <QProcessEnvironment>
20 #endif
21 
22 #ifdef Q_OS_ANDROID
23 #include <QtAndroidExtras>
24 #endif
25 
26 #include "previewgeneratorqueue.h"
27 #include "referencecounter.h"
28 #include "mythmiscutil.h"
29 #include "mythconfig.h"
30 #include "mythcdrom.h"
31 #include "mythsystemlegacy.h"
32 #include "tv.h"
33 #include "proglist.h"
34 #include "prevreclist.h"
35 #include "progfind.h"
36 #include "scheduleeditor.h"
37 #include "manualschedule.h"
38 #include "playbackbox.h"
39 #include "themechooser.h"
40 #include "setupwizard_general.h"
41 #include "customedit.h"
42 #include "viewscheduled.h"
43 #include "programrecpriority.h"
44 #include "channelrecpriority.h"
45 #include "custompriority.h"
46 #include "audiooutput.h"
47 #include "globalsettings.h"
48 #include "audiogeneralsettings.h"
49 #include "grabbersettings.h"
50 #include "playgroup.h"
51 #include "networkcontrol.h"
52 #include "scheduledrecording.h"
53 #include "mythsystemevent.h"
54 #include "hardwareprofile.h"
55 #include "signalhandling.h"
56 #include "loggingserver.h"
57 
58 #include "compat.h" // For SIG* on MinGW
59 #include "exitcodes.h"
60 #include "exitprompt.h"
61 #include "programinfo.h"
62 #include "mythcontext.h"
63 #include "mythdbcon.h"
64 #include "guidegrid.h"
65 #include "mythplugin.h"
66 #include "remoteutil.h"
67 #include "dbcheck.h"
68 #include "mythmediamonitor.h"
69 #include "statusbox.h"
70 #include "idlescreen.h"
71 #include "lcddevice.h"
72 #include "langsettings.h"
73 #include "mythtranslation.h"
74 #include "commandlineparser.h"
75 #include "tvremoteutil.h"
76 #include "channelutil.h"
77 
78 #include "myththemedmenu.h"
79 #include "mediarenderer.h"
80 #include "mythmainwindow.h"
81 #include "mythcontrols.h"
82 #include "mythuihelper.h"
83 #include "mythdirs.h"
84 #include "mythdb.h"
86 #include "themechooser.h"
87 #include "mythversion.h"
88 #include "taskqueue.h"
89 #include "cleanupguard.h"
90 #include "standardsettings.h"
91 #include "settingshelper.h"
92 
93 // Video
94 #include "cleanup.h"
95 #include "globals.h"
96 #include "videodlg.h"
97 #include "videoglobalsettings.h"
98 #include "videofileassoc.h"
99 #include "videoplayersettings.h"
100 #include "videometadatasettings.h"
101 #include "videolist.h"
102 
103 // Gallery
104 #include "gallerythumbview.h"
105 
106 // DVD & Bluray
107 #include "DVD/dvdringbuffer.h"
108 #include "Bluray/bdringbuffer.h"
109 
110 // AirPlay
111 #ifdef USING_AIRPLAY
112 #include "AirPlay/mythraopdevice.h"
114 #endif
115 
116 #ifdef USING_LIBDNS_SD
117 #include <QScopedPointer>
118 #include "bonjourregister.h"
119 #endif
120 #if CONFIG_SYSTEMD_NOTIFY
121 #include <systemd/sd-daemon.h>
122 #define fe_sd_notify(x) \
123  (void)sd_notify(0, x);
124 #else
125 #define fe_sd_notify(x)
126 #endif
127 
128 static ExitPrompter *g_exitPopup = nullptr;
130 
131 static MediaRenderer *g_pUPnp = nullptr;
132 static MythPluginManager *g_pmanager = nullptr;
133 
135 
136 static void handleExit(bool prompt);
137 static void resetAllKeys(void);
138 void handleSIGUSR1(void);
139 void handleSIGUSR2(void);
140 
141 #if CONFIG_DARWIN
142 static bool gLoaded = false;
143 #endif
144 
145 static const QString _Location = qApp->translate("(Common)",
146  "MythFrontend");
147 
148 namespace
149 {
150  class RunSettingsCompletion : public QObject
151  {
152  Q_OBJECT
153 
154  public:
155  static void Create(bool check)
156  {
157  new RunSettingsCompletion(check);
158  }
159 
160  private:
161  explicit RunSettingsCompletion(bool check)
162  {
163  if (check)
164  {
165  connect(&m_plcc,
166  SIGNAL(SigResultReady(bool, ParentalLevel::Level)),
167  SLOT(OnPasswordResultReady(bool,
170  }
171  else
172  {
173  OnPasswordResultReady(true, ParentalLevel::plHigh);
174  }
175  }
176 
177  ~RunSettingsCompletion() override = default;
178 
179  private slots:
180  void OnPasswordResultReady(bool passwordValid,
181  ParentalLevel::Level newLevel)
182  {
183  (void) newLevel;
184 
185  if (passwordValid)
186  {
188  auto *ssd =
189  new StandardSettingDialog(mainStack, "videogeneralsettings",
190  new VideoGeneralSettings());
191 
192  if (ssd->Create())
193  {
194  mainStack->AddScreen(ssd);
195  }
196  else
197  delete ssd;
198  }
199  else
200  {
201  LOG(VB_GENERAL, LOG_WARNING,
202  "Aggressive Parental Controls Warning: "
203  "invalid password. An attempt to enter a "
204  "MythVideo settings screen was prevented.");
205  }
206 
207  deleteLater();
208  }
209 
210  public:
212  };
213 
214  class BookmarkDialog : MythScreenType
215  {
216  Q_DECLARE_TR_FUNCTIONS(BookmarkDialog)
217 
218  public:
219  BookmarkDialog(ProgramInfo *pginfo, MythScreenStack *parent) :
220  MythScreenType(parent, "bookmarkdialog"),
221  m_pgi(pginfo)
222  {
223  }
224 
225  bool Create() override // MythScreenType
226  {
227  QString msg = tr("DVD/Video contains a bookmark");
228  QString btn0msg = tr("Play from bookmark");
229  QString btn1msg = tr("Play from beginning");
230 
231  auto *popup = new MythDialogBox(msg, GetScreenStack(), "bookmarkdialog");
232  if (!popup->Create())
233  {
234  delete popup;
235  return false;
236  }
237 
238  GetScreenStack()->AddScreen(popup);
239 
240  popup->SetReturnEvent(this, "bookmarkdialog");
241  popup->AddButton(btn0msg);
242  popup->AddButton(btn1msg);
243  return true;
244  }
245 
246  void customEvent(QEvent *event) override // MythUIType
247  {
248  if (event->type() == DialogCompletionEvent::kEventType)
249  {
250  auto *dce = (DialogCompletionEvent*)(event);
251  int buttonnum = dce->GetResult();
252 
253  if (dce->GetId() == "bookmarkdialog")
254  {
255  uint flags = kStartTVNoFlags;
256  if (buttonnum == 1)
257  {
258  flags |= kStartTVIgnoreBookmark;
259  }
260  else if (buttonnum != 0)
261  {
262  delete m_pgi;
263  return;
264  }
265 
266  TV::StartTV(m_pgi, flags);
267 
268  delete m_pgi;
269  }
270  }
271  }
272 
273  private:
274  ProgramInfo* m_pgi {nullptr};
275  };
276 
277  void cleanup()
278  {
279  qApp->processEvents();
281 #ifdef USING_AIRPLAY
284 #endif
285 
286  delete g_exitPopup;
287  g_exitPopup = nullptr;
288 
290 
291  if (g_pUPnp)
292  {
293  // This takes a few seconds, so inform the user:
294  LOG(VB_GENERAL, LOG_INFO, "Shutting down UPnP client...");
295  delete g_pUPnp;
296  g_pUPnp = nullptr;
297  }
298 
299  if (g_pmanager)
300  {
301  delete g_pmanager;
302  g_pmanager = nullptr;
303  }
304 
305  if (g_settingsHelper)
306  {
307  delete g_settingsHelper;
308  g_settingsHelper = nullptr;
309  }
310 
311  delete gContext;
312  gContext = nullptr;
313 
315 
316  delete qApp;
317 
319  }
320 }
321 
322 static void startAppearWiz(void)
323 {
324  int curX = gCoreContext->GetNumSetting("GuiOffsetX", 0);
325  int curY = gCoreContext->GetNumSetting("GuiOffsetY", 0);
326  int curW = gCoreContext->GetNumSetting("GuiWidth", 0);
327  int curH = gCoreContext->GetNumSetting("GuiHeight", 0);
328 
329  bool isWindowed =
330  (gCoreContext->GetNumSetting("RunFrontendInWindow", 0) == 1);
331 
332  bool reload = false;
333 
334  if (isWindowed)
335  ShowOkPopup(qApp->translate("(MythFrontendMain)",
336  "The ScreenSetupWizard cannot be used while "
337  "mythfrontend is operating in windowed mode."));
338  else
339  {
340  auto *wizard = new MythSystemLegacy(
341  GetAppBinDir() + "mythscreenwizard",
342  QStringList(),
344  wizard->Run();
345 
346  if (!wizard->Wait())
347  {
348  // no reported errors, check for changed geometry parameters
349  gCoreContext->ClearSettingsCache("GuiOffsetX");
350  gCoreContext->ClearSettingsCache("GuiOffsetY");
351  gCoreContext->ClearSettingsCache("GuiWidth");
352  gCoreContext->ClearSettingsCache("GuiHeight");
353 
354  if ((curX != gCoreContext->GetNumSetting("GuiOffsetX", 0)) ||
355  (curY != gCoreContext->GetNumSetting("GuiOffsetY", 0)) ||
356  (curW != gCoreContext->GetNumSetting("GuiWidth", 0)) ||
357  (curH != gCoreContext->GetNumSetting("GuiHeight", 0)))
358  reload = true;
359  }
360 
361  delete wizard;
362  wizard = nullptr;
363  }
364 
365  if (reload)
366  GetMythMainWindow()->JumpTo("Reload Theme");
367 }
368 
369 static void startKeysSetup()
370 {
372 
373  auto *mythcontrols = new MythControls(mainStack, "mythcontrols");
374 
375  if (mythcontrols->Create())
376  mainStack->AddScreen(mythcontrols);
377  else
378  delete mythcontrols;
379 }
380 
381 static void startGuide(void)
382 {
383  uint chanid = 0;
384  QString channum = gCoreContext->GetSetting("DefaultTVChannel");
385  QDateTime startTime;
386  GuideGrid::RunProgramGuide(chanid, channum, startTime, nullptr, false, true, -2);
387 }
388 
389 static void startFinder(void)
390 {
392 }
393 
394 static void startSearchTitle(void)
395 {
397  auto *pl = new ProgLister(mainStack, plTitleSearch, "", "");
398  if (pl->Create())
399  mainStack->AddScreen(pl);
400  else
401  delete pl;
402 }
403 
404 static void startSearchKeyword(void)
405 {
407  auto *pl = new ProgLister(mainStack, plKeywordSearch, "", "");
408  if (pl->Create())
409  mainStack->AddScreen(pl);
410  else
411  delete pl;
412 }
413 
414 static void startSearchPeople(void)
415 {
417  auto *pl = new ProgLister(mainStack, plPeopleSearch, "", "");
418  if (pl->Create())
419  mainStack->AddScreen(pl);
420  else
421  delete pl;
422 }
423 
424 static void startSearchPower(void)
425 {
427  auto *pl = new ProgLister(mainStack, plPowerSearch, "", "");
428  if (pl->Create())
429  mainStack->AddScreen(pl);
430  else
431  delete pl;
432 }
433 
434 static void startSearchStored(void)
435 {
437  auto *pl = new ProgLister(mainStack, plStoredSearch, "", "");
438  if (pl->Create())
439  mainStack->AddScreen(pl);
440  else
441  delete pl;
442 }
443 
444 static void startSearchChannel(void)
445 {
447  auto *pl = new ProgLister(mainStack, plChannel, "", "");
448  if (pl->Create())
449  mainStack->AddScreen(pl);
450  else
451  delete pl;
452 }
453 
454 static void startSearchCategory(void)
455 {
457  auto *pl = new ProgLister(mainStack, plCategory, "", "");
458  if (pl->Create())
459  mainStack->AddScreen(pl);
460  else
461  delete pl;
462 }
463 
464 static void startSearchMovie(void)
465 {
467  auto *pl = new ProgLister(mainStack, plMovies, "", "");
468  if (pl->Create())
469  mainStack->AddScreen(pl);
470  else
471  delete pl;
472 }
473 
474 static void startSearchNew(void)
475 {
477  auto *pl = new ProgLister(mainStack, plNewListings, "", "");
478  if (pl->Create())
479  mainStack->AddScreen(pl);
480  else
481  delete pl;
482 }
483 
484 static void startSearchTime(void)
485 {
487  auto *pl = new ProgLister(mainStack, plTime, "", "");
488  if (pl->Create())
489  mainStack->AddScreen(pl);
490  else
491  delete pl;
492 }
493 
494 static void startManaged(void)
495 {
497 
498  auto *viewsched = new ViewScheduled(mainStack);
499 
500  if (viewsched->Create())
501  mainStack->AddScreen(viewsched);
502  else
503  delete viewsched;
504 }
505 
506 static void startManageRecordingRules(void)
507 {
509 
510  auto *progRecPrior = new ProgramRecPriority(mainStack, "ManageRecRules");
511 
512  if (progRecPrior->Create())
513  mainStack->AddScreen(progRecPrior);
514  else
515  delete progRecPrior;
516 }
517 
518 static void startChannelRecPriorities(void)
519 {
521 
522  auto *chanRecPrior = new ChannelRecPriority(mainStack);
523 
524  if (chanRecPrior->Create())
525  mainStack->AddScreen(chanRecPrior);
526  else
527  delete chanRecPrior;
528 }
529 
530 static void startCustomPriority(void)
531 {
533 
534  auto *custom = new CustomPriority(mainStack);
535 
536  if (custom->Create())
537  mainStack->AddScreen(custom);
538  else
539  delete custom;
540 }
541 
542 static void startPlaybackWithGroup(const QString& recGroup = "")
543 {
545 
546  auto *pbb = new PlaybackBox(mainStack, "playbackbox");
547 
548  if (pbb->Create())
549  {
550  if (!recGroup.isEmpty())
551  pbb->setInitialRecGroup(recGroup);
552 
553  mainStack->AddScreen(pbb);
554  }
555  else
556  delete pbb;
557 }
558 
559 static void startPlayback(void)
560 {
562 }
563 
564 static void startPrevious(void)
565 {
567  auto *pl = new PrevRecordedList(mainStack);
568  if (pl->Create())
569  mainStack->AddScreen(pl);
570  else
571  delete pl;
572 }
573 
574 static void startPreviousOld(void)
575 {
577  auto *pl = new ProgLister(mainStack);
578  if (pl->Create())
579  mainStack->AddScreen(pl);
580  else
581  delete pl;
582 }
583 
584 static void startCustomEdit(void)
585 {
587  auto *custom = new CustomEdit(mainStack);
588 
589  if (custom->Create())
590  mainStack->AddScreen(custom);
591  else
592  delete custom;
593 }
594 
595 static void startManualSchedule(void)
596 {
598 
599  auto *mansched= new ManualSchedule(mainStack);
600 
601  if (mansched->Create())
602  mainStack->AddScreen(mansched);
603  else
604  delete mansched;
605 }
606 
607 static bool isLiveTVAvailable(void)
608 {
609  if (RemoteGetFreeRecorderCount() > 0)
610  return true;
611 
612  QString msg = qApp->translate("(Common)", "All tuners are currently busy.");
613 
614  if (TV::ConfiguredTunerCards() < 1)
615  msg = qApp->translate("(Common)", "There are no configured tuners.");
616 
617  ShowOkPopup(msg);
618  return false;
619 }
620 
621 static void startTVNormal(void)
622 {
623  if (!isLiveTVAvailable())
624  return;
625 
626  // Get the default channel keys (callsign(0) and channum(1)) and
627  // use them to generate the ordered list of channels.
628  QStringList keylist = gCoreContext->GetSettingOnHost(
629  "DefaultChanKeys", gCoreContext->GetHostName()).split("[]:[]");
630  while (keylist.size() < 2)
631  keylist << "";
632  uint dummy = 0;
634  0, // startIndex
635  0, // count
636  dummy, // totalAvailable
637  true, // ignoreHidden
640  0, // sourceID
641  0, // channelGroupID
642  true, // liveTVOnly
643  keylist[0], // callsign
644  keylist[1]); // channum
645 
646  TV::StartTV(nullptr, kStartTVNoFlags, livetvchannels);
647 }
648 
649 static void showStatus(void)
650 {
652 
653  auto *statusbox = new StatusBox(mainStack);
654 
655  if (statusbox->Create())
656  mainStack->AddScreen(statusbox);
657  else
658  delete statusbox;
659 }
660 
661 
662 static void standbyScreen(void)
663 {
665 
666  auto *idlescreen = new IdleScreen(mainStack);
667 
668  if (idlescreen->Create())
669  mainStack->AddScreen(idlescreen);
670  else
671  delete idlescreen;
672 }
673 
674 static void RunVideoScreen(VideoDialog::DialogType type, bool fromJump = false)
675 {
676  QString message = qApp->translate("(MythFrontendMain)",
677  "Loading videos ...");
678 
679  MythScreenStack *popupStack =
680  GetMythMainWindow()->GetStack("popup stack");
681 
682  auto *busyPopup = new MythUIBusyDialog(message, popupStack,
683  "mythvideobusydialog");
684 
685  if (busyPopup->Create())
686  popupStack->AddScreen(busyPopup, false);
687 
689 
690  VideoDialog::VideoListPtr video_list;
691  if (fromJump)
692  {
695  if (!saved.isNull())
696  {
697  video_list = saved->GetSaved();
698  LOG(VB_GENERAL, LOG_INFO,
699  QString("Reusing saved video list because MythVideo was resumed"
700  " within %1ms").arg(VideoListDeathDelay::kDelayTimeMS));
701  }
702  }
703 
704  VideoDialog::BrowseType browse = static_cast<VideoDialog::BrowseType>(
705  gCoreContext->GetNumSetting("mythvideo.db_group_type",
707 
708  if (!video_list)
709  video_list = new VideoList;
710 
711  auto *mythvideo =
712  new VideoDialog(mainStack, "mythvideo", video_list, type, browse);
713 
714  if (mythvideo->Create())
715  {
716  busyPopup->Close();
717  mainStack->AddScreen(mythvideo);
718  }
719  else
720  busyPopup->Close();
721 }
722 
728 
729 static void RunGallery()
730 {
732  auto *galleryView = new GalleryThumbView(mainStack, "galleryview");
733  if (galleryView->Create())
734  {
735  mainStack->AddScreen(galleryView);
736  galleryView->Start();
737  }
738  else
739  {
740  delete galleryView;
741  }
742 }
743 
744 static void playDisc()
745 {
746  //
747  // Get the command string to play a DVD
748  //
749 
750  bool isBD = false;
751 
752  QString command_string =
753  gCoreContext->GetSetting("mythdvd.DVDPlayerCommand");
754  QString bluray_mountpoint =
755  gCoreContext->GetSetting("BluRayMountpoint", "/media/cdrom");
756  QDir bdtest(bluray_mountpoint + "/BDMV");
757 
758  if (bdtest.exists() || MythCDROM::inspectImage(bluray_mountpoint) == MythCDROM::kBluray)
759  isBD = true;
760 
761  if (isBD)
762  {
763  GetMythUI()->AddCurrentLocation("playdisc");
764 
765  QString filename = QString("bd:/%1").arg(bluray_mountpoint);
766 
767  GetMythMainWindow()->HandleMedia("Internal", filename, "", "", "", "",
768  0, 0, "", 0, "", "", true);
769 
771  }
772  else
773  {
774  QString dvd_device = MediaMonitor::defaultDVDdevice();
775 
776  if (dvd_device.isEmpty())
777  return; // User cancelled in the Popup
778 
779  GetMythUI()->AddCurrentLocation("playdisc");
780 
781  if ((command_string.indexOf("internal", 0, Qt::CaseInsensitive) > -1) ||
782  (command_string.length() < 1))
783  {
784 #ifdef Q_OS_MAC
785  // Convert a BSD 'leaf' name into a raw device path
786  QString filename = "dvd://dev/r"; // e.g. 'dvd://dev/rdisk2'
787 #elif _WIN32
788  QString filename = "dvd:"; // e.g. 'dvd:E\\'
789 #else
790  QString filename = "dvd:/"; // e.g. 'dvd://dev/sda'
791 #endif
792  filename += dvd_device;
793 
794  command_string = "Internal";
795  GetMythMainWindow()->HandleMedia(command_string, filename, "", "",
796  "", "", 0, 0, "", 0, "", "", true);
798 
799  return;
800  }
801 
802  if (command_string.contains("%d"))
803  {
804  //
805  // Need to do device substitution
806  //
807  command_string =
808  command_string.replace(QRegExp("%d"), dvd_device);
809  }
812  myth_system(command_string);
815  if (GetMythMainWindow())
816  {
817  GetMythMainWindow()->raise();
818  GetMythMainWindow()->activateWindow();
819  }
821  }
822 }
823 
828 {
829  if (!dvd)
830  return;
831 
832  if (!dvd->isUsable()) // This isn't infallible, on some drives both a mount and libudf fail
833  return;
834 
835  switch (gCoreContext->GetNumSetting("DVDOnInsertDVD", 1))
836  {
837  case 0 : // Do nothing
838  case 1 : // Display menu (mythdvd)*/
839  break;
840  case 2 : // play DVD or Blu-ray
841  playDisc();
842  break;
843  default:
844  LOG(VB_GENERAL, LOG_ERR,
845  "mythdvd main.o: handleMedia() does not know what to do");
846  }
847 }
848 
850 {
851  // Only handle events for media that are newly mounted
852  if (!dev || (dev->getStatus() != MEDIASTAT_MOUNTED
853  && dev->getStatus() != MEDIASTAT_USEABLE))
854  return;
855 
856  // Check if gallery is already running
857  QVector<MythScreenType*> screens;
859 
860  QVector<MythScreenType*>::const_iterator it = screens.begin();
861  QVector<MythScreenType*>::const_iterator itend = screens.end();
862 
863  for (; it != itend; ++it)
864  {
865  if (dynamic_cast<GalleryThumbView*>(*it))
866  {
867  // Running gallery will receive this event later
868  LOG(VB_MEDIA, LOG_INFO, "Main: Ignoring new gallery media - already running");
869  return;
870  }
871  }
872 
873  if (gCoreContext->GetBoolSetting("GalleryAutoLoad", false))
874  {
875  LOG(VB_GUI, LOG_INFO, "Main: Autostarting Gallery for new media");
877  }
878  else
879  LOG(VB_MEDIA, LOG_INFO, "Main: Ignoring new gallery media - autorun not set");
880 }
881 
882 static void TVMenuCallback(void *data, QString &selection)
883 {
884  (void)data;
885  QString sel = selection.toLower();
886 
887  if (sel.startsWith("settings ") || sel == "video_settings_general")
888  {
889  if (!g_settingsHelper)
891 
893  }
894 
895  if (sel == "tv_watch_live")
896  startTVNormal();
897  else if (sel.startsWith("tv_watch_recording"))
898  {
899  // use selection here because its case is untouched
900  if ((selection.length() > 19) && (selection.mid(18, 1) == " "))
901  startPlaybackWithGroup(selection.mid(19));
902  else
903  startPlayback();
904  }
905  else if (sel == "tv_schedule")
906  startGuide();
907  else if (sel == "tv_manualschedule")
909  else if (sel == "tv_custom_record")
910  startCustomEdit();
911  else if (sel == "tv_fix_conflicts")
912  startManaged();
913  else if (sel == "tv_manage_recording_rules")
915  else if (sel == "tv_progfind")
916  startFinder();
917  else if (sel == "tv_search_title")
919  else if (sel == "tv_search_keyword")
921  else if (sel == "tv_search_people")
923  else if (sel == "tv_search_power")
925  else if (sel == "tv_search_stored")
927  else if (sel == "tv_search_channel")
929  else if (sel == "tv_search_category")
931  else if (sel == "tv_search_movie")
933  else if (sel == "tv_search_new")
934  startSearchNew();
935  else if (sel == "tv_search_time")
936  startSearchTime();
937  else if (sel == "tv_previous")
938  startPrevious();
939  else if (sel == "tv_previous_old")
941  else if (sel == "settings appearance")
942  {
944  auto *ssd = new StandardSettingDialog(mainStack, "videogeneralsettings",
945  new AppearanceSettings());
946 
947  if (ssd->Create())
948  {
949  mainStack->AddScreen(ssd);
950  }
951  else
952  delete ssd;
953  }
954  else if (sel == "settings themechooser")
955  {
957  auto *tp = new ThemeChooser(mainStack);
958 
959  if (tp->Create())
960  mainStack->AddScreen(tp);
961  else
962  delete tp;
963  }
964  else if (sel == "settings setupwizard")
965  {
967  auto *sw = new GeneralSetupWizard(mainStack, "setupwizard");
968 
969  if (sw->Create())
970  mainStack->AddScreen(sw);
971  else
972  delete sw;
973  }
974  else if (sel == "settings grabbers")
975  {
977  auto *gs = new GrabberSettings(mainStack, "grabbersettings");
978 
979  if (gs->Create())
980  mainStack->AddScreen(gs);
981  else
982  delete gs;
983  }
984  else if (sel == "screensetupwizard")
985  {
986  startAppearWiz();
987  }
988  else if (sel == "setup_keys")
989  {
990  startKeysSetup();
991  }
992  else if (sel == "settings playgroup")
993  {
995  auto *ssd = new StandardSettingDialog(mainStack, "playbackgroupsetting",
996  new PlayGroupEditor());
997 
998  if (ssd->Create())
999  {
1000  mainStack->AddScreen(ssd);
1001  }
1002  else
1003  delete ssd;
1004  }
1005  else if (sel == "settings general")
1006  {
1008  auto *ssd = new StandardSettingDialog(mainStack, "videogeneralsettings",
1009  new GeneralSettings());
1010 
1011  if (ssd->Create())
1012  {
1013  mainStack->AddScreen(ssd);
1014  }
1015  else
1016  delete ssd;
1017  }
1018  else if (sel == "settings audiogeneral")
1019  {
1021  StandardSettingDialog *ssd =
1022  new AudioConfigScreen(mainStack, "audiogeneralsettings",
1023  new AudioConfigSettings());
1024 
1025  if (ssd->Create())
1026  {
1027  mainStack->AddScreen(ssd);
1028  }
1029  else
1030  delete ssd;
1031  }
1032  else if (sel == "settings maingeneral")
1033  {
1035  auto *ssd = new StandardSettingDialog(mainStack, "maingeneralsettings",
1036  new MainGeneralSettings());
1037 
1038  if (ssd->Create())
1039  {
1040  mainStack->AddScreen(ssd);
1041  }
1042  else
1043  delete ssd;
1044  }
1045  else if (sel == "settings playback")
1046  {
1048  StandardSettingDialog *ssd =
1049  new PlaybackSettingsDialog(mainStack);
1050 
1051  if (ssd->Create())
1052  {
1053  mainStack->AddScreen(ssd);
1054  }
1055  else
1056  delete ssd;
1057  }
1058  else if (sel == "settings osd")
1059  {
1061  auto *ssd = new StandardSettingDialog(mainStack, "osdsettings",
1062  new OSDSettings());
1063 
1064  if (ssd->Create())
1065  {
1066  mainStack->AddScreen(ssd);
1067  }
1068  else
1069  delete ssd;
1070  }
1071  else if (sel == "settings epg")
1072  {
1074  auto *ssd = new StandardSettingDialog(mainStack, "epgsettings",
1075  new EPGSettings());
1076 
1077  if (ssd->Create())
1078  {
1079  mainStack->AddScreen(ssd);
1080  }
1081  else
1082  delete ssd;
1083  }
1084  else if (sel == "settings channelgroups")
1085  {
1087  auto *ssd = new StandardSettingDialog(mainStack, "channelgroupssettings",
1088  new ChannelGroupsSetting());
1089 
1090  if (ssd->Create())
1091  {
1092  mainStack->AddScreen(ssd);
1093  }
1094  else
1095  delete ssd;
1096  }
1097  else if (sel == "settings generalrecpriorities")
1098  {
1100  auto *ssd = new StandardSettingDialog(mainStack,
1101  "generalrecprioritiessettings",
1103 
1104  if (ssd->Create())
1105  {
1106  mainStack->AddScreen(ssd);
1107  }
1108  else
1109  delete ssd;
1110  }
1111  else if (sel == "settings channelrecpriorities")
1112  {
1114  }
1115  else if (sel == "settings custompriority")
1116  {
1118  }
1119  else if (sel == "system_events")
1120  {
1122 
1123  auto *msee = new MythSystemEventEditor(mainStack, "System Event Editor");
1124 
1125  if (msee->Create())
1126  mainStack->AddScreen(msee);
1127  else
1128  delete msee;
1129  }
1130  else if (sel == "video_settings_general")
1131  {
1132  RunSettingsCompletion::Create(gCoreContext->
1133  GetBoolSetting("VideoAggressivePC", false));
1134  }
1135  else if (sel == "video_settings_player")
1136  {
1138 
1139  auto *ps = new PlayerSettings(mainStack, "player settings");
1140 
1141  if (ps->Create())
1142  mainStack->AddScreen(ps);
1143  else
1144  delete ps;
1145  }
1146  else if (sel == "video_settings_metadata")
1147  {
1149 
1150  auto *ms = new MetadataSettings(mainStack, "metadata settings");
1151 
1152  if (ms->Create())
1153  mainStack->AddScreen(ms);
1154  else
1155  delete ms;
1156  }
1157  else if (sel == "video_settings_associations")
1158  {
1160 
1161  auto *fa = new FileAssocDialog(mainStack, "fa dialog");
1162 
1163  if (fa->Create())
1164  mainStack->AddScreen(fa);
1165  }
1166  else if (sel == "manager")
1168  else if (sel == "browser")
1170  else if (sel == "listing")
1172  else if (sel == "gallery")
1174  else if (sel == "disc_play")
1175  {
1176  playDisc();
1177  }
1178  else if (sel == "tv_status")
1179  showStatus();
1180  else if (sel == "exiting_app_prompt")
1181  handleExit(true);
1182  else if (sel == "exiting_app")
1183  handleExit(false);
1184  else if (sel == "standby_mode")
1185  standbyScreen();
1186  else if (sel == "exiting_menu")
1187  {
1188  //ignore
1189  }
1190  else
1191  LOG(VB_GENERAL, LOG_ERR, "Unknown menu action: " + selection);
1192 
1193  if (sel.startsWith("settings ") || sel == "video_settings_general")
1194  {
1195  if (g_settingsHelper)
1196  {
1197  qApp->connect(GetMythMainWindow()->GetMainStack()->GetTopScreen(),
1198  SIGNAL(Exiting()),
1200  SLOT(RunEpilog()));
1201  }
1202  }
1203 }
1204 
1205 static void handleExit(bool prompt)
1206 {
1207  if (prompt)
1208  {
1209  if (!g_exitPopup)
1210  g_exitPopup = new ExitPrompter();
1211 
1213  }
1214  else
1215  qApp->quit();
1216 }
1217 
1218 static bool RunMenu(const QString& themedir, const QString& themename)
1219 {
1220  QByteArray tmp = themedir.toLocal8Bit();
1221  g_menu = new MythThemedMenu(QString(tmp.constData()), "mainmenu.xml",
1222  GetMythMainWindow()->GetMainStack(), "mainmenu");
1223 
1224  if (g_menu->foundTheme())
1225  {
1226  LOG(VB_GENERAL, LOG_NOTICE, QString("Found mainmenu.xml for theme '%1'")
1227  .arg(themename));
1230  return true;
1231  }
1232 
1233  LOG(VB_GENERAL, LOG_ERR,
1234  QString("Couldn't find mainmenu.xml for theme '%1'") .arg(themename));
1235  delete g_menu;
1236  g_menu = nullptr;
1237 
1238  return false;
1239 }
1240 
1241 // If any settings are missing from the database, this will write
1242 // the default values
1243 static void WriteDefaults()
1244 {
1245  PlaybackSettings ps;
1246  ps.Load();
1247  ps.Save();
1248  OSDSettings os;
1249  os.Load();
1250  os.Save();
1251  GeneralSettings gs;
1252  gs.Load();
1253  gs.Save();
1254  EPGSettings es;
1255  es.Load();
1256  es.Save();
1257  AppearanceSettings as;
1258  as.Load();
1259  as.Save();
1260  MainGeneralSettings mgs;
1261  mgs.Load();
1262  mgs.Save();
1264  grs.Load();
1265  grs.Save();
1267  vgs.Load();
1268  vgs.Save();
1269  //TODo Playback group not loaded?
1270  //TODo Channel group not loaded?
1271 }
1272 
1273 static int internal_play_media(const QString &mrl, const QString &plot,
1274  const QString &title, const QString &subtitle,
1275  const QString &director, int season, int episode,
1276  const QString &inetref, int lenMins, const QString &year,
1277  const QString &id, const bool useBookmark)
1278 {
1279  int res = -1;
1280 
1281  QFile checkFile(mrl);
1282  if ((!checkFile.exists() && !mrl.startsWith("dvd:")
1283  && !mrl.startsWith("bd:")
1284  && !mrl.startsWith("myth:")
1285  && !mrl.startsWith("http://")
1286  && !mrl.startsWith("https://")))
1287  {
1288  QString errorText = qApp->translate("(MythFrontendMain)",
1289  "Failed to open \n '%1' in %2 \n"
1290  "Check if the video exists")
1291  .arg(mrl.section('/', -1))
1292  .arg(mrl.section('/', 0, -2));
1293 
1294  ShowOkPopup(errorText);
1295  return res;
1296  }
1297 
1298  auto *pginfo = new ProgramInfo(
1299  mrl, plot, title, QString(), subtitle, QString(),
1300  director, season, episode, inetref, lenMins,
1301  (year.toUInt()) ? year.toUInt() : 1900, id);
1302 
1303  pginfo->SetProgramInfoType(pginfo->DiscoverProgramInfoType());
1304 
1305  bool bookmarkPresent = false;
1306 
1307  if (pginfo->IsVideoDVD())
1308  {
1309  auto *dvd = new DVDInfo(pginfo->GetPlaybackURL());
1310  if (dvd->IsValid())
1311  {
1312  QString name;
1313  QString serialid;
1314  if (dvd->GetNameAndSerialNum(name, serialid))
1315  {
1316  QStringList fields = pginfo->QueryDVDBookmark(serialid);
1317  bookmarkPresent = (fields.count() > 0);
1318  }
1319  }
1320  else
1321  {
1322  ShowNotificationError(qApp->translate("(MythFrontendMain)",
1323  "DVD Failure"),
1324  _Location,
1325  dvd->GetLastError());
1326  delete dvd;
1327  delete pginfo;
1328  return res;
1329  }
1330  delete dvd;
1331  }
1332  else if (pginfo->IsVideoBD())
1333  {
1334  BDInfo bd(pginfo->GetPlaybackURL());
1335  if (bd.IsValid())
1336  {
1337  QString name;
1338  QString serialid;
1339  if (bd.GetNameAndSerialNum(name, serialid))
1340  {
1341  QStringList fields = pginfo->QueryBDBookmark(serialid);
1342  bookmarkPresent = (fields.count() > 0);
1343  }
1344  }
1345  else
1346  {
1347  // ToDo: Change string to "BD Failure" after 0.28 is released
1348  ShowNotificationError(qApp->translate("(MythFrontendMain)",
1349  "DVD Failure"),
1350  _Location,
1351  bd.GetLastError());
1352  delete pginfo;
1353  return res;
1354  }
1355  }
1356  else if (pginfo->IsVideo())
1357  bookmarkPresent = (pginfo->QueryBookmark() > 0);
1358 
1359  if (useBookmark && bookmarkPresent)
1360  {
1362  auto *bookmarkdialog = new BookmarkDialog(pginfo, mainStack);
1363  if (!bookmarkdialog->Create())
1364  {
1365  delete bookmarkdialog;
1366  delete pginfo;
1367  return res;
1368  }
1369  }
1370  else
1371  {
1373 
1374  res = 0;
1375 
1376  delete pginfo;
1377  }
1378 
1379  return res;
1380 }
1381 
1382 static void gotoMainMenu(void)
1383 {
1384  // Reset the selected button to the first item.
1385  auto *lmenu = dynamic_cast<MythThemedMenuState *>
1386  (GetMythMainWindow()->GetMainStack()->GetTopScreen());
1387  if (lmenu)
1388  lmenu->m_buttonList->SetItemCurrent(0);
1389 }
1390 
1391 // If the theme specified in the DB is somehow broken, try a standard one:
1392 //
1393 static bool resetTheme(QString themedir, const QString &badtheme)
1394 {
1395  QString themename = DEFAULT_UI_THEME;
1396 
1397  if (badtheme == DEFAULT_UI_THEME)
1398  themename = FALLBACK_UI_THEME;
1399 
1400  LOG(VB_GENERAL, LOG_WARNING,
1401  QString("Overriding broken theme '%1' with '%2'")
1402  .arg(badtheme).arg(themename));
1403 
1404  gCoreContext->OverrideSettingForSession("Theme", themename);
1405  themedir = GetMythUI()->FindThemeDir(themename);
1406 
1409  GetMythUI()->LoadQtConfig();
1410 #if CONFIG_DARWIN
1412 #else
1413  GetMythMainWindow()->Init();
1414 #endif
1415 
1417 
1418  return RunMenu(themedir, themename);
1419 }
1420 
1421 static int reloadTheme(void)
1422 {
1423 
1424 #ifdef Q_OS_ANDROID
1425 
1426  // jni code to launch the application again
1427  // reinitializing the main windows causes a segfault
1428  // with android
1429 
1430  auto activity = QtAndroid::androidActivity();
1431  auto packageManager = activity.callObjectMethod
1432  ( "getPackageManager",
1433  "()Landroid/content/pm/PackageManager;" );
1434 
1435  auto activityIntent = packageManager.callObjectMethod
1436  ( "getLaunchIntentForPackage",
1437  "(Ljava/lang/String;)Landroid/content/Intent;",
1438  activity.callObjectMethod("getPackageName",
1439  "()Ljava/lang/String;").object() );
1440 
1441  auto pendingIntent = QAndroidJniObject::callStaticObjectMethod
1442  ( "android/app/PendingIntent",
1443  "getActivity",
1444  "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;",
1445  activity.object(),
1446  0,
1447  activityIntent.object(),
1448  QAndroidJniObject::getStaticField<jint>("android/content/Intent",
1449  "FLAG_ACTIVITY_CLEAR_TOP") );
1450 
1451  auto alarmManager = activity.callObjectMethod
1452  ( "getSystemService",
1453  "(Ljava/lang/String;)Ljava/lang/Object;",
1454  QAndroidJniObject::getStaticObjectField("android/content/Context",
1455  "ALARM_SERVICE",
1456  "Ljava/lang/String;").object() );
1457 
1458  alarmManager.callMethod<void>
1459  ( "set",
1460  "(IJLandroid/app/PendingIntent;)V",
1461  QAndroidJniObject::getStaticField<jint>("android/app/AlarmManager", "RTC"),
1462  jlong(QDateTime::currentMSecsSinceEpoch() + 100),
1463  pendingIntent.object() );
1464 
1465  qApp->quit();
1466  // QString title = QObject::tr("Your change will take effect the next time "
1467  // "mythfrontend is started.");
1468  // MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); MythConfirmationDialog *okPopup =
1469  // new MythConfirmationDialog(popupStack, title, false);
1470  // if (okPopup->Create())
1471  // popupStack->AddScreen(okPopup);
1472  return 0;
1473 #else
1474 
1475  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
1476  QString themedir = GetMythUI()->FindThemeDir(themename);
1477  if (themedir.isEmpty())
1478  {
1479  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
1480  .arg(themename));
1481  return GENERIC_EXIT_NO_THEME;
1482  }
1483 
1486 
1488 
1489  GetMythUI()->LoadQtConfig();
1490 
1491  if (g_menu)
1492  {
1493  g_menu->Close();
1494  }
1495 #if CONFIG_DARWIN
1497 #else
1498  GetMythMainWindow()->Init();
1499 #endif
1500 
1502 
1504 
1505  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
1506  return GENERIC_EXIT_NO_THEME;
1507 
1508  LCD::SetupLCD();
1509  if (LCD *lcd = LCD::Get())
1510  {
1511  lcd->setupLEDs(RemoteGetRecordingMask);
1512  lcd->resetServer();
1513  }
1514 
1515  return 0;
1516 #endif // Q_OS_ANDROID else
1517 }
1518 
1519 static void reloadTheme_void(void)
1520 {
1521  int err = reloadTheme();
1522  if (err)
1523  exit(err);
1524 }
1525 
1526 static void setDebugShowBorders(void)
1527 {
1529  p->SetDebugMode(!p->ShowBorders(), p->ShowTypeNames());
1530 
1533 }
1534 
1535 static void setDebugShowNames(void)
1536 {
1538  p->SetDebugMode(p->ShowBorders(), !p->ShowTypeNames());
1539 
1542 }
1543 
1544 static void InitJumpPoints(void)
1545 {
1546  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Reload Theme"),
1547  "", "", reloadTheme_void);
1548  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Main Menu"),
1549  "", "", gotoMainMenu);
1550  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Guide"),
1551  "", "", startGuide, "GUIDE");
1552  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Finder"),
1553  "", "", startFinder, "FINDER");
1554  //REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Search Listings"),
1555  // "", "", startSearch);
1556  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Manage Recordings / "
1557  "Fix Conflicts"), "", "", startManaged, "VIEWSCHEDULED");
1558  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Manage Recording Rules"),
1559  "", "", startManageRecordingRules);
1560  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Channel Recording "
1561  "Priorities"), "", "", startChannelRecPriorities);
1562  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "TV Recording Playback"),
1563  "", "", startPlayback, "JUMPREC");
1564  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Live TV"),
1565  "", "", startTVNormal);
1566  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Status Screen"),
1567  "", "", showStatus);
1568  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Previously Recorded"),
1569  "", "", startPrevious);
1570 
1571  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Standby Mode"),
1572  "", "", standbyScreen);
1573 
1574  // Video
1575 
1576  REG_JUMP(JUMP_VIDEO_DEFAULT, QT_TRANSLATE_NOOP("MythControls",
1577  "The Video Default View"), "", jumpScreenVideoDefault);
1578  REG_JUMP(JUMP_VIDEO_MANAGER, QT_TRANSLATE_NOOP("MythControls",
1579  "The Video Manager"), "", jumpScreenVideoManager);
1580  REG_JUMP(JUMP_VIDEO_BROWSER, QT_TRANSLATE_NOOP("MythControls",
1581  "The Video Browser"), "", jumpScreenVideoBrowser);
1582  REG_JUMP(JUMP_VIDEO_TREE, QT_TRANSLATE_NOOP("MythControls",
1583  "The Video Listings"), "", jumpScreenVideoTree);
1584  REG_JUMP(JUMP_VIDEO_GALLERY, QT_TRANSLATE_NOOP("MythControls",
1585  "The Video Gallery"), "", jumpScreenVideoGallery);
1586  REG_JUMP("Play Disc", QT_TRANSLATE_NOOP("MythControls",
1587  "Play an Optical Disc"), "", playDisc);
1588 
1589  // Gallery
1590 
1591  REG_JUMP(JUMP_GALLERY_DEFAULT, QT_TRANSLATE_NOOP("MythControls",
1592  "Image Gallery"), "", RunGallery);
1593 
1594  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Borders"),
1595  "", "", setDebugShowBorders, false);
1596  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Names"),
1597  "", "", setDebugShowNames, false);
1598  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Reset All Keys"),
1599  QT_TRANSLATE_NOOP("MythControls", "Reset all keys to defaults"),
1600  "", resetAllKeys, false);
1601 }
1602 
1603 static void ReloadJumpPoints(void)
1604 {
1605  MythMainWindow *mainWindow = GetMythMainWindow();
1606  mainWindow->ClearAllJumps();
1607  InitJumpPoints();
1608 }
1609 
1610 static void InitKeys(void)
1611 {
1612  REG_KEY("Video","PLAYALT", QT_TRANSLATE_NOOP("MythControls",
1613  "Play selected item in alternate player"), "ALT+P");
1614  REG_KEY("Video","FILTER", QT_TRANSLATE_NOOP("MythControls",
1615  "Open video filter dialog"), "F");
1616  REG_KEY("Video","INCPARENT", QT_TRANSLATE_NOOP("MythControls",
1617  "Increase Parental Level"), "],},F11");
1618  REG_KEY("Video","DECPARENT", QT_TRANSLATE_NOOP("MythControls",
1619  "Decrease Parental Level"), "[,{,F10");
1620  REG_KEY("Video","INCSEARCH", QT_TRANSLATE_NOOP("MythControls",
1621  "Show Incremental Search Dialog"), "Ctrl+S");
1622  REG_KEY("Video","DOWNLOADDATA", QT_TRANSLATE_NOOP("MythControls",
1623  "Download metadata for current item"), "W");
1624  REG_KEY("Video","ITEMDETAIL", QT_TRANSLATE_NOOP("MythControls",
1625  "Display Item Detail Popup"), "");
1626 
1627  // Gallery keybindings
1628  REG_KEY("Images", "PLAY", QT_TRANSLATE_NOOP("MythControls",
1629  "Start/Stop Slideshow"), "P");
1630  REG_KEY("Images", "RECURSIVESHOW", QT_TRANSLATE_NOOP("MythControls",
1631  "Start Recursive Slideshow"), "R");
1632  REG_KEY("Images", "ROTRIGHT", QT_TRANSLATE_NOOP("MythControls",
1633  "Rotate image right 90 degrees"), "],3");
1634  REG_KEY("Images", "ROTLEFT", QT_TRANSLATE_NOOP("MythControls",
1635  "Rotate image left 90 degrees"), "[,1");
1636  REG_KEY("Images", "FLIPHORIZONTAL", QT_TRANSLATE_NOOP("MythControls",
1637  "Flip image horizontally"), "");
1638  REG_KEY("Images", "FLIPVERTICAL", QT_TRANSLATE_NOOP("MythControls",
1639  "Flip image vertically"), "");
1640  REG_KEY("Images", "ZOOMOUT", QT_TRANSLATE_NOOP("MythControls",
1641  "Zoom image out"), "7");
1642  REG_KEY("Images", "ZOOMIN", QT_TRANSLATE_NOOP("MythControls",
1643  "Zoom image in"), "9");
1644  REG_KEY("Images", "FULLSIZE", QT_TRANSLATE_NOOP("MythControls",
1645  "Full-size (un-zoom) image"), "0");
1646  REG_KEY("Images", "MARK", QT_TRANSLATE_NOOP("MythControls",
1647  "Mark image"), "T");
1648  REG_KEY("Images", "SCROLLUP", QT_TRANSLATE_NOOP("MythControls",
1649  "Scroll image up"), "2");
1650  REG_KEY("Images", "SCROLLLEFT", QT_TRANSLATE_NOOP("MythControls",
1651  "Scroll image left"), "4");
1652  REG_KEY("Images", "SCROLLRIGHT", QT_TRANSLATE_NOOP("MythControls",
1653  "Scroll image right"), "6");
1654  REG_KEY("Images", "SCROLLDOWN", QT_TRANSLATE_NOOP("MythControls",
1655  "Scroll image down"), "8");
1656  REG_KEY("Images", "RECENTER", QT_TRANSLATE_NOOP("MythControls",
1657  "Recenter image"), "5");
1658  REG_KEY("Images", "COVER", QT_TRANSLATE_NOOP("MythControls",
1659  "Set or clear cover image"), "C");
1660 }
1661 
1662 static void ReloadKeys(void)
1663 {
1664  GetMythMainWindow()->ClearKeyContext("Video");
1665  InitKeys();
1666 
1667  TV::ReloadKeys();
1668 }
1669 
1670 static void SetFuncPtrs(void)
1671 {
1672  TV::SetFuncPtr("playbackbox", (void *)PlaybackBox::RunPlaybackBox);
1673  TV::SetFuncPtr("viewscheduled", (void *)ViewScheduled::RunViewScheduled);
1674  TV::SetFuncPtr("programguide", (void *)GuideGrid::RunProgramGuide);
1675  TV::SetFuncPtr("programfinder", (void *)RunProgramFinder);
1676  TV::SetFuncPtr("scheduleeditor", (void *)ScheduleEditor::RunScheduleEditor);
1677 }
1678 
1682 static void clearAllKeys(void)
1683 {
1684  MSqlQuery query(MSqlQuery::InitCon());
1685 
1686  query.prepare("DELETE FROM keybindings "
1687  "WHERE hostname = :HOSTNAME;");
1688  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1689  if (!query.exec())
1690  MythDB::DBError("Deleting keybindings", query);
1691  query.prepare("DELETE FROM jumppoints "
1692  "WHERE hostname = :HOSTNAME;");
1693  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1694  if (!query.exec())
1695  MythDB::DBError("Deleting jumppoints", query);
1696 }
1697 
1701 static void resetAllKeys(void)
1702 {
1703  clearAllKeys();
1704  // Reload MythMainWindow bindings
1706  // Reload Jump Points
1707  ReloadJumpPoints();
1708  // Reload mythfrontend and TV bindings
1709  ReloadKeys();
1710 }
1711 
1713 {
1714  REG_MEDIAPLAYER("Internal", QT_TRANSLATE_NOOP("MythControls",
1715  "MythTV's native media player."), internal_play_media);
1716  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1717  "MythDVD DVD Media Handler"), "", handleDVDMedia,
1718  MEDIATYPE_DVD, QString());
1719  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1720  "MythImage Media Handler 1/2"), "", handleGalleryMedia,
1721  MEDIATYPE_DATA | MEDIATYPE_MIXED, QString());
1722 
1723  QStringList extensions(ImageAdapterBase::SupportedImages()
1725 
1726  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1727  "MythImage Media Handler 2/2"), "", handleGalleryMedia,
1728  MEDIATYPE_MGALLERY | MEDIATYPE_MVIDEO, extensions.join(","));
1729  return 0;
1730 }
1731 
1732 static void CleanupMyOldInUsePrograms(void)
1733 {
1734  MSqlQuery query(MSqlQuery::InitCon());
1735 
1736  query.prepare("DELETE FROM inuseprograms "
1737  "WHERE hostname = :HOSTNAME and recusage = 'player' ;");
1738  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1739  if (!query.exec())
1740  MythDB::DBError("CleanupMyOldInUsePrograms", query);
1741 }
1742 
1743 static bool WasAutomaticStart(void)
1744 {
1745  bool autoStart = false;
1746 
1747  // Is backend running?
1748  //
1750  {
1751  QDateTime startupTime = QDateTime();
1752 
1753  if( gCoreContext->IsMasterHost() )
1754  {
1755  QString s = gCoreContext->GetSetting("MythShutdownWakeupTime", "");
1756  if (s.length())
1757  startupTime = MythDate::fromString(s);
1758 
1759  // if we don't have a valid startup time assume we were started manually
1760  if (startupTime.isValid())
1761  {
1762  int startupSecs = gCoreContext->GetNumSetting("StartupSecsBeforeRecording");
1763  // If we started within 'StartupSecsBeforeRecording' OR 15 minutes
1764  // of the saved wakeup time assume we either started automatically
1765  // to record, to obtain guide data or or for a
1766  // daily wakeup/shutdown period
1767  if (abs(startupTime.secsTo(MythDate::current())) <
1768  max(startupSecs, 15 * 60))
1769  {
1770  LOG(VB_GENERAL, LOG_INFO,
1771  "Close to auto-start time, AUTO-Startup assumed");
1772 
1773  QString str = gCoreContext->GetSetting("MythFillSuggestedRunTime");
1774  QDateTime guideRunTime = MythDate::fromString(str);
1775  if (guideRunTime.secsTo(MythDate::current()) <
1776  max(startupSecs, 15 * 60))
1777  {
1778  LOG(VB_GENERAL, LOG_INFO,
1779  "Close to MythFillDB suggested run time, AUTO-Startup to fetch guide data?");
1780  }
1781  autoStart = true;
1782  }
1783  else
1784  LOG(VB_GENERAL, LOG_DEBUG,
1785  "NOT close to auto-start time, USER-initiated startup assumed");
1786  }
1787  }
1788  else
1789  {
1790  QString wakeupCmd = gCoreContext->GetSetting("WakeUpCommand");
1791 
1792  // A slave backend that has no wakeup command cannot be woken
1793  // automatically so can be ignored.
1794  if (!wakeupCmd.isEmpty())
1795  {
1796  ProgramList progList;
1797  bool bConflicts = false;
1798  QDateTime nextRecordingStart;
1799 
1800  if (LoadFromScheduler(progList, bConflicts))
1801  {
1802  // Find the first recording to be recorded
1803  // on this machine
1804  QString hostname = gCoreContext->GetHostName();
1805  ProgramList::const_iterator it = progList.begin();
1806  for (; it != progList.end(); ++it)
1807  {
1808  if (((*it)->GetRecordingStatus() == RecStatus::WillRecord ||
1809  (*it)->GetRecordingStatus() == RecStatus::Pending) &&
1810  ((*it)->GetHostname() == hostname) &&
1811  (nextRecordingStart.isNull() ||
1812  nextRecordingStart > (*it)->GetRecordingStartTime()))
1813  {
1814  nextRecordingStart = (*it)->GetRecordingStartTime();
1815  }
1816  }
1817 
1818  if (!nextRecordingStart.isNull() &&
1819  (abs(nextRecordingStart.secsTo(MythDate::current())) < (4 * 60)))
1820  {
1821  LOG(VB_GENERAL, LOG_INFO,
1822  "Close to start time, AUTO-Startup assumed");
1823 
1824  // If we started within 4 minutes of the next recording,
1825  // we almost certainly started automatically.
1826  autoStart = true;
1827  }
1828  else
1829  LOG(VB_GENERAL, LOG_DEBUG,
1830  "NOT close to auto-start time, USER-initiated startup assumed");
1831 
1832  }
1833  }
1834  }
1835  }
1836 
1837  return autoStart;
1838 }
1839 
1840 // from https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=16897
1841 // The old way of revoking root with setuid(getuid())
1842 // causes system hang in certain cases on raspberry pi
1843 
1844 static int revokeRoot (void)
1845 {
1846  if (getuid () == 0 && geteuid () == 0) // Really running as root
1847  return 0;
1848 
1849  if (geteuid () == 0) // Running setuid root
1850  return seteuid (getuid ()) ; // Change effective uid to the uid of the caller
1851  return 0;
1852 }
1853 
1854 
1855 int main(int argc, char **argv)
1856 {
1857  bool bPromptForBackend = false;
1858  bool bBypassAutoDiscovery = false;
1859 
1861  if (!cmdline.Parse(argc, argv))
1862  {
1863  cmdline.PrintHelp();
1865  }
1866 
1867  if (cmdline.toBool("showhelp"))
1868  {
1869  cmdline.PrintHelp();
1870  return GENERIC_EXIT_OK;
1871  }
1872 
1873  if (cmdline.toBool("showversion"))
1874  {
1876  return GENERIC_EXIT_OK;
1877  }
1878 
1879  CleanupGuard callCleanup(cleanup);
1880 
1881  // Set the default surface format. Explicitly required on some platforms.
1882  QSurfaceFormat format;
1883  format.setDepthBufferSize(0);
1884  format.setStencilBufferSize(0);
1885  format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
1886  format.setProfile(QSurfaceFormat::CompatibilityProfile);
1887  format.setSwapInterval(1);
1888  QSurfaceFormat::setDefaultFormat(format);
1889 
1890 #ifdef Q_OS_MAC
1891  // Without this, we can't set focus to any of the CheckBoxSetting, and most
1892  // of the MythPushButton widgets, and they don't use the themed background.
1893  QApplication::setDesktopSettingsAware(false);
1894 #endif
1895 #if defined (Q_OS_LINUX)
1896 #if defined (USING_VAAPI) || defined (USING_MMAL)
1897  // When using VAAPI (linux/desktop only) we want to use EGL to ensure we
1898  // can use zero copy video buffers for the best performance (N.B. not tested
1899  // on AMD desktops). For non-VAAPI users this should make no difference - on NVidia
1900  // installations it has no effect.
1901  // Likewise for MMAL (Raspberry Pi), we want EGL for zero copy direct rendering.
1902  // This is the only way to force Qt to use EGL and must be done before any
1903  // GUI is created.
1904  // If problems are encountered, set the environment variable NO_EGL
1905 
1906  // Disabled this for now as it does actually break NVidia desktops
1907  //if (qgetenv("NO_EGL").isEmpty())
1908  // setenv("QT_XCB_GL_INTEGRATION", "xcb_egl", 0);
1909 
1910  // This makes Xlib calls thread-safe which seems to be required for hardware
1911  // accelerated Flash playback to work without causing mythfrontend to abort.
1912  QApplication::setAttribute(Qt::AA_X11InitThreads);
1913 #endif
1914 #endif
1915 #ifdef Q_OS_ANDROID
1916  //QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
1917 #endif
1918 
1919 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
1920  // Ignore desktop scaling
1921  QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
1922 #endif
1923 
1924  QApplication::setSetuidAllowed(true);
1925  new QApplication(argc, argv);
1926  QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHFRONTEND);
1927 
1928 
1929 #ifdef Q_OS_MAC
1930  QString path = QCoreApplication::applicationDirPath();
1931  setenv("PYTHONPATH",
1932  QString("%1/../Resources/lib/python2.6/site-packages:%2")
1933  .arg(path)
1934  .arg(QProcessEnvironment::systemEnvironment().value("PYTHONPATH"))
1935  .toUtf8().constData(), 1);
1936 #endif
1937 
1938 #ifndef _WIN32
1939  QList<int> signallist;
1940  signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
1941  << SIGILL;
1942 #if ! CONFIG_DARWIN
1943  signallist << SIGRTMIN;
1944 #endif
1945  SignalHandler::Init(signallist);
1948  SignalHandler::SetHandler(SIGHUP, logSigHup);
1949 #endif
1950 
1951  int retval = cmdline.ConfigureLogging();
1952  if (retval != GENERIC_EXIT_OK)
1953  return retval;
1954 
1955  bool ResetSettings = false;
1956 
1957  if (cmdline.toBool("prompt"))
1958  bPromptForBackend = true;
1959  if (cmdline.toBool("noautodiscovery"))
1960  bBypassAutoDiscovery = true;
1961 
1962  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1963  cerr << "Unable to ignore SIGPIPE\n";
1964 
1965  if (!cmdline.toString("display").isEmpty())
1966  {
1968  }
1969 
1970  if (!cmdline.toString("geometry").isEmpty())
1971  {
1973  }
1974 
1975  fe_sd_notify("STATUS=Connecting to database.");
1977  gCoreContext->SetAsFrontend(true);
1978 
1980  if (!gContext->Init(true, bPromptForBackend, bBypassAutoDiscovery))
1981  {
1982  LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
1983  gCoreContext->SetExiting(true);
1985  }
1986 
1988 
1989  if (!GetMythDB()->HaveSchema())
1990  {
1991  if (!InitializeMythSchema())
1992  return GENERIC_EXIT_DB_ERROR;
1993  }
1994 
1995  if (cmdline.toBool("reset"))
1996  ResetSettings = true;
1997 
1998  if (!cmdline.toBool("noupnp"))
1999  {
2000  fe_sd_notify("STATUS=Creating UPnP media renderer");
2001  g_pUPnp = new MediaRenderer();
2002  if (!g_pUPnp->isInitialized())
2003  {
2004  delete g_pUPnp;
2005  g_pUPnp = nullptr;
2006  }
2007  }
2008 
2009  QString fileprefix = GetConfDir();
2010 
2011  QDir dir(fileprefix);
2012  if (!dir.exists())
2013  dir.mkdir(fileprefix);
2014 
2015  if (ResetSettings)
2016  {
2017  AppearanceSettings as;
2018  as.Save();
2019 
2021  gCoreContext->GetDB()->ClearSetting("Language");
2022  gCoreContext->GetDB()->ClearSettingOnHost("Language", nullptr);
2023  gCoreContext->GetDB()->ClearSetting("Country");
2024  gCoreContext->GetDB()->ClearSettingOnHost("Country", nullptr);
2025 
2026  LOG(VB_GENERAL, LOG_NOTICE, "Appearance settings and language have "
2027  "been reset to defaults. You will need to "
2028  "restart the frontend.");
2029  gContext-> saveSettingsCache();
2030  return GENERIC_EXIT_OK;
2031  }
2032 
2033  qApp->setSetuidAllowed(true);
2034 
2035  if (revokeRoot() != 0)
2036  {
2037  LOG(VB_GENERAL, LOG_ERR, "Failed to revokeRoot(), exiting.");
2038  return GENERIC_EXIT_NOT_OK;
2039  }
2040 
2041 #ifdef USING_LIBDNS_SD
2042  // this needs to come after gCoreContext has been initialised
2043  // (for hostname) - hence it is not in MediaRenderer
2044  QScopedPointer<BonjourRegister> bonjour(new BonjourRegister());
2045  if (bonjour.data())
2046  {
2047  fe_sd_notify("STATUS=Registering frontend with bonjour");
2048  QByteArray dummy;
2049  int port = gCoreContext->GetNumSetting("UPnP/MythFrontend/ServicePort", 6547);
2050  QByteArray name("Mythfrontend on ");
2051  name.append(gCoreContext->GetHostName());
2052  bonjour->Register(port, "_mythfrontend._tcp",
2053  name, dummy);
2054  }
2055 #endif
2056 
2057  fe_sd_notify("STATUS=Initializing LCD");
2058  LCD::SetupLCD();
2059  if (LCD *lcd = LCD::Get())
2060  lcd->setupLEDs(RemoteGetRecordingMask);
2061 
2062  fe_sd_notify("STATUS=Loading translation");
2063  MythTranslation::load("mythfrontend");
2064 
2065  fe_sd_notify("STATUS=Loading themes");
2066  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
2067 
2068  QString themedir = GetMythUI()->FindThemeDir(themename);
2069  if (themedir.isEmpty())
2070  {
2071  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
2072  .arg(themename));
2073  return GENERIC_EXIT_NO_THEME;
2074  }
2075 
2076  GetMythUI()->LoadQtConfig();
2077 
2078  themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
2079  themedir = GetMythUI()->FindThemeDir(themename);
2080  if (themedir.isEmpty())
2081  {
2082  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
2083  .arg(themename));
2084  return GENERIC_EXIT_NO_THEME;
2085  }
2086 
2087  MythMainWindow *mainWindow = GetMythMainWindow();
2088 #if CONFIG_DARWIN
2089  mainWindow->Init(QT_PAINTER, false);
2090 #else
2091  mainWindow->Init(QString(), false);
2092 #endif
2093  mainWindow->setWindowTitle(qApp->translate("(MythFrontendMain)",
2094  "MythTV Frontend",
2095  "Main window title"));
2096 
2097 #ifdef USING_AIRPLAY
2098  if (gCoreContext->GetBoolSetting("AirPlayEnabled", true))
2099  {
2100  fe_sd_notify("STATUS=Initializing AirPlay");
2102  if (!gCoreContext->GetBoolSetting("AirPlayAudioOnly", false))
2103  {
2105  }
2106  }
2107 #endif
2108 
2109  // We must reload the translation after a language change and this
2110  // also means clearing the cached/loaded theme strings, so reload the
2111  // theme which also triggers a translation reload
2113  {
2114  if (!reloadTheme())
2115  return GENERIC_EXIT_NO_THEME;
2116  }
2117 
2118  if (!UpgradeTVDatabaseSchema(false, false, true))
2119  {
2120  LOG(VB_GENERAL, LOG_ERR,
2121  "Couldn't upgrade database to new schema, exiting.");
2123  }
2124 
2125  WriteDefaults();
2126 
2127  // Refresh Global/Main Menu keys after DB update in case there was no DB
2128  // when they were written originally
2129  mainWindow->ReloadKeys();
2130 
2131  fe_sd_notify("STATUS=Initializing jump points");
2132  InitJumpPoints();
2133  InitKeys();
2134  TV::InitKeys();
2135  SetFuncPtrs();
2136 
2138 
2140 
2141  setHttpProxy();
2142 
2143  fe_sd_notify("STATUS=Initializing plugins");
2144  g_pmanager = new MythPluginManager();
2146 
2147  fe_sd_notify("STATUS=Initializing media monitor");
2149  if (mon)
2150  {
2151  mon->StartMonitoring();
2152  mainWindow->installEventFilter(mon);
2153  }
2154 
2155  fe_sd_notify("STATUS=Initializing network control");
2156  NetworkControl *networkControl = nullptr;
2157  if (gCoreContext->GetBoolSetting("NetworkControlEnabled", false))
2158  {
2159  int port = gCoreContext->GetNumSetting("NetworkControlPort", 6546);
2160  networkControl = new NetworkControl();
2161  if (!networkControl->listen(port))
2162  LOG(VB_GENERAL, LOG_ERR,
2163  QString("NetworkControl failed to bind to port %1.")
2164  .arg(port));
2165  }
2166 
2167 #if CONFIG_DARWIN
2172  gLoaded = true;
2173 #endif
2174  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
2175  {
2176  return GENERIC_EXIT_NO_THEME;
2177  }
2178  fe_sd_notify("STATUS=Loading theme updates");
2179  ThemeUpdateChecker *themeUpdateChecker = nullptr;
2180  if (gCoreContext->GetBoolSetting("ThemeUpdateNofications", true))
2181  themeUpdateChecker = new ThemeUpdateChecker();
2182 
2184 
2186 
2188  PreviewGenerator::kRemote, 50, 60);
2189 
2190  fe_sd_notify("STATUS=Creating housekeeper");
2191  auto *housekeeping = new HouseKeeper();
2192 #ifdef __linux__
2193  #ifdef CONFIG_BINDINGS_PYTHON
2195  #endif
2196 #endif
2197  housekeeping->Start();
2198 
2199 
2200  if (cmdline.toBool("runplugin"))
2201  {
2202  QStringList plugins = g_pmanager->EnumeratePlugins();
2203 
2204  if (plugins.contains(cmdline.toString("runplugin")))
2205  g_pmanager->run_plugin(cmdline.toString("runplugin"));
2206  else if (plugins.contains("myth" + cmdline.toString("runplugin")))
2207  g_pmanager->run_plugin("myth" + cmdline.toString("runplugin"));
2208  else
2209  {
2210  LOG(VB_GENERAL, LOG_ERR,
2211  QString("Invalid plugin name supplied on command line: '%1'")
2212  .arg(cmdline.toString("runplugin")));
2213  LOG(VB_GENERAL, LOG_ERR,
2214  QString("Available plugins: %1")
2215  .arg(plugins.join(", ")));
2217  }
2218  }
2219  else if (cmdline.toBool("jumppoint"))
2220  {
2222 
2223  if (mmw->DestinationExists(cmdline.toString("jumppoint")))
2224  mmw->JumpTo(cmdline.toString("jumppoint"));
2225  else
2226  {
2227  LOG(VB_GENERAL, LOG_ERR,
2228  QString("Invalid jump point supplied on the command line: %1")
2229  .arg(cmdline.toString("jumppoint")));
2230  LOG(VB_GENERAL, LOG_ERR,
2231  QString("Available jump points: %2")
2232  .arg(mmw->EnumerateDestinations().join(", ")));
2234  }
2235  }
2236 
2237  if (WasAutomaticStart())
2238  {
2239  // We appear to have been started automatically
2240  // so enter standby so that the machine can
2241  // shutdown again as soon as possible if necessary.
2242  standbyScreen();
2243  }
2244 
2245  // Provide systemd ready notification (for type=notify units)
2246  fe_sd_notify("STATUS=");
2247  fe_sd_notify("READY=1");
2248 
2249  int ret = qApp->exec();
2250 
2251  fe_sd_notify("STOPPING=1\nSTATUS=Exiting");
2252  if (ret==0)
2253  gContext-> saveSettingsCache();
2254 
2255  DestroyMythUI();
2257 
2258  delete housekeeping;
2259  delete themeUpdateChecker;
2260  delete sysEventHandler;
2261 
2263 
2264  if (mon)
2265  mon->deleteLater();
2266 
2267  delete networkControl;
2268  return ret;
2269 }
2270 
2271 void handleSIGUSR1(void)
2272 {
2273  LOG(VB_GENERAL, LOG_INFO, "Reloading theme");
2274  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
2276  GetMythMainWindow()->JumpTo("Reload Theme");
2278 }
2279 
2280 void handleSIGUSR2(void)
2281 {
2282  LOG(VB_GENERAL, LOG_INFO, "Restarting LIRC handler");
2284 }
2285 
2286 #include "main.moc"
2287 /* vim: set expandtab tabstop=4 shiftwidth=4: */
#define GENERIC_EXIT_DB_ERROR
Database error.
Definition: exitcodes.h:17
#define REG_JUMP(a, b, c, d)
Screen for managing and configuring keyboard input bindings.
Definition: mythcontrols.h:48
static bool WasAutomaticStart(void)
static void standbyScreen(void)
Startup context for MythTV.
Definition: mythcontext.h:42
static MediaRenderer * g_pUPnp
QStringList EnumeratePlugins(void)
Definition: mythplugin.cpp:238
static void startSearchMovie(void)
void DestroyAllPlugins()
Definition: mythplugin.cpp:225
#define REG_MEDIA_HANDLER(a, b, c, d, e)
QString FindThemeDir(const QString &themename, bool doFallback=true)
Returns the full path to the theme denoted by themename.
const QString JUMP_VIDEO_BROWSER
Definition: globals.cpp:37
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:862
const QString JUMP_VIDEO_DEFAULT
Definition: globals.cpp:40
bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, const bool upgradeIfNoUI, const bool informSystemd)
Called from outside dbcheck.cpp to update the schema.
unsigned int slots[4]
Definition: element.c:38
static ChannelInfoList LoadChannels(uint startIndex, uint count, uint &totalAvailable, bool ignoreHidden=true, OrderBy orderBy=kChanOrderByChanNum, GroupBy groupBy=kChanGroupByChanid, uint sourceID=0, uint channelGroupID=0, bool liveTVOnly=false, const QString &callsign="", const QString &channum="", bool ignoreUntunable=true)
Load channels from database into a list of ChannelInfo objects.
static void startPrevious(void)
static void startPlayback(void)
static QString themedir
Definition: mythdirs.cpp:21
static void gotoMainMenu(void)
Main header for mythcontrols.
void LoadQtConfig(void)
static void startPreviousOld(void)
static void playDisc()
static void setDebugShowBorders(void)
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
Definition: serverpool.cpp:380
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
void RegisterTask(HouseKeeperTask *task)
static void startSearchPower(void)
static VideoListDeathDelayPtr & GetSavedVideoList()
Definition: videodlg.cpp:838
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
static void Cleanup(void)
void setHttpProxy(void)
Get network proxy settings from OS, and use for [Q]Http[Comms].
void SetProgramInfoType(ProgramInfoType t)
Definition: programinfo.h:504
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
int main(int argc, char **argv)
static void startChannelRecPriorities(void)
void SaveSetting(const QString &key, int newValue)
static void reloadTheme_void(void)
static void PrintVersion(void)
Print application version information.
void SetRedraw(void)
Definition: mythuitype.cpp:295
static void startKeysSetup()
static int ConfiguredTunerCards(void)
If any cards are configured, return the number.
Definition: tv_play.cpp:193
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
A screen to create a fully custom recording.
Definition: customedit.h:17
virtual void Load(void)
static void TVMenuCallback(void *data, QString &selection)
Basic menu dialog, message and a list of options.
static void startCustomEdit(void)
void PrintHelp(void) const
Print command line option help.
virtual void StartMonitoring(void)
Start the monitoring thread if needed.
HouseKeeper * housekeeping
static void clearAllKeys(void)
Deletes all key bindings and jump points for this host.
static void SetupLCD(void)
Definition: lcddevice.cpp:72
static void TeardownPreviewGeneratorQueue()
Destroy the singleton queue of preview generators.
int RemoteGetFreeRecorderCount(void)
static bool RunMenu(const QString &themedir, const QString &themename)
MythSystemEventHandler * sysEventHandler
static void Init(QList< int > &signallist, QObject *parent=nullptr)
static void startSearchCategory(void)
static void * RunPlaybackBox(void *player, bool)
MythPainter * GetMythPainter(void)
QString GetSettingOnHost(const QString &key, const QString &host, const QString &defaultval="")
void DestroyMythMainWindow(void)
void setCallback(void(*lcallback)(void *, QString &), void *data)
Set the themed menus callback function and data for that function.
MythScreenStack * GetStack(const QString &stackname)
static bool Create(void)
#define DEFAULT_UI_THEME
Definition: mythuihelper.h:12
void AddCurrentLocation(const QString &location)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythScreenStack * GetMainStack()
static void setDebugShowNames(void)
#define REG_KEY(a, b, c, d)
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:62
static QString defaultDVDdevice()
DVDDeviceLocation, user-selected drive, or /dev/dvd.
static void jumpScreenVideoBrowser()
static guint32 * tmp
Definition: goom_core.c:35
void DestroyMythUI()
#define REG_MEDIAPLAYER(a, b, c)
iterator begin(void)
void Init(const QString &forcedpainter=QString(), bool mayReInit=true)
void ClearKeyContext(const QString &context)
static Type kEventType
Definition: mythdialogbox.h:50
#define seteuid(x)
Definition: compat.h:263
typename List::const_iterator const_iterator
void SendMessage(const QString &message)
static void startSearchTitle(void)
static void SetX11Display(const QString &display)
This needs to be set before MythUIHelper is initialized so that the MythUIHelper::Init() can detect X...
#define OPENGL2_PAINTER
Definition: mythuidefines.h:4
virtual void deleteLater(void)
static LCD * Get(void)
Definition: lcddevice.cpp:65
QString GetConfDir(void)
Definition: mythdirs.cpp:224
static void resetAllKeys(void)
Reset this host's key bindings and jump points to default values.
virtual void Close()
QPointer< class VideoListDeathDelay > VideoListDeathDelayPtr
Definition: videodlg.h:45
void ApplySettingsOverride(void)
Apply all overrides to the global context.
Holds information on recordings and videos.
Definition: programinfo.h:66
static void * RunViewScheduled(void *player, bool)
static int revokeRoot(void)
static void startTVNormal(void)
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
static void jumpScreenVideoDefault()
#define REG_JUMPEX(a, b, c, d, e)
static void startSearchNew(void)
add arguments for MythTV log propagation
Definition: mythsystem.h:50
Thumbnail screen.
const QString JUMP_VIDEO_TREE
Definition: globals.cpp:38
void emitTVPlaybackStopped(void)
static void ReloadKeys(void)
virtual MythScreenType * GetTopScreen(void) const
void SetExiting(bool exiting=true)
Screen for viewing and managing upcoming and conflicted recordings.
Definition: viewscheduled.h:27
static void startSearchPeople(void)
static const QString _Location
void OverrideSettingForSession(const QString &key, const QString &value)
QString GetAppBinDir(void)
Definition: mythdirs.cpp:221
static void RunGallery()
static void jumpScreenVideoManager()
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString GetSetting(const QString &key, const QString &defaultval="")
static bool BackendIsRunning(void)
a backend process is running on this host
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
void GetScreenList(QVector< MythScreenType * > &screens)
void Load(void) override
static MediaMonitor * GetMediaMonitor(void)
View and select installed themes.
Definition: themechooser.h:27
void SetPluginManager(MythPluginManager *pmanager)
static void startSearchChannel(void)
void emitTVPlaybackStarted(void)
static void ParseGeometryOverride(const QString &geometry)
Parse an X11 style command line geometry string.
static void SetFuncPtrs(void)
Manages registered HouseKeeperTasks and queues tasks for operation.
Definition: housekeeper.h:148
static int internal_media_init()
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
void ShowNotificationError(const QString &msg, const QString &from, const QString &detail, const VNMask visibility, const MythNotification::Priority priority)
convenience utility to display error message as notification
#define geteuid()
Definition: compat.h:261
static const int kDelayTimeMS
Definition: videodlg.h:229
static QStringList SupportedVideos()
Return recognised video extensions.
string hostname
Definition: caa.py:17
bool isInitialized()
Definition: upnp.h:120
static void Done(void)
unsigned int uint
Definition: compat.h:140
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:534
void JumpTo(const QString &destination, bool pop=true)
static void SetHandler(int signum, SigHandlerFunc handler)
static void startCustomPriority(void)
static void InitJumpPoints(void)
MythCommFlagCommandLineParser cmdline
static void InitKeys(void)
static bool prompt(bool force=false)
Ask the user for the language to use.
uint myth_system(const QString &command, uint flags, uint timeout)
static void Cleanup(void)
#define SIGUSR1
Definition: compat.h:216
bool IsMasterHost(void)
is this the same host as the master
MythUIHelper * GetMythUI()
void RunProgramFinder(TV *player, bool embedVideo, bool allowEPG)
Definition: progfind.cpp:35
static void PrintDebug(void)
Print out any leaks if that level of debugging is enabled.
static void reload()
Reload all active translators based on the current language setting.
disable MythMessage UDP listener for the duration of application.
Definition: mythsystem.h:48
MythMainWindow * GetMythMainWindow(void)
static bool StartTV(ProgramInfo *tvrec, uint flags, const ChannelInfoList &selection=ChannelInfoList())
returns true if the recording completed when exiting.
Definition: tv_play.cpp:289
static void startManageRecordingRules(void)
const QString JUMP_VIDEO_GALLERY
Definition: globals.cpp:39
static ExitPrompter * g_exitPopup
static void ReloadKeys(void)
Definition: tv_play.cpp:994
virtual void Save(void)
static void startSearchTime(void)
void PauseIdleTimer(bool pause)
int GetNumSetting(const QString &key, int defaultval=0)
#define FALLBACK_UI_THEME
Definition: mythuihelper.h:13
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:806
static void ReloadJumpPoints(void)
const QString JUMP_GALLERY_DEFAULT
Definition: globals.cpp:42
void RunProlog(const QString &settingsPage)
static bool Create(void)
static void jumpScreenVideoGallery()
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
Themed menu class, used for main menus in MythTV frontend.
bool Create(void) override
Reports on various status items.
Definition: statusbox.h:18
QStringList EnumerateDestinations(void) const
#define MYTH_APPNAME_MYTHFRONTEND
static void startSearchStored(void)
bool GetBoolSetting(const QString &key, bool defaultval=false)
const QString JUMP_VIDEO_MANAGER
Definition: globals.cpp:36
bool DestinationExists(const QString &destination) const
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
static void Cleanup(void)
Definition: audiooutput.cpp:51
Screen for managing channel priorities in recording scheduling decisions.
static void RunProgramGuide(uint startChanId, const QString &startChanNum, const QDateTime &startTime, TV *player=nullptr, bool embedVideo=false, bool allowFinder=true, int changrpid=-1)
Definition: guidegrid.cpp:413
#define SIGUSR2
Definition: compat.h:217
QString RemoveCurrentLocation(void)
iterator end(void)
int RemoteGetRecordingMask(void)
Definition: remoteutil.cpp:395
static bool resetTheme(QString themedir, const QString &badtheme)
static MythPluginManager * g_pmanager
bool LoadFromScheduler(AutoDeleteDeque< TYPE * > &destination, bool &hasConflicts, QString altTable="", int recordid=-1)
Definition: programinfo.h:876
#define SIGHUP
Definition: compat.h:213
void SetEffectsEnabled(bool enable)
static void startGuide(void)
void ClearSettingsCache(const QString &myKey=QString(""))
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:16
bool foundTheme(void)
Returns true iff a theme has been found by a previous call to SetMenuTheme().
bool isUsable() const
Is this device "ready", for a plugin to access?
Definition: mythmedia.h:84
static void startManualSchedule(void)
static void startPlaybackWithGroup(const QString &recGroup="")
Definition: lcddevice.h:165
MythDB * GetDB(void)
An editor for MythSystemEvent handler commands.
static void showStatus(void)
static QString cleanup(const QString &str)
static void SetFuncPtr(const char *, void *)
Import pointers to functions used to embed the TV window into other containers e.g.
Definition: tv_play.cpp:488
virtual void Load(void)
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
#define QT_PAINTER
Definition: mythuidefines.h:2
#define REG_JUMPLOC(a, b, c, d, e)
static SettingsHelper * g_settingsHelper
static ImageType inspectImage(const QString &path)
Definition: mythcdrom.cpp:179
#define getuid()
Definition: compat.h:260
#define setenv(x, y, z)
Definition: compat.h:156
bool Init(const bool gui=true, const bool promptForBackend=false, const bool disableAutoDiscovery=false, const bool ignoreDB=false)
Handles incoming MythSystemEvent messages.
static void handleExit(bool prompt)
static int internal_play_media(const QString &mrl, const QString &plot, const QString &title, const QString &subtitle, const QString &director, int season, int episode, const QString &inetref, int lenMins, const QString &year, const QString &id, const bool useBookmark)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:602
#define GENERIC_EXIT_NO_THEME
No Theme available.
Definition: exitcodes.h:14
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:13
#define SIGPIPE
Definition: compat.h:218
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
static void jumpScreenVideoTree()
bool HandleMedia(const QString &handler, const QString &mrl, const QString &plot="", const QString &title="", const QString &subtitle="", const QString &director="", int season=0, int episode=0, const QString &inetref="", int lenMins=120, const QString &year="1895", const QString &id="", bool useBookmarks=false)
Screen in which all other widgets are contained and rendered.
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
Definition: exitcodes.h:15
void ActivateSettingsCache(bool activate=true)
#define GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:11
static void startFinder(void)
static void WriteDefaults()
static void RunVideoScreen(VideoDialog::DialogType type, bool fromJump=false)
static void InitKeys(void)
Definition: tv_play.cpp:503
QString GetHostName(void)
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
static MythThemedMenu * g_menu
static void handleGalleryMedia(MythMediaDevice *dev)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
void SetAsFrontend(bool frontend)
static void * RunScheduleEditor(ProgramInfo *proginfo, void *player=nullptr)
Callback.
void ReinitDone(void)
void ReloadKeys(void)
vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:121
void StartLIRC(void)
Implements Gallery Thumbnail screen.
static QStringList SupportedImages()
Return recognised pictures.
static int reloadTheme(void)
static void startSearchKeyword(void)
bool InitializeMythSchema(void)
command to get the the initial database layout from an empty database:
static void handleDVDMedia(MythMediaDevice *dvd)
static void startManaged(void)
int ConfigureLogging(const QString &mask="general", unsigned int progress=0)
Read in logging options and initialize the logging interface.
MythMediaStatus getStatus() const
Definition: mythmedia.h:70
static void CreatePreviewGeneratorQueue(PreviewGenerator::Mode mode, uint maxAttempts, uint minBlockSeconds)
Create the singleton queue of preview generators.
static void CleanupMyOldInUsePrograms(void)
bool run_plugin(const QString &plugname)
Definition: mythplugin.cpp:164
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16
static void startAppearWiz(void)
static bool isLiveTVAvailable(void)
void Start(void)