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 <QWidget>
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/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  StandardSettingDialog *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  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  MythDialogBox *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  {
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 pgi;
263  return;
264  }
265 
266  TV::StartTV(pgi, flags);
267 
268  delete pgi;
269  }
270  }
271  }
272 
273  private:
274  ProgramInfo* pgi {nullptr};
275  };
276 
277  void cleanup()
278  {
279  qApp->processEvents();
281 #ifdef USING_AIRPLAY
284 #endif
285 
286  delete g_exitPopup;
287  g_exitPopup = nullptr;
288 
290 
291  if (g_pUPnp)
292  {
293  // This takes a few seconds, so inform the user:
294  LOG(VB_GENERAL, LOG_INFO, "Shutting down UPnP client...");
295  delete g_pUPnp;
296  g_pUPnp = nullptr;
297  }
298 
299  if (g_pmanager)
300  {
301  delete g_pmanager;
302  g_pmanager = nullptr;
303  }
304 
305  if (g_settingsHelper)
306  {
307  delete g_settingsHelper;
308  g_settingsHelper = nullptr;
309  }
310 
311  delete gContext;
312  gContext = nullptr;
313 
315 
316  delete qApp;
317 
319  }
320 }
321 
322 static void startAppearWiz(void)
323 {
324  int curX = gCoreContext->GetNumSetting("GuiOffsetX", 0);
325  int curY = gCoreContext->GetNumSetting("GuiOffsetY", 0);
326  int curW = gCoreContext->GetNumSetting("GuiWidth", 0);
327  int curH = gCoreContext->GetNumSetting("GuiHeight", 0);
328 
329  bool isWindowed =
330  (gCoreContext->GetNumSetting("RunFrontendInWindow", 0) == 1);
331 
332  bool reload = false;
333 
334  if (isWindowed)
335  ShowOkPopup(qApp->translate("(MythFrontendMain)",
336  "The ScreenSetupWizard cannot be used while "
337  "mythfrontend is operating in windowed mode."));
338  else
339  {
340  MythSystemLegacy *wizard = new MythSystemLegacy(
341  GetAppBinDir() + "mythscreenwizard",
342  QStringList(),
344  wizard->Run();
345 
346  if (!wizard->Wait())
347  {
348  // no reported errors, check for changed geometry parameters
349  gCoreContext->ClearSettingsCache("GuiOffsetX");
350  gCoreContext->ClearSettingsCache("GuiOffsetY");
351  gCoreContext->ClearSettingsCache("GuiWidth");
352  gCoreContext->ClearSettingsCache("GuiHeight");
353 
354  if ((curX != gCoreContext->GetNumSetting("GuiOffsetX", 0)) ||
355  (curY != gCoreContext->GetNumSetting("GuiOffsetY", 0)) ||
356  (curW != gCoreContext->GetNumSetting("GuiWidth", 0)) ||
357  (curH != gCoreContext->GetNumSetting("GuiHeight", 0)))
358  reload = true;
359  }
360 
361  delete wizard;
362  wizard = nullptr;
363  }
364 
365  if (reload)
366  GetMythMainWindow()->JumpTo("Reload Theme");
367 }
368 
369 static void startKeysSetup()
370 {
372 
373  MythControls *mythcontrols = new MythControls(mainStack, "mythcontrols");
374 
375  if (mythcontrols->Create())
376  mainStack->AddScreen(mythcontrols);
377  else
378  delete mythcontrols;
379 }
380 
381 static void startGuide(void)
382 {
383  uint chanid = 0;
384  QString channum = gCoreContext->GetSetting("DefaultTVChannel");
385  QDateTime startTime;
386  GuideGrid::RunProgramGuide(chanid, channum, startTime, nullptr, false, true, -2);
387 }
388 
389 static void startFinder(void)
390 {
392 }
393 
394 static void startSearchTitle(void)
395 {
397  ProgLister *pl = new ProgLister(mainStack, plTitleSearch, "", "");
398  if (pl->Create())
399  mainStack->AddScreen(pl);
400  else
401  delete pl;
402 }
403 
404 static void startSearchKeyword(void)
405 {
407  ProgLister *pl = new ProgLister(mainStack, plKeywordSearch, "", "");
408  if (pl->Create())
409  mainStack->AddScreen(pl);
410  else
411  delete pl;
412 }
413 
414 static void startSearchPeople(void)
415 {
417  ProgLister *pl = new ProgLister(mainStack, plPeopleSearch, "", "");
418  if (pl->Create())
419  mainStack->AddScreen(pl);
420  else
421  delete pl;
422 }
423 
424 static void startSearchPower(void)
425 {
427  ProgLister *pl = new ProgLister(mainStack, plPowerSearch, "", "");
428  if (pl->Create())
429  mainStack->AddScreen(pl);
430  else
431  delete pl;
432 }
433 
434 static void startSearchStored(void)
435 {
437  ProgLister *pl = new ProgLister(mainStack, plStoredSearch, "", "");
438  if (pl->Create())
439  mainStack->AddScreen(pl);
440  else
441  delete pl;
442 }
443 
444 static void startSearchChannel(void)
445 {
447  ProgLister *pl = new ProgLister(mainStack, plChannel, "", "");
448  if (pl->Create())
449  mainStack->AddScreen(pl);
450  else
451  delete pl;
452 }
453 
454 static void startSearchCategory(void)
455 {
457  ProgLister *pl = new ProgLister(mainStack, plCategory, "", "");
458  if (pl->Create())
459  mainStack->AddScreen(pl);
460  else
461  delete pl;
462 }
463 
464 static void startSearchMovie(void)
465 {
467  ProgLister *pl = new ProgLister(mainStack, plMovies, "", "");
468  if (pl->Create())
469  mainStack->AddScreen(pl);
470  else
471  delete pl;
472 }
473 
474 static void startSearchNew(void)
475 {
477  ProgLister *pl = new ProgLister(mainStack, plNewListings, "", "");
478  if (pl->Create())
479  mainStack->AddScreen(pl);
480  else
481  delete pl;
482 }
483 
484 static void startSearchTime(void)
485 {
487  ProgLister *pl = new ProgLister(mainStack, plTime, "", "");
488  if (pl->Create())
489  mainStack->AddScreen(pl);
490  else
491  delete pl;
492 }
493 
494 static void startManaged(void)
495 {
497 
498  ViewScheduled *viewsched = new ViewScheduled(mainStack);
499 
500  if (viewsched->Create())
501  mainStack->AddScreen(viewsched);
502  else
503  delete viewsched;
504 }
505 
506 static void startManageRecordingRules(void)
507 {
509 
510  ProgramRecPriority *progRecPrior = new ProgramRecPriority(mainStack,
511  "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  ChannelRecPriority *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  CustomPriority *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  PlaybackBox *pbb = new PlaybackBox(
548  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  PrevRecordedList *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  ProgLister *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  CustomEdit *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  ManualSchedule *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;
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  StatusBox *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  IdleScreen *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  MythUIBusyDialog *busyPopup = new MythUIBusyDialog(message,
685  popupStack, "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  VideoDialog *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  GalleryThumbView *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  if (GetMythMainWindow()->currentWidget())
822  GetMythMainWindow()->currentWidget()->setFocus();
823  }
825  }
826 }
827 
832 {
833  if (!dvd)
834  return;
835 
836  if (!dvd->isUsable()) // This isn't infallible, on some drives both a mount and libudf fail
837  return;
838 
839  switch (gCoreContext->GetNumSetting("DVDOnInsertDVD", 1))
840  {
841  case 0 : // Do nothing
842  break;
843  case 1 : // Display menu (mythdvd)*/
844  break;
845  case 2 : // play DVD or Blu-ray
846  playDisc();
847  break;
848  default:
849  LOG(VB_GENERAL, LOG_ERR,
850  "mythdvd main.o: handleMedia() does not know what to do");
851  }
852 }
853 
855 {
856  // Only handle events for media that are newly mounted
857  if (!dev || (dev->getStatus() != MEDIASTAT_MOUNTED
858  && dev->getStatus() != MEDIASTAT_USEABLE))
859  return;
860 
861  // Check if gallery is already running
862  QVector<MythScreenType*> screens;
864 
865  QVector<MythScreenType*>::const_iterator it = screens.begin();
866  QVector<MythScreenType*>::const_iterator itend = screens.end();
867 
868  for (; it != itend; ++it)
869  {
870  if (dynamic_cast<GalleryThumbView*>(*it))
871  {
872  // Running gallery will receive this event later
873  LOG(VB_MEDIA, LOG_INFO, "Main: Ignoring new gallery media - already running");
874  return;
875  }
876  }
877 
878  if (gCoreContext->GetBoolSetting("GalleryAutoLoad", false))
879  {
880  LOG(VB_GUI, LOG_INFO, "Main: Autostarting Gallery for new media");
882  }
883  else
884  LOG(VB_MEDIA, LOG_INFO, "Main: Ignoring new gallery media - autorun not set");
885 }
886 
887 static void TVMenuCallback(void *data, QString &selection)
888 {
889  (void)data;
890  QString sel = selection.toLower();
891 
892  if (sel.startsWith("settings ") || sel == "video_settings_general")
893  {
894  if (!g_settingsHelper)
896 
898  }
899 
900  if (sel == "tv_watch_live")
901  startTVNormal();
902  else if (sel.startsWith("tv_watch_recording"))
903  {
904  // use selection here because its case is untouched
905  if ((selection.length() > 19) && (selection.mid(18, 1) == " "))
906  startPlaybackWithGroup(selection.mid(19));
907  else
908  startPlayback();
909  }
910  else if (sel == "tv_schedule")
911  startGuide();
912  else if (sel == "tv_manualschedule")
914  else if (sel == "tv_custom_record")
915  startCustomEdit();
916  else if (sel == "tv_fix_conflicts")
917  startManaged();
918  else if (sel == "tv_manage_recording_rules")
920  else if (sel == "tv_progfind")
921  startFinder();
922  else if (sel == "tv_search_title")
924  else if (sel == "tv_search_keyword")
926  else if (sel == "tv_search_people")
928  else if (sel == "tv_search_power")
930  else if (sel == "tv_search_stored")
932  else if (sel == "tv_search_channel")
934  else if (sel == "tv_search_category")
936  else if (sel == "tv_search_movie")
938  else if (sel == "tv_search_new")
939  startSearchNew();
940  else if (sel == "tv_search_time")
941  startSearchTime();
942  else if (sel == "tv_previous")
943  startPrevious();
944  else if (sel == "tv_previous_old")
946  else if (sel == "settings appearance")
947  {
949  StandardSettingDialog *ssd =
950  new StandardSettingDialog(mainStack, "videogeneralsettings",
951  new AppearanceSettings());
952 
953  if (ssd->Create())
954  {
955  mainStack->AddScreen(ssd);
956  }
957  else
958  delete ssd;
959  }
960  else if (sel == "settings themechooser")
961  {
963  ThemeChooser *tp = new ThemeChooser(mainStack);
964 
965  if (tp->Create())
966  mainStack->AddScreen(tp);
967  else
968  delete tp;
969  }
970  else if (sel == "settings setupwizard")
971  {
973  GeneralSetupWizard *sw = new GeneralSetupWizard(mainStack, "setupwizard");
974 
975  if (sw->Create())
976  mainStack->AddScreen(sw);
977  else
978  delete sw;
979  }
980  else if (sel == "settings grabbers")
981  {
983  GrabberSettings *gs = new GrabberSettings(mainStack, "grabbersettings");
984 
985  if (gs->Create())
986  mainStack->AddScreen(gs);
987  else
988  delete gs;
989  }
990  else if (sel == "screensetupwizard")
991  {
992  startAppearWiz();
993  }
994  else if (sel == "setup_keys")
995  {
996  startKeysSetup();
997  }
998  else if (sel == "settings playgroup")
999  {
1001  StandardSettingDialog *ssd =
1002  new StandardSettingDialog(mainStack, "playbackgroupsetting",
1003  new PlayGroupEditor());
1004 
1005  if (ssd->Create())
1006  {
1007  mainStack->AddScreen(ssd);
1008  }
1009  else
1010  delete ssd;
1011  }
1012  else if (sel == "settings general")
1013  {
1015  StandardSettingDialog *ssd =
1016  new StandardSettingDialog(mainStack, "videogeneralsettings",
1017  new GeneralSettings());
1018 
1019  if (ssd->Create())
1020  {
1021  mainStack->AddScreen(ssd);
1022  }
1023  else
1024  delete ssd;
1025  }
1026  else if (sel == "settings audiogeneral")
1027  {
1029  StandardSettingDialog *ssd =
1030  new AudioConfigScreen(mainStack, "audiogeneralsettings",
1031  new AudioConfigSettings());
1032 
1033  if (ssd->Create())
1034  {
1035  mainStack->AddScreen(ssd);
1036  }
1037  else
1038  delete ssd;
1039  }
1040  else if (sel == "settings maingeneral")
1041  {
1043  StandardSettingDialog *ssd =
1044  new StandardSettingDialog(mainStack, "maingeneralsettings",
1045  new MainGeneralSettings());
1046 
1047  if (ssd->Create())
1048  {
1049  mainStack->AddScreen(ssd);
1050  }
1051  else
1052  delete ssd;
1053  }
1054  else if (sel == "settings playback")
1055  {
1057  StandardSettingDialog *ssd =
1058  new PlaybackSettingsDialog(mainStack);
1059 
1060  if (ssd->Create())
1061  {
1062  mainStack->AddScreen(ssd);
1063  }
1064  else
1065  delete ssd;
1066  }
1067  else if (sel == "settings osd")
1068  {
1070  StandardSettingDialog *ssd =
1071  new StandardSettingDialog(mainStack, "osdsettings",
1072  new OSDSettings());
1073 
1074  if (ssd->Create())
1075  {
1076  mainStack->AddScreen(ssd);
1077  }
1078  else
1079  delete ssd;
1080  }
1081  else if (sel == "settings epg")
1082  {
1084  StandardSettingDialog *ssd =
1085  new StandardSettingDialog(mainStack, "epgsettings",
1086  new EPGSettings());
1087 
1088  if (ssd->Create())
1089  {
1090  mainStack->AddScreen(ssd);
1091  }
1092  else
1093  delete ssd;
1094  }
1095  else if (sel == "settings channelgroups")
1096  {
1098  StandardSettingDialog *ssd =
1099  new StandardSettingDialog(mainStack, "channelgroupssettings",
1100  new ChannelGroupsSetting());
1101 
1102  if (ssd->Create())
1103  {
1104  mainStack->AddScreen(ssd);
1105  }
1106  else
1107  delete ssd;
1108  }
1109  else if (sel == "settings generalrecpriorities")
1110  {
1112  StandardSettingDialog *ssd =
1113  new StandardSettingDialog(mainStack,
1114  "generalrecprioritiessettings",
1116 
1117  if (ssd->Create())
1118  {
1119  mainStack->AddScreen(ssd);
1120  }
1121  else
1122  delete ssd;
1123  }
1124  else if (sel == "settings channelrecpriorities")
1125  {
1127  }
1128  else if (sel == "settings custompriority")
1129  {
1131  }
1132  else if (sel == "system_events")
1133  {
1135 
1137  mainStack, "System Event Editor");
1138 
1139  if (msee->Create())
1140  mainStack->AddScreen(msee);
1141  else
1142  delete msee;
1143  }
1144  else if (sel == "video_settings_general")
1145  {
1146  RunSettingsCompletion::Create(gCoreContext->
1147  GetBoolSetting("VideoAggressivePC", false));
1148  }
1149  else if (sel == "video_settings_player")
1150  {
1152 
1153  PlayerSettings *ps = new PlayerSettings(mainStack, "player settings");
1154 
1155  if (ps->Create())
1156  mainStack->AddScreen(ps);
1157  else
1158  delete ps;
1159  }
1160  else if (sel == "video_settings_metadata")
1161  {
1163 
1164  MetadataSettings *ms = new MetadataSettings(mainStack, "metadata settings");
1165 
1166  if (ms->Create())
1167  mainStack->AddScreen(ms);
1168  else
1169  delete ms;
1170  }
1171  else if (sel == "video_settings_associations")
1172  {
1174 
1175  FileAssocDialog *fa = new FileAssocDialog(mainStack, "fa dialog");
1176 
1177  if (fa->Create())
1178  mainStack->AddScreen(fa);
1179  }
1180  else if (sel == "manager")
1182  else if (sel == "browser")
1184  else if (sel == "listing")
1186  else if (sel == "gallery")
1188  else if (sel == "disc_play")
1189  {
1190  playDisc();
1191  }
1192  else if (sel == "tv_status")
1193  showStatus();
1194  else if (sel == "exiting_app_prompt")
1195  handleExit(true);
1196  else if (sel == "exiting_app")
1197  handleExit(false);
1198  else if (sel == "standby_mode")
1199  standbyScreen();
1200  else if (sel == "exiting_menu")
1201  {
1202  //ignore
1203  }
1204  else
1205  LOG(VB_GENERAL, LOG_ERR, "Unknown menu action: " + selection);
1206 
1207  if (sel.startsWith("settings ") || sel == "video_settings_general")
1208  {
1209  if (g_settingsHelper)
1210  {
1211  qApp->connect(GetMythMainWindow()->GetMainStack()->GetTopScreen(),
1212  SIGNAL(Exiting()),
1214  SLOT(RunEpilog()));
1215  }
1216  }
1217 }
1218 
1219 static void handleExit(bool prompt)
1220 {
1221  if (prompt)
1222  {
1223  if (!g_exitPopup)
1224  g_exitPopup = new ExitPrompter();
1225 
1227  }
1228  else
1229  qApp->quit();
1230 }
1231 
1232 static bool RunMenu(const QString& themedir, const QString& themename)
1233 {
1234  QByteArray tmp = themedir.toLocal8Bit();
1235  g_menu = new MythThemedMenu(QString(tmp.constData()), "mainmenu.xml",
1236  GetMythMainWindow()->GetMainStack(), "mainmenu");
1237 
1238  if (g_menu->foundTheme())
1239  {
1240  LOG(VB_GENERAL, LOG_NOTICE, QString("Found mainmenu.xml for theme '%1'")
1241  .arg(themename));
1244  return true;
1245  }
1246 
1247  LOG(VB_GENERAL, LOG_ERR,
1248  QString("Couldn't find mainmenu.xml for theme '%1'") .arg(themename));
1249  delete g_menu;
1250  g_menu = nullptr;
1251 
1252  return false;
1253 }
1254 
1255 // If any settings are missing from the database, this will write
1256 // the default values
1257 static void WriteDefaults()
1258 {
1259  PlaybackSettings ps;
1260  ps.Load();
1261  ps.Save();
1262  OSDSettings os;
1263  os.Load();
1264  os.Save();
1265  GeneralSettings gs;
1266  gs.Load();
1267  gs.Save();
1268  EPGSettings es;
1269  es.Load();
1270  es.Save();
1271  AppearanceSettings as;
1272  as.Load();
1273  as.Save();
1274  MainGeneralSettings mgs;
1275  mgs.Load();
1276  mgs.Save();
1278  grs.Load();
1279  grs.Save();
1281  vgs.Load();
1282  vgs.Save();
1283  //TODo Playback group not loaded?
1284  //TODo Channel group not loaded?
1285 }
1286 
1287 static int internal_play_media(const QString &mrl, const QString &plot,
1288  const QString &title, const QString &subtitle,
1289  const QString &director, int season, int episode,
1290  const QString &inetref, int lenMins, const QString &year,
1291  const QString &id, const bool useBookmark)
1292 {
1293  int res = -1;
1294 
1295  QFile checkFile(mrl);
1296  if ((!checkFile.exists() && !mrl.startsWith("dvd:")
1297  && !mrl.startsWith("bd:")
1298  && !mrl.startsWith("myth:")
1299  && !mrl.startsWith("http://")
1300  && !mrl.startsWith("https://")))
1301  {
1302  QString errorText = qApp->translate("(MythFrontendMain)",
1303  "Failed to open \n '%1' in %2 \n"
1304  "Check if the video exists")
1305  .arg(mrl.section('/', -1))
1306  .arg(mrl.section('/', 0, -2));
1307 
1308  ShowOkPopup(errorText);
1309  return res;
1310  }
1311 
1312  ProgramInfo *pginfo = new ProgramInfo(
1313  mrl, plot, title, QString(), subtitle, QString(),
1314  director, season, episode, inetref, lenMins,
1315  (year.toUInt()) ? year.toUInt() : 1900, id);
1316 
1317  pginfo->SetProgramInfoType(pginfo->DiscoverProgramInfoType());
1318 
1319  bool bookmarkPresent = false;
1320 
1321  if (pginfo->IsVideoDVD())
1322  {
1323  DVDInfo *dvd = new DVDInfo(pginfo->GetPlaybackURL());
1324  if (dvd->IsValid())
1325  {
1326  QString name;
1327  QString serialid;
1328  if (dvd->GetNameAndSerialNum(name, serialid))
1329  {
1330  QStringList fields = pginfo->QueryDVDBookmark(serialid);
1331  bookmarkPresent = (fields.count() > 0);
1332  }
1333  }
1334  else
1335  {
1336  ShowNotificationError(qApp->translate("(MythFrontendMain)",
1337  "DVD Failure"),
1338  _Location,
1339  dvd->GetLastError());
1340  delete dvd;
1341  delete pginfo;
1342  return res;
1343  }
1344  delete dvd;
1345  }
1346  else if (pginfo->IsVideoBD())
1347  {
1348  BDInfo bd(pginfo->GetPlaybackURL());
1349  if (bd.IsValid())
1350  {
1351  QString name;
1352  QString serialid;
1353  if (bd.GetNameAndSerialNum(name, serialid))
1354  {
1355  QStringList fields = pginfo->QueryBDBookmark(serialid);
1356  bookmarkPresent = (fields.count() > 0);
1357  }
1358  }
1359  else
1360  {
1361  // ToDo: Change string to "BD Failure" after 0.28 is released
1362  ShowNotificationError(qApp->translate("(MythFrontendMain)",
1363  "DVD Failure"),
1364  _Location,
1365  bd.GetLastError());
1366  delete pginfo;
1367  return res;
1368  }
1369  }
1370  else if (pginfo->IsVideo())
1371  bookmarkPresent = (pginfo->QueryBookmark() > 0);
1372 
1373  if (useBookmark && bookmarkPresent)
1374  {
1376  BookmarkDialog *bookmarkdialog = new BookmarkDialog(pginfo, mainStack);
1377  if (!bookmarkdialog->Create())
1378  {
1379  delete bookmarkdialog;
1380  delete pginfo;
1381  return res;
1382  }
1383  }
1384  else
1385  {
1387 
1388  res = 0;
1389 
1390  delete pginfo;
1391  }
1392 
1393  return res;
1394 }
1395 
1396 static void gotoMainMenu(void)
1397 {
1398  // Reset the selected button to the first item.
1399  MythThemedMenuState *lmenu = dynamic_cast<MythThemedMenuState *>
1400  (GetMythMainWindow()->GetMainStack()->GetTopScreen());
1401  if (lmenu)
1402  lmenu->m_buttonList->SetItemCurrent(0);
1403 }
1404 
1405 // If the theme specified in the DB is somehow broken, try a standard one:
1406 //
1407 static bool resetTheme(QString themedir, const QString &badtheme)
1408 {
1409  QString themename = DEFAULT_UI_THEME;
1410 
1411  if (badtheme == DEFAULT_UI_THEME)
1412  themename = FALLBACK_UI_THEME;
1413 
1414  LOG(VB_GENERAL, LOG_WARNING,
1415  QString("Overriding broken theme '%1' with '%2'")
1416  .arg(badtheme).arg(themename));
1417 
1418  gCoreContext->OverrideSettingForSession("Theme", themename);
1419  themedir = GetMythUI()->FindThemeDir(themename);
1420 
1423  GetMythUI()->LoadQtConfig();
1424 #if CONFIG_DARWIN
1426 #else
1427  GetMythMainWindow()->Init();
1428 #endif
1429 
1431 
1432  return RunMenu(themedir, themename);
1433 }
1434 
1435 static int reloadTheme(void)
1436 {
1437 
1438 #ifdef Q_OS_ANDROID
1439 
1440  // jni code to launch the application again
1441  // reinitializing the main windows causes a segfault
1442  // with android
1443 
1444  auto activity = QtAndroid::androidActivity();
1445  auto packageManager = activity.callObjectMethod
1446  ( "getPackageManager",
1447  "()Landroid/content/pm/PackageManager;" );
1448 
1449  auto activityIntent = packageManager.callObjectMethod
1450  ( "getLaunchIntentForPackage",
1451  "(Ljava/lang/String;)Landroid/content/Intent;",
1452  activity.callObjectMethod("getPackageName",
1453  "()Ljava/lang/String;").object() );
1454 
1455  auto pendingIntent = QAndroidJniObject::callStaticObjectMethod
1456  ( "android/app/PendingIntent",
1457  "getActivity",
1458  "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;",
1459  activity.object(),
1460  0,
1461  activityIntent.object(),
1462  QAndroidJniObject::getStaticField<jint>("android/content/Intent",
1463  "FLAG_ACTIVITY_CLEAR_TOP") );
1464 
1465  auto alarmManager = activity.callObjectMethod
1466  ( "getSystemService",
1467  "(Ljava/lang/String;)Ljava/lang/Object;",
1468  QAndroidJniObject::getStaticObjectField("android/content/Context",
1469  "ALARM_SERVICE",
1470  "Ljava/lang/String;").object() );
1471 
1472  alarmManager.callMethod<void>
1473  ( "set",
1474  "(IJLandroid/app/PendingIntent;)V",
1475  QAndroidJniObject::getStaticField<jint>("android/app/AlarmManager", "RTC"),
1476  jlong(QDateTime::currentMSecsSinceEpoch() + 100),
1477  pendingIntent.object() );
1478 
1479  qApp->quit();
1480  // QString title = QObject::tr("Your change will take effect the next time "
1481  // "mythfrontend is started.");
1482  // MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack"); MythConfirmationDialog *okPopup =
1483  // new MythConfirmationDialog(popupStack, title, false);
1484  // if (okPopup->Create())
1485  // popupStack->AddScreen(okPopup);
1486  return 0;
1487 #else
1488 
1489  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
1490  QString themedir = GetMythUI()->FindThemeDir(themename);
1491  if (themedir.isEmpty())
1492  {
1493  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
1494  .arg(themename));
1495  return GENERIC_EXIT_NO_THEME;
1496  }
1497 
1500 
1502 
1503  GetMythUI()->LoadQtConfig();
1504 
1505  if (g_menu)
1506  {
1507  g_menu->Close();
1508  }
1509 #if CONFIG_DARWIN
1511 #else
1512  GetMythMainWindow()->Init();
1513 #endif
1514 
1516 
1518 
1519  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
1520  return GENERIC_EXIT_NO_THEME;
1521 
1522  LCD::SetupLCD();
1523  if (LCD *lcd = LCD::Get())
1524  {
1525  lcd->setupLEDs(RemoteGetRecordingMask);
1526  lcd->resetServer();
1527  }
1528 
1529  return 0;
1530 #endif // Q_OS_ANDROID else
1531 }
1532 
1533 static void reloadTheme_void(void)
1534 {
1535  int err = reloadTheme();
1536  if (err)
1537  exit(err);
1538 }
1539 
1540 static void setDebugShowBorders(void)
1541 {
1542  MythPainter *p = GetMythPainter();
1543  p->SetDebugMode(!p->ShowBorders(), p->ShowTypeNames());
1544 
1547 }
1548 
1549 static void setDebugShowNames(void)
1550 {
1551  MythPainter *p = GetMythPainter();
1552  p->SetDebugMode(p->ShowBorders(), !p->ShowTypeNames());
1553 
1556 }
1557 
1558 static void InitJumpPoints(void)
1559 {
1560  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Reload Theme"),
1561  "", "", reloadTheme_void);
1562  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Main Menu"),
1563  "", "", gotoMainMenu);
1564  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Guide"),
1565  "", "", startGuide, "GUIDE");
1566  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Program Finder"),
1567  "", "", startFinder, "FINDER");
1568  //REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Search Listings"),
1569  // "", "", startSearch);
1570  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "Manage Recordings / "
1571  "Fix Conflicts"), "", "", startManaged, "VIEWSCHEDULED");
1572  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Manage Recording Rules"),
1573  "", "", startManageRecordingRules);
1574  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Channel Recording "
1575  "Priorities"), "", "", startChannelRecPriorities);
1576  REG_JUMPLOC(QT_TRANSLATE_NOOP("MythControls", "TV Recording Playback"),
1577  "", "", startPlayback, "JUMPREC");
1578  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Live TV"),
1579  "", "", startTVNormal);
1580  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Status Screen"),
1581  "", "", showStatus);
1582  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Previously Recorded"),
1583  "", "", startPrevious);
1584 
1585  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Standby Mode"),
1586  "", "", standbyScreen);
1587 
1588  // Video
1589 
1590  REG_JUMP(JUMP_VIDEO_DEFAULT, QT_TRANSLATE_NOOP("MythControls",
1591  "The Video Default View"), "", jumpScreenVideoDefault);
1592  REG_JUMP(JUMP_VIDEO_MANAGER, QT_TRANSLATE_NOOP("MythControls",
1593  "The Video Manager"), "", jumpScreenVideoManager);
1594  REG_JUMP(JUMP_VIDEO_BROWSER, QT_TRANSLATE_NOOP("MythControls",
1595  "The Video Browser"), "", jumpScreenVideoBrowser);
1596  REG_JUMP(JUMP_VIDEO_TREE, QT_TRANSLATE_NOOP("MythControls",
1597  "The Video Listings"), "", jumpScreenVideoTree);
1598  REG_JUMP(JUMP_VIDEO_GALLERY, QT_TRANSLATE_NOOP("MythControls",
1599  "The Video Gallery"), "", jumpScreenVideoGallery);
1600  REG_JUMP("Play Disc", QT_TRANSLATE_NOOP("MythControls",
1601  "Play an Optical Disc"), "", playDisc);
1602 
1603  // Gallery
1604 
1605  REG_JUMP(JUMP_GALLERY_DEFAULT, QT_TRANSLATE_NOOP("MythControls",
1606  "Image Gallery"), "", RunGallery);
1607 
1608  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Borders"),
1609  "", "", setDebugShowBorders, false);
1610  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Toggle Show Widget Names"),
1611  "", "", setDebugShowNames, false);
1612  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Reset All Keys"),
1613  QT_TRANSLATE_NOOP("MythControls", "Reset all keys to defaults"),
1614  "", resetAllKeys, false);
1615 }
1616 
1617 static void ReloadJumpPoints(void)
1618 {
1619  MythMainWindow *mainWindow = GetMythMainWindow();
1620  mainWindow->ClearAllJumps();
1621  InitJumpPoints();
1622 }
1623 
1624 static void InitKeys(void)
1625 {
1626  REG_KEY("Video","PLAYALT", QT_TRANSLATE_NOOP("MythControls",
1627  "Play selected item in alternate player"), "ALT+P");
1628  REG_KEY("Video","FILTER", QT_TRANSLATE_NOOP("MythControls",
1629  "Open video filter dialog"), "F");
1630  REG_KEY("Video","INCPARENT", QT_TRANSLATE_NOOP("MythControls",
1631  "Increase Parental Level"), "],},F11");
1632  REG_KEY("Video","DECPARENT", QT_TRANSLATE_NOOP("MythControls",
1633  "Decrease Parental Level"), "[,{,F10");
1634  REG_KEY("Video","INCSEARCH", QT_TRANSLATE_NOOP("MythControls",
1635  "Show Incremental Search Dialog"), "Ctrl+S");
1636  REG_KEY("Video","DOWNLOADDATA", QT_TRANSLATE_NOOP("MythControls",
1637  "Download metadata for current item"), "W");
1638  REG_KEY("Video","ITEMDETAIL", QT_TRANSLATE_NOOP("MythControls",
1639  "Display Item Detail Popup"), "");
1640 
1641  // Gallery keybindings
1642  REG_KEY("Images", "PLAY", QT_TRANSLATE_NOOP("MythControls",
1643  "Start/Stop Slideshow"), "P");
1644  REG_KEY("Images", "RECURSIVESHOW", QT_TRANSLATE_NOOP("MythControls",
1645  "Start Recursive Slideshow"), "R");
1646  REG_KEY("Images", "ROTRIGHT", QT_TRANSLATE_NOOP("MythControls",
1647  "Rotate image right 90 degrees"), "],3");
1648  REG_KEY("Images", "ROTLEFT", QT_TRANSLATE_NOOP("MythControls",
1649  "Rotate image left 90 degrees"), "[,1");
1650  REG_KEY("Images", "FLIPHORIZONTAL", QT_TRANSLATE_NOOP("MythControls",
1651  "Flip image horizontally"), "");
1652  REG_KEY("Images", "FLIPVERTICAL", QT_TRANSLATE_NOOP("MythControls",
1653  "Flip image vertically"), "");
1654  REG_KEY("Images", "ZOOMOUT", QT_TRANSLATE_NOOP("MythControls",
1655  "Zoom image out"), "7");
1656  REG_KEY("Images", "ZOOMIN", QT_TRANSLATE_NOOP("MythControls",
1657  "Zoom image in"), "9");
1658  REG_KEY("Images", "FULLSIZE", QT_TRANSLATE_NOOP("MythControls",
1659  "Full-size (un-zoom) image"), "0");
1660  REG_KEY("Images", "MARK", QT_TRANSLATE_NOOP("MythControls",
1661  "Mark image"), "T");
1662  REG_KEY("Images", "SCROLLUP", QT_TRANSLATE_NOOP("MythControls",
1663  "Scroll image up"), "2");
1664  REG_KEY("Images", "SCROLLLEFT", QT_TRANSLATE_NOOP("MythControls",
1665  "Scroll image left"), "4");
1666  REG_KEY("Images", "SCROLLRIGHT", QT_TRANSLATE_NOOP("MythControls",
1667  "Scroll image right"), "6");
1668  REG_KEY("Images", "SCROLLDOWN", QT_TRANSLATE_NOOP("MythControls",
1669  "Scroll image down"), "8");
1670  REG_KEY("Images", "RECENTER", QT_TRANSLATE_NOOP("MythControls",
1671  "Recenter image"), "5");
1672  REG_KEY("Images", "COVER", QT_TRANSLATE_NOOP("MythControls",
1673  "Set or clear cover image"), "C");
1674 }
1675 
1676 static void ReloadKeys(void)
1677 {
1678  GetMythMainWindow()->ClearKeyContext("Video");
1679  InitKeys();
1680 
1681  TV::ReloadKeys();
1682 }
1683 
1684 static void SetFuncPtrs(void)
1685 {
1686  TV::SetFuncPtr("playbackbox", (void *)PlaybackBox::RunPlaybackBox);
1687  TV::SetFuncPtr("viewscheduled", (void *)ViewScheduled::RunViewScheduled);
1688  TV::SetFuncPtr("programguide", (void *)GuideGrid::RunProgramGuide);
1689  TV::SetFuncPtr("programfinder", (void *)RunProgramFinder);
1690  TV::SetFuncPtr("scheduleeditor", (void *)ScheduleEditor::RunScheduleEditor);
1691 }
1692 
1696 static void clearAllKeys(void)
1697 {
1698  MSqlQuery query(MSqlQuery::InitCon());
1699 
1700  query.prepare("DELETE FROM keybindings "
1701  "WHERE hostname = :HOSTNAME;");
1702  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1703  if (!query.exec())
1704  MythDB::DBError("Deleting keybindings", query);
1705  query.prepare("DELETE FROM jumppoints "
1706  "WHERE hostname = :HOSTNAME;");
1707  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1708  if (!query.exec())
1709  MythDB::DBError("Deleting jumppoints", query);
1710 }
1711 
1715 static void resetAllKeys(void)
1716 {
1717  clearAllKeys();
1718  // Reload MythMainWindow bindings
1720  // Reload Jump Points
1721  ReloadJumpPoints();
1722  // Reload mythfrontend and TV bindings
1723  ReloadKeys();
1724 }
1725 
1727 {
1728  REG_MEDIAPLAYER("Internal", QT_TRANSLATE_NOOP("MythControls",
1729  "MythTV's native media player."), internal_play_media);
1730  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1731  "MythDVD DVD Media Handler"), "", handleDVDMedia,
1732  MEDIATYPE_DVD, QString());
1733  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1734  "MythImage Media Handler 1/2"), "", handleGalleryMedia,
1735  MEDIATYPE_DATA | MEDIATYPE_MIXED, QString());
1736 
1737  QStringList extensions(ImageAdapterBase::SupportedImages()
1739 
1740  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
1741  "MythImage Media Handler 2/2"), "", handleGalleryMedia,
1742  MEDIATYPE_MGALLERY | MEDIATYPE_MVIDEO, extensions.join(","));
1743  return 0;
1744 }
1745 
1746 static void CleanupMyOldInUsePrograms(void)
1747 {
1748  MSqlQuery query(MSqlQuery::InitCon());
1749 
1750  query.prepare("DELETE FROM inuseprograms "
1751  "WHERE hostname = :HOSTNAME and recusage = 'player' ;");
1752  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1753  if (!query.exec())
1754  MythDB::DBError("CleanupMyOldInUsePrograms", query);
1755 }
1756 
1757 static bool WasAutomaticStart(void)
1758 {
1759  bool autoStart = false;
1760 
1761  // Is backend running?
1762  //
1764  {
1765  QDateTime startupTime = QDateTime();
1766 
1767  if( gCoreContext->IsMasterHost() )
1768  {
1769  QString s = gCoreContext->GetSetting("MythShutdownWakeupTime", "");
1770  if (s.length())
1771  startupTime = MythDate::fromString(s);
1772 
1773  // if we don't have a valid startup time assume we were started manually
1774  if (startupTime.isValid())
1775  {
1776  int startupSecs = gCoreContext->GetNumSetting("StartupSecsBeforeRecording");
1777  // If we started within 'StartupSecsBeforeRecording' OR 15 minutes
1778  // of the saved wakeup time assume we either started automatically
1779  // to record, to obtain guide data or or for a
1780  // daily wakeup/shutdown period
1781  if (abs(startupTime.secsTo(MythDate::current())) <
1782  max(startupSecs, 15 * 60))
1783  {
1784  LOG(VB_GENERAL, LOG_INFO,
1785  "Close to auto-start time, AUTO-Startup assumed");
1786 
1787  QString str = gCoreContext->GetSetting("MythFillSuggestedRunTime");
1788  QDateTime guideRunTime = MythDate::fromString(str);
1789  if (guideRunTime.secsTo(MythDate::current()) <
1790  max(startupSecs, 15 * 60))
1791  {
1792  LOG(VB_GENERAL, LOG_INFO,
1793  "Close to MythFillDB suggested run time, AUTO-Startup to fetch guide data?");
1794  }
1795  autoStart = true;
1796  }
1797  else
1798  LOG(VB_GENERAL, LOG_DEBUG,
1799  "NOT close to auto-start time, USER-initiated startup assumed");
1800  }
1801  }
1802  else
1803  {
1804  QString wakeupCmd = gCoreContext->GetSetting("WakeUpCommand");
1805 
1806  // A slave backend that has no wakeup command cannot be woken
1807  // automatically so can be ignored.
1808  if (!wakeupCmd.isEmpty())
1809  {
1810  ProgramList progList;
1811  bool bConflicts;
1812  QDateTime nextRecordingStart;
1813 
1814  if (LoadFromScheduler(progList, bConflicts))
1815  {
1816  // Find the first recording to be recorded
1817  // on this machine
1818  QString hostname = gCoreContext->GetHostName();
1819  ProgramList::const_iterator it = progList.begin();
1820  for (; it != progList.end(); ++it)
1821  {
1822  if (((*it)->GetRecordingStatus() == RecStatus::WillRecord ||
1823  (*it)->GetRecordingStatus() == RecStatus::Pending) &&
1824  ((*it)->GetHostname() == hostname) &&
1825  (nextRecordingStart.isNull() ||
1826  nextRecordingStart > (*it)->GetRecordingStartTime()))
1827  {
1828  nextRecordingStart = (*it)->GetRecordingStartTime();
1829  }
1830  }
1831 
1832  if (!nextRecordingStart.isNull() &&
1833  (abs(nextRecordingStart.secsTo(MythDate::current())) < (4 * 60)))
1834  {
1835  LOG(VB_GENERAL, LOG_INFO,
1836  "Close to start time, AUTO-Startup assumed");
1837 
1838  // If we started within 4 minutes of the next recording,
1839  // we almost certainly started automatically.
1840  autoStart = true;
1841  }
1842  else
1843  LOG(VB_GENERAL, LOG_DEBUG,
1844  "NOT close to auto-start time, USER-initiated startup assumed");
1845 
1846  }
1847  }
1848  }
1849  }
1850 
1851  return autoStart;
1852 }
1853 
1854 // from https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=16897
1855 // The old way of revoking root with setuid(getuid())
1856 // causes system hang in certain cases on raspberry pi
1857 
1858 static int revokeRoot (void)
1859 {
1860  if (getuid () == 0 && geteuid () == 0) // Really running as root
1861  return 0;
1862 
1863  if (geteuid () == 0) // Running setuid root
1864  return seteuid (getuid ()) ; // Change effective uid to the uid of the caller
1865  return 0;
1866 }
1867 
1868 
1869 int main(int argc, char **argv)
1870 {
1871  bool bPromptForBackend = false;
1872  bool bBypassAutoDiscovery = false;
1873 
1874 #if CONFIG_OMX_RPI
1875  setenv("QT_XCB_GL_INTEGRATION","none",0);
1876 #endif
1877 
1879  if (!cmdline.Parse(argc, argv))
1880  {
1881  cmdline.PrintHelp();
1883  }
1884 
1885  if (cmdline.toBool("showhelp"))
1886  {
1887  cmdline.PrintHelp();
1888  return GENERIC_EXIT_OK;
1889  }
1890 
1891  if (cmdline.toBool("showversion"))
1892  {
1894  return GENERIC_EXIT_OK;
1895  }
1896 
1897  CleanupGuard callCleanup(cleanup);
1898 
1899 #ifdef Q_OS_MAC
1900  // Without this, we can't set focus to any of the CheckBoxSetting, and most
1901  // of the MythPushButton widgets, and they don't use the themed background.
1902  QApplication::setDesktopSettingsAware(false);
1903 #endif
1904 #ifdef Q_OS_LINUX
1905  // This makes Xlib calls thread-safe which seems to be required for hardware
1906  // accelerated Flash playback to work without causing mythfrontend to abort.
1907  QApplication::setAttribute(Qt::AA_X11InitThreads);
1908 #endif
1909 #ifdef Q_OS_ANDROID
1910  //QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
1911 #endif
1912 
1913 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
1914  // Ignore desktop scaling
1915  QApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
1916 #endif
1917 
1918  QApplication::setSetuidAllowed(true);
1919  new QApplication(argc, argv);
1920  QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHFRONTEND);
1921 
1922 
1923 #ifdef Q_OS_MAC
1924  QString path = QCoreApplication::applicationDirPath();
1925  setenv("PYTHONPATH",
1926  QString("%1/../Resources/lib/python2.6/site-packages:%2")
1927  .arg(path)
1928  .arg(QProcessEnvironment::systemEnvironment().value("PYTHONPATH"))
1929  .toUtf8().constData(), 1);
1930 #endif
1931 
1932 #ifndef _WIN32
1933  QList<int> signallist;
1934  signallist << SIGINT << SIGTERM << SIGSEGV << SIGABRT << SIGBUS << SIGFPE
1935  << SIGILL;
1936 #if ! CONFIG_DARWIN
1937  signallist << SIGRTMIN;
1938 #endif
1939  SignalHandler::Init(signallist);
1942  SignalHandler::SetHandler(SIGHUP, logSigHup);
1943 #endif
1944 
1945  int retval;
1946  if ((retval = cmdline.ConfigureLogging()) != GENERIC_EXIT_OK)
1947  return retval;
1948 
1949  bool ResetSettings = false;
1950 
1951  if (cmdline.toBool("prompt"))
1952  bPromptForBackend = true;
1953  if (cmdline.toBool("noautodiscovery"))
1954  bBypassAutoDiscovery = true;
1955 
1956  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
1957  cerr << "Unable to ignore SIGPIPE\n";
1958 
1959  if (!cmdline.toString("display").isEmpty())
1960  {
1962  }
1963 
1964  if (!cmdline.toString("geometry").isEmpty())
1965  {
1967  }
1968 
1969  fe_sd_notify("STATUS=Connecting to database.");
1971  gCoreContext->SetAsFrontend(true);
1972 
1974  if (!gContext->Init(true, bPromptForBackend, bBypassAutoDiscovery))
1975  {
1976  LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
1977  gCoreContext->SetExiting(true);
1979  }
1980 
1982 
1983  if (!GetMythDB()->HaveSchema())
1984  {
1985  if (!InitializeMythSchema())
1986  return GENERIC_EXIT_DB_ERROR;
1987  }
1988 
1989  if (cmdline.toBool("reset"))
1990  ResetSettings = true;
1991 
1992  if (!cmdline.toBool("noupnp"))
1993  {
1994  fe_sd_notify("STATUS=Creating UPnP media renderer");
1995  g_pUPnp = new MediaRenderer();
1996  if (!g_pUPnp->isInitialized())
1997  {
1998  delete g_pUPnp;
1999  g_pUPnp = nullptr;
2000  }
2001  }
2002 
2003  QString fileprefix = GetConfDir();
2004 
2005  QDir dir(fileprefix);
2006  if (!dir.exists())
2007  dir.mkdir(fileprefix);
2008 
2009  if (ResetSettings)
2010  {
2011  AppearanceSettings as;
2012  as.Save();
2013 
2015  gCoreContext->GetDB()->ClearSetting("Language");
2016  gCoreContext->GetDB()->ClearSettingOnHost("Language", nullptr);
2017  gCoreContext->GetDB()->ClearSetting("Country");
2018  gCoreContext->GetDB()->ClearSettingOnHost("Country", nullptr);
2019 
2020  LOG(VB_GENERAL, LOG_NOTICE, "Appearance settings and language have "
2021  "been reset to defaults. You will need to "
2022  "restart the frontend.");
2023  gContext-> saveSettingsCache();
2024  return GENERIC_EXIT_OK;
2025  }
2026 
2027  qApp->setSetuidAllowed(true);
2028 
2029  if (revokeRoot() != 0)
2030  {
2031  LOG(VB_GENERAL, LOG_ERR, "Failed to revokeRoot(), exiting.");
2032  return GENERIC_EXIT_NOT_OK;
2033  }
2034 
2035 #ifdef USING_LIBDNS_SD
2036  // this needs to come after gCoreContext has been initialised
2037  // (for hostname) - hence it is not in MediaRenderer
2038  QScopedPointer<BonjourRegister> bonjour(new BonjourRegister());
2039  if (bonjour.data())
2040  {
2041  fe_sd_notify("STATUS=Registering frontend with bonjour");
2042  QByteArray dummy;
2043  int port = gCoreContext->GetNumSetting("UPnP/MythFrontend/ServicePort", 6547);
2044  QByteArray name("Mythfrontend on ");
2045  name.append(gCoreContext->GetHostName());
2046  bonjour->Register(port, "_mythfrontend._tcp",
2047  name, dummy);
2048  }
2049 #endif
2050 
2051  fe_sd_notify("STATUS=Initializing LCD");
2052  LCD::SetupLCD();
2053  if (LCD *lcd = LCD::Get())
2054  lcd->setupLEDs(RemoteGetRecordingMask);
2055 
2056  fe_sd_notify("STATUS=Loading translation");
2057  MythTranslation::load("mythfrontend");
2058 
2059  fe_sd_notify("STATUS=Loading themes");
2060  QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
2061 
2062  QString themedir = GetMythUI()->FindThemeDir(themename);
2063  if (themedir.isEmpty())
2064  {
2065  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
2066  .arg(themename));
2067  return GENERIC_EXIT_NO_THEME;
2068  }
2069 
2070  GetMythUI()->LoadQtConfig();
2071 
2072  themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
2073  themedir = GetMythUI()->FindThemeDir(themename);
2074  if (themedir.isEmpty())
2075  {
2076  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find theme '%1'")
2077  .arg(themename));
2078  return GENERIC_EXIT_NO_THEME;
2079  }
2080 
2081  MythMainWindow *mainWindow = GetMythMainWindow();
2082 #if CONFIG_DARWIN
2083  mainWindow->Init(QT_PAINTER, false);
2084 #else
2085  mainWindow->Init(QString(), false);
2086 #endif
2087  mainWindow->setWindowTitle(qApp->translate("(MythFrontendMain)",
2088  "MythTV Frontend",
2089  "Main window title"));
2090 
2091 #ifdef USING_AIRPLAY
2092  if (gCoreContext->GetBoolSetting("AirPlayEnabled", true))
2093  {
2094  fe_sd_notify("STATUS=Initializing AirPlay");
2096  if (!gCoreContext->GetBoolSetting("AirPlayAudioOnly", false))
2097  {
2099  }
2100  }
2101 #endif
2102 
2103  // We must reload the translation after a language change and this
2104  // also means clearing the cached/loaded theme strings, so reload the
2105  // theme which also triggers a translation reload
2107  {
2108  if (!reloadTheme())
2109  return GENERIC_EXIT_NO_THEME;
2110  }
2111 
2112  if (!UpgradeTVDatabaseSchema(false, false, true))
2113  {
2114  LOG(VB_GENERAL, LOG_ERR,
2115  "Couldn't upgrade database to new schema, exiting.");
2117  }
2118 
2119  WriteDefaults();
2120 
2121  // Refresh Global/Main Menu keys after DB update in case there was no DB
2122  // when they were written originally
2123  mainWindow->ReloadKeys();
2124 
2125  fe_sd_notify("STATUS=Initializing jump points");
2126  InitJumpPoints();
2127  InitKeys();
2128  TV::InitKeys();
2129  SetFuncPtrs();
2130 
2132 
2134 
2135  setHttpProxy();
2136 
2137  fe_sd_notify("STATUS=Initializing plugins");
2138  g_pmanager = new MythPluginManager();
2140 
2141  fe_sd_notify("STATUS=Initializing media monitor");
2143  if (mon)
2144  {
2145  mon->StartMonitoring();
2146  mainWindow->installEventFilter(mon);
2147  }
2148 
2149  fe_sd_notify("STATUS=Initializing network control");
2150  NetworkControl *networkControl = nullptr;
2151  if (gCoreContext->GetBoolSetting("NetworkControlEnabled", false))
2152  {
2153  int port = gCoreContext->GetNumSetting("NetworkControlPort", 6546);
2154  networkControl = new NetworkControl();
2155  if (!networkControl->listen(port))
2156  LOG(VB_GENERAL, LOG_ERR,
2157  QString("NetworkControl failed to bind to port %1.")
2158  .arg(port));
2159  }
2160 
2161 #if CONFIG_DARWIN
2166  gLoaded = true;
2167 #endif
2168  if (!RunMenu(themedir, themename) && !resetTheme(themedir, themename))
2169  {
2170  return GENERIC_EXIT_NO_THEME;
2171  }
2172  fe_sd_notify("STATUS=Loading theme updates");
2173  ThemeUpdateChecker *themeUpdateChecker = nullptr;
2174  if (gCoreContext->GetBoolSetting("ThemeUpdateNofications", true))
2175  themeUpdateChecker = new ThemeUpdateChecker();
2176 
2178 
2180 
2182  PreviewGenerator::kRemote, 50, 60);
2183 
2184  fe_sd_notify("STATUS=Creating housekeeper");
2186 #ifdef __linux__
2187  #ifdef CONFIG_BINDINGS_PYTHON
2189  #endif
2190 #endif
2191  housekeeping->Start();
2192 
2193 
2194  if (cmdline.toBool("runplugin"))
2195  {
2196  QStringList plugins = g_pmanager->EnumeratePlugins();
2197 
2198  if (plugins.contains(cmdline.toString("runplugin")))
2199  g_pmanager->run_plugin(cmdline.toString("runplugin"));
2200  else if (plugins.contains("myth" + cmdline.toString("runplugin")))
2201  g_pmanager->run_plugin("myth" + cmdline.toString("runplugin"));
2202  else
2203  {
2204  LOG(VB_GENERAL, LOG_ERR,
2205  QString("Invalid plugin name supplied on command line: '%1'")
2206  .arg(cmdline.toString("runplugin")));
2207  LOG(VB_GENERAL, LOG_ERR,
2208  QString("Available plugins: %1")
2209  .arg(plugins.join(", ")));
2211  }
2212  }
2213  else if (cmdline.toBool("jumppoint"))
2214  {
2216 
2217  if (mmw->DestinationExists(cmdline.toString("jumppoint")))
2218  mmw->JumpTo(cmdline.toString("jumppoint"));
2219  else
2220  {
2221  LOG(VB_GENERAL, LOG_ERR,
2222  QString("Invalid jump point supplied on the command line: %1")
2223  .arg(cmdline.toString("jumppoint")));
2224  LOG(VB_GENERAL, LOG_ERR,
2225  QString("Available jump points: %2")
2226  .arg(mmw->EnumerateDestinations().join(", ")));
2228  }
2229  }
2230 
2231  if (WasAutomaticStart())
2232  {
2233  // We appear to have been started automatically
2234  // so enter standby so that the machine can
2235  // shutdown again as soon as possible if necessary.
2236  standbyScreen();
2237  }
2238 
2239  // Provide systemd ready notification (for type=notify units)
2240  fe_sd_notify("STATUS=");
2241  fe_sd_notify("READY=1");
2242 
2243  int ret = qApp->exec();
2244 
2245  fe_sd_notify("STOPPING=1\nSTATUS=Exiting");
2246  if (ret==0)
2247  gContext-> saveSettingsCache();
2248 
2249  DestroyMythUI();
2251 
2252  delete housekeeping;
2253  delete themeUpdateChecker;
2254  delete sysEventHandler;
2255 
2257 
2258  if (mon)
2259  mon->deleteLater();
2260 
2261  delete networkControl;
2262  return ret;
2263 }
2264 
2265 void handleSIGUSR1(void)
2266 {
2267  LOG(VB_GENERAL, LOG_INFO, "Reloading theme");
2268  gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
2270  GetMythMainWindow()->JumpTo("Reload Theme");
2272 }
2273 
2274 void handleSIGUSR2(void)
2275 {
2276  LOG(VB_GENERAL, LOG_INFO, "Restarting LIRC handler");
2278 }
2279 
2280 #include "main.moc"
2281 /* 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
void Run(time_t timeout=0)
Runs a command inside the /bin/sh shell. Returns immediately.
QStringList EnumeratePlugins(void)
Definition: mythplugin.cpp:240
static void startSearchMovie(void)
void DestroyAllPlugins()
Definition: mythplugin.cpp:227
#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:863
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 void startPrevious(void)
static void startPlayback(void)
static QString themedir
Definition: mythdirs.cpp:21
static void gotoMainMenu(void)
Main header for mythcontrols.
void LoadQtConfig(void)
static void startPreviousOld(void)
static void playDisc()
static void setDebugShowBorders(void)
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
Definition: serverpool.cpp:380
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
bool IsVideo(void) const
Definition: programinfo.h:476
void RegisterTask(HouseKeeperTask *task)
static void startSearchPower(void)
QWidget * currentWidget(void)
static VideoListDeathDelayPtr & GetSavedVideoList()
Definition: videodlg.cpp:841
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
static void Cleanup(void)
void setHttpProxy(void)
Get network proxy settings from OS, and use for [Q]Http[Comms].
void SetProgramInfoType(ProgramInfoType t)
Definition: programinfo.h:504
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
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="")
Load channels from database into a list of ChannelInfo objects.
int main(int argc, char **argv)
static void startChannelRecPriorities(void)
bool Create(void) override
Creates the UI screen.
bool Create(void) override
Definition: statusbox.cpp:76
void SaveSetting(const QString &key, int newValue)
static void reloadTheme_void(void)
bool Create() override
MythUIButtonList * m_buttonList
void SetRedraw(void)
Definition: mythuitype.cpp:295
bool Create() override
Initialises and shows the graphical elements.
static void startKeysSetup()
static int ConfiguredTunerCards(void)
If any cards are configured, return the number.
Definition: tv_play.cpp:194
bool Create(void) override
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
bool Create(void) override
Definition: proglist.cpp:98
bool Create(void) override
virtual void Load(void)
bool IsVideoDVD(void) const
Definition: programinfo.h:339
static void TVMenuCallback(void *data, QString &selection)
Basic menu dialog, message and a list of options.
static void startCustomEdit(void)
void PrintHelp(void) const
Print command line option help.
virtual void StartMonitoring(void)
Start the monitoring thread if needed.
HouseKeeper * housekeeping
static void clearAllKeys(void)
Deletes all key bindings and jump points for this host.
static void SetupLCD(void)
Definition: lcddevice.cpp:72
static void TeardownPreviewGeneratorQueue()
Destroy the singleton queue of preview generators.
int RemoteGetFreeRecorderCount(void)
static bool RunMenu(const QString &themedir, const QString &themename)
MythSystemEventHandler * sysEventHandler
static void Init(QList< int > &signallist, QObject *parent=nullptr)
static void startSearchCategory(void)
static void * RunPlaybackBox(void *player, bool)
MythPainter * GetMythPainter(void)
bool GetNameAndSerialNum(QString &name, QString &serialnum)
bool Create() override
Definition: customedit.cpp:51
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 setInitialRecGroup(const QString &initialGroup)
Definition: playbackbox.h:128
void AddCurrentLocation(const QString &location)
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythScreenStack * GetMainStack()
static void setDebugShowNames(void)
ProgramInfoType DiscoverProgramInfoType(void) const
#define REG_KEY(a, b, c, d)
MythContext * gContext
This global variable contains the MythContext instance for the application.
Definition: mythcontext.cpp:63
static QString defaultDVDdevice()
DVDDeviceLocation, user-selected drive, or /dev/dvd.
static void jumpScreenVideoBrowser()
static guint32 * tmp
Definition: goom_core.c:35
void DestroyMythUI()
#define REG_MEDIAPLAYER(a, b, c)
bool Create(void) override
iterator begin(void)
void Init(const QString &forcedpainter=QString(), bool mayReInit=true)
void ClearKeyContext(const QString &context)
static Type kEventType
Definition: mythdialogbox.h:50
#define seteuid(x)
Definition: compat.h:263
void Start()
Start Thumbnail screen.
void SendMessage(const QString &message)
bool ShowTypeNames(void)
Definition: mythpainter.h:97
static void startSearchTitle(void)
static void SetX11Display(const QString &display)
This needs to be set before MythUIHelper is initialized so that the MythUIHelper::Init() can detect X...
#define OPENGL2_PAINTER
Definition: mythuidefines.h:4
virtual void deleteLater(void)
add arguments for MythTV log propagation
Definition: mythsystem.h:50
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.
bool Create(void) override
virtual void Close()
void AddButton(const QString &title, QVariant data=0, bool newMenu=false, bool setCurrent=false)
void ApplySettingsOverride(void)
Apply all overrides to the global context.
Holds information on recordings and videos.
Definition: programinfo.h:66
static void * RunViewScheduled(void *player, bool)
static int revokeRoot(void)
static void startTVNormal(void)
bool Create(void) override
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
static void jumpScreenVideoDefault()
#define REG_JUMPEX(a, b, c, d, e)
static void startSearchNew(void)
QStringList QueryBDBookmark(const QString &serialid) const
Queries "bdbookmark" table for bookmarking BD serial number.
Thumbnail screen.
bool Create(void) override
const QString JUMP_VIDEO_TREE
Definition: globals.cpp:38
QStringList QueryDVDBookmark(const QString &serialid) const
Queries "dvdbookmark" table for bookmarking DVD serial number.
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="")
bool BackendIsRunning(void)
a backend process is running on this host
bool IsVideoBD(void) const
Definition: programinfo.h:341
QString toString(const QString &key) const
Returns stored QVariant as a QString, falling to default if not provided.
void GetScreenList(QVector< MythScreenType * > &screens)
QPointer< class VideoListDeathDelay > VideoListDeathDelayPtr
Definition: videodlg.h:46
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:230
static QStringList SupportedVideos()
Return recognised video extensions.
bool Create(void) override
string hostname
Definition: caa.py:17
bool isInitialized()
Definition: upnp.h:121
bool Create(void) override
static void Done(void)
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
void JumpTo(const QString &destination, bool pop=true)
static void SetHandler(int signum, SigHandlerFunc handler)
static void startCustomPriority(void)
static void InitJumpPoints(void)
bool Create() override
MythCommFlagCommandLineParser cmdline
const char * name
Definition: ParseText.cpp:328
static void InitKeys(void)
uint64_t QueryBookmark(void) const
Gets any bookmark position in database, unless the ignore bookmark flag is set.
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
disable MythMessage UDP listener for the duration of application.
Definition: mythsystem.h:48
MythUIHelper * GetMythUI()
bool Create(void) override
Loads UI elements from theme.
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.
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
uint Wait(time_t timeout=0)
bool Create() override
Definition: videodlg.cpp:898
static ExitPrompter * g_exitPopup
static void ReloadKeys(void)
Definition: tv_play.cpp:999
virtual void Save(void)
static void startSearchTime(void)
vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:120
bool Create(void) override
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:807
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.
QString GetLastError(void) const
Definition: dvdringbuffer.h:75
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)
bool ShowBorders(void)
Definition: mythpainter.h:96
const QString JUMP_VIDEO_MANAGER
Definition: globals.cpp:36
bool Create(void) override
Definition: idlescreen.cpp:41
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:54
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:418
#define SIGUSR2
Definition: compat.h:217
void SetReturnEvent(QObject *retobject, const QString &resultid)
QString RemoveCurrentLocation(void)
iterator end(void)
int RemoteGetRecordingMask(void)
Definition: remoteutil.cpp:396
static bool resetTheme(QString themedir, const QString &badtheme)
static MythPluginManager * g_pmanager
static void cleanup(VideoFilter *filter)
QString GetPlaybackURL(bool checkMaster=false, bool forceCheckLocal=false) const
Returns filename or URL to be used to play back this recording.
bool LoadFromScheduler(AutoDeleteDeque< TYPE * > &destination, bool &hasConflicts, QString altTable="", int recordid=-1)
Definition: programinfo.h:876
#define SIGHUP
Definition: compat.h:213
void SetEffectsEnabled(bool enable)
static void startGuide(void)
void ClearSettingsCache(const QString &myKey=QString(""))
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:16
bool foundTheme(void)
Returns true iff a theme has been found by a previous call to SetMenuTheme().
bool isUsable() const
Is this device "ready", for a plugin to access?
Definition: mythmedia.h:84
static void startManualSchedule(void)
static void startPlaybackWithGroup(const QString &recGroup="")
Definition: lcddevice.h:165
bool Create(void) override
MythDB * GetDB(void)
An editor for MythSystemEvent handler commands.
static void showStatus(void)
bool IsValid(void) const
Definition: dvdringbuffer.h:73
static void SetFuncPtr(const char *, void *)
Import pointers to functions used to embed the TV window into other containers e.g.
Definition: tv_play.cpp:490
void SetItemCurrent(MythUIButtonListItem *item)
virtual void Load(void)
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
#define QT_PAINTER
Definition: mythuidefines.h:2
#define REG_JUMPLOC(a, b, c, d, e)
static SettingsHelper * g_settingsHelper
static ImageType inspectImage(const QString &path)
Definition: mythcdrom.cpp:179
#define getuid()
Definition: compat.h:260
#define setenv(x, y, z)
Definition: compat.h:156
bool Init(const bool gui=true, const bool promptForBackend=false, const bool disableAutoDiscovery=false, const bool ignoreDB=false)
Handles incoming MythSystemEvent messages.
static void handleExit(bool prompt)
static int internal_play_media(const QString &mrl, const QString &plot, const QString &title, const QString &subtitle, const QString &director, int season, int episode, const QString &inetref, int lenMins, const QString &year, const QString &id, const bool useBookmark)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
#define GENERIC_EXIT_NO_THEME
No Theme available.
Definition: exitcodes.h:14
int ConfigureLogging(QString mask="general", unsigned int progress=0)
Read in logging options and initialize the logging interface.
bool Create(void) override
MythDB * GetMythDB(void)
Definition: mythdb.cpp:46
#define GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:13
#define SIGPIPE
Definition: compat.h:218
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
static void jumpScreenVideoTree()
bool HandleMedia(const QString &handler, const QString &mrl, const QString &plot="", const QString &title="", const QString &subtitle="", const QString &director="", int season=0, int episode=0, const QString &inetref="", int lenMins=120, const QString &year="1895", const QString &id="", bool useBookmarks=false)
Screen in which all other widgets are contained and rendered.
#define GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
Definition: exitcodes.h:15
void ActivateSettingsCache(bool activate=true)
List::const_iterator const_iterator
#define GENERIC_EXIT_NOT_OK
Exited with error.
Definition: exitcodes.h:11
static void startFinder(void)
static void WriteDefaults()
bool Create(void) override
static void RunVideoScreen(VideoDialog::DialogType type, bool fromJump=false)
static void InitKeys(void)
Definition: tv_play.cpp:505
QString GetHostName(void)
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:37
static MythThemedMenu * g_menu
static void handleGalleryMedia(MythMediaDevice *dev)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
void SetAsFrontend(bool frontend)
static void * RunScheduleEditor(ProgramInfo *proginfo, void *player=nullptr)
Callback.
void SetDebugMode(bool showBorders, bool showNames)
Definition: mythpainter.h:90
void ReinitDone(void)
void ReloadKeys(void)
void PrintVersion(void) const
Print application version information.
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)
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:166
#define GENERIC_EXIT_DB_OUTOFDATE
Database needs upgrade.
Definition: exitcodes.h:16
bool Create(void) override
static void startAppearWiz(void)
static bool isLiveTVAvailable(void)
void Start(void)