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  {
336  ShowOkPopup(qApp->translate("(MythFrontendMain)",
337  "The ScreenSetupWizard cannot be used while "
338  "mythfrontend is operating in windowed mode."));
339  }
340  else
341  {
342  auto *wizard = new MythSystemLegacy(
343  GetAppBinDir() + "mythscreenwizard",
344  QStringList(),
346  wizard->Run();
347 
348  if (!wizard->Wait())
349  {
350  // no reported errors, check for changed geometry parameters
351  gCoreContext->ClearSettingsCache("GuiOffsetX");
352  gCoreContext->ClearSettingsCache("GuiOffsetY");
353  gCoreContext->ClearSettingsCache("GuiWidth");
354  gCoreContext->ClearSettingsCache("GuiHeight");
355 
356  if ((curX != gCoreContext->GetNumSetting("GuiOffsetX", 0)) ||
357  (curY != gCoreContext->GetNumSetting("GuiOffsetY", 0)) ||
358  (curW != gCoreContext->GetNumSetting("GuiWidth", 0)) ||
359  (curH != gCoreContext->GetNumSetting("GuiHeight", 0)))
360  reload = true;
361  }
362 
363  delete wizard;
364  wizard = nullptr;
365  }
366 
367  if (reload)
368  GetMythMainWindow()->JumpTo("Reload Theme");
369 }
370 
371 static void startKeysSetup()
372 {
374 
375  auto *mythcontrols = new MythControls(mainStack, "mythcontrols");
376 
377  if (mythcontrols->Create())
378  mainStack->AddScreen(mythcontrols);
379  else
380  delete mythcontrols;
381 }
382 
383 static void startGuide(void)
384 {
385  uint chanid = 0;
386  QString channum = gCoreContext->GetSetting("DefaultTVChannel");
387  QDateTime startTime;
388  GuideGrid::RunProgramGuide(chanid, channum, startTime, nullptr, false, true, -2);
389 }
390 
391 static void startFinder(void)
392 {
394 }
395 
396 static void startSearchTitle(void)
397 {
399  auto *pl = new ProgLister(mainStack, plTitleSearch, "", "");
400  if (pl->Create())
401  mainStack->AddScreen(pl);
402  else
403  delete pl;
404 }
405 
406 static void startSearchKeyword(void)
407 {
409  auto *pl = new ProgLister(mainStack, plKeywordSearch, "", "");
410  if (pl->Create())
411  mainStack->AddScreen(pl);
412  else
413  delete pl;
414 }
415 
416 static void startSearchPeople(void)
417 {
419  auto *pl = new ProgLister(mainStack, plPeopleSearch, "", "");
420  if (pl->Create())
421  mainStack->AddScreen(pl);
422  else
423  delete pl;
424 }
425 
426 static void startSearchPower(void)
427 {
429  auto *pl = new ProgLister(mainStack, plPowerSearch, "", "");
430  if (pl->Create())
431  mainStack->AddScreen(pl);
432  else
433  delete pl;
434 }
435 
436 static void startSearchStored(void)
437 {
439  auto *pl = new ProgLister(mainStack, plStoredSearch, "", "");
440  if (pl->Create())
441  mainStack->AddScreen(pl);
442  else
443  delete pl;
444 }
445 
446 static void startSearchChannel(void)
447 {
449  auto *pl = new ProgLister(mainStack, plChannel, "", "");
450  if (pl->Create())
451  mainStack->AddScreen(pl);
452  else
453  delete pl;
454 }
455 
456 static void startSearchCategory(void)
457 {
459  auto *pl = new ProgLister(mainStack, plCategory, "", "");
460  if (pl->Create())
461  mainStack->AddScreen(pl);
462  else
463  delete pl;
464 }
465 
466 static void startSearchMovie(void)
467 {
469  auto *pl = new ProgLister(mainStack, plMovies, "", "");
470  if (pl->Create())
471  mainStack->AddScreen(pl);
472  else
473  delete pl;
474 }
475 
476 static void startSearchNew(void)
477 {
479  auto *pl = new ProgLister(mainStack, plNewListings, "", "");
480  if (pl->Create())
481  mainStack->AddScreen(pl);
482  else
483  delete pl;
484 }
485 
486 static void startSearchTime(void)
487 {
489  auto *pl = new ProgLister(mainStack, plTime, "", "");
490  if (pl->Create())
491  mainStack->AddScreen(pl);
492  else
493  delete pl;
494 }
495 
496 static void startManaged(void)
497 {
499 
500  auto *viewsched = new ViewScheduled(mainStack);
501 
502  if (viewsched->Create())
503  mainStack->AddScreen(viewsched);
504  else
505  delete viewsched;
506 }
507 
508 static void startManageRecordingRules(void)
509 {
511 
512  auto *progRecPrior = new ProgramRecPriority(mainStack, "ManageRecRules");
513 
514  if (progRecPrior->Create())
515  mainStack->AddScreen(progRecPrior);
516  else
517  delete progRecPrior;
518 }
519 
520 static void startChannelRecPriorities(void)
521 {
523 
524  auto *chanRecPrior = new ChannelRecPriority(mainStack);
525 
526  if (chanRecPrior->Create())
527  mainStack->AddScreen(chanRecPrior);
528  else
529  delete chanRecPrior;
530 }
531 
532 static void startCustomPriority(void)
533 {
535 
536  auto *custom = new CustomPriority(mainStack);
537 
538  if (custom->Create())
539  mainStack->AddScreen(custom);
540  else
541  delete custom;
542 }
543 
544 static void startPlaybackWithGroup(const QString& recGroup = "")
545 {
547 
548  auto *pbb = new PlaybackBox(mainStack, "playbackbox");
549 
550  if (pbb->Create())
551  {
552  if (!recGroup.isEmpty())
553  pbb->setInitialRecGroup(recGroup);
554 
555  mainStack->AddScreen(pbb);
556  }
557  else
558  delete pbb;
559 }
560 
561 static void startPlayback(void)
562 {
564 }
565 
566 static void startPrevious(void)
567 {
569  auto *pl = new PrevRecordedList(mainStack);
570  if (pl->Create())
571  mainStack->AddScreen(pl);
572  else
573  delete pl;
574 }
575 
576 static void startPreviousOld(void)
577 {
579  auto *pl = new ProgLister(mainStack);
580  if (pl->Create())
581  mainStack->AddScreen(pl);
582  else
583  delete pl;
584 }
585 
586 static void startCustomEdit(void)
587 {
589  auto *custom = new CustomEdit(mainStack);
590 
591  if (custom->Create())
592  mainStack->AddScreen(custom);
593  else
594  delete custom;
595 }
596 
597 static void startManualSchedule(void)
598 {
600 
601  auto *mansched= new ManualSchedule(mainStack);
602 
603  if (mansched->Create())
604  mainStack->AddScreen(mansched);
605  else
606  delete mansched;
607 }
608 
609 static bool isLiveTVAvailable(void)
610 {
611  if (RemoteGetFreeRecorderCount() > 0)
612  return true;
613 
614  QString msg = qApp->translate("(Common)", "All tuners are currently busy.");
615 
616  if (TV::ConfiguredTunerCards() < 1)
617  msg = qApp->translate("(Common)", "There are no configured tuners.");
618 
619  ShowOkPopup(msg);
620  return false;
621 }
622 
623 static void startTVNormal(void)
624 {
625  if (!isLiveTVAvailable())
626  return;
627 
628  // Get the default channel keys (callsign(0) and channum(1)) and
629  // use them to generate the ordered list of channels.
630  QStringList keylist = gCoreContext->GetSettingOnHost(
631  "DefaultChanKeys", gCoreContext->GetHostName()).split("[]:[]");
632  while (keylist.size() < 2)
633  keylist << "";
634  uint dummy = 0;
636  0, // startIndex
637  0, // count
638  dummy, // totalAvailable
639  true, // ignoreHidden
642  0, // sourceID
643  0, // channelGroupID
644  true, // liveTVOnly
645  keylist[0], // callsign
646  keylist[1]); // channum
647 
648  TV::StartTV(nullptr, kStartTVNoFlags, livetvchannels);
649 }
650 
651 static void showStatus(void)
652 {
654 
655  auto *statusbox = new StatusBox(mainStack);
656 
657  if (statusbox->Create())
658  mainStack->AddScreen(statusbox);
659  else
660  delete statusbox;
661 }
662 
663 
664 static void standbyScreen(void)
665 {
667 
668  auto *idlescreen = new IdleScreen(mainStack);
669 
670  if (idlescreen->Create())
671  mainStack->AddScreen(idlescreen);
672  else
673  delete idlescreen;
674 }
675 
676 static void RunVideoScreen(VideoDialog::DialogType type, bool fromJump = false)
677 {
678  QString message = qApp->translate("(MythFrontendMain)",
679  "Loading videos ...");
680 
681  MythScreenStack *popupStack =
682  GetMythMainWindow()->GetStack("popup stack");
683 
684  auto *busyPopup = new MythUIBusyDialog(message, popupStack,
685  "mythvideobusydialog");
686 
687  if (busyPopup->Create())
688  popupStack->AddScreen(busyPopup, false);
689 
691 
692  VideoDialog::VideoListPtr video_list;
693  if (fromJump)
694  {
697  if (!saved.isNull())
698  {
699  video_list = saved->GetSaved();
700  LOG(VB_GENERAL, LOG_INFO,
701  QString("Reusing saved video list because MythVideo was resumed"
702  " within %1ms").arg(VideoListDeathDelay::kDelayTimeMS));
703  }
704  }
705 
706  VideoDialog::BrowseType browse = static_cast<VideoDialog::BrowseType>(
707  gCoreContext->GetNumSetting("mythvideo.db_group_type",
709 
710  if (!video_list)
711  video_list = new VideoList;
712 
713  auto *mythvideo =
714  new VideoDialog(mainStack, "mythvideo", video_list, type, browse);
715 
716  if (mythvideo->Create())
717  {
718  busyPopup->Close();
719  mainStack->AddScreen(mythvideo);
720  }
721  else
722  busyPopup->Close();
723 }
724 
730 
731 static void RunGallery()
732 {
734  auto *galleryView = new GalleryThumbView(mainStack, "galleryview");
735  if (galleryView->Create())
736  {
737  mainStack->AddScreen(galleryView);
738  galleryView->Start();
739  }
740  else
741  {
742  delete galleryView;
743  }
744 }
745 
746 static void playDisc()
747 {
748  //
749  // Get the command string to play a DVD
750  //
751 
752  bool isBD = false;
753 
754  QString command_string =
755  gCoreContext->GetSetting("mythdvd.DVDPlayerCommand");
756  QString bluray_mountpoint =
757  gCoreContext->GetSetting("BluRayMountpoint", "/media/cdrom");
758  QDir bdtest(bluray_mountpoint + "/BDMV");
759 
760  if (bdtest.exists() || MythCDROM::inspectImage(bluray_mountpoint) == MythCDROM::kBluray)
761  isBD = true;
762 
763  if (isBD)
764  {
765  GetMythUI()->AddCurrentLocation("playdisc");
766 
767  QString filename = QString("bd:/%1").arg(bluray_mountpoint);
768 
769  GetMythMainWindow()->HandleMedia("Internal", filename, "", "", "", "",
770  0, 0, "", 0, "", "", true);
771 
773  }
774  else
775  {
776  QString dvd_device = MediaMonitor::defaultDVDdevice();
777 
778  if (dvd_device.isEmpty())
779  return; // User cancelled in the Popup
780 
781  GetMythUI()->AddCurrentLocation("playdisc");
782 
783  if ((command_string.indexOf("internal", 0, Qt::CaseInsensitive) > -1) ||
784  (command_string.length() < 1))
785  {
786 #ifdef Q_OS_MAC
787  // Convert a BSD 'leaf' name into a raw device path
788  QString filename = "dvd://dev/r"; // e.g. 'dvd://dev/rdisk2'
789 #elif _WIN32
790  QString filename = "dvd:"; // e.g. 'dvd:E\\'
791 #else
792  QString filename = "dvd:/"; // e.g. 'dvd://dev/sda'
793 #endif
794  filename += dvd_device;
795 
796  command_string = "Internal";
797  GetMythMainWindow()->HandleMedia(command_string, filename, "", "",
798  "", "", 0, 0, "", 0, "", "", true);
800 
801  return;
802  }
803 
804  if (command_string.contains("%d"))
805  {
806  //
807  // Need to do device substitution
808  //
809  command_string =
810  command_string.replace(QRegExp("%d"), dvd_device);
811  }
814  myth_system(command_string);
817  if (GetMythMainWindow())
818  {
819  GetMythMainWindow()->raise();
820  GetMythMainWindow()->activateWindow();
821  }
823  }
824 }
825 
830 {
831  if (!dvd)
832  return;
833 
834  if (!dvd->isUsable()) // This isn't infallible, on some drives both a mount and libudf fail
835  return;
836 
837  switch (gCoreContext->GetNumSetting("DVDOnInsertDVD", 1))
838  {
839  case 0 : // Do nothing
840  case 1 : // Display menu (mythdvd)*/
841  break;
842  case 2 : // play DVD or Blu-ray
843  playDisc();
844  break;
845  default:
846  LOG(VB_GENERAL, LOG_ERR,
847  "mythdvd main.o: handleMedia() does not know what to do");
848  }
849 }
850 
852 {
853  // Only handle events for media that are newly mounted
854  if (!dev || (dev->getStatus() != MEDIASTAT_MOUNTED
855  && dev->getStatus() != MEDIASTAT_USEABLE))
856  return;
857 
858  // Check if gallery is already running
859  QVector<MythScreenType*> screens;
861 
862 
863  foreach (auto screen, screens)
864  {
865  if (dynamic_cast<GalleryThumbView*>(screen))
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  GetMythMainWindow()->Init();
1412 
1413  return RunMenu(themedir, themename);
1414 }
1415 
1416 static int reloadTheme(void)
1417 {
1418 
1419 #ifdef Q_OS_ANDROID
1420 
1421  // jni code to launch the application again
1422  // reinitializing the main windows causes a segfault
1423  // with android
1424 
1425  auto activity = QtAndroid::androidActivity();
1426  auto packageManager = activity.callObjectMethod
1427  ( "getPackageManager",
1428  "()Landroid/content/pm/PackageManager;" );
1429 
1430  auto activityIntent = packageManager.callObjectMethod
1431  ( "getLaunchIntentForPackage",
1432  "(Ljava/lang/String;)Landroid/content/Intent;",
1433  activity.callObjectMethod("getPackageName",
1434  "()Ljava/lang/String;").object() );
1435 
1436  auto pendingIntent = QAndroidJniObject::callStaticObjectMethod
1437  ( "android/app/PendingIntent",
1438  "getActivity",
1439  "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;",
1440  activity.object(),
1441  0,
1442  activityIntent.object(),
1443  QAndroidJniObject::getStaticField<jint>("android/content/Intent",
1444  "FLAG_ACTIVITY_CLEAR_TOP") );
1445 
1446  auto alarmManager = activity.callObjectMethod
1447  ( "getSystemService",
1448  "(Ljava/lang/String;)Ljava/lang/Object;",
1449  QAndroidJniObject::getStaticObjectField("android/content/Context",
1450  "ALARM_SERVICE",
1451  "Ljava/lang/String;").object() );
1452 
1453  alarmManager.callMethod<void>
1454  ( "set",
1455  "(IJLandroid/app/PendingIntent;)V",
1456  QAndroidJniObject::getStaticField<jint>("android/app/AlarmManager", "RTC"),
1457  jlong(QDateTime::currentMSecsSinceEpoch() + 100),
1458  pendingIntent.object() );
1459 
1460  qApp->quit();
1461  // QString title = QObject::tr("Your change will take effect the next time "
1462  // "mythfrontend is started.");
1463  // MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); MythConfirmationDialog *okPopup =
1464  // new MythConfirmationDialog(popupStack, title, false);
1465  // if (okPopup->Create())
1466  // popupStack->AddScreen(okPopup);
1467  return 0;
1468 #else
1469 
1470  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
1471  QString themedir = GetMythUI()->FindThemeDir(themename);
1472  if (themedir.isEmpty())
1473  {
1474  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
1475  .arg(themename));
1476  return GENERIC_EXIT_NO_THEME;
1477  }
1478 
1481 
1483  GetMythUI()->LoadQtConfig();
1484  if (g_menu)
1485  g_menu->Close();
1486  GetMythMainWindow()->Init();
1489 
1490  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
1491  return GENERIC_EXIT_NO_THEME;
1492 
1493  LCD::SetupLCD();
1494  if (LCD *lcd = LCD::Get())
1495  {
1496  lcd->setupLEDs(RemoteGetRecordingMask);
1497  lcd->resetServer();
1498  }
1499 
1500  return 0;
1501 #endif // Q_OS_ANDROID else
1502 }
1503 
1504 static void reloadTheme_void(void)
1505 {
1506  int err = reloadTheme();
1507  if (err)
1508  exit(err);
1509 }
1510 
1511 static void setDebugShowBorders(void)
1512 {
1514  p->SetDebugMode(!p->ShowBorders(), p->ShowTypeNames());
1515 
1518 }
1519 
1520 static void setDebugShowNames(void)
1521 {
1523  p->SetDebugMode(p->ShowBorders(), !p->ShowTypeNames());
1524 
1527 }
1528 
1529 static void InitJumpPoints(void)
1530 {
1531  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Reload Theme"),
1532  "", "", reloadTheme_void);
1533  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Main Menu"),
1534  "", "", gotoMainMenu);
1535  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Guide"),
1536  "", "", startGuide, "GUIDE");
1537  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Finder"),
1538  "", "", startFinder, "FINDER");
1539  //REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Search Listings"),
1540  // "", "", startSearch);
1541  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Manage Recordings / "
1542  "Fix Conflicts"), "", "", startManaged, "VIEWSCHEDULED");
1543  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Manage Recording Rules"),
1544  "", "", startManageRecordingRules);
1545  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Channel Recording "
1546  "Priorities"), "", "", startChannelRecPriorities);
1547  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "TV Recording Playback"),
1548  "", "", startPlayback, "JUMPREC");
1549  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Live TV"),
1550  "", "", startTVNormal);
1551  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Status Screen"),
1552  "", "", showStatus);
1553  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Previously Recorded"),
1554  "", "", startPrevious);
1555 
1556  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Standby Mode"),
1557  "", "", standbyScreen);
1558 
1559  // Video
1560 
1561  REG_JUMP(JUMP_VIDEO_DEFAULT, QT_TRANSLATE_NOOP("MythControls",
1562  "The Video Default View"), "", jumpScreenVideoDefault);
1563  REG_JUMP(JUMP_VIDEO_MANAGER, QT_TRANSLATE_NOOP("MythControls",
1564  "The Video Manager"), "", jumpScreenVideoManager);
1565  REG_JUMP(JUMP_VIDEO_BROWSER, QT_TRANSLATE_NOOP("MythControls",
1566  "The Video Browser"), "", jumpScreenVideoBrowser);
1567  REG_JUMP(JUMP_VIDEO_TREE, QT_TRANSLATE_NOOP("MythControls",
1568  "The Video Listings"), "", jumpScreenVideoTree);
1569  REG_JUMP(JUMP_VIDEO_GALLERY, QT_TRANSLATE_NOOP("MythControls",
1570  "The Video Gallery"), "", jumpScreenVideoGallery);
1571  REG_JUMP("Play Disc", QT_TRANSLATE_NOOP("MythControls",
1572  "Play an Optical Disc"), "", playDisc);
1573 
1574  // Gallery
1575 
1576  REG_JUMP(JUMP_GALLERY_DEFAULT, QT_TRANSLATE_NOOP("MythControls",
1577  "Image Gallery"), "", RunGallery);
1578 
1579  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Borders"),
1580  "", "", setDebugShowBorders, false);
1581  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Names"),
1582  "", "", setDebugShowNames, false);
1583  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Reset All Keys"),
1584  QT_TRANSLATE_NOOP("MythControls", "Reset all keys to defaults"),
1585  "", resetAllKeys, false);
1586 }
1587 
1588 static void ReloadJumpPoints(void)
1589 {
1590  MythMainWindow *mainWindow = GetMythMainWindow();
1591  mainWindow->ClearAllJumps();
1592  InitJumpPoints();
1593 }
1594 
1595 static void InitKeys(void)
1596 {
1597  REG_KEY("Video","PLAYALT", QT_TRANSLATE_NOOP("MythControls",
1598  "Play selected item in alternate player"), "ALT+P");
1599  REG_KEY("Video","FILTER", QT_TRANSLATE_NOOP("MythControls",
1600  "Open video filter dialog"), "F");
1601  REG_KEY("Video","INCPARENT", QT_TRANSLATE_NOOP("MythControls",
1602  "Increase Parental Level"), "],},F11");
1603  REG_KEY("Video","DECPARENT", QT_TRANSLATE_NOOP("MythControls",
1604  "Decrease Parental Level"), "[,{,F10");
1605  REG_KEY("Video","INCSEARCH", QT_TRANSLATE_NOOP("MythControls",
1606  "Show Incremental Search Dialog"), "Ctrl+S");
1607  REG_KEY("Video","DOWNLOADDATA", QT_TRANSLATE_NOOP("MythControls",
1608  "Download metadata for current item"), "W");
1609  REG_KEY("Video","ITEMDETAIL", QT_TRANSLATE_NOOP("MythControls",
1610  "Display Item Detail Popup"), "");
1611 
1612  // Gallery keybindings
1613  REG_KEY("Images", "PLAY", QT_TRANSLATE_NOOP("MythControls",
1614  "Start/Stop Slideshow"), "P");
1615  REG_KEY("Images", "RECURSIVESHOW", QT_TRANSLATE_NOOP("MythControls",
1616  "Start Recursive Slideshow"), "R");
1617  REG_KEY("Images", "ROTRIGHT", QT_TRANSLATE_NOOP("MythControls",
1618  "Rotate image right 90 degrees"), "],3");
1619  REG_KEY("Images", "ROTLEFT", QT_TRANSLATE_NOOP("MythControls",
1620  "Rotate image left 90 degrees"), "[,1");
1621  REG_KEY("Images", "FLIPHORIZONTAL", QT_TRANSLATE_NOOP("MythControls",
1622  "Flip image horizontally"), "");
1623  REG_KEY("Images", "FLIPVERTICAL", QT_TRANSLATE_NOOP("MythControls",
1624  "Flip image vertically"), "");
1625  REG_KEY("Images", "ZOOMOUT", QT_TRANSLATE_NOOP("MythControls",
1626  "Zoom image out"), "7");
1627  REG_KEY("Images", "ZOOMIN", QT_TRANSLATE_NOOP("MythControls",
1628  "Zoom image in"), "9");
1629  REG_KEY("Images", "FULLSIZE", QT_TRANSLATE_NOOP("MythControls",
1630  "Full-size (un-zoom) image"), "0");
1631  REG_KEY("Images", "MARK", QT_TRANSLATE_NOOP("MythControls",
1632  "Mark image"), "T");
1633  REG_KEY("Images", "SCROLLUP", QT_TRANSLATE_NOOP("MythControls",
1634  "Scroll image up"), "2");
1635  REG_KEY("Images", "SCROLLLEFT", QT_TRANSLATE_NOOP("MythControls",
1636  "Scroll image left"), "4");
1637  REG_KEY("Images", "SCROLLRIGHT", QT_TRANSLATE_NOOP("MythControls",
1638  "Scroll image right"), "6");
1639  REG_KEY("Images", "SCROLLDOWN", QT_TRANSLATE_NOOP("MythControls",
1640  "Scroll image down"), "8");
1641  REG_KEY("Images", "RECENTER", QT_TRANSLATE_NOOP("MythControls",
1642  "Recenter image"), "5");
1643  REG_KEY("Images", "COVER", QT_TRANSLATE_NOOP("MythControls",
1644  "Set or clear cover image"), "C");
1645 }
1646 
1647 static void ReloadKeys(void)
1648 {
1649  GetMythMainWindow()->ClearKeyContext("Video");
1650  InitKeys();
1651 
1652  TV::ReloadKeys();
1653 }
1654 
1655 static void SetFuncPtrs(void)
1656 {
1657  TV::SetFuncPtr("playbackbox", (void *)PlaybackBox::RunPlaybackBox);
1658  TV::SetFuncPtr("viewscheduled", (void *)ViewScheduled::RunViewScheduled);
1659  TV::SetFuncPtr("programguide", (void *)GuideGrid::RunProgramGuide);
1660  TV::SetFuncPtr("programfinder", (void *)RunProgramFinder);
1661  TV::SetFuncPtr("scheduleeditor", (void *)ScheduleEditor::RunScheduleEditor);
1662 }
1663 
1667 static void clearAllKeys(void)
1668 {
1669  MSqlQuery query(MSqlQuery::InitCon());
1670 
1671  query.prepare("DELETE FROM keybindings "
1672  "WHERE hostname = :HOSTNAME;");
1673  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1674  if (!query.exec())
1675  MythDB::DBError("Deleting keybindings", query);
1676  query.prepare("DELETE FROM jumppoints "
1677  "WHERE hostname = :HOSTNAME;");
1678  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1679  if (!query.exec())
1680  MythDB::DBError("Deleting jumppoints", query);
1681 }
1682 
1686 static void resetAllKeys(void)
1687 {
1688  clearAllKeys();
1689  // Reload MythMainWindow bindings
1691  // Reload Jump Points
1692  ReloadJumpPoints();
1693  // Reload mythfrontend and TV bindings
1694  ReloadKeys();
1695 }
1696 
1698 {
1699  REG_MEDIAPLAYER("Internal", QT_TRANSLATE_NOOP("MythControls",
1700  "MythTV's native media player."), internal_play_media);
1701  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1702  "MythDVD DVD Media Handler"), "", handleDVDMedia,
1703  MEDIATYPE_DVD, QString());
1704  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1705  "MythImage Media Handler 1/2"), "", handleGalleryMedia,
1706  MEDIATYPE_DATA | MEDIATYPE_MIXED, QString());
1707 
1708  QStringList extensions(ImageAdapterBase::SupportedImages()
1710 
1711  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1712  "MythImage Media Handler 2/2"), "", handleGalleryMedia,
1713  MEDIATYPE_MGALLERY | MEDIATYPE_MVIDEO, extensions.join(","));
1714  return 0;
1715 }
1716 
1717 static void CleanupMyOldInUsePrograms(void)
1718 {
1719  MSqlQuery query(MSqlQuery::InitCon());
1720 
1721  query.prepare("DELETE FROM inuseprograms "
1722  "WHERE hostname = :HOSTNAME and recusage = 'player' ;");
1723  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1724  if (!query.exec())
1725  MythDB::DBError("CleanupMyOldInUsePrograms", query);
1726 }
1727 
1728 static bool WasAutomaticStart(void)
1729 {
1730  bool autoStart = false;
1731 
1732  // Is backend running?
1733  //
1735  {
1736  QDateTime startupTime = QDateTime();
1737 
1738  if( gCoreContext->IsMasterHost() )
1739  {
1740  QString s = gCoreContext->GetSetting("MythShutdownWakeupTime", "");
1741  if (s.length())
1742  startupTime = MythDate::fromString(s);
1743 
1744  // if we don't have a valid startup time assume we were started manually
1745  if (startupTime.isValid())
1746  {
1747  int startupSecs = gCoreContext->GetNumSetting("StartupSecsBeforeRecording");
1748  // If we started within 'StartupSecsBeforeRecording' OR 15 minutes
1749  // of the saved wakeup time assume we either started automatically
1750  // to record, to obtain guide data or or for a
1751  // daily wakeup/shutdown period
1752  if (abs(startupTime.secsTo(MythDate::current())) <
1753  max(startupSecs, 15 * 60))
1754  {
1755  LOG(VB_GENERAL, LOG_INFO,
1756  "Close to auto-start time, AUTO-Startup assumed");
1757 
1758  QString str = gCoreContext->GetSetting("MythFillSuggestedRunTime");
1759  QDateTime guideRunTime = MythDate::fromString(str);
1760  if (guideRunTime.secsTo(MythDate::current()) <
1761  max(startupSecs, 15 * 60))
1762  {
1763  LOG(VB_GENERAL, LOG_INFO,
1764  "Close to MythFillDB suggested run time, AUTO-Startup to fetch guide data?");
1765  }
1766  autoStart = true;
1767  }
1768  else
1769  LOG(VB_GENERAL, LOG_DEBUG,
1770  "NOT close to auto-start time, USER-initiated startup assumed");
1771  }
1772  }
1773  else
1774  {
1775  QString wakeupCmd = gCoreContext->GetSetting("WakeUpCommand");
1776 
1777  // A slave backend that has no wakeup command cannot be woken
1778  // automatically so can be ignored.
1779  if (!wakeupCmd.isEmpty())
1780  {
1781  ProgramList progList;
1782  bool bConflicts = false;
1783  QDateTime nextRecordingStart;
1784 
1785  if (LoadFromScheduler(progList, bConflicts))
1786  {
1787  // Find the first recording to be recorded
1788  // on this machine
1789  QString hostname = gCoreContext->GetHostName();
1790  for (auto prog : progList)
1791  {
1792  if ((prog->GetRecordingStatus() == RecStatus::WillRecord ||
1793  prog->GetRecordingStatus() == RecStatus::Pending) &&
1794  (prog->GetHostname() == hostname) &&
1795  (nextRecordingStart.isNull() ||
1796  nextRecordingStart > prog->GetRecordingStartTime()))
1797  {
1798  nextRecordingStart = prog->GetRecordingStartTime();
1799  }
1800  }
1801 
1802  if (!nextRecordingStart.isNull() &&
1803  (abs(nextRecordingStart.secsTo(MythDate::current())) < (4 * 60)))
1804  {
1805  LOG(VB_GENERAL, LOG_INFO,
1806  "Close to start time, AUTO-Startup assumed");
1807 
1808  // If we started within 4 minutes of the next recording,
1809  // we almost certainly started automatically.
1810  autoStart = true;
1811  }
1812  else
1813  LOG(VB_GENERAL, LOG_DEBUG,
1814  "NOT close to auto-start time, USER-initiated startup assumed");
1815 
1816  }
1817  }
1818  }
1819  }
1820 
1821  return autoStart;
1822 }
1823 
1824 // from https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=16897
1825 // The old way of revoking root with setuid(getuid())
1826 // causes system hang in certain cases on raspberry pi
1827 
1828 static int revokeRoot (void)
1829 {
1830  if (getuid () == 0 && geteuid () == 0) // Really running as root
1831  return 0;
1832 
1833  if (geteuid () == 0) // Running setuid root
1834  return seteuid (getuid ()) ; // Change effective uid to the uid of the caller
1835  return 0;
1836 }
1837 
1838 
1839 int main(int argc, char **argv)
1840 {
1841  bool bPromptForBackend = false;
1842  bool bBypassAutoDiscovery = false;
1843 
1845  if (!cmdline.Parse(argc, argv))
1846  {
1847  cmdline.PrintHelp();
1849  }
1850 
1851  if (cmdline.toBool("showhelp"))
1852  {
1853  cmdline.PrintHelp();
1854  return GENERIC_EXIT_OK;
1855  }
1856 
1857  if (cmdline.toBool("showversion"))
1858  {
1860  return GENERIC_EXIT_OK;
1861  }
1862 
1863  CleanupGuard callCleanup(cleanup);
1864 
1865  // Set the default surface format. Explicitly required on some platforms.
1866  QSurfaceFormat format;
1867  format.setDepthBufferSize(0);
1868  format.setStencilBufferSize(0);
1869  format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
1870  format.setProfile(QSurfaceFormat::CompatibilityProfile);
1871  format.setSwapInterval(1);
1872  QSurfaceFormat::setDefaultFormat(format);
1873 
1874 #ifdef Q_OS_MAC
1875  // Without this, we can't set focus to any of the CheckBoxSetting, and most
1876  // of the MythPushButton widgets, and they don't use the themed background.
1877  QApplication::setDesktopSettingsAware(false);
1878 #endif
1879 #if defined (Q_OS_LINUX)
1880 #if defined (USING_VAAPI) || defined (USING_MMAL)
1881  // When using VAAPI (linux/desktop only) we want to use EGL to ensure we
1882  // can use zero copy video buffers for the best performance (N.B. not tested
1883  // on AMD desktops). For non-VAAPI users this should make no difference - on NVidia
1884  // installations it has no effect.
1885  // Likewise for MMAL (Raspberry Pi), we want EGL for zero copy direct rendering.
1886  // This is the only way to force Qt to use EGL and must be done before any
1887  // GUI is created.
1888  // If problems are encountered, set the environment variable NO_EGL
1889 
1890  // Disabled this for now as it does actually break NVidia desktops
1891  //if (qgetenv("NO_EGL").isEmpty())
1892  // setenv("QT_XCB_GL_INTEGRATION", "xcb_egl", 0);
1893 
1894  // This makes Xlib calls thread-safe which seems to be required for hardware
1895  // accelerated Flash playback to work without causing mythfrontend to abort.
1896  QApplication::setAttribute(Qt::AA_X11InitThreads);
1897 #endif
1898 #endif
1899 #ifdef Q_OS_ANDROID
1900  //QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
1901 #endif
1902 
1903 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
1904  // Ignore desktop scaling
1905  QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
1906 #endif
1907 
1908  QApplication::setSetuidAllowed(true);
1909  new QApplication(argc, argv);
1910  QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHFRONTEND);
1911 
1912 
1913 #ifdef Q_OS_MAC
1914  QString path = QCoreApplication::applicationDirPath();
1915  setenv("PYTHONPATH",
1916  QString("%1/../Resources/lib/python2.6/site-packages:%2")
1917  .arg(path)
1918  .arg(QProcessEnvironment::systemEnvironment().value("PYTHONPATH"))
1919  .toUtf8().constData(), 1);
1920 #endif
1921 
1922 #ifndef _WIN32
1923  QList<int> signallist;
1924  signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
1925  << SIGILL;
1926 #if ! CONFIG_DARWIN
1927  signallist << SIGRTMIN;
1928 #endif
1929  SignalHandler::Init(signallist);
1932  SignalHandler::SetHandler(SIGHUP, logSigHup);
1933 #endif
1934 
1935  int retval = cmdline.ConfigureLogging();
1936  if (retval != GENERIC_EXIT_OK)
1937  return retval;
1938 
1939  bool ResetSettings = false;
1940 
1941  if (cmdline.toBool("prompt"))
1942  bPromptForBackend = true;
1943  if (cmdline.toBool("noautodiscovery"))
1944  bBypassAutoDiscovery = true;
1945 
1946  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1947  cerr << "Unable to ignore SIGPIPE\n";
1948 
1949  if (!cmdline.toString("display").isEmpty())
1950  {
1952  }
1953 
1954  if (!cmdline.toString("geometry").isEmpty())
1955  {
1957  }
1958 
1959  fe_sd_notify("STATUS=Connecting to database.");
1961  gCoreContext->SetAsFrontend(true);
1962 
1964  if (!gContext->Init(true, bPromptForBackend, bBypassAutoDiscovery))
1965  {
1966  LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
1967  gCoreContext->SetExiting(true);
1969  }
1970 
1972 
1973  if (!GetMythDB()->HaveSchema())
1974  {
1975  if (!InitializeMythSchema())
1976  return GENERIC_EXIT_DB_ERROR;
1977  }
1978 
1979  if (cmdline.toBool("reset"))
1980  ResetSettings = true;
1981 
1982  if (!cmdline.toBool("noupnp"))
1983  {
1984  fe_sd_notify("STATUS=Creating UPnP media renderer");
1985  g_pUPnp = new MediaRenderer();
1986  if (!g_pUPnp->isInitialized())
1987  {
1988  delete g_pUPnp;
1989  g_pUPnp = nullptr;
1990  }
1991  }
1992 
1993  QString fileprefix = GetConfDir();
1994 
1995  QDir dir(fileprefix);
1996  if (!dir.exists())
1997  dir.mkdir(fileprefix);
1998 
1999  if (ResetSettings)
2000  {
2001  AppearanceSettings as;
2002  as.Save();
2003 
2005  gCoreContext->GetDB()->ClearSetting("Language");
2006  gCoreContext->GetDB()->ClearSettingOnHost("Language", nullptr);
2007  gCoreContext->GetDB()->ClearSetting("Country");
2008  gCoreContext->GetDB()->ClearSettingOnHost("Country", nullptr);
2009 
2010  LOG(VB_GENERAL, LOG_NOTICE, "Appearance settings and language have "
2011  "been reset to defaults. You will need to "
2012  "restart the frontend.");
2013  gContext-> saveSettingsCache();
2014  return GENERIC_EXIT_OK;
2015  }
2016 
2017  qApp->setSetuidAllowed(true);
2018 
2019  if (revokeRoot() != 0)
2020  {
2021  LOG(VB_GENERAL, LOG_ERR, "Failed to revokeRoot(), exiting.");
2022  return GENERIC_EXIT_NOT_OK;
2023  }
2024 
2025 #ifdef USING_LIBDNS_SD
2026  // this needs to come after gCoreContext has been initialised
2027  // (for hostname) - hence it is not in MediaRenderer
2028  QScopedPointer<BonjourRegister> bonjour(new BonjourRegister());
2029  if (bonjour.data())
2030  {
2031  fe_sd_notify("STATUS=Registering frontend with bonjour");
2032  QByteArray dummy;
2033  int port = gCoreContext->GetNumSetting("UPnP/MythFrontend/ServicePort", 6547);
2034  QByteArray name("Mythfrontend on ");
2035  name.append(gCoreContext->GetHostName());
2036  bonjour->Register(port, "_mythfrontend._tcp",
2037  name, dummy);
2038  }
2039 #endif
2040 
2041  fe_sd_notify("STATUS=Initializing LCD");
2042  LCD::SetupLCD();
2043  if (LCD *lcd = LCD::Get())
2044  lcd->setupLEDs(RemoteGetRecordingMask);
2045 
2046  fe_sd_notify("STATUS=Loading translation");
2047  MythTranslation::load("mythfrontend");
2048 
2049  fe_sd_notify("STATUS=Loading themes");
2050  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
2051 
2052  QString themedir = GetMythUI()->FindThemeDir(themename);
2053  if (themedir.isEmpty())
2054  {
2055  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
2056  .arg(themename));
2057  return GENERIC_EXIT_NO_THEME;
2058  }
2059 
2060  GetMythUI()->LoadQtConfig();
2061 
2062  themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
2063  themedir = GetMythUI()->FindThemeDir(themename);
2064  if (themedir.isEmpty())
2065  {
2066  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
2067  .arg(themename));
2068  return GENERIC_EXIT_NO_THEME;
2069  }
2070 
2071  MythMainWindow *mainWindow = GetMythMainWindow();
2072  mainWindow->Init(false);
2073  mainWindow->setWindowTitle(qApp->translate("(MythFrontendMain)",
2074  "MythTV Frontend",
2075  "Main window title"));
2076 
2077 #ifdef USING_AIRPLAY
2078  if (gCoreContext->GetBoolSetting("AirPlayEnabled", true))
2079  {
2080  fe_sd_notify("STATUS=Initializing AirPlay");
2082  if (!gCoreContext->GetBoolSetting("AirPlayAudioOnly", false))
2083  {
2085  }
2086  }
2087 #endif
2088 
2089  // We must reload the translation after a language change and this
2090  // also means clearing the cached/loaded theme strings, so reload the
2091  // theme which also triggers a translation reload
2093  {
2094  if (!reloadTheme())
2095  return GENERIC_EXIT_NO_THEME;
2096  }
2097 
2098  if (!UpgradeTVDatabaseSchema(false, false, true))
2099  {
2100  LOG(VB_GENERAL, LOG_ERR,
2101  "Couldn't upgrade database to new schema, exiting.");
2103  }
2104 
2105  WriteDefaults();
2106 
2107  // Refresh Global/Main Menu keys after DB update in case there was no DB
2108  // when they were written originally
2109  mainWindow->ReloadKeys();
2110 
2111  fe_sd_notify("STATUS=Initializing jump points");
2112  InitJumpPoints();
2113  InitKeys();
2114  TV::InitKeys();
2115  SetFuncPtrs();
2116 
2118 
2120 
2121  setHttpProxy();
2122 
2123  fe_sd_notify("STATUS=Initializing plugins");
2124  g_pmanager = new MythPluginManager();
2126 
2127  fe_sd_notify("STATUS=Initializing media monitor");
2129  if (mon)
2130  {
2131  mon->StartMonitoring();
2132  mainWindow->installEventFilter(mon);
2133  }
2134 
2135  fe_sd_notify("STATUS=Initializing network control");
2136  NetworkControl *networkControl = nullptr;
2137  if (gCoreContext->GetBoolSetting("NetworkControlEnabled", false))
2138  {
2139  int port = gCoreContext->GetNumSetting("NetworkControlPort", 6546);
2140  networkControl = new NetworkControl();
2141  if (!networkControl->listen(port))
2142  {
2143  LOG(VB_GENERAL, LOG_ERR,
2144  QString("NetworkControl failed to bind to port %1.")
2145  .arg(port));
2146  }
2147  }
2148 
2149 #if CONFIG_DARWIN
2151  GetMythMainWindow()->Init();
2154  gLoaded = true;
2155 #endif
2156  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
2157  {
2158  return GENERIC_EXIT_NO_THEME;
2159  }
2160  fe_sd_notify("STATUS=Loading theme updates");
2161  ThemeUpdateChecker *themeUpdateChecker = nullptr;
2162  if (gCoreContext->GetBoolSetting("ThemeUpdateNofications", true))
2163  themeUpdateChecker = new ThemeUpdateChecker();
2164 
2166 
2168 
2170  PreviewGenerator::kRemote, 50, 60);
2171 
2172  fe_sd_notify("STATUS=Creating housekeeper");
2173  auto *housekeeping = new HouseKeeper();
2174 #ifdef __linux__
2175  #ifdef CONFIG_BINDINGS_PYTHON
2177  #endif
2178 #endif
2179  housekeeping->Start();
2180 
2181 
2182  if (cmdline.toBool("runplugin"))
2183  {
2184  QStringList plugins = g_pmanager->EnumeratePlugins();
2185 
2186  if (plugins.contains(cmdline.toString("runplugin")))
2187  g_pmanager->run_plugin(cmdline.toString("runplugin"));
2188  else if (plugins.contains("myth" + cmdline.toString("runplugin")))
2189  g_pmanager->run_plugin("myth" + cmdline.toString("runplugin"));
2190  else
2191  {
2192  LOG(VB_GENERAL, LOG_ERR,
2193  QString("Invalid plugin name supplied on command line: '%1'")
2194  .arg(cmdline.toString("runplugin")));
2195  LOG(VB_GENERAL, LOG_ERR,
2196  QString("Available plugins: %1")
2197  .arg(plugins.join(", ")));
2199  }
2200  }
2201  else if (cmdline.toBool("jumppoint"))
2202  {
2204 
2205  if (mmw->DestinationExists(cmdline.toString("jumppoint")))
2206  mmw->JumpTo(cmdline.toString("jumppoint"));
2207  else
2208  {
2209  LOG(VB_GENERAL, LOG_ERR,
2210  QString("Invalid jump point supplied on the command line: %1")
2211  .arg(cmdline.toString("jumppoint")));
2212  LOG(VB_GENERAL, LOG_ERR,
2213  QString("Available jump points: %2")
2214  .arg(mmw->EnumerateDestinations().join(", ")));
2216  }
2217  }
2218 
2219  if (WasAutomaticStart())
2220  {
2221  // We appear to have been started automatically
2222  // so enter standby so that the machine can
2223  // shutdown again as soon as possible if necessary.
2224  standbyScreen();
2225  }
2226 
2227  // Provide systemd ready notification (for type=notify units)
2228  fe_sd_notify("STATUS=");
2229  fe_sd_notify("READY=1");
2230 
2231  int ret = qApp->exec();
2232 
2233  fe_sd_notify("STOPPING=1\nSTATUS=Exiting");
2234  if (ret==0)
2235  gContext-> saveSettingsCache();
2236 
2237  DestroyMythUI();
2239 
2240  delete housekeeping;
2241  delete themeUpdateChecker;
2242  delete sysEventHandler;
2243 
2245 
2246  if (mon)
2247  mon->deleteLater();
2248 
2249  delete networkControl;
2250  return ret;
2251 }
2252 
2253 void handleSIGUSR1(void)
2254 {
2255  LOG(VB_GENERAL, LOG_INFO, "Reloading theme");
2256  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
2258  GetMythMainWindow()->JumpTo("Reload Theme");
2260 }
2261 
2262 void handleSIGUSR2(void)
2263 {
2264  LOG(VB_GENERAL, LOG_INFO, "Restarting LIRC handler");
2266 }
2267 
2268 #include "main.moc"
2269 /* 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: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
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 * RunPlaybackBox(void *player, bool showTV)
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: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:488
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: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)
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 * RunViewScheduled(void *player, bool showTv)
static void jumpScreenVideoBrowser()
static guint32 * tmp
Definition: goom_core.c:35
void DestroyMythUI()
#define REG_MEDIAPLAYER(a, b, c)
void ClearKeyContext(const QString &context)
static Type kEventType
Definition: mythdialogbox.h:56
#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
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
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: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: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()
#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: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 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="")
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 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: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
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:161
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16
static void startAppearWiz(void)
static bool isLiveTVAvailable(void)
void Start(void)