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 #include <memory>
7 using namespace std;
8 
9 #include <QFile>
10 #include <QFileInfo>
11 #include <QMap>
12 #include <QKeyEvent>
13 #include <QEvent>
14 #include <QDir>
15 #include <QTextCodec>
16 #include <QApplication>
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/mythdvdbuffer.h"
108 #include "Bluray/mythbdinfo.h"
109 #include "Bluray/mythbdbuffer.h"
110 
111 // AirPlay
112 #ifdef USING_AIRPLAY
113 #include "AirPlay/mythraopdevice.h"
115 #endif
116 
117 #ifdef USING_LIBDNS_SD
118 #include <QScopedPointer>
119 #include "bonjourregister.h"
120 #endif
121 #if CONFIG_SYSTEMD_NOTIFY
122 #include <systemd/sd-daemon.h>
123 #define fe_sd_notify(x) \
124  (void)sd_notify(0, x);
125 #else
126 #define fe_sd_notify(x)
127 #endif
128 
129 static ExitPrompter *g_exitPopup = nullptr;
131 
132 static MediaRenderer *g_pUPnp = nullptr;
133 static MythPluginManager *g_pmanager = nullptr;
134 
136 
137 static void handleExit(bool prompt);
138 static void resetAllKeys(void);
139 void handleSIGUSR1(void);
140 void handleSIGUSR2(void);
141 
142 #if CONFIG_DARWIN
143 static bool gLoaded = false;
144 #endif
145 
146 static const QString sLocation = QCoreApplication::translate("(Common)",
147  "MythFrontend");
148 
149 namespace
150 {
151  class RunSettingsCompletion : public QObject
152  {
153  Q_OBJECT
154 
155  public:
156  static void Create(bool check)
157  {
158  new RunSettingsCompletion(check);
159  }
160 
161  private:
162  explicit RunSettingsCompletion(bool check)
163  {
164  if (check)
165  {
166  connect(&m_plcc,
167  SIGNAL(SigResultReady(bool, ParentalLevel::Level)),
168  SLOT(OnPasswordResultReady(bool,
171  }
172  else
173  {
174  OnPasswordResultReady(true, ParentalLevel::plHigh);
175  }
176  }
177 
178  ~RunSettingsCompletion() override = default;
179 
180  private slots:
181  void OnPasswordResultReady(bool passwordValid,
182  ParentalLevel::Level newLevel)
183  {
184  (void) newLevel;
185 
186  if (passwordValid)
187  {
189  auto *ssd =
190  new StandardSettingDialog(mainStack, "videogeneralsettings",
191  new VideoGeneralSettings());
192 
193  if (ssd->Create())
194  {
195  mainStack->AddScreen(ssd);
196  }
197  else
198  delete ssd;
199  }
200  else
201  {
202  LOG(VB_GENERAL, LOG_WARNING,
203  "Aggressive Parental Controls Warning: "
204  "invalid password. An attempt to enter a "
205  "MythVideo settings screen was prevented.");
206  }
207 
208  deleteLater();
209  }
210 
211  public:
213  };
214 
215  class BookmarkDialog : MythScreenType
216  {
217  Q_DECLARE_TR_FUNCTIONS(BookmarkDialog)
218 
219  public:
220  BookmarkDialog(ProgramInfo *pginfo, MythScreenStack *parent) :
221  MythScreenType(parent, "bookmarkdialog"),
222  m_pgi(pginfo)
223  {
224  }
225 
226  bool Create() override // MythScreenType
227  {
228  QString msg = tr("DVD/Video contains a bookmark");
229  QString btn0msg = tr("Play from bookmark");
230  QString btn1msg = tr("Play from beginning");
231 
232  auto *popup = new MythDialogBox(msg, GetScreenStack(), "bookmarkdialog");
233  if (!popup->Create())
234  {
235  delete popup;
236  return false;
237  }
238 
239  GetScreenStack()->AddScreen(popup);
240 
241  popup->SetReturnEvent(this, "bookmarkdialog");
242  popup->AddButton(btn0msg);
243  popup->AddButton(btn1msg);
244  return true;
245  }
246 
247  void customEvent(QEvent *event) override // MythUIType
248  {
249  if (event->type() == DialogCompletionEvent::kEventType)
250  {
251  auto *dce = (DialogCompletionEvent*)(event);
252  int buttonnum = dce->GetResult();
253 
254  if (dce->GetId() == "bookmarkdialog")
255  {
256  uint flags = kStartTVNoFlags;
257  if (buttonnum == 1)
258  {
259  flags |= kStartTVIgnoreBookmark;
260  }
261  else if (buttonnum != 0)
262  {
263  delete m_pgi;
264  return;
265  }
266 
267  TV::StartTV(m_pgi, flags);
268 
269  delete m_pgi;
270  }
271  }
272  }
273 
274  private:
275  ProgramInfo* m_pgi {nullptr};
276  };
277 
278  void cleanup()
279  {
280  QCoreApplication::processEvents();
282 #ifdef USING_AIRPLAY
285 #endif
286 
287  delete g_exitPopup;
288  g_exitPopup = nullptr;
289 
291 
292  if (g_pUPnp)
293  {
294  // This takes a few seconds, so inform the user:
295  LOG(VB_GENERAL, LOG_INFO, "Shutting down UPnP client...");
296  delete g_pUPnp;
297  g_pUPnp = nullptr;
298  }
299 
300  if (g_pmanager)
301  {
302  delete g_pmanager;
303  g_pmanager = nullptr;
304  }
305 
306  if (g_settingsHelper)
307  {
308  delete g_settingsHelper;
309  g_settingsHelper = nullptr;
310  }
311 
312  delete gContext;
313  gContext = nullptr;
314 
316 
318  }
319 }
320 
321 static void startAppearWiz(void)
322 {
323  int curX = gCoreContext->GetNumSetting("GuiOffsetX", 0);
324  int curY = gCoreContext->GetNumSetting("GuiOffsetY", 0);
325  int curW = gCoreContext->GetNumSetting("GuiWidth", 0);
326  int curH = gCoreContext->GetNumSetting("GuiHeight", 0);
327 
328  bool isWindowed =
329  (gCoreContext->GetNumSetting("RunFrontendInWindow", 0) == 1);
330 
331  bool reload = false;
332 
333  if (isWindowed)
334  {
335  ShowOkPopup(QCoreApplication::translate("(MythFrontendMain)",
336  "The ScreenSetupWizard cannot be used while "
337  "mythfrontend is operating in windowed mode."));
338  }
339  else
340  {
341  auto *wizard = new MythSystemLegacy(
342  GetAppBinDir() + "mythscreenwizard",
343  QStringList(),
345  wizard->Run();
346 
347  if (!wizard->Wait())
348  {
349  // no reported errors, check for changed geometry parameters
350  gCoreContext->ClearSettingsCache("GuiOffsetX");
351  gCoreContext->ClearSettingsCache("GuiOffsetY");
352  gCoreContext->ClearSettingsCache("GuiWidth");
353  gCoreContext->ClearSettingsCache("GuiHeight");
354 
355  if ((curX != gCoreContext->GetNumSetting("GuiOffsetX", 0)) ||
356  (curY != gCoreContext->GetNumSetting("GuiOffsetY", 0)) ||
357  (curW != gCoreContext->GetNumSetting("GuiWidth", 0)) ||
358  (curH != gCoreContext->GetNumSetting("GuiHeight", 0)))
359  reload = true;
360  }
361 
362  delete wizard;
363  wizard = nullptr;
364  }
365 
366  if (reload)
367  GetMythMainWindow()->JumpTo("Reload Theme");
368 }
369 
370 static void startKeysSetup()
371 {
373 
374  auto *mythcontrols = new MythControls(mainStack, "mythcontrols");
375 
376  if (mythcontrols->Create())
377  mainStack->AddScreen(mythcontrols);
378  else
379  delete mythcontrols;
380 }
381 
382 static void startGuide(void)
383 {
384  uint chanid = 0;
385  QString channum = gCoreContext->GetSetting("DefaultTVChannel");
386  QDateTime startTime;
387  GuideGrid::RunProgramGuide(chanid, channum, startTime, nullptr, false, true, -2);
388 }
389 
390 static void startFinder(void)
391 {
393 }
394 
395 static void startSearchTitle(void)
396 {
398  auto *pl = new ProgLister(mainStack, plTitleSearch, "", "");
399  if (pl->Create())
400  mainStack->AddScreen(pl);
401  else
402  delete pl;
403 }
404 
405 static void startSearchKeyword(void)
406 {
408  auto *pl = new ProgLister(mainStack, plKeywordSearch, "", "");
409  if (pl->Create())
410  mainStack->AddScreen(pl);
411  else
412  delete pl;
413 }
414 
415 static void startSearchPeople(void)
416 {
418  auto *pl = new ProgLister(mainStack, plPeopleSearch, "", "");
419  if (pl->Create())
420  mainStack->AddScreen(pl);
421  else
422  delete pl;
423 }
424 
425 static void startSearchPower(void)
426 {
428  auto *pl = new ProgLister(mainStack, plPowerSearch, "", "");
429  if (pl->Create())
430  mainStack->AddScreen(pl);
431  else
432  delete pl;
433 }
434 
435 static void startSearchStored(void)
436 {
438  auto *pl = new ProgLister(mainStack, plStoredSearch, "", "");
439  if (pl->Create())
440  mainStack->AddScreen(pl);
441  else
442  delete pl;
443 }
444 
445 static void startSearchChannel(void)
446 {
448  auto *pl = new ProgLister(mainStack, plChannel, "", "");
449  if (pl->Create())
450  mainStack->AddScreen(pl);
451  else
452  delete pl;
453 }
454 
455 static void startSearchCategory(void)
456 {
458  auto *pl = new ProgLister(mainStack, plCategory, "", "");
459  if (pl->Create())
460  mainStack->AddScreen(pl);
461  else
462  delete pl;
463 }
464 
465 static void startSearchMovie(void)
466 {
468  auto *pl = new ProgLister(mainStack, plMovies, "", "");
469  if (pl->Create())
470  mainStack->AddScreen(pl);
471  else
472  delete pl;
473 }
474 
475 static void startSearchNew(void)
476 {
478  auto *pl = new ProgLister(mainStack, plNewListings, "", "");
479  if (pl->Create())
480  mainStack->AddScreen(pl);
481  else
482  delete pl;
483 }
484 
485 static void startSearchTime(void)
486 {
488  auto *pl = new ProgLister(mainStack, plTime, "", "");
489  if (pl->Create())
490  mainStack->AddScreen(pl);
491  else
492  delete pl;
493 }
494 
495 static void startManaged(void)
496 {
498 
499  auto *viewsched = new ViewScheduled(mainStack);
500 
501  if (viewsched->Create())
502  mainStack->AddScreen(viewsched);
503  else
504  delete viewsched;
505 }
506 
507 static void startManageRecordingRules(void)
508 {
510 
511  auto *progRecPrior = new ProgramRecPriority(mainStack, "ManageRecRules");
512 
513  if (progRecPrior->Create())
514  mainStack->AddScreen(progRecPrior);
515  else
516  delete progRecPrior;
517 }
518 
519 static void startChannelRecPriorities(void)
520 {
522 
523  auto *chanRecPrior = new ChannelRecPriority(mainStack);
524 
525  if (chanRecPrior->Create())
526  mainStack->AddScreen(chanRecPrior);
527  else
528  delete chanRecPrior;
529 }
530 
531 static void startCustomPriority(void)
532 {
534 
535  auto *custom = new CustomPriority(mainStack);
536 
537  if (custom->Create())
538  mainStack->AddScreen(custom);
539  else
540  delete custom;
541 }
542 
543 static void startPlaybackWithGroup(const QString& recGroup = "")
544 {
546 
547  auto *pbb = new PlaybackBox(mainStack, "playbackbox");
548 
549  if (pbb->Create())
550  {
551  if (!recGroup.isEmpty())
552  pbb->setInitialRecGroup(recGroup);
553 
554  mainStack->AddScreen(pbb);
555  }
556  else
557  delete pbb;
558 }
559 
560 static void startPlayback(void)
561 {
563 }
564 
565 static void startPrevious(void)
566 {
568  auto *pl = new PrevRecordedList(mainStack);
569  if (pl->Create())
570  mainStack->AddScreen(pl);
571  else
572  delete pl;
573 }
574 
575 static void startPreviousOld(void)
576 {
578  auto *pl = new ProgLister(mainStack);
579  if (pl->Create())
580  mainStack->AddScreen(pl);
581  else
582  delete pl;
583 }
584 
585 static void startCustomEdit(void)
586 {
588  auto *custom = new CustomEdit(mainStack);
589 
590  if (custom->Create())
591  mainStack->AddScreen(custom);
592  else
593  delete custom;
594 }
595 
596 static void startManualSchedule(void)
597 {
599 
600  auto *mansched= new ManualSchedule(mainStack);
601 
602  if (mansched->Create())
603  mainStack->AddScreen(mansched);
604  else
605  delete mansched;
606 }
607 
608 static bool isLiveTVAvailable(void)
609 {
610  if (RemoteGetFreeRecorderCount() > 0)
611  return true;
612 
613  QString msg = QCoreApplication::translate("(Common)", "All tuners are currently busy.");
614 
615  if (TV::ConfiguredTunerCards() < 1)
616  msg = QCoreApplication::translate("(Common)", "There are no configured tuners.");
617 
618  ShowOkPopup(msg);
619  return false;
620 }
621 
622 static void startTVNormal(void)
623 {
624  if (!isLiveTVAvailable())
625  return;
626 
627  // Get the default channel keys (callsign(0) and channum(1)) and
628  // use them to generate the ordered list of channels.
629  QStringList keylist = gCoreContext->GetSettingOnHost(
630  "DefaultChanKeys", gCoreContext->GetHostName()).split("[]:[]");
631  while (keylist.size() < 2)
632  keylist << "";
633  uint dummy = 0;
635  0, // startIndex
636  0, // count
637  dummy, // totalAvailable
638  true, // ignoreHidden
641  0, // sourceID
642  0, // channelGroupID
643  true, // liveTVOnly
644  keylist[0], // callsign
645  keylist[1]); // channum
646 
647  TV::StartTV(nullptr, kStartTVNoFlags, livetvchannels);
648 }
649 
650 static void showStatus(void)
651 {
653 
654  auto *statusbox = new StatusBox(mainStack);
655 
656  if (statusbox->Create())
657  mainStack->AddScreen(statusbox);
658  else
659  delete statusbox;
660 }
661 
662 
663 static void standbyScreen(void)
664 {
666 
667  auto *idlescreen = new IdleScreen(mainStack);
668 
669  if (idlescreen->Create())
670  mainStack->AddScreen(idlescreen);
671  else
672  delete idlescreen;
673 }
674 
675 static void RunVideoScreen(VideoDialog::DialogType type, bool fromJump = false)
676 {
677  QString message = QCoreApplication::translate("(MythFrontendMain)",
678  "Loading videos ...");
679 
680  MythScreenStack *popupStack =
681  GetMythMainWindow()->GetStack("popup stack");
682 
683  auto *busyPopup = new MythUIBusyDialog(message, popupStack,
684  "mythvideobusydialog");
685 
686  if (busyPopup->Create())
687  popupStack->AddScreen(busyPopup, false);
688 
690 
691  VideoDialog::VideoListPtr video_list;
692  if (fromJump)
693  {
696  if (!saved.isNull())
697  {
698  video_list = saved->GetSaved();
699  LOG(VB_GENERAL, LOG_INFO,
700  QString("Reusing saved video list because MythVideo was resumed"
701  " within %1ms").arg(VideoListDeathDelay::kDelayTimeMS));
702  }
703  }
704 
705  VideoDialog::BrowseType browse = static_cast<VideoDialog::BrowseType>(
706  gCoreContext->GetNumSetting("mythvideo.db_group_type",
708 
709  if (!video_list)
710  video_list = new VideoList;
711 
712  auto *mythvideo =
713  new VideoDialog(mainStack, "mythvideo", video_list, type, browse);
714 
715  if (mythvideo->Create())
716  {
717  busyPopup->Close();
718  mainStack->AddScreen(mythvideo);
719  }
720  else
721  busyPopup->Close();
722 }
723 
729 
730 static void RunGallery()
731 {
733  auto *galleryView = new GalleryThumbView(mainStack, "galleryview");
734  if (galleryView->Create())
735  {
736  mainStack->AddScreen(galleryView);
737  galleryView->Start();
738  }
739  else
740  {
741  delete galleryView;
742  }
743 }
744 
745 static void playDisc()
746 {
747  //
748  // Get the command string to play a DVD
749  //
750 
751  bool isBD = false;
752 
753  QString command_string =
754  gCoreContext->GetSetting("mythdvd.DVDPlayerCommand");
755  QString bluray_mountpoint =
756  gCoreContext->GetSetting("BluRayMountpoint", "/media/cdrom");
757  QDir bdtest(bluray_mountpoint + "/BDMV");
758 
759  if (bdtest.exists() || MythCDROM::inspectImage(bluray_mountpoint) == MythCDROM::kBluray)
760  isBD = true;
761 
762  if (isBD)
763  {
764  GetMythUI()->AddCurrentLocation("playdisc");
765 
766  QString filename = QString("bd:/%1").arg(bluray_mountpoint);
767 
768  GetMythMainWindow()->HandleMedia("Internal", filename, "", "", "", "",
769  0, 0, "", 0, "", "", true);
770 
772  }
773  else
774  {
775  QString dvd_device = MediaMonitor::defaultDVDdevice();
776 
777  if (dvd_device.isEmpty())
778  return; // User cancelled in the Popup
779 
780  GetMythUI()->AddCurrentLocation("playdisc");
781 
782  if ((command_string.indexOf("internal", 0, Qt::CaseInsensitive) > -1) ||
783  (command_string.length() < 1))
784  {
785 #ifdef Q_OS_MAC
786  // Convert a BSD 'leaf' name into a raw device path
787  QString filename = "dvd://dev/r"; // e.g. 'dvd://dev/rdisk2'
788 #elif _WIN32
789  QString filename = "dvd:"; // e.g. 'dvd:E\\'
790 #else
791  QString filename = "dvd:/"; // e.g. 'dvd://dev/sda'
792 #endif
793  filename += dvd_device;
794 
795  command_string = "Internal";
796  GetMythMainWindow()->HandleMedia(command_string, filename, "", "",
797  "", "", 0, 0, "", 0, "", "", true);
799 
800  return;
801  }
802 
803  if (command_string.contains("%d"))
804  {
805  //
806  // Need to do device substitution
807  //
808  command_string =
809  command_string.replace(QRegExp("%d"), dvd_device);
810  }
813  myth_system(command_string);
816  if (GetMythMainWindow())
817  {
818  GetMythMainWindow()->raise();
819  GetMythMainWindow()->activateWindow();
820  }
822  }
823 }
824 
829 {
830  if (!dvd)
831  return;
832 
833  if (!dvd->isUsable()) // This isn't infallible, on some drives both a mount and libudf fail
834  return;
835 
836  switch (gCoreContext->GetNumSetting("DVDOnInsertDVD", 1))
837  {
838  case 0 : // Do nothing
839  case 1 : // Display menu (mythdvd)*/
840  break;
841  case 2 : // play DVD or Blu-ray
842  playDisc();
843  break;
844  default:
845  LOG(VB_GENERAL, LOG_ERR,
846  "mythdvd main.o: handleMedia() does not know what to do");
847  }
848 }
849 
851 {
852  // Only handle events for media that are newly mounted
853  if (!dev || (dev->getStatus() != MEDIASTAT_MOUNTED
854  && dev->getStatus() != MEDIASTAT_USEABLE))
855  return;
856 
857  // Check if gallery is already running
858  QVector<MythScreenType*> screens;
860 
861 
862  for (const auto *screen : qAsConst(screens))
863  {
864  if (dynamic_cast<const GalleryThumbView*>(screen))
865  {
866  // Running gallery will receive this event later
867  LOG(VB_MEDIA, LOG_INFO, "Main: Ignoring new gallery media - already running");
868  return;
869  }
870  }
871 
872  if (gCoreContext->GetBoolSetting("GalleryAutoLoad", false))
873  {
874  LOG(VB_GUI, LOG_INFO, "Main: Autostarting Gallery for new media");
876  }
877  else
878  LOG(VB_MEDIA, LOG_INFO, "Main: Ignoring new gallery media - autorun not set");
879 }
880 
881 static void TVMenuCallback(void *data, QString &selection)
882 {
883  (void)data;
884  QString sel = selection.toLower();
885 
886  if (sel.startsWith("settings ") || sel == "video_settings_general")
887  {
888  if (!g_settingsHelper)
890 
892  }
893 
894  if (sel == "tv_watch_live")
895  startTVNormal();
896  else if (sel.startsWith("tv_watch_recording"))
897  {
898  // use selection here because its case is untouched
899  if ((selection.length() > 19) && (selection.mid(18, 1) == " "))
900  startPlaybackWithGroup(selection.mid(19));
901  else
902  startPlayback();
903  }
904  else if (sel == "tv_schedule")
905  startGuide();
906  else if (sel == "tv_manualschedule")
908  else if (sel == "tv_custom_record")
909  startCustomEdit();
910  else if (sel == "tv_fix_conflicts")
911  startManaged();
912  else if (sel == "tv_manage_recording_rules")
914  else if (sel == "tv_progfind")
915  startFinder();
916  else if (sel == "tv_search_title")
918  else if (sel == "tv_search_keyword")
920  else if (sel == "tv_search_people")
922  else if (sel == "tv_search_power")
924  else if (sel == "tv_search_stored")
926  else if (sel == "tv_search_channel")
928  else if (sel == "tv_search_category")
930  else if (sel == "tv_search_movie")
932  else if (sel == "tv_search_new")
933  startSearchNew();
934  else if (sel == "tv_search_time")
935  startSearchTime();
936  else if (sel == "tv_previous")
937  startPrevious();
938  else if (sel == "tv_previous_old")
940  else if (sel == "settings appearance")
941  {
943  auto *ssd = new StandardSettingDialog(mainStack, "videogeneralsettings",
944  new AppearanceSettings());
945 
946  if (ssd->Create())
947  {
948  mainStack->AddScreen(ssd);
949  }
950  else
951  delete ssd;
952  }
953  else if (sel == "settings themechooser")
954  {
956  auto *tp = new ThemeChooser(mainStack);
957 
958  if (tp->Create())
959  mainStack->AddScreen(tp);
960  else
961  delete tp;
962  }
963  else if (sel == "settings setupwizard")
964  {
966  auto *sw = new GeneralSetupWizard(mainStack, "setupwizard");
967 
968  if (sw->Create())
969  mainStack->AddScreen(sw);
970  else
971  delete sw;
972  }
973  else if (sel == "settings grabbers")
974  {
976  auto *gs = new GrabberSettings(mainStack, "grabbersettings");
977 
978  if (gs->Create())
979  mainStack->AddScreen(gs);
980  else
981  delete gs;
982  }
983  else if (sel == "screensetupwizard")
984  {
985  startAppearWiz();
986  }
987  else if (sel == "setup_keys")
988  {
989  startKeysSetup();
990  }
991  else if (sel == "settings playgroup")
992  {
994  auto *ssd = new StandardSettingDialog(mainStack, "playbackgroupsetting",
995  new PlayGroupEditor());
996 
997  if (ssd->Create())
998  {
999  mainStack->AddScreen(ssd);
1000  }
1001  else
1002  delete ssd;
1003  }
1004  else if (sel == "settings general")
1005  {
1007  auto *ssd = new StandardSettingDialog(mainStack, "videogeneralsettings",
1008  new GeneralSettings());
1009 
1010  if (ssd->Create())
1011  {
1012  mainStack->AddScreen(ssd);
1013  }
1014  else
1015  delete ssd;
1016  }
1017  else if (sel == "settings audiogeneral")
1018  {
1020  StandardSettingDialog *ssd =
1021  new AudioConfigScreen(mainStack, "audiogeneralsettings",
1022  new AudioConfigSettings());
1023 
1024  if (ssd->Create())
1025  {
1026  mainStack->AddScreen(ssd);
1027  }
1028  else
1029  delete ssd;
1030  }
1031  else if (sel == "settings maingeneral")
1032  {
1034  auto *ssd = new StandardSettingDialog(mainStack, "maingeneralsettings",
1035  new MainGeneralSettings());
1036 
1037  if (ssd->Create())
1038  {
1039  mainStack->AddScreen(ssd);
1040  }
1041  else
1042  delete ssd;
1043  }
1044  else if (sel == "settings playback")
1045  {
1047  StandardSettingDialog *ssd =
1048  new PlaybackSettingsDialog(mainStack);
1049 
1050  if (ssd->Create())
1051  {
1052  mainStack->AddScreen(ssd);
1053  }
1054  else
1055  delete ssd;
1056  }
1057  else if (sel == "settings osd")
1058  {
1060  auto *ssd = new StandardSettingDialog(mainStack, "osdsettings",
1061  new OSDSettings());
1062 
1063  if (ssd->Create())
1064  {
1065  mainStack->AddScreen(ssd);
1066  }
1067  else
1068  delete ssd;
1069  }
1070  else if (sel == "settings epg")
1071  {
1073  auto *ssd = new StandardSettingDialog(mainStack, "epgsettings",
1074  new EPGSettings());
1075 
1076  if (ssd->Create())
1077  {
1078  mainStack->AddScreen(ssd);
1079  }
1080  else
1081  delete ssd;
1082  }
1083  else if (sel == "settings channelgroups")
1084  {
1086  auto *ssd = new StandardSettingDialog(mainStack, "channelgroupssettings",
1087  new ChannelGroupsSetting());
1088 
1089  if (ssd->Create())
1090  {
1091  mainStack->AddScreen(ssd);
1092  }
1093  else
1094  delete ssd;
1095  }
1096  else if (sel == "settings generalrecpriorities")
1097  {
1099  auto *ssd = new StandardSettingDialog(mainStack,
1100  "generalrecprioritiessettings",
1102 
1103  if (ssd->Create())
1104  {
1105  mainStack->AddScreen(ssd);
1106  }
1107  else
1108  delete ssd;
1109  }
1110  else if (sel == "settings channelrecpriorities")
1111  {
1113  }
1114  else if (sel == "settings custompriority")
1115  {
1117  }
1118  else if (sel == "system_events")
1119  {
1121 
1122  auto *msee = new MythSystemEventEditor(mainStack, "System Event Editor");
1123 
1124  if (msee->Create())
1125  mainStack->AddScreen(msee);
1126  else
1127  delete msee;
1128  }
1129  else if (sel == "video_settings_general")
1130  {
1131  RunSettingsCompletion::Create(gCoreContext->
1132  GetBoolSetting("VideoAggressivePC", false));
1133  }
1134  else if (sel == "video_settings_player")
1135  {
1137 
1138  auto *ps = new PlayerSettings(mainStack, "player settings");
1139 
1140  if (ps->Create())
1141  mainStack->AddScreen(ps);
1142  else
1143  delete ps;
1144  }
1145  else if (sel == "video_settings_metadata")
1146  {
1148 
1149  auto *ms = new MetadataSettings(mainStack, "metadata settings");
1150 
1151  if (ms->Create())
1152  mainStack->AddScreen(ms);
1153  else
1154  delete ms;
1155  }
1156  else if (sel == "video_settings_associations")
1157  {
1159 
1160  auto *fa = new FileAssocDialog(mainStack, "fa dialog");
1161 
1162  if (fa->Create())
1163  mainStack->AddScreen(fa);
1164  }
1165  else if (sel == "manager")
1167  else if (sel == "browser")
1169  else if (sel == "listing")
1171  else if (sel == "gallery")
1173  else if (sel == "disc_play")
1174  {
1175  playDisc();
1176  }
1177  else if (sel == "tv_status")
1178  showStatus();
1179  else if (sel == "exiting_app_prompt")
1180  handleExit(true);
1181  else if (sel == "exiting_app")
1182  handleExit(false);
1183  else if (sel == "standby_mode")
1184  standbyScreen();
1185  else if (sel == "exiting_menu")
1186  {
1187  //ignore
1188  }
1189  else
1190  LOG(VB_GENERAL, LOG_ERR, "Unknown menu action: " + selection);
1191 
1192  if (sel.startsWith("settings ") || sel == "video_settings_general")
1193  {
1194  if (g_settingsHelper)
1195  {
1196  QObject::connect(GetMythMainWindow()->GetMainStack()->GetTopScreen(),
1197  SIGNAL(Exiting()),
1199  SLOT(RunEpilog()));
1200  }
1201  }
1202 }
1203 
1204 static void handleExit(bool prompt)
1205 {
1206  if (prompt)
1207  {
1208  if (!g_exitPopup)
1209  g_exitPopup = new ExitPrompter();
1211  }
1212  else
1214 }
1215 
1216 static bool RunMenu(const QString& themedir, const QString& themename)
1217 {
1218  QByteArray tmp = themedir.toLocal8Bit();
1219  g_menu = new MythThemedMenu(QString(tmp.constData()), "mainmenu.xml",
1220  GetMythMainWindow()->GetMainStack(), "mainmenu");
1221 
1222  if (g_menu->foundTheme())
1223  {
1224  LOG(VB_GENERAL, LOG_NOTICE, QString("Found mainmenu.xml for theme '%1'")
1225  .arg(themename));
1228  return true;
1229  }
1230 
1231  LOG(VB_GENERAL, LOG_ERR,
1232  QString("Couldn't find mainmenu.xml for theme '%1'") .arg(themename));
1233  delete g_menu;
1234  g_menu = nullptr;
1235 
1236  return false;
1237 }
1238 
1239 // If any settings are missing from the database, this will write
1240 // the default values
1241 static void WriteDefaults()
1242 {
1243  PlaybackSettings ps;
1244  ps.Load();
1245  ps.Save();
1246  OSDSettings os;
1247  os.Load();
1248  os.Save();
1249  GeneralSettings gs;
1250  gs.Load();
1251  gs.Save();
1252  EPGSettings es;
1253  es.Load();
1254  es.Save();
1255  AppearanceSettings as;
1256  as.Load();
1257  as.Save();
1258  MainGeneralSettings mgs;
1259  mgs.Load();
1260  mgs.Save();
1262  grs.Load();
1263  grs.Save();
1265  vgs.Load();
1266  vgs.Save();
1267  //TODo Playback group not loaded?
1268  //TODo Channel group not loaded?
1269 }
1270 
1271 static int internal_play_media(const QString &mrl, const QString &plot,
1272  const QString &title, const QString &subtitle,
1273  const QString &director, int season, int episode,
1274  const QString &inetref, int lenMins, const QString &year,
1275  const QString &id, const bool useBookmark)
1276 {
1277  int res = -1;
1278 
1279  QFile checkFile(mrl);
1280  if ((!checkFile.exists() && !mrl.startsWith("dvd:")
1281  && !mrl.startsWith("bd:")
1282  && !mrl.startsWith("myth:")
1283  && !mrl.startsWith("http://")
1284  && !mrl.startsWith("https://")))
1285  {
1286  QString errorText = QCoreApplication::translate("(MythFrontendMain)",
1287  "Failed to open \n '%1' in %2 \n"
1288  "Check if the video exists")
1289  .arg(mrl.section('/', -1))
1290  .arg(mrl.section('/', 0, -2));
1291 
1292  ShowOkPopup(errorText);
1293  return res;
1294  }
1295 
1296  auto *pginfo = new ProgramInfo(
1297  mrl, plot, title, QString(), subtitle, QString(),
1298  director, season, episode, inetref, lenMins,
1299  (year.toUInt()) ? year.toUInt() : 1900, id);
1300 
1301  pginfo->SetProgramInfoType(pginfo->DiscoverProgramInfoType());
1302 
1303  bool bookmarkPresent = false;
1304 
1305  if (pginfo->IsVideoDVD())
1306  {
1307  auto *dvd = new MythDVDInfo(pginfo->GetPlaybackURL());
1308  if (dvd->IsValid())
1309  {
1310  QString name;
1311  QString serialid;
1312  if (dvd->GetNameAndSerialNum(name, serialid))
1313  {
1314  QStringList fields = pginfo->QueryDVDBookmark(serialid);
1315  bookmarkPresent = (fields.count() > 0);
1316  }
1317  }
1318  else
1319  {
1320  ShowNotificationError(QCoreApplication::translate("(MythFrontendMain)",
1321  "DVD Failure"),
1322  sLocation,
1323  dvd->GetLastError());
1324  delete dvd;
1325  delete pginfo;
1326  return res;
1327  }
1328  delete dvd;
1329  }
1330  else if (pginfo->IsVideoBD())
1331  {
1332  MythBDInfo bd(pginfo->GetPlaybackURL());
1333  if (bd.IsValid())
1334  {
1335  QString name;
1336  QString serialid;
1337  if (bd.GetNameAndSerialNum(name, serialid))
1338  {
1339  QStringList fields = pginfo->QueryBDBookmark(serialid);
1340  bookmarkPresent = (fields.count() > 0);
1341  }
1342  }
1343  else
1344  {
1345  // ToDo: Change string to "BD Failure" after 0.28 is released
1346  ShowNotificationError(QCoreApplication::translate("(MythFrontendMain)",
1347  "DVD Failure"),
1348  sLocation,
1349  bd.GetLastError());
1350  delete pginfo;
1351  return res;
1352  }
1353  }
1354  else if (pginfo->IsVideo())
1355  bookmarkPresent = (pginfo->QueryBookmark() > 0);
1356 
1357  if (useBookmark && bookmarkPresent)
1358  {
1360  auto *bookmarkdialog = new BookmarkDialog(pginfo, mainStack);
1361  if (!bookmarkdialog->Create())
1362  {
1363  delete bookmarkdialog;
1364  delete pginfo;
1365  return res;
1366  }
1367  }
1368  else
1369  {
1371 
1372  res = 0;
1373 
1374  delete pginfo;
1375  }
1376 
1377  return res;
1378 }
1379 
1380 static void gotoMainMenu(void)
1381 {
1382  // Reset the selected button to the first item.
1383  auto *lmenu = dynamic_cast<MythThemedMenuState *>
1384  (GetMythMainWindow()->GetMainStack()->GetTopScreen());
1385  if (lmenu)
1386  lmenu->m_buttonList->SetItemCurrent(0);
1387 }
1388 
1389 // If the theme specified in the DB is somehow broken, try a standard one:
1390 //
1391 static bool resetTheme(QString themedir, const QString &badtheme)
1392 {
1393  QString themename = DEFAULT_UI_THEME;
1394 
1395  if (badtheme == DEFAULT_UI_THEME)
1396  themename = FALLBACK_UI_THEME;
1397 
1398  LOG(VB_GENERAL, LOG_WARNING,
1399  QString("Overriding broken theme '%1' with '%2'")
1400  .arg(badtheme).arg(themename));
1401 
1402  gCoreContext->OverrideSettingForSession("Theme", themename);
1403  themedir = GetMythUI()->FindThemeDir(themename);
1404 
1407  GetMythUI()->LoadQtConfig();
1408  GetMythMainWindow()->Init();
1410 
1411  return RunMenu(themedir, themename);
1412 }
1413 
1414 static int reloadTheme(void)
1415 {
1416 
1417 #ifdef Q_OS_ANDROID
1418 
1419  // jni code to launch the application again
1420  // reinitializing the main windows causes a segfault
1421  // with android
1422 
1423  auto activity = QtAndroid::androidActivity();
1424  auto packageManager = activity.callObjectMethod
1425  ( "getPackageManager",
1426  "()Landroid/content/pm/PackageManager;" );
1427 
1428  auto activityIntent = packageManager.callObjectMethod
1429  ( "getLaunchIntentForPackage",
1430  "(Ljava/lang/String;)Landroid/content/Intent;",
1431  activity.callObjectMethod("getPackageName",
1432  "()Ljava/lang/String;").object() );
1433 
1434  auto pendingIntent = QAndroidJniObject::callStaticObjectMethod
1435  ( "android/app/PendingIntent",
1436  "getActivity",
1437  "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;",
1438  activity.object(),
1439  0,
1440  activityIntent.object(),
1441  QAndroidJniObject::getStaticField<jint>("android/content/Intent",
1442  "FLAG_ACTIVITY_CLEAR_TOP") );
1443 
1444  auto alarmManager = activity.callObjectMethod
1445  ( "getSystemService",
1446  "(Ljava/lang/String;)Ljava/lang/Object;",
1447  QAndroidJniObject::getStaticObjectField("android/content/Context",
1448  "ALARM_SERVICE",
1449  "Ljava/lang/String;").object() );
1450 
1451  alarmManager.callMethod<void>
1452  ( "set",
1453  "(IJLandroid/app/PendingIntent;)V",
1454  QAndroidJniObject::getStaticField<jint>("android/app/AlarmManager", "RTC"),
1455  jlong(QDateTime::currentMSecsSinceEpoch() + 100),
1456  pendingIntent.object() );
1457 
1458  qApp->quit();
1459  // QString title = QObject::tr("Your change will take effect the next time "
1460  // "mythfrontend is started.");
1461  // MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); MythConfirmationDialog *okPopup =
1462  // new MythConfirmationDialog(popupStack, title, false);
1463  // if (okPopup->Create())
1464  // popupStack->AddScreen(okPopup);
1465  return 0;
1466 #else
1467 
1468  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
1469  QString themedir = GetMythUI()->FindThemeDir(themename);
1470  if (themedir.isEmpty())
1471  {
1472  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
1473  .arg(themename));
1474  return GENERIC_EXIT_NO_THEME;
1475  }
1476 
1479 
1481  GetMythUI()->LoadQtConfig();
1482  if (g_menu)
1483  g_menu->Close();
1484  GetMythMainWindow()->Init();
1487 
1488  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
1489  return GENERIC_EXIT_NO_THEME;
1490 
1491  LCD::SetupLCD();
1492  if (LCD *lcd = LCD::Get())
1493  {
1494  lcd->setupLEDs(RemoteGetRecordingMask);
1495  lcd->resetServer();
1496  }
1497 
1498  return 0;
1499 #endif // Q_OS_ANDROID else
1500 }
1501 
1502 static void reloadTheme_void(void)
1503 {
1504  int err = reloadTheme();
1505  if (err)
1506  exit(err);
1507 }
1508 
1509 static void setDebugShowBorders(void)
1510 {
1512  p->SetDebugMode(!p->ShowBorders(), p->ShowTypeNames());
1513 
1516 }
1517 
1518 static void setDebugShowNames(void)
1519 {
1521  p->SetDebugMode(p->ShowBorders(), !p->ShowTypeNames());
1522 
1525 }
1526 
1527 static void InitJumpPoints(void)
1528 {
1529  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Reload Theme"),
1530  "", "", reloadTheme_void);
1531  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Main Menu"),
1532  "", "", gotoMainMenu);
1533  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Guide"),
1534  "", "", startGuide, "GUIDE");
1535  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Finder"),
1536  "", "", startFinder, "FINDER");
1537  //REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Search Listings"),
1538  // "", "", startSearch);
1539  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Manage Recordings / "
1540  "Fix Conflicts"), "", "", startManaged, "VIEWSCHEDULED");
1541  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Manage Recording Rules"),
1542  "", "", startManageRecordingRules);
1543  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Channel Recording "
1544  "Priorities"), "", "", startChannelRecPriorities);
1545  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "TV Recording Playback"),
1546  "", "", startPlayback, "JUMPREC");
1547  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Live TV"),
1548  "", "", startTVNormal);
1549  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Status Screen"),
1550  "", "", showStatus);
1551  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Previously Recorded"),
1552  "", "", startPrevious);
1553 
1554  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Standby Mode"),
1555  "", "", standbyScreen);
1556 
1557  // Video
1558 
1559  REG_JUMP(JUMP_VIDEO_DEFAULT, QT_TRANSLATE_NOOP("MythControls",
1560  "The Video Default View"), "", jumpScreenVideoDefault);
1561  REG_JUMP(JUMP_VIDEO_MANAGER, QT_TRANSLATE_NOOP("MythControls",
1562  "The Video Manager"), "", jumpScreenVideoManager);
1563  REG_JUMP(JUMP_VIDEO_BROWSER, QT_TRANSLATE_NOOP("MythControls",
1564  "The Video Browser"), "", jumpScreenVideoBrowser);
1565  REG_JUMP(JUMP_VIDEO_TREE, QT_TRANSLATE_NOOP("MythControls",
1566  "The Video Listings"), "", jumpScreenVideoTree);
1567  REG_JUMP(JUMP_VIDEO_GALLERY, QT_TRANSLATE_NOOP("MythControls",
1568  "The Video Gallery"), "", jumpScreenVideoGallery);
1569  REG_JUMP("Play Disc", QT_TRANSLATE_NOOP("MythControls",
1570  "Play an Optical Disc"), "", playDisc);
1571 
1572  // Gallery
1573 
1574  REG_JUMP(JUMP_GALLERY_DEFAULT, QT_TRANSLATE_NOOP("MythControls",
1575  "Image Gallery"), "", RunGallery);
1576 
1577  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Borders"),
1578  "", "", setDebugShowBorders, false);
1579  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Names"),
1580  "", "", setDebugShowNames, false);
1581  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Reset All Keys"),
1582  QT_TRANSLATE_NOOP("MythControls", "Reset all keys to defaults"),
1583  "", resetAllKeys, false);
1584 }
1585 
1586 static void ReloadJumpPoints(void)
1587 {
1588  MythMainWindow *mainWindow = GetMythMainWindow();
1589  mainWindow->ClearAllJumps();
1590  InitJumpPoints();
1591 }
1592 
1593 static void InitKeys(void)
1594 {
1595  REG_KEY("Video","PLAYALT", QT_TRANSLATE_NOOP("MythControls",
1596  "Play selected item in alternate player"), "ALT+P");
1597  REG_KEY("Video","FILTER", QT_TRANSLATE_NOOP("MythControls",
1598  "Open video filter dialog"), "F");
1599  REG_KEY("Video","INCPARENT", QT_TRANSLATE_NOOP("MythControls",
1600  "Increase Parental Level"), "],},F11");
1601  REG_KEY("Video","DECPARENT", QT_TRANSLATE_NOOP("MythControls",
1602  "Decrease Parental Level"), "[,{,F10");
1603  REG_KEY("Video","INCSEARCH", QT_TRANSLATE_NOOP("MythControls",
1604  "Show Incremental Search Dialog"), "Ctrl+S");
1605  REG_KEY("Video","DOWNLOADDATA", QT_TRANSLATE_NOOP("MythControls",
1606  "Download metadata for current item"), "W");
1607  REG_KEY("Video","ITEMDETAIL", QT_TRANSLATE_NOOP("MythControls",
1608  "Display Item Detail Popup"), "");
1609 
1610  // Gallery keybindings
1611  REG_KEY("Images", "PLAY", QT_TRANSLATE_NOOP("MythControls",
1612  "Start/Stop Slideshow"), "P");
1613  REG_KEY("Images", "RECURSIVESHOW", QT_TRANSLATE_NOOP("MythControls",
1614  "Start Recursive Slideshow"), "R");
1615  REG_KEY("Images", "ROTRIGHT", QT_TRANSLATE_NOOP("MythControls",
1616  "Rotate image right 90 degrees"), "],3");
1617  REG_KEY("Images", "ROTLEFT", QT_TRANSLATE_NOOP("MythControls",
1618  "Rotate image left 90 degrees"), "[,1");
1619  REG_KEY("Images", "FLIPHORIZONTAL", QT_TRANSLATE_NOOP("MythControls",
1620  "Flip image horizontally"), "");
1621  REG_KEY("Images", "FLIPVERTICAL", QT_TRANSLATE_NOOP("MythControls",
1622  "Flip image vertically"), "");
1623  REG_KEY("Images", "ZOOMOUT", QT_TRANSLATE_NOOP("MythControls",
1624  "Zoom image out"), "7");
1625  REG_KEY("Images", "ZOOMIN", QT_TRANSLATE_NOOP("MythControls",
1626  "Zoom image in"), "9");
1627  REG_KEY("Images", "FULLSIZE", QT_TRANSLATE_NOOP("MythControls",
1628  "Full-size (un-zoom) image"), "0");
1629  REG_KEY("Images", "MARK", QT_TRANSLATE_NOOP("MythControls",
1630  "Mark image"), "T");
1631  REG_KEY("Images", "SCROLLUP", QT_TRANSLATE_NOOP("MythControls",
1632  "Scroll image up"), "2");
1633  REG_KEY("Images", "SCROLLLEFT", QT_TRANSLATE_NOOP("MythControls",
1634  "Scroll image left"), "4");
1635  REG_KEY("Images", "SCROLLRIGHT", QT_TRANSLATE_NOOP("MythControls",
1636  "Scroll image right"), "6");
1637  REG_KEY("Images", "SCROLLDOWN", QT_TRANSLATE_NOOP("MythControls",
1638  "Scroll image down"), "8");
1639  REG_KEY("Images", "RECENTER", QT_TRANSLATE_NOOP("MythControls",
1640  "Recenter image"), "5");
1641  REG_KEY("Images", "COVER", QT_TRANSLATE_NOOP("MythControls",
1642  "Set or clear cover image"), "C");
1643 }
1644 
1645 static void ReloadKeys(void)
1646 {
1647  GetMythMainWindow()->ClearKeyContext("Video");
1648  InitKeys();
1649 
1650  TV::ReloadKeys();
1651 }
1652 
1653 static void SetFuncPtrs(void)
1654 {
1655  TV::SetFuncPtr("playbackbox", (void *)PlaybackBox::RunPlaybackBox);
1656  TV::SetFuncPtr("viewscheduled", (void *)ViewScheduled::RunViewScheduled);
1657  TV::SetFuncPtr("programguide", (void *)GuideGrid::RunProgramGuide);
1658  TV::SetFuncPtr("programfinder", (void *)RunProgramFinder);
1659  TV::SetFuncPtr("scheduleeditor", (void *)ScheduleEditor::RunScheduleEditor);
1660 }
1661 
1665 static void clearAllKeys(void)
1666 {
1668 
1669  query.prepare("DELETE FROM keybindings "
1670  "WHERE hostname = :HOSTNAME;");
1671  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1672  if (!query.exec())
1673  MythDB::DBError("Deleting keybindings", query);
1674  query.prepare("DELETE FROM jumppoints "
1675  "WHERE hostname = :HOSTNAME;");
1676  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1677  if (!query.exec())
1678  MythDB::DBError("Deleting jumppoints", query);
1679 }
1680 
1684 static void resetAllKeys(void)
1685 {
1686  clearAllKeys();
1687  // Reload MythMainWindow bindings
1689  // Reload Jump Points
1690  ReloadJumpPoints();
1691  // Reload mythfrontend and TV bindings
1692  ReloadKeys();
1693 }
1694 
1696 {
1697  REG_MEDIAPLAYER("Internal", QT_TRANSLATE_NOOP("MythControls",
1698  "MythTV's native media player."), internal_play_media);
1699  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1700  "MythDVD DVD Media Handler"), "", handleDVDMedia,
1701  MEDIATYPE_DVD, QString());
1702  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1703  "MythImage Media Handler 1/2"), "", handleGalleryMedia,
1704  MEDIATYPE_DATA | MEDIATYPE_MIXED, QString());
1705 
1706  QStringList extensions(ImageAdapterBase::SupportedImages()
1708 
1709  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1710  "MythImage Media Handler 2/2"), "", handleGalleryMedia,
1711  MEDIATYPE_MGALLERY | MEDIATYPE_MVIDEO, extensions.join(","));
1712  return 0;
1713 }
1714 
1715 static void CleanupMyOldInUsePrograms(void)
1716 {
1718 
1719  query.prepare("DELETE FROM inuseprograms "
1720  "WHERE hostname = :HOSTNAME and recusage = 'player' ;");
1721  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1722  if (!query.exec())
1723  MythDB::DBError("CleanupMyOldInUsePrograms", query);
1724 }
1725 
1726 static bool WasAutomaticStart(void)
1727 {
1728  bool autoStart = false;
1729 
1730  // Is backend running?
1731  //
1733  {
1734  QDateTime startupTime = QDateTime();
1735 
1736  if( gCoreContext->IsMasterHost() )
1737  {
1738  QString s = gCoreContext->GetSetting("MythShutdownWakeupTime", "");
1739  if (s.length())
1740  startupTime = MythDate::fromString(s);
1741 
1742  // if we don't have a valid startup time assume we were started manually
1743  if (startupTime.isValid())
1744  {
1745  int startupSecs = gCoreContext->GetNumSetting("StartupSecsBeforeRecording");
1746  // If we started within 'StartupSecsBeforeRecording' OR 15 minutes
1747  // of the saved wakeup time assume we either started automatically
1748  // to record, to obtain guide data or or for a
1749  // daily wakeup/shutdown period
1750  if (abs(startupTime.secsTo(MythDate::current())) <
1751  max(startupSecs, 15 * 60))
1752  {
1753  LOG(VB_GENERAL, LOG_INFO,
1754  "Close to auto-start time, AUTO-Startup assumed");
1755 
1756  QString str = gCoreContext->GetSetting("MythFillSuggestedRunTime");
1757  QDateTime guideRunTime = MythDate::fromString(str);
1758  if (guideRunTime.secsTo(MythDate::current()) <
1759  max(startupSecs, 15 * 60))
1760  {
1761  LOG(VB_GENERAL, LOG_INFO,
1762  "Close to MythFillDB suggested run time, AUTO-Startup to fetch guide data?");
1763  }
1764  autoStart = true;
1765  }
1766  else
1767  LOG(VB_GENERAL, LOG_DEBUG,
1768  "NOT close to auto-start time, USER-initiated startup assumed");
1769  }
1770  }
1771  else
1772  {
1773  QString wakeupCmd = gCoreContext->GetSetting("WakeUpCommand");
1774 
1775  // A slave backend that has no wakeup command cannot be woken
1776  // automatically so can be ignored.
1777  if (!wakeupCmd.isEmpty())
1778  {
1779  ProgramList progList;
1780  bool bConflicts = false;
1781  QDateTime nextRecordingStart;
1782 
1783  if (LoadFromScheduler(progList, bConflicts))
1784  {
1785  // Find the first recording to be recorded
1786  // on this machine
1787  QString hostname = gCoreContext->GetHostName();
1788  for (auto *prog : progList)
1789  {
1790  if ((prog->GetRecordingStatus() == RecStatus::WillRecord ||
1791  prog->GetRecordingStatus() == RecStatus::Pending) &&
1792  (prog->GetHostname() == hostname) &&
1793  (nextRecordingStart.isNull() ||
1794  nextRecordingStart > prog->GetRecordingStartTime()))
1795  {
1796  nextRecordingStart = prog->GetRecordingStartTime();
1797  }
1798  }
1799 
1800  if (!nextRecordingStart.isNull() &&
1801  (abs(nextRecordingStart.secsTo(MythDate::current())) < (4 * 60)))
1802  {
1803  LOG(VB_GENERAL, LOG_INFO,
1804  "Close to start time, AUTO-Startup assumed");
1805 
1806  // If we started within 4 minutes of the next recording,
1807  // we almost certainly started automatically.
1808  autoStart = true;
1809  }
1810  else
1811  LOG(VB_GENERAL, LOG_DEBUG,
1812  "NOT close to auto-start time, USER-initiated startup assumed");
1813 
1814  }
1815  }
1816  }
1817  }
1818 
1819  return autoStart;
1820 }
1821 
1822 // from https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=16897
1823 // The old way of revoking root with setuid(getuid())
1824 // causes system hang in certain cases on raspberry pi
1825 
1826 static int revokeRoot (void)
1827 {
1828  if (getuid () == 0 && geteuid () == 0) // Really running as root
1829  return 0;
1830 
1831  if (geteuid () == 0) // Running setuid root
1832  return seteuid (getuid ()) ; // Change effective uid to the uid of the caller
1833  return 0;
1834 }
1835 
1836 
1837 int main(int argc, char **argv)
1838 {
1839  bool bPromptForBackend = false;
1840  bool bBypassAutoDiscovery = false;
1841 
1843  if (!cmdline.Parse(argc, argv))
1844  {
1845  cmdline.PrintHelp();
1847  }
1848 
1849  if (cmdline.toBool("showhelp"))
1850  {
1851  cmdline.PrintHelp();
1852  return GENERIC_EXIT_OK;
1853  }
1854 
1855  if (cmdline.toBool("showversion"))
1856  {
1858  return GENERIC_EXIT_OK;
1859  }
1860 
1862  QApplication::setSetuidAllowed(true);
1863  QApplication a(argc, argv);
1864  QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHFRONTEND);
1865  CleanupGuard callCleanup(cleanup);
1866 
1867 #ifdef Q_OS_MAC
1868  QString path = QCoreApplication::applicationDirPath();
1869  setenv("PYTHONPATH",
1870  QString("%1/../Resources/lib/python2.6/site-packages:%2")
1871  .arg(path)
1872  .arg(QProcessEnvironment::systemEnvironment().value("PYTHONPATH"))
1873  .toUtf8().constData(), 1);
1874 #endif
1875 
1876 #ifndef _WIN32
1877  QList<int> signallist;
1878  signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
1879  << SIGILL;
1880 #if ! CONFIG_DARWIN
1881  signallist << SIGRTMIN;
1882 #endif
1883  SignalHandler::Init(signallist);
1886  SignalHandler::SetHandler(SIGHUP, logSigHup);
1887 #endif
1888 
1889  int retval = cmdline.ConfigureLogging();
1890  if (retval != GENERIC_EXIT_OK)
1891  return retval;
1892 
1893  bool ResetSettings = false;
1894 
1895  if (cmdline.toBool("prompt"))
1896  bPromptForBackend = true;
1897  if (cmdline.toBool("noautodiscovery"))
1898  bBypassAutoDiscovery = true;
1899 
1900  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1901  cerr << "Unable to ignore SIGPIPE\n";
1902 
1903  if (!cmdline.toString("display").isEmpty())
1904  {
1906  }
1907 
1908  if (!cmdline.toString("geometry").isEmpty())
1909  {
1911  }
1912 
1913  fe_sd_notify("STATUS=Connecting to database.");
1915  gCoreContext->SetAsFrontend(true);
1916 
1918  if (!gContext->Init(true, bPromptForBackend, bBypassAutoDiscovery))
1919  {
1920  LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
1921  gCoreContext->SetExiting(true);
1923  }
1924 
1926 
1927  if (!GetMythDB()->HaveSchema())
1928  {
1929  if (!InitializeMythSchema())
1930  return GENERIC_EXIT_DB_ERROR;
1931  }
1932 
1933  if (cmdline.toBool("reset"))
1934  ResetSettings = true;
1935 
1936  if (!cmdline.toBool("noupnp"))
1937  {
1938  fe_sd_notify("STATUS=Creating UPnP media renderer");
1939  g_pUPnp = new MediaRenderer();
1940  if (!g_pUPnp->isInitialized())
1941  {
1942  delete g_pUPnp;
1943  g_pUPnp = nullptr;
1944  }
1945  }
1946 
1947  QString fileprefix = GetConfDir();
1948 
1949  QDir dir(fileprefix);
1950  if (!dir.exists())
1951  dir.mkdir(fileprefix);
1952 
1953  if (ResetSettings)
1954  {
1955  AppearanceSettings as;
1956  as.Save();
1957 
1959  gCoreContext->GetDB()->ClearSetting("Language");
1960  gCoreContext->GetDB()->ClearSettingOnHost("Language", nullptr);
1961  gCoreContext->GetDB()->ClearSetting("Country");
1962  gCoreContext->GetDB()->ClearSettingOnHost("Country", nullptr);
1963 
1964  LOG(VB_GENERAL, LOG_NOTICE, "Appearance settings and language have "
1965  "been reset to defaults. You will need to "
1966  "restart the frontend.");
1967  gContext-> saveSettingsCache();
1968  return GENERIC_EXIT_OK;
1969  }
1970 
1971  QCoreApplication::setSetuidAllowed(true);
1972 
1973  if (revokeRoot() != 0)
1974  {
1975  LOG(VB_GENERAL, LOG_ERR, "Failed to revokeRoot(), exiting.");
1976  return GENERIC_EXIT_NOT_OK;
1977  }
1978 
1979 #ifdef USING_LIBDNS_SD
1980  // this needs to come after gCoreContext has been initialised
1981  // (for hostname) - hence it is not in MediaRenderer
1982  QScopedPointer<BonjourRegister> bonjour(new BonjourRegister());
1983  if (bonjour.data())
1984  {
1985  fe_sd_notify("STATUS=Registering frontend with bonjour");
1986  QByteArray dummy;
1987  int port = gCoreContext->GetNumSetting("UPnP/MythFrontend/ServicePort", 6547);
1988  QByteArray name("Mythfrontend on ");
1989  name.append(gCoreContext->GetHostName());
1990  bonjour->Register(port, "_mythfrontend._tcp",
1991  name, dummy);
1992  }
1993 #endif
1994 
1995  fe_sd_notify("STATUS=Initializing LCD");
1996  LCD::SetupLCD();
1997  if (LCD *lcd = LCD::Get())
1998  lcd->setupLEDs(RemoteGetRecordingMask);
1999 
2000  fe_sd_notify("STATUS=Loading translation");
2001  MythTranslation::load("mythfrontend");
2002 
2003  fe_sd_notify("STATUS=Loading themes");
2004  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
2005 
2006  QString themedir = GetMythUI()->FindThemeDir(themename);
2007  if (themedir.isEmpty())
2008  {
2009  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
2010  .arg(themename));
2011  return GENERIC_EXIT_NO_THEME;
2012  }
2013 
2014  GetMythUI()->LoadQtConfig();
2015 
2016  themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
2017  themedir = GetMythUI()->FindThemeDir(themename);
2018  if (themedir.isEmpty())
2019  {
2020  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
2021  .arg(themename));
2022  return GENERIC_EXIT_NO_THEME;
2023  }
2024 
2025  MythMainWindow *mainWindow = GetMythMainWindow();
2026  mainWindow->Init(false);
2027  mainWindow->setWindowTitle(QCoreApplication::translate("(MythFrontendMain)",
2028  "MythTV Frontend",
2029  "Main window title"));
2030 
2031 #ifdef USING_AIRPLAY
2032  if (gCoreContext->GetBoolSetting("AirPlayEnabled", true))
2033  {
2034  fe_sd_notify("STATUS=Initializing AirPlay");
2036  if (!gCoreContext->GetBoolSetting("AirPlayAudioOnly", false))
2037  {
2039  }
2040  }
2041 #endif
2042 
2043  // We must reload the translation after a language change and this
2044  // also means clearing the cached/loaded theme strings, so reload the
2045  // theme which also triggers a translation reload
2047  {
2048  if (!reloadTheme())
2049  return GENERIC_EXIT_NO_THEME;
2050  }
2051 
2052  if (!UpgradeTVDatabaseSchema(false, false, true))
2053  {
2054  LOG(VB_GENERAL, LOG_ERR,
2055  "Couldn't upgrade database to new schema, exiting.");
2057  }
2058 
2059  WriteDefaults();
2060 
2061  // Refresh Global/Main Menu keys after DB update in case there was no DB
2062  // when they were written originally
2063  mainWindow->ReloadKeys();
2064 
2065  fe_sd_notify("STATUS=Initializing jump points");
2066  InitJumpPoints();
2067  InitKeys();
2068  TV::InitKeys();
2069  SetFuncPtrs();
2070 
2072 
2074 
2075  setHttpProxy();
2076 
2077  fe_sd_notify("STATUS=Initializing plugins");
2078  g_pmanager = new MythPluginManager();
2080 
2081  fe_sd_notify("STATUS=Initializing media monitor");
2083  if (mon)
2084  {
2085  mon->StartMonitoring();
2086  mainWindow->installEventFilter(mon);
2087  }
2088 
2089  fe_sd_notify("STATUS=Initializing network control");
2090  NetworkControl *networkControl = nullptr;
2091  if (gCoreContext->GetBoolSetting("NetworkControlEnabled", false))
2092  {
2093  int port = gCoreContext->GetNumSetting("NetworkControlPort", 6546);
2094  networkControl = new NetworkControl();
2095  if (!networkControl->listen(port))
2096  {
2097  LOG(VB_GENERAL, LOG_ERR,
2098  QString("NetworkControl failed to bind to port %1.")
2099  .arg(port));
2100  }
2101  }
2102 
2103 #if CONFIG_DARWIN
2105  GetMythMainWindow()->Init();
2108  gLoaded = true;
2109 #endif
2110  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
2111  {
2112  return GENERIC_EXIT_NO_THEME;
2113  }
2114  fe_sd_notify("STATUS=Loading theme updates");
2115  std::unique_ptr<ThemeUpdateChecker> themeUpdateChecker;
2116  if (gCoreContext->GetBoolSetting("ThemeUpdateNofications", true))
2117  themeUpdateChecker = make_unique<ThemeUpdateChecker>();
2118 
2120 
2122 
2124  PreviewGenerator::kRemote, 50, 60);
2125 
2126  fe_sd_notify("STATUS=Creating housekeeper");
2127  auto *housekeeping = new HouseKeeper();
2128 #ifdef __linux__
2129  #ifdef CONFIG_BINDINGS_PYTHON
2131  #endif
2132 #endif
2133  housekeeping->Start();
2134 
2135 
2136  if (cmdline.toBool("runplugin"))
2137  {
2138  QStringList plugins = g_pmanager->EnumeratePlugins();
2139 
2140  if (plugins.contains(cmdline.toString("runplugin")))
2141  g_pmanager->run_plugin(cmdline.toString("runplugin"));
2142  else if (plugins.contains("myth" + cmdline.toString("runplugin")))
2143  g_pmanager->run_plugin("myth" + cmdline.toString("runplugin"));
2144  else
2145  {
2146  LOG(VB_GENERAL, LOG_ERR,
2147  QString("Invalid plugin name supplied on command line: '%1'")
2148  .arg(cmdline.toString("runplugin")));
2149  LOG(VB_GENERAL, LOG_ERR,
2150  QString("Available plugins: %1")
2151  .arg(plugins.join(", ")));
2153  }
2154  }
2155  else if (cmdline.toBool("jumppoint"))
2156  {
2158 
2159  if (mmw->DestinationExists(cmdline.toString("jumppoint")))
2160  mmw->JumpTo(cmdline.toString("jumppoint"));
2161  else
2162  {
2163  LOG(VB_GENERAL, LOG_ERR,
2164  QString("Invalid jump point supplied on the command line: %1")
2165  .arg(cmdline.toString("jumppoint")));
2166  LOG(VB_GENERAL, LOG_ERR,
2167  QString("Available jump points: %2")
2168  .arg(mmw->EnumerateDestinations().join(", ")));
2170  }
2171  }
2172 
2173  if (WasAutomaticStart())
2174  {
2175  // We appear to have been started automatically
2176  // so enter standby so that the machine can
2177  // shutdown again as soon as possible if necessary.
2178  standbyScreen();
2179  }
2180 
2181  // Provide systemd ready notification (for type=notify units)
2182  fe_sd_notify("STATUS=");
2183  fe_sd_notify("READY=1");
2184 
2185  int ret = QCoreApplication::exec();
2186 
2187  fe_sd_notify("STOPPING=1\nSTATUS=Exiting");
2188  if (ret==0)
2189  gContext-> saveSettingsCache();
2190 
2191  DestroyMythUI();
2193 
2194  delete housekeeping;
2195 
2197 
2198  if (mon)
2199  mon->deleteLater();
2200 
2201  delete networkControl;
2202  return ret;
2203 }
2204 
2205 void handleSIGUSR1(void)
2206 {
2207  LOG(VB_GENERAL, LOG_INFO, "Reloading theme");
2208  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
2210  GetMythMainWindow()->JumpTo("Reload Theme");
2212 }
2213 
2214 void handleSIGUSR2(void)
2215 {
2216  LOG(VB_GENERAL, LOG_INFO, "Restarting LIRC handler");
2218 }
2219 
2220 #include "main.moc"
2221 /* vim: set expandtab tabstop=4 shiftwidth=4: */
static void ConfigureQtGUI(int SwapInterval=1)
Shared static initialistaion code for all MythTV GUI applications.
#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:234
static void startSearchMovie(void)
void DestroyAllPlugins()
Definition: mythplugin.cpp:222
#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:864
const QString JUMP_VIDEO_DEFAULT
Definition: globals.cpp:40
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 * RunPlaybackBox(void *player, bool showTV)
static void gotoMainMenu(void)
Main header for mythcontrols.
void RestartInputHandlers(void)
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:390
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
static void SetFuncPtr(const char *string, void *lptr)
Import pointers to functions used to embed the TV window into other containers e.g.
Definition: tv_play.cpp:489
void RegisterTask(HouseKeeperTask *task)
static void startSearchPower(void)
static VideoListDeathDelayPtr & GetSavedVideoList()
Definition: videodlg.cpp:844
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:506
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.
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
void SetRedraw(void)
Definition: mythuitype.cpp:293
static void startKeysSetup()
static int ConfiguredTunerCards(void)
If any cards are configured, return the number.
Definition: tv_play.cpp:194
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.
unsigned int slots[4]
Definition: element.cpp:38
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)
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 guint32 * tmp
Definition: goom_core.cpp:30
static QString defaultDVDdevice()
DVDDeviceLocation, user-selected drive, or /dev/dvd.
static void * RunViewScheduled(void *player, bool showTv)
static void jumpScreenVideoBrowser()
void DestroyMythUI()
#define REG_MEDIAPLAYER(a, b, c)
void ClearKeyContext(const QString &context)
static Type kEventType
Definition: mythdialogbox.h:57
#define seteuid(x)
Definition: compat.h:263
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...
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:67
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
MSqlQuery query(MSqlQuery::InitCon())
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)
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)
bool InitializeMythSchema(void)
command to get the the initial database layout from an empty database:
Definition: dbcheck.cpp:3706
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:126
static void Done(void)
unsigned int uint
Definition: compat.h:140
void JumpTo(const QString &destination, bool pop=true)
static void SetHandler(int signum, SigHandlerFunc handler)
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
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:290
static void startManageRecordingRules(void)
const QString JUMP_VIDEO_GALLERY
Definition: globals.cpp:39
int ConfigureLogging(const QString &mask="general", bool progress=false)
Read in logging options and initialize the logging interface.
static ExitPrompter * g_exitPopup
static void ReloadKeys(void)
Definition: tv_play.cpp:995
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:808
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()
Themed menu class, used for main menus in MythTV frontend.
bool Create(void) override
Reports on various status items.
Definition: statusbox.h:37
QStringList EnumerateDestinations(void) const
#define MYTH_APPNAME_MYTHFRONTEND
static void startSearchStored(void)
bool GetBoolSetting(const QString &key, bool defaultval=false)
bool foundTheme(void) const
Returns true iff a theme has been found by a previous call to SetMenuTheme().
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:415
#define SIGUSR2
Definition: compat.h:217
QString RemoveCurrentLocation(void)
int RemoteGetRecordingMask(void)
Definition: remoteutil.cpp:397
static bool resetTheme(QString themedir, const QString &badtheme)
static MythPluginManager * g_pmanager
#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 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="")
bool Init(bool gui=true, bool promptForBackend=false, bool disableAutoDiscovery=false, bool ignoreDB=false)
Definition: lcddevice.h:169
MythDB * GetDB(void)
An editor for MythSystemEvent handler commands.
static void showStatus(void)
static QString cleanup(const QString &str)
virtual void Load(void)
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
#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
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:603
#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
bool LoadFromScheduler(AutoDeleteDeque< TYPE * > &destination, bool &hasConflicts, const QString &altTable="", int recordid=-1)
Definition: programinfo.h:877
void ActivateSettingsCache(bool activate=true)
void Init(bool mayReInit=true)
#define GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:11
static const QString sLocation
static void startFinder(void)
static void WriteDefaults()
static void RunVideoScreen(VideoDialog::DialogType type, bool fromJump=false)
static void InitKeys(void)
Definition: tv_play.cpp:504
QString GetHostName(void)
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:41
static MythThemedMenu * g_menu
static void handleGalleryMedia(MythMediaDevice *dev)
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:133
Implements Gallery Thumbnail screen.
static QStringList SupportedImages()
Return recognised pictures.
static int reloadTheme(void)
static void startSearchKeyword(void)
static void handleDVDMedia(MythMediaDevice *dvd)
static void startManaged(void)
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:161
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16
bool UpgradeTVDatabaseSchema(const bool upgradeAllowed, const bool upgradeIfNoUI, const bool informSystemd)
Called from outside dbcheck.cpp to update the schema.
Definition: dbcheck.cpp:362
static void startAppearWiz(void)
static bool isLiveTVAvailable(void)
void Start(void)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23