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